Merge branch 'bugfix-2.0.x' into Implement-M591-Configurable-Runout-Sensors

This commit is contained in:
InsanityAutomation
2022-04-03 10:33:18 -04:00
143 changed files with 5556 additions and 1157 deletions
+151 -35
View File
@@ -35,7 +35,7 @@
*
* Advanced settings can be found in Configuration_adv.h
*/
#define CONFIGURATION_H_VERSION 02000903
#define CONFIGURATION_H_VERSION 02010000
//===========================================================================
//============================= Getting Started =============================
@@ -150,9 +150,9 @@
//#define MACHINE_UUID "00000000-0000-0000-0000-000000000000"
/**
* Define the number of coordinated linear axes.
* Define the number of coordinated axes.
* See https://github.com/DerAndere1/Marlin/wiki
* Each linear axis gets its own stepper control and endstop:
* Each axis gets its own stepper control and endstop:
*
* Steppers: *_STEP_PIN, *_ENABLE_PIN, *_DIR_PIN, *_ENABLE_ON
* Endstops: *_STOP_PIN, USE_*MIN_PLUG, USE_*MAX_PLUG
@@ -161,31 +161,50 @@
* DEFAULT_MAX_ACCELERATION, AXIS_RELATIVE_MODES,
* MICROSTEP_MODES, MANUAL_FEEDRATE
*
* :[3, 4, 5, 6]
* :[3, 4, 5, 6, 7, 8, 9]
*/
//#define LINEAR_AXES 3
//#define NUM_AXES 3
/**
* Axis codes for additional axes:
* This defines the axis code that is used in G-code commands to
* reference a specific axis.
* 'A' for rotational axis parallel to X
* 'B' for rotational axis parallel to Y
* 'C' for rotational axis parallel to Z
* 'U' for secondary linear axis parallel to X
* 'V' for secondary linear axis parallel to Y
* 'W' for secondary linear axis parallel to Z
* Regardless of the settings, firmware-internal axis IDs are
* I (AXIS4), J (AXIS5), K (AXIS6).
* Additional Axis Settings
*
* Define AXISn_ROTATES for all axes that rotate or pivot.
* Rotational axis coordinates are expressed in degrees.
*
* AXISn_NAME defines the letter used to refer to the axis in (most) G-code commands.
* By convention the names and roles are typically:
* 'A' : Rotational axis parallel to X
* 'B' : Rotational axis parallel to Y
* 'C' : Rotational axis parallel to Z
* 'U' : Secondary linear axis parallel to X
* 'V' : Secondary linear axis parallel to Y
* 'W' : Secondary linear axis parallel to Z
*
* Regardless of these settings the axes are internally named I, J, K, U, V, W.
*/
#if LINEAR_AXES >= 4
#if NUM_AXES >= 4
#define AXIS4_NAME 'A' // :['A', 'B', 'C', 'U', 'V', 'W']
#define AXIS4_ROTATES
#endif
#if LINEAR_AXES >= 5
#define AXIS5_NAME 'B' // :['A', 'B', 'C', 'U', 'V', 'W']
#if NUM_AXES >= 5
#define AXIS5_NAME 'B' // :['B', 'C', 'U', 'V', 'W']
#define AXIS5_ROTATES
#endif
#if LINEAR_AXES >= 6
#define AXIS6_NAME 'C' // :['A', 'B', 'C', 'U', 'V', 'W']
#if NUM_AXES >= 6
#define AXIS6_NAME 'C' // :['C', 'U', 'V', 'W']
#define AXIS6_ROTATES
#endif
#if NUM_AXES >= 7
#define AXIS7_NAME 'U' // :['U', 'V', 'W']
//#define AXIS7_ROTATES
#endif
#if NUM_AXES >= 8
#define AXIS8_NAME 'V' // :['V', 'W']
//#define AXIS8_ROTATES
#endif
#if NUM_AXES >= 9
#define AXIS9_NAME 'W' // :['W']
//#define AXIS9_ROTATES
#endif
// @section extruder
@@ -589,10 +608,12 @@
//===========================================================================
//============================= PID Settings ================================
//===========================================================================
// PID Tuning Guide here: https://reprap.org/wiki/PID_Tuning
// Comment the following line to disable PID and enable bang-bang.
#define PIDTEMP
// Enable PIDTEMP for PID control or MPCTEMP for Predictive Model.
// temperature control. Disable both for bang-bang heating.
#define PIDTEMP // See the PID Tuning Guide at https://reprap.org/wiki/PID_Tuning
//#define MPCTEMP // ** EXPERIMENTAL **
#define BANG_MAX 255 // Limits current to nozzle while in bang-bang mode; 255=full current
#define PID_MAX BANG_MAX // Limits current to nozzle while PID is active (see PID_FUNCTIONAL_RANGE below); 255=full current
#define PID_K1 0.95 // Smoothing factor within any PID loop
@@ -614,7 +635,45 @@
#define DEFAULT_Ki 1.08
#define DEFAULT_Kd 114.00
#endif
#endif // PIDTEMP
#endif
/**
* Model Predictive Control for hotend
*
* Use a physical model of the hotend to control temperature. When configured correctly
* this gives better responsiveness and stability than PID and it also removes the need
* for PID_EXTRUSION_SCALING and PID_FAN_SCALING. Use M306 to autotune the model.
*/
#if ENABLED(MPCTEMP)
#define MPC_MAX BANG_MAX // (0..255) Current to nozzle while MPC is active.
#define MPC_HEATER_POWER { 40.0f } // (W) Heat cartridge powers.
#define MPC_INCLUDE_FAN // Model the fan speed?
// Measured physical constants from M306
#define MPC_BLOCK_HEAT_CAPACITY { 16.7f } // (J/K) Heat block heat capacities.
#define MPC_SENSOR_RESPONSIVENESS { 0.22f } // (K/s per ∆K) Rate of change of sensor temperature from heat block.
#define MPC_AMBIENT_XFER_COEFF { 0.068f } // (W/K) Heat transfer coefficients from heat block to room air with fan off.
#if ENABLED(MPC_INCLUDE_FAN)
#define MPC_AMBIENT_XFER_COEFF_FAN255 { 0.097f } // (W/K) Heat transfer coefficients from heat block to room air with fan on full.
#endif
// For one fan and multiple hotends MPC needs to know how to apply the fan cooling effect.
#if ENABLED(MPC_INCLUDE_FAN)
//#define MPC_FAN_0_ALL_HOTENDS
//#define MPC_FAN_0_ACTIVE_HOTEND
#endif
#define FILAMENT_HEAT_CAPACITY_PERMM 5.6e-3f // 0.0056 J/K/mm for 1.75mm PLA (0.0149 J/K/mm for 2.85mm PLA).
//#define FILAMENT_HEAT_CAPACITY_PERMM 3.6e-3f // 0.0036 J/K/mm for 1.75mm PETG (0.0094 J/K/mm for 2.85mm PETG).
// Advanced options
#define MPC_SMOOTHING_FACTOR 0.5f // (0.0...1.0) Noisy temperature sensors may need a lower value for stabilization.
#define MPC_MIN_AMBIENT_CHANGE 1.0f // (K/s) Modeled ambient temperature rate of change, when correcting model inaccuracies.
#define MPC_STEADYSTATE 0.5f // (K/s) Temperature change rate for steady state logic to be enforced.
#define MPC_TUNING_POS { X_CENTER, Y_CENTER, 1.0f } // (mm) M306 Autotuning position, ideally bed center just above the surface.
#endif
//===========================================================================
//====================== PID > Bed Temperature Control ======================
@@ -793,12 +852,18 @@
//#define USE_IMIN_PLUG
//#define USE_JMIN_PLUG
//#define USE_KMIN_PLUG
//#define USE_UMIN_PLUG
//#define USE_VMIN_PLUG
//#define USE_WMIN_PLUG
//#define USE_XMAX_PLUG
//#define USE_YMAX_PLUG
//#define USE_ZMAX_PLUG
//#define USE_IMAX_PLUG
//#define USE_JMAX_PLUG
//#define USE_KMAX_PLUG
//#define USE_UMAX_PLUG
//#define USE_VMAX_PLUG
//#define USE_WMAX_PLUG
// Enable pullup for all endstops to prevent a floating state
#define ENDSTOPPULLUPS
@@ -810,12 +875,18 @@
//#define ENDSTOPPULLUP_IMIN
//#define ENDSTOPPULLUP_JMIN
//#define ENDSTOPPULLUP_KMIN
//#define ENDSTOPPULLUP_UMIN
//#define ENDSTOPPULLUP_VMIN
//#define ENDSTOPPULLUP_WMIN
//#define ENDSTOPPULLUP_XMAX
//#define ENDSTOPPULLUP_YMAX
//#define ENDSTOPPULLUP_ZMAX
//#define ENDSTOPPULLUP_IMAX
//#define ENDSTOPPULLUP_JMAX
//#define ENDSTOPPULLUP_KMAX
//#define ENDSTOPPULLUP_UMAX
//#define ENDSTOPPULLUP_VMAX
//#define ENDSTOPPULLUP_WMAX
//#define ENDSTOPPULLUP_ZMIN_PROBE
#endif
@@ -829,12 +900,18 @@
//#define ENDSTOPPULLDOWN_IMIN
//#define ENDSTOPPULLDOWN_JMIN
//#define ENDSTOPPULLDOWN_KMIN
//#define ENDSTOPPULLDOWN_UMIN
//#define ENDSTOPPULLDOWN_VMIN
//#define ENDSTOPPULLDOWN_WMIN
//#define ENDSTOPPULLDOWN_XMAX
//#define ENDSTOPPULLDOWN_YMAX
//#define ENDSTOPPULLDOWN_ZMAX
//#define ENDSTOPPULLDOWN_IMAX
//#define ENDSTOPPULLDOWN_JMAX
//#define ENDSTOPPULLDOWN_KMAX
//#define ENDSTOPPULLDOWN_UMAX
//#define ENDSTOPPULLDOWN_VMAX
//#define ENDSTOPPULLDOWN_WMAX
//#define ENDSTOPPULLDOWN_ZMIN_PROBE
#endif
@@ -845,12 +922,18 @@
#define I_MIN_ENDSTOP_INVERTING false // Set to true to invert the logic of the endstop.
#define J_MIN_ENDSTOP_INVERTING false // Set to true to invert the logic of the endstop.
#define K_MIN_ENDSTOP_INVERTING false // Set to true to invert the logic of the endstop.
#define U_MIN_ENDSTOP_INVERTING false // Set to true to invert the logic of the endstop.
#define V_MIN_ENDSTOP_INVERTING false // Set to true to invert the logic of the endstop.
#define W_MIN_ENDSTOP_INVERTING false // Set to true to invert the logic of the endstop.
#define X_MAX_ENDSTOP_INVERTING false // Set to true to invert the logic of the endstop.
#define Y_MAX_ENDSTOP_INVERTING false // Set to true to invert the logic of the endstop.
#define Z_MAX_ENDSTOP_INVERTING false // Set to true to invert the logic of the endstop.
#define I_MAX_ENDSTOP_INVERTING false // Set to true to invert the logic of the endstop.
#define J_MAX_ENDSTOP_INVERTING false // Set to true to invert the logic of the endstop.
#define K_MAX_ENDSTOP_INVERTING false // Set to true to invert the logic of the endstop.
#define U_MAX_ENDSTOP_INVERTING false // Set to true to invert the logic of the endstop.
#define V_MAX_ENDSTOP_INVERTING false // Set to true to invert the logic of the endstop.
#define W_MAX_ENDSTOP_INVERTING false // Set to true to invert the logic of the endstop.
#define Z_MIN_PROBE_ENDSTOP_INVERTING false // Set to true to invert the logic of the probe.
/**
@@ -882,6 +965,9 @@
//#define I_DRIVER_TYPE A4988
//#define J_DRIVER_TYPE A4988
//#define K_DRIVER_TYPE A4988
//#define U_DRIVER_TYPE A4988
//#define V_DRIVER_TYPE A4988
//#define W_DRIVER_TYPE A4988
#define E0_DRIVER_TYPE A4988
//#define E1_DRIVER_TYPE A4988
//#define E2_DRIVER_TYPE A4988
@@ -933,16 +1019,16 @@
//#define DISTINCT_E_FACTORS
/**
* Default Axis Steps Per Unit (steps/mm)
* Default Axis Steps Per Unit (linear=steps/mm, rotational=steps/°)
* Override with M92
* X, Y, Z [, I [, J [, K]]], E0 [, E1[, E2...]]
* X, Y, Z [, I [, J [, K...]]], E0 [, E1[, E2...]]
*/
#define DEFAULT_AXIS_STEPS_PER_UNIT { 80, 80, 400, 500 }
/**
* Default Max Feed Rate (mm/s)
* Default Max Feed Rate (linear=mm/s, rotational=°/s)
* Override with M203
* X, Y, Z [, I [, J [, K]]], E0 [, E1[, E2...]]
* X, Y, Z [, I [, J [, K...]]], E0 [, E1[, E2...]]
*/
#define DEFAULT_MAX_FEEDRATE { 300, 300, 5, 25 }
@@ -952,10 +1038,10 @@
#endif
/**
* Default Max Acceleration (change/s) change = mm/s
* Default Max Acceleration (speed change with time) (linear=mm/(s^2), rotational=°/(s^2))
* (Maximum start speed for accelerated moves)
* Override with M201
* X, Y, Z [, I [, J [, K]]], E0 [, E1[, E2...]]
* X, Y, Z [, I [, J [, K...]]], E0 [, E1[, E2...]]
*/
#define DEFAULT_MAX_ACCELERATION { 3000, 3000, 100, 10000 }
@@ -965,7 +1051,7 @@
#endif
/**
* Default Acceleration (change/s) change = mm/s
* Default Acceleration (speed change with time) (linear=mm/(s^2), rotational=°/(s^2))
* Override with M204
*
* M204 P Acceleration
@@ -978,7 +1064,7 @@
/**
* Default Jerk limits (mm/s)
* Override with M205 X Y Z E
* Override with M205 X Y Z . . . E
*
* "Jerk" specifies the minimum speed change that requires acceleration.
* When changing speed and direction, if the difference is less than the
@@ -992,6 +1078,9 @@
//#define DEFAULT_IJERK 0.3
//#define DEFAULT_JJERK 0.3
//#define DEFAULT_KJERK 0.3
//#define DEFAULT_UJERK 0.3
//#define DEFAULT_VJERK 0.3
//#define DEFAULT_WJERK 0.3
//#define TRAVEL_EXTRA_XYJERK 0.0 // Additional jerk allowance for all travel moves
@@ -1330,6 +1419,9 @@
//#define I_ENABLE_ON 0
//#define J_ENABLE_ON 0
//#define K_ENABLE_ON 0
//#define U_ENABLE_ON 0
//#define V_ENABLE_ON 0
//#define W_ENABLE_ON 0
// Disable axis steppers immediately when they're not being stepped.
// WARNING: When motors turn off there is a chance of losing position accuracy!
@@ -1339,6 +1431,9 @@
//#define DISABLE_I false
//#define DISABLE_J false
//#define DISABLE_K false
//#define DISABLE_U false
//#define DISABLE_V false
//#define DISABLE_W false
// Turn off the display blinking that warns about possible accuracy reduction
//#define DISABLE_REDUCED_ACCURACY_WARNING
@@ -1357,6 +1452,9 @@
//#define INVERT_I_DIR false
//#define INVERT_J_DIR false
//#define INVERT_K_DIR false
//#define INVERT_U_DIR false
//#define INVERT_V_DIR false
//#define INVERT_W_DIR false
// @section extruder
@@ -1395,6 +1493,9 @@
//#define I_HOME_DIR -1
//#define J_HOME_DIR -1
//#define K_HOME_DIR -1
//#define U_HOME_DIR -1
//#define V_HOME_DIR -1
//#define W_HOME_DIR -1
// @section machine
@@ -1402,7 +1503,7 @@
#define X_BED_SIZE 200
#define Y_BED_SIZE 200
// Travel limits (mm) after homing, corresponding to endstop positions.
// Travel limits (linear=mm, rotational=°) after homing, corresponding to endstop positions.
#define X_MIN_POS 0
#define Y_MIN_POS 0
#define Z_MIN_POS 0
@@ -1415,6 +1516,12 @@
//#define J_MAX_POS 50
//#define K_MIN_POS 0
//#define K_MAX_POS 50
//#define U_MIN_POS 0
//#define U_MAX_POS 50
//#define V_MIN_POS 0
//#define V_MAX_POS 50
//#define W_MIN_POS 0
//#define W_MAX_POS 50
/**
* Software Endstops
@@ -1434,6 +1541,9 @@
#define MIN_SOFTWARE_ENDSTOP_I
#define MIN_SOFTWARE_ENDSTOP_J
#define MIN_SOFTWARE_ENDSTOP_K
#define MIN_SOFTWARE_ENDSTOP_U
#define MIN_SOFTWARE_ENDSTOP_V
#define MIN_SOFTWARE_ENDSTOP_W
#endif
// Max software endstops constrain movement within maximum coordinate bounds
@@ -1445,6 +1555,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)
@@ -1745,6 +1858,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.
@@ -1760,7 +1876,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
+131 -15
View File
@@ -30,7 +30,7 @@
*
* Basic settings can be found in Configuration.h
*/
#define CONFIGURATION_ADV_H_VERSION 02000903
#define CONFIGURATION_ADV_H_VERSION 02010000
//===========================================================================
//============================= Thermal Settings ============================
@@ -843,12 +843,12 @@
* the position of the toolhead relative to the workspace.
*/
//#define SENSORLESS_BACKOFF_MM { 2, 2, 0 } // (mm) Backoff from endstops before sensorless homing
//#define SENSORLESS_BACKOFF_MM { 2, 2, 0 } // (linear=mm, rotational=°) Backoff from endstops before sensorless homing
#define HOMING_BUMP_MM { 5, 5, 2 } // (mm) Backoff from endstops after first bump
#define HOMING_BUMP_MM { 5, 5, 2 } // (linear=mm, rotational=°) Backoff from endstops after first bump
#define HOMING_BUMP_DIVISOR { 2, 2, 4 } // Re-Bump Speed Divisor (Divides the Homing Feedrate)
//#define HOMING_BACKOFF_POST_MM { 2, 2, 2 } // (mm) Backoff from endstops after homing
//#define HOMING_BACKOFF_POST_MM { 2, 2, 2 } // (linear=mm, rotational=°) Backoff from endstops after homing
//#define QUICK_HOME // If G28 contains XY do a diagonal move first
//#define HOME_Y_BEFORE_X // If G28 contains XY home Y before X
@@ -1034,6 +1034,9 @@
#define INVERT_I_STEP_PIN false
#define INVERT_J_STEP_PIN false
#define INVERT_K_STEP_PIN false
#define INVERT_U_STEP_PIN false
#define INVERT_V_STEP_PIN false
#define INVERT_W_STEP_PIN false
#define INVERT_E_STEP_PIN false
/**
@@ -1048,11 +1051,14 @@
#define DISABLE_INACTIVE_I true
#define DISABLE_INACTIVE_J true
#define DISABLE_INACTIVE_K true
#define DISABLE_INACTIVE_U true
#define DISABLE_INACTIVE_V true
#define DISABLE_INACTIVE_W true
#define DISABLE_INACTIVE_E true
// Default Minimum Feedrates for printing and travel moves
#define DEFAULT_MINIMUMFEEDRATE 0.0 // (mm/s) Minimum feedrate. Set with M205 S.
#define DEFAULT_MINTRAVELFEEDRATE 0.0 // (mm/s) Minimum travel feedrate. Set with M205 T.
#define DEFAULT_MINIMUMFEEDRATE 0.0 // (mm/s. °/s for rotational-only moves) Minimum feedrate. Set with M205 S.
#define DEFAULT_MINTRAVELFEEDRATE 0.0 // (mm/s. °/s for rotational-only moves) Minimum travel feedrate. Set with M205 T.
// Minimum time that a segment needs to take as the buffer gets emptied
#define DEFAULT_MINSEGMENTTIME 20000 // (µs) Set with M205 B.
@@ -1088,7 +1094,7 @@
#if ENABLED(BACKLASH_COMPENSATION)
// Define values for backlash distance and correction.
// If BACKLASH_GCODE is enabled these values are the defaults.
#define BACKLASH_DISTANCE_MM { 0, 0, 0 } // (mm) One value for each linear axis
#define BACKLASH_DISTANCE_MM { 0, 0, 0 } // (linear=mm, rotational=°) One value for each linear axis
#define BACKLASH_CORRECTION 0.0 // 0.0 = no correction; 1.0 = full correction
// Add steps for motor direction changes on CORE kinematics
@@ -1165,6 +1171,12 @@
//#define CALIBRATION_MEASURE_JMAX
//#define CALIBRATION_MEASURE_KMIN
//#define CALIBRATION_MEASURE_KMAX
//#define CALIBRATION_MEASURE_UMIN
//#define CALIBRATION_MEASURE_UMAX
//#define CALIBRATION_MEASURE_VMIN
//#define CALIBRATION_MEASURE_VMAX
//#define CALIBRATION_MEASURE_WMIN
//#define CALIBRATION_MEASURE_WMAX
// Probing at the exact top center only works if the center is flat. If
// probing on a screwhead or hollow washer, probe near the edges.
@@ -2012,6 +2024,21 @@
// @section leveling
/**
* Use Safe Bed Leveling coordinates to move axes to a useful position before bed probing.
* For example, after homing a rotational axis the Z probe might not be perpendicular to the bed.
* Choose values the orient the bed horizontally and the Z-probe vertically.
*/
//#define SAFE_BED_LEVELING_START_X 0.0
//#define SAFE_BED_LEVELING_START_Y 0.0
//#define SAFE_BED_LEVELING_START_Z 0.0
//#define SAFE_BED_LEVELING_START_I 0.0
//#define SAFE_BED_LEVELING_START_J 0.0
//#define SAFE_BED_LEVELING_START_K 0.0
//#define SAFE_BED_LEVELING_START_U 0.0
//#define SAFE_BED_LEVELING_START_V 0.0
//#define SAFE_BED_LEVELING_START_W 0.0
/**
* Points to probe for all 3-point Leveling procedures.
* Override if the automatically selected points are inadequate.
@@ -2423,7 +2450,7 @@
/**
* Extra G-code to run while executing tool-change commands. Can be used to use an additional
* stepper motor (I axis, see option LINEAR_AXES in Configuration.h) to drive the tool-changer.
* stepper motor (I axis, see option NUM_AXES in Configuration.h) to drive the tool-changer.
*/
//#define EVENT_GCODE_TOOLCHANGE_T0 "G28 A\nG1 A0" // Extra G-code to run while executing tool-change command T0
//#define EVENT_GCODE_TOOLCHANGE_T1 "G1 A10" // Extra G-code to run while executing tool-change command T1
@@ -2626,6 +2653,24 @@
#define K_MICROSTEPS 16
#endif
#if AXIS_DRIVER_TYPE_U(TMC26X)
#define U_MAX_CURRENT 1000
#define U_SENSE_RESISTOR 91
#define U_MICROSTEPS 16
#endif
#if AXIS_DRIVER_TYPE_V(TMC26X)
#define V_MAX_CURRENT 1000
#define V_SENSE_RESISTOR 91
#define V_MICROSTEPS 16
#endif
#if AXIS_DRIVER_TYPE_W(TMC26X)
#define W_MAX_CURRENT 1000
#define W_SENSE_RESISTOR 91
#define W_MICROSTEPS 16
#endif
#if AXIS_DRIVER_TYPE_E0(TMC26X)
#define E0_MAX_CURRENT 1000
#define E0_SENSE_RESISTOR 91
@@ -2814,6 +2859,33 @@
//#define K_HOLD_MULTIPLIER 0.5
#endif
#if AXIS_IS_TMC(U)
#define U_CURRENT 800
#define U_CURRENT_HOME U_CURRENT
#define U_MICROSTEPS 8
#define U_RSENSE 0.11
#define U_CHAIN_POS -1
//#define U_INTERPOLATE true
#endif
#if AXIS_IS_TMC(V)
#define V_CURRENT 800
#define V_CURRENT_HOME V_CURRENT
#define V_MICROSTEPS 8
#define V_RSENSE 0.11
#define V_CHAIN_POS -1
//#define V_INTERPOLATE true
#endif
#if AXIS_IS_TMC(W)
#define W_CURRENT 800
#define W_CURRENT_HOME W_CURRENT
#define W_MICROSTEPS 8
#define W_RSENSE 0.11
#define W_CHAIN_POS -1
//#define W_INTERPOLATE true
#endif
#if AXIS_IS_TMC(E0)
#define E0_CURRENT 800
#define E0_MICROSTEPS 16
@@ -2901,6 +2973,9 @@
//#define I_CS_PIN -1
//#define J_CS_PIN -1
//#define K_CS_PIN -1
//#define U_CS_PIN -1
//#define V_CS_PIN -1
//#define W_CS_PIN -1
//#define E0_CS_PIN -1
//#define E1_CS_PIN -1
//#define E2_CS_PIN -1
@@ -2943,6 +3018,9 @@
//#define I_SLAVE_ADDRESS 0
//#define J_SLAVE_ADDRESS 0
//#define K_SLAVE_ADDRESS 0
//#define U_SLAVE_ADDRESS 0
//#define V_SLAVE_ADDRESS 0
//#define W_SLAVE_ADDRESS 0
//#define E0_SLAVE_ADDRESS 0
//#define E1_SLAVE_ADDRESS 0
//#define E2_SLAVE_ADDRESS 0
@@ -2970,6 +3048,9 @@
#define STEALTHCHOP_I
#define STEALTHCHOP_J
#define STEALTHCHOP_K
#define STEALTHCHOP_U
#define STEALTHCHOP_V
#define STEALTHCHOP_W
#define STEALTHCHOP_E
/**
@@ -2996,9 +3077,12 @@
//#define CHOPPER_TIMING_Z2 CHOPPER_TIMING_Z
//#define CHOPPER_TIMING_Z3 CHOPPER_TIMING_Z
//#define CHOPPER_TIMING_Z4 CHOPPER_TIMING_Z
//#define CHOPPER_TIMING_I CHOPPER_TIMING
//#define CHOPPER_TIMING_J CHOPPER_TIMING
//#define CHOPPER_TIMING_K CHOPPER_TIMING
//#define CHOPPER_TIMING_I CHOPPER_TIMING // For I Axis
//#define CHOPPER_TIMING_J CHOPPER_TIMING // For J Axis
//#define CHOPPER_TIMING_K CHOPPER_TIMING // For K Axis
//#define CHOPPER_TIMING_U CHOPPER_TIMING // For U Axis
//#define CHOPPER_TIMING_V CHOPPER_TIMING // For V Axis
//#define CHOPPER_TIMING_W CHOPPER_TIMING // For W Axis
//#define CHOPPER_TIMING_E CHOPPER_TIMING // For Extruders (override below)
//#define CHOPPER_TIMING_E1 CHOPPER_TIMING_E
//#define CHOPPER_TIMING_E2 CHOPPER_TIMING_E
@@ -3044,9 +3128,12 @@
#define Z2_HYBRID_THRESHOLD 3
#define Z3_HYBRID_THRESHOLD 3
#define Z4_HYBRID_THRESHOLD 3
#define I_HYBRID_THRESHOLD 3
#define J_HYBRID_THRESHOLD 3
#define K_HYBRID_THRESHOLD 3
#define I_HYBRID_THRESHOLD 3 // [linear=mm/s, rotational=°/s]
#define J_HYBRID_THRESHOLD 3 // [linear=mm/s, rotational=°/s]
#define K_HYBRID_THRESHOLD 3 // [linear=mm/s, rotational=°/s]
#define U_HYBRID_THRESHOLD 3 // [mm/s]
#define V_HYBRID_THRESHOLD 3
#define W_HYBRID_THRESHOLD 3
#define E0_HYBRID_THRESHOLD 30
#define E1_HYBRID_THRESHOLD 30
#define E2_HYBRID_THRESHOLD 30
@@ -3096,6 +3183,9 @@
//#define I_STALL_SENSITIVITY 8
//#define J_STALL_SENSITIVITY 8
//#define K_STALL_SENSITIVITY 8
//#define U_STALL_SENSITIVITY 8
//#define V_STALL_SENSITIVITY 8
//#define W_STALL_SENSITIVITY 8
//#define SPI_ENDSTOPS // TMC2130 only
//#define IMPROVE_HOMING_RELIABILITY
#endif
@@ -3263,6 +3353,33 @@
#define K_SLEW_RATE 1
#endif
#if AXIS_IS_L64XX(U)
#define U_MICROSTEPS 128
#define U_OVERCURRENT 2000
#define U_STALLCURRENT 1500
#define U_MAX_VOLTAGE 127
#define U_CHAIN_POS -1
#define U_SLEW_RATE 1
#endif
#if AXIS_IS_L64XX(V)
#define V_MICROSTEPS 128
#define V_OVERCURRENT 2000
#define V_STALLCURRENT 1500
#define V_MAX_VOLTAGE 127
#define V_CHAIN_POS -1
#define V_SLEW_RATE 1
#endif
#if AXIS_IS_L64XX(W)
#define W_MICROSTEPS 128
#define W_OVERCURRENT 2000
#define W_STALLCURRENT 1500
#define W_MAX_VOLTAGE 127
#define W_CHAIN_POS -1
#define W_SLEW_RATE 1
#endif
#if AXIS_IS_L64XX(E0)
#define E0_MICROSTEPS 128
#define E0_OVERCURRENT 2000
@@ -4110,7 +4227,6 @@
/**
* Instant freeze / unfreeze functionality
* Specified pin has pullup and connecting to ground will instantly pause motion.
* Potentially useful for emergency stop that allows being resumed.
*/
//#define FREEZE_FEATURE
+1 -1
View File
@@ -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-03-29"
//#define STRING_DISTRIBUTION_DATE "2022-04-03"
/**
* Defines a generic printer name to be output to the LCD after booting Marlin.
+45
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);
+6
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));
}
+13 -13
View File
@@ -209,19 +209,19 @@ void MarlinHAL::adc_init() {
adc1_config_width(ADC_WIDTH_12Bit);
// Configure channels only if used as (re-)configuring a pin for ADC that is used elsewhere might have adverse effects
TERN_(HAS_TEMP_ADC_0, adc1_set_attenuation(get_channel(TEMP_0_PIN), ADC_ATTEN_11db));
TERN_(HAS_TEMP_ADC_1, adc1_set_attenuation(get_channel(TEMP_1_PIN), ADC_ATTEN_11db));
TERN_(HAS_TEMP_ADC_2, adc1_set_attenuation(get_channel(TEMP_2_PIN), ADC_ATTEN_11db));
TERN_(HAS_TEMP_ADC_3, adc1_set_attenuation(get_channel(TEMP_3_PIN), ADC_ATTEN_11db));
TERN_(HAS_TEMP_ADC_4, adc1_set_attenuation(get_channel(TEMP_4_PIN), ADC_ATTEN_11db));
TERN_(HAS_TEMP_ADC_5, adc1_set_attenuation(get_channel(TEMP_5_PIN), ADC_ATTEN_11db));
TERN_(HAS_TEMP_ADC_6, adc2_set_attenuation(get_channel(TEMP_6_PIN), ADC_ATTEN_11db));
TERN_(HAS_TEMP_ADC_7, adc3_set_attenuation(get_channel(TEMP_7_PIN), ADC_ATTEN_11db));
TERN_(HAS_HEATED_BED, adc1_set_attenuation(get_channel(TEMP_BED_PIN), ADC_ATTEN_11db));
TERN_(HAS_TEMP_CHAMBER, adc1_set_attenuation(get_channel(TEMP_CHAMBER_PIN), ADC_ATTEN_11db));
TERN_(HAS_TEMP_PROBE, adc1_set_attenuation(get_channel(TEMP_PROBE_PIN), ADC_ATTEN_11db));
TERN_(HAS_TEMP_COOLER, adc1_set_attenuation(get_channel(TEMP_COOLER_PIN), ADC_ATTEN_11db));
TERN_(HAS_TEMP_BOARD, adc1_set_attenuation(get_channel(TEMP_BOARD_PIN), ADC_ATTEN_11db));
TERN_(HAS_TEMP_ADC_0, adc1_set_attenuation(get_channel(TEMP_0_PIN), ADC_ATTEN_11db));
TERN_(HAS_TEMP_ADC_1, adc1_set_attenuation(get_channel(TEMP_1_PIN), ADC_ATTEN_11db));
TERN_(HAS_TEMP_ADC_2, adc1_set_attenuation(get_channel(TEMP_2_PIN), ADC_ATTEN_11db));
TERN_(HAS_TEMP_ADC_3, adc1_set_attenuation(get_channel(TEMP_3_PIN), ADC_ATTEN_11db));
TERN_(HAS_TEMP_ADC_4, adc1_set_attenuation(get_channel(TEMP_4_PIN), ADC_ATTEN_11db));
TERN_(HAS_TEMP_ADC_5, adc1_set_attenuation(get_channel(TEMP_5_PIN), ADC_ATTEN_11db));
TERN_(HAS_TEMP_ADC_6, adc2_set_attenuation(get_channel(TEMP_6_PIN), ADC_ATTEN_11db));
TERN_(HAS_TEMP_ADC_7, adc3_set_attenuation(get_channel(TEMP_7_PIN), ADC_ATTEN_11db));
TERN_(HAS_HEATED_BED, adc1_set_attenuation(get_channel(TEMP_BED_PIN), ADC_ATTEN_11db));
TERN_(HAS_TEMP_CHAMBER, adc1_set_attenuation(get_channel(TEMP_CHAMBER_PIN), ADC_ATTEN_11db));
TERN_(HAS_TEMP_PROBE, adc1_set_attenuation(get_channel(TEMP_PROBE_PIN), ADC_ATTEN_11db));
TERN_(HAS_TEMP_COOLER, adc1_set_attenuation(get_channel(TEMP_COOLER_PIN), ADC_ATTEN_11db));
TERN_(HAS_TEMP_BOARD, adc1_set_attenuation(get_channel(TEMP_BOARD_PIN), ADC_ATTEN_11db));
TERN_(FILAMENT_WIDTH_SENSOR, adc1_set_attenuation(get_channel(FILWIDTH_PIN), ADC_ATTEN_11db));
// Note that adc2 is shared with the WiFi module, which has higher priority, so the conversion may fail.
@@ -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));
}
@@ -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
}
@@ -29,7 +29,7 @@
#include "../../../inc/MarlinConfigPre.h"
#if MB(MKS_SBASE)
#if ENABLED(DIGIPOT_MCP4451) && MB(MKS_SBASE)
#ifdef __cplusplus
extern "C" {
@@ -37,35 +37,6 @@
#include "digipot_mcp4451_I2C_routines.h"
// These two routines are exact copies of the lpc17xx_i2c.c routines. Couldn't link to
// to the lpc17xx_i2c.c routines so had to copy them into this file & rename them.
static uint32_t _I2C_Start(LPC_I2C_TypeDef *I2Cx) {
// Reset STA, STO, SI
I2Cx->I2CONCLR = I2C_I2CONCLR_SIC|I2C_I2CONCLR_STOC|I2C_I2CONCLR_STAC;
// Enter to Master Transmitter mode
I2Cx->I2CONSET = I2C_I2CONSET_STA;
// Wait for complete
while (!(I2Cx->I2CONSET & I2C_I2CONSET_SI));
I2Cx->I2CONCLR = I2C_I2CONCLR_STAC;
return (I2Cx->I2STAT & I2C_STAT_CODE_BITMASK);
}
static void _I2C_Stop(LPC_I2C_TypeDef *I2Cx) {
// Make sure start bit is not active
if (I2Cx->I2CONSET & I2C_I2CONSET_STA)
I2Cx->I2CONCLR = I2C_I2CONCLR_STAC;
I2Cx->I2CONSET = I2C_I2CONSET_STO|I2C_I2CONSET_AA;
I2Cx->I2CONCLR = I2C_I2CONCLR_SIC;
}
I2C_M_SETUP_Type transferMCfg;
#define I2C_status (LPC_I2C1->I2STAT & I2C_STAT_CODE_BITMASK)
uint8_t digipot_mcp4451_start(uint8_t sla) { // send slave address and write bit
// Sometimes TX data ACK or NAK status is returned. That mean the start state didn't
// happen which means only the value of the slave address was send. Keep looping until
@@ -102,5 +73,5 @@ uint8_t digipot_mcp4451_send_byte(uint8_t data) {
}
#endif
#endif // MB(MKS_SBASE)
#endif // DIGIPOT_MCP4451 && MKS_SBASE
#endif // TARGET_LPC1768
+26
View File
@@ -63,6 +63,32 @@ void configure_i2c(const uint8_t clock_option) {
I2C_Cmd(I2CDEV_M, I2C_MASTER_MODE, ENABLE);
}
//////////////////////////////////////////////////////////////////////////////////////
// These two routines are exact copies of the lpc17xx_i2c.c routines. Couldn't link to
// to the lpc17xx_i2c.c routines so had to copy them into this file & rename them.
uint32_t _I2C_Start(LPC_I2C_TypeDef *I2Cx) {
// Reset STA, STO, SI
I2Cx->I2CONCLR = I2C_I2CONCLR_SIC|I2C_I2CONCLR_STOC|I2C_I2CONCLR_STAC;
// Enter to Master Transmitter mode
I2Cx->I2CONSET = I2C_I2CONSET_STA;
// Wait for complete
while (!(I2Cx->I2CONSET & I2C_I2CONSET_SI));
I2Cx->I2CONCLR = I2C_I2CONCLR_STAC;
return (I2Cx->I2STAT & I2C_STAT_CODE_BITMASK);
}
void _I2C_Stop(LPC_I2C_TypeDef *I2Cx) {
/* Make sure start bit is not active */
if (I2Cx->I2CONSET & I2C_I2CONSET_STA)
I2Cx->I2CONCLR = I2C_I2CONCLR_STAC;
I2Cx->I2CONSET = I2C_I2CONSET_STO|I2C_I2CONSET_AA;
I2Cx->I2CONCLR = I2C_I2CONCLR_SIC;
}
#ifdef __cplusplus
}
#endif
@@ -51,6 +51,11 @@
void configure_i2c(const uint8_t clock_option);
uint32_t _I2C_Start(LPC_I2C_TypeDef *I2Cx);
void _I2C_Stop(LPC_I2C_TypeDef *I2Cx);
#define I2C_status (LPC_I2C1->I2STAT & I2C_STAT_CODE_BITMASK)
#ifdef __cplusplus
}
#endif
@@ -36,40 +36,7 @@ extern int millis();
//////////////////////////////////////////////////////////////////////////////////////
// These two routines are exact copies of the lpc17xx_i2c.c routines. Couldn't link to
// to the lpc17xx_i2c.c routines so had to copy them into this file & rename them.
static uint32_t _I2C_Start(LPC_I2C_TypeDef *I2Cx) {
// Reset STA, STO, SI
I2Cx->I2CONCLR = I2C_I2CONCLR_SIC|I2C_I2CONCLR_STOC|I2C_I2CONCLR_STAC;
// Enter to Master Transmitter mode
I2Cx->I2CONSET = I2C_I2CONSET_STA;
// Wait for complete
while (!(I2Cx->I2CONSET & I2C_I2CONSET_SI));
I2Cx->I2CONCLR = I2C_I2CONCLR_STAC;
return (I2Cx->I2STAT & I2C_STAT_CODE_BITMASK);
}
static void _I2C_Stop (LPC_I2C_TypeDef *I2Cx) {
/* Make sure start bit is not active */
if (I2Cx->I2CONSET & I2C_I2CONSET_STA)
I2Cx->I2CONCLR = I2C_I2CONCLR_STAC;
I2Cx->I2CONSET = I2C_I2CONSET_STO|I2C_I2CONSET_AA;
I2Cx->I2CONCLR = I2C_I2CONCLR_SIC;
}
//////////////////////////////////////////////////////////////////////////////////////
#define I2CDEV_S_ADDR 0x78 // from SSD1306 //actual address is 0x3C - shift left 1 with LSB set to 0 to indicate write
#define BUFFER_SIZE 0x1 // only do single byte transfers with LCDs
I2C_M_SETUP_Type transferMCfg;
#define I2C_status (LPC_I2C1->I2STAT & I2C_STAT_CODE_BITMASK)
#define I2CDEV_S_ADDR 0x78 // From SSD1306 (actual address is 0x3C - shift left 1 with LSB set to 0 to indicate write)
// Send slave address and write bit
uint8_t u8g_i2c_start(const uint8_t sla) {
@@ -115,7 +82,6 @@ uint8_t u8g_i2c_send_byte(uint8_t data) {
void u8g_i2c_stop() {
}
#ifdef __cplusplus
}
#endif
@@ -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
}
@@ -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));
}
@@ -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));
}
@@ -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));
}
@@ -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));
}
+12
View File
@@ -436,6 +436,9 @@ inline void manage_inactivity(const bool no_stepper_sleep=false) {
TERN_(DISABLE_INACTIVE_I, stepper.disable_axis(I_AXIS));
TERN_(DISABLE_INACTIVE_J, stepper.disable_axis(J_AXIS));
TERN_(DISABLE_INACTIVE_K, stepper.disable_axis(K_AXIS));
TERN_(DISABLE_INACTIVE_U, stepper.disable_axis(U_AXIS));
TERN_(DISABLE_INACTIVE_V, stepper.disable_axis(V_AXIS));
TERN_(DISABLE_INACTIVE_W, stepper.disable_axis(W_AXIS));
TERN_(DISABLE_INACTIVE_E, stepper.disable_e_steppers());
TERN_(AUTO_BED_LEVELING_UBL, ubl.steppers_were_disabled());
@@ -993,6 +996,15 @@ inline void tmc_standby_setup() {
#if PIN_EXISTS(K_STDBY)
SET_INPUT_PULLDOWN(K_STDBY_PIN);
#endif
#if PIN_EXISTS(U_STDBY)
SET_INPUT_PULLDOWN(U_STDBY_PIN);
#endif
#if PIN_EXISTS(V_STDBY)
SET_INPUT_PULLDOWN(V_STDBY_PIN);
#endif
#if PIN_EXISTS(W_STDBY)
SET_INPUT_PULLDOWN(W_STDBY_PIN);
#endif
#if PIN_EXISTS(E0_STDBY)
SET_INPUT_PULLDOWN(E0_STDBY_PIN);
#endif
+5
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) (EITHER(X_DUAL_STEPPER_DRIVERS, DUAL_X_CARRIAGE) && _AXIS_DRIVER_TYPE(X2,T))
#define AXIS_DRIVER_TYPE_Y2(T) (ENABLED(Y_DUAL_STEPPER_DRIVERS) && _AXIS_DRIVER_TYPE(Y2,T))
@@ -87,6 +90,7 @@
#define HAS_DRIVER(T) ( AXIS_DRIVER_TYPE_X(T) || AXIS_DRIVER_TYPE_Y(T) || AXIS_DRIVER_TYPE_Z(T) \
|| AXIS_DRIVER_TYPE_I(T) || AXIS_DRIVER_TYPE_J(T) || AXIS_DRIVER_TYPE_K(T) \
|| AXIS_DRIVER_TYPE_U(T) || AXIS_DRIVER_TYPE_V(T) || AXIS_DRIVER_TYPE_W(T) \
|| AXIS_DRIVER_TYPE_X2(T) || AXIS_DRIVER_TYPE_Y2(T) || AXIS_DRIVER_TYPE_Z2(T) \
|| AXIS_DRIVER_TYPE_Z3(T) || AXIS_DRIVER_TYPE_Z4(T) || HAS_E_DRIVER(T) )
@@ -161,6 +165,7 @@
|| AXIS_HAS_##T(Y) || AXIS_HAS_##T(Y2) \
|| AXIS_HAS_##T(Z) || AXIS_HAS_##T(Z2) || AXIS_HAS_##T(Z3) || AXIS_HAS_##T(Z4) \
|| AXIS_HAS_##T(I) || AXIS_HAS_##T(J) || AXIS_HAS_##T(K) \
|| AXIS_HAS_##T(U) || AXIS_HAS_##T(V) || AXIS_HAS_##T(W) \
|| E_AXIS_HAS(T) )
#if ANY_AXIS_HAS(STEALTHCHOP)
+48
View File
@@ -444,6 +444,54 @@
#define STR_K ""
#endif
#if HAS_U_AXIS
#if AXIS7_NAME == 'U'
#define STR_U "U"
#define STR_U_MIN "u_min"
#define STR_U_MAX "u_max"
#elif AXIS7_NAME == 'V'
#define STR_U "V"
#define STR_U_MIN "v_min"
#define STR_U_MAX "v_max"
#elif AXIS7_NAME == 'W'
#define STR_U "W"
#define STR_U_MIN "w_min"
#define STR_U_MAX "w_max"
#else
#error "AXIS7_NAME can only be one of 'U', 'V', or 'W'."
#endif
#else
#define STR_U ""
#endif
#if HAS_V_AXIS
#if AXIS8_NAME == 'V'
#define STR_V "V"
#define STR_V_MIN "v_min"
#define STR_V_MAX "v_max"
#elif AXIS8_NAME == 'W'
#define STR_V "W"
#define STR_V_MIN "w_min"
#define STR_V_MAX "w_max"
#else
#error "AXIS8_NAME can only be one of 'V', or 'W'."
#endif
#else
#define STR_V ""
#endif
#if HAS_W_AXIS
#if AXIS9_NAME == 'W'
#define STR_W "W"
#define STR_W_MIN "w_min"
#define STR_W_MAX "w_max"
#else
#error "AXIS9_NAME can only be 'W'."
#endif
#else
#define STR_W ""
#endif
#if EITHER(HAS_MARLINUI_HD44780, IS_TFTGLCD_PANEL)
// Custom characters defined in the first 8 characters of the LCD
+13 -1
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) }
+6 -2
View File
@@ -32,14 +32,18 @@ uint8_t marlin_debug_flags = MARLIN_DEBUG_NONE;
// Commonly-used strings in serial output
PGMSTR(NUL_STR, ""); PGMSTR(SP_P_STR, " P"); PGMSTR(SP_T_STR, " T");
PGMSTR(X_STR, "X"); PGMSTR(Y_STR, "Y"); PGMSTR(Z_STR, "Z"); PGMSTR(E_STR, "E");
PGMSTR(U_STR, STR_U); PGMSTR(V_STR, STR_V); PGMSTR(W_STR, STR_W);
PGMSTR(X_LBL, "X:"); PGMSTR(Y_LBL, "Y:"); PGMSTR(Z_LBL, "Z:"); PGMSTR(E_LBL, "E:");
PGMSTR(U_LBL, STR_U ":"); PGMSTR(V_LBL, STR_V ":"); PGMSTR(W_LBL, STR_W ":");
PGMSTR(SP_A_STR, " A"); PGMSTR(SP_B_STR, " B"); PGMSTR(SP_C_STR, " C");
PGMSTR(SP_X_STR, " X"); PGMSTR(SP_Y_STR, " Y"); PGMSTR(SP_Z_STR, " Z"); PGMSTR(SP_E_STR, " E");
PGMSTR(SP_X_LBL, " X:"); PGMSTR(SP_Y_LBL, " Y:"); PGMSTR(SP_Z_LBL, " Z:"); PGMSTR(SP_E_LBL, " E:");
PGMSTR(I_STR, STR_I); PGMSTR(J_STR, STR_J); PGMSTR(K_STR, STR_K);
PGMSTR(I_LBL, STR_I ":"); PGMSTR(J_LBL, STR_J ":"); PGMSTR(K_LBL, STR_K ":");
PGMSTR(SP_I_STR, " " STR_I); PGMSTR(SP_J_STR, " " STR_J); PGMSTR(SP_K_STR, " " STR_K);
PGMSTR(SP_U_STR, " " STR_U); PGMSTR(SP_V_STR, " " STR_V); PGMSTR(SP_W_STR, " " STR_W);
PGMSTR(SP_I_LBL, " " STR_I ":"); PGMSTR(SP_J_LBL, " " STR_J ":"); PGMSTR(SP_K_LBL, " " STR_K ":");
PGMSTR(SP_U_LBL, " " STR_U ":"); PGMSTR(SP_V_LBL, " " STR_V ":"); PGMSTR(SP_W_LBL, " " STR_W ":");
// Hook Meatpack if it's enabled on the first leaf
#if ENABLED(MEATPACK_ON_SERIAL_PORT_1)
@@ -102,10 +106,10 @@ void print_bin(uint16_t val) {
}
}
void print_pos(LINEAR_AXIS_ARGS(const_float_t), FSTR_P const prefix/*=nullptr*/, FSTR_P const suffix/*=nullptr*/) {
void print_pos(NUM_AXIS_ARGS(const_float_t), FSTR_P const prefix/*=nullptr*/, FSTR_P const suffix/*=nullptr*/) {
if (prefix) serial_print(prefix);
SERIAL_ECHOPGM_P(
LIST_N(DOUBLE(LINEAR_AXES), SP_X_STR, x, SP_Y_STR, y, SP_Z_STR, z, SP_I_STR, i, SP_J_STR, j, SP_K_STR, k)
LIST_N(DOUBLE(NUM_AXES), SP_X_STR, x, SP_Y_STR, y, SP_Z_STR, z, SP_I_STR, i, SP_J_STR, j, SP_K_STR, k, SP_U_STR, u, SP_V_STR, v, SP_W_STR, w)
);
if (suffix) serial_print(suffix); else SERIAL_EOL();
}
+8 -13
View File
@@ -29,17 +29,12 @@
#endif
// Commonly-used strings in serial output
extern const char NUL_STR[],
SP_X_STR[], SP_Y_STR[], SP_Z_STR[],
SP_A_STR[], SP_B_STR[], SP_C_STR[], SP_E_STR[],
SP_X_LBL[], SP_Y_LBL[], SP_Z_LBL[], SP_E_LBL[],
SP_I_STR[], SP_J_STR[], SP_K_STR[],
SP_I_LBL[], SP_J_LBL[], SP_K_LBL[],
SP_P_STR[], SP_T_STR[],
X_STR[], Y_STR[], Z_STR[], E_STR[],
I_STR[], J_STR[], K_STR[],
X_LBL[], Y_LBL[], Z_LBL[], E_LBL[],
I_LBL[], J_LBL[], K_LBL[];
extern const char NUL_STR[], SP_P_STR[], SP_T_STR[],
SP_A_STR[], SP_B_STR[], SP_C_STR[],
SP_X_STR[], SP_Y_STR[], SP_Z_STR[], SP_I_STR[], SP_J_STR[], SP_K_STR[], SP_U_STR[], SP_V_STR[], SP_W_STR[], SP_E_STR[],
SP_X_LBL[], SP_Y_LBL[], SP_Z_LBL[], SP_I_LBL[], SP_J_LBL[], SP_K_LBL[], SP_U_LBL[], SP_V_LBL[], SP_W_LBL[], SP_E_LBL[],
X_STR[], Y_STR[], Z_STR[], I_STR[], J_STR[], K_STR[], U_STR[], V_STR[], W_STR[], E_STR[],
X_LBL[], Y_LBL[], Z_LBL[], I_LBL[], J_LBL[], K_LBL[], U_LBL[], V_LBL[], W_LBL[], E_LBL[];
//
// Debugging flags for use by M111
@@ -348,10 +343,10 @@ void serial_spaces(uint8_t count);
void serial_offset(const_float_t v, const uint8_t sp=0); // For v==0 draw space (sp==1) or plus (sp==2)
void print_bin(const uint16_t val);
void print_pos(LINEAR_AXIS_ARGS(const_float_t), FSTR_P const prefix=nullptr, FSTR_P const suffix=nullptr);
void print_pos(NUM_AXIS_ARGS(const_float_t), FSTR_P const prefix=nullptr, FSTR_P const suffix=nullptr);
inline void print_pos(const xyz_pos_t &xyz, FSTR_P const prefix=nullptr, FSTR_P const suffix=nullptr) {
print_pos(LINEAR_AXIS_ELEM(xyz), prefix, suffix);
print_pos(NUM_AXIS_ELEM(xyz), prefix, suffix);
}
#define SERIAL_POS(SUFFIX,VAR) do { print_pos(VAR, F(" " STRINGIFY(VAR) "="), F(" : " SUFFIX "\n")); }while(0)
+206 -176
View File
@@ -36,23 +36,33 @@ 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_ARRAY(V...) { NUM_AXIS_LIST(V) }
#define NUM_AXIS_ARGS(T...) NUM_AXIS_LIST(T x, T y, T z, T i, T j, T k, T u, T v, T w)
#define NUM_AXIS_ELEM(O) NUM_AXIS_LIST(O.x, O.y, O.z, O.i, O.j, O.k, O.u, O.v, O.w)
#define NUM_AXIS_DEFS(T,V) NUM_AXIS_LIST(T x=V, T y=V, T z=V, T i=V, T j=V, T k=V, T u=V, T v=V, T w=V)
#define LOGICAL_AXIS_GANG(E,V...) 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_ARRAY(E,V...) { LOGICAL_AXIS_LIST(E,V) }
#define LOGICAL_AXIS_ARGS(T...) LOGICAL_AXIS_LIST(T e, T x, T y, T z, T i, T j, T k)
#define LOGICAL_AXIS_ELEM(O) LOGICAL_AXIS_LIST(O.e, O.x, O.y, O.z, O.i, O.j, O.k)
#define LOGICAL_AXIS_DECL(T,V) LOGICAL_AXIS_LIST(T e=V, T x=V, T y=V, T z=V, T i=V, T j=V, T k=V)
#define LOGICAL_AXIS_ARGS(T...) LOGICAL_AXIS_LIST(T e, T x, T y, T z, T i, T j, T k, T u, T v, T w)
#define LOGICAL_AXIS_ELEM(O) LOGICAL_AXIS_LIST(O.e, O.x, O.y, O.z, O.i, O.j, O.k, O.u, O.v, O.w)
#define LOGICAL_AXIS_DECL(T,V) LOGICAL_AXIS_LIST(T e=V, T x=V, T y=V, T z=V, T i=V, T j=V, T k=V, T u=V, T v=V, T w=V)
#define LOGICAL_AXES_STRING LOGICAL_AXIS_GANG("E", "X", "Y", "Z", STR_I, STR_J, STR_K)
#define LOGICAL_AXES_STRING LOGICAL_AXIS_GANG("E", "X", "Y", "Z", STR_I, STR_J, STR_K, STR_U, STR_V, STR_W)
#define XYZ_GANG(V...) GANG_N(PRIMARY_LINEAR_AXES, V)
#define XYZ_CODE(V...) CODE_N(PRIMARY_LINEAR_AXES, V)
#define SECONDARY_AXIS_GANG(V...) GANG_N(SECONDARY_AXES, V)
#define SECONDARY_AXIS_CODE(V...) CODE_N(SECONDARY_AXES, V)
#if HAS_ROTATIONAL_AXES
#define ROTATIONAL_AXIS_GANG(V...) GANG_N(ROTATIONAL_AXES, V)
#endif
#if HAS_EXTRUDERS
#define LIST_ITEM_E(N) , N
@@ -64,7 +74,7 @@ struct IF<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)
//
// Enumerated axis indices
@@ -76,7 +86,7 @@ struct IF<true, L, R> { typedef L type; };
enum AxisEnum : uint8_t {
// Linear axes may be controlled directly or indirectly
LINEAR_AXIS_LIST(X_AXIS, Y_AXIS, Z_AXIS, I_AXIS, J_AXIS, K_AXIS)
NUM_AXIS_LIST(X_AXIS, Y_AXIS, Z_AXIS, I_AXIS, J_AXIS, K_AXIS, U_AXIS, V_AXIS, W_AXIS)
// Extruder axes may be considered distinctly
#define _EN_ITEM(N) , E##N##_AXIS
@@ -110,12 +120,13 @@ enum AxisEnum : uint8_t {
};
typedef IF<(NUM_AXIS_ENUMS > 8), uint16_t, uint8_t>::type axis_bits_t;
typedef IF<(NUM_AXES > 8), uint16_t, uint8_t>::type linear_axis_bits_t;
//
// Loop over axes
//
#define LOOP_ABC(VAR) LOOP_S_LE_N(VAR, A_AXIS, C_AXIS)
#define LOOP_LINEAR_AXES(VAR) LOOP_S_L_N(VAR, X_AXIS, LINEAR_AXES)
#define LOOP_NUM_AXES(VAR) LOOP_S_L_N(VAR, X_AXIS, NUM_AXES)
#define LOOP_LOGICAL_AXES(VAR) LOOP_S_L_N(VAR, X_AXIS, LOGICAL_AXES)
#define LOOP_DISTINCT_AXES(VAR) LOOP_S_L_N(VAR, X_AXIS, DISTINCT_AXES)
#define LOOP_DISTINCT_E(VAR) LOOP_L_N(VAR, DISTINCT_E)
@@ -260,10 +271,10 @@ struct XYval {
FI void set(const T px, const T py) { x = px; y = py; }
FI void set(const T (&arr)[XY]) { x = arr[0]; y = arr[1]; }
#endif
#if LINEAR_AXES > XY
FI void set(const T (&arr)[LINEAR_AXES]) { x = arr[0]; y = arr[1]; }
#if NUM_AXES > XY
FI void set(const T (&arr)[NUM_AXES]) { x = arr[0]; y = arr[1]; }
#endif
#if LOGICAL_AXES > LINEAR_AXES
#if LOGICAL_AXES > NUM_AXES
FI void set(const T (&arr)[LOGICAL_AXES]) { x = arr[0]; y = arr[1]; }
#if DISTINCT_AXES > LOGICAL_AXES
FI void set(const T (&arr)[DISTINCT_AXES]) { x = arr[0]; y = arr[1]; }
@@ -385,60 +396,69 @@ struct XYval {
template<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; }
@@ -449,78 +469,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); }
};
@@ -532,56 +552,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; }
@@ -598,9 +628,9 @@ struct XYZEval {
FI const T& operator[](const int n) const { return pos[n]; }
// Assignment operator overrides do the expected thing
FI XYZEval<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; }
@@ -611,57 +641,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); }
};
+2 -2
View File
@@ -125,7 +125,7 @@ void safe_delay(millis_t ms) {
#endif
#if ABL_PLANAR
SERIAL_ECHOPGM("ABL Adjustment");
LOOP_LINEAR_AXES(a) {
LOOP_NUM_AXES(a) {
SERIAL_CHAR(' ', AXIS_CHAR(a));
serial_offset(planner.get_axis_position_mm(AxisEnum(a)) - current_position[a]);
}
@@ -135,7 +135,7 @@ void safe_delay(millis_t ms) {
const float rz = ubl.get_z_correction(current_position);
#elif ENABLED(AUTO_BED_LEVELING_BILINEAR)
SERIAL_ECHOPGM("ABL Adjustment Z");
const float rz = bilinear_z_offset(current_position);
const float rz = bbl.get_z_correction(current_position);
#endif
SERIAL_ECHO(ftostr43sign(rz, '+'));
#if ENABLED(ENABLE_LEVELING_FADE_HEIGHT)
+6 -3
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
#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
+4 -4
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);
@@ -165,11 +165,11 @@ class Backlash::StepAdjuster {
xyz_long_t applied_steps;
public:
StepAdjuster() {
LOOP_LINEAR_AXES(axis) applied_steps[axis] = backlash.get_applied_steps((AxisEnum)axis);
LOOP_NUM_AXES(axis) applied_steps[axis] = backlash.get_applied_steps((AxisEnum)axis);
}
~StepAdjuster() {
// after backlash compensation parameter changes, ensure applied step count does not change
LOOP_LINEAR_AXES(axis) residual_error[axis] += backlash.get_applied_steps((AxisEnum)axis) - applied_steps[axis];
LOOP_NUM_AXES(axis) residual_error[axis] += backlash.get_applied_steps((AxisEnum)axis) - applied_steps[axis];
}
};
-45
View File
@@ -1,45 +0,0 @@
/**
* Marlin 3D Printer Firmware
* Copyright (c) 2020 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
*
* Based on Sprinter and grbl.
* Copyright (c) 2011 Camiel Gubbels / Erik van der Zalm
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*
*/
#pragma once
#include "../../../inc/MarlinConfigPre.h"
extern xy_pos_t bilinear_grid_spacing, bilinear_start;
extern xy_float_t bilinear_grid_factor;
extern bed_mesh_t z_values;
float bilinear_z_offset(const xy_pos_t &raw);
void extrapolate_unprobed_bed_level();
void print_bilinear_leveling_grid();
void refresh_bed_level();
#if ENABLED(ABL_BILINEAR_SUBDIVISION)
void print_bilinear_leveling_grid_virt();
void bed_level_virt_interpolate();
#endif
#if IS_CARTESIAN && DISABLED(SEGMENT_LEVELED_MOVES)
void bilinear_line_to_destination(const_feedRate_t scaled_fr_mm_s, uint16_t x_splits=0xFFFF, uint16_t y_splits=0xFFFF);
#endif
#define _GET_MESH_X(I) float(bilinear_start.x + (I) * bilinear_grid_spacing.x)
#define _GET_MESH_Y(J) float(bilinear_start.y + (J) * bilinear_grid_spacing.y)
#define Z_VALUES_ARR z_values
@@ -35,14 +35,19 @@
#include "../../../lcd/extui/ui_api.h"
#endif
xy_pos_t bilinear_grid_spacing, bilinear_start;
xy_float_t bilinear_grid_factor;
bed_mesh_t z_values;
LevelingBilinear bbl;
xy_pos_t LevelingBilinear::grid_spacing,
LevelingBilinear::grid_start;
xy_float_t LevelingBilinear::grid_factor;
bed_mesh_t LevelingBilinear::z_values;
xy_pos_t LevelingBilinear::cached_rel;
xy_int8_t LevelingBilinear::cached_g;
/**
* Extrapolate a single point from its neighbors
*/
static void extrapolate_one_point(const uint8_t x, const uint8_t y, const int8_t xdir, const int8_t ydir) {
void LevelingBilinear::extrapolate_one_point(const uint8_t x, const uint8_t y, const int8_t xdir, const int8_t ydir) {
if (!isnan(z_values[x][y])) return;
if (DEBUGGING(LEVELING)) {
DEBUG_ECHOPGM("Extrapolate [");
@@ -92,11 +97,26 @@ static void extrapolate_one_point(const uint8_t x, const uint8_t y, const int8_t
#endif
#endif
void LevelingBilinear::reset() {
grid_start.reset();
grid_spacing.reset();
GRID_LOOP(x, y) {
z_values[x][y] = NAN;
TERN_(EXTENSIBLE_UI, ExtUI::onMeshUpdate(x, y, 0));
}
}
void LevelingBilinear::set_grid(const xy_pos_t& _grid_spacing, const xy_pos_t& _grid_start) {
grid_spacing = _grid_spacing;
grid_start = _grid_start;
grid_factor = grid_spacing.reciprocal();
}
/**
* Fill in the unprobed points (corners of circular print surface)
* using linear extrapolation, away from the center.
*/
void extrapolate_unprobed_bed_level() {
void LevelingBilinear::extrapolate_unprobed_bed_level() {
#ifdef HALF_IN_X
constexpr uint8_t ctrx2 = 0, xend = GRID_MAX_POINTS_X - 1;
#else
@@ -131,35 +151,31 @@ void extrapolate_unprobed_bed_level() {
#endif
extrapolate_one_point(x2, y2, -1, -1); // right-above - -
}
}
void print_bilinear_leveling_grid() {
void LevelingBilinear::print_leveling_grid(const bed_mesh_t* _z_values /*= NULL*/) {
// print internal grid(s) or just the one passed as a parameter
SERIAL_ECHOLNPGM("Bilinear Leveling Grid:");
print_2d_array(GRID_MAX_POINTS_X, GRID_MAX_POINTS_Y, 3,
[](const uint8_t ix, const uint8_t iy) { return z_values[ix][iy]; }
);
print_2d_array(GRID_MAX_POINTS_X, GRID_MAX_POINTS_Y, 3, _z_values ? *_z_values[0] : z_values[0]);
#if ENABLED(ABL_BILINEAR_SUBDIVISION)
if (!_z_values) {
SERIAL_ECHOLNPGM("Subdivided with CATMULL ROM Leveling Grid:");
print_2d_array(ABL_GRID_POINTS_VIRT_X, ABL_GRID_POINTS_VIRT_Y, 5, z_values_virt[0]);
}
#endif
}
#if ENABLED(ABL_BILINEAR_SUBDIVISION)
#define ABL_GRID_POINTS_VIRT_X GRID_MAX_CELLS_X * (BILINEAR_SUBDIVISIONS) + 1
#define ABL_GRID_POINTS_VIRT_Y GRID_MAX_CELLS_Y * (BILINEAR_SUBDIVISIONS) + 1
#define ABL_TEMP_POINTS_X (GRID_MAX_POINTS_X + 2)
#define ABL_TEMP_POINTS_Y (GRID_MAX_POINTS_Y + 2)
float z_values_virt[ABL_GRID_POINTS_VIRT_X][ABL_GRID_POINTS_VIRT_Y];
xy_pos_t bilinear_grid_spacing_virt;
xy_float_t bilinear_grid_factor_virt;
void print_bilinear_leveling_grid_virt() {
SERIAL_ECHOLNPGM("Subdivided with CATMULL ROM Leveling Grid:");
print_2d_array(ABL_GRID_POINTS_VIRT_X, ABL_GRID_POINTS_VIRT_Y, 5,
[](const uint8_t ix, const uint8_t iy) { return z_values_virt[ix][iy]; }
);
}
float LevelingBilinear::z_values_virt[ABL_GRID_POINTS_VIRT_X][ABL_GRID_POINTS_VIRT_Y];
xy_pos_t LevelingBilinear::grid_spacing_virt;
xy_float_t LevelingBilinear::grid_factor_virt;
#define LINEAR_EXTRAPOLATION(E, I) ((E) * 2 - (I))
float bed_level_virt_coord(const uint8_t x, const uint8_t y) {
float LevelingBilinear::bed_level_virt_coord(const uint8_t x, const uint8_t y) {
uint8_t ep = 0, ip = 1;
if (x > (GRID_MAX_POINTS_X) + 1 || y > (GRID_MAX_POINTS_Y) + 1) {
// The requested point requires extrapolating two points beyond the mesh.
@@ -204,7 +220,7 @@ void print_bilinear_leveling_grid() {
return z_values[x - 1][y - 1];
}
static float bed_level_virt_cmr(const float p[4], const uint8_t i, const float t) {
float LevelingBilinear::bed_level_virt_cmr(const float p[4], const uint8_t i, const float t) {
return (
p[i-1] * -t * sq(1 - t)
+ p[i] * (2 - 5 * sq(t) + 3 * t * sq(t))
@@ -213,7 +229,7 @@ void print_bilinear_leveling_grid() {
) * 0.5f;
}
static float bed_level_virt_2cmr(const uint8_t x, const uint8_t y, const_float_t tx, const_float_t ty) {
float LevelingBilinear::bed_level_virt_2cmr(const uint8_t x, const uint8_t y, const_float_t tx, const_float_t ty) {
float row[4], column[4];
LOOP_L_N(i, 4) {
LOOP_L_N(j, 4) {
@@ -224,9 +240,9 @@ void print_bilinear_leveling_grid() {
return bed_level_virt_cmr(row, 1, tx);
}
void bed_level_virt_interpolate() {
bilinear_grid_spacing_virt = bilinear_grid_spacing / (BILINEAR_SUBDIVISIONS);
bilinear_grid_factor_virt = bilinear_grid_spacing_virt.reciprocal();
void LevelingBilinear::bed_level_virt_interpolate() {
grid_spacing_virt = grid_spacing / (BILINEAR_SUBDIVISIONS);
grid_factor_virt = grid_spacing_virt.reciprocal();
LOOP_L_N(y, GRID_MAX_POINTS_Y)
LOOP_L_N(x, GRID_MAX_POINTS_X)
LOOP_L_N(ty, BILINEAR_SUBDIVISIONS)
@@ -244,38 +260,40 @@ void print_bilinear_leveling_grid() {
}
#endif // ABL_BILINEAR_SUBDIVISION
// Refresh after other values have been updated
void refresh_bed_level() {
bilinear_grid_factor = bilinear_grid_spacing.reciprocal();
void LevelingBilinear::refresh_bed_level() {
TERN_(ABL_BILINEAR_SUBDIVISION, bed_level_virt_interpolate());
cached_rel.x = cached_rel.y = -999.999;
cached_g.x = cached_g.y = -99;
}
#if ENABLED(ABL_BILINEAR_SUBDIVISION)
#define ABL_BG_SPACING(A) bilinear_grid_spacing_virt.A
#define ABL_BG_FACTOR(A) bilinear_grid_factor_virt.A
#define ABL_BG_SPACING(A) grid_spacing_virt.A
#define ABL_BG_FACTOR(A) grid_factor_virt.A
#define ABL_BG_POINTS_X ABL_GRID_POINTS_VIRT_X
#define ABL_BG_POINTS_Y ABL_GRID_POINTS_VIRT_Y
#define ABL_BG_GRID(X,Y) z_values_virt[X][Y]
#else
#define ABL_BG_SPACING(A) bilinear_grid_spacing.A
#define ABL_BG_FACTOR(A) bilinear_grid_factor.A
#define ABL_BG_SPACING(A) grid_spacing.A
#define ABL_BG_FACTOR(A) grid_factor.A
#define ABL_BG_POINTS_X GRID_MAX_POINTS_X
#define ABL_BG_POINTS_Y GRID_MAX_POINTS_Y
#define ABL_BG_GRID(X,Y) z_values[X][Y]
#endif
// Get the Z adjustment for non-linear bed leveling
float bilinear_z_offset(const xy_pos_t &raw) {
float LevelingBilinear::get_z_correction(const xy_pos_t &raw) {
static float z1, d2, z3, d4, L, D;
static xy_pos_t prev { -999.999, -999.999 }, ratio;
static xy_pos_t ratio;
// Whole units for the grid line indices. Constrained within bounds.
static xy_int8_t thisg, nextg, lastg { -99, -99 };
static xy_int8_t thisg, nextg;
// XY relative to the probed area
xy_pos_t rel = raw - bilinear_start.asFloat();
xy_pos_t rel = raw - grid_start.asFloat();
#if ENABLED(EXTRAPOLATE_BEYOND_GRID)
#define FAR_EDGE_OR_BOX 2 // Keep using the last grid box
@@ -283,8 +301,8 @@ float bilinear_z_offset(const xy_pos_t &raw) {
#define FAR_EDGE_OR_BOX 1 // Just use the grid far edge
#endif
if (prev.x != rel.x) {
prev.x = rel.x;
if (cached_rel.x != rel.x) {
cached_rel.x = rel.x;
ratio.x = rel.x * ABL_BG_FACTOR(x);
const float gx = constrain(FLOOR(ratio.x), 0, ABL_BG_POINTS_X - (FAR_EDGE_OR_BOX));
ratio.x -= gx; // Subtract whole to get the ratio within the grid box
@@ -298,10 +316,10 @@ float bilinear_z_offset(const xy_pos_t &raw) {
nextg.x = _MIN(thisg.x + 1, ABL_BG_POINTS_X - 1);
}
if (prev.y != rel.y || lastg.x != thisg.x) {
if (cached_rel.y != rel.y || cached_g.x != thisg.x) {
if (prev.y != rel.y) {
prev.y = rel.y;
if (cached_rel.y != rel.y) {
cached_rel.y = rel.y;
ratio.y = rel.y * ABL_BG_FACTOR(y);
const float gy = constrain(FLOOR(ratio.y), 0, ABL_BG_POINTS_Y - (FAR_EDGE_OR_BOX));
ratio.y -= gy;
@@ -315,8 +333,8 @@ float bilinear_z_offset(const xy_pos_t &raw) {
nextg.y = _MIN(thisg.y + 1, ABL_BG_POINTS_Y - 1);
}
if (lastg != thisg) {
lastg = thisg;
if (cached_g != thisg) {
cached_g = thisg;
// Z at the box corners
z1 = ABL_BG_GRID(thisg.x, thisg.y); // left-front
d2 = ABL_BG_GRID(thisg.x, nextg.y) - z1; // left-back (delta)
@@ -336,8 +354,8 @@ float bilinear_z_offset(const xy_pos_t &raw) {
/*
static float last_offset = 0;
if (ABS(last_offset - offset) > 0.2) {
SERIAL_ECHOLNPGM("Sudden Shift at x=", rel.x, " / ", bilinear_grid_spacing.x, " -> thisg.x=", thisg.x);
SERIAL_ECHOLNPGM(" y=", rel.y, " / ", bilinear_grid_spacing.y, " -> thisg.y=", thisg.y);
SERIAL_ECHOLNPGM("Sudden Shift at x=", rel.x, " / ", grid_spacing.x, " -> thisg.x=", thisg.x);
SERIAL_ECHOLNPGM(" y=", rel.y, " / ", grid_spacing.y, " -> thisg.y=", thisg.y);
SERIAL_ECHOLNPGM(" ratio.x=", ratio.x, " ratio.y=", ratio.y);
SERIAL_ECHOLNPGM(" z1=", z1, " z2=", z2, " z3=", z3, " z4=", z4);
SERIAL_ECHOLNPGM(" L=", L, " R=", R, " offset=", offset);
@@ -350,13 +368,13 @@ float bilinear_z_offset(const xy_pos_t &raw) {
#if IS_CARTESIAN && DISABLED(SEGMENT_LEVELED_MOVES)
#define CELL_INDEX(A,V) ((V - bilinear_start.A) * ABL_BG_FACTOR(A))
#define CELL_INDEX(A,V) ((V - grid_start.A) * ABL_BG_FACTOR(A))
/**
* Prepare a bilinear-leveled linear move on Cartesian,
* splitting the move where it crosses grid borders.
*/
void bilinear_line_to_destination(const_feedRate_t scaled_fr_mm_s, uint16_t x_splits, uint16_t y_splits) {
void LevelingBilinear::line_to_destination(const_feedRate_t scaled_fr_mm_s, uint16_t x_splits, uint16_t y_splits) {
// Get current and destination cells for this line
xy_int_t c1 { CELL_INDEX(x, current_position.x), CELL_INDEX(y, current_position.y) },
c2 { CELL_INDEX(x, destination.x), CELL_INDEX(y, destination.y) };
@@ -384,7 +402,7 @@ float bilinear_z_offset(const xy_pos_t &raw) {
// Split on the X grid line
CBI(x_splits, gc.x);
end = destination;
destination.x = bilinear_start.x + ABL_BG_SPACING(x) * gc.x;
destination.x = grid_start.x + ABL_BG_SPACING(x) * gc.x;
normalized_dist = (destination.x - current_position.x) / (end.x - current_position.x);
destination.y = LINE_SEGMENT_END(y);
}
@@ -393,7 +411,7 @@ float bilinear_z_offset(const xy_pos_t &raw) {
// Split on the Y grid line
CBI(y_splits, gc.y);
end = destination;
destination.y = bilinear_start.y + ABL_BG_SPACING(y) * gc.y;
destination.y = grid_start.y + ABL_BG_SPACING(y) * gc.y;
normalized_dist = (destination.y - current_position.y) / (end.y - current_position.y);
destination.x = LINE_SEGMENT_END(x);
}
@@ -409,11 +427,11 @@ float bilinear_z_offset(const xy_pos_t &raw) {
destination.e = LINE_SEGMENT_END(e);
// Do the split and look for more borders
bilinear_line_to_destination(scaled_fr_mm_s, x_splits, y_splits);
line_to_destination(scaled_fr_mm_s, x_splits, y_splits);
// Restore destination from stack
destination = end;
bilinear_line_to_destination(scaled_fr_mm_s, x_splits, y_splits);
line_to_destination(scaled_fr_mm_s, x_splits, y_splits);
}
#endif // IS_CARTESIAN && !SEGMENT_LEVELED_MOVES
+72
View File
@@ -0,0 +1,72 @@
/**
* Marlin 3D Printer Firmware
* Copyright (c) 2020 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
*
* Based on Sprinter and grbl.
* Copyright (c) 2011 Camiel Gubbels / Erik van der Zalm
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*
*/
#pragma once
#include "../../../inc/MarlinConfigPre.h"
class LevelingBilinear {
static xy_pos_t grid_spacing, grid_start;
static xy_float_t grid_factor;
static bed_mesh_t z_values;
static xy_pos_t cached_rel;
static xy_int8_t cached_g;
static void extrapolate_one_point(const uint8_t x, const uint8_t y, const int8_t xdir, const int8_t ydir);
#if ENABLED(ABL_BILINEAR_SUBDIVISION)
#define ABL_GRID_POINTS_VIRT_X (GRID_MAX_CELLS_X * (BILINEAR_SUBDIVISIONS) + 1)
#define ABL_GRID_POINTS_VIRT_Y (GRID_MAX_CELLS_Y * (BILINEAR_SUBDIVISIONS) + 1)
static float z_values_virt[ABL_GRID_POINTS_VIRT_X][ABL_GRID_POINTS_VIRT_Y];
static xy_pos_t grid_spacing_virt;
static xy_float_t grid_factor_virt;
static float bed_level_virt_coord(const uint8_t x, const uint8_t y);
static float bed_level_virt_cmr(const float p[4], const uint8_t i, const float t);
static float bed_level_virt_2cmr(const uint8_t x, const uint8_t y, const_float_t tx, const_float_t ty);
static void bed_level_virt_interpolate();
#endif
public:
static void reset();
static void set_grid(const xy_pos_t& _grid_spacing, const xy_pos_t& _grid_start);
static void extrapolate_unprobed_bed_level();
static void print_leveling_grid(const bed_mesh_t* _z_values = NULL);
static void refresh_bed_level();
static bool has_mesh() { return !!grid_spacing.x; }
static bed_mesh_t& get_z_values() { return z_values; }
static const xy_pos_t& get_grid_spacing() { return grid_spacing; }
static const xy_pos_t& get_grid_start() { return grid_start; }
static float get_mesh_x(int16_t i) { return grid_start.x + i * grid_spacing.x; }
static float get_mesh_y(int16_t j) { return grid_start.y + j * grid_spacing.y; }
static float get_z_correction(const xy_pos_t &raw);
#if IS_CARTESIAN && DISABLED(SEGMENT_LEVELED_MOVES)
static void line_to_destination(const_feedRate_t scaled_fr_mm_s, uint16_t x_splits=0xFFFF, uint16_t y_splits=0xFFFF);
#endif
};
extern LevelingBilinear bbl;
#define _GET_MESH_X(I) bbl.get_mesh_x(I)
#define _GET_MESH_Y(J) bbl.get_mesh_y(J)
#define Z_VALUES_ARR bbl.get_z_values()
+4 -15
View File
@@ -48,7 +48,7 @@
bool leveling_is_valid() {
return TERN1(MESH_BED_LEVELING, mbl.has_mesh())
&& TERN1(AUTO_BED_LEVELING_BILINEAR, !!bilinear_grid_spacing.x)
&& TERN1(AUTO_BED_LEVELING_BILINEAR, bbl.has_mesh())
&& TERN1(AUTO_BED_LEVELING_UBL, ubl.mesh_is_valid());
}
@@ -67,12 +67,6 @@ void set_bed_leveling_enabled(const bool enable/*=true*/) {
planner.synchronize();
#if ENABLED(AUTO_BED_LEVELING_BILINEAR)
// Force bilinear_z_offset to re-calculate next time
const xyz_pos_t reset { -9999.999, -9999.999, 0 };
(void)bilinear_z_offset(reset);
#endif
if (planner.leveling_active) { // leveling from on to off
if (DEBUGGING(LEVELING)) DEBUG_POS("Leveling ON", current_position);
// change unleveled current_position to physical current_position without moving steppers.
@@ -129,12 +123,7 @@ void reset_bed_level() {
#if ENABLED(MESH_BED_LEVELING)
mbl.reset();
#elif ENABLED(AUTO_BED_LEVELING_BILINEAR)
bilinear_start.reset();
bilinear_grid_spacing.reset();
GRID_LOOP(x, y) {
z_values[x][y] = NAN;
TERN_(EXTENSIBLE_UI, ExtUI::onMeshUpdate(x, y, 0));
}
bbl.reset();
#elif ABL_PLANAR
planner.bed_level_matrix.set_to_identity();
#endif
@@ -156,7 +145,7 @@ void reset_bed_level() {
/**
* Print calibration results for plotting or manual frame adjustment.
*/
void print_2d_array(const uint8_t sx, const uint8_t sy, const uint8_t precision, element_2d_fn fn) {
void print_2d_array(const uint8_t sx, const uint8_t sy, const uint8_t precision, const float *values) {
#ifndef SCAD_MESH_OUTPUT
LOOP_L_N(x, sx) {
serial_spaces(precision + (x < 10 ? 3 : 2));
@@ -176,7 +165,7 @@ void reset_bed_level() {
#endif
LOOP_L_N(x, sx) {
SERIAL_CHAR(' ');
const float offset = fn(x, y);
const float offset = values[x * sx + y];
if (!isnan(offset)) {
if (offset >= 0) SERIAL_CHAR('+');
SERIAL_ECHO_F(offset, int(precision));
+2 -2
View File
@@ -62,7 +62,7 @@ class TemporaryBedLevelingState {
typedef float bed_mesh_t[GRID_MAX_POINTS_X][GRID_MAX_POINTS_Y];
#if ENABLED(AUTO_BED_LEVELING_BILINEAR)
#include "abl/abl.h"
#include "abl/bbl.h"
#elif ENABLED(AUTO_BED_LEVELING_UBL)
#include "ubl/ubl.h"
#elif ENABLED(MESH_BED_LEVELING)
@@ -81,7 +81,7 @@ class TemporaryBedLevelingState {
/**
* Print calibration results for plotting or manual frame adjustment.
*/
void print_2d_array(const uint8_t sx, const uint8_t sy, const uint8_t precision, element_2d_fn fn);
void print_2d_array(const uint8_t sx, const uint8_t sy, const uint8_t precision, const float *values);
#endif
@@ -125,9 +125,7 @@
void mesh_bed_leveling::report_mesh() {
SERIAL_ECHOPAIR_F(STRINGIFY(GRID_MAX_POINTS_X) "x" STRINGIFY(GRID_MAX_POINTS_Y) " mesh. Z offset: ", z_offset, 5);
SERIAL_ECHOLNPGM("\nMeasured points:");
print_2d_array(GRID_MAX_POINTS_X, GRID_MAX_POINTS_Y, 5,
[](const uint8_t ix, const uint8_t iy) { return z_values[ix][iy]; }
);
print_2d_array(GRID_MAX_POINTS_X, GRID_MAX_POINTS_Y, 5, z_values[0]);
}
#endif // MESH_BED_LEVELING
@@ -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.
+2 -2
View File
@@ -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);
}
+1 -1
View File
@@ -67,7 +67,7 @@ public:
}
// Convert raw measurement to mm
static float raw_to_mm(const uint16_t v) { return v * 5.0f * RECIPROCAL(float(MAX_RAW_THERMISTOR_VALUE)); }
static float raw_to_mm(const uint16_t v) { return v * float(ADC_VREF) * RECIPROCAL(float(MAX_RAW_THERMISTOR_VALUE)); }
static float raw_to_mm() { return raw_to_mm(raw); }
// A scaled reading is ready
+1 -1
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]);
}
+3 -3
View File
@@ -562,7 +562,7 @@ void PrintJobRecovery::resume() {
TERN_(HAS_HOME_OFFSET, home_offset = info.home_offset);
TERN_(HAS_POSITION_SHIFT, position_shift = info.position_shift);
#if HAS_HOME_OFFSET || HAS_POSITION_SHIFT
LOOP_LINEAR_AXES(i) update_workspace_offset((AxisEnum)i);
LOOP_NUM_AXES(i) update_workspace_offset((AxisEnum)i);
#endif
// Relative axis modes
@@ -612,7 +612,7 @@ void PrintJobRecovery::resume() {
#if HAS_HOME_OFFSET
DEBUG_ECHOPGM("home_offset: ");
LOOP_LINEAR_AXES(i) {
LOOP_NUM_AXES(i) {
if (i) DEBUG_CHAR(',');
DEBUG_DECIMAL(info.home_offset[i]);
}
@@ -621,7 +621,7 @@ void PrintJobRecovery::resume() {
#if HAS_POSITION_SHIFT
DEBUG_ECHOPGM("position_shift: ");
LOOP_LINEAR_AXES(i) {
LOOP_NUM_AXES(i) {
if (i) DEBUG_CHAR(',');
DEBUG_DECIMAL(info.position_shift[i]);
}
+22 -16
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
+57
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
+1 -1
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;
+8 -6
View File
@@ -67,14 +67,17 @@ void GcodeSuite::M420() {
const float x_min = probe.min_x(), x_max = probe.max_x(),
y_min = probe.min_y(), y_max = probe.max_y();
#if ENABLED(AUTO_BED_LEVELING_BILINEAR)
bilinear_start.set(x_min, y_min);
bilinear_grid_spacing.set((x_max - x_min) / (GRID_MAX_CELLS_X),
(y_max - y_min) / (GRID_MAX_CELLS_Y));
xy_pos_t start, spacing;
start.set(x_min, y_min);
spacing.set((x_max - x_min) / (GRID_MAX_CELLS_X),
(y_max - y_min) / (GRID_MAX_CELLS_Y));
bbl.set_grid(spacing, start);
#endif
GRID_LOOP(x, y) {
Z_VALUES(x, y) = 0.001 * random(-200, 200);
TERN_(EXTENSIBLE_UI, ExtUI::onMeshUpdate(x, y, Z_VALUES(x, y)));
}
TERN_(AUTO_BED_LEVELING_BILINEAR, bbl.refresh_bed_level());
SERIAL_ECHOPGM("Simulated " STRINGIFY(GRID_MAX_POINTS_X) "x" STRINGIFY(GRID_MAX_POINTS_Y) " mesh ");
SERIAL_ECHOPGM(" (", x_min);
SERIAL_CHAR(','); SERIAL_ECHO(y_min);
@@ -178,7 +181,7 @@ void GcodeSuite::M420() {
Z_VALUES(x, y) -= zmean;
TERN_(EXTENSIBLE_UI, ExtUI::onMeshUpdate(x, y, Z_VALUES(x, y)));
}
TERN_(ABL_BILINEAR_SUBDIVISION, bed_level_virt_interpolate());
TERN_(AUTO_BED_LEVELING_BILINEAR, bbl.refresh_bed_level());
}
#endif
@@ -199,8 +202,7 @@ void GcodeSuite::M420() {
#else
if (leveling_is_valid()) {
#if ENABLED(AUTO_BED_LEVELING_BILINEAR)
print_bilinear_leveling_grid();
TERN_(ABL_BILINEAR_SUBDIVISION, print_bilinear_leveling_grid_virt());
bbl.print_leveling_grid();
#elif ENABLED(MESH_BED_LEVELING)
SERIAL_ECHOLNPGM("Mesh Bed Level data:");
mbl.report_mesh();
+55 -18
View File
@@ -124,6 +124,7 @@ public:
#if ENABLED(AUTO_BED_LEVELING_BILINEAR)
float Z_offset;
bed_mesh_t z_values;
#endif
#if ENABLED(AUTO_BED_LEVELING_LINEAR)
@@ -308,8 +309,8 @@ G29_TYPE GcodeSuite::G29() {
if (!isnan(rx) && !isnan(ry)) {
// Get nearest i / j from rx / ry
i = (rx - bilinear_start.x + 0.5 * abl.gridSpacing.x) / abl.gridSpacing.x;
j = (ry - bilinear_start.y + 0.5 * abl.gridSpacing.y) / abl.gridSpacing.y;
i = (rx - bbl.get_grid_start().x) / bbl.get_grid_spacing().x + 0.5f;
j = (ry - bbl.get_grid_start().y) / bbl.get_grid_spacing().y + 0.5f;
LIMIT(i, 0, (GRID_MAX_POINTS_X) - 1);
LIMIT(j, 0, (GRID_MAX_POINTS_Y) - 1);
}
@@ -318,8 +319,8 @@ G29_TYPE GcodeSuite::G29() {
if (WITHIN(i, 0, (GRID_MAX_POINTS_X) - 1) && WITHIN(j, 0, (GRID_MAX_POINTS_Y) - 1)) {
set_bed_leveling_enabled(false);
z_values[i][j] = rz;
TERN_(ABL_BILINEAR_SUBDIVISION, bed_level_virt_interpolate());
Z_VALUES_ARR[i][j] = rz;
bbl.refresh_bed_level();
TERN_(EXTENSIBLE_UI, ExtUI::onMeshUpdate(i, j, rz));
set_bed_leveling_enabled(abl.reenable);
if (abl.reenable) report_current_position();
@@ -436,6 +437,42 @@ G29_TYPE GcodeSuite::G29() {
#endif
}
// Position bed horizontally and Z probe vertically.
#if defined(SAFE_BED_LEVELING_START_X) || defined(SAFE_BED_LEVELING_START_Y) || defined(SAFE_BED_LEVELING_START_Z) \
|| defined(SAFE_BED_LEVELING_START_I) || defined(SAFE_BED_LEVELING_START_J) || defined(SAFE_BED_LEVELING_START_K) \
|| defined(SAFE_BED_LEVELING_START_U) || defined(SAFE_BED_LEVELING_START_V) || defined(SAFE_BED_LEVELING_START_W)
xyze_pos_t safe_position = current_position;
#ifdef SAFE_BED_LEVELING_START_X
safe_position.x = SAFE_BED_LEVELING_START_X;
#endif
#ifdef SAFE_BED_LEVELING_START_Y
safe_position.y = SAFE_BED_LEVELING_START_Y;
#endif
#ifdef SAFE_BED_LEVELING_START_Z
safe_position.z = SAFE_BED_LEVELING_START_Z;
#endif
#ifdef SAFE_BED_LEVELING_START_I
safe_position.i = SAFE_BED_LEVELING_START_I;
#endif
#ifdef SAFE_BED_LEVELING_START_J
safe_position.j = SAFE_BED_LEVELING_START_J;
#endif
#ifdef SAFE_BED_LEVELING_START_K
safe_position.k = SAFE_BED_LEVELING_START_K;
#endif
#ifdef SAFE_BED_LEVELING_START_U
safe_position.u = SAFE_BED_LEVELING_START_U;
#endif
#ifdef SAFE_BED_LEVELING_START_V
safe_position.v = SAFE_BED_LEVELING_START_V;
#endif
#ifdef SAFE_BED_LEVELING_START_W
safe_position.w = SAFE_BED_LEVELING_START_W;
#endif
do_blocking_move_to(safe_position);
#endif
// Disable auto bed leveling during G29.
// Be formal so G29 can be done successively without G28.
if (!no_action) set_bed_leveling_enabled(false);
@@ -451,16 +488,12 @@ G29_TYPE GcodeSuite::G29() {
#endif
#if ENABLED(AUTO_BED_LEVELING_BILINEAR)
if (TERN1(PROBE_MANUALLY, !no_action)
&& (abl.gridSpacing != bilinear_grid_spacing || abl.probe_position_lf != bilinear_start)
if (!abl.dryrun
&& (abl.gridSpacing != bbl.get_grid_spacing() || abl.probe_position_lf != bbl.get_grid_start())
) {
// Reset grid to 0.0 or "not probed". (Also disables ABL)
reset_bed_level();
// Initialize a grid with the given dimensions
bilinear_grid_spacing = abl.gridSpacing;
bilinear_start = abl.probe_position_lf;
// Can't re-enable (on error) until the new grid is written
abl.reenable = false;
}
@@ -531,7 +564,7 @@ G29_TYPE GcodeSuite::G29() {
#elif ENABLED(AUTO_BED_LEVELING_BILINEAR)
const float newz = abl.measured_z + abl.Z_offset;
z_values[abl.meshCount.x][abl.meshCount.y] = newz;
abl.z_values[abl.meshCount.x][abl.meshCount.y] = newz;
TERN_(EXTENSIBLE_UI, ExtUI::onMeshUpdate(abl.meshCount, newz));
if (DEBUGGING(LEVELING)) DEBUG_ECHOLNPGM_P(PSTR("Save X"), abl.meshCount.x, SP_Y_STR, abl.meshCount.y, SP_Z_STR, abl.measured_z + abl.Z_offset);
@@ -682,7 +715,7 @@ G29_TYPE GcodeSuite::G29() {
#elif ENABLED(AUTO_BED_LEVELING_BILINEAR)
const float z = abl.measured_z + abl.Z_offset;
z_values[abl.meshCount.x][abl.meshCount.y] = z;
abl.z_values[abl.meshCount.x][abl.meshCount.y] = z;
TERN_(EXTENSIBLE_UI, ExtUI::onMeshUpdate(abl.meshCount, z));
#endif
@@ -753,12 +786,16 @@ G29_TYPE GcodeSuite::G29() {
if (!isnan(abl.measured_z)) {
#if ENABLED(AUTO_BED_LEVELING_BILINEAR)
if (!abl.dryrun) extrapolate_unprobed_bed_level();
print_bilinear_leveling_grid();
if (abl.dryrun)
bbl.print_leveling_grid(&abl.z_values);
else {
bbl.set_grid(abl.gridSpacing, abl.probe_position_lf);
COPY(Z_VALUES_ARR, abl.z_values);
TERN_(IS_KINEMATIC, bbl.extrapolate_unprobed_bed_level());
bbl.refresh_bed_level();
refresh_bed_level();
TERN_(ABL_BILINEAR_SUBDIVISION, print_bilinear_leveling_grid_virt());
bbl.print_leveling_grid();
}
#elif ENABLED(AUTO_BED_LEVELING_LINEAR)
@@ -878,7 +915,7 @@ G29_TYPE GcodeSuite::G29() {
// Unapply the offset because it is going to be immediately applied
// and cause compensation movement in Z
const float fade_scaling_factor = TERN(ENABLE_LEVELING_FADE_HEIGHT, planner.fade_scaling_factor_for_z(current_position.z), 1);
current_position.z -= fade_scaling_factor * bilinear_z_offset(current_position);
current_position.z -= fade_scaling_factor * bbl.get_z_correction(current_position);
if (DEBUGGING(LEVELING)) DEBUG_ECHOLNPGM(" corrected Z:", current_position.z);
}
+3 -3
View File
@@ -58,11 +58,11 @@ void GcodeSuite::M421() {
sy = iy >= 0 ? iy : 0, ey = iy >= 0 ? iy : GRID_MAX_POINTS_Y - 1;
LOOP_S_LE_N(x, sx, ex) {
LOOP_S_LE_N(y, sy, ey) {
z_values[x][y] = zval + (hasQ ? z_values[x][y] : 0);
TERN_(EXTENSIBLE_UI, ExtUI::onMeshUpdate(x, y, z_values[x][y]));
Z_VALUES_ARR[x][y] = zval + (hasQ ? Z_VALUES_ARR[x][y] : 0);
TERN_(EXTENSIBLE_UI, ExtUI::onMeshUpdate(x, y, Z_VALUES_ARR[x][y]));
}
}
TERN_(ABL_BILINEAR_SUBDIVISION, bed_level_virt_interpolate());
bbl.refresh_bed_level();
}
else
SERIAL_ERROR_MSG(STR_ERR_MESH_XY);
+37
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;
+82 -48
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
#endif
#if ENABLED(IMPROVE_HOMING_RELIABILITY)
@@ -364,23 +364,28 @@ void GcodeSuite::G28() {
#define _UNSAFE(A) (homeZ && TERN0(Z_SAFE_HOMING, axes_should_home(_BV(A##_AXIS))))
const bool homeZ = TERN0(HAS_Z_AXIS, parser.seen_test('Z')),
LINEAR_AXIS_LIST( // Other axes should be homed before Z safe-homing
NUM_AXIS_LIST( // Other axes should be homed before Z safe-homing
needX = _UNSAFE(X), needY = _UNSAFE(Y), needZ = false, // UNUSED
needI = _UNSAFE(I), needJ = _UNSAFE(J), needK = _UNSAFE(K)
needI = _UNSAFE(I), needJ = _UNSAFE(J), needK = _UNSAFE(K),
needU = _UNSAFE(U), needV = _UNSAFE(V), needW = _UNSAFE(W)
),
LINEAR_AXIS_LIST( // Home each axis if needed or flagged
NUM_AXIS_LIST( // Home each axis if needed or flagged
homeX = needX || parser.seen_test('X'),
homeY = needY || parser.seen_test('Y'),
homeZZ = homeZ,
homeI = needI || parser.seen_test(AXIS4_NAME), homeJ = needJ || parser.seen_test(AXIS5_NAME), homeK = needK || parser.seen_test(AXIS6_NAME)
homeI = needI || parser.seen_test(AXIS4_NAME), homeJ = needJ || parser.seen_test(AXIS5_NAME),
homeK = needK || parser.seen_test(AXIS6_NAME), homeU = needU || parser.seen_test(AXIS7_NAME),
homeV = needV || parser.seen_test(AXIS8_NAME), homeW = needW || parser.seen_test(AXIS9_NAME),
),
home_all = LINEAR_AXIS_GANG( // Home-all if all or none are flagged
home_all = NUM_AXIS_GANG( // Home-all if all or none are flagged
homeX == homeX, && homeY == homeX, && homeZ == homeX,
&& homeI == homeX, && homeJ == homeX, && homeK == homeX
&& homeI == homeX, && homeJ == homeX, && homeK == homeX,
&& homeU == homeX, && homeV == homeX, && homeW == homeX
),
LINEAR_AXIS_LIST(
NUM_AXIS_LIST(
doX = home_all || homeX, doY = home_all || homeY, doZ = home_all || homeZ,
doI = home_all || homeI, doJ = home_all || homeJ, doK = home_all || homeK
doI = home_all || homeI, doJ = home_all || homeJ, doK = home_all || homeK,
doU = home_all || homeU, doV = home_all || homeV, doW = home_all || homeW
);
#if HAS_Z_AXIS
@@ -394,7 +399,7 @@ void GcodeSuite::G28() {
const bool seenR = parser.seenval('R');
const float z_homing_height = seenR ? parser.value_linear_units() : Z_HOMING_HEIGHT;
if (z_homing_height && (seenR || LINEAR_AXIS_GANG(doX, || doY, || TERN0(Z_SAFE_HOMING, doZ), || doI, || doJ, || doK))) {
if (z_homing_height && (seenR || NUM_AXIS_GANG(doX, || doY, || TERN0(Z_SAFE_HOMING, doZ), || doI, || doJ, || doK, || doU, || doV, || doW))) {
// Raise Z before homing any other axes and z is not already high enough (never lower z)
if (DEBUGGING(LEVELING)) DEBUG_ECHOLNPGM("Raise Z (before homing) by ", z_homing_height);
do_z_clearance(z_homing_height);
@@ -434,32 +439,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();
@@ -542,6 +567,15 @@ void GcodeSuite::G28() {
#if HAS_CURRENT_HOME(K)
stepperK.rms_current(tmc_save_current_K);
#endif
#if HAS_CURRENT_HOME(U)
stepperU.rms_current(tmc_save_current_U);
#endif
#if HAS_CURRENT_HOME(V)
stepperV.rms_current(tmc_save_current_V);
#endif
#if HAS_CURRENT_HOME(W)
stepperW.rms_current(tmc_save_current_W);
#endif
#endif // HAS_HOMING_CURRENT
ui.refresh();
@@ -562,7 +596,7 @@ void GcodeSuite::G28() {
// If not, this will need a PROGMEM directive and an accessor.
#define _EN_ITEM(N) , E_AXIS
static constexpr AxisEnum L64XX_axis_xref[MAX_L64XX] = {
LINEAR_AXIS_LIST(X_AXIS, Y_AXIS, Z_AXIS, I_AXIS, J_AXIS, K_AXIS),
NUM_AXIS_LIST(X_AXIS, Y_AXIS, Z_AXIS, I_AXIS, J_AXIS, K_AXIS, U_AXIS, V_AXIS, W_AXIS),
X_AXIS, Y_AXIS, Z_AXIS, Z_AXIS, Z_AXIS
REPEAT(E_STEPPERS, _EN_ITEM)
};
+5 -5
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;
@@ -536,7 +536,7 @@ void GcodeSuite::G33() {
case 1:
test_precision = 0.0f; // forced end
LOOP_LINEAR_AXES(axis) e_delta[axis] = +Z4(CEN);
LOOP_NUM_AXES(axis) e_delta[axis] = +Z4(CEN);
break;
case 2:
@@ -584,14 +584,14 @@ void GcodeSuite::G33() {
// Normalize angles to least-squares
if (_angle_results) {
float a_sum = 0.0f;
LOOP_LINEAR_AXES(axis) a_sum += delta_tower_angle_trim[axis];
LOOP_LINEAR_AXES(axis) delta_tower_angle_trim[axis] -= a_sum / 3.0f;
LOOP_NUM_AXES(axis) a_sum += delta_tower_angle_trim[axis];
LOOP_NUM_AXES(axis) delta_tower_angle_trim[axis] -= a_sum / 3.0f;
}
// adjust delta_height and endstops by the max amount
const float z_temp = _MAX(delta_endstop_adj.a, delta_endstop_adj.b, delta_endstop_adj.c);
delta_height -= z_temp;
LOOP_LINEAR_AXES(axis) delta_endstop_adj[axis] -= z_temp;
LOOP_NUM_AXES(axis) delta_endstop_adj[axis] -= z_temp;
}
recalc_delta_settings();
NOMORE(zero_std_dev_min, zero_std_dev);
+130 -6
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_ECHOLNPAIR(" " STR_U_MIN ": ", m.obj_side[UMINIMUM]);
#endif
#if ENABLED(CALIBRATION_MEASURE_UMAX)
SERIAL_ECHOLNPAIR(" " STR_U_MAX ": ", m.obj_side[UMAXIMUM]);
#endif
#endif
#if HAS_V_AXIS
#if ENABLED(CALIBRATION_MEASURE_VMIN)
SERIAL_ECHOLNPAIR(" " STR_V_MIN ": ", m.obj_side[VMINIMUM]);
#endif
#if ENABLED(CALIBRATION_MEASURE_VMAX)
SERIAL_ECHOLNPAIR(" " STR_V_MAX ": ", m.obj_side[VMAXIMUM]);
#endif
#endif
#if HAS_W_AXIS
#if ENABLED(CALIBRATION_MEASURE_WMIN)
SERIAL_ECHOLNPAIR(" " STR_W_MIN ": ", m.obj_side[WMINIMUM]);
#endif
#if ENABLED(CALIBRATION_MEASURE_WMAX)
SERIAL_ECHOLNPAIR(" " STR_W_MAX ": ", m.obj_side[WMAXIMUM]);
#endif
#endif
SERIAL_EOL();
}
@@ -427,6 +481,15 @@ inline void probe_sides(measurements_t &m, const float uncertainty) {
#if HAS_K_CENTER
SERIAL_ECHOLNPGM_P(SP_K_STR, m.obj_center.k);
#endif
#if HAS_U_CENTER
SERIAL_ECHOLNPGM_P(SP_U_STR, m.obj_center.u);
#endif
#if HAS_V_CENTER
SERIAL_ECHOLNPGM_P(SP_V_STR, m.obj_center.v);
#endif
#if HAS_W_CENTER
SERIAL_ECHOLNPGM_P(SP_W_STR, m.obj_center.w);
#endif
SERIAL_EOL();
}
@@ -475,6 +538,30 @@ inline void probe_sides(measurements_t &m, const float uncertainty) {
SERIAL_ECHOLNPGM(" " STR_K_MAX ": ", m.backlash[KMAXIMUM]);
#endif
#endif
#if HAS_U_AXIS && AXIS_CAN_CALIBRATE(U)
#if ENABLED(CALIBRATION_MEASURE_UMIN)
SERIAL_ECHOLNPGM(" " STR_U_MIN ": ", m.backlash[UMINIMUM]);
#endif
#if ENABLED(CALIBRATION_MEASURE_UMAX)
SERIAL_ECHOLNPGM(" " STR_U_MAX ": ", m.backlash[UMAXIMUM]);
#endif
#endif
#if HAS_V_AXIS && AXIS_CAN_CALIBRATE(V)
#if ENABLED(CALIBRATION_MEASURE_VMIN)
SERIAL_ECHOLNPGM(" " STR_V_MIN ": ", m.backlash[VMINIMUM]);
#endif
#if ENABLED(CALIBRATION_MEASURE_VMAX)
SERIAL_ECHOLNPGM(" " STR_V_MAX ": ", m.backlash[VMAXIMUM]);
#endif
#endif
#if HAS_W_AXIS && AXIS_CAN_CALIBRATE(W)
#if ENABLED(CALIBRATION_MEASURE_WMIN)
SERIAL_ECHOLNPGM(" " STR_W_MIN ": ", m.backlash[WMINIMUM]);
#endif
#if ENABLED(CALIBRATION_MEASURE_WMAX)
SERIAL_ECHOLNPGM(" " STR_W_MAX ": ", m.backlash[WMAXIMUM]);
#endif
#endif
SERIAL_EOL();
}
@@ -498,7 +585,16 @@ inline void probe_sides(measurements_t &m, const float uncertainty) {
SERIAL_ECHOLNPGM_P(SP_J_STR, m.pos_error.j);
#endif
#if HAS_K_CENTER && AXIS_CAN_CALIBRATE(K)
SERIAL_ECHOLNPGM_P(SP_Z_STR, m.pos_error.z);
SERIAL_ECHOLNPGM_P(SP_K_STR, m.pos_error.k);
#endif
#if HAS_U_CENTER && AXIS_CAN_CALIBRATE(U)
SERIAL_ECHOLNPGM_P(SP_U_STR, m.pos_error.u);
#endif
#if HAS_V_CENTER && AXIS_CAN_CALIBRATE(V)
SERIAL_ECHOLNPGM_P(SP_V_STR, m.pos_error.v);
#endif
#if HAS_W_CENTER && AXIS_CAN_CALIBRATE(W)
SERIAL_ECHOLNPGM_P(SP_W_STR, m.pos_error.w);
#endif
SERIAL_EOL();
}
@@ -587,6 +683,30 @@ inline void calibrate_backlash(measurements_t &m, const float uncertainty) {
backlash.set_distance_mm(K_AXIS, m.backlash[KMAXIMUM]);
#endif
#if HAS_U_CENTER
backlash.distance_mm.u = (m.backlash[UMINIMUM] + m.backlash[UMAXIMUM]) / 2;
#elif ENABLED(CALIBRATION_MEASURE_UMIN)
backlash.distance_mm.u = m.backlash[UMINIMUM];
#elif ENABLED(CALIBRATION_MEASURE_UMAX)
backlash.distance_mm.u = m.backlash[UMAXIMUM];
#endif
#if HAS_V_CENTER
backlash.distance_mm.v = (m.backlash[VMINIMUM] + m.backlash[VMAXIMUM]) / 2;
#elif ENABLED(CALIBRATION_MEASURE_VMIN)
backlash.distance_mm.v = m.backlash[VMINIMUM];
#elif ENABLED(CALIBRATION_MEASURE_UMAX)
backlash.distance_mm.v = m.backlash[VMAXIMUM];
#endif
#if HAS_W_CENTER
backlash.distance_mm.w = (m.backlash[WMINIMUM] + m.backlash[WMAXIMUM]) / 2;
#elif ENABLED(CALIBRATION_MEASURE_WMIN)
backlash.distance_mm.w = m.backlash[WMINIMUM];
#elif ENABLED(CALIBRATION_MEASURE_WMAX)
backlash.distance_mm.w = m.backlash[WMAXIMUM];
#endif
#endif // BACKLASH_GCODE
}
@@ -597,9 +717,10 @@ inline void calibrate_backlash(measurements_t &m, const float uncertainty) {
// New scope for TEMPORARY_BACKLASH_CORRECTION
TEMPORARY_BACKLASH_CORRECTION(backlash.all_on);
TEMPORARY_BACKLASH_SMOOTHING(0.0f);
const xyz_float_t move = LINEAR_AXIS_ARRAY(
const xyz_float_t move = NUM_AXIS_ARRAY(
AXIS_CAN_CALIBRATE(X) * 3, AXIS_CAN_CALIBRATE(Y) * 3, AXIS_CAN_CALIBRATE(Z) * 3,
AXIS_CAN_CALIBRATE(I) * 3, AXIS_CAN_CALIBRATE(J) * 3, AXIS_CAN_CALIBRATE(K) * 3
AXIS_CAN_CALIBRATE(I) * 3, AXIS_CAN_CALIBRATE(J) * 3, AXIS_CAN_CALIBRATE(K) * 3,
AXIS_CAN_CALIBRATE(U) * 3, AXIS_CAN_CALIBRATE(V) * 3, AXIS_CAN_CALIBRATE(W) * 3
);
current_position += move; calibration_move();
current_position -= move; calibration_move();
@@ -650,6 +771,9 @@ inline void calibrate_toolhead(measurements_t &m, const float uncertainty, const
TERN_(HAS_I_CENTER, update_measurements(m, I_AXIS));
TERN_(HAS_J_CENTER, update_measurements(m, J_AXIS));
TERN_(HAS_K_CENTER, update_measurements(m, K_AXIS));
TERN_(HAS_U_CENTER, update_measurements(m, U_AXIS));
TERN_(HAS_V_CENTER, update_measurements(m, V_AXIS));
TERN_(HAS_W_CENTER, update_measurements(m, W_AXIS));
sync_plan_position();
}
+16 -10
View File
@@ -49,21 +49,24 @@ void GcodeSuite::M425() {
auto axis_can_calibrate = [](const uint8_t a) {
switch (a) {
default: return false;
LINEAR_AXIS_CODE(
NUM_AXIS_CODE(
case X_AXIS: return AXIS_CAN_CALIBRATE(X),
case Y_AXIS: return AXIS_CAN_CALIBRATE(Y),
case Z_AXIS: return AXIS_CAN_CALIBRATE(Z),
case I_AXIS: return AXIS_CAN_CALIBRATE(I),
case J_AXIS: return AXIS_CAN_CALIBRATE(J),
case K_AXIS: return AXIS_CAN_CALIBRATE(K)
case K_AXIS: return AXIS_CAN_CALIBRATE(K),
case U_AXIS: return AXIS_CAN_CALIBRATE(U),
case V_AXIS: return AXIS_CAN_CALIBRATE(V),
case W_AXIS: return AXIS_CAN_CALIBRATE(W)
);
}
};
LOOP_LINEAR_AXES(a) {
LOOP_NUM_AXES(a) {
if (axis_can_calibrate(a) && parser.seen(AXIS_CHAR(a))) {
planner.synchronize();
backlash.set_distance_mm(AxisEnum(a), parser.has_value() ? parser.value_linear_units() : backlash.get_measurement(AxisEnum(a)));
backlash.set_distance_mm(AxisEnum(a), parser.has_value() ? parser.value_axis_units(AxisEnum(a)) : backlash.get_measurement(AxisEnum(a)));
noArgs = false;
}
}
@@ -88,7 +91,7 @@ void GcodeSuite::M425() {
SERIAL_ECHOLNPGM("active:");
SERIAL_ECHOLNPGM(" Correction Amount/Fade-out: F", backlash.get_correction(), " (F1.0 = full, F0.0 = none)");
SERIAL_ECHOPGM(" Backlash Distance (mm): ");
LOOP_LINEAR_AXES(a) if (axis_can_calibrate(a)) {
LOOP_NUM_AXES(a) if (axis_can_calibrate(a)) {
SERIAL_CHAR(' ', AXIS_CHAR(a));
SERIAL_ECHO(backlash.get_distance_mm(AxisEnum(a)));
SERIAL_EOL();
@@ -101,7 +104,7 @@ void GcodeSuite::M425() {
#if ENABLED(MEASURE_BACKLASH_WHEN_PROBING)
SERIAL_ECHOPGM(" Average measured backlash (mm):");
if (backlash.has_any_measurement()) {
LOOP_LINEAR_AXES(a) if (axis_can_calibrate(a) && backlash.has_measurement(AxisEnum(a))) {
LOOP_NUM_AXES(a) if (axis_can_calibrate(a) && backlash.has_measurement(AxisEnum(a))) {
SERIAL_CHAR(' ', AXIS_CHAR(a));
SERIAL_ECHO(backlash.get_measurement(AxisEnum(a)));
}
@@ -120,13 +123,16 @@ void GcodeSuite::M425_report(const bool forReplay/*=true*/) {
#ifdef BACKLASH_SMOOTHING_MM
, PSTR(" S"), LINEAR_UNIT(backlash.get_smoothing_mm())
#endif
, LIST_N(DOUBLE(LINEAR_AXES),
, LIST_N(DOUBLE(NUM_AXES),
SP_X_STR, LINEAR_UNIT(backlash.get_distance_mm(X_AXIS)),
SP_Y_STR, LINEAR_UNIT(backlash.get_distance_mm(Y_AXIS)),
SP_Z_STR, LINEAR_UNIT(backlash.get_distance_mm(Z_AXIS)),
SP_I_STR, LINEAR_UNIT(backlash.get_distance_mm(I_AXIS)),
SP_J_STR, LINEAR_UNIT(backlash.get_distance_mm(J_AXIS)),
SP_K_STR, LINEAR_UNIT(backlash.get_distance_mm(K_AXIS))
SP_I_STR, I_AXIS_UNIT(backlash.get_distance_mm(I_AXIS)),
SP_J_STR, J_AXIS_UNIT(backlash.get_distance_mm(J_AXIS)),
SP_K_STR, K_AXIS_UNIT(backlash.get_distance_mm(K_AXIS)),
SP_U_STR, U_AXIS_UNIT(backlash.get_distance_mm(U_AXIS)),
SP_V_STR, V_AXIS_UNIT(backlash.get_distance_mm(V_AXIS)),
SP_W_STR, W_AXIS_UNIT(backlash.get_distance_mm(W_AXIS))
)
);
}
+1 -1
View File
@@ -44,7 +44,7 @@
void GcodeSuite::M666() {
DEBUG_SECTION(log_M666, "M666", DEBUGGING(LEVELING));
bool is_err = false, is_set = false;
LOOP_LINEAR_AXES(i) {
LOOP_NUM_AXES(i) {
if (parser.seen(AXIS_CHAR(i))) {
is_set = true;
const float v = parser.value_linear_units();
+28 -15
View File
@@ -135,13 +135,16 @@ void GcodeSuite::M201() {
void GcodeSuite::M201_report(const bool forReplay/*=true*/) {
report_heading_etc(forReplay, F(STR_MAX_ACCELERATION));
SERIAL_ECHOLNPGM_P(
LIST_N(DOUBLE(LINEAR_AXES),
LIST_N(DOUBLE(NUM_AXES),
PSTR(" M201 X"), LINEAR_UNIT(planner.settings.max_acceleration_mm_per_s2[X_AXIS]),
SP_Y_STR, LINEAR_UNIT(planner.settings.max_acceleration_mm_per_s2[Y_AXIS]),
SP_Z_STR, LINEAR_UNIT(planner.settings.max_acceleration_mm_per_s2[Z_AXIS]),
SP_I_STR, LINEAR_UNIT(planner.settings.max_acceleration_mm_per_s2[I_AXIS]),
SP_J_STR, LINEAR_UNIT(planner.settings.max_acceleration_mm_per_s2[J_AXIS]),
SP_K_STR, LINEAR_UNIT(planner.settings.max_acceleration_mm_per_s2[K_AXIS])
SP_I_STR, I_AXIS_UNIT(planner.settings.max_acceleration_mm_per_s2[I_AXIS]),
SP_J_STR, J_AXIS_UNIT(planner.settings.max_acceleration_mm_per_s2[J_AXIS]),
SP_K_STR, K_AXIS_UNIT(planner.settings.max_acceleration_mm_per_s2[K_AXIS]),
SP_U_STR, U_AXIS_UNIT(planner.settings.max_acceleration_mm_per_s2[U_AXIS]),
SP_V_STR, V_AXIS_UNIT(planner.settings.max_acceleration_mm_per_s2[V_AXIS]),
SP_W_STR, W_AXIS_UNIT(planner.settings.max_acceleration_mm_per_s2[W_AXIS]),
)
#if HAS_EXTRUDERS && DISABLED(DISTINCT_E_FACTORS)
, SP_E_STR, VOLUMETRIC_UNIT(planner.settings.max_acceleration_mm_per_s2[E_AXIS])
@@ -180,13 +183,16 @@ void GcodeSuite::M203() {
void GcodeSuite::M203_report(const bool forReplay/*=true*/) {
report_heading_etc(forReplay, F(STR_MAX_FEEDRATES));
SERIAL_ECHOLNPGM_P(
LIST_N(DOUBLE(LINEAR_AXES),
LIST_N(DOUBLE(NUM_AXES),
PSTR(" M203 X"), LINEAR_UNIT(planner.settings.max_feedrate_mm_s[X_AXIS]),
SP_Y_STR, LINEAR_UNIT(planner.settings.max_feedrate_mm_s[Y_AXIS]),
SP_Z_STR, LINEAR_UNIT(planner.settings.max_feedrate_mm_s[Z_AXIS]),
SP_I_STR, LINEAR_UNIT(planner.settings.max_feedrate_mm_s[I_AXIS]),
SP_J_STR, LINEAR_UNIT(planner.settings.max_feedrate_mm_s[J_AXIS]),
SP_K_STR, LINEAR_UNIT(planner.settings.max_feedrate_mm_s[K_AXIS])
SP_K_STR, LINEAR_UNIT(planner.settings.max_feedrate_mm_s[K_AXIS]),
SP_U_STR, LINEAR_UNIT(planner.settings.max_feedrate_mm_s[U_AXIS]),
SP_V_STR, LINEAR_UNIT(planner.settings.max_feedrate_mm_s[V_AXIS]),
SP_W_STR, LINEAR_UNIT(planner.settings.max_feedrate_mm_s[W_AXIS])
)
#if HAS_EXTRUDERS && DISABLED(DISTINCT_E_FACTORS)
, SP_E_STR, VOLUMETRIC_UNIT(planner.settings.max_feedrate_mm_s[E_AXIS])
@@ -273,9 +279,12 @@ void GcodeSuite::M205() {
if (parser.seenval('X')) planner.set_max_jerk(X_AXIS, parser.value_linear_units()),
if (parser.seenval('Y')) planner.set_max_jerk(Y_AXIS, parser.value_linear_units()),
if ((seenZ = parser.seenval('Z'))) planner.set_max_jerk(Z_AXIS, parser.value_linear_units()),
if (parser.seenval(AXIS4_NAME)) planner.set_max_jerk(I_AXIS, parser.value_linear_units()),
if (parser.seenval(AXIS5_NAME)) planner.set_max_jerk(J_AXIS, parser.value_linear_units()),
if (parser.seenval(AXIS6_NAME)) planner.set_max_jerk(K_AXIS, parser.value_linear_units())
if (parser.seenval(AXIS4_NAME)) planner.set_max_jerk(I_AXIS, parser.TERN(AXIS4_ROTATES, value_float, value_linear_units)()),
if (parser.seenval(AXIS5_NAME)) planner.set_max_jerk(J_AXIS, parser.TERN(AXIS5_ROTATES, value_float, value_linear_units)()),
if (parser.seenval(AXIS6_NAME)) planner.set_max_jerk(K_AXIS, parser.TERN(AXIS6_ROTATES, value_float, value_linear_units)()),
if (parser.seenval(AXIS7_NAME)) planner.set_max_jerk(U_AXIS, parser.TERN(AXIS7_ROTATES, value_float, value_linear_units)()),
if (parser.seenval(AXIS8_NAME)) planner.set_max_jerk(V_AXIS, parser.TERN(AXIS8_ROTATES, value_float, value_linear_units)()),
if (parser.seenval(AXIS9_NAME)) planner.set_max_jerk(W_AXIS, parser.TERN(AXIS9_ROTATES, value_float, value_linear_units)())
);
#if HAS_MESH && DISABLED(LIMITED_JERK_EDITING)
if (seenZ && planner.max_jerk.z <= 0.1f)
@@ -289,9 +298,10 @@ void GcodeSuite::M205_report(const bool forReplay/*=true*/) {
"Advanced (B<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>")
@@ -305,13 +315,16 @@ void GcodeSuite::M205_report(const bool forReplay/*=true*/) {
, PSTR(" J"), LINEAR_UNIT(planner.junction_deviation_mm)
#endif
#if HAS_CLASSIC_JERK
, LIST_N(DOUBLE(LINEAR_AXES),
, LIST_N(DOUBLE(NUM_AXES),
SP_X_STR, LINEAR_UNIT(planner.max_jerk.x),
SP_Y_STR, LINEAR_UNIT(planner.max_jerk.y),
SP_Z_STR, LINEAR_UNIT(planner.max_jerk.z),
SP_I_STR, LINEAR_UNIT(planner.max_jerk.i),
SP_J_STR, LINEAR_UNIT(planner.max_jerk.j),
SP_K_STR, LINEAR_UNIT(planner.max_jerk.k)
SP_I_STR, I_AXIS_UNIT(planner.max_jerk.i),
SP_J_STR, J_AXIS_UNIT(planner.max_jerk.j),
SP_K_STR, K_AXIS_UNIT(planner.max_jerk.k),
SP_U_STR, U_AXIS_UNIT(planner.max_jerk.u),
SP_V_STR, V_AXIS_UNIT(planner.max_jerk.v),
SP_W_STR, W_AXIS_UNIT(planner.max_jerk.w)
)
#if HAS_CLASSIC_E_JERK
, SP_E_STR, LINEAR_UNIT(planner.max_jerk.e)
+27 -16
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[linear] Fan Speed 0-255
* G[linear/s] Fan time
@@ -95,13 +98,22 @@ void GcodeSuite::M217() {
if (parser.seenval('Y')) { const int16_t v = parser.value_linear_units(); toolchange_settings.change_point.y = constrain(v, Y_MIN_POS, Y_MAX_POS); }
#endif
#if HAS_I_AXIS
if (parser.seenval('I')) { const int16_t v = parser.value_linear_units(); toolchange_settings.change_point.i = constrain(v, I_MIN_POS, I_MAX_POS); }
if (parser.seenval('I')) { const int16_t v = parser.TERN(AXIS4_ROTATES, value_int, value_linear_units)(); toolchange_settings.change_point.i = constrain(v, I_MIN_POS, I_MAX_POS); }
#endif
#if HAS_J_AXIS
if (parser.seenval('J')) { const int16_t v = parser.value_linear_units(); toolchange_settings.change_point.j = constrain(v, J_MIN_POS, J_MAX_POS); }
if (parser.seenval('J')) { const int16_t v = parser.TERN(AXIS5_ROTATES, value_int, value_linear_units)(); toolchange_settings.change_point.j = constrain(v, J_MIN_POS, J_MAX_POS); }
#endif
#if HAS_K_AXIS
if (parser.seenval('K')) { const int16_t v = parser.value_linear_units(); toolchange_settings.change_point.k = constrain(v, K_MIN_POS, K_MAX_POS); }
if (parser.seenval('K')) { const int16_t v = parser.TERN(AXIS6_ROTATES, value_int, value_linear_units)(); toolchange_settings.change_point.k = constrain(v, K_MIN_POS, K_MAX_POS); }
#endif
#if HAS_U_AXIS
if (parser.seenval('C')) { const int16_t v = parser.TERN(AXIS7_ROTATES, value_int, value_linear_units)(); toolchange_settings.change_point.u = constrain(v, U_MIN_POS, U_MAX_POS); }
#endif
#if HAS_V_AXIS
if (parser.seenval('H')) { const int16_t v = parser.TERN(AXIS8_ROTATES, value_int, value_linear_units)(); toolchange_settings.change_point.v = constrain(v, V_MIN_POS, V_MAX_POS); }
#endif
#if HAS_W_AXIS
if (parser.seenval('O')) { const int16_t v = parser.TERN(AXIS9_ROTATES, value_int, value_linear_units)(); toolchange_settings.change_point.w = constrain(v, W_MIN_POS, W_MAX_POS); }
#endif
#endif
@@ -167,24 +179,23 @@ void GcodeSuite::M217_report(const bool forReplay/*=true*/) {
#endif
#if ENABLED(TOOLCHANGE_PARK)
{
SERIAL_ECHOPGM(" W", LINEAR_UNIT(toolchange_settings.enable_park));
SERIAL_ECHOPGM_P(
SP_X_STR, LINEAR_UNIT(toolchange_settings.change_point.x)
#if HAS_Y_AXIS
, SP_Y_STR, LINEAR_UNIT(toolchange_settings.change_point.y)
#endif
#if HAS_I_AXIS
, SP_I_STR, LINEAR_UNIT(toolchange_settings.change_point.i)
#endif
#if HAS_J_AXIS
, SP_J_STR, LINEAR_UNIT(toolchange_settings.change_point.j)
#endif
#if HAS_K_AXIS
, SP_K_STR, LINEAR_UNIT(toolchange_settings.change_point.k)
#if SECONDARY_AXES >= 1
, LIST_N(DOUBLE(SECONDARY_AXES),
PSTR(" I"), I_AXIS_UNIT(toolchange_settings.change_point.i),
PSTR(" J"), J_AXIS_UNIT(toolchange_settings.change_point.j),
PSTR(" K"), K_AXIS_UNIT(toolchange_settings.change_point.k),
SP_C_STR, U_AXIS_UNIT(toolchange_settings.change_point.u),
PSTR(" H"), V_AXIS_UNIT(toolchange_settings.change_point.v),
PSTR(" O"), W_AXIS_UNIT(toolchange_settings.change_point.w),
)
#endif
);
}
#endif
#if ENABLED(TOOLCHANGE_FS_PRIME_FIRST_USED)
+9 -6
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.
@@ -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
+20 -11
View File
@@ -46,13 +46,16 @@ inline axis_flags_t selected_axis_bits() {
selected.bits = selected.e_bits();
}
#endif
selected.bits |= LINEAR_AXIS_GANG(
selected.bits |= NUM_AXIS_GANG(
(parser.seen_test('X') << X_AXIS),
| (parser.seen_test('Y') << Y_AXIS),
| (parser.seen_test('Z') << Z_AXIS),
| (parser.seen_test(AXIS4_NAME) << I_AXIS),
| (parser.seen_test(AXIS5_NAME) << J_AXIS),
| (parser.seen_test(AXIS6_NAME) << K_AXIS)
| (parser.seen_test(AXIS6_NAME) << K_AXIS),
| (parser.seen_test(AXIS7_NAME) << U_AXIS),
| (parser.seen_test(AXIS8_NAME) << V_AXIS),
| (parser.seen_test(AXIS9_NAME) << W_AXIS)
);
return selected;
}
@@ -69,7 +72,7 @@ void do_enable(const axis_flags_t to_enable) {
ena_mask_t also_enabled = 0; // Track steppers enabled due to overlap
// Enable all flagged axes
LOOP_LINEAR_AXES(a) {
LOOP_NUM_AXES(a) {
if (TEST(shall_enable, a)) {
stepper.enable_axis(AxisEnum(a)); // Mark and enable the requested axis
DEBUG_ECHOLNPGM("Enabled ", axis_codes[a], " (", a, ") with overlap ", hex_word(enable_overlap[a]), " ... Enabled: ", hex_word(stepper.axis_enabled.bits));
@@ -89,7 +92,7 @@ void do_enable(const axis_flags_t to_enable) {
if ((also_enabled &= ~(shall_enable | was_enabled))) {
SERIAL_CHAR('(');
LOOP_LINEAR_AXES(a) if (TEST(also_enabled, a)) SERIAL_CHAR(axis_codes[a], ' ');
LOOP_NUM_AXES(a) if (TEST(also_enabled, a)) SERIAL_CHAR(axis_codes[a], ' ');
#if HAS_EXTRUDERS
#define _EN_ALSO(N) if (TEST(also_enabled, INDEX_OF_AXIS(E_AXIS, N))) SERIAL_CHAR('E', '0' + N, ' ');
REPEAT(EXTRUDERS, _EN_ALSO)
@@ -125,13 +128,16 @@ void GcodeSuite::M17() {
stepper.enable_e_steppers();
}
#endif
LINEAR_AXIS_CODE(
NUM_AXIS_CODE(
if (parser.seen_test('X')) stepper.enable_axis(X_AXIS),
if (parser.seen_test('Y')) stepper.enable_axis(Y_AXIS),
if (parser.seen_test('Z')) stepper.enable_axis(Z_AXIS),
if (parser.seen_test(AXIS4_NAME)) stepper.enable_axis(I_AXIS),
if (parser.seen_test(AXIS5_NAME)) stepper.enable_axis(J_AXIS),
if (parser.seen_test(AXIS6_NAME)) stepper.enable_axis(K_AXIS)
if (parser.seen_test(AXIS6_NAME)) stepper.enable_axis(K_AXIS),
if (parser.seen_test(AXIS7_NAME)) stepper.enable_axis(U_AXIS),
if (parser.seen_test(AXIS8_NAME)) stepper.enable_axis(V_AXIS),
if (parser.seen_test(AXIS9_NAME)) stepper.enable_axis(W_AXIS)
);
}
}
@@ -149,7 +155,7 @@ void try_to_disable(const axis_flags_t to_disable) {
if (!still_enabled) return;
// Attempt to disable all flagged axes
LOOP_LINEAR_AXES(a)
LOOP_NUM_AXES(a)
if (TEST(to_disable.bits, a)) {
DEBUG_ECHOPGM("Try to disable ", axis_codes[a], " (", a, ") with overlap ", hex_word(enable_overlap[a]), " ... ");
if (stepper.disable_axis(AxisEnum(a))) { // Mark the requested axis and request to disable
@@ -178,7 +184,7 @@ void try_to_disable(const axis_flags_t to_disable) {
auto overlap_warning = [](const ena_mask_t axis_bits) {
SERIAL_ECHOPGM(" not disabled. Shared with");
LOOP_LINEAR_AXES(a) if (TEST(axis_bits, a)) SERIAL_CHAR(' ', axis_codes[a]);
LOOP_NUM_AXES(a) if (TEST(axis_bits, a)) SERIAL_CHAR(' ', axis_codes[a]);
#if HAS_EXTRUDERS
#define _EN_STILLON(N) if (TEST(axis_bits, INDEX_OF_AXIS(E_AXIS, N))) SERIAL_CHAR(' ', 'E', '0' + N);
REPEAT(EXTRUDERS, _EN_STILLON)
@@ -187,7 +193,7 @@ void try_to_disable(const axis_flags_t to_disable) {
};
// If any of the requested axes are still enabled, give a warning
LOOP_LINEAR_AXES(a) {
LOOP_NUM_AXES(a) {
if (TEST(still_enabled, a)) {
SERIAL_CHAR(axis_codes[a]);
overlap_warning(stepper.axis_enabled.bits & enable_overlap[a]);
@@ -229,13 +235,16 @@ void GcodeSuite::M18_M84() {
stepper.disable_e_steppers();
}
#endif
LINEAR_AXIS_CODE(
NUM_AXIS_CODE(
if (parser.seen_test('X')) stepper.disable_axis(X_AXIS),
if (parser.seen_test('Y')) stepper.disable_axis(Y_AXIS),
if (parser.seen_test('Z')) stepper.disable_axis(Z_AXIS),
if (parser.seen_test(AXIS4_NAME)) stepper.disable_axis(I_AXIS),
if (parser.seen_test(AXIS5_NAME)) stepper.disable_axis(J_AXIS),
if (parser.seen_test(AXIS6_NAME)) stepper.disable_axis(K_AXIS)
if (parser.seen_test(AXIS6_NAME)) stepper.disable_axis(K_AXIS),
if (parser.seen_test(AXIS7_NAME)) stepper.disable_axis(U_AXIS),
if (parser.seen_test(AXIS8_NAME)) stepper.disable_axis(V_AXIS),
if (parser.seen_test(AXIS9_NAME)) stepper.disable_axis(W_AXIS)
);
}
}
+1 -1
View File
@@ -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();
+16 -12
View File
@@ -39,7 +39,7 @@
#endif
/**
* M907: Set digital trimpot motor current using axis codes X [Y] [Z] [E]
* M907: Set digital trimpot motor current using axis codes X [Y] [Z] [I] [J] [K] [U] [V] [W] [E]
* B<current> - Special case for 4th (E) axis
* S<current> - Special case to set first 3 axes
*/
@@ -49,15 +49,15 @@ void GcodeSuite::M907() {
if (!parser.seen("BS" LOGICAL_AXES_STRING))
return M907_report();
LOOP_LOGICAL_AXES(i) if (parser.seenval(axis_codes[i])) stepper.set_digipot_current(i, parser.value_int());
LOOP_LOGICAL_AXES(i) if (parser.seenval(IAXIS_CHAR(i))) stepper.set_digipot_current(i, parser.value_int());
if (parser.seenval('B')) stepper.set_digipot_current(4, parser.value_int());
if (parser.seenval('S')) LOOP_LE_N(i, 4) stepper.set_digipot_current(i, parser.value_int());
#elif HAS_MOTOR_CURRENT_PWM
if (!parser.seen(
#if ANY_PIN(MOTOR_CURRENT_PWM_X, MOTOR_CURRENT_PWM_Y, MOTOR_CURRENT_PWM_XY)
"XY"
#if ANY_PIN(MOTOR_CURRENT_PWM_X, MOTOR_CURRENT_PWM_Y, MOTOR_CURRENT_PWM_XY, MOTOR_CURRENT_PWM_I, MOTOR_CURRENT_PWM_J, MOTOR_CURRENT_PWM_K, MOTOR_CURRENT_PWM_U, MOTOR_CURRENT_PWM_V, MOTOR_CURRENT_PWM_W)
"XY" SECONDARY_AXIS_GANG("I", "J", "K", "U", "V", "W")
#endif
#if PIN_EXISTS(MOTOR_CURRENT_PWM_Z)
"Z"
@@ -67,8 +67,12 @@ void GcodeSuite::M907() {
#endif
)) return M907_report();
#if ANY_PIN(MOTOR_CURRENT_PWM_X, MOTOR_CURRENT_PWM_Y, MOTOR_CURRENT_PWM_XY)
if (parser.seenval('X') || parser.seenval('Y')) stepper.set_digipot_current(0, parser.value_int());
#if ANY_PIN(MOTOR_CURRENT_PWM_X, MOTOR_CURRENT_PWM_Y, MOTOR_CURRENT_PWM_XY, MOTOR_CURRENT_PWM_I, MOTOR_CURRENT_PWM_J, MOTOR_CURRENT_PWM_K, MOTOR_CURRENT_PWM_U, MOTOR_CURRENT_PWM_V, MOTOR_CURRENT_PWM_W)
if (NUM_AXIS_GANG(
parser.seenval('X'), || parser.seenval('Y'), || false,
|| parser.seenval('I'), || parser.seenval('J'), || parser.seenval('K'),
|| parser.seenval('U'), || parser.seenval('V'), || parser.seenval('W')
)) stepper.set_digipot_current(0, parser.value_int());
#endif
#if PIN_EXISTS(MOTOR_CURRENT_PWM_Z)
if (parser.seenval('Z')) stepper.set_digipot_current(1, parser.value_int());
@@ -81,7 +85,7 @@ void GcodeSuite::M907() {
#if HAS_MOTOR_CURRENT_I2C
// this one uses actual amps in floating point
LOOP_LOGICAL_AXES(i) if (parser.seenval(axis_codes[i])) digipot_i2c.set_current(i, parser.value_float());
LOOP_LOGICAL_AXES(i) if (parser.seenval(IAXIS_CHAR(i))) digipot_i2c.set_current(i, parser.value_float());
// Additional extruders use B,C,D for channels 4,5,6.
// TODO: Change these parameters because 'E' is used. B<index>?
#if HAS_EXTRUDERS
@@ -95,7 +99,7 @@ void GcodeSuite::M907() {
const float dac_percent = parser.value_float();
LOOP_LE_N(i, 4) stepper_dac.set_current_percent(i, dac_percent);
}
LOOP_LOGICAL_AXES(i) if (parser.seenval(axis_codes[i])) stepper_dac.set_current_percent(i, parser.value_float());
LOOP_LOGICAL_AXES(i) if (parser.seenval(IAXIS_CHAR(i))) stepper_dac.set_current_percent(i, parser.value_float());
#endif
}
@@ -104,15 +108,15 @@ void GcodeSuite::M907() {
void GcodeSuite::M907_report(const bool forReplay/*=true*/) {
report_heading_etc(forReplay, F(STR_STEPPER_MOTOR_CURRENTS));
#if HAS_MOTOR_CURRENT_PWM
SERIAL_ECHOLNPGM_P( // PWM-based has 3 values:
PSTR(" M907 X"), stepper.motor_current_setting[0] // X and Y
SERIAL_ECHOLNPGM_P( // PWM-based has 3 values:
PSTR(" M907 X"), stepper.motor_current_setting[0] // X, Y, (I, J, K, U, V, W)
, SP_Z_STR, stepper.motor_current_setting[1] // Z
, SP_E_STR, stepper.motor_current_setting[2] // E
);
#elif HAS_MOTOR_CURRENT_SPI
SERIAL_ECHOPGM(" M907"); // SPI-based has 5 values:
LOOP_LOGICAL_AXES(q) { // X Y Z (I J K) E (map to X Y Z (I J K) E0 by default)
SERIAL_CHAR(' ', axis_codes[q]);
LOOP_LOGICAL_AXES(q) { // X Y Z (I J K U V W) E (map to X Y Z (I J K U V W) E0 by default)
SERIAL_CHAR(' ', IAXIS_CHAR(q));
SERIAL_ECHO(stepper.motor_current_setting[q]);
}
SERIAL_CHAR(' ', 'B'); // B (maps to E1 by default)
+6 -2
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_ECHOLNPAIR_F_P(
LIST_N(DOUBLE(LINEAR_AXES), PSTR(" : X"), pos.x, SP_Y_STR, pos.y, SP_Z_STR, pos.z, SP_I_STR, pos.i, SP_J_STR, pos.j, SP_K_STR, pos.k)
LIST_N(DOUBLE(NUM_AXES),
SP_Y_STR, pos.x, SP_Y_STR, pos.y, SP_Z_STR, pos.z,
SP_I_STR, pos.i, SP_J_STR, pos.j, SP_K_STR, pos.k,
SP_U_STR, pos.u, SP_V_STR, pos.v, SP_W_STR, pos.w
)
#if HAS_EXTRUDERS
, SP_E_STR, pos.e
#endif
+2 -2
View File
@@ -68,9 +68,9 @@ void GcodeSuite::G61() {
SYNC_E(stored_position[slot].e);
}
else {
if (parser.seen(LINEAR_AXIS_GANG("X", "Y", "Z", STR_I, STR_J, STR_K))) {
if (parser.seen(NUM_AXIS_GANG("X", "Y", "Z", STR_I, STR_J, STR_K, STR_U, STR_V, STR_W))) {
DEBUG_ECHOPGM(STR_RESTORING_POS " S", slot);
LOOP_LINEAR_AXES(i) {
LOOP_NUM_AXES(i) {
destination[i] = parser.seen(AXIS_CHAR(i))
? stored_position[slot][i] + parser.value_axis_units((AxisEnum)i)
: current_position[i];
+13 -5
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];
+18 -13
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
+25 -4
View File
@@ -85,6 +85,15 @@ static void set_stealth_status(const bool enable, const int8_t eindex) {
#if K_HAS_STEALTHCHOP
case K_AXIS: TMC_SET_STEALTH(K); break;
#endif
#if U_HAS_STEALTHCHOP
case U_AXIS: TMC_SET_STEALTH(U); break;
#endif
#if V_HAS_STEALTHCHOP
case V_AXIS: TMC_SET_STEALTH(V); break;
#endif
#if W_HAS_STEALTHCHOP
case W_AXIS: TMC_SET_STEALTH(W); break;
#endif
#if E_STEPPERS
case E_AXIS: {
@@ -115,6 +124,9 @@ static void say_stealth_status() {
OPTCODE( I_HAS_STEALTHCHOP, TMC_SAY_STEALTH_STATUS(I))
OPTCODE( J_HAS_STEALTHCHOP, TMC_SAY_STEALTH_STATUS(J))
OPTCODE( K_HAS_STEALTHCHOP, TMC_SAY_STEALTH_STATUS(K))
OPTCODE( U_HAS_STEALTHCHOP, TMC_SAY_STEALTH_STATUS(U))
OPTCODE( V_HAS_STEALTHCHOP, TMC_SAY_STEALTH_STATUS(V))
OPTCODE( W_HAS_STEALTHCHOP, TMC_SAY_STEALTH_STATUS(W))
OPTCODE(E0_HAS_STEALTHCHOP, TMC_SAY_STEALTH_STATUS(E0))
OPTCODE(E1_HAS_STEALTHCHOP, TMC_SAY_STEALTH_STATUS(E1))
OPTCODE(E2_HAS_STEALTHCHOP, TMC_SAY_STEALTH_STATUS(E2))
@@ -157,17 +169,23 @@ void GcodeSuite::M569_report(const bool forReplay/*=true*/) {
chop_z = TERN0(Z_HAS_STEALTHCHOP, stepperZ.get_stored_stealthChop()),
chop_i = TERN0(I_HAS_STEALTHCHOP, stepperI.get_stored_stealthChop()),
chop_j = TERN0(J_HAS_STEALTHCHOP, stepperJ.get_stored_stealthChop()),
chop_k = TERN0(K_HAS_STEALTHCHOP, stepperK.get_stored_stealthChop());
chop_k = TERN0(K_HAS_STEALTHCHOP, stepperK.get_stored_stealthChop()),
chop_u = TERN0(U_HAS_STEALTHCHOP, stepperU.get_stored_stealthChop()),
chop_v = TERN0(V_HAS_STEALTHCHOP, stepperV.get_stored_stealthChop()),
chop_w = TERN0(W_HAS_STEALTHCHOP, stepperW.get_stored_stealthChop());
if (chop_x || chop_y || chop_z || chop_i || chop_j || chop_k) {
if (chop_x || chop_y || chop_z || chop_i || chop_j || chop_k || chop_u || chop_v || chop_w) {
say_M569(forReplay);
LINEAR_AXIS_CODE(
NUM_AXIS_CODE(
if (chop_x) SERIAL_ECHOPGM_P(SP_X_STR),
if (chop_y) SERIAL_ECHOPGM_P(SP_Y_STR),
if (chop_z) SERIAL_ECHOPGM_P(SP_Z_STR),
if (chop_i) SERIAL_ECHOPGM_P(SP_I_STR),
if (chop_j) SERIAL_ECHOPGM_P(SP_J_STR),
if (chop_k) SERIAL_ECHOPGM_P(SP_K_STR)
if (chop_k) SERIAL_ECHOPGM_P(SP_K_STR),
if (chop_u) SERIAL_ECHOPGM_P(SP_U_STR),
if (chop_v) SERIAL_ECHOPGM_P(SP_V_STR),
if (chop_w) SERIAL_ECHOPGM_P(SP_W_STR)
);
SERIAL_EOL();
}
@@ -190,6 +208,9 @@ void GcodeSuite::M569_report(const bool forReplay/*=true*/) {
if (TERN0( I_HAS_STEALTHCHOP, stepperI.get_stored_stealthChop())) { say_M569(forReplay, FPSTR(SP_I_STR), true); }
if (TERN0( J_HAS_STEALTHCHOP, stepperJ.get_stored_stealthChop())) { say_M569(forReplay, FPSTR(SP_J_STR), true); }
if (TERN0( K_HAS_STEALTHCHOP, stepperK.get_stored_stealthChop())) { say_M569(forReplay, FPSTR(SP_K_STR), true); }
if (TERN0( U_HAS_STEALTHCHOP, stepperU.get_stored_stealthChop())) { say_M569(forReplay, FPSTR(SP_U_STR), true); }
if (TERN0( V_HAS_STEALTHCHOP, stepperV.get_stored_stealthChop())) { say_M569(forReplay, FPSTR(SP_V_STR), true); }
if (TERN0( W_HAS_STEALTHCHOP, stepperW.get_stored_stealthChop())) { say_M569(forReplay, FPSTR(SP_W_STR), true); }
if (TERN0(E0_HAS_STEALTHCHOP, stepperE0.get_stored_stealthChop())) { say_M569(forReplay, F("T0 E"), true); }
if (TERN0(E1_HAS_STEALTHCHOP, stepperE1.get_stored_stealthChop())) { say_M569(forReplay, F("T1 E"), true); }
+33 -1
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.)
@@ -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
@@ -53,12 +53,21 @@
#if HAS_K_AXIS && M91x_USE(K)
#define M91x_USE_K 1
#endif
#if HAS_U_AXIS && M91x_USE(U)
#define M91x_USE_U 1
#endif
#if HAS_V_AXIS && M91x_USE(V)
#define M91x_USE_V 1
#endif
#if HAS_W_AXIS && M91x_USE(W)
#define M91x_USE_W 1
#endif
#if M91x_USE_E(0) || M91x_USE_E(1) || M91x_USE_E(2) || M91x_USE_E(3) || M91x_USE_E(4) || M91x_USE_E(5) || M91x_USE_E(6) || M91x_USE_E(7)
#define M91x_SOME_E 1
#endif
#if !M91x_SOME_X && !M91x_SOME_Y && !M91x_SOME_Z && !M91x_USE_I && !M91x_USE_J && !M91x_USE_K && !M91x_SOME_E
#if !M91x_SOME_X && !M91x_SOME_Y && !M91x_SOME_Z && !M91x_USE_I && !M91x_USE_J && !M91x_USE_K && !M91x_USE_U && !M91x_USE_V && !M91x_USE_W && !M91x_SOME_E
#error "MONITOR_DRIVER_STATUS requires at least one TMC2130, 2160, 2208, 2209, 2660, 5130, or 5160."
#endif
@@ -109,6 +118,9 @@
TERN_(M91x_USE_I, tmc_report_otpw(stepperI));
TERN_(M91x_USE_J, tmc_report_otpw(stepperJ));
TERN_(M91x_USE_K, tmc_report_otpw(stepperK));
TERN_(M91x_USE_U, tmc_report_otpw(stepperU));
TERN_(M91x_USE_V, tmc_report_otpw(stepperV));
TERN_(M91x_USE_W, tmc_report_otpw(stepperW));
#if M91x_USE_E(0)
tmc_report_otpw(stepperE0);
#endif
@@ -137,7 +149,7 @@
/**
* M912: Clear TMC stepper driver overtemperature pre-warn flag held by the library
* Specify one or more axes with X, Y, Z, X1, Y1, Z1, X2, Y2, Z2, Z3, Z4 and E[index].
* Specify one or more axes with X, Y, Z, X1, Y1, Z1, X2, Y2, Z2, Z3, Z4, A, B, C, U, V, W, and E[index].
* If no axes are given, clear all.
*
* Examples:
@@ -154,9 +166,12 @@
hasI = TERN0(M91x_USE_I, parser.seen(axis_codes.i)),
hasJ = TERN0(M91x_USE_J, parser.seen(axis_codes.j)),
hasK = TERN0(M91x_USE_K, parser.seen(axis_codes.k)),
hasU = TERN0(M91x_USE_U, parser.seen(axis_codes.u)),
hasV = TERN0(M91x_USE_V, parser.seen(axis_codes.v)),
hasW = TERN0(M91x_USE_W, parser.seen(axis_codes.w)),
hasE = TERN0(M91x_SOME_E, parser.seen(axis_codes.e));
const bool hasNone = !hasE && !hasX && !hasY && !hasZ && !hasI && !hasJ && !hasK;
const bool hasNone = !hasE && !hasX && !hasY && !hasZ && !hasI && !hasJ && !hasK && !hasU && !hasV && !hasW;
#if M91x_SOME_X
const int8_t xval = int8_t(parser.byteval(axis_codes.x, 0xFF));
@@ -206,6 +221,18 @@
const int8_t kval = int8_t(parser.byteval(axis_codes.k, 0xFF));
if (hasNone || kval == 1 || (hasK && kval < 0)) tmc_clear_otpw(stepperK);
#endif
#if M91x_USE_U
const int8_t uval = int8_t(parser.byteval(axis_codes.u, 0xFF));
if (hasNone || uval == 1 || (hasU && uval < 0)) tmc_clear_otpw(stepperU);
#endif
#if M91x_USE_V
const int8_t vval = int8_t(parser.byteval(axis_codes.v, 0xFF));
if (hasNone || vval == 1 || (hasV && vval < 0)) tmc_clear_otpw(stepperV);
#endif
#if M91x_USE_W
const int8_t wval = int8_t(parser.byteval(axis_codes.w, 0xFF));
if (hasNone || wval == 1 || (hasW && wval < 0)) tmc_clear_otpw(stepperW);
#endif
#if M91x_SOME_E
const int8_t eval = int8_t(parser.byteval(axis_codes.e, 0xFF));
@@ -296,6 +323,15 @@
#if K_HAS_STEALTHCHOP
case K_AXIS: TMC_SET_PWMTHRS(K,K); break;
#endif
#if U_HAS_STEALTHCHOP
case U_AXIS: TMC_SET_PWMTHRS(U,U); break;
#endif
#if V_HAS_STEALTHCHOP
case V_AXIS: TMC_SET_PWMTHRS(V,V); break;
#endif
#if W_HAS_STEALTHCHOP
case W_AXIS: TMC_SET_PWMTHRS(W,W); break;
#endif
#if E0_HAS_STEALTHCHOP || E1_HAS_STEALTHCHOP || E2_HAS_STEALTHCHOP || E3_HAS_STEALTHCHOP || E4_HAS_STEALTHCHOP || E5_HAS_STEALTHCHOP || E6_HAS_STEALTHCHOP || E7_HAS_STEALTHCHOP
case E_AXIS: {
@@ -326,6 +362,9 @@
TERN_( I_HAS_STEALTHCHOP, TMC_SAY_PWMTHRS(I,I));
TERN_( J_HAS_STEALTHCHOP, TMC_SAY_PWMTHRS(J,J));
TERN_( K_HAS_STEALTHCHOP, TMC_SAY_PWMTHRS(K,K));
TERN_( U_HAS_STEALTHCHOP, TMC_SAY_PWMTHRS(U,U));
TERN_( V_HAS_STEALTHCHOP, TMC_SAY_PWMTHRS(V,V));
TERN_( W_HAS_STEALTHCHOP, TMC_SAY_PWMTHRS(W,W));
TERN_(E0_HAS_STEALTHCHOP, TMC_SAY_PWMTHRS_E(0));
TERN_(E1_HAS_STEALTHCHOP, TMC_SAY_PWMTHRS_E(1));
@@ -397,6 +436,18 @@
say_M913(forReplay);
SERIAL_ECHOLNPGM_P(SP_K_STR, stepperK.get_pwm_thrs());
#endif
#if U_HAS_STEALTHCHOP
say_M913(forReplay);
SERIAL_ECHOLNPGM_P(SP_U_STR, stepperU.get_pwm_thrs());
#endif
#if V_HAS_STEALTHCHOP
say_M913(forReplay);
SERIAL_ECHOLNPGM_P(SP_V_STR, stepperV.get_pwm_thrs());
#endif
#if W_HAS_STEALTHCHOP
say_M913(forReplay);
SERIAL_ECHOLNPGM_P(SP_W_STR, stepperW.get_pwm_thrs());
#endif
#if E0_HAS_STEALTHCHOP
say_M913(forReplay);
@@ -451,7 +502,7 @@
bool report = true;
const uint8_t index = parser.byteval('I');
LOOP_LINEAR_AXES(i) if (parser.seen(AXIS_CHAR(i))) {
LOOP_NUM_AXES(i) if (parser.seen(AXIS_CHAR(i))) {
const int16_t value = parser.value_int();
report = false;
switch (i) {
@@ -484,6 +535,15 @@
#if K_SENSORLESS
case K_AXIS: stepperK.homing_threshold(value); break;
#endif
#if U_SENSORLESS && AXIS_HAS_STALLGUARD(U)
case U_AXIS: stepperU.homing_threshold(value); break;
#endif
#if V_SENSORLESS && AXIS_HAS_STALLGUARD(V)
case V_AXIS: stepperV.homing_threshold(value); break;
#endif
#if W_SENSORLESS && AXIS_HAS_STALLGUARD(W)
case W_AXIS: stepperW.homing_threshold(value); break;
#endif
}
}
@@ -499,6 +559,9 @@
TERN_(I_SENSORLESS, tmc_print_sgt(stepperI));
TERN_(J_SENSORLESS, tmc_print_sgt(stepperJ));
TERN_(K_SENSORLESS, tmc_print_sgt(stepperK));
TERN_(U_SENSORLESS, tmc_print_sgt(stepperU));
TERN_(V_SENSORLESS, tmc_print_sgt(stepperV));
TERN_(W_SENSORLESS, tmc_print_sgt(stepperW));
}
}
@@ -561,6 +624,18 @@
say_M914(forReplay);
SERIAL_ECHOLNPGM_P(SP_K_STR, stepperK.homing_threshold());
#endif
#if U_SENSORLESS
say_M914(forReplay);
SERIAL_ECHOLNPGM_P(SP_U_STR, stepperU.homing_threshold());
#endif
#if V_SENSORLESS
say_M914(forReplay);
SERIAL_ECHOLNPGM_P(SP_V_STR, stepperV.homing_threshold());
#endif
#if W_SENSORLESS
say_M914(forReplay);
SERIAL_ECHOLNPGM_P(SP_W_STR, stepperW.homing_threshold());
#endif
}
#endif // USE_SENSORLESS
+9 -2
View File
@@ -85,7 +85,10 @@ axis_bits_t GcodeSuite::axis_relative = 0 LOGICAL_AXIS_GANG(
| (ar_init.z << REL_Z),
| (ar_init.i << REL_I),
| (ar_init.j << REL_J),
| (ar_init.k << REL_K)
| (ar_init.k << REL_K),
| (ar_init.u << REL_U),
| (ar_init.v << REL_V),
| (ar_init.w << REL_W)
);
#if EITHER(HAS_AUTO_REPORTING, HOST_KEEPALIVE_FEATURE)
@@ -176,7 +179,7 @@ void GcodeSuite::get_destination_from_command() {
#endif
// Get new XYZ position, whether absolute or relative
LOOP_LINEAR_AXES(i) {
LOOP_NUM_AXES(i) {
if ( (seen[i] = parser.seenval(AXIS_CHAR(i))) ) {
const float v = parser.value_axis_units((AxisEnum)i);
if (skip_move)
@@ -787,6 +790,10 @@ void GcodeSuite::process_parsed_command(const bool no_ok/*=false*/) {
case 305: M305(); break; // M305: Set user thermistor parameters
#endif
#if ENABLED(MPCTEMP)
case 306: M306(); break; // M306: MPC autotune
#endif
#if ENABLED(REPETIER_GCODE_M360)
case 360: M360(); break; // M360: Firmware settings
#endif
+9 -2
View File
@@ -215,6 +215,7 @@
* M303 - PID relay autotune S<temperature> sets the target temperature. Default 150C. (Requires PIDTEMP)
* M304 - Set bed PID parameters P I and D. (Requires PIDTEMPBED)
* M305 - Set user thermistor parameters R T and P. (Requires TEMP_SENSOR_x 1000)
* M306 - MPC autotune. (Requires MPCTEMP)
* M309 - Set chamber PID parameters P I and D. (Requires PIDTEMPCHAMBER)
* M350 - Set microstepping mode. (Requires digital microstepping pins.)
* M351 - Toggle MS1 MS2 pins directly. (Requires digital microstepping pins.)
@@ -337,7 +338,7 @@
#endif
enum AxisRelative : uint8_t {
LOGICAL_AXIS_LIST(REL_E, REL_X, REL_Y, REL_Z, REL_I, REL_J, REL_K)
LOGICAL_AXIS_LIST(REL_E, REL_X, REL_Y, REL_Z, REL_I, REL_J, REL_K, REL_U, REL_V, REL_W)
#if HAS_EXTRUDERS
, E_MODE_ABS, E_MODE_REL
#endif
@@ -363,7 +364,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
@@ -928,6 +930,11 @@ private:
static void M305();
#endif
#if ENABLED(MPCTEMP)
static void M306();
static void M306_report(const bool forReplay=true);
#endif
#if ENABLED(PIDTEMPCHAMBER)
static void M309();
static void M309_report(const bool forReplay=true);
+1 -1
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);
+5 -5
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);
}
+20 -11
View File
@@ -39,11 +39,17 @@
*/
void GcodeSuite::M206() {
if (!parser.seen_any()) return M206_report();
LOOP_LINEAR_AXES(i)
if (parser.seen(AXIS_CHAR(i)))
set_home_offset((AxisEnum)i, parser.value_linear_units());
NUM_AXIS_CODE(
if (parser.seen('X')) set_home_offset(X_AXIS, parser.value_linear_units()),
if (parser.seen('Y')) set_home_offset(Y_AXIS, parser.value_linear_units()),
if (parser.seen('Z')) set_home_offset(Y_AXIS, parser.value_linear_units()),
if (parser.seen(AXIS4_NAME)) set_home_offset(I_AXIS, parser.TERN(AXIS4_ROTATES, value_float, value_linear_units)()),
if (parser.seen(AXIS5_NAME)) set_home_offset(J_AXIS, parser.TERN(AXIS5_ROTATES, value_float, value_linear_units)()),
if (parser.seen(AXIS6_NAME)) set_home_offset(K_AXIS, parser.TERN(AXIS6_ROTATES, value_float, value_linear_units)()),
if (parser.seen(AXIS7_NAME)) set_home_offset(U_AXIS, parser.TERN(AXIS7_ROTATES, value_float, value_linear_units)()),
if (parser.seen(AXIS8_NAME)) set_home_offset(V_AXIS, parser.TERN(AXIS8_ROTATES, value_float, value_linear_units)()),
if (parser.seen(AXIS9_NAME)) set_home_offset(W_AXIS, parser.TERN(AXIS9_ROTATES, value_float, value_linear_units)())
);
#if ENABLED(MORGAN_SCARA)
if (parser.seen('T')) set_home_offset(A_AXIS, parser.value_float()); // Theta
if (parser.seen('P')) set_home_offset(B_AXIS, parser.value_float()); // Psi
@@ -56,13 +62,16 @@ void GcodeSuite::M206_report(const bool forReplay/*=true*/) {
report_heading_etc(forReplay, F(STR_HOME_OFFSET));
SERIAL_ECHOLNPGM_P(
#if IS_CARTESIAN
LIST_N(DOUBLE(LINEAR_AXES),
LIST_N(DOUBLE(NUM_AXES),
PSTR(" M206 X"), LINEAR_UNIT(home_offset.x),
SP_Y_STR, LINEAR_UNIT(home_offset.y),
SP_Z_STR, LINEAR_UNIT(home_offset.z),
SP_I_STR, LINEAR_UNIT(home_offset.i),
SP_J_STR, LINEAR_UNIT(home_offset.j),
SP_K_STR, LINEAR_UNIT(home_offset.k)
SP_I_STR, I_AXIS_UNIT(home_offset.i),
SP_J_STR, J_AXIS_UNIT(home_offset.j),
SP_K_STR, K_AXIS_UNIT(home_offset.k),
SP_U_STR, U_AXIS_UNIT(home_offset.u),
SP_V_STR, V_AXIS_UNIT(home_offset.v),
SP_W_STR, W_AXIS_UNIT(home_offset.w)
)
#else
PSTR(" M206 Z"), LINEAR_UNIT(home_offset.z)
@@ -85,7 +94,7 @@ void GcodeSuite::M428() {
if (homing_needed_error()) return;
xyz_float_t diff;
LOOP_LINEAR_AXES(i) {
LOOP_NUM_AXES(i) {
diff[i] = base_home_pos((AxisEnum)i) - current_position[i];
if (!WITHIN(diff[i], -20, 20) && home_dir((AxisEnum)i) > 0)
diff[i] = -current_position[i];
@@ -97,7 +106,7 @@ void GcodeSuite::M428() {
}
}
LOOP_LINEAR_AXES(i) set_home_offset((AxisEnum)i, diff[i]);
LOOP_NUM_AXES(i) set_home_offset((AxisEnum)i, diff[i]);
report_current_position();
LCD_MESSAGE(MSG_HOME_OFFSETS_APPLIED);
OKAY_BUZZ();
+14 -2
View File
@@ -47,7 +47,7 @@
void report_linear_axis_pos(const xyz_pos_t &pos, const uint8_t precision=3) {
char str[12];
LOOP_LINEAR_AXES(a) {
LOOP_NUM_AXES(a) {
SERIAL_CHAR(' ', AXIS_CHAR(a), ':');
SERIAL_ECHO(dtostrf(pos[a], 1, precision, str));
}
@@ -134,6 +134,15 @@
#if AXIS_IS_L64XX(K)
REPORT_ABSOLUTE_POS(K);
#endif
#if AXIS_IS_L64XX(U)
REPORT_ABSOLUTE_POS(U);
#endif
#if AXIS_IS_L64XX(V)
REPORT_ABSOLUTE_POS(V);
#endif
#if AXIS_IS_L64XX(W)
REPORT_ABSOLUTE_POS(W);
#endif
#if AXIS_IS_L64XX(E0)
REPORT_ABSOLUTE_POS(E0);
#endif
@@ -184,7 +193,10 @@
cartes.x, cartes.y, cartes.z,
planner.get_axis_position_mm(I_AXIS),
planner.get_axis_position_mm(J_AXIS),
planner.get_axis_position_mm(K_AXIS)
planner.get_axis_position_mm(K_AXIS),
planner.get_axis_position_mm(U_AXIS),
planner.get_axis_position_mm(V_AXIS),
planner.get_axis_position_mm(W_AXIS)
);
report_all_axis_pos(from_steppers);
+2 -2
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
+6 -3
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(NUM_AXIS_GANG("X", "Y", "Z", STR_I, STR_J, STR_K, STR_U, STR_V, STR_W))
) {
const float echange = destination.e - current_position.e;
// Is this a retract or recover move?
+55 -19
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);
+2 -2
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(NUM_AXIS_GANG("X", "Y", "Z", STR_I, STR_J, STR_K, STR_U, STR_V, STR_W)) || parser.seen('R')) {
SERIAL_ECHO_START();
#if ENABLED(BABYSTEP_ZPROBE_OFFSET)
+1 -1
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';
+19 -7
View File
@@ -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()); }
+2 -2
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
+86
View File
@@ -0,0 +1,86 @@
/**
* Marlin 3D Printer Firmware
* Copyright (c) 2022 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
*
* Based on Sprinter and grbl.
* Copyright (c) 2011 Camiel Gubbels / Erik van der Zalm
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*
*/
#include "../../inc/MarlinConfig.h"
#if ENABLED(MPCTEMP)
#include "../gcode.h"
#include "../../module/temperature.h"
/**
* M306: MPC settings and autotune
*
* T Autotune the active extruder.
*
* A<watts/kelvin> Ambient heat transfer coefficient (no fan).
* C<joules/kelvin> Block heat capacity.
* E<extruder> Extruder number to set. (Default: E0)
* F<watts/kelvin> Ambient heat transfer coefficient (fan on full).
* P<watts> Heater power.
* R<kelvin/second/kelvin> Sensor responsiveness (= transfer coefficient / heat capcity).
*/
void GcodeSuite::M306() {
if (parser.seen_test('T')) { thermalManager.MPC_autotune(); return; }
if (parser.seen("ACFPR")) {
const heater_id_t hid = (heater_id_t)parser.intval('E', 0);
MPC_t &constants = thermalManager.temp_hotend[hid].constants;
if (parser.seenval('P')) constants.heater_power = parser.value_float();
if (parser.seenval('C')) constants.block_heat_capacity = parser.value_float();
if (parser.seenval('R')) constants.sensor_responsiveness = parser.value_float();
if (parser.seenval('A')) constants.ambient_xfer_coeff_fan0 = parser.value_float();
#if ENABLED(MPC_INCLUDE_FAN)
if (parser.seenval('F')) constants.fan255_adjustment = parser.value_float() - constants.ambient_xfer_coeff_fan0;
#endif
return;
}
HOTEND_LOOP() {
SERIAL_ECHOLNPGM("MPC constants for hotend ", e);
MPC_t& constants = thermalManager.temp_hotend[e].constants;
SERIAL_ECHOLNPGM("Heater power: ", constants.heater_power);
SERIAL_ECHOLNPGM("Heatblock heat capacity: ", constants.block_heat_capacity);
SERIAL_ECHOLNPAIR_F("Sensor responsivness: ", constants.sensor_responsiveness, 4);
SERIAL_ECHOLNPAIR_F("Ambient heat transfer coeff. (no fan): ", constants.ambient_xfer_coeff_fan0, 4);
#if ENABLED(MPC_INCLUDE_FAN)
SERIAL_ECHOLNPAIR_F("Ambient heat transfer coeff. (full fan): ", constants.ambient_xfer_coeff_fan0 + constants.fan255_adjustment, 4);
#endif
}
}
void GcodeSuite::M306_report(const bool forReplay/*=true*/) {
report_heading(forReplay, F("Model predictive control"));
HOTEND_LOOP() {
report_echo_start(forReplay);
MPC_t& constants = thermalManager.temp_hotend[e].constants;
SERIAL_ECHOPGM(" M306 E", e);
SERIAL_ECHOPAIR_F(" P", constants.heater_power, 2);
SERIAL_ECHOPAIR_F(" C", constants.block_heat_capacity, 2);
SERIAL_ECHOPAIR_F(" R", constants.sensor_responsiveness, 4);
SERIAL_ECHOPAIR_F(" A", constants.ambient_xfer_coeff_fan0, 4);
SERIAL_ECHOLNPAIR_F(" F", constants.ambient_xfer_coeff_fan0 + constants.fan255_adjustment, 4);
}
}
#endif // MPCTEMP
+90 -13
View File
@@ -677,22 +677,31 @@
#endif
/**
* Number of Linear Axes (e.g., XYZ)
* Number of Linear Axes (e.g., XYZIJKUVW)
* All the logical axes except for the tool (E) axis
*/
#ifndef LINEAR_AXES
#define LINEAR_AXES XYZ
#ifndef NUM_AXES
#define NUM_AXES XYZ
#endif
#if LINEAR_AXES >= XY
#if NUM_AXES >= XY
#define HAS_Y_AXIS 1
#if LINEAR_AXES >= XYZ
#if NUM_AXES >= XYZ
#define HAS_Z_AXIS 1
#if LINEAR_AXES >= 4
#if NUM_AXES >= 4
#define HAS_I_AXIS 1
#if LINEAR_AXES >= 5
#if NUM_AXES >= 5
#define HAS_J_AXIS 1
#if LINEAR_AXES >= 6
#if NUM_AXES >= 6
#define HAS_K_AXIS 1
#if NUM_AXES >= 7
#define HAS_U_AXIS 1
#if NUM_AXES >= 8
#define HAS_V_AXIS 1
#if NUM_AXES >= 9
#define HAS_W_AXIS 1
#endif
#endif
#endif
#endif
#endif
#endif
@@ -700,14 +709,58 @@
#endif
/**
* Number of Logical Axes (e.g., XYZE)
* All the logical axes that can be commanded directly by G-code.
* Number of Primary Linear Axes (e.g., XYZ)
* X, XY, or XYZ axes. Excluding duplicate axes (X2, Y2. Z2. Z3, Z4)
*/
#if HAS_I_AXIS
#define PRIMARY_LINEAR_AXES 3
#else
#define PRIMARY_LINEAR_AXES NUM_AXES
#endif
/**
* Number of Secondary Axes (e.g., IJKUVW)
* All linear/rotational axes between XYZ and E.
*/
#define SECONDARY_AXES SUB3(NUM_AXES)
/**
* Number of Rotational Axes (e.g., IJK)
* All axes for which AXIS*_ROTATES is defined.
* For these axes, positions are specified in angular degrees.
*/
#if ENABLED(AXIS9_ROTATES)
#define ROTATIONAL_AXES 6
#elif ENABLED(AXIS8_ROTATES)
#define ROTATIONAL_AXES 5
#elif ENABLED(AXIS7_ROTATES)
#define ROTATIONAL_AXES 4
#elif ENABLED(AXIS6_ROTATES)
#define ROTATIONAL_AXES 3
#elif ENABLED(AXIS5_ROTATES)
#define ROTATIONAL_AXES 2
#elif ENABLED(AXIS4_ROTATES)
#define ROTATIONAL_AXES 1
#else
#define ROTATIONAL_AXES 0
#endif
/**
* Number of Secondary Linear Axes (e.g., UVW)
* All secondary axes for which AXIS*_ROTATES is not defined.
* Excluding primary axes and excluding duplicate axes (X2, Y2, Z2, Z3, Z4)
*/
#define SECONDARY_LINEAR_AXES (NUM_AXES - PRIMARY_LINEAR_AXES - ROTATIONAL_AXES)
/**
* Number of Logical Axes (e.g., XYZIJKUVWE)
* All logical axes that can be commanded directly by G-code.
* Delta maps stepper-specific values to ABC steppers.
*/
#if HAS_EXTRUDERS
#define LOGICAL_AXES INCREMENT(LINEAR_AXES)
#define LOGICAL_AXES INCREMENT(NUM_AXES)
#else
#define LOGICAL_AXES LINEAR_AXES
#define LOGICAL_AXES NUM_AXES
#endif
/**
@@ -725,7 +778,7 @@
* distinguished.
*/
#if ENABLED(DISTINCT_E_FACTORS) && E_STEPPERS > 1
#define DISTINCT_AXES (LINEAR_AXES + E_STEPPERS)
#define DISTINCT_AXES (NUM_AXES + E_STEPPERS)
#define DISTINCT_E E_STEPPERS
#define E_INDEX_N(E) (E)
#else
@@ -939,6 +992,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
@@ -1212,6 +1280,15 @@
#if HAS_K_AXIS && !defined(INVERT_K_DIR)
#define INVERT_K_DIR false
#endif
#if HAS_U_AXIS && !defined(INVERT_U_DIR)
#define INVERT_U_DIR false
#endif
#if HAS_V_AXIS && !defined(INVERT_V_DIR)
#define INVERT_V_DIR false
#endif
#if HAS_W_AXIS && !defined(INVERT_W_DIR)
#define INVERT_W_DIR false
#endif
#if HAS_EXTRUDERS && !defined(INVERT_E_DIR)
#define INVERT_E_DIR false
#endif
+39 -24
View File
@@ -902,30 +902,45 @@
#endif
// Remove unused STEALTHCHOP flags
#if LINEAR_AXES < 6
#undef STEALTHCHOP_K
#undef CALIBRATION_MEASURE_KMIN
#undef CALIBRATION_MEASURE_KMAX
#if LINEAR_AXES < 5
#undef STEALTHCHOP_J
#undef CALIBRATION_MEASURE_JMIN
#undef CALIBRATION_MEASURE_JMAX
#if LINEAR_AXES < 4
#undef STEALTHCHOP_I
#undef CALIBRATION_MEASURE_IMIN
#undef CALIBRATION_MEASURE_IMAX
#if LINEAR_AXES < 3
#undef Z_IDLE_HEIGHT
#undef STEALTHCHOP_Z
#undef Z_PROBE_SLED
#undef Z_SAFE_HOMING
#undef HOME_Z_FIRST
#undef HOMING_Z_WITH_PROBE
#undef ENABLE_LEVELING_FADE_HEIGHT
#undef NUM_Z_STEPPER_DRIVERS
#undef CNC_WORKSPACE_PLANES
#if LINEAR_AXES < 2
#undef STEALTHCHOP_Y
#if NUM_AXES < 9
#undef STEALTHCHOP_W
#undef CALIBRATION_MEASURE_WMIN
#undef CALIBRATION_MEASURE_WMAX
#if NUM_AXES < 8
#undef STEALTHCHOP_V
#undef CALIBRATION_MEASURE_VMIN
#undef CALIBRATION_MEASURE_VMAX
#if NUM_AXES < 7
#undef STEALTHCHOP_U
#undef CALIBRATION_MEASURE_UMIN
#undef CALIBRATION_MEASURE_UMAX
#if NUM_AXES < 6
#undef STEALTHCHOP_K
#undef CALIBRATION_MEASURE_KMIN
#undef CALIBRATION_MEASURE_KMAX
#if NUM_AXES < 5
#undef STEALTHCHOP_J
#undef CALIBRATION_MEASURE_JMIN
#undef CALIBRATION_MEASURE_JMAX
#if NUM_AXES < 4
#undef STEALTHCHOP_I
#undef CALIBRATION_MEASURE_IMIN
#undef CALIBRATION_MEASURE_IMAX
#if NUM_AXES < 3
#undef Z_IDLE_HEIGHT
#undef STEALTHCHOP_Z
#undef Z_PROBE_SLED
#undef Z_SAFE_HOMING
#undef HOME_Z_FIRST
#undef HOMING_Z_WITH_PROBE
#undef ENABLE_LEVELING_FADE_HEIGHT
#undef NUM_Z_STEPPER_DRIVERS
#undef CNC_WORKSPACE_PLANES
#if NUM_AXES < 2
#undef STEALTHCHOP_Y
#endif
#endif
#endif
#endif
#endif
#endif
+254 -3
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
+254 -38
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
@@ -617,6 +617,8 @@
#error "Z_STEPPER_ALIGN_KNOWN_STEPPER_POSITIONS is now just Z_STEPPER_ALIGN_STEPPER_XY."
#elif defined(DWIN_CREALITY_LCD_ENHANCED)
#error "DWIN_CREALITY_LCD_ENHANCED is now DWIN_LCD_PROUI."
#elif defined(LINEAR_AXES)
#error "LINEAR_AXES is now NUM_AXES (to account for rotational axes)."
#endif
constexpr float arm[] = AXIS_RELATIVE_MODES;
@@ -798,6 +800,12 @@ static_assert(Y_MAX_LENGTH >= Y_BED_SIZE, "Movement bounds (Y_MIN_POS, Y_MAX_POS
#error "Enable only one of ENDSTOPPULLUP_J_MAX or ENDSTOPPULLDOWN_J_MAX."
#elif BOTH(ENDSTOPPULLUP_KMAX, ENDSTOPPULLDOWN_KMAX)
#error "Enable only one of ENDSTOPPULLUP_K_MAX or ENDSTOPPULLDOWN_K_MAX."
#elif BOTH(ENDSTOPPULLUP_UMAX, ENDSTOPPULLDOWN_UMAX)
#error "Enable only one of ENDSTOPPULLUP_U_MAX or ENDSTOPPULLDOWN_U_MAX."
#elif BOTH(ENDSTOPPULLUP_VMAX, ENDSTOPPULLDOWN_VMAX)
#error "Enable only one of ENDSTOPPULLUP_V_MAX or ENDSTOPPULLDOWN_V_MAX."
#elif BOTH(ENDSTOPPULLUP_WMAX, ENDSTOPPULLDOWN_WMAX)
#error "Enable only one of ENDSTOPPULLUP_W_MAX or ENDSTOPPULLDOWN_W_MAX."
#elif BOTH(ENDSTOPPULLUP_XMIN, ENDSTOPPULLDOWN_XMIN)
#error "Enable only one of ENDSTOPPULLUP_X_MIN or ENDSTOPPULLDOWN_X_MIN."
#elif BOTH(ENDSTOPPULLUP_YMIN, ENDSTOPPULLDOWN_YMIN)
@@ -810,6 +818,12 @@ static_assert(Y_MAX_LENGTH >= Y_BED_SIZE, "Movement bounds (Y_MIN_POS, Y_MAX_POS
#error "Enable only one of ENDSTOPPULLUP_J_MIN or ENDSTOPPULLDOWN_J_MIN."
#elif BOTH(ENDSTOPPULLUP_KMIN, ENDSTOPPULLDOWN_KMIN)
#error "Enable only one of ENDSTOPPULLUP_K_MIN or ENDSTOPPULLDOWN_K_MIN."
#elif BOTH(ENDSTOPPULLUP_UMIN, ENDSTOPPULLDOWN_UMIN)
#error "Enable only one of ENDSTOPPULLUP_U_MIN or ENDSTOPPULLDOWN_U_MIN."
#elif BOTH(ENDSTOPPULLUP_VMIN, ENDSTOPPULLDOWN_VMIN)
#error "Enable only one of ENDSTOPPULLUP_V_MIN or ENDSTOPPULLDOWN_V_MIN."
#elif BOTH(ENDSTOPPULLUP_WMIN, ENDSTOPPULLDOWN_WMIN)
#error "Enable only one of ENDSTOPPULLUP_W_MIN or ENDSTOPPULLDOWN_W_MIN."
#endif
/**
@@ -853,7 +867,7 @@ static_assert(Y_MAX_LENGTH >= Y_BED_SIZE, "Movement bounds (Y_MIN_POS, Y_MAX_POS
/**
* Custom Boot and Status screens
*/
#if ENABLED(SHOW_CUSTOM_BOOTSCREEN) && NONE(HAS_MARLINUI_U8GLIB, TOUCH_UI_FTDI_EVE)
#if ENABLED(SHOW_CUSTOM_BOOTSCREEN) && NONE(HAS_MARLINUI_U8GLIB, TOUCH_UI_FTDI_EVE, IS_DWIN_MARLINUI)
#error "SHOW_CUSTOM_BOOTSCREEN requires Graphical LCD or TOUCH_UI_FTDI_EVE."
#elif ENABLED(SHOW_CUSTOM_BOOTSCREEN) && DISABLED(SHOW_BOOTSCREEN)
#error "SHOW_CUSTOM_BOOTSCREEN requires SHOW_BOOTSCREEN."
@@ -1450,6 +1464,26 @@ static_assert(Y_MAX_LENGTH >= Y_BED_SIZE, "Movement bounds (Y_MIN_POS, Y_MAX_POS
#error "You must set DISPLAY_CHARSET_HD44780 to JAPANESE, WESTERN or CYRILLIC for your LCD controller."
#endif
/**
* Extruder temperature control algorithm - There can be only one!
*/
#if BOTH(PIDTEMP, MPCTEMP)
#error "Only enable PIDTEMP or MPCTEMP, but not both."
#endif
#if ENABLED(MPC_INCLUDE_FAN)
#if FAN_COUNT < 1
#error "MPC_INCLUDE_FAN requires at least one fan."
#endif
#if FAN_COUNT < HOTENDS
#if COUNT_ENABLED(MPC_FAN_0_ALL_HOTENDS, MPC_FAN_0_ACTIVE_HOTEND) > 1
#error "Enable either MPC_FAN_0_ALL_HOTENDS or MPC_FAN_0_ACTIVE_HOTEND, not both."
#elif NONE(MPC_FAN_0_ALL_HOTENDS, MPC_FAN_0_ACTIVE_HOTEND)
#error "MPC_INCLUDE_FAN requires MPC_FAN_0_ALL_HOTENDS or MPC_FAN_0_ACTIVE_HOTEND for one fan with multiple hotends."
#endif
#endif
#endif
/**
* Bed Heating Options - PID vs Limit Switching
*/
@@ -1476,16 +1510,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
/**
@@ -1493,33 +1529,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
@@ -1909,49 +1988,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
@@ -1974,9 +2065,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
@@ -2490,7 +2581,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
@@ -2512,6 +2605,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)
@@ -2535,6 +2637,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
@@ -3018,6 +3132,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
@@ -3063,6 +3183,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
@@ -3092,6 +3219,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)
@@ -3153,6 +3286,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
@@ -3182,6 +3321,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)
@@ -3208,6 +3356,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
@@ -3288,6 +3449,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
@@ -3305,6 +3502,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
@@ -3373,6 +3573,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)
@@ -3393,6 +3599,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
@@ -3406,8 +3613,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
/**
@@ -3431,7 +3638,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;
@@ -3450,7 +3657,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
@@ -3890,6 +4097,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
@@ -3962,7 +4178,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
+2 -2
View File
@@ -42,7 +42,7 @@
* version was tagged.
*/
#ifndef STRING_DISTRIBUTION_DATE
#define STRING_DISTRIBUTION_DATE "2022-03-29"
#define STRING_DISTRIBUTION_DATE "2022-04-03"
#endif
/**
@@ -52,7 +52,7 @@
* to alert users to major changes.
*/
#define MARLIN_HEX_VERSION 02000903
#define MARLIN_HEX_VERSION 02010000
#ifndef REQUIRED_CONFIGURATION_H_VERSION
#define REQUIRED_CONFIGURATION_H_VERSION MARLIN_HEX_VERSION
#endif
+157
View File
@@ -532,6 +532,163 @@
#endif
#endif
#if AUTO_ASSIGNED_U_STEPPER
#warning "Note: Auto-assigned U STEP/DIR/ENABLE_PINs to unused En_STEP/DIR/ENABLE_PINs. (Define NO_AUTO_ASSIGN_WARNING to suppress this warning.)"
#endif
#if AUTO_ASSIGNED_U_CS
#warning "Note: Auto-assigned U_CS_PIN to an unused En_CS_PIN. (Define NO_AUTO_ASSIGN_WARNING to suppress this warning.)"
#endif
#if AUTO_ASSIGNED_U_MS1
#warning "Note: Auto-assigned U_MS1_PIN to an unused En_MS1_PIN. (Define NO_AUTO_ASSIGN_WARNING to suppress this warning.)"
#endif
#if AUTO_ASSIGNED_U_MS2
#warning "Note: Auto-assigned U_MS2_PIN to an unused En_MS2_PIN. (Define NO_AUTO_ASSIGN_WARNING to suppress this warning.)"
#endif
#if AUTO_ASSIGNED_U_MS3
#warning "Note: Auto-assigned U_MS3_PIN to an unused En_MS3_PIN. (Define NO_AUTO_ASSIGN_WARNING to suppress this warning.)"
#endif
#if AUTO_ASSIGNED_U_DIAG
#if U_USE_ENDSTOP == _XMIN_
#warning "Note: Auto-assigned U_DIAG_PIN to X_MIN_PIN. (Define NO_AUTO_ASSIGN_WARNING to suppress this warning.)"
#elif U_USE_ENDSTOP == _XMAX_
#warning "Note: Auto-assigned U_DIAG_PIN to X_MAX_PIN. (Define NO_AUTO_ASSIGN_WARNING to suppress this warning.)"
#elif K_USE_ENDSTOP == _YMIN_
#warning "Note: Auto-assigned U_DIAG_PIN to Y_MIN_PIN. (Define NO_AUTO_ASSIGN_WARNING to suppress this warning.)"
#elif U_USE_ENDSTOP == _YMAX_
#warning "Note: Auto-assigned U_DIAG_PIN to Y_MAX_PIN. (Define NO_AUTO_ASSIGN_WARNING to suppress this warning.)"
#elif U_USE_ENDSTOP == _ZMIN_
#warning "Note: Auto-assigned U_DIAG_PIN to Z_MIN_PIN. (Define NO_AUTO_ASSIGN_WARNING to suppress this warning.)"
#elif U_USE_ENDSTOP == _ZMAX_
#warning "Note: Auto-assigned U_DIAG_PIN to Z_MAX_PIN. (Define NO_AUTO_ASSIGN_WARNING to suppress this warning.)"
#elif U_USE_ENDSTOP == _XDIAG_
#warning "Note: Auto-assigned U_DIAG_PIN to X_DIAG_PIN. (Define NO_AUTO_ASSIGN_WARNING to suppress this warning.)"
#elif U_USE_ENDSTOP == _YDIAG_
#warning "Note: Auto-assigned U_DIAG_PIN to Y_DIAG_PIN. (Define NO_AUTO_ASSIGN_WARNING to suppress this warning.)"
#elif U_USE_ENDSTOP == _ZDIAG_
#warning "Note: Auto-assigned U_DIAG_PIN to Z_DIAG_PIN. (Define NO_AUTO_ASSIGN_WARNING to suppress this warning.)"
#elif U_USE_ENDSTOP == _E0DIAG_
#warning "Note: Auto-assigned U_DIAG_PIN to E0_DIAG_PIN. (Define NO_AUTO_ASSIGN_WARNING to suppress this warning.)"
#elif U_USE_ENDSTOP == _E1DIAG_
#warning "Note: Auto-assigned U_DIAG_PIN to E1_DIAG_PIN. (Define NO_AUTO_ASSIGN_WARNING to suppress this warning.)"
#elif U_USE_ENDSTOP == _E2DIAG_
#warning "Note: Auto-assigned U_DIAG_PIN to E2_DIAG_PIN. (Define NO_AUTO_ASSIGN_WARNING to suppress this warning.)"
#elif U_USE_ENDSTOP == _E3DIAG_
#warning "Note: Auto-assigned U_DIAG_PIN to E3_DIAG_PIN. (Define NO_AUTO_ASSIGN_WARNING to suppress this warning.)"
#elif U_USE_ENDSTOP == _E4DIAG_
#warning "Note: Auto-assigned U_DIAG_PIN to E4_DIAG_PIN. (Define NO_AUTO_ASSIGN_WARNING to suppress this warning.)"
#elif U_USE_ENDSTOP == _E5DIAG_
#warning "Note: Auto-assigned U_DIAG_PIN to E5_DIAG_PIN. (Define NO_AUTO_ASSIGN_WARNING to suppress this warning.)"
#elif U_USE_ENDSTOP == _E6DIAG_
#warning "Note: Auto-assigned U_DIAG_PIN to E6_DIAG_PIN. (Define NO_AUTO_ASSIGN_WARNING to suppress this warning.)"
#elif U_USE_ENDSTOP == _E7DIAG_
#warning "Note: Auto-assigned U_DIAG_PIN to E7_DIAG_PIN. (Define NO_AUTO_ASSIGN_WARNING to suppress this warning.)"
#endif
#endif
#if AUTO_ASSIGNED_V_STEPPER
#warning "Note: Auto-assigned V STEP/DIR/ENABLE_PINs to unused En_STEP/DIR/ENABLE_PINs. (Define NO_AUTO_ASSIGN_WARNING to suppress this warning.)"
#endif
#if AUTO_ASSIGNED_V_CS
#warning "Note: Auto-assigned V_CS_PIN to an unused En_CS_PIN. (Define NO_AUTO_ASSIGN_WARNING to suppress this warning.)"
#endif
#if AUTO_ASSIGNED_V_MS1
#warning "Note: Auto-assigned V_MS1_PIN to an unused En_MS1_PIN. (Define NO_AUTO_ASSIGN_WARNING to suppress this warning.)"
#endif
#if AUTO_ASSIGNED_V_MS2
#warning "Note: Auto-assigned V_MS2_PIN to an unused En_MS2_PIN. (Define NO_AUTO_ASSIGN_WARNING to suppress this warning.)"
#endif
#if AUTO_ASSIGNED_V_MS3
#warning "Note: Auto-assigned V_MS3_PIN to an unused En_MS3_PIN. (Define NO_AUTO_ASSIGN_WARNING to suppress this warning.)"
#endif
#if AUTO_ASSIGNED_V_DIAG
#if V_USE_ENDSTOP == _XMIN_
#warning "Note: Auto-assigned V_DIAG_PIN to X_MIN_PIN. (Define NO_AUTO_ASSIGN_WARNING to suppress this warning.)"
#elif V_USE_ENDSTOP == _XMAX_
#warning "Note: Auto-assigned V_DIAG_PIN to X_MAX_PIN. (Define NO_AUTO_ASSIGN_WARNING to suppress this warning.)"
#elif V_USE_ENDSTOP == _YMIN_
#warning "Note: Auto-assigned V_DIAG_PIN to Y_MIN_PIN. (Define NO_AUTO_ASSIGN_WARNING to suppress this warning.)"
#elif V_USE_ENDSTOP == _YMAX_
#warning "Note: Auto-assigned V_DIAG_PIN to Y_MAX_PIN. (Define NO_AUTO_ASSIGN_WARNING to suppress this warning.)"
#elif V_USE_ENDSTOP == _ZMIN_
#warning "Note: Auto-assigned V_DIAG_PIN to Z_MIN_PIN. (Define NO_AUTO_ASSIGN_WARNING to suppress this warning.)"
#elif V_USE_ENDSTOP == _ZMAX_
#warning "Note: Auto-assigned V_DIAG_PIN to Z_MAX_PIN. (Define NO_AUTO_ASSIGN_WARNING to suppress this warning.)"
#elif V_USE_ENDSTOP == _XDIAG_
#warning "Note: Auto-assigned V_DIAG_PIN to X_DIAG_PIN. (Define NO_AUTO_ASSIGN_WARNING to suppress this warning.)"
#elif V_USE_ENDSTOP == _YDIAG_
#warning "Note: Auto-assigned V_DIAG_PIN to Y_DIAG_PIN. (Define NO_AUTO_ASSIGN_WARNING to suppress this warning.)"
#elif V_USE_ENDSTOP == _ZDIAG_
#warning "Note: Auto-assigned V_DIAG_PIN to Z_DIAG_PIN. (Define NO_AUTO_ASSIGN_WARNING to suppress this warning.)"
#elif V_USE_ENDSTOP == _E0DIAG_
#warning "Note: Auto-assigned V_DIAG_PIN to E0_DIAG_PIN. (Define NO_AUTO_ASSIGN_WARNING to suppress this warning.)"
#elif V_USE_ENDSTOP == _E1DIAG_
#warning "Note: Auto-assigned V_DIAG_PIN to E1_DIAG_PIN. (Define NO_AUTO_ASSIGN_WARNING to suppress this warning.)"
#elif V_USE_ENDSTOP == _E2DIAG_
#warning "Note: Auto-assigned V_DIAG_PIN to E2_DIAG_PIN. (Define NO_AUTO_ASSIGN_WARNING to suppress this warning.)"
#elif V_USE_ENDSTOP == _E3DIAG_
#warning "Note: Auto-assigned V_DIAG_PIN to E3_DIAG_PIN. (Define NO_AUTO_ASSIGN_WARNING to suppress this warning.)"
#elif V_USE_ENDSTOP == _E4DIAG_
#warning "Note: Auto-assigned V_DIAG_PIN to E4_DIAG_PIN. (Define NO_AUTO_ASSIGN_WARNING to suppress this warning.)"
#elif V_USE_ENDSTOP == _E5DIAG_
#warning "Note: Auto-assigned V_DIAG_PIN to E5_DIAG_PIN. (Define NO_AUTO_ASSIGN_WARNING to suppress this warning.)"
#elif V_USE_ENDSTOP == _E6DIAG_
#warning "Note: Auto-assigned V_DIAG_PIN to E6_DIAG_PIN. (Define NO_AUTO_ASSIGN_WARNING to suppress this warning.)"
#elif V_USE_ENDSTOP == _E7DIAG_
#warning "Note: Auto-assigned V_DIAG_PIN to E7_DIAG_PIN. (Define NO_AUTO_ASSIGN_WARNING to suppress this warning.)"
#endif
#endif
#if AUTO_ASSIGNED_W_STEPPER
#warning "Note: Auto-assigned W STEP/DIR/ENABLE_PINs to unused En_STEP/DIR/ENABLE_PINs. (Define NO_AUTO_ASSIGN_WARNING to suppress this warning.)"
#endif
#if AUTO_ASSIGNED_W_CS
#warning "Note: Auto-assigned W_CS_PIN to an unused En_CS_PIN. (Define NO_AUTO_ASSIGN_WARNING to suppress this warning.)"
#endif
#if AUTO_ASSIGNED_W_MS1
#warning "Note: Auto-assigned W_MS1_PIN to an unused En_MS1_PIN. (Define NO_AUTO_ASSIGN_WARNING to suppress this warning.)"
#endif
#if AUTO_ASSIGNED_W_MS2
#warning "Note: Auto-assigned W_MS2_PIN to an unused En_MS2_PIN. (Define NO_AUTO_ASSIGN_WARNING to suppress this warning.)"
#endif
#if AUTO_ASSIGNED_W_MS3
#warning "Note: Auto-assigned W_MS3_PIN to an unused En_MS3_PIN. (Define NO_AUTO_ASSIGN_WARNING to suppress this warning.)"
#endif
#if AUTO_ASSIGNED_W_DIAG
#if W_USE_ENDSTOP == _XMIN_
#warning "Note: Auto-assigned W_DIAG_PIN to X_MIN_PIN. (Define NO_AUTO_ASSIGN_WARNING to suppress this warning.)"
#elif W_USE_ENDSTOP == _XMAX_
#warning "Note: Auto-assigned W_DIAG_PIN to X_MAX_PIN. (Define NO_AUTO_ASSIGN_WARNING to suppress this warning.)"
#elif W_USE_ENDSTOP == _YMIN_
#warning "Note: Auto-assigned W_DIAG_PIN to Y_MIN_PIN. (Define NO_AUTO_ASSIGN_WARNING to suppress this warning.)"
#elif W_USE_ENDSTOP == _YMAX_
#warning "Note: Auto-assigned W_DIAG_PIN to Y_MAX_PIN. (Define NO_AUTO_ASSIGN_WARNING to suppress this warning.)"
#elif W_USE_ENDSTOP == _ZMIN_
#warning "Note: Auto-assigned W_DIAG_PIN to Z_MIN_PIN. (Define NO_AUTO_ASSIGN_WARNING to suppress this warning.)"
#elif W_USE_ENDSTOP == _ZMAX_
#warning "Note: Auto-assigned W_DIAG_PIN to Z_MAX_PIN. (Define NO_AUTO_ASSIGN_WARNING to suppress this warning.)"
#elif W_USE_ENDSTOP == _XDIAG_
#warning "Note: Auto-assigned W_DIAG_PIN to X_DIAG_PIN. (Define NO_AUTO_ASSIGN_WARNING to suppress this warning.)"
#elif W_USE_ENDSTOP == _YDIAG_
#warning "Note: Auto-assigned W_DIAG_PIN to Y_DIAG_PIN. (Define NO_AUTO_ASSIGN_WARNING to suppress this warning.)"
#elif W_USE_ENDSTOP == _ZDIAG_
#warning "Note: Auto-assigned W_DIAG_PIN to Z_DIAG_PIN. (Define NO_AUTO_ASSIGN_WARNING to suppress this warning.)"
#elif W_USE_ENDSTOP == _E0DIAG_
#warning "Note: Auto-assigned W_DIAG_PIN to E0_DIAG_PIN. (Define NO_AUTO_ASSIGN_WARNING to suppress this warning.)"
#elif W_USE_ENDSTOP == _E1DIAG_
#warning "Note: Auto-assigned W_DIAG_PIN to E1_DIAG_PIN. (Define NO_AUTO_ASSIGN_WARNING to suppress this warning.)"
#elif W_USE_ENDSTOP == _E2DIAG_
#warning "Note: Auto-assigned W_DIAG_PIN to E2_DIAG_PIN. (Define NO_AUTO_ASSIGN_WARNING to suppress this warning.)"
#elif W_USE_ENDSTOP == _E3DIAG_
#warning "Note: Auto-assigned W_DIAG_PIN to E3_DIAG_PIN. (Define NO_AUTO_ASSIGN_WARNING to suppress this warning.)"
#elif W_USE_ENDSTOP == _E4DIAG_
#warning "Note: Auto-assigned W_DIAG_PIN to E4_DIAG_PIN. (Define NO_AUTO_ASSIGN_WARNING to suppress this warning.)"
#elif W_USE_ENDSTOP == _E5DIAG_
#warning "Note: Auto-assigned W_DIAG_PIN to E5_DIAG_PIN. (Define NO_AUTO_ASSIGN_WARNING to suppress this warning.)"
#elif W_USE_ENDSTOP == _E6DIAG_
#warning "Note: Auto-assigned W_DIAG_PIN to E6_DIAG_PIN. (Define NO_AUTO_ASSIGN_WARNING to suppress this warning.)"
#elif W_USE_ENDSTOP == _E7DIAG_
#warning "Note: Auto-assigned W_DIAG_PIN to E7_DIAG_PIN. (Define NO_AUTO_ASSIGN_WARNING to suppress this warning.)"
#endif
#endif
#if ENABLED(CHAMBER_FAN) && !defined(CHAMBER_FAN_INDEX)
#warning "Note: Auto-assigned CHAMBER_FAN_INDEX to the first free FAN pin. (Define NO_AUTO_ASSIGN_WARNING to suppress this warning.)"
#endif
+42
View File
@@ -25,6 +25,7 @@
#include "dwin_api.h"
#include "dwin_set.h"
#include "dwin_font.h"
#include "../../../inc/MarlinConfig.h"
@@ -89,6 +90,40 @@ bool DWIN_Handshake() {
}
#endif
// Get font character width
uint8_t fontWidth(uint8_t cfont) {
switch (cfont) {
case font6x12 : return 6;
case font8x16 : return 8;
case font10x20: return 10;
case font12x24: return 12;
case font14x28: return 14;
case font16x32: return 16;
case font20x40: return 20;
case font24x48: return 24;
case font28x56: return 28;
case font32x64: return 32;
default: return 0;
}
}
// Get font character height
uint8_t fontHeight(uint8_t cfont) {
switch (cfont) {
case font6x12 : return 12;
case font8x16 : return 16;
case font10x20: return 20;
case font12x24: return 24;
case font14x28: return 28;
case font16x32: return 32;
case font20x40: return 40;
case font24x48: return 48;
case font28x56: return 56;
case font32x64: return 64;
default: return 0;
}
}
// Set screen display direction
// dir: 0=0°, 1=90°, 2=180°, 3=270°
void DWIN_Frame_SetDir(uint8_t dir) {
@@ -199,6 +234,8 @@ void DWIN_Frame_AreaMove(uint8_t mode, uint8_t dir, uint16_t dis,
// *string: The string
// rlimit: To limit the drawn string length
void DWIN_Draw_String(bool bShow, uint8_t size, uint16_t color, uint16_t bColor, uint16_t x, uint16_t y, const char * const string, uint16_t rlimit/*=0xFFFF*/) {
DWIN_Draw_Rectangle(1, bColor, x, y, x + (fontWidth(size) * strlen_P(string)), y + fontHeight(size));
DWIN_UpdateLCD();
constexpr uint8_t widthAdjust = 0;
size_t i = 0;
DWIN_Byte(i, 0x11);
@@ -213,6 +250,7 @@ void DWIN_Draw_String(bool bShow, uint8_t size, uint16_t color, uint16_t bColor,
DWIN_Word(i, y);
DWIN_Text(i, string, rlimit);
DWIN_Send(i);
DWIN_UpdateLCD();
}
// Draw a positive integer
@@ -228,6 +266,7 @@ void DWIN_Draw_String(bool bShow, uint8_t size, uint16_t color, uint16_t bColor,
void DWIN_Draw_IntValue(uint8_t bShow, bool zeroFill, uint8_t zeroMode, uint8_t size, uint16_t color,
uint16_t bColor, uint8_t iNum, uint16_t x, uint16_t y, uint32_t value) {
size_t i = 0;
DWIN_Draw_Rectangle(1, bColor, x, y, x + fontWidth(size) * iNum + 1, y + fontHeight(size));
DWIN_Byte(i, 0x14);
// Bit 7: bshow
// Bit 6: 1 = signed; 0 = unsigned number;
@@ -258,6 +297,7 @@ void DWIN_Draw_IntValue(uint8_t bShow, bool zeroFill, uint8_t zeroMode, uint8_t
#endif
DWIN_Send(i);
DWIN_UpdateLCD();
}
// Draw a floating point number
@@ -275,6 +315,7 @@ void DWIN_Draw_FloatValue(uint8_t bShow, bool zeroFill, uint8_t zeroMode, uint8_
uint16_t bColor, uint8_t iNum, uint8_t fNum, uint16_t x, uint16_t y, int32_t value) {
//uint8_t *fvalue = (uint8_t*)&value;
size_t i = 0;
DWIN_Draw_Rectangle(1, bColor, x, y, x + fontWidth(size) * (iNum+fNum+1), y + fontHeight(size));
DWIN_Byte(i, 0x14);
DWIN_Byte(i, (bShow * 0x80) | (zeroFill * 0x20) | (zeroMode * 0x10) | size);
DWIN_Word(i, color);
@@ -291,6 +332,7 @@ void DWIN_Draw_FloatValue(uint8_t bShow, bool zeroFill, uint8_t zeroMode, uint8_
DWIN_Byte(i, fvalue[0]);
*/
DWIN_Send(i);
DWIN_UpdateLCD();
}
// Draw a floating point number
+1 -1
View File
@@ -3415,7 +3415,7 @@ void CrealityDWINClass::Menu_Item_Handler(uint8_t menu, uint8_t item, bool draw/
Draw_Menu_Item(row, ICON_Back, F("Back"));
else {
set_bed_leveling_enabled(level_state);
TERN_(AUTO_BED_LEVELING_BILINEAR, refresh_bed_level());
TERN_(AUTO_BED_LEVELING_BILINEAR, bbl.refresh_bed_level());
Draw_Menu(Leveling, LEVELING_MANUAL);
}
break;
+1 -1
View File
@@ -45,8 +45,8 @@ void DWIN_Startup() {
const bool success = DWIN_Handshake();
if (success) DEBUG_ECHOLNPGM("ok."); else DEBUG_ECHOLNPGM("error.");
DWIN_Frame_SetDir(TERN(DWIN_MARLINUI_LANDSCAPE, 0, 1));
DWIN_JPG_ShowAndCache(3);
DWIN_Frame_Clear(Color_Bg_Black); // MarlinUI handles the bootscreen so just clear here
DWIN_JPG_ShowAndCache(3);
DWIN_UpdateLCD();
}
+18 -6
View File
@@ -84,6 +84,7 @@ void MarlinUI::init_lcd() { DWIN_Startup(); }
// This LCD should clear where it will draw anew
void MarlinUI::clear_lcd() {
DWIN_ICON_AnimationControl(0x0000); // disable all icon animations
DWIN_JPG_ShowAndCache(3);
DWIN_Frame_Clear(Color_Bg_Black);
DWIN_UpdateLCD();
@@ -93,29 +94,39 @@ void MarlinUI::clear_lcd() {
#if ENABLED(SHOW_BOOTSCREEN)
void MarlinUI::show_bootscreen() {
clear_lcd();
dwin_string.set(F(SHORT_BUILD_VERSION));
#if ENABLED(SHOW_CUSTOM_BOOTSCREEN) && !defined(CUSTOM_BOOTSCREEN_TIMEOUT)
#define CUSTOM_BOOTSCREEN_TIMEOUT 3000
#endif
#if ENABLED(DWIN_MARLINUI_PORTRAIT)
#define LOGO_CENTER ((LCD_PIXEL_WIDTH) / 2)
#define INFO_CENTER LOGO_CENTER
#define VERSION_Y 330
DWIN_ICON_Show(BOOT_ICON, ICON_MarlinBoot, LOGO_CENTER - 266 / 2, 15);
#else
#define LOGO_CENTER (280 / 2)
#define INFO_CENTER ((LCD_PIXEL_WIDTH) - 200 / 2)
#define VERSION_Y 84
#endif
DWIN_Draw_String(false, font10x20, Color_Yellow, Color_Bg_Black, INFO_CENTER - (dwin_string.length() * 10) / 2, VERSION_Y, S(dwin_string.string()));
TERN_(SHOW_CUSTOM_BOOTSCREEN, safe_delay(CUSTOM_BOOTSCREEN_TIMEOUT));
clear_lcd();
DWIN_ICON_Show(BOOT_ICON, ICON_MarlinBoot, LOGO_CENTER - 266 / 2, 15);
#if ENABLED(DWIN_MARLINUI_PORTRAIT)
DWIN_ICON_Show(BOOT_ICON, ICON_OpenSource, LOGO_CENTER - 174 / 2, 280);
DWIN_ICON_Show(BOOT_ICON, ICON_GitHubURL, LOGO_CENTER - 180 / 2, 420);
DWIN_ICON_Show(BOOT_ICON, ICON_MarlinURL, LOGO_CENTER - 100 / 2, 440);
DWIN_ICON_Show(BOOT_ICON, ICON_Copyright, LOGO_CENTER - 126 / 2, 460);
#else
#define LOGO_CENTER (280 / 2)
#define INFO_CENTER ((LCD_PIXEL_WIDTH) - 200 / 2)
#define VERSION_Y 84
DWIN_ICON_Show(BOOT_ICON, ICON_MarlinBoot, LOGO_CENTER - 266 / 2, 15);
DWIN_ICON_Show(BOOT_ICON, ICON_OpenSource, INFO_CENTER - 174 / 2, 60);
DWIN_ICON_Show(BOOT_ICON, ICON_GitHubURL, INFO_CENTER - 180 / 2, 130);
DWIN_ICON_Show(BOOT_ICON, ICON_MarlinURL, INFO_CENTER - 100 / 2, 152);
DWIN_ICON_Show(BOOT_ICON, ICON_Copyright, INFO_CENTER - 126 / 2, 200);
#endif
DWIN_Draw_String(false, font10x20, Color_Yellow, Color_Bg_Black, INFO_CENTER - (dwin_string.length() * 10) / 2, VERSION_Y, S(dwin_string.string()));
DWIN_UpdateLCD();
}
@@ -170,6 +181,7 @@ void MarlinUI::draw_status_message(const bool blink) {
dwin_font.solid = true;
dwin_font.fg = Color_White;
dwin_font.bg = Color_Bg_Black;
DWIN_Draw_Box(1, Color_Bg_Black, 0, (LCD_PIXEL_HEIGHT - (STAT_FONT_HEIGHT) - 1), 272, STAT_FONT_HEIGHT + 1);
lcd_moveto_xy(0, LCD_PIXEL_HEIGHT - (STAT_FONT_HEIGHT) - 1);
constexpr uint8_t max_status_chars = (LCD_PIXEL_WIDTH) / (STAT_FONT_WIDTH);
@@ -193,11 +193,11 @@ FORCE_INLINE void _draw_heater_status(const heater_id_t heater, const uint16_t x
#define HOTEND_STATS 3
#elif HOTENDS > 1
#define HOTEND_STATS 2
#elif HAS_HOTEND
#else
#define HOTEND_STATS 1
#endif
static celsius_t old_temp[HOTEND_STATS] = ARRAY_N_1(HOTEND_STATS, 500),
old_target[HOTEND_STATS] = ARRAY_N_1(HOTEND_STATS, 500);
old_target[HOTEND_STATS] = ARRAY_N_1(HOTEND_STATS, 500);
static bool old_on[HOTEND_STATS] = ARRAY_N_1(HOTEND_STATS, false);
#endif
@@ -210,25 +210,27 @@ FORCE_INLINE void _draw_heater_status(const heater_id_t heater, const uint16_t x
#endif
#if HAS_HOTEND && HAS_HEATED_BED
float tc, tt;
bool c_draw, t_draw, i_draw, ta;
const bool isBed = heater < 0;
const float tc = isBed ? thermalManager.degBed() : thermalManager.degHotend(heater),
tt = isBed ? thermalManager.degTargetBed() : thermalManager.degTargetHotend(heater);
const bool ta = isBed ? thermalManager.isHeatingBed() : thermalManager.isHeatingHotend(heater);
bool c_draw = tc != (isBed ? old_bed_temp : old_temp[heater]),
t_draw = tt != (isBed ? old_bed_target : old_target[heater]),
i_draw = ta != (isBed ? old_bed_on : old_on[heater]);
if (isBed) {
#if HAS_LEVELING
if (!i_draw && planner.leveling_active != old_leveling_on) i_draw = true;
old_leveling_on = planner.leveling_active;
#endif
tc = thermalManager.degBed();
tt = thermalManager.degTargetBed();
ta = thermalManager.isHeatingBed();
c_draw = tc != old_bed_temp;
t_draw = tt != old_bed_target;
i_draw = ta != old_bed_on;
old_bed_temp = tc;
old_bed_target = tt;
old_bed_on = ta;
}
else {
tc = thermalManager.degHotend(heater);
tt = thermalManager.degTargetHotend(heater);
ta = thermalManager.isHeatingHotend(heater);
c_draw = tc != old_temp[heater];
t_draw = tt != old_target[heater];
i_draw = ta != old_on[heater];
old_temp[heater] = tc;
old_target[heater] = tt;
old_on[heater] = ta;
@@ -237,31 +239,41 @@ FORCE_INLINE void _draw_heater_status(const heater_id_t heater, const uint16_t x
constexpr bool isBed = false;
const float tc = thermalManager.degHotend(heater), tt = thermalManager.degTargetHotend(heater);
const uint8_t ta = thermalManager.isHeatingHotend(heater);
const bool c_draw = tc != old_bed_temp, t_draw = tt != old_bed_target, i_draw = ta != old_bed_on;
bool c_draw = tc != old_temp[heater], t_draw = tt != old_target[heater], i_draw = ta != old_on[heater];
old_temp[heater] = tc; old_target[heater] = tt; old_on[heater] = ta;
#elif HAS_HEATED_BED
constexpr bool isBed = true;
const float tc = thermalManager.degBed(), tt = thermalManager.degTargetBed();
const uint8_t ta = thermalManager.isHeatingBed();
bool c_draw = tc != old_temp[heater], t_draw = tt != old_target[heater], i_draw = ta != old_on[heater];
#if HAS_LEVELING
if (!idraw && planner.leveling_active != old_leveling_on) i_draw = true;
old_leveling_on = tl;
#endif
bool c_draw = tc != old_bed_temp, t_draw = tt != old_bed_target, i_draw = ta != old_bed_on;
old_bed_temp = tc; old_bed_target = tt; old_bed_on = ta;
#else
bool c_draw = false, t_draw = false, i_draw = false;
constexpr float tc = 0, tt = 0;
constexpr uint8_t ta = 0;
#endif
#if HAS_HEATED_BED && HAS_LEVELING
if (isBed) {
i_draw |= (planner.leveling_active != old_leveling_on);
old_leveling_on = planner.leveling_active;
}
#endif
// Draw target temperature, if needed
if (!ui.did_first_redraw || t_draw) {
dwin_string.set(i16tostr3rj(tt + 0.5));
dwin_string.add(LCD_STR_DEGREE);
DWIN_Draw_String(true, font14x28, Color_White, Color_Bg_Black, x, y, S(dwin_string.string()));
}
if (!ui.did_first_redraw || i_draw){
// Draw heater icon with on / off / leveled states
if (!ui.did_first_redraw || i_draw) {
const uint8_t ico = isBed ? (TERN0(HAS_LEVELING, planner.leveling_active) ? ICON_BedLevelOff : ICON_BedOff) : ICON_HotendOff;
DWIN_ICON_Show(ICON, ico + ta, x, y + STATUS_CHR_HEIGHT + 2);
}
// Draw current temperature, if needed
if (!ui.did_first_redraw || c_draw) {
dwin_string.set(i16tostr3rj(tc + 0.5));
dwin_string.add(LCD_STR_DEGREE);
@@ -412,43 +424,45 @@ void MarlinUI::draw_status_screen() {
//
// Progress Bar
//
constexpr int16_t pb_margin = 5,
pb_left = pb_margin + TERN(DWIN_MARLINUI_PORTRAIT, 0, 90),
pb_height = TERN(DWIN_MARLINUI_PORTRAIT, 60, 20),
pb_right = LCD_PIXEL_WIDTH - pb_margin,
pb_bottom = TERN(DWIN_MARLINUI_PORTRAIT, 410, 220),
pb_top = pb_bottom - pb_height,
pb_width = pb_right - pb_left;
#if HAS_PRINT_PROGRESS
constexpr int16_t pb_margin = 5,
pb_left = pb_margin + TERN(DWIN_MARLINUI_PORTRAIT, 0, 90),
pb_height = TERN(DWIN_MARLINUI_PORTRAIT, 60, 20),
pb_right = LCD_PIXEL_WIDTH - pb_margin,
pb_bottom = TERN(DWIN_MARLINUI_PORTRAIT, 410, 220),
pb_top = pb_bottom - pb_height,
pb_width = pb_right - pb_left;
const progress_t progress = TERN(HAS_PRINT_PROGRESS_PERMYRIAD, get_progress_permyriad, get_progress_percent)();
const progress_t progress = TERN(HAS_PRINT_PROGRESS_PERMYRIAD, get_progress_permyriad, get_progress_percent)();
if (!ui.did_first_redraw)
DWIN_Draw_Rectangle(0, Select_Color, pb_left, pb_top, pb_right, pb_bottom); // Outline
if (!ui.did_first_redraw)
DWIN_Draw_Rectangle(0, Select_Color, pb_left, pb_top, pb_right, pb_bottom); // Outline
static uint16_t old_solid = 50;
const uint16_t pb_solid = (pb_width - 2) * (progress / (PROGRESS_SCALE)) * 0.01f;
const bool p_draw = !ui.did_first_redraw || old_solid != pb_solid;
static uint16_t old_solid = 50;
const uint16_t pb_solid = (pb_width - 2) * (progress / (PROGRESS_SCALE)) * 0.01f;
const bool p_draw = !ui.did_first_redraw || old_solid != pb_solid;
if (p_draw) {
//if (pb_solid)
DWIN_Draw_Rectangle(1, Select_Color, pb_left + 1, pb_top + 1, pb_left + pb_solid, pb_bottom - 1); // Fill the solid part
if (p_draw) {
//if (pb_solid)
DWIN_Draw_Rectangle(1, Select_Color, pb_left + 1, pb_top + 1, pb_left + pb_solid, pb_bottom - 1); // Fill the solid part
//if (pb_solid < old_solid)
DWIN_Draw_Rectangle(1, Color_Bg_Black, pb_left + 1 + pb_solid, pb_top + 1, pb_right - 1, pb_bottom - 1); // Erase the rest
//if (pb_solid < old_solid)
DWIN_Draw_Rectangle(1, Color_Bg_Black, pb_left + 1 + pb_solid, pb_top + 1, pb_right - 1, pb_bottom - 1); // Erase the rest
#if ENABLED(SHOW_SD_PERCENT)
dwin_string.set(TERN(PRINT_PROGRESS_SHOW_DECIMALS, permyriadtostr4(progress), ui8tostr3rj(progress / (PROGRESS_SCALE))));
dwin_string.add(PSTR("%"));
DWIN_Draw_String(
false, font16x32, Percent_Color, Color_Bg_Black,
pb_left + (pb_width - dwin_string.length() * 16) / 2,
pb_top + (pb_height - 32) / 2,
S(dwin_string.string())
);
#endif
#if ENABLED(SHOW_SD_PERCENT)
dwin_string.set(TERN(PRINT_PROGRESS_SHOW_DECIMALS, permyriadtostr4(progress), ui8tostr3rj(progress / (PROGRESS_SCALE))));
dwin_string.add(PSTR("%"));
DWIN_Draw_String(
false, font16x32, Percent_Color, Color_Bg_Black,
pb_left + (pb_width - dwin_string.length() * 16) / 2,
pb_top + (pb_height - 32) / 2,
S(dwin_string.string())
);
#endif
old_solid = pb_solid;
}
old_solid = pb_solid;
}
#endif // HAS_PRINT_PROGRESS
//
// Status Message
@@ -94,12 +94,12 @@ namespace ExtUI {
// Called after loading or resetting stored settings
}
void onConfigurationStoreWritten(bool success) {
void onSettingsStored(bool success) {
// Called after the entire EEPROM has been written,
// whether successful or not.
}
void onConfigurationStoreRead(bool success) {
void onSettingsLoaded(bool success) {
// Called after the entire EEPROM has been read,
// whether successful or not.
}
@@ -82,7 +82,7 @@ void ChironTFT::Startup() {
TFTSer.begin(115200);
// wait for the TFT panel to initialise and finish the animation
// Wait for the TFT panel to initialize and finish the animation
safe_delay(1000);
// There are different panels for the Chiron with slightly different commands
@@ -83,12 +83,12 @@ namespace ExtUI {
// Called after loading or resetting stored settings
}
void onConfigurationStoreWritten(bool success) {
void onSettingsStored(bool success) {
// Called after the entire EEPROM has been written,
// whether successful or not.
}
void onConfigurationStoreRead(bool success) {
void onSettingsLoaded(bool success) {
// Called after the entire EEPROM has been read,
// whether successful or not.
}
@@ -85,7 +85,7 @@ void AnycubicTFTClass::OnSetup() {
SENDLINE_DBG_PGM("J17", "TFT Serial Debug: Main board reset... J17"); // J17 Main board reset
delay_ms(10);
// initialise the state of the key pins running on the tft
// Init the state of the key pins running on the TFT
#if ENABLED(SDSUPPORT) && PIN_EXISTS(SD_DETECT)
SET_INPUT_PULLUP(SD_DETECT_PIN);
#endif
+2 -2
View File
@@ -102,12 +102,12 @@ namespace ExtUI {
// Called after loading or resetting stored settings
}
void onConfigurationStoreWritten(bool success) {
void onSettingsStored(bool success) {
// Called after the entire EEPROM has been written,
// whether successful or not.
}
void onConfigurationStoreRead(bool success) {
void onSettingsLoaded(bool success) {
// Called after the entire EEPROM has been read,
// whether successful or not.
}
@@ -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)));
}
@@ -100,11 +100,11 @@ namespace ExtUI {
void onPostprocessSettings() {}
void onConfigurationStoreWritten(bool success) {
void onSettingsStored(bool success) {
dgus_screen_handler.ConfigurationStoreWritten(success);
}
void onConfigurationStoreRead(bool success) {
void onSettingsLoaded(bool success) {
dgus_screen_handler.ConfigurationStoreRead(success);
}
+2 -2
View File
@@ -88,12 +88,12 @@ namespace ExtUI {
// Called after loading or resetting stored settings
}
void onConfigurationStoreWritten(bool success) {
void onSettingsStored(bool success) {
// Called after the entire EEPROM has been written,
// whether successful or not.
}
void onConfigurationStoreRead(bool success) {
void onSettingsLoaded(bool success) {
// Called after the entire EEPROM has been read,
// whether successful or not.
}
@@ -97,7 +97,7 @@ namespace ExtUI {
void onLoadSettings(const char *buff) { InterfaceSettingsScreen::loadSettings(buff); }
void onPostprocessSettings() {} // Called after loading or resetting stored settings
void onConfigurationStoreWritten(bool success) {
void onSettingsStored(bool success) {
#ifdef ARCHIM2_SPI_FLASH_EEPROM_BACKUP_SIZE
if (success && InterfaceSettingsScreen::backupEEPROM()) {
SERIAL_ECHOLNPGM("EEPROM backed up to SPI Flash");
@@ -106,7 +106,7 @@ namespace ExtUI {
UNUSED(success);
#endif
}
void onConfigurationStoreRead(bool) {}
void onSettingsLoaded(bool) {}
void onPlayTone(const uint16_t frequency, const uint16_t duration) { sound.play_tone(frequency, duration); }
+2 -2
View File
@@ -147,8 +147,8 @@ namespace ExtUI {
void onStoreSettings(char*) {}
void onLoadSettings(const char*) {}
void onPostprocessSettings() {}
void onConfigurationStoreWritten(bool) {}
void onConfigurationStoreRead(bool) {}
void onSettingsStored(bool) {}
void onSettingsLoaded(bool) {}
#if HAS_MESH
void onLevelingStart() {}
@@ -79,12 +79,12 @@ namespace ExtUI {
// Called after loading or resetting stored settings
}
void onConfigurationStoreWritten(bool success) {
void onSettingsStored(bool success) {
// Called after the entire EEPROM has been written,
// whether successful or not.
}
void onConfigurationStoreRead(bool success) {
void onSettingsLoaded(bool success) {
// Called after the entire EEPROM has been read,
// whether successful or not.
}
@@ -117,6 +117,7 @@ namespace ExtUI {
void onSteppersDisabled() {}
void onSteppersEnabled() {}
}
#endif // NEXTION_TFT
+30
View File
@@ -420,6 +420,15 @@ namespace ExtUI {
#if AXIS_IS_TMC(K)
case K: return stepperK.getMilliamps();
#endif
#if AXIS_IS_TMC(U)
case U: return stepperU.getMilliamps();
#endif
#if AXIS_IS_TMC(V)
case V: return stepperV.getMilliamps();
#endif
#if AXIS_IS_TMC(W)
case W: return stepperW.getMilliamps();
#endif
#if AXIS_IS_TMC(X2)
case X2: return stepperX2.getMilliamps();
#endif
@@ -489,6 +498,15 @@ namespace ExtUI {
#if AXIS_IS_TMC(K)
case K: stepperK.rms_current(constrain(mA, 400, 1500)); break;
#endif
#if AXIS_IS_TMC(U)
case U: stepperU.rms_current(constrain(mA, 400, 1500)); break;
#endif
#if AXIS_IS_TMC(V)
case V: stepperV.rms_current(constrain(mA, 400, 1500)); break;
#endif
#if AXIS_IS_TMC(W)
case W: stepperW.rms_current(constrain(mA, 400, 1500)); break;
#endif
#if AXIS_IS_TMC(X2)
case X2: stepperX2.rms_current(constrain(mA, 400, 1500)); break;
#endif
@@ -546,6 +564,9 @@ namespace ExtUI {
OPTCODE(I_SENSORLESS, case I: return stepperI.homing_threshold())
OPTCODE(J_SENSORLESS, case J: return stepperJ.homing_threshold())
OPTCODE(K_SENSORLESS, case K: return stepperK.homing_threshold())
OPTCODE(U_SENSORLESS, case U: return stepperU.homing_threshold())
OPTCODE(V_SENSORLESS, case V: return stepperV.homing_threshold())
OPTCODE(W_SENSORLESS, case W: return stepperW.homing_threshold())
OPTCODE(X2_SENSORLESS, case X2: return stepperX2.homing_threshold())
OPTCODE(Y2_SENSORLESS, case Y2: return stepperY2.homing_threshold())
OPTCODE(Z2_SENSORLESS, case Z2: return stepperZ2.homing_threshold())
@@ -575,6 +596,15 @@ namespace ExtUI {
#if K_SENSORLESS
case K: stepperK.homing_threshold(value); break;
#endif
#if U_SENSORLESS
case U: stepperU.homing_threshold(value); break;
#endif
#if V_SENSORLESS
case V: stepperV.homing_threshold(value); break;
#endif
#if W_SENSORLESS
case W: stepperW.homing_threshold(value); break;
#endif
#if X2_SENSORLESS
case X2: stepperX2.homing_threshold(value); break;
#endif

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