diff --git a/.github/workflows/test-builds.yml b/.github/workflows/test-builds.yml index e37f532402..069f36714d 100644 --- a/.github/workflows/test-builds.yml +++ b/.github/workflows/test-builds.yml @@ -113,10 +113,10 @@ jobs: steps: - name: Check out the PR - uses: actions/checkout@v2 + uses: actions/checkout@v3 - name: Cache pip - uses: actions/cache@v2 + uses: actions/cache@v3 with: path: ~/.cache/pip key: ${{ runner.os }}-pip-${{ hashFiles('**/requirements.txt') }} @@ -124,20 +124,20 @@ jobs: ${{ runner.os }}-pip- - name: Cache PlatformIO - uses: actions/cache@v2 + uses: actions/cache@v3 with: path: ~/.platformio key: ${{ runner.os }}-${{ hashFiles('**/lockfiles') }} - name: Select Python 3.7 - uses: actions/setup-python@v2 + uses: actions/setup-python@v3 with: python-version: '3.7' # Version range or exact version of a Python version to use, using semvers version range syntax. architecture: 'x64' # optional x64 or x86. Defaults to x64 if not specified - name: Install PlatformIO run: | - pip install -U https://github.com/platformio/platformio-core/archive/develop.zip + pip install -U https://github.com/platformio/platformio-core/archive/v5.2.5.zip platformio update - name: Run ${{ matrix.test-platform }} Tests diff --git a/Marlin/Configuration.h b/Marlin/Configuration.h index 78592de115..435a4f524f 100644 --- a/Marlin/Configuration.h +++ b/Marlin/Configuration.h @@ -30,7 +30,7 @@ #define tallVersion -//#define ABL_Bilinear +#define ABL_Bilinear /* * Enables a filament sensor plugged into the laser pin. Disables the laser */ @@ -99,7 +99,7 @@ * * Advanced settings can be found in Configuration_adv.h */ -#define CONFIGURATION_H_VERSION 02000903 +#define CONFIGURATION_H_VERSION 02010000 //=========================================================================== //============================= Getting Started ============================= @@ -233,9 +233,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 @@ -244,31 +244,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 @@ -585,7 +604,7 @@ * */ #if ENABLED(TREX3) - #define TEMP_SENSOR_0 61 + #define TEMP_SENSOR_0 1047 #define TEMP_SENSOR_1 61 #else #define TEMP_SENSOR_0 1 @@ -618,12 +637,12 @@ //#define MAX31865_SENSOR_OHMS_1 100 //#define MAX31865_CALIBRATION_OHMS_1 430 -#define TEMP_RESIDENCY_TIME 5 // (seconds) Time to wait for hotend to "settle" in M109 -#define TEMP_WINDOW 3 // (°C) Temperature proximity for the "temperature reached" timer -#define TEMP_HYSTERESIS 3 // (°C) Temperature proximity considered "close enough" to the target +#define TEMP_RESIDENCY_TIME 2 // (seconds) Time to wait for hotend to "settle" in M109 +#define TEMP_WINDOW 5 // (°C) Temperature proximity for the "temperature reached" timer +#define TEMP_HYSTERESIS 5 // (°C) Temperature proximity considered "close enough" to the target #define TEMP_BED_RESIDENCY_TIME 5 // (seconds) Time to wait for bed to "settle" in M190 -#define TEMP_BED_WINDOW 1 // (°C) Temperature proximity for the "temperature reached" timer +#define TEMP_BED_WINDOW 2 // (°C) Temperature proximity for the "temperature reached" timer #define TEMP_BED_HYSTERESIS 3 // (°C) Temperature proximity considered "close enough" to the target #define TEMP_CHAMBER_RESIDENCY_TIME 10 // (seconds) Time to wait for chamber to "settle" in M191 @@ -691,10 +710,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 @@ -722,17 +743,45 @@ #define DEFAULT_Ki 1.08 #define DEFAULT_Kd 114 #endif - // MakerGear - //#define DEFAULT_Kp 7.0 - //#define DEFAULT_Ki 0.1 - //#define DEFAULT_Kd 12 +#endif - // Mendel Parts V9 on 12V - //#define DEFAULT_Kp 63.0 - //#define DEFAULT_Ki 2.25 - //#define DEFAULT_Kd 440 +/** + * 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. -#endif // PIDTEMP + #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 ====================== @@ -911,12 +960,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 @@ -928,12 +983,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 @@ -947,12 +1008,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 @@ -963,12 +1030,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 true // Set to true to invert the logic of the endstop. #define Z_MAX_ENDSTOP_INVERTING true // 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. /** @@ -1028,13 +1101,16 @@ #else #define Z_DRIVER_TYPE DRV8825 #endif - //#define Y2_DRIVER_TYPE A4988 - //#define Z2_DRIVER_TYPE A4988 - //#define Z3_DRIVER_TYPE A4988 - //#define Z4_DRIVER_TYPE A4988 - //#define I_DRIVER_TYPE A4988 - //#define J_DRIVER_TYPE A4988 - //#define K_DRIVER_TYPE A4988 +//#define Y2_DRIVER_TYPE A4988 +//#define Z2_DRIVER_TYPE A4988 +//#define Z3_DRIVER_TYPE A4988 +//#define Z4_DRIVER_TYPE A4988 +//#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 #if ENABLED(E_2208) #define E0_DRIVER_TYPE TMC2208_STANDALONE #define E1_DRIVER_TYPE TMC2208_STANDALONE @@ -1093,9 +1169,9 @@ #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...]] */ @@ -1114,9 +1190,9 @@ #define DEFAULT_AXIS_STEPS_PER_UNIT { 80, Y_STEPSMM, Z_STEPSMM, 93, 93 } /** - * 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...]] */ #if ENABLED(Y_2208) && DISABLED(Y_Spreadcycle) #define Y_MAXFEED 100 @@ -1131,10 +1207,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 { 750, 500, 400, 3000, 3000 } @@ -1144,7 +1220,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 @@ -1157,7 +1233,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 @@ -1171,6 +1247,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 @@ -1513,6 +1592,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! @@ -1522,6 +1604,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 @@ -1552,6 +1637,10 @@ //#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 // For direct drive extruder v9 set to true, for geared extruder set to false. @@ -1594,6 +1683,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 @@ -1601,7 +1693,7 @@ #define X_BED_SIZE 400 #define Y_BED_SIZE 400 -// Travel limits (mm) after homing, corresponding to endstop positions. +// Travel limits (linear=mm, rotational=°) after homing, corresponding to endstop positions. #if DISABLED(TREX3) || ENABLED(TREX3_UPGRADE) #define X_MIN_POS -42 #define Y_MIN_POS 0 @@ -1626,6 +1718,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 @@ -1645,6 +1743,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 @@ -1656,6 +1757,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) @@ -1670,86 +1774,80 @@ * Marlin knows a print job is running when: * 1. Running a print job from media started with M24. * 2. The Print Job Timer has been started with M75. - * 3. The heaters were turned on and PRINTJOB_TIMER_AUTOSTART is enabled. + * 3. The heaters were turned on with a wait command (M109) and PRINTJOB_TIMER_AUTOSTART is enabled. * * RAMPS-based boards use SERVO3_PIN for the first runout sensor. * For other boards you may need to define FIL_RUNOUT_PIN, FIL_RUNOUT2_PIN, etc. */ -#if ANY(FilamentSensor, filamentEncoder, lerdgeFilSensor) - #define FILAMENT_RUNOUT_SENSOR -#endif + +#define FILAMENT_RUNOUT_SENSOR #if ENABLED(FILAMENT_RUNOUT_SENSOR) - #define FIL_RUNOUT_ENABLED_DEFAULT true // Enable the sensor on startup. Override with M412 followed by M500. - #if ENABLED(TREX3) - #define NUM_RUNOUT_SENSORS 2 - #else - #define NUM_RUNOUT_SENSORS 1 // Number of sensors, up to one per extruder. Define a FIL_RUNOUT#_PIN for each. - #endif - #if ENABLED(lerdgeFilSensor) || ENABLED(TREX3) - #define FIL_RUNOUT_STATE LOW // set to true to invert the logic of the sensor. - #else - #define FIL_RUNOUT_STATE HIGH // set to true to invert the logic of the sensor. - #endif - #define FIL_RUNOUT_PULLUP // Use internal pullup for filament runout pins. - //#define FIL_RUNOUT_PULLDOWN // Use internal pulldown for filament runout pins. - //#define WATCH_ALL_RUNOUT_SENSORS // Execute runout script on any triggering sensor, not only for the active extruder. - // This is automatically enabled for MIXING_EXTRUDERs. - - // Override individually if the runout sensors vary - //#define FIL_RUNOUT1_STATE LOW - //#define FIL_RUNOUT1_PULLUP - //#define FIL_RUNOUT1_PULLDOWN - - //#define FIL_RUNOUT2_STATE LOW - //#define FIL_RUNOUT2_PULLUP - //#define FIL_RUNOUT2_PULLDOWN - - //#define FIL_RUNOUT3_STATE LOW - //#define FIL_RUNOUT3_PULLUP - //#define FIL_RUNOUT3_PULLDOWN - - //#define FIL_RUNOUT4_STATE LOW - //#define FIL_RUNOUT4_PULLUP - //#define FIL_RUNOUT4_PULLDOWN - - //#define FIL_RUNOUT5_STATE LOW - //#define FIL_RUNOUT5_PULLUP - //#define FIL_RUNOUT5_PULLDOWN - - //#define FIL_RUNOUT6_STATE LOW - //#define FIL_RUNOUT6_PULLUP - //#define FIL_RUNOUT6_PULLDOWN - - //#define FIL_RUNOUT7_STATE LOW - //#define FIL_RUNOUT7_PULLUP - //#define FIL_RUNOUT7_PULLDOWN - - //#define FIL_RUNOUT8_STATE LOW - //#define FIL_RUNOUT8_PULLUP - //#define FIL_RUNOUT8_PULLDOWN + #if ENABLED(TREX3) + #define NUM_RUNOUT_SENSORS 2 + #else + #define NUM_RUNOUT_SENSORS 1 // Number of sensors, up to one per extruder. Define a FIL_RUNOUT#_PIN for each. + #endif + #if ENABLED(TREX3) + #define FIL_RUNOUT_ENABLED { true, true } // Default enabled state for sensors E0[, E1[, E2[, E3...]]]. Override with M591EnnSn followed by M500. + #else + #define FIL_RUNOUT_ENABLED { true } // Default enabled state for sensors E0[, E1[, E2[, E3...]]]. Override with M591EnnSn followed by M500. + #endif + #if ENABLED(TREX3) + #define FIL_RUNOUT_MODE { 1, 1 } // Default mode for sensors E0[, E1[, E2[, E3...]]]. 0:NONE 1:Switch NO 2:Switch NC 7:Motion Sensor Override with M591EnPnn + #elif ENABLED(lerdgeFilSensor) + #define FIL_RUNOUT_MODE { 1 } // Default mode for sensors E0[, E1[, E2[, E3...]]]. 0:NONE 1:Switch NO 2:Switch NC 7:Motion Sensor Override with M591EnPnn + #elif ANY(FilamentSensor, lerdgeFilSensor) + #define FIL_RUNOUT_MODE { 2 } // Default mode for sensors E0[, E1[, E2[, E3...]]]. 0:NONE 1:Switch NO 2:Switch NC 7:Motion Sensor Override with M591EnPnn + #elif ENABLED(filamentEncoder) + #define FIL_RUNOUT_MODE { 7 } // Default mode for sensors E0[, E1[, E2[, E3...]]]. 0:NONE 1:Switch NO 2:Switch NC 7:Motion Sensor Override with M591EnPnn + #else + #define FIL_RUNOUT_MODE { 0 } // Default mode for sensors E0[, E1[, E2[, E3...]]]. 0:NONE 1:Switch NO 2:Switch NC 7:Motion Sensor Override with M591EnPnn + #endif + //#define WATCH_ALL_RUNOUT_SENSORS // Execute runout script on any triggering sensor, not only for the active extruder. + // This is automatically enabled for MIXING_EXTRUDERs. // Commands to execute on filament runout. // With multiple runout sensors use the %c placeholder for the current tool in commands (e.g., "M600 T%c") - // NOTE: After 'M412 H1' the host handles filament runout and this script does not apply. + // NOTE: After 'M591 H1' the host handles filament runout and this script does not apply. #define FILAMENT_RUNOUT_SCRIPT "M600" - // After a runout is detected, continue printing this length of filament - // before executing the runout script. Useful for a sensor at the end of - // a feed tube. Requires 4 bytes SRAM per sensor, plus 4 bytes overhead. - #if ENABLED(filamentEncoder) - #define FILAMENT_RUNOUT_DISTANCE_MM 15 + // In Mode 1 or 2, continue printing this length of filament after a run out occurs before executing the + // runout script. Useful for a sensor at the end of a feed tube or debounce on a flakey sensor. + // In Mode 7, extrusion distance to expect a change of state. + // Override with M591EnLnn + #if ENABLED(TREX3) + #define FIL_RUNOUT_DISTANCE_MM { 15, 15 } #else - #define FILAMENT_RUNOUT_DISTANCE_MM 5 + #define FIL_RUNOUT_DISTANCE_MM { 15 } #endif - #ifdef FILAMENT_RUNOUT_DISTANCE_MM - // Enable this option to use an encoder disc that toggles the runout pin - // as the filament moves. (Be sure to set FILAMENT_RUNOUT_DISTANCE_MM - // large enough to avoid false positives.) - #if ENABLED(filamentEncoder) - #define FILAMENT_MOTION_SENSOR - #endif - #endif + #define FIL_RUNOUT_PULLUP // Use internal pullup for filament runout pins. + //#define FIL_RUNOUT_PULLDOWN // Use internal pulldown for filament runout pins. + + // Override individually if the runout sensors vary + //#define FIL_RUNOUT1_PULLUP + //#define FIL_RUNOUT1_PULLDOWN + + //#define FIL_RUNOUT2_PULLUP + //#define FIL_RUNOUT2_PULLDOWN + + //#define FIL_RUNOUT3_PULLUP + //#define FIL_RUNOUT3_PULLDOWN + + //#define FIL_RUNOUT4_PULLUP + //#define FIL_RUNOUT4_PULLDOWN + + //#define FIL_RUNOUT5_PULLUP + //#define FIL_RUNOUT5_PULLDOWN + + //#define FIL_RUNOUT6_PULLUP + //#define FIL_RUNOUT6_PULLDOWN + + //#define FIL_RUNOUT7_PULLUP + //#define FIL_RUNOUT7_PULLDOWN + + //#define FIL_RUNOUT8_PULLUP + //#define FIL_RUNOUT8_PULLDOWN #endif //=========================================================================== @@ -1990,6 +2088,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. @@ -2005,7 +2106,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 @@ -3038,7 +3139,7 @@ // Ender-3 v2 OEM display. A DWIN display with Rotary Encoder. // //#define DWIN_CREALITY_LCD // Creality UI -//#define DWIN_CREALITY_LCD_ENHANCED // Enhanced UI +//#define DWIN_LCD_PROUI // Pro UI by MRiscoC //#define DWIN_CREALITY_LCD_JYERSUI // Jyers UI by Jacob Myers //#define DWIN_MARLINUI_PORTRAIT // MarlinUI (portrait orientation) //#define DWIN_MARLINUI_LANDSCAPE // MarlinUI (landscape orientation) diff --git a/Marlin/Configuration_adv.h b/Marlin/Configuration_adv.h index ce838a4aec..1f3db379fc 100644 --- a/Marlin/Configuration_adv.h +++ b/Marlin/Configuration_adv.h @@ -30,7 +30,7 @@ * * Basic settings can be found in Configuration.h */ -#define CONFIGURATION_ADV_H_VERSION 02000903 +#define CONFIGURATION_ADV_H_VERSION 02010000 //=========================================================================== //============================= Thermal Settings ============================ @@ -859,12 +859,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 @@ -1050,6 +1050,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 /** @@ -1064,11 +1067,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. @@ -1108,7 +1114,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.5 // 0.0 = no correction; 1.0 = full correction // Add steps for motor direction changes on CORE kinematics @@ -1189,6 +1195,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. @@ -1362,24 +1374,27 @@ #endif // HAS_MARLINUI_MENU -#if ANY(HAS_DISPLAY, DWIN_CREALITY_LCD_ENHANCED, DWIN_CREALITY_LCD_JYERSUI) +#if ANY(HAS_DISPLAY, DWIN_LCD_PROUI, DWIN_CREALITY_LCD_JYERSUI) //#define SOUND_MENU_ITEM // Add a mute option to the LCD menu #endif -#if EITHER(HAS_DISPLAY, DWIN_CREALITY_LCD_ENHANCED) - // The timeout (in ms) to return to the status screen from sub-menus - //#define LCD_TIMEOUT_TO_STATUS 15000 +#if EITHER(HAS_DISPLAY, DWIN_LCD_PROUI) + // The timeout to return to the status screen from sub-menus + //#define LCD_TIMEOUT_TO_STATUS 15000 // (ms) #if ENABLED(SHOW_BOOTSCREEN) - #define BOOTSCREEN_TIMEOUT 4000 // (ms) Total Duration to display the boot screen(s) + #define BOOTSCREEN_TIMEOUT 4000 // (ms) Total Duration to display the boot screen(s) #if EITHER(HAS_MARLINUI_U8GLIB, TFT_COLOR_UI) - #define BOOT_MARLIN_LOGO_SMALL // Show a smaller Marlin logo on the Boot Screen (saving lots of flash) + #define BOOT_MARLIN_LOGO_SMALL // Show a smaller Marlin logo on the Boot Screen (saving lots of flash) #endif #endif // Scroll a longer status message into view //#define STATUS_MESSAGE_SCROLLING + // Apply a timeout to low-priority status messages + //#define STATUS_MESSAGE_TIMEOUT_SEC 30 // (seconds) + // On the Info Screen, display XY with one decimal place when possible //#define LCD_DECIMAL_SMALL_XY @@ -2046,6 +2061,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. @@ -2463,7 +2493,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 @@ -2666,6 +2696,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 @@ -2854,6 +2902,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 @@ -2941,6 +3016,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 @@ -2983,6 +3061,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 @@ -3010,6 +3091,9 @@ #define STEALTHCHOP_I #define STEALTHCHOP_J #define STEALTHCHOP_K + #define STEALTHCHOP_U + #define STEALTHCHOP_V + #define STEALTHCHOP_W #define STEALTHCHOP_E /** @@ -3036,9 +3120,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 @@ -3084,9 +3171,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 @@ -3136,6 +3226,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 @@ -3303,6 +3396,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 @@ -3497,7 +3617,7 @@ * You'll need to select a pin for the ON/OFF function and optionally choose a 0-5V * hardware PWM pin for the speed control and a pin for the rotation direction. * - * See https://marlinfw.org/docs/configuration/laser_spindle.html for more config details. + * See https://marlinfw.org/docs/configuration/2.0.9/laser_spindle.html for more config details. */ //#define SPINDLE_FEATURE #if ENABLED(TREX3) @@ -3512,7 +3632,7 @@ //#define SPINDLE_LASER_USE_PWM // Enable if your controller supports setting the speed/power #if ENABLED(SPINDLE_LASER_USE_PWM) #define SPINDLE_LASER_PWM_INVERT false // Set to "true" if the speed/power goes up when you want it to go slower - #define SPINDLE_LASER_FREQUENCY 2500 // (Hz) Spindle/laser frequency (only on supported HALs: AVR and LPC) + #define SPINDLE_LASER_FREQUENCY 2500 // (Hz) Spindle/laser frequency (only on supported HALs: AVR, ESP32, and LPC) #endif //#define AIR_EVACUATION // Cutter Vacuum / Laser Blower motor control with G-codes M10-M11 @@ -4097,12 +4217,12 @@ /** * 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 #if ENABLED(FREEZE_FEATURE) //#define FREEZE_PIN 41 // Override the default (KILL) pin here + #define FREEZE_STATE LOW // State of pin indicating freeze #endif /** diff --git a/Marlin/Makefile b/Marlin/Makefile index eee1403b53..f1c89ff7f5 100644 --- a/Marlin/Makefile +++ b/Marlin/Makefile @@ -132,7 +132,7 @@ CC_MIN:=$(shell $(CC) -dM -E - < /dev/null | grep __GNUC_MINOR__ | cut -f3 -d\ ) CC_PATCHLEVEL:=$(shell $(CC) -dM -E - < /dev/null | grep __GNUC_PATCHLEVEL__ | cut -f3 -d\ ) CC_VER:=$(shell echo $$(( $(CC_MAJ) * 10000 + $(CC_MIN) * 100 + $(CC_PATCHLEVEL) ))) ifeq ($(shell test $(CC_VER) -lt 40901 && echo 1),1) - @echo This version of GCC is likely broken. Enabling relocation workaround. + $(warning This GCC version $(CC_VER) is likely broken. Enabling relocation workaround.) RELOC_WORKAROUND = 1 endif diff --git a/Marlin/Version.h b/Marlin/Version.h index 3263e97fb1..e7c51c1ebb 100644 --- a/Marlin/Version.h +++ b/Marlin/Version.h @@ -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-05" +#define STRING_DISTRIBUTION_DATE "2022-04-03" /** * Defines a generic printer name to be output to the LCD after booting Marlin. diff --git a/Marlin/src/HAL/AVR/endstop_interrupts.h b/Marlin/src/HAL/AVR/endstop_interrupts.h index 0ce8574c53..5511aa406f 100644 --- a/Marlin/src/HAL/AVR/endstop_interrupts.h +++ b/Marlin/src/HAL/AVR/endstop_interrupts.h @@ -213,6 +213,51 @@ void setup_endstop_interrupts() { pciSetup(K_MIN_PIN); #endif #endif + #if HAS_U_MAX + #if (digitalPinToInterrupt(U_MAX_PIN) != NOT_AN_INTERRUPT) + _ATTACH(U_MAX_PIN); + #else + static_assert(digitalPinHasPCICR(U_MAX_PIN), "U_MAX_PIN is not interrupt-capable"); + pciSetup(U_MAX_PIN); + #endif + #elif HAS_U_MIN + #if (digitalPinToInterrupt(U_MIN_PIN) != NOT_AN_INTERRUPT) + _ATTACH(U_MIN_PIN); + #else + static_assert(digitalPinHasPCICR(U_MIN_PIN), "U_MIN_PIN is not interrupt-capable"); + pciSetup(U_MIN_PIN); + #endif + #endif + #if HAS_V_MAX + #if (digitalPinToInterrupt(V_MAX_PIN) != NOT_AN_INTERRUPT) + _ATTACH(V_MAX_PIN); + #else + static_assert(digitalPinHasPCICR(V_MAX_PIN), "V_MAX_PIN is not interrupt-capable"); + pciSetup(V_MAX_PIN); + #endif + #elif HAS_V_MIN + #if (digitalPinToInterrupt(V_MIN_PIN) != NOT_AN_INTERRUPT) + _ATTACH(V_MIN_PIN); + #else + static_assert(digitalPinHasPCICR(V_MIN_PIN), "V_MIN_PIN is not interrupt-capable"); + pciSetup(V_MIN_PIN); + #endif + #endif + #if HAS_W_MAX + #if (digitalPinToInterrupt(W_MAX_PIN) != NOT_AN_INTERRUPT) + _ATTACH(W_MAX_PIN); + #else + static_assert(digitalPinHasPCICR(W_MAX_PIN), "W_MAX_PIN is not interrupt-capable"); + pciSetup(W_MAX_PIN); + #endif + #elif HAS_W_MIN + #if (digitalPinToInterrupt(W_MIN_PIN) != NOT_AN_INTERRUPT) + _ATTACH(W_MIN_PIN); + #else + static_assert(digitalPinHasPCICR(W_MIN_PIN), "W_MIN_PIN is not interrupt-capable"); + pciSetup(W_MIN_PIN); + #endif + #endif #if HAS_X2_MAX #if (digitalPinToInterrupt(X2_MAX_PIN) != NOT_AN_INTERRUPT) _ATTACH(X2_MAX_PIN); diff --git a/Marlin/src/HAL/AVR/inc/SanityCheck.h b/Marlin/src/HAL/AVR/inc/SanityCheck.h index 5c1f01a8f4..15a5be4cd2 100644 --- a/Marlin/src/HAL/AVR/inc/SanityCheck.h +++ b/Marlin/src/HAL/AVR/inc/SanityCheck.h @@ -71,3 +71,7 @@ #if ENABLED(POSTMORTEM_DEBUGGING) #error "POSTMORTEM_DEBUGGING is not supported on AVR boards." #endif + +#if USING_PULLDOWNS + #error "PULLDOWN pin mode is not available on AVR boards." +#endif diff --git a/Marlin/src/HAL/DUE/endstop_interrupts.h b/Marlin/src/HAL/DUE/endstop_interrupts.h index 9c7e210488..c1bbcb121b 100644 --- a/Marlin/src/HAL/DUE/endstop_interrupts.h +++ b/Marlin/src/HAL/DUE/endstop_interrupts.h @@ -70,4 +70,10 @@ void setup_endstop_interrupts() { TERN_(HAS_J_MIN, _ATTACH(J_MIN_PIN)); TERN_(HAS_K_MAX, _ATTACH(K_MAX_PIN)); TERN_(HAS_K_MIN, _ATTACH(K_MIN_PIN)); + TERN_(HAS_U_MAX, _ATTACH(U_MAX_PIN)); + TERN_(HAS_U_MIN, _ATTACH(U_MIN_PIN)); + TERN_(HAS_V_MAX, _ATTACH(V_MAX_PIN)); + TERN_(HAS_V_MIN, _ATTACH(V_MIN_PIN)); + TERN_(HAS_W_MAX, _ATTACH(W_MAX_PIN)); + TERN_(HAS_W_MIN, _ATTACH(W_MIN_PIN)); } diff --git a/Marlin/src/HAL/DUE/inc/SanityCheck.h b/Marlin/src/HAL/DUE/inc/SanityCheck.h index 87b09cf292..75480acaf2 100644 --- a/Marlin/src/HAL/DUE/inc/SanityCheck.h +++ b/Marlin/src/HAL/DUE/inc/SanityCheck.h @@ -59,3 +59,7 @@ #if HAS_TMC_SW_SERIAL #error "TMC220x Software Serial is not supported on the DUE platform." #endif + +#if USING_PULLDOWNS + #error "PULLDOWN pin mode is not available on DUE boards." +#endif diff --git a/Marlin/src/HAL/ESP32/HAL.cpp b/Marlin/src/HAL/ESP32/HAL.cpp index 4000dcc908..e204e0b6fe 100644 --- a/Marlin/src/HAL/ESP32/HAL.cpp +++ b/Marlin/src/HAL/ESP32/HAL.cpp @@ -73,9 +73,16 @@ uint16_t MarlinHAL::adc_result; esp_adc_cal_characteristics_t characteristics[ADC_ATTEN_MAX]; adc_atten_t attenuations[ADC1_CHANNEL_MAX] = {}; uint32_t thresholds[ADC_ATTEN_MAX]; -volatile int numPWMUsed = 0, - pwmPins[MAX_PWM_PINS], - pwmValues[MAX_PWM_PINS]; + +volatile int numPWMUsed = 0; +volatile struct { pin_t pin; int value; } pwmState[MAX_PWM_PINS]; + +pin_t chan_pin[CHANNEL_MAX_NUM + 1] = { 0 }; // PWM capable IOpins - not 0 or >33 on ESP32 + +struct { + uint32_t freq; // ledcReadFreq doesn't work if a duty hasn't been set yet! + uint16_t res; +} pwmInfo[(CHANNEL_MAX_NUM + 1) / 2]; // ------------------------ // Public functions @@ -202,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. @@ -229,11 +236,15 @@ void MarlinHAL::adc_init() { } } +#ifndef ADC_REFERENCE_VOLTAGE + #define ADC_REFERENCE_VOLTAGE 3.3 +#endif + void MarlinHAL::adc_start(const pin_t pin) { const adc1_channel_t chan = get_channel(pin); uint32_t mv; esp_adc_cal_get_voltage((adc_channel_t)chan, &characteristics[attenuations[chan]], &mv); - adc_result = mv * 1023.0 / 3300.0; + adc_result = mv * 1023.0f / float(ADC_REFERENCE_VOLTAGE) / 1000.0f; // Change the attenuation level based on the new reading adc_atten_t atten; @@ -250,25 +261,81 @@ void MarlinHAL::adc_start(const pin_t pin) { adc1_set_attenuation(chan, atten); } -void analogWrite(pin_t pin, int value) { - // Use ledc hardware for internal pins - if (pin < 34) { - static int cnt_channel = 1, pin_to_channel[40] = { 0 }; - if (pin_to_channel[pin] == 0) { - ledcAttachPin(pin, cnt_channel); - ledcSetup(cnt_channel, 490, 8); - ledcWrite(cnt_channel, value); - pin_to_channel[pin] = cnt_channel++; +// ------------------------ +// PWM +// ------------------------ + +int8_t channel_for_pin(const uint8_t pin) { + for (int i = 0; i <= CHANNEL_MAX_NUM; i++) + if (chan_pin[i] == pin) return i; + return -1; +} + +// get PWM channel for pin - if none then attach a new one +// return -1 if fail or invalid pin#, channel # (0-15) if success +int8_t get_pwm_channel(const pin_t pin, const uint32_t freq, const uint16_t res) { + if (!WITHIN(pin, 1, MAX_PWM_IOPIN)) return -1; // Not a hardware PWM pin! + int8_t cid = channel_for_pin(pin); + if (cid >= 0) return cid; + + // Find an empty adjacent channel (same timer & freq/res) + for (int i = 0; i <= CHANNEL_MAX_NUM; i++) { + if (chan_pin[i] == 0) { + if (chan_pin[i ^ 0x1] != 0) { + if (pwmInfo[i / 2].freq == freq && pwmInfo[i / 2].res == res) { + chan_pin[i] = pin; // Allocate PWM to this channel + ledcAttachPin(pin, i); + return i; + } + } + else if (cid == -1) // Pair of empty channels? + cid = i & 0xFE; // Save lower channel number } - ledcWrite(pin_to_channel[pin], value); + } + // not attached, is an empty timer slot avail? + if (cid >= 0) { + chan_pin[cid] = pin; + pwmInfo[cid / 2].freq = freq; + pwmInfo[cid / 2].res = res; + ledcSetup(cid, freq, res); + ledcAttachPin(pin, cid); + } + return cid; // -1 if no channel avail +} + +void MarlinHAL::set_pwm_duty(const pin_t pin, const uint16_t v, const uint16_t v_size/*=_BV(PWM_RESOLUTION)-1*/, const bool invert/*=false*/) { + const int8_t cid = get_pwm_channel(pin, PWM_FREQUENCY, PWM_RESOLUTION); + if (cid >= 0) { + uint32_t duty = map(invert ? v_size - v : v, 0, v_size, 0, _BV(PWM_RESOLUTION)-1); + ledcWrite(cid, duty); + } +} + +int8_t MarlinHAL::set_pwm_frequency(const pin_t pin, const uint32_t f_desired) { + const int8_t cid = channel_for_pin(pin); + if (cid >= 0) { + if (f_desired == ledcReadFreq(cid)) return cid; // no freq change + ledcDetachPin(chan_pin[cid]); + chan_pin[cid] = 0; // remove old freq channel + } + return get_pwm_channel(pin, f_desired, PWM_RESOLUTION); // try for new one +} + +// use hardware PWM if avail, if not then ISR +void analogWrite(const pin_t pin, const uint16_t value, const uint32_t freq/*=PWM_FREQUENCY*/, const uint16_t res/*=8*/) { // always 8 bit resolution! + // Use ledc hardware for internal pins + const int8_t cid = get_pwm_channel(pin, freq, res); + if (cid >= 0) { + ledcWrite(cid, value); // set duty value return; } + // not a hardware PWM pin OR no PWM channels available int idx = -1; // Search Pin for (int i = 0; i < numPWMUsed; ++i) - if (pwmPins[i] == pin) { idx = i; break; } + if (pwmState[i].pin == pin) { idx = i; break; } // not found ? if (idx < 0) { @@ -277,7 +344,7 @@ void analogWrite(pin_t pin, int value) { // Take new slot for pin idx = numPWMUsed; - pwmPins[idx] = pin; + pwmState[idx].pin = pin; // Start timer on first use if (idx == 0) HAL_timer_start(MF_TIMER_PWM, PWM_TIMER_FREQUENCY); @@ -285,7 +352,7 @@ void analogWrite(pin_t pin, int value) { } // Use 7bit internal value - add 1 to have 100% high at 255 - pwmValues[idx] = (value + 1) / 2; + pwmState[idx].value = (value + 1) / 2; } // Handle PWM timer interrupt @@ -296,9 +363,9 @@ HAL_PWM_TIMER_ISR() { for (int i = 0; i < numPWMUsed; ++i) { if (count == 0) // Start of interval - WRITE(pwmPins[i], pwmValues[i] ? HIGH : LOW); - else if (pwmValues[i] == count) // End of duration - WRITE(pwmPins[i], LOW); + digitalWrite(pwmState[i].pin, pwmState[i].value ? HIGH : LOW); + else if (pwmState[i].value == count) // End of duration + digitalWrite(pwmState[i].pin, LOW); } // 128 for 7 Bit resolution diff --git a/Marlin/src/HAL/ESP32/HAL.h b/Marlin/src/HAL/ESP32/HAL.h index df52e2186c..8b26c3471d 100644 --- a/Marlin/src/HAL/ESP32/HAL.h +++ b/Marlin/src/HAL/ESP32/HAL.h @@ -64,6 +64,12 @@ #define CRITICAL_SECTION_START() portENTER_CRITICAL(&spinlock) #define CRITICAL_SECTION_END() portEXIT_CRITICAL(&spinlock) +#define HAL_CAN_SET_PWM_FREQ // This HAL supports PWM Frequency adjustment +#define PWM_FREQUENCY 1000u // Default PWM frequency when set_pwm_duty() is called without set_pwm_frequency() +#define PWM_RESOLUTION 10u // Default PWM bit resolution +#define CHANNEL_MAX_NUM 15u // max PWM channel # to allocate (7 to only use low speed, 15 to use low & high) +#define MAX_PWM_IOPIN 33u // hardware pwm pins < 34 + // ------------------------ // Types // ------------------------ @@ -83,7 +89,7 @@ typedef Servo hal_servo_t; void tone(const pin_t _pin, const unsigned int frequency, const unsigned long duration=0); void noTone(const pin_t _pin); -void analogWrite(pin_t pin, int value); +void analogWrite(const pin_t pin, const uint16_t value, const uint32_t freq=PWM_FREQUENCY, const uint16_t res=8); // // Pin Mapping for M42, M43, M226 @@ -209,12 +215,17 @@ public: static uint16_t adc_value() { return adc_result; } /** - * Set the PWM duty cycle for the pin to the given value. - * No inverting the duty cycle in this HAL. - * No changing the maximum size of the provided value to enable finer PWM duty control in this HAL. + * If not already allocated, allocate a hardware PWM channel + * to the pin and set the duty cycle.. + * Optionally invert the duty cycle [default = false] + * Optionally change the scale of the provided value to enable finer PWM duty control [default = 255] */ - static void set_pwm_duty(const pin_t pin, const uint16_t v, const uint16_t=255, const bool=false) { - analogWrite(pin, v); - } + static void set_pwm_duty(const pin_t pin, const uint16_t v, const uint16_t v_size=255, const bool invert=false); + + /** + * Allocate and set the frequency of a hardware PWM pin + * Returns -1 if no pin available. + */ + static int8_t set_pwm_frequency(const pin_t pin, const uint32_t f_desired); }; diff --git a/Marlin/src/HAL/ESP32/Servo.cpp b/Marlin/src/HAL/ESP32/Servo.cpp index fcf5848581..ca3950d07f 100644 --- a/Marlin/src/HAL/ESP32/Servo.cpp +++ b/Marlin/src/HAL/ESP32/Servo.cpp @@ -31,20 +31,18 @@ // so we only allocate servo channels up high to avoid side effects with regards to analogWrite (fans, leds, laser pwm etc.) int Servo::channel_next_free = 12; -Servo::Servo() { - channel = channel_next_free++; -} +Servo::Servo() {} int8_t Servo::attach(const int inPin) { - if (channel >= CHANNEL_MAX_NUM) return -1; if (inPin > 0) pin = inPin; - - ledcSetup(channel, 50, 16); // channel X, 50 Hz, 16-bit depth - ledcAttachPin(pin, channel); - return true; + channel = get_pwm_channel(pin, 50u, 16u); + return channel; // -1 if no PWM avail. } -void Servo::detach() { ledcDetachPin(pin); } +// leave channel connected to servo - set duty to zero +void Servo::detach() { + if (channel >= 0) ledcWrite(channel, 0); +} int Servo::read() { return degrees; } @@ -52,7 +50,7 @@ void Servo::write(int inDegrees) { degrees = constrain(inDegrees, MIN_ANGLE, MAX_ANGLE); int us = map(degrees, MIN_ANGLE, MAX_ANGLE, MIN_PULSE_WIDTH, MAX_PULSE_WIDTH); int duty = map(us, 0, TAU_USEC, 0, MAX_COMPARE); - ledcWrite(channel, duty); + if (channel >= 0) ledcWrite(channel, duty); // don't save duty for servos! } void Servo::move(const int value) { diff --git a/Marlin/src/HAL/ESP32/Servo.h b/Marlin/src/HAL/ESP32/Servo.h index 8542092d66..1dbb416a83 100644 --- a/Marlin/src/HAL/ESP32/Servo.h +++ b/Marlin/src/HAL/ESP32/Servo.h @@ -30,8 +30,7 @@ class Servo { MAX_PULSE_WIDTH = 2400, // Longest pulse sent to a servo TAU_MSEC = 20, TAU_USEC = (TAU_MSEC * 1000), - MAX_COMPARE = _BV(16) - 1, // 65535 - CHANNEL_MAX_NUM = 16; + MAX_COMPARE = _BV(16) - 1; // 65535 public: Servo(); diff --git a/Marlin/src/HAL/ESP32/endstop_interrupts.h b/Marlin/src/HAL/ESP32/endstop_interrupts.h index 4725df921b..0536864610 100644 --- a/Marlin/src/HAL/ESP32/endstop_interrupts.h +++ b/Marlin/src/HAL/ESP32/endstop_interrupts.h @@ -65,4 +65,10 @@ void setup_endstop_interrupts() { TERN_(HAS_J_MIN, _ATTACH(J_MIN_PIN)); TERN_(HAS_K_MAX, _ATTACH(K_MAX_PIN)); TERN_(HAS_K_MIN, _ATTACH(K_MIN_PIN)); + TERN_(HAS_U_MAX, _ATTACH(U_MAX_PIN)); + TERN_(HAS_U_MIN, _ATTACH(U_MIN_PIN)); + TERN_(HAS_V_MAX, _ATTACH(V_MAX_PIN)); + TERN_(HAS_V_MIN, _ATTACH(V_MIN_PIN)); + TERN_(HAS_W_MAX, _ATTACH(W_MAX_PIN)); + TERN_(HAS_W_MIN, _ATTACH(W_MIN_PIN)); } diff --git a/Marlin/src/HAL/ESP32/inc/SanityCheck.h b/Marlin/src/HAL/ESP32/inc/SanityCheck.h index 8bbc68d871..04d70ec14f 100644 --- a/Marlin/src/HAL/ESP32/inc/SanityCheck.h +++ b/Marlin/src/HAL/ESP32/inc/SanityCheck.h @@ -25,8 +25,8 @@ #error "EMERGENCY_PARSER is not yet implemented for ESP32. Disable EMERGENCY_PARSER to continue." #endif -#if ENABLED(FAST_PWM_FAN) || SPINDLE_LASER_FREQUENCY - #error "Features requiring Hardware PWM (FAST_PWM_FAN, SPINDLE_LASER_FREQUENCY) are not yet supported on ESP32." +#if (ENABLED(SPINDLE_LASER_USE_PWM) && SPINDLE_LASER_FREQUENCY > 78125) || (ENABLED(FAST_PWM_FAN_FREQUENCY) && FAST_PWM_FAN_FREQUENCY > 78125) + #error "SPINDLE_LASER_FREQUENCY and FAST_PWM_FREQUENCY maximum value is 78125Hz for ESP32." #endif #if HAS_TMC_SW_SERIAL @@ -40,3 +40,11 @@ #if ENABLED(POSTMORTEM_DEBUGGING) #error "POSTMORTEM_DEBUGGING is not yet supported on ESP32." #endif + +#if MB(MKS_TINYBEE) && ENABLED(FAST_PWM_FAN) + #error "FAST_PWM_FAN is not available on TinyBee." +#endif + +#if USING_PULLDOWNS + #error "PULLDOWN pin mode is not available on ESP32 boards." +#endif diff --git a/Marlin/src/HAL/LPC1768/endstop_interrupts.h b/Marlin/src/HAL/LPC1768/endstop_interrupts.h index 23bd0cc982..e4ac17f608 100644 --- a/Marlin/src/HAL/LPC1768/endstop_interrupts.h +++ b/Marlin/src/HAL/LPC1768/endstop_interrupts.h @@ -155,4 +155,37 @@ void setup_endstop_interrupts() { #endif _ATTACH(K_MIN_PIN); #endif + #if HAS_U_MAX + #if !LPC1768_PIN_INTERRUPT_M(U_MAX_PIN) + #error "U_MAX_PIN is not INTERRUPT-capable." + #endif + _ATTACH(U_MAX_PIN); + #elif HAS_U_MIN + #if !LPC1768_PIN_INTERRUPT_M(U_MIN_PIN) + #error "U_MIN_PIN is not INTERRUPT-capable." + #endif + _ATTACH(U_MIN_PIN); + #endif + #if HAS_V_MAX + #if !LPC1768_PIN_INTERRUPT_M(V_MAX_PIN) + #error "V_MAX_PIN is not INTERRUPT-capable." + #endif + _ATTACH(V_MAX_PIN); + #elif HAS_V_MIN + #if !LPC1768_PIN_INTERRUPT_M(V_MIN_PIN) + #error "V_MIN_PIN is not INTERRUPT-capable." + #endif + _ATTACH(V_MIN_PIN); + #endif + #if HAS_W_MAX + #if !LPC1768_PIN_INTERRUPT_M(W_MAX_PIN) + #error "W_MAX_PIN is not INTERRUPT-capable." + #endif + _ATTACH(W_MAX_PIN); + #elif HAS_W_MIN + #if !LPC1768_PIN_INTERRUPT_M(W_MIN_PIN) + #error "W_MIN_PIN is not INTERRUPT-capable." + #endif + _ATTACH(W_MIN_PIN); + #endif } diff --git a/Marlin/src/HAL/LPC1768/include/digipot_mcp4451_I2C_routines.c b/Marlin/src/HAL/LPC1768/include/digipot_mcp4451_I2C_routines.c index f442ab71c0..c489c16e5e 100644 --- a/Marlin/src/HAL/LPC1768/include/digipot_mcp4451_I2C_routines.c +++ b/Marlin/src/HAL/LPC1768/include/digipot_mcp4451_I2C_routines.c @@ -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 diff --git a/Marlin/src/HAL/LPC1768/include/i2c_util.c b/Marlin/src/HAL/LPC1768/include/i2c_util.c index e52fb7c4de..4e24f23236 100644 --- a/Marlin/src/HAL/LPC1768/include/i2c_util.c +++ b/Marlin/src/HAL/LPC1768/include/i2c_util.c @@ -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 diff --git a/Marlin/src/HAL/LPC1768/include/i2c_util.h b/Marlin/src/HAL/LPC1768/include/i2c_util.h index a57f68a407..1f1c19f279 100644 --- a/Marlin/src/HAL/LPC1768/include/i2c_util.h +++ b/Marlin/src/HAL/LPC1768/include/i2c_util.h @@ -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 diff --git a/Marlin/src/HAL/LPC1768/u8g/LCD_I2C_routines.cpp b/Marlin/src/HAL/LPC1768/u8g/LCD_I2C_routines.cpp index a48a820dc4..e714c3c16d 100644 --- a/Marlin/src/HAL/LPC1768/u8g/LCD_I2C_routines.cpp +++ b/Marlin/src/HAL/LPC1768/u8g/LCD_I2C_routines.cpp @@ -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 diff --git a/Marlin/src/HAL/SAMD51/endstop_interrupts.h b/Marlin/src/HAL/SAMD51/endstop_interrupts.h index 61a06c0d4b..2f02f404f5 100644 --- a/Marlin/src/HAL/SAMD51/endstop_interrupts.h +++ b/Marlin/src/HAL/SAMD51/endstop_interrupts.h @@ -60,6 +60,12 @@ #define MATCH_J_MIN_EILINE(P) TERN0(HAS_J_MIN, DEFER4(MATCH_EILINE)(P, J_MIN_PIN)) #define MATCH_K_MAX_EILINE(P) TERN0(HAS_K_MAX, DEFER4(MATCH_EILINE)(P, K_MAX_PIN)) #define MATCH_K_MIN_EILINE(P) TERN0(HAS_K_MIN, DEFER4(MATCH_EILINE)(P, K_MIN_PIN)) +#define MATCH_U_MAX_EILINE(P) TERN0(HAS_U_MAX, DEFER4(MATCH_EILINE)(P, U_MAX_PIN)) +#define MATCH_U_MIN_EILINE(P) TERN0(HAS_U_MIN, DEFER4(MATCH_EILINE)(P, U_MIN_PIN)) +#define MATCH_V_MAX_EILINE(P) TERN0(HAS_V_MAX, DEFER4(MATCH_EILINE)(P, V_MAX_PIN)) +#define MATCH_V_MIN_EILINE(P) TERN0(HAS_V_MIN, DEFER4(MATCH_EILINE)(P, V_MIN_PIN)) +#define MATCH_W_MAX_EILINE(P) TERN0(HAS_W_MAX, DEFER4(MATCH_EILINE)(P, W_MAX_PIN)) +#define MATCH_W_MIN_EILINE(P) TERN0(HAS_W_MIN, DEFER4(MATCH_EILINE)(P, W_MIN_PIN)) #define MATCH_Z2_MAX_EILINE(P) TERN0(HAS_Z2_MAX, DEFER4(MATCH_EILINE)(P, Z2_MAX_PIN)) #define MATCH_Z2_MIN_EILINE(P) TERN0(HAS_Z2_MIN, DEFER4(MATCH_EILINE)(P, Z2_MIN_PIN)) #define MATCH_Z3_MAX_EILINE(P) TERN0(HAS_Z3_MAX, DEFER4(MATCH_EILINE)(P, Z3_MAX_PIN)) @@ -75,6 +81,9 @@ && !MATCH_I_MAX_EILINE(P) && !MATCH_I_MIN_EILINE(P) \ && !MATCH_J_MAX_EILINE(P) && !MATCH_J_MIN_EILINE(P) \ && !MATCH_K_MAX_EILINE(P) && !MATCH_K_MIN_EILINE(P) \ + && !MATCH_U_MAX_EILINE(P) && !MATCH_U_MIN_EILINE(P) \ + && !MATCH_V_MAX_EILINE(P) && !MATCH_V_MIN_EILINE(P) \ + && !MATCH_W_MAX_EILINE(P) && !MATCH_W_MIN_EILINE(P) \ && !MATCH_Z2_MAX_EILINE(P) && !MATCH_Z2_MIN_EILINE(P) \ && !MATCH_Z3_MAX_EILINE(P) && !MATCH_Z3_MIN_EILINE(P) \ && !MATCH_Z4_MAX_EILINE(P) && !MATCH_Z4_MIN_EILINE(P) \ @@ -199,4 +208,40 @@ void setup_endstop_interrupts() { #endif attachInterrupt(K_MIN_PIN, endstop_ISR, CHANGE); #endif + #if HAS_U_MAX + #if !AVAILABLE_EILINE(U_MAX_PIN) + #error "U_MAX_PIN has no EXTINT line available." + #endif + attachInterrupt(U_MAX_PIN, endstop_ISR, CHANGE); + #endif + #if HAS_U_MIN + #if !AVAILABLE_EILINE(U_MIN_PIN) + #error "U_MIN_PIN has no EXTINT line available." + #endif + attachInterrupt(U_MIN_PIN, endstop_ISR, CHANGE); + #endif + #if HAS_V_MAX + #if !AVAILABLE_EILINE(V_MAX_PIN) + #error "V_MAX_PIN has no EXTINT line available." + #endif + attachInterrupt(V_MAX_PIN, endstop_ISR, CHANGE); + #endif + #if HAS_V_MIN + #if !AVAILABLE_EILINE(V_MIN_PIN) + #error "V_MIN_PIN has no EXTINT line available." + #endif + attachInterrupt(V_MIN_PIN, endstop_ISR, CHANGE); + #endif + #if HAS_W_MAX + #if !AVAILABLE_EILINE(W_MAX_PIN) + #error "W_MAX_PIN has no EXTINT line available." + #endif + attachInterrupt(W_MAX_PIN, endstop_ISR, CHANGE); + #endif + #if HAS_W_MIN + #if !AVAILABLE_EILINE(W_MIN_PIN) + #error "W_MIN_PIN has no EXTINT line available." + #endif + attachInterrupt(W_MIN_PIN, endstop_ISR, CHANGE); + #endif } diff --git a/Marlin/src/HAL/STM32/endstop_interrupts.h b/Marlin/src/HAL/STM32/endstop_interrupts.h index 90870881fe..d2f20ba1c7 100644 --- a/Marlin/src/HAL/STM32/endstop_interrupts.h +++ b/Marlin/src/HAL/STM32/endstop_interrupts.h @@ -52,4 +52,10 @@ void setup_endstop_interrupts() { TERN_(HAS_J_MIN, _ATTACH(J_MIN_PIN)); TERN_(HAS_K_MAX, _ATTACH(K_MAX_PIN)); TERN_(HAS_K_MIN, _ATTACH(K_MIN_PIN)); + TERN_(HAS_U_MAX, _ATTACH(U_MAX_PIN)); + TERN_(HAS_U_MIN, _ATTACH(U_MIN_PIN)); + TERN_(HAS_V_MAX, _ATTACH(V_MAX_PIN)); + TERN_(HAS_V_MIN, _ATTACH(V_MIN_PIN)); + TERN_(HAS_W_MAX, _ATTACH(W_MAX_PIN)); + TERN_(HAS_W_MIN, _ATTACH(W_MIN_PIN)); } diff --git a/Marlin/src/HAL/STM32F1/HAL.cpp b/Marlin/src/HAL/STM32F1/HAL.cpp index 1d58b106ad..636dc742fc 100644 --- a/Marlin/src/HAL/STM32F1/HAL.cpp +++ b/Marlin/src/HAL/STM32F1/HAL.cpp @@ -335,7 +335,7 @@ void MarlinHAL::adc_start(const pin_t pin) { _TCASE(POWER_MONITOR_CURRENT, POWER_MONITOR_CURRENT_PIN, POWERMON_CURRENT) _TCASE(POWER_MONITOR_VOLTAGE, POWER_MONITOR_VOLTAGE_PIN, POWERMON_VOLTS) } - adc_result = adc_results[(int)pin_index] >> (12 - HAL_ADC_RESOLUTION); // shift out unused bits + adc_result = (adc_results[(int)pin_index] & 0xFFF) >> (12 - HAL_ADC_RESOLUTION); // shift out unused bits } #endif // __STM32F1__ diff --git a/Marlin/src/HAL/STM32F1/HAL.h b/Marlin/src/HAL/STM32F1/HAL.h index 8fbb43c602..ceb17b4884 100644 --- a/Marlin/src/HAL/STM32F1/HAL.h +++ b/Marlin/src/HAL/STM32F1/HAL.h @@ -177,7 +177,7 @@ typedef int8_t pin_t; // ------------------------ #define CRITICAL_SECTION_START() const bool irqon = !__get_primask(); (void)__iCliRetVal() -#define CRITICAL_SECTION_END() if (!primask) (void)__iSeiRetVal() +#define CRITICAL_SECTION_END() if (!irqon) (void)__iSeiRetVal() #define cli() noInterrupts() #define sei() interrupts() diff --git a/Marlin/src/HAL/STM32F1/endstop_interrupts.h b/Marlin/src/HAL/STM32F1/endstop_interrupts.h index 4d7edb9496..a1ef8a8c3a 100644 --- a/Marlin/src/HAL/STM32F1/endstop_interrupts.h +++ b/Marlin/src/HAL/STM32F1/endstop_interrupts.h @@ -77,4 +77,10 @@ void setup_endstop_interrupts() { TERN_(HAS_J_MIN, _ATTACH(J_MIN_PIN)); TERN_(HAS_K_MAX, _ATTACH(K_MAX_PIN)); TERN_(HAS_K_MIN, _ATTACH(K_MIN_PIN)); + TERN_(HAS_U_MAX, _ATTACH(U_MAX_PIN)); + TERN_(HAS_U_MIN, _ATTACH(U_MIN_PIN)); + TERN_(HAS_V_MAX, _ATTACH(V_MAX_PIN)); + TERN_(HAS_V_MIN, _ATTACH(V_MIN_PIN)); + TERN_(HAS_W_MAX, _ATTACH(W_MAX_PIN)); + TERN_(HAS_W_MIN, _ATTACH(W_MIN_PIN)); } diff --git a/Marlin/src/HAL/TEENSY31_32/endstop_interrupts.h b/Marlin/src/HAL/TEENSY31_32/endstop_interrupts.h index 9c7e210488..c1bbcb121b 100644 --- a/Marlin/src/HAL/TEENSY31_32/endstop_interrupts.h +++ b/Marlin/src/HAL/TEENSY31_32/endstop_interrupts.h @@ -70,4 +70,10 @@ void setup_endstop_interrupts() { TERN_(HAS_J_MIN, _ATTACH(J_MIN_PIN)); TERN_(HAS_K_MAX, _ATTACH(K_MAX_PIN)); TERN_(HAS_K_MIN, _ATTACH(K_MIN_PIN)); + TERN_(HAS_U_MAX, _ATTACH(U_MAX_PIN)); + TERN_(HAS_U_MIN, _ATTACH(U_MIN_PIN)); + TERN_(HAS_V_MAX, _ATTACH(V_MAX_PIN)); + TERN_(HAS_V_MIN, _ATTACH(V_MIN_PIN)); + TERN_(HAS_W_MAX, _ATTACH(W_MAX_PIN)); + TERN_(HAS_W_MIN, _ATTACH(W_MIN_PIN)); } diff --git a/Marlin/src/HAL/TEENSY31_32/inc/SanityCheck.h b/Marlin/src/HAL/TEENSY31_32/inc/SanityCheck.h index 1efa76b1e9..dbce187673 100644 --- a/Marlin/src/HAL/TEENSY31_32/inc/SanityCheck.h +++ b/Marlin/src/HAL/TEENSY31_32/inc/SanityCheck.h @@ -40,3 +40,7 @@ #if ENABLED(POSTMORTEM_DEBUGGING) #error "POSTMORTEM_DEBUGGING is not yet supported on Teensy 3.1/3.2." #endif + +#if USING_PULLDOWNS + #error "PULLDOWN pin mode is not available on Teensy 3.1/3.2 boards." +#endif diff --git a/Marlin/src/HAL/TEENSY35_36/endstop_interrupts.h b/Marlin/src/HAL/TEENSY35_36/endstop_interrupts.h index a300248885..48d3bbbfa1 100644 --- a/Marlin/src/HAL/TEENSY35_36/endstop_interrupts.h +++ b/Marlin/src/HAL/TEENSY35_36/endstop_interrupts.h @@ -69,4 +69,10 @@ void setup_endstop_interrupts() { TERN_(HAS_J_MIN, _ATTACH(J_MIN_PIN)); TERN_(HAS_K_MAX, _ATTACH(K_MAX_PIN)); TERN_(HAS_K_MIN, _ATTACH(K_MIN_PIN)); + TERN_(HAS_U_MAX, _ATTACH(U_MAX_PIN)); + TERN_(HAS_U_MIN, _ATTACH(U_MIN_PIN)); + TERN_(HAS_V_MAX, _ATTACH(V_MAX_PIN)); + TERN_(HAS_V_MIN, _ATTACH(V_MIN_PIN)); + TERN_(HAS_W_MAX, _ATTACH(W_MAX_PIN)); + TERN_(HAS_W_MIN, _ATTACH(W_MIN_PIN)); } diff --git a/Marlin/src/HAL/TEENSY35_36/inc/SanityCheck.h b/Marlin/src/HAL/TEENSY35_36/inc/SanityCheck.h index eef2850550..3308707371 100644 --- a/Marlin/src/HAL/TEENSY35_36/inc/SanityCheck.h +++ b/Marlin/src/HAL/TEENSY35_36/inc/SanityCheck.h @@ -40,3 +40,7 @@ #if ENABLED(POSTMORTEM_DEBUGGING) #error "POSTMORTEM_DEBUGGING is not yet supported on Teensy 3.5/3.6." #endif + +#if USING_PULLDOWNS + #error "PULLDOWN pin mode is not available on Teensy 3.5/3.6 boards." +#endif diff --git a/Marlin/src/MarlinCore.cpp b/Marlin/src/MarlinCore.cpp index 81dc7db4cc..2570e6ebde 100644 --- a/Marlin/src/MarlinCore.cpp +++ b/Marlin/src/MarlinCore.cpp @@ -74,7 +74,7 @@ #include "lcd/e3v2/common/encoder.h" #if ENABLED(DWIN_CREALITY_LCD) #include "lcd/e3v2/creality/dwin.h" - #elif ENABLED(DWIN_CREALITY_LCD_ENHANCED) + #elif ENABLED(DWIN_LCD_PROUI) #include "lcd/e3v2/proui/dwin.h" #elif ENABLED(DWIN_CREALITY_LCD_JYERSUI) #include "lcd/e3v2/jyersui/dwin.h" @@ -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()); @@ -476,7 +479,7 @@ inline void manage_inactivity(const bool no_stepper_sleep=false) { #endif #if HAS_FREEZE_PIN - Stepper::frozen = !READ(FREEZE_PIN); + stepper.frozen = READ(FREEZE_PIN) == FREEZE_STATE; #endif #if HAS_HOME @@ -822,7 +825,7 @@ void idle(bool no_stepper_sleep/*=false*/) { TERN_(USE_BEEPER, buzzer.tick()); // Handle UI input / draw events - TERN(HAS_DWIN_E3V2_BASIC, DWIN_Update(), ui.update()); + TERN(DWIN_CREALITY_LCD, DWIN_Update(), ui.update()); // Run i2c Position Encoders #if ENABLED(I2C_POSITION_ENCODERS) @@ -878,7 +881,7 @@ void kill(FSTR_P const lcd_error/*=nullptr*/, FSTR_P const lcd_component/*=nullp // Echo the LCD message to serial for extra context if (lcd_error) { SERIAL_ECHO_START(); SERIAL_ECHOLNF(lcd_error); } - #if EITHER(HAS_DISPLAY, DWIN_CREALITY_LCD_ENHANCED) + #if EITHER(HAS_DISPLAY, DWIN_LCD_PROUI) ui.kill_screen(lcd_error ?: GET_TEXT_F(MSG_KILLED), lcd_component ?: FPSTR(NUL_STR)); #else UNUSED(lcd_error); UNUSED(lcd_component); @@ -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 @@ -1166,9 +1178,13 @@ void setup() { #endif #endif - #if HAS_FREEZE_PIN + #if ENABLED(FREEZE_FEATURE) SETUP_LOG("FREEZE_PIN"); - SET_INPUT_PULLUP(FREEZE_PIN); + #if FREEZE_STATE + SET_INPUT_PULLDOWN(FREEZE_PIN); + #else + SET_INPUT_PULLUP(FREEZE_PIN); + #endif #endif #if HAS_SUICIDE @@ -1571,11 +1587,7 @@ void setup() { #endif #if HAS_DWIN_E3V2_BASIC - SETUP_LOG("E3V2 Init"); - Encoder_Configuration(); - HMI_Init(); - HMI_SetLanguageCache(); - HMI_StartFrame(true); + SETUP_RUN(DWIN_InitScreen()); #endif #if HAS_SERVICE_INTERVALS && !HAS_DWIN_E3V2_BASIC diff --git a/Marlin/src/core/boards.h b/Marlin/src/core/boards.h index 3ec24e7760..d1cc971e51 100644 --- a/Marlin/src/core/boards.h +++ b/Marlin/src/core/boards.h @@ -364,6 +364,7 @@ #define BOARD_ZONESTAR_ZM3E4 4061 // Zonestar ZM3E4 V1 (STM32F103VC) #define BOARD_ZONESTAR_ZM3E4V2 4062 // Zonestar ZM3E4 V2 (STM32F103VC) #define BOARD_ERYONE_ERY32_MINI 4063 // Eryone Ery32 mini (STM32F103VE) +#define BOARD_PANDA_PI_V29 4064 // Panda Pi V2.9 - Standalone (STM32F103RC) // // ARM Cortex-M4F diff --git a/Marlin/src/core/drivers.h b/Marlin/src/core/drivers.h index 2e66cc9201..80262d513f 100644 --- a/Marlin/src/core/drivers.h +++ b/Marlin/src/core/drivers.h @@ -63,6 +63,9 @@ #define AXIS_DRIVER_TYPE_I(T) _AXIS_DRIVER_TYPE(I,T) #define AXIS_DRIVER_TYPE_J(T) _AXIS_DRIVER_TYPE(J,T) #define AXIS_DRIVER_TYPE_K(T) _AXIS_DRIVER_TYPE(K,T) +#define AXIS_DRIVER_TYPE_U(T) _AXIS_DRIVER_TYPE(U,T) +#define AXIS_DRIVER_TYPE_V(T) _AXIS_DRIVER_TYPE(V,T) +#define AXIS_DRIVER_TYPE_W(T) _AXIS_DRIVER_TYPE(W,T) #define AXIS_DRIVER_TYPE_X2(T) (EITHER(X_DUAL_STEPPER_DRIVERS, DUAL_X_CARRIAGE) && _AXIS_DRIVER_TYPE(X2,T)) #define AXIS_DRIVER_TYPE_Y2(T) (ENABLED(Y_DUAL_STEPPER_DRIVERS) && _AXIS_DRIVER_TYPE(Y2,T)) @@ -87,6 +90,7 @@ #define HAS_DRIVER(T) ( AXIS_DRIVER_TYPE_X(T) || AXIS_DRIVER_TYPE_Y(T) || AXIS_DRIVER_TYPE_Z(T) \ || AXIS_DRIVER_TYPE_I(T) || AXIS_DRIVER_TYPE_J(T) || AXIS_DRIVER_TYPE_K(T) \ + || AXIS_DRIVER_TYPE_U(T) || AXIS_DRIVER_TYPE_V(T) || AXIS_DRIVER_TYPE_W(T) \ || AXIS_DRIVER_TYPE_X2(T) || AXIS_DRIVER_TYPE_Y2(T) || AXIS_DRIVER_TYPE_Z2(T) \ || AXIS_DRIVER_TYPE_Z3(T) || AXIS_DRIVER_TYPE_Z4(T) || HAS_E_DRIVER(T) ) @@ -161,6 +165,7 @@ || AXIS_HAS_##T(Y) || AXIS_HAS_##T(Y2) \ || AXIS_HAS_##T(Z) || AXIS_HAS_##T(Z2) || AXIS_HAS_##T(Z3) || AXIS_HAS_##T(Z4) \ || AXIS_HAS_##T(I) || AXIS_HAS_##T(J) || AXIS_HAS_##T(K) \ + || AXIS_HAS_##T(U) || AXIS_HAS_##T(V) || AXIS_HAS_##T(W) \ || E_AXIS_HAS(T) ) #if ANY_AXIS_HAS(STEALTHCHOP) @@ -200,4 +205,4 @@ #define HAS_L64XX_NOT_L6474 1 #endif -#define AXIS_IS_L64XX(A) (AXIS_DRIVER_TYPE_##A(L6470) || AXIS_DRIVER_TYPE_##A(L6474) || AXIS_DRIVER_TYPE_##A(L6480) || AXIS_DRIVER_TYPE_##A(POWERSTEP01)) +#define AXIS_IS_L64XX(A) (AXIS_DRIVER_TYPE_##A(L6470) || AXIS_DRIVER_TYPE_##A(L6474) || AXIS_DRIVER_TYPE_##A(L6480) || AXIS_DRIVER_TYPE_##A(POWERSTEP01)) diff --git a/Marlin/src/core/language.h b/Marlin/src/core/language.h index 8e0784f70d..89c0babc25 100644 --- a/Marlin/src/core/language.h +++ b/Marlin/src/core/language.h @@ -444,6 +444,54 @@ #define STR_K "" #endif +#if HAS_U_AXIS + #if AXIS7_NAME == 'U' + #define STR_U "U" + #define STR_U_MIN "u_min" + #define STR_U_MAX "u_max" + #elif AXIS7_NAME == 'V' + #define STR_U "V" + #define STR_U_MIN "v_min" + #define STR_U_MAX "v_max" + #elif AXIS7_NAME == 'W' + #define STR_U "W" + #define STR_U_MIN "w_min" + #define STR_U_MAX "w_max" + #else + #error "AXIS7_NAME can only be one of 'U', 'V', or 'W'." + #endif +#else + #define STR_U "" +#endif + +#if HAS_V_AXIS + #if AXIS8_NAME == 'V' + #define STR_V "V" + #define STR_V_MIN "v_min" + #define STR_V_MAX "v_max" + #elif AXIS8_NAME == 'W' + #define STR_V "W" + #define STR_V_MIN "w_min" + #define STR_V_MAX "w_max" + #else + #error "AXIS8_NAME can only be one of 'V', or 'W'." + #endif +#else + #define STR_V "" +#endif + +#if HAS_W_AXIS + #if AXIS9_NAME == 'W' + #define STR_W "W" + #define STR_W_MIN "w_min" + #define STR_W_MAX "w_max" + #else + #error "AXIS9_NAME can only be 'W'." + #endif +#else + #define STR_W "" +#endif + #if EITHER(HAS_MARLINUI_HD44780, IS_TFTGLCD_PANEL) // Custom characters defined in the first 8 characters of the LCD diff --git a/Marlin/src/core/macros.h b/Marlin/src/core/macros.h index 31808586cf..629486d85f 100644 --- a/Marlin/src/core/macros.h +++ b/Marlin/src/core/macros.h @@ -39,24 +39,36 @@ #define _ISTOP_ 0x04 #define _JSTOP_ 0x05 #define _KSTOP_ 0x06 +#define _USTOP_ 0x07 +#define _VSTOP_ 0x08 +#define _WSTOP_ 0x09 #define _XMIN_ 0x11 #define _YMIN_ 0x12 #define _ZMIN_ 0x13 #define _IMIN_ 0x14 #define _JMIN_ 0x15 #define _KMIN_ 0x16 +#define _UMIN_ 0x17 +#define _VMIN_ 0x18 +#define _WMIN_ 0x19 #define _XMAX_ 0x21 #define _YMAX_ 0x22 #define _ZMAX_ 0x23 #define _IMAX_ 0x24 #define _JMAX_ 0x25 #define _KMAX_ 0x26 +#define _UMAX_ 0x27 +#define _VMAX_ 0x28 +#define _WMAX_ 0x29 #define _XDIAG_ 0x31 #define _YDIAG_ 0x32 #define _ZDIAG_ 0x33 #define _IDIAG_ 0x34 #define _JDIAG_ 0x35 #define _KDIAG_ 0x36 +#define _UDIAG_ 0x37 +#define _VDIAG_ 0x38 +#define _WDIAG_ 0x39 #define _E0DIAG_ 0xE0 #define _E1DIAG_ 0xE1 #define _E2DIAG_ 0xE2 @@ -350,7 +362,7 @@ #define _LIST_N(N,V...) LIST_##N(V) #define LIST_N(N,V...) _LIST_N(N,V) -#define LIST_N_1(N,K) _LIST_N(N,K,K,K,K,K,K,K,K,K,K,K,K,K,K,K,K) +#define LIST_N_1(N,K) _LIST_N(N,K,K,K,K,K,K,K,K,K,K,K,K,K,K,K,K,K,K,K,K) #define ARRAY_N(N,V...) { _LIST_N(N,V) } #define ARRAY_N_1(N,K) { LIST_N_1(N,K) } diff --git a/Marlin/src/core/multi_language.h b/Marlin/src/core/multi_language.h index 2106f946ac..a605a6f024 100644 --- a/Marlin/src/core/multi_language.h +++ b/Marlin/src/core/multi_language.h @@ -80,6 +80,9 @@ typedef const char Language_Str[]; #endif #define GET_TEXT_F(MSG) FPSTR(GET_TEXT(MSG)) +#define GET_EN_TEXT(MSG) GET_LANG(en)::MSG +#define GET_EN_TEXT_F(MSG) FPSTR(GET_EN_TEXT(MSG)) + #define GET_LANGUAGE_NAME(INDEX) GET_LANG(LCD_LANGUAGE_##INDEX)::LANGUAGE #define LANG_CHARSIZE GET_TEXT(CHARSIZE) #define USE_WIDE_GLYPH (LANG_CHARSIZE > 2) diff --git a/Marlin/src/core/serial.cpp b/Marlin/src/core/serial.cpp index 2b1ae1f1fe..819b06968c 100644 --- a/Marlin/src/core/serial.cpp +++ b/Marlin/src/core/serial.cpp @@ -32,14 +32,18 @@ uint8_t marlin_debug_flags = MARLIN_DEBUG_NONE; // Commonly-used strings in serial output PGMSTR(NUL_STR, ""); PGMSTR(SP_P_STR, " P"); PGMSTR(SP_T_STR, " T"); PGMSTR(X_STR, "X"); PGMSTR(Y_STR, "Y"); PGMSTR(Z_STR, "Z"); PGMSTR(E_STR, "E"); +PGMSTR(U_STR, STR_U); PGMSTR(V_STR, STR_V); PGMSTR(W_STR, STR_W); PGMSTR(X_LBL, "X:"); PGMSTR(Y_LBL, "Y:"); PGMSTR(Z_LBL, "Z:"); PGMSTR(E_LBL, "E:"); +PGMSTR(U_LBL, STR_U ":"); PGMSTR(V_LBL, STR_V ":"); PGMSTR(W_LBL, STR_W ":"); PGMSTR(SP_A_STR, " A"); PGMSTR(SP_B_STR, " B"); PGMSTR(SP_C_STR, " C"); PGMSTR(SP_X_STR, " X"); PGMSTR(SP_Y_STR, " Y"); PGMSTR(SP_Z_STR, " Z"); PGMSTR(SP_E_STR, " E"); PGMSTR(SP_X_LBL, " X:"); PGMSTR(SP_Y_LBL, " Y:"); PGMSTR(SP_Z_LBL, " Z:"); PGMSTR(SP_E_LBL, " E:"); PGMSTR(I_STR, STR_I); PGMSTR(J_STR, STR_J); PGMSTR(K_STR, STR_K); PGMSTR(I_LBL, STR_I ":"); PGMSTR(J_LBL, STR_J ":"); PGMSTR(K_LBL, STR_K ":"); PGMSTR(SP_I_STR, " " STR_I); PGMSTR(SP_J_STR, " " STR_J); PGMSTR(SP_K_STR, " " STR_K); +PGMSTR(SP_U_STR, " " STR_U); PGMSTR(SP_V_STR, " " STR_V); PGMSTR(SP_W_STR, " " STR_W); PGMSTR(SP_I_LBL, " " STR_I ":"); PGMSTR(SP_J_LBL, " " STR_J ":"); PGMSTR(SP_K_LBL, " " STR_K ":"); +PGMSTR(SP_U_LBL, " " STR_U ":"); PGMSTR(SP_V_LBL, " " STR_V ":"); PGMSTR(SP_W_LBL, " " STR_W ":"); // Hook Meatpack if it's enabled on the first leaf #if ENABLED(MEATPACK_ON_SERIAL_PORT_1) @@ -78,6 +82,14 @@ void serial_error_start() { static PGMSTR(errormagic, "Error:"); serial_print_P( void serial_spaces(uint8_t count) { count *= (PROPORTIONAL_FONT_RATIO); while (count--) SERIAL_CHAR(' '); } +void serial_offset(const_float_t v, const uint8_t sp/*=0*/) { + if (v == 0 && sp == 1) + SERIAL_CHAR(' '); + else if (v > 0 || (v == 0 && sp == 2)) + SERIAL_CHAR('+'); + SERIAL_DECIMAL(v); +} + void serial_ternary(const bool onoff, FSTR_P const pre, FSTR_P const on, FSTR_P const off, FSTR_P const post/*=nullptr*/) { if (pre) serial_print(pre); serial_print(onoff ? on : off); @@ -94,10 +106,10 @@ void print_bin(uint16_t val) { } } -void print_pos(LINEAR_AXIS_ARGS(const_float_t), FSTR_P const prefix/*=nullptr*/, FSTR_P const suffix/*=nullptr*/) { +void print_pos(NUM_AXIS_ARGS(const_float_t), FSTR_P const prefix/*=nullptr*/, FSTR_P const suffix/*=nullptr*/) { if (prefix) serial_print(prefix); SERIAL_ECHOPGM_P( - LIST_N(DOUBLE(LINEAR_AXES), SP_X_STR, x, SP_Y_STR, y, SP_Z_STR, z, SP_I_STR, i, SP_J_STR, j, SP_K_STR, k) + LIST_N(DOUBLE(NUM_AXES), SP_X_STR, x, SP_Y_STR, y, SP_Z_STR, z, SP_I_STR, i, SP_J_STR, j, SP_K_STR, k, SP_U_STR, u, SP_V_STR, v, SP_W_STR, w) ); if (suffix) serial_print(suffix); else SERIAL_EOL(); } diff --git a/Marlin/src/core/serial.h b/Marlin/src/core/serial.h index aee4d4d43d..2998fe803f 100644 --- a/Marlin/src/core/serial.h +++ b/Marlin/src/core/serial.h @@ -29,17 +29,12 @@ #endif // Commonly-used strings in serial output -extern const char NUL_STR[], - SP_X_STR[], SP_Y_STR[], SP_Z_STR[], - SP_A_STR[], SP_B_STR[], SP_C_STR[], SP_E_STR[], - SP_X_LBL[], SP_Y_LBL[], SP_Z_LBL[], SP_E_LBL[], - SP_I_STR[], SP_J_STR[], SP_K_STR[], - SP_I_LBL[], SP_J_LBL[], SP_K_LBL[], - SP_P_STR[], SP_T_STR[], - X_STR[], Y_STR[], Z_STR[], E_STR[], - I_STR[], J_STR[], K_STR[], - X_LBL[], Y_LBL[], Z_LBL[], E_LBL[], - I_LBL[], J_LBL[], K_LBL[]; +extern const char NUL_STR[], SP_P_STR[], SP_T_STR[], + SP_A_STR[], SP_B_STR[], SP_C_STR[], + SP_X_STR[], SP_Y_STR[], SP_Z_STR[], SP_I_STR[], SP_J_STR[], SP_K_STR[], SP_U_STR[], SP_V_STR[], SP_W_STR[], SP_E_STR[], + SP_X_LBL[], SP_Y_LBL[], SP_Z_LBL[], SP_I_LBL[], SP_J_LBL[], SP_K_LBL[], SP_U_LBL[], SP_V_LBL[], SP_W_LBL[], SP_E_LBL[], + X_STR[], Y_STR[], Z_STR[], I_STR[], J_STR[], K_STR[], U_STR[], V_STR[], W_STR[], E_STR[], + X_LBL[], Y_LBL[], Z_LBL[], I_LBL[], J_LBL[], K_LBL[], U_LBL[], V_LBL[], W_LBL[], E_LBL[]; // // Debugging flags for use by M111 @@ -345,12 +340,13 @@ void serialprint_onoff(const bool onoff); void serialprintln_onoff(const bool onoff); void serialprint_truefalse(const bool tf); void serial_spaces(uint8_t count); +void serial_offset(const_float_t v, const uint8_t sp=0); // For v==0 draw space (sp==1) or plus (sp==2) void print_bin(const uint16_t val); -void print_pos(LINEAR_AXIS_ARGS(const_float_t), FSTR_P const prefix=nullptr, FSTR_P const suffix=nullptr); +void print_pos(NUM_AXIS_ARGS(const_float_t), FSTR_P const prefix=nullptr, FSTR_P const suffix=nullptr); inline void print_pos(const xyz_pos_t &xyz, FSTR_P const prefix=nullptr, FSTR_P const suffix=nullptr) { - print_pos(LINEAR_AXIS_ELEM(xyz), prefix, suffix); + print_pos(NUM_AXIS_ELEM(xyz), prefix, suffix); } #define SERIAL_POS(SUFFIX,VAR) do { print_pos(VAR, F(" " STRINGIFY(VAR) "="), F(" : " SUFFIX "\n")); }while(0) diff --git a/Marlin/src/core/types.h b/Marlin/src/core/types.h index b95b595659..47a126f165 100644 --- a/Marlin/src/core/types.h +++ b/Marlin/src/core/types.h @@ -36,23 +36,33 @@ struct IF { typedef R type; }; template struct IF { typedef L type; }; -#define LINEAR_AXIS_GANG(V...) GANG_N(LINEAR_AXES, V) -#define LINEAR_AXIS_CODE(V...) CODE_N(LINEAR_AXES, V) -#define LINEAR_AXIS_LIST(V...) LIST_N(LINEAR_AXES, V) -#define LINEAR_AXIS_ARRAY(V...) { LINEAR_AXIS_LIST(V) } -#define LINEAR_AXIS_ARGS(T...) LINEAR_AXIS_LIST(T x, T y, T z, T i, T j, T k) -#define LINEAR_AXIS_ELEM(O) LINEAR_AXIS_LIST(O.x, O.y, O.z, O.i, O.j, O.k) -#define LINEAR_AXIS_DEFS(T,V) LINEAR_AXIS_LIST(T x=V, T y=V, T z=V, T i=V, T j=V, T k=V) +#define 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 { typedef L type; }; #define GANG_ITEM_E(N) #endif -#define AXIS_COLLISION(L) (AXIS4_NAME == L || AXIS5_NAME == L || AXIS6_NAME == L) +#define AXIS_COLLISION(L) (AXIS4_NAME == L || AXIS5_NAME == L || AXIS6_NAME == L || AXIS7_NAME == L || AXIS8_NAME == L || AXIS9_NAME == L) // // Enumerated axis indices @@ -76,7 +86,7 @@ struct IF { typedef L type; }; enum AxisEnum : uint8_t { // Linear axes may be controlled directly or indirectly - LINEAR_AXIS_LIST(X_AXIS, Y_AXIS, Z_AXIS, I_AXIS, J_AXIS, K_AXIS) + NUM_AXIS_LIST(X_AXIS, Y_AXIS, Z_AXIS, I_AXIS, J_AXIS, K_AXIS, U_AXIS, V_AXIS, W_AXIS) // Extruder axes may be considered distinctly #define _EN_ITEM(N) , E##N##_AXIS @@ -110,14 +120,16 @@ 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) // // feedRate_t is just a humble float @@ -128,6 +140,7 @@ typedef float feedRate_t; // celsius_t is the native unit of temperature. Signed to handle a disconnected thermistor value (-14). // For more resolition (e.g., for a chocolate printer) this may later be changed to Celsius x 100 // +typedef uint16_t raw_adc_t; typedef int16_t celsius_t; typedef float celsius_float_t; @@ -258,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]; } @@ -383,60 +396,69 @@ struct XYval { template struct XYZval { union { - struct { T LINEAR_AXIS_ARGS(); }; - struct { T LINEAR_AXIS_LIST(a, b, c, u, v, w); }; - T pos[LINEAR_AXES]; + struct { T NUM_AXIS_ARGS(); }; + struct { T NUM_AXIS_LIST(a, b, c, _i, _j, _k, _u, _v, _w); }; + T pos[NUM_AXES]; }; // Set all to 0 - FI void reset() { LINEAR_AXIS_GANG(x =, y =, z =, i =, j =, k =) 0; } + FI void reset() { NUM_AXIS_GANG(x =, y =, z =, i =, j =, k =, u =, v =, w =) 0; } // Setters taking struct types and arrays FI void set(const T px) { x = px; } FI void set(const T px, const T py) { x = px; y = py; } FI void set(const XYval pxy) { x = pxy.x; y = pxy.y; } - FI void set(const XYval pxy, const T pz) { LINEAR_AXIS_CODE(x = pxy.x, y = pxy.y, z = pz, NOOP, NOOP, NOOP); } + FI void set(const XYval pxy, const T pz) { NUM_AXIS_CODE(x = pxy.x, y = pxy.y, z = pz, NOOP, NOOP, NOOP, NOOP, NOOP, NOOP); } FI void set(const T (&arr)[XY]) { x = arr[0]; y = arr[1]; } #if HAS_Z_AXIS - FI void set(const T (&arr)[LINEAR_AXES]) { LINEAR_AXIS_CODE(x = arr[0], y = arr[1], z = arr[2], i = arr[3], j = arr[4], k = arr[5]); } - FI void set(LINEAR_AXIS_ARGS(const T)) { LINEAR_AXIS_CODE(a = x, b = y, c = z, u = i, v = j, w = k ); } + FI void set(const T (&arr)[NUM_AXES]) { NUM_AXIS_CODE(x = arr[0], y = arr[1], z = arr[2], i = arr[3], j = arr[4], k = arr[5], u = arr[6], v = arr[7], w = arr[8]); } + FI void set(NUM_AXIS_ARGS(const T)) { NUM_AXIS_CODE(a = x, b = y, c = z, _i = i, _j = j, _k = k, _u = u, _v = v, _w = w ); } #endif - #if LOGICAL_AXES > LINEAR_AXES - FI void set(const T (&arr)[LOGICAL_AXES]) { LINEAR_AXIS_CODE(x = arr[0], y = arr[1], z = arr[2], i = arr[3], j = arr[4], k = arr[5]); } - FI void set(LOGICAL_AXIS_ARGS(const T)) { LINEAR_AXIS_CODE(a = x, b = y, c = z, u = i, v = j, w = k ); } + #if LOGICAL_AXES > NUM_AXES + FI void set(const T (&arr)[LOGICAL_AXES]) { NUM_AXIS_CODE(x = arr[0], y = arr[1], z = arr[2], i = arr[3], j = arr[4], k = arr[5], u = arr[6], v = arr[7], w = arr[8]); } + FI void set(LOGICAL_AXIS_ARGS(const T)) { NUM_AXIS_CODE(a = x, b = y, c = z, _i = i, _j = j, _k = k, _u = u, _v = v, _w = w ); } #if DISTINCT_AXES > LOGICAL_AXES - FI void set(const T (&arr)[DISTINCT_AXES]) { LINEAR_AXIS_CODE(x = arr[0], y = arr[1], z = arr[2], i = arr[3], j = arr[4], k = arr[5]); } + FI void set(const T (&arr)[DISTINCT_AXES]) { NUM_AXIS_CODE(x = arr[0], y = arr[1], z = arr[2], i = arr[3], j = arr[4], k = arr[5], u = arr[6], v = arr[7], w = arr[8]); } #endif #endif #if HAS_I_AXIS - FI void set(const T px, const T py, const T pz) { x = px; y = py; z = pz; } + FI void set(const T px, const T py, const T pz) { x = px; y = py; z = pz; } #endif #if HAS_J_AXIS - FI void set(const T px, const T py, const T pz, const T pi) { x = px; y = py; z = pz; i = pi; } + FI void set(const T px, const T py, const T pz, const T pi) { x = px; y = py; z = pz; i = pi; } #endif #if HAS_K_AXIS FI void set(const T px, const T py, const T pz, const T pi, const T pj) { x = px; y = py; z = pz; i = pi; j = pj; } #endif + #if HAS_U_AXIS + FI void set(const T px, const T py, const T pz, const T pi, const T pj, const T pk) { x = px; y = py; z = pz; i = pi; j = pj; k = pk; } + #endif + #if HAS_V_AXIS + FI void set(const T px, const T py, const T pz, const T pi, const T pj, const T pk, const T pm) { x = px; y = py; z = pz; i = pi; j = pj; k = pk; u = pu; } + #endif + #if HAS_W_AXIS + FI void set(const T px, const T py, const T pz, const T pi, const T pj, const T pk, const T pm, const T po) { x = px; y = py; z = pz; i = pi; j = pj; k = pk; u = pu; v = pv; } + #endif // Length reduced to one dimension - FI T magnitude() const { return (T)sqrtf(LINEAR_AXIS_GANG(x*x, + y*y, + z*z, + i*i, + j*j, + k*k)); } + FI T magnitude() const { return (T)sqrtf(NUM_AXIS_GANG(x*x, + y*y, + z*z, + i*i, + j*j, + k*k, + u*u, + v*v, + w*w)); } // Pointer to the data as a simple array FI operator T* () { return pos; } // If any element is true then it's true - FI operator bool() { return LINEAR_AXIS_GANG(x, || y, || z, || i, || j, || k); } + FI operator bool() { return NUM_AXIS_GANG(x, || y, || z, || i, || j, || k, || u, || v, || w); } // Explicit copy and copies with conversion FI XYZval copy() const { XYZval o = *this; return o; } - FI XYZval ABS() const { return LINEAR_AXIS_ARRAY(T(_ABS(x)), T(_ABS(y)), T(_ABS(z)), T(_ABS(i)), T(_ABS(j)), T(_ABS(k))); } - FI XYZval asInt() { return LINEAR_AXIS_ARRAY(int16_t(x), int16_t(y), int16_t(z), int16_t(i), int16_t(j), int16_t(k)); } - FI XYZval asInt() const { return LINEAR_AXIS_ARRAY(int16_t(x), int16_t(y), int16_t(z), int16_t(i), int16_t(j), int16_t(k)); } - FI XYZval asLong() { return LINEAR_AXIS_ARRAY(int32_t(x), int32_t(y), int32_t(z), int32_t(i), int32_t(j), int32_t(k)); } - FI XYZval asLong() const { return LINEAR_AXIS_ARRAY(int32_t(x), int32_t(y), int32_t(z), int32_t(i), int32_t(j), int32_t(k)); } - FI XYZval ROUNDL() { return LINEAR_AXIS_ARRAY(int32_t(LROUND(x)), int32_t(LROUND(y)), int32_t(LROUND(z)), int32_t(LROUND(i)), int32_t(LROUND(j)), int32_t(LROUND(k))); } - FI XYZval ROUNDL() const { return LINEAR_AXIS_ARRAY(int32_t(LROUND(x)), int32_t(LROUND(y)), int32_t(LROUND(z)), int32_t(LROUND(i)), int32_t(LROUND(j)), int32_t(LROUND(k))); } - FI XYZval asFloat() { return LINEAR_AXIS_ARRAY(static_cast(x), static_cast(y), static_cast(z), static_cast(i), static_cast(j), static_cast(k)); } - FI XYZval asFloat() const { return LINEAR_AXIS_ARRAY(static_cast(x), static_cast(y), static_cast(z), static_cast(i), static_cast(j), static_cast(k)); } - FI XYZval reciprocal() const { return LINEAR_AXIS_ARRAY(_RECIP(x), _RECIP(y), _RECIP(z), _RECIP(i), _RECIP(j), _RECIP(k)); } + FI XYZval ABS() const { return NUM_AXIS_ARRAY(T(_ABS(x)), T(_ABS(y)), T(_ABS(z)), T(_ABS(i)), T(_ABS(j)), T(_ABS(k)), T(_ABS(u)), T(_ABS(v)), T(_ABS(w))); } + FI XYZval asInt() { return NUM_AXIS_ARRAY(int16_t(x), int16_t(y), int16_t(z), int16_t(i), int16_t(j), int16_t(k), int16_t(u), int16_t(v), int16_t(w)); } + FI XYZval asInt() const { return NUM_AXIS_ARRAY(int16_t(x), int16_t(y), int16_t(z), int16_t(i), int16_t(j), int16_t(k), int16_t(u), int16_t(v), int16_t(w)); } + FI XYZval asLong() { return NUM_AXIS_ARRAY(int32_t(x), int32_t(y), int32_t(z), int32_t(i), int32_t(j), int32_t(k), int32_t(u), int32_t(v), int32_t(w)); } + FI XYZval asLong() const { return NUM_AXIS_ARRAY(int32_t(x), int32_t(y), int32_t(z), int32_t(i), int32_t(j), int32_t(k), int32_t(u), int32_t(v), int32_t(w)); } + FI XYZval ROUNDL() { return NUM_AXIS_ARRAY(int32_t(LROUND(x)), int32_t(LROUND(y)), int32_t(LROUND(z)), int32_t(LROUND(i)), int32_t(LROUND(j)), int32_t(LROUND(k)), int32_t(LROUND(u)), int32_t(LROUND(v)), int32_t(LROUND(w))); } + FI XYZval ROUNDL() const { return NUM_AXIS_ARRAY(int32_t(LROUND(x)), int32_t(LROUND(y)), int32_t(LROUND(z)), int32_t(LROUND(i)), int32_t(LROUND(j)), int32_t(LROUND(k)), int32_t(LROUND(u)), int32_t(LROUND(v)), int32_t(LROUND(w))); } + FI XYZval asFloat() { return NUM_AXIS_ARRAY(static_cast(x), static_cast(y), static_cast(z), static_cast(i), static_cast(j), static_cast(k), static_cast(u), static_cast(v), static_cast(w)); } + FI XYZval asFloat() const { return NUM_AXIS_ARRAY(static_cast(x), static_cast(y), static_cast(z), static_cast(i), static_cast(j), static_cast(k), static_cast(u), static_cast(v), static_cast(w)); } + FI XYZval reciprocal() const { return NUM_AXIS_ARRAY(_RECIP(x), _RECIP(y), _RECIP(z), _RECIP(i), _RECIP(j), _RECIP(k), _RECIP(u), _RECIP(v), _RECIP(w)); } // Marlin workspace shifting is done with G92 and M206 FI XYZval asLogical() const { XYZval o = asFloat(); toLogical(o); return o; } @@ -447,78 +469,78 @@ struct XYZval { FI operator const XYval&() const { return *(const XYval*)this; } // Cast to a type with more fields by making a new object - FI operator XYZEval() const { return LINEAR_AXIS_ARRAY(x, y, z, i, j, k); } + FI operator XYZEval() const { return NUM_AXIS_ARRAY(x, y, z, i, j, k, u, v, w); } // Accessor via an AxisEnum (or any integer) [index] FI T& operator[](const int n) { return pos[n]; } FI const T& operator[](const int n) const { return pos[n]; } // Assignment operator overrides do the expected thing - FI XYZval& operator= (const T v) { set(ARRAY_N_1(LINEAR_AXES, v)); return *this; } + FI XYZval& operator= (const T v) { set(ARRAY_N_1(NUM_AXES, v)); return *this; } FI XYZval& operator= (const XYval &rs) { set(rs.x, rs.y ); return *this; } - FI XYZval& operator= (const XYZEval &rs) { set(LINEAR_AXIS_ELEM(rs)); return *this; } + FI XYZval& operator= (const XYZEval &rs) { set(NUM_AXIS_ELEM(rs)); return *this; } // Override other operators to get intuitive behaviors - FI XYZval operator+ (const XYval &rs) const { XYZval ls = *this; LINEAR_AXIS_CODE(ls.x += rs.x, ls.y += rs.y, NOOP , NOOP , NOOP , NOOP ); return ls; } - FI XYZval operator+ (const XYval &rs) { XYZval ls = *this; LINEAR_AXIS_CODE(ls.x += rs.x, ls.y += rs.y, NOOP , NOOP , NOOP , NOOP ); return ls; } - FI XYZval operator- (const XYval &rs) const { XYZval ls = *this; LINEAR_AXIS_CODE(ls.x -= rs.x, ls.y -= rs.y, NOOP , NOOP , NOOP , NOOP ); return ls; } - FI XYZval operator- (const XYval &rs) { XYZval ls = *this; LINEAR_AXIS_CODE(ls.x -= rs.x, ls.y -= rs.y, NOOP , NOOP , NOOP , NOOP ); return ls; } - FI XYZval operator* (const XYval &rs) const { XYZval ls = *this; LINEAR_AXIS_CODE(ls.x *= rs.x, ls.y *= rs.y, NOOP , NOOP , NOOP , NOOP ); return ls; } - FI XYZval operator* (const XYval &rs) { XYZval ls = *this; LINEAR_AXIS_CODE(ls.x *= rs.x, ls.y *= rs.y, NOOP , NOOP , NOOP , NOOP ); return ls; } - FI XYZval operator/ (const XYval &rs) const { XYZval ls = *this; LINEAR_AXIS_CODE(ls.x /= rs.x, ls.y /= rs.y, NOOP , NOOP , NOOP , NOOP ); return ls; } - FI XYZval operator/ (const XYval &rs) { XYZval ls = *this; LINEAR_AXIS_CODE(ls.x /= rs.x, ls.y /= rs.y, NOOP , NOOP , NOOP , NOOP ); return ls; } - FI XYZval operator+ (const XYZval &rs) const { XYZval ls = *this; LINEAR_AXIS_CODE(ls.x += rs.x, ls.y += rs.y, ls.z += rs.z, ls.i += rs.i, ls.j += rs.j, ls.k += rs.k); return ls; } - FI XYZval operator+ (const XYZval &rs) { XYZval ls = *this; LINEAR_AXIS_CODE(ls.x += rs.x, ls.y += rs.y, ls.z += rs.z, ls.i += rs.i, ls.j += rs.j, ls.k += rs.k); return ls; } - FI XYZval operator- (const XYZval &rs) const { XYZval ls = *this; LINEAR_AXIS_CODE(ls.x -= rs.x, ls.y -= rs.y, ls.z -= rs.z, ls.i -= rs.i, ls.j -= rs.j, ls.k -= rs.k); return ls; } - FI XYZval operator- (const XYZval &rs) { XYZval ls = *this; LINEAR_AXIS_CODE(ls.x -= rs.x, ls.y -= rs.y, ls.z -= rs.z, ls.i -= rs.i, ls.j -= rs.j, ls.k -= rs.k); return ls; } - FI XYZval operator* (const XYZval &rs) const { XYZval ls = *this; LINEAR_AXIS_CODE(ls.x *= rs.x, ls.y *= rs.y, ls.z *= rs.z, ls.i *= rs.i, ls.j *= rs.j, ls.k *= rs.k); return ls; } - FI XYZval operator* (const XYZval &rs) { XYZval ls = *this; LINEAR_AXIS_CODE(ls.x *= rs.x, ls.y *= rs.y, ls.z *= rs.z, ls.i *= rs.i, ls.j *= rs.j, ls.k *= rs.k); return ls; } - FI XYZval operator/ (const XYZval &rs) const { XYZval ls = *this; LINEAR_AXIS_CODE(ls.x /= rs.x, ls.y /= rs.y, ls.z /= rs.z, ls.i /= rs.i, ls.j /= rs.j, ls.k /= rs.k); return ls; } - FI XYZval operator/ (const XYZval &rs) { XYZval ls = *this; LINEAR_AXIS_CODE(ls.x /= rs.x, ls.y /= rs.y, ls.z /= rs.z, ls.i /= rs.i, ls.j /= rs.j, ls.k /= rs.k); return ls; } - FI XYZval operator+ (const XYZEval &rs) const { XYZval ls = *this; LINEAR_AXIS_CODE(ls.x += rs.x, ls.y += rs.y, ls.z += rs.z, ls.i += rs.i, ls.j += rs.j, ls.k += rs.k); return ls; } - FI XYZval operator+ (const XYZEval &rs) { XYZval ls = *this; LINEAR_AXIS_CODE(ls.x += rs.x, ls.y += rs.y, ls.z += rs.z, ls.i += rs.i, ls.j += rs.j, ls.k += rs.k); return ls; } - FI XYZval operator- (const XYZEval &rs) const { XYZval ls = *this; LINEAR_AXIS_CODE(ls.x -= rs.x, ls.y -= rs.y, ls.z -= rs.z, ls.i -= rs.i, ls.j -= rs.j, ls.k -= rs.k); return ls; } - FI XYZval operator- (const XYZEval &rs) { XYZval ls = *this; LINEAR_AXIS_CODE(ls.x -= rs.x, ls.y -= rs.y, ls.z -= rs.z, ls.i -= rs.i, ls.j -= rs.j, ls.k -= rs.k); return ls; } - FI XYZval operator* (const XYZEval &rs) const { XYZval ls = *this; LINEAR_AXIS_CODE(ls.x *= rs.x, ls.y *= rs.y, ls.z *= rs.z, ls.i *= rs.i, ls.j *= rs.j, ls.k *= rs.k); return ls; } - FI XYZval operator* (const XYZEval &rs) { XYZval ls = *this; LINEAR_AXIS_CODE(ls.x *= rs.x, ls.y *= rs.y, ls.z *= rs.z, ls.i *= rs.i, ls.j *= rs.j, ls.k *= rs.k); return ls; } - FI XYZval operator/ (const XYZEval &rs) const { XYZval ls = *this; LINEAR_AXIS_CODE(ls.x /= rs.x, ls.y /= rs.y, ls.z /= rs.z, ls.i /= rs.i, ls.j /= rs.j, ls.k /= rs.k); return ls; } - FI XYZval operator/ (const XYZEval &rs) { XYZval ls = *this; LINEAR_AXIS_CODE(ls.x /= rs.x, ls.y /= rs.y, ls.z /= rs.z, ls.i /= rs.i, ls.j /= rs.j, ls.k /= rs.k); return ls; } - FI XYZval operator* (const float &v) const { XYZval ls = *this; LINEAR_AXIS_CODE(ls.x *= v, ls.y *= v, ls.z *= v, ls.i *= v, ls.j *= v, ls.k *= v ); return ls; } - FI XYZval operator* (const float &v) { XYZval ls = *this; LINEAR_AXIS_CODE(ls.x *= v, ls.y *= v, ls.z *= v, ls.i *= v, ls.j *= v, ls.k *= v ); return ls; } - FI XYZval operator* (const int &v) const { XYZval ls = *this; LINEAR_AXIS_CODE(ls.x *= v, ls.y *= v, ls.z *= v, ls.i *= v, ls.j *= v, ls.k *= v ); return ls; } - FI XYZval operator* (const int &v) { XYZval ls = *this; LINEAR_AXIS_CODE(ls.x *= v, ls.y *= v, ls.z *= v, ls.i *= v, ls.j *= v, ls.k *= v ); return ls; } - FI XYZval operator/ (const float &v) const { XYZval ls = *this; LINEAR_AXIS_CODE(ls.x /= v, ls.y /= v, ls.z /= v, ls.i /= v, ls.j /= v, ls.k /= v ); return ls; } - FI XYZval operator/ (const float &v) { XYZval ls = *this; LINEAR_AXIS_CODE(ls.x /= v, ls.y /= v, ls.z /= v, ls.i /= v, ls.j /= v, ls.k /= v ); return ls; } - FI XYZval operator/ (const int &v) const { XYZval ls = *this; LINEAR_AXIS_CODE(ls.x /= v, ls.y /= v, ls.z /= v, ls.i /= v, ls.j /= v, ls.k /= v ); return ls; } - FI XYZval operator/ (const int &v) { XYZval ls = *this; LINEAR_AXIS_CODE(ls.x /= v, ls.y /= v, ls.z /= v, ls.i /= v, ls.j /= v, ls.k /= v ); return ls; } - FI XYZval operator>>(const int &v) const { XYZval ls = *this; LINEAR_AXIS_CODE(_RS(ls.x), _RS(ls.y), _RS(ls.z), _RS(ls.i), _RS(ls.j), _RS(ls.k) ); return ls; } - FI XYZval operator>>(const int &v) { XYZval ls = *this; LINEAR_AXIS_CODE(_RS(ls.x), _RS(ls.y), _RS(ls.z), _RS(ls.i), _RS(ls.j), _RS(ls.k) ); return ls; } - FI XYZval operator<<(const int &v) const { XYZval ls = *this; LINEAR_AXIS_CODE(_LS(ls.x), _LS(ls.y), _LS(ls.z), _LS(ls.i), _LS(ls.j), _LS(ls.k) ); return ls; } - FI XYZval operator<<(const int &v) { XYZval ls = *this; LINEAR_AXIS_CODE(_LS(ls.x), _LS(ls.y), _LS(ls.z), _LS(ls.i), _LS(ls.j), _LS(ls.k) ); return ls; } - FI const XYZval operator-() const { XYZval o = *this; LINEAR_AXIS_CODE(o.x = -x, o.y = -y, o.z = -z, o.i = -i, o.j = -j, o.k = -k); return o; } - FI XYZval operator-() { XYZval o = *this; LINEAR_AXIS_CODE(o.x = -x, o.y = -y, o.z = -z, o.i = -i, o.j = -j, o.k = -k); return o; } + FI XYZval operator+ (const XYval &rs) const { XYZval ls = *this; NUM_AXIS_CODE(ls.x += rs.x, ls.y += rs.y, NOOP , NOOP , NOOP , NOOP , NOOP , NOOP , NOOP ); return ls; } + FI XYZval operator+ (const XYval &rs) { XYZval ls = *this; NUM_AXIS_CODE(ls.x += rs.x, ls.y += rs.y, NOOP , NOOP , NOOP , NOOP , NOOP , NOOP , NOOP ); return ls; } + FI XYZval operator- (const XYval &rs) const { XYZval ls = *this; NUM_AXIS_CODE(ls.x -= rs.x, ls.y -= rs.y, NOOP , NOOP , NOOP , NOOP , NOOP , NOOP , NOOP ); return ls; } + FI XYZval operator- (const XYval &rs) { XYZval ls = *this; NUM_AXIS_CODE(ls.x -= rs.x, ls.y -= rs.y, NOOP , NOOP , NOOP , NOOP , NOOP , NOOP , NOOP ); return ls; } + FI XYZval operator* (const XYval &rs) const { XYZval ls = *this; NUM_AXIS_CODE(ls.x *= rs.x, ls.y *= rs.y, NOOP , NOOP , NOOP , NOOP , NOOP , NOOP , NOOP ); return ls; } + FI XYZval operator* (const XYval &rs) { XYZval ls = *this; NUM_AXIS_CODE(ls.x *= rs.x, ls.y *= rs.y, NOOP , NOOP , NOOP , NOOP , NOOP , NOOP , NOOP ); return ls; } + FI XYZval operator/ (const XYval &rs) const { XYZval ls = *this; NUM_AXIS_CODE(ls.x /= rs.x, ls.y /= rs.y, NOOP , NOOP , NOOP , NOOP , NOOP , NOOP , NOOP ); return ls; } + FI XYZval operator/ (const XYval &rs) { XYZval ls = *this; NUM_AXIS_CODE(ls.x /= rs.x, ls.y /= rs.y, NOOP , NOOP , NOOP , NOOP , NOOP , NOOP , NOOP ); return ls; } + FI XYZval operator+ (const XYZval &rs) const { XYZval ls = *this; NUM_AXIS_CODE(ls.x += rs.x, ls.y += rs.y, ls.z += rs.z, ls.i += rs.i, ls.j += rs.j, ls.k += rs.k, ls.u += rs.u, ls.v += rs.v, ls.w += rs.w); return ls; } + FI XYZval operator+ (const XYZval &rs) { XYZval ls = *this; NUM_AXIS_CODE(ls.x += rs.x, ls.y += rs.y, ls.z += rs.z, ls.i += rs.i, ls.j += rs.j, ls.k += rs.k, ls.u += rs.u, ls.v += rs.v, ls.w += rs.w); return ls; } + FI XYZval operator- (const XYZval &rs) const { XYZval ls = *this; NUM_AXIS_CODE(ls.x -= rs.x, ls.y -= rs.y, ls.z -= rs.z, ls.i -= rs.i, ls.j -= rs.j, ls.k -= rs.k, ls.u -= rs.u, ls.v -= rs.v, ls.w -= rs.w); return ls; } + FI XYZval operator- (const XYZval &rs) { XYZval ls = *this; NUM_AXIS_CODE(ls.x -= rs.x, ls.y -= rs.y, ls.z -= rs.z, ls.i -= rs.i, ls.j -= rs.j, ls.k -= rs.k, ls.u -= rs.u, ls.v -= rs.v, ls.w -= rs.w); return ls; } + FI XYZval operator* (const XYZval &rs) const { XYZval ls = *this; NUM_AXIS_CODE(ls.x *= rs.x, ls.y *= rs.y, ls.z *= rs.z, ls.i *= rs.i, ls.j *= rs.j, ls.k *= rs.k, ls.u *= rs.u, ls.v *= rs.v, ls.w *= rs.w); return ls; } + FI XYZval operator* (const XYZval &rs) { XYZval ls = *this; NUM_AXIS_CODE(ls.x *= rs.x, ls.y *= rs.y, ls.z *= rs.z, ls.i *= rs.i, ls.j *= rs.j, ls.k *= rs.k, ls.u *= rs.u, ls.v *= rs.v, ls.w *= rs.w); return ls; } + FI XYZval operator/ (const XYZval &rs) const { XYZval ls = *this; NUM_AXIS_CODE(ls.x /= rs.x, ls.y /= rs.y, ls.z /= rs.z, ls.i /= rs.i, ls.j /= rs.j, ls.k /= rs.k, ls.u /= rs.u, ls.v /= rs.v, ls.w /= rs.w); return ls; } + FI XYZval operator/ (const XYZval &rs) { XYZval ls = *this; NUM_AXIS_CODE(ls.x /= rs.x, ls.y /= rs.y, ls.z /= rs.z, ls.i /= rs.i, ls.j /= rs.j, ls.k /= rs.k, ls.u /= rs.u, ls.v /= rs.v, ls.w /= rs.w); return ls; } + FI XYZval operator+ (const XYZEval &rs) const { XYZval ls = *this; NUM_AXIS_CODE(ls.x += rs.x, ls.y += rs.y, ls.z += rs.z, ls.i += rs.i, ls.j += rs.j, ls.k += rs.k, ls.u += rs.u, ls.v += rs.v, ls.w += rs.w); return ls; } + FI XYZval operator+ (const XYZEval &rs) { XYZval ls = *this; NUM_AXIS_CODE(ls.x += rs.x, ls.y += rs.y, ls.z += rs.z, ls.i += rs.i, ls.j += rs.j, ls.k += rs.k, ls.u += rs.u, ls.v += rs.v, ls.w += rs.w); return ls; } + FI XYZval operator- (const XYZEval &rs) const { XYZval ls = *this; NUM_AXIS_CODE(ls.x -= rs.x, ls.y -= rs.y, ls.z -= rs.z, ls.i -= rs.i, ls.j -= rs.j, ls.k -= rs.k, ls.u -= rs.u, ls.v -= rs.v, ls.w -= rs.w); return ls; } + FI XYZval operator- (const XYZEval &rs) { XYZval ls = *this; NUM_AXIS_CODE(ls.x -= rs.x, ls.y -= rs.y, ls.z -= rs.z, ls.i -= rs.i, ls.j -= rs.j, ls.k -= rs.k, ls.u -= rs.u, ls.v -= rs.v, ls.w -= rs.w); return ls; } + FI XYZval operator* (const XYZEval &rs) const { XYZval ls = *this; NUM_AXIS_CODE(ls.x *= rs.x, ls.y *= rs.y, ls.z *= rs.z, ls.i *= rs.i, ls.j *= rs.j, ls.k *= rs.k, ls.u *= rs.u, ls.v *= rs.v, ls.w *= rs.w); return ls; } + FI XYZval operator* (const XYZEval &rs) { XYZval ls = *this; NUM_AXIS_CODE(ls.x *= rs.x, ls.y *= rs.y, ls.z *= rs.z, ls.i *= rs.i, ls.j *= rs.j, ls.k *= rs.k, ls.u *= rs.u, ls.v *= rs.v, ls.w *= rs.w); return ls; } + FI XYZval operator/ (const XYZEval &rs) const { XYZval ls = *this; NUM_AXIS_CODE(ls.x /= rs.x, ls.y /= rs.y, ls.z /= rs.z, ls.i /= rs.i, ls.j /= rs.j, ls.k /= rs.k, ls.u /= rs.u, ls.v /= rs.v, ls.w /= rs.w); return ls; } + FI XYZval operator/ (const XYZEval &rs) { XYZval ls = *this; NUM_AXIS_CODE(ls.x /= rs.x, ls.y /= rs.y, ls.z /= rs.z, ls.i /= rs.i, ls.j /= rs.j, ls.k /= rs.k, ls.u /= rs.u, ls.v /= rs.v, ls.w /= rs.w); return ls; } + FI XYZval operator* (const float &v) const { XYZval ls = *this; NUM_AXIS_CODE(ls.x *= v, ls.y *= v, ls.z *= v, ls.i *= v, ls.j *= v, ls.k *= v, ls.u *= v, ls.v *= v, ls.w *= v ); return ls; } + FI XYZval operator* (const float &v) { XYZval ls = *this; NUM_AXIS_CODE(ls.x *= v, ls.y *= v, ls.z *= v, ls.i *= v, ls.j *= v, ls.k *= v, ls.u *= v, ls.v *= v, ls.w *= v ); return ls; } + FI XYZval operator* (const int &v) const { XYZval ls = *this; NUM_AXIS_CODE(ls.x *= v, ls.y *= v, ls.z *= v, ls.i *= v, ls.j *= v, ls.k *= v, ls.u *= v, ls.v *= v, ls.w *= v ); return ls; } + FI XYZval operator* (const int &v) { XYZval ls = *this; NUM_AXIS_CODE(ls.x *= v, ls.y *= v, ls.z *= v, ls.i *= v, ls.j *= v, ls.k *= v, ls.u *= v, ls.v *= v, ls.w *= v ); return ls; } + FI XYZval operator/ (const float &v) const { XYZval ls = *this; NUM_AXIS_CODE(ls.x /= v, ls.y /= v, ls.z /= v, ls.i /= v, ls.j /= v, ls.k /= v, ls.u /= v, ls.v /= v, ls.w /= v ); return ls; } + FI XYZval operator/ (const float &v) { XYZval ls = *this; NUM_AXIS_CODE(ls.x /= v, ls.y /= v, ls.z /= v, ls.i /= v, ls.j /= v, ls.k /= v, ls.u /= v, ls.v /= v, ls.w /= v ); return ls; } + FI XYZval operator/ (const int &v) const { XYZval ls = *this; NUM_AXIS_CODE(ls.x /= v, ls.y /= v, ls.z /= v, ls.i /= v, ls.j /= v, ls.k /= v, ls.u /= v, ls.v /= v, ls.w /= v ); return ls; } + FI XYZval operator/ (const int &v) { XYZval ls = *this; NUM_AXIS_CODE(ls.x /= v, ls.y /= v, ls.z /= v, ls.i /= v, ls.j /= v, ls.k /= v, ls.u /= v, ls.v /= v, ls.w /= v ); return ls; } + FI XYZval operator>>(const int &v) const { XYZval ls = *this; NUM_AXIS_CODE(_RS(ls.x), _RS(ls.y), _RS(ls.z), _RS(ls.i), _RS(ls.j), _RS(ls.k), _RS(ls.u), _RS(ls.v), _RS(ls.w) ); return ls; } + FI XYZval operator>>(const int &v) { XYZval ls = *this; NUM_AXIS_CODE(_RS(ls.x), _RS(ls.y), _RS(ls.z), _RS(ls.i), _RS(ls.j), _RS(ls.k), _RS(ls.u), _RS(ls.v), _RS(ls.w) ); return ls; } + FI XYZval operator<<(const int &v) const { XYZval ls = *this; NUM_AXIS_CODE(_LS(ls.x), _LS(ls.y), _LS(ls.z), _LS(ls.i), _LS(ls.j), _LS(ls.k), _LS(ls.u), _LS(ls.v), _LS(ls.w) ); return ls; } + FI XYZval operator<<(const int &v) { XYZval ls = *this; NUM_AXIS_CODE(_LS(ls.x), _LS(ls.y), _LS(ls.z), _LS(ls.i), _LS(ls.j), _LS(ls.k), _LS(ls.u), _LS(ls.v), _LS(ls.w) ); return ls; } + FI const XYZval operator-() const { XYZval o = *this; NUM_AXIS_CODE(o.x = -x, o.y = -y, o.z = -z, o.i = -i, o.j = -j, o.k = -k, o.u = -u, o.v = -v, o.w = -w); return o; } + FI XYZval operator-() { XYZval o = *this; NUM_AXIS_CODE(o.x = -x, o.y = -y, o.z = -z, o.i = -i, o.j = -j, o.k = -k, o.u = -u, o.v = -v, o.w = -w); return o; } // Modifier operators - FI XYZval& operator+=(const XYval &rs) { LINEAR_AXIS_CODE(x += rs.x, y += rs.y, NOOP, NOOP, NOOP, NOOP ); return *this; } - FI XYZval& operator-=(const XYval &rs) { LINEAR_AXIS_CODE(x -= rs.x, y -= rs.y, NOOP, NOOP, NOOP, NOOP ); return *this; } - FI XYZval& operator*=(const XYval &rs) { LINEAR_AXIS_CODE(x *= rs.x, y *= rs.y, NOOP, NOOP, NOOP, NOOP ); return *this; } - FI XYZval& operator/=(const XYval &rs) { LINEAR_AXIS_CODE(x /= rs.x, y /= rs.y, NOOP, NOOP, NOOP, NOOP ); return *this; } - FI XYZval& operator+=(const XYZval &rs) { LINEAR_AXIS_CODE(x += rs.x, y += rs.y, z += rs.z, i += rs.i, j += rs.j, k += rs.k); return *this; } - FI XYZval& operator-=(const XYZval &rs) { LINEAR_AXIS_CODE(x -= rs.x, y -= rs.y, z -= rs.z, i -= rs.i, j -= rs.j, k -= rs.k); return *this; } - FI XYZval& operator*=(const XYZval &rs) { LINEAR_AXIS_CODE(x *= rs.x, y *= rs.y, z *= rs.z, i *= rs.i, j *= rs.j, k *= rs.k); return *this; } - FI XYZval& operator/=(const XYZval &rs) { LINEAR_AXIS_CODE(x /= rs.x, y /= rs.y, z /= rs.z, i /= rs.i, j /= rs.j, k /= rs.k); return *this; } - FI XYZval& operator+=(const XYZEval &rs) { LINEAR_AXIS_CODE(x += rs.x, y += rs.y, z += rs.z, i += rs.i, j += rs.j, k += rs.k); return *this; } - FI XYZval& operator-=(const XYZEval &rs) { LINEAR_AXIS_CODE(x -= rs.x, y -= rs.y, z -= rs.z, i -= rs.i, j -= rs.j, k -= rs.k); return *this; } - FI XYZval& operator*=(const XYZEval &rs) { LINEAR_AXIS_CODE(x *= rs.x, y *= rs.y, z *= rs.z, i *= rs.i, j *= rs.j, k *= rs.k); return *this; } - FI XYZval& operator/=(const XYZEval &rs) { LINEAR_AXIS_CODE(x /= rs.x, y /= rs.y, z /= rs.z, i /= rs.i, j /= rs.j, k /= rs.k); return *this; } - FI XYZval& operator*=(const float &v) { LINEAR_AXIS_CODE(x *= v, y *= v, z *= v, i *= v, j *= v, k *= v); return *this; } - FI XYZval& operator*=(const int &v) { LINEAR_AXIS_CODE(x *= v, y *= v, z *= v, i *= v, j *= v, k *= v); return *this; } - FI XYZval& operator>>=(const int &v) { LINEAR_AXIS_CODE(_RS(x), _RS(y), _RS(z), _RS(i), _RS(j), _RS(k)); return *this; } - FI XYZval& operator<<=(const int &v) { LINEAR_AXIS_CODE(_LS(x), _LS(y), _LS(z), _LS(i), _LS(j), _LS(k)); return *this; } + FI XYZval& operator+=(const XYval &rs) { NUM_AXIS_CODE(x += rs.x, y += rs.y, NOOP, NOOP, NOOP, NOOP, NOOP, NOOP, NOOP ); return *this; } + FI XYZval& operator-=(const XYval &rs) { NUM_AXIS_CODE(x -= rs.x, y -= rs.y, NOOP, NOOP, NOOP, NOOP, NOOP, NOOP, NOOP ); return *this; } + FI XYZval& operator*=(const XYval &rs) { NUM_AXIS_CODE(x *= rs.x, y *= rs.y, NOOP, NOOP, NOOP, NOOP, NOOP, NOOP, NOOP ); return *this; } + FI XYZval& operator/=(const XYval &rs) { NUM_AXIS_CODE(x /= rs.x, y /= rs.y, NOOP, NOOP, NOOP, NOOP, NOOP, NOOP, NOOP ); return *this; } + FI XYZval& operator+=(const XYZval &rs) { NUM_AXIS_CODE(x += rs.x, y += rs.y, z += rs.z, i += rs.i, j += rs.j, k += rs.k, u += rs.u, v += rs.v, w += rs.w); return *this; } + FI XYZval& operator-=(const XYZval &rs) { NUM_AXIS_CODE(x -= rs.x, y -= rs.y, z -= rs.z, i -= rs.i, j -= rs.j, k -= rs.k, u -= rs.u, v -= rs.v, w -= rs.w); return *this; } + FI XYZval& operator*=(const XYZval &rs) { NUM_AXIS_CODE(x *= rs.x, y *= rs.y, z *= rs.z, i *= rs.i, j *= rs.j, k *= rs.k, u *= rs.u, v *= rs.v, w *= rs.w); return *this; } + FI XYZval& operator/=(const XYZval &rs) { NUM_AXIS_CODE(x /= rs.x, y /= rs.y, z /= rs.z, i /= rs.i, j /= rs.j, k /= rs.k, u /= rs.u, v /= rs.v, w /= rs.w); return *this; } + FI XYZval& operator+=(const XYZEval &rs) { NUM_AXIS_CODE(x += rs.x, y += rs.y, z += rs.z, i += rs.i, j += rs.j, k += rs.k, u += rs.u, v += rs.v, w += rs.w); return *this; } + FI XYZval& operator-=(const XYZEval &rs) { NUM_AXIS_CODE(x -= rs.x, y -= rs.y, z -= rs.z, i -= rs.i, j -= rs.j, k -= rs.k, u -= rs.u, v -= rs.v, w -= rs.w); return *this; } + FI XYZval& operator*=(const XYZEval &rs) { NUM_AXIS_CODE(x *= rs.x, y *= rs.y, z *= rs.z, i *= rs.i, j *= rs.j, k *= rs.k, u *= rs.u, v *= rs.v, w *= rs.w); return *this; } + FI XYZval& operator/=(const XYZEval &rs) { NUM_AXIS_CODE(x /= rs.x, y /= rs.y, z /= rs.z, i /= rs.i, j /= rs.j, k /= rs.k, u /= rs.u, v /= rs.v, w /= rs.w); return *this; } + FI XYZval& operator*=(const float &v) { NUM_AXIS_CODE(x *= v, y *= v, z *= v, i *= v, j *= v, k *= v, u *= v, v *= v, w *= v); return *this; } + FI XYZval& operator*=(const int &v) { NUM_AXIS_CODE(x *= v, y *= v, z *= v, i *= v, j *= v, k *= v, u *= v, v *= v, w *= v); return *this; } + FI XYZval& operator>>=(const int &v) { NUM_AXIS_CODE(_RS(x), _RS(y), _RS(z), _RS(i), _RS(j), _RS(k), _RS(u), _RS(v), _RS(w)); return *this; } + FI XYZval& operator<<=(const int &v) { NUM_AXIS_CODE(_LS(x), _LS(y), _LS(z), _LS(i), _LS(j), _LS(k), _LS(u), _LS(v), _LS(w)); return *this; } // Exact comparisons. For floats a "NEAR" operation may be better. - FI bool operator==(const XYZEval &rs) { return true LINEAR_AXIS_GANG(&& x == rs.x, && y == rs.y, && z == rs.z, && i == rs.i, && j == rs.j, && k == rs.k); } - FI bool operator==(const XYZEval &rs) const { return true LINEAR_AXIS_GANG(&& x == rs.x, && y == rs.y, && z == rs.z, && i == rs.i, && j == rs.j, && k == rs.k); } + FI bool operator==(const XYZEval &rs) { return true NUM_AXIS_GANG(&& x == rs.x, && y == rs.y, && z == rs.z, && i == rs.i, && j == rs.j, && k == rs.k, && u == rs.u, && v == rs.v, && w == rs.w); } + FI bool operator==(const XYZEval &rs) const { return true NUM_AXIS_GANG(&& x == rs.x, && y == rs.y, && z == rs.z, && i == rs.i, && j == rs.j, && k == rs.k, && u == rs.u, && v == rs.v, && w == rs.w); } FI bool operator!=(const XYZEval &rs) { return !operator==(rs); } FI bool operator!=(const XYZEval &rs) const { return !operator==(rs); } }; @@ -530,56 +552,66 @@ template struct XYZEval { union { struct { T LOGICAL_AXIS_ARGS(); }; - struct { T LOGICAL_AXIS_LIST(_e, a, b, c, u, v, w); }; + struct { T LOGICAL_AXIS_LIST(_e, a, b, c, _i, _j, _k, _u, _v, _w); }; T pos[LOGICAL_AXES]; }; // Reset all to 0 - FI void reset() { LOGICAL_AXIS_GANG(e =, x =, y =, z =, i =, j =, k =) 0; } + FI void reset() { LOGICAL_AXIS_GANG(e =, x =, y =, z =, i =, j =, k =, u =, v =, w =) 0; } // Setters for some number of linear axes, not all - FI void set(const T px) { x = px; } - FI void set(const T px, const T py) { x = px; y = py; } + FI void set(const T px) { x = px; } + FI void set(const T px, const T py) { x = px; y = py; } #if HAS_I_AXIS - FI void set(const T px, const T py, const T pz) { x = px; y = py; z = pz; } + FI void set(const T px, const T py, const T pz) { x = px; y = py; z = pz; } #endif #if HAS_J_AXIS - FI void set(const T px, const T py, const T pz, const T pi) { x = px; y = py; z = pz; i = pi; } + FI void set(const T px, const T py, const T pz, const T pi) { x = px; y = py; z = pz; i = pi; } #endif #if HAS_K_AXIS - FI void set(const T px, const T py, const T pz, const T pi, const T pj) { x = px; y = py; z = pz; i = pi; j = pj; } + FI void set(const T px, const T py, const T pz, const T pi, const T pj) { x = px; y = py; z = pz; i = pi; j = pj; } #endif + #if HAS_U_AXIS + FI void set(const T px, const T py, const T pz, const T pi, const T pj, const T pk) { x = px; y = py; z = pz; i = pi; j = pj; k = pk; } + #endif + #if HAS_V_AXIS + FI void set(const T px, const T py, const T pz, const T pi, const T pj, const T pk, const T pm) { x = px; y = py; z = pz; i = pi; j = pj; k = pk; u = pu; } + #endif + #if HAS_W_AXIS + FI void set(const T px, const T py, const T pz, const T pi, const T pj, const T pk, const T pm, const T po) { x = px; y = py; z = pz; i = pi; j = pj; k = pk; u = pm; v = pv; } + #endif + // Setters taking struct types and arrays - FI void set(const XYval pxy) { x = pxy.x; y = pxy.y; } - FI void set(const XYZval pxyz) { set(LINEAR_AXIS_ELEM(pxyz)); } + FI void set(const XYval pxy) { x = pxy.x; y = pxy.y; } + FI void set(const XYZval pxyz) { set(NUM_AXIS_ELEM(pxyz)); } #if HAS_Z_AXIS - FI void set(LINEAR_AXIS_ARGS(const T)) { LINEAR_AXIS_CODE(a = x, b = y, c = z, u = i, v = j, w = k); } + FI void set(NUM_AXIS_ARGS(const T)) { NUM_AXIS_CODE(a = x, b = y, c = z, _i = i, _j = j, _k = k, _u = u, _v = v, _w = w); } #endif - FI void set(const XYval pxy, const T pz) { set(pxy); TERN_(HAS_Z_AXIS, z = pz); } - #if LOGICAL_AXES > LINEAR_AXES + FI void set(const XYval pxy, const T pz) { set(pxy); TERN_(HAS_Z_AXIS, z = pz); } + #if LOGICAL_AXES > NUM_AXES FI void set(const XYval pxy, const T pz, const T pe) { set(pxy, pz); e = pe; } - FI void set(const XYZval pxyz, const T pe) { set(pxyz); e = pe; } - FI void set(LOGICAL_AXIS_ARGS(const T)) { LOGICAL_AXIS_CODE(_e = e, a = x, b = y, c = z, u = i, v = j, w = k); } + FI void set(const XYZval pxyz, const T pe) { set(pxyz); e = pe; } + FI void set(LOGICAL_AXIS_ARGS(const T)) { LOGICAL_AXIS_CODE(_e = e, a = x, b = y, c = z, _i = i, _j = j, _k = k, _u = u, _v = v, _w = w); } #endif // Length reduced to one dimension - FI T magnitude() const { return (T)sqrtf(LOGICAL_AXIS_GANG(+ e*e, + x*x, + y*y, + z*z, + i*i, + j*j, + k*k)); } + FI T magnitude() const { return (T)sqrtf(LOGICAL_AXIS_GANG(+ e*e, + x*x, + y*y, + z*z, + i*i, + j*j, + k*k, + u*u, + v*v, + w*w)); } // Pointer to the data as a simple array FI operator T* () { return pos; } // If any element is true then it's true - FI operator bool() { return 0 LOGICAL_AXIS_GANG(|| e, || x, || y, || z, || i, || j, || k); } + FI operator bool() { return 0 LOGICAL_AXIS_GANG(|| e, || x, || y, || z, || i, || j, || k, || u, || v, || w); } // Explicit copy and copies with conversion - FI XYZEval copy() const { XYZEval o = *this; return o; } - FI XYZEval ABS() const { return LOGICAL_AXIS_ARRAY(T(_ABS(e)), T(_ABS(x)), T(_ABS(y)), T(_ABS(z)), T(_ABS(i)), T(_ABS(j)), T(_ABS(k))); } - FI XYZEval asInt() { return LOGICAL_AXIS_ARRAY(int16_t(e), int16_t(x), int16_t(y), int16_t(z), int16_t(i), int16_t(j), int16_t(k)); } - FI XYZEval asInt() const { return LOGICAL_AXIS_ARRAY(int16_t(e), int16_t(x), int16_t(y), int16_t(z), int16_t(i), int16_t(j), int16_t(k)); } - FI XYZEval asLong() { return LOGICAL_AXIS_ARRAY(int32_t(e), int32_t(x), int32_t(y), int32_t(z), int32_t(i), int32_t(j), int32_t(k)); } - FI XYZEval asLong() const { return LOGICAL_AXIS_ARRAY(int32_t(e), int32_t(x), int32_t(y), int32_t(z), int32_t(i), int32_t(j), int32_t(k)); } - FI XYZEval ROUNDL() { return LOGICAL_AXIS_ARRAY(int32_t(LROUND(e)), int32_t(LROUND(x)), int32_t(LROUND(y)), int32_t(LROUND(z)), int32_t(LROUND(i)), int32_t(LROUND(j)), int32_t(LROUND(k))); } - FI XYZEval ROUNDL() const { return LOGICAL_AXIS_ARRAY(int32_t(LROUND(e)), int32_t(LROUND(x)), int32_t(LROUND(y)), int32_t(LROUND(z)), int32_t(LROUND(i)), int32_t(LROUND(j)), int32_t(LROUND(k))); } - FI XYZEval asFloat() { return LOGICAL_AXIS_ARRAY(static_cast(e), static_cast(x), static_cast(y), static_cast(z), static_cast(i), static_cast(j), static_cast(k)); } - FI XYZEval asFloat() const { return LOGICAL_AXIS_ARRAY(static_cast(e), static_cast(x), static_cast(y), static_cast(z), static_cast(i), static_cast(j), static_cast(k)); } - FI XYZEval reciprocal() const { return LOGICAL_AXIS_ARRAY(_RECIP(e), _RECIP(x), _RECIP(y), _RECIP(z), _RECIP(i), _RECIP(j), _RECIP(k)); } + FI XYZEval copy() const { XYZEval v = *this; return v; } + FI XYZEval ABS() const { return LOGICAL_AXIS_ARRAY(T(_ABS(e)), T(_ABS(x)), T(_ABS(y)), T(_ABS(z)), T(_ABS(i)), T(_ABS(j)), T(_ABS(k)), T(_ABS(u)), T(_ABS(v)), T(_ABS(w))); } + FI XYZEval asInt() { return LOGICAL_AXIS_ARRAY(int16_t(e), int16_t(x), int16_t(y), int16_t(z), int16_t(i), int16_t(j), int16_t(k), int16_t(u), int16_t(v), int16_t(w)); } + FI XYZEval asInt() const { return LOGICAL_AXIS_ARRAY(int16_t(e), int16_t(x), int16_t(y), int16_t(z), int16_t(i), int16_t(j), int16_t(k), int16_t(u), int16_t(v), int16_t(w)); } + FI XYZEval asLong() { return LOGICAL_AXIS_ARRAY(int32_t(e), int32_t(x), int32_t(y), int32_t(z), int32_t(i), int32_t(j), int32_t(k), int32_t(u), int32_t(v), int32_t(w)); } + FI XYZEval asLong() const { return LOGICAL_AXIS_ARRAY(int32_t(e), int32_t(x), int32_t(y), int32_t(z), int32_t(i), int32_t(j), int32_t(k), int32_t(u), int32_t(v), int32_t(w)); } + FI XYZEval ROUNDL() { return LOGICAL_AXIS_ARRAY(int32_t(LROUND(e)), int32_t(LROUND(x)), int32_t(LROUND(y)), int32_t(LROUND(z)), int32_t(LROUND(i)), int32_t(LROUND(j)), int32_t(LROUND(k)), int32_t(LROUND(u)), int32_t(LROUND(v)), int32_t(LROUND(w))); } + FI XYZEval ROUNDL() const { return LOGICAL_AXIS_ARRAY(int32_t(LROUND(e)), int32_t(LROUND(x)), int32_t(LROUND(y)), int32_t(LROUND(z)), int32_t(LROUND(i)), int32_t(LROUND(j)), int32_t(LROUND(k)), int32_t(LROUND(u)), int32_t(LROUND(v)), int32_t(LROUND(w))); } + FI XYZEval asFloat() { return LOGICAL_AXIS_ARRAY(static_cast(e), static_cast(x), static_cast(y), static_cast(z), static_cast(i), static_cast(j), static_cast(k), static_cast(u), static_cast(v), static_cast(w)); } + FI XYZEval asFloat() const { return LOGICAL_AXIS_ARRAY(static_cast(e), static_cast(x), static_cast(y), static_cast(z), static_cast(i), static_cast(j), static_cast(k), static_cast(u), static_cast(v), static_cast(w)); } + FI XYZEval reciprocal() const { return LOGICAL_AXIS_ARRAY(_RECIP(e), _RECIP(x), _RECIP(y), _RECIP(z), _RECIP(i), _RECIP(j), _RECIP(k), _RECIP(u), _RECIP(v), _RECIP(w)); } // Marlin workspace shifting is done with G92 and M206 FI XYZEval asLogical() const { XYZEval o = asFloat(); toLogical(o); return o; } @@ -596,9 +628,9 @@ struct XYZEval { FI const T& operator[](const int n) const { return pos[n]; } // Assignment operator overrides do the expected thing - FI XYZEval& operator= (const T v) { set(LIST_N_1(LINEAR_AXES, v)); return *this; } + FI XYZEval& operator= (const T v) { set(LIST_N_1(NUM_AXES, v)); return *this; } FI XYZEval& operator= (const XYval &rs) { set(rs.x, rs.y); return *this; } - FI XYZEval& operator= (const XYZval &rs) { set(LINEAR_AXIS_ELEM(rs)); return *this; } + FI XYZEval& operator= (const XYZval &rs) { set(NUM_AXIS_ELEM(rs)); return *this; } // Override other operators to get intuitive behaviors FI XYZEval operator+ (const XYval &rs) const { XYZEval ls = *this; ls.x += rs.x; ls.y += rs.y; return ls; } @@ -609,57 +641,57 @@ struct XYZEval { FI XYZEval operator* (const XYval &rs) { XYZEval ls = *this; ls.x *= rs.x; ls.y *= rs.y; return ls; } FI XYZEval operator/ (const XYval &rs) const { XYZEval ls = *this; ls.x /= rs.x; ls.y /= rs.y; return ls; } FI XYZEval operator/ (const XYval &rs) { XYZEval ls = *this; ls.x /= rs.x; ls.y /= rs.y; return ls; } - FI XYZEval operator+ (const XYZval &rs) const { XYZval ls = *this; LINEAR_AXIS_CODE(ls.x += rs.x, ls.y += rs.y, ls.z += rs.z, ls.i += rs.i, ls.j += rs.j, ls.k += rs.k); return ls; } - FI XYZEval operator+ (const XYZval &rs) { XYZval ls = *this; LINEAR_AXIS_CODE(ls.x += rs.x, ls.y += rs.y, ls.z += rs.z, ls.i += rs.i, ls.j += rs.j, ls.k += rs.k); return ls; } - FI XYZEval operator- (const XYZval &rs) const { XYZval ls = *this; LINEAR_AXIS_CODE(ls.x -= rs.x, ls.y -= rs.y, ls.z -= rs.z, ls.i -= rs.i, ls.j -= rs.j, ls.k -= rs.k); return ls; } - FI XYZEval operator- (const XYZval &rs) { XYZval ls = *this; LINEAR_AXIS_CODE(ls.x -= rs.x, ls.y -= rs.y, ls.z -= rs.z, ls.i -= rs.i, ls.j -= rs.j, ls.k -= rs.k); return ls; } - FI XYZEval operator* (const XYZval &rs) const { XYZval ls = *this; LINEAR_AXIS_CODE(ls.x *= rs.x, ls.y *= rs.y, ls.z *= rs.z, ls.i *= rs.i, ls.j *= rs.j, ls.k *= rs.k); return ls; } - FI XYZEval operator* (const XYZval &rs) { XYZval ls = *this; LINEAR_AXIS_CODE(ls.x *= rs.x, ls.y *= rs.y, ls.z *= rs.z, ls.i *= rs.i, ls.j *= rs.j, ls.k *= rs.k); return ls; } - FI XYZEval operator/ (const XYZval &rs) const { XYZval ls = *this; LINEAR_AXIS_CODE(ls.x /= rs.x, ls.y /= rs.y, ls.z /= rs.z, ls.i /= rs.i, ls.j /= rs.j, ls.k /= rs.k); return ls; } - FI XYZEval operator/ (const XYZval &rs) { XYZval ls = *this; LINEAR_AXIS_CODE(ls.x /= rs.x, ls.y /= rs.y, ls.z /= rs.z, ls.i /= rs.i, ls.j /= rs.j, ls.k /= rs.k); return ls; } - FI XYZEval operator+ (const XYZEval &rs) const { XYZEval ls = *this; LOGICAL_AXIS_CODE(ls.e += rs.e, ls.x += rs.x, ls.y += rs.y, ls.z += rs.z, ls.i += rs.i, ls.j += rs.j, ls.k += rs.k); return ls; } - FI XYZEval operator+ (const XYZEval &rs) { XYZEval ls = *this; LOGICAL_AXIS_CODE(ls.e += rs.e, ls.x += rs.x, ls.y += rs.y, ls.z += rs.z, ls.i += rs.i, ls.j += rs.j, ls.k += rs.k); return ls; } - FI XYZEval operator- (const XYZEval &rs) const { XYZEval ls = *this; LOGICAL_AXIS_CODE(ls.e -= rs.e, ls.x -= rs.x, ls.y -= rs.y, ls.z -= rs.z, ls.i -= rs.i, ls.j -= rs.j, ls.k -= rs.k); return ls; } - FI XYZEval operator- (const XYZEval &rs) { XYZEval ls = *this; LOGICAL_AXIS_CODE(ls.e -= rs.e, ls.x -= rs.x, ls.y -= rs.y, ls.z -= rs.z, ls.i -= rs.i, ls.j -= rs.j, ls.k -= rs.k); return ls; } - FI XYZEval operator* (const XYZEval &rs) const { XYZEval ls = *this; LOGICAL_AXIS_CODE(ls.e *= rs.e, ls.x *= rs.x, ls.y *= rs.y, ls.z *= rs.z, ls.i *= rs.i, ls.j *= rs.j, ls.k *= rs.k); return ls; } - FI XYZEval operator* (const XYZEval &rs) { XYZEval ls = *this; LOGICAL_AXIS_CODE(ls.e *= rs.e, ls.x *= rs.x, ls.y *= rs.y, ls.z *= rs.z, ls.i *= rs.i, ls.j *= rs.j, ls.k *= rs.k); return ls; } - FI XYZEval operator/ (const XYZEval &rs) const { XYZEval ls = *this; LOGICAL_AXIS_CODE(ls.e /= rs.e, ls.x /= rs.x, ls.y /= rs.y, ls.z /= rs.z, ls.i /= rs.i, ls.j /= rs.j, ls.k /= rs.k); return ls; } - FI XYZEval operator/ (const XYZEval &rs) { XYZEval ls = *this; LOGICAL_AXIS_CODE(ls.e /= rs.e, ls.x /= rs.x, ls.y /= rs.y, ls.z /= rs.z, ls.i /= rs.i, ls.j /= rs.j, ls.k /= rs.k); return ls; } - FI XYZEval operator* (const float &v) const { XYZEval ls = *this; LOGICAL_AXIS_CODE(ls.e *= v, ls.x *= v, ls.y *= v, ls.z *= v, ls.i *= v, ls.j *= v, ls.k *= v ); return ls; } - FI XYZEval operator* (const float &v) { XYZEval ls = *this; LOGICAL_AXIS_CODE(ls.e *= v, ls.x *= v, ls.y *= v, ls.z *= v, ls.i *= v, ls.j *= v, ls.k *= v ); return ls; } - FI XYZEval operator* (const int &v) const { XYZEval ls = *this; LOGICAL_AXIS_CODE(ls.e *= v, ls.x *= v, ls.y *= v, ls.z *= v, ls.i *= v, ls.j *= v, ls.k *= v ); return ls; } - FI XYZEval operator* (const int &v) { XYZEval ls = *this; LOGICAL_AXIS_CODE(ls.e *= v, ls.x *= v, ls.y *= v, ls.z *= v, ls.i *= v, ls.j *= v, ls.k *= v ); return ls; } - FI XYZEval operator/ (const float &v) const { XYZEval ls = *this; LOGICAL_AXIS_CODE(ls.e /= v, ls.x /= v, ls.y /= v, ls.z /= v, ls.i /= v, ls.j /= v, ls.k /= v ); return ls; } - FI XYZEval operator/ (const float &v) { XYZEval ls = *this; LOGICAL_AXIS_CODE(ls.e /= v, ls.x /= v, ls.y /= v, ls.z /= v, ls.i /= v, ls.j /= v, ls.k /= v ); return ls; } - FI XYZEval operator/ (const int &v) const { XYZEval ls = *this; LOGICAL_AXIS_CODE(ls.e /= v, ls.x /= v, ls.y /= v, ls.z /= v, ls.i /= v, ls.j /= v, ls.k /= v ); return ls; } - FI XYZEval operator/ (const int &v) { XYZEval ls = *this; LOGICAL_AXIS_CODE(ls.e /= v, ls.x /= v, ls.y /= v, ls.z /= v, ls.i /= v, ls.j /= v, ls.k /= v ); return ls; } - FI XYZEval operator>>(const int &v) const { XYZEval ls = *this; LOGICAL_AXIS_CODE(_RS(ls.e), _RS(ls.x), _RS(ls.y), _RS(ls.z), _RS(ls.i), _RS(ls.j), _RS(ls.k) ); return ls; } - FI XYZEval operator>>(const int &v) { XYZEval ls = *this; LOGICAL_AXIS_CODE(_RS(ls.e), _RS(ls.x), _RS(ls.y), _RS(ls.z), _RS(ls.i), _RS(ls.j), _RS(ls.k) ); return ls; } - FI XYZEval operator<<(const int &v) const { XYZEval ls = *this; LOGICAL_AXIS_CODE(_LS(ls.e), _LS(ls.x), _LS(ls.y), _LS(ls.z), _LS(ls.i), _LS(ls.j), _LS(ls.k) ); return ls; } - FI XYZEval operator<<(const int &v) { XYZEval ls = *this; LOGICAL_AXIS_CODE(_LS(ls.e), _LS(ls.x), _LS(ls.y), _LS(ls.z), _LS(ls.i), _LS(ls.j), _LS(ls.k) ); return ls; } - FI const XYZEval operator-() const { return LOGICAL_AXIS_ARRAY(-e, -x, -y, -z, -i, -j, -k); } - FI XYZEval operator-() { return LOGICAL_AXIS_ARRAY(-e, -x, -y, -z, -i, -j, -k); } + FI XYZEval operator+ (const XYZval &rs) const { XYZval ls = *this; NUM_AXIS_CODE(ls.x += rs.x, ls.y += rs.y, ls.z += rs.z, ls.i += rs.i, ls.j += rs.j, ls.k += rs.k, ls.u += rs.u, ls.v += rs.v, ls.w += rs.w); return ls; } + FI XYZEval operator+ (const XYZval &rs) { XYZval ls = *this; NUM_AXIS_CODE(ls.x += rs.x, ls.y += rs.y, ls.z += rs.z, ls.i += rs.i, ls.j += rs.j, ls.k += rs.k, ls.u += rs.u, ls.v += rs.v, ls.w += rs.w); return ls; } + FI XYZEval operator- (const XYZval &rs) const { XYZval ls = *this; NUM_AXIS_CODE(ls.x -= rs.x, ls.y -= rs.y, ls.z -= rs.z, ls.i -= rs.i, ls.j -= rs.j, ls.k -= rs.k, ls.u -= rs.u, ls.v -= rs.v, ls.w -= rs.w); return ls; } + FI XYZEval operator- (const XYZval &rs) { XYZval ls = *this; NUM_AXIS_CODE(ls.x -= rs.x, ls.y -= rs.y, ls.z -= rs.z, ls.i -= rs.i, ls.j -= rs.j, ls.k -= rs.k, ls.u -= rs.u, ls.v -= rs.v, ls.w -= rs.w); return ls; } + FI XYZEval operator* (const XYZval &rs) const { XYZval ls = *this; NUM_AXIS_CODE(ls.x *= rs.x, ls.y *= rs.y, ls.z *= rs.z, ls.i *= rs.i, ls.j *= rs.j, ls.k *= rs.k, ls.u *= rs.u, ls.v *= rs.v, ls.w *= rs.w); return ls; } + FI XYZEval operator* (const XYZval &rs) { XYZval ls = *this; NUM_AXIS_CODE(ls.x *= rs.x, ls.y *= rs.y, ls.z *= rs.z, ls.i *= rs.i, ls.j *= rs.j, ls.k *= rs.k, ls.u *= rs.u, ls.v *= rs.v, ls.w *= rs.w); return ls; } + FI XYZEval operator/ (const XYZval &rs) const { XYZval ls = *this; NUM_AXIS_CODE(ls.x /= rs.x, ls.y /= rs.y, ls.z /= rs.z, ls.i /= rs.i, ls.j /= rs.j, ls.k /= rs.k, ls.u /= rs.u, ls.v /= rs.v, ls.w /= rs.w); return ls; } + FI XYZEval operator/ (const XYZval &rs) { XYZval ls = *this; NUM_AXIS_CODE(ls.x /= rs.x, ls.y /= rs.y, ls.z /= rs.z, ls.i /= rs.i, ls.j /= rs.j, ls.k /= rs.k, ls.u /= rs.u, ls.v /= rs.v, ls.w /= rs.w); return ls; } + FI XYZEval operator+ (const XYZEval &rs) const { XYZEval ls = *this; LOGICAL_AXIS_CODE(ls.e += rs.e, ls.x += rs.x, ls.y += rs.y, ls.z += rs.z, ls.i += rs.i, ls.j += rs.j, ls.k += rs.k, ls.u += rs.u, ls.v += rs.v, ls.w += rs.w); return ls; } + FI XYZEval operator+ (const XYZEval &rs) { XYZEval ls = *this; LOGICAL_AXIS_CODE(ls.e += rs.e, ls.x += rs.x, ls.y += rs.y, ls.z += rs.z, ls.i += rs.i, ls.j += rs.j, ls.k += rs.k, ls.u += rs.u, ls.v += rs.v, ls.w += rs.w); return ls; } + FI XYZEval operator- (const XYZEval &rs) const { XYZEval ls = *this; LOGICAL_AXIS_CODE(ls.e -= rs.e, ls.x -= rs.x, ls.y -= rs.y, ls.z -= rs.z, ls.i -= rs.i, ls.j -= rs.j, ls.k -= rs.k, ls.u -= rs.u, ls.v -= rs.v, ls.w -= rs.w); return ls; } + FI XYZEval operator- (const XYZEval &rs) { XYZEval ls = *this; LOGICAL_AXIS_CODE(ls.e -= rs.e, ls.x -= rs.x, ls.y -= rs.y, ls.z -= rs.z, ls.i -= rs.i, ls.j -= rs.j, ls.k -= rs.k, ls.u -= rs.u, ls.v -= rs.v, ls.w -= rs.w); return ls; } + FI XYZEval operator* (const XYZEval &rs) const { XYZEval ls = *this; LOGICAL_AXIS_CODE(ls.e *= rs.e, ls.x *= rs.x, ls.y *= rs.y, ls.z *= rs.z, ls.i *= rs.i, ls.j *= rs.j, ls.k *= rs.k, ls.u *= rs.u, ls.v *= rs.v, ls.w *= rs.w); return ls; } + FI XYZEval operator* (const XYZEval &rs) { XYZEval ls = *this; LOGICAL_AXIS_CODE(ls.e *= rs.e, ls.x *= rs.x, ls.y *= rs.y, ls.z *= rs.z, ls.i *= rs.i, ls.j *= rs.j, ls.k *= rs.k, ls.u *= rs.u, ls.v *= rs.v, ls.w *= rs.w); return ls; } + FI XYZEval operator/ (const XYZEval &rs) const { XYZEval ls = *this; LOGICAL_AXIS_CODE(ls.e /= rs.e, ls.x /= rs.x, ls.y /= rs.y, ls.z /= rs.z, ls.i /= rs.i, ls.j /= rs.j, ls.k /= rs.k, ls.u /= rs.u, ls.v /= rs.v, ls.w /= rs.w); return ls; } + FI XYZEval operator/ (const XYZEval &rs) { XYZEval ls = *this; LOGICAL_AXIS_CODE(ls.e /= rs.e, ls.x /= rs.x, ls.y /= rs.y, ls.z /= rs.z, ls.i /= rs.i, ls.j /= rs.j, ls.k /= rs.k, ls.u /= rs.u, ls.v /= rs.v, ls.w /= rs.w); return ls; } + FI XYZEval operator* (const float &v) const { XYZEval ls = *this; LOGICAL_AXIS_CODE(ls.e *= v, ls.x *= v, ls.y *= v, ls.z *= v, ls.i *= v, ls.j *= v, ls.k *= v, ls.u *= v, ls.v *= v, ls.w *= v ); return ls; } + FI XYZEval operator* (const float &v) { XYZEval ls = *this; LOGICAL_AXIS_CODE(ls.e *= v, ls.x *= v, ls.y *= v, ls.z *= v, ls.i *= v, ls.j *= v, ls.k *= v, ls.u *= v, ls.v *= v, ls.w *= v ); return ls; } + FI XYZEval operator* (const int &v) const { XYZEval ls = *this; LOGICAL_AXIS_CODE(ls.e *= v, ls.x *= v, ls.y *= v, ls.z *= v, ls.i *= v, ls.j *= v, ls.k *= v, ls.u *= v, ls.v *= v, ls.w *= v ); return ls; } + FI XYZEval operator* (const int &v) { XYZEval ls = *this; LOGICAL_AXIS_CODE(ls.e *= v, ls.x *= v, ls.y *= v, ls.z *= v, ls.i *= v, ls.j *= v, ls.k *= v, ls.u *= v, ls.v *= v, ls.w *= v ); return ls; } + FI XYZEval operator/ (const float &v) const { XYZEval ls = *this; LOGICAL_AXIS_CODE(ls.e /= v, ls.x /= v, ls.y /= v, ls.z /= v, ls.i /= v, ls.j /= v, ls.k /= v, ls.u /= v, ls.v /= v, ls.w /= v ); return ls; } + FI XYZEval operator/ (const float &v) { XYZEval ls = *this; LOGICAL_AXIS_CODE(ls.e /= v, ls.x /= v, ls.y /= v, ls.z /= v, ls.i /= v, ls.j /= v, ls.k /= v, ls.u /= v, ls.v /= v, ls.w /= v ); return ls; } + FI XYZEval operator/ (const int &v) const { XYZEval ls = *this; LOGICAL_AXIS_CODE(ls.e /= v, ls.x /= v, ls.y /= v, ls.z /= v, ls.i /= v, ls.j /= v, ls.k /= v, ls.u /= v, ls.v /= v, ls.w /= v ); return ls; } + FI XYZEval operator/ (const int &v) { XYZEval ls = *this; LOGICAL_AXIS_CODE(ls.e /= v, ls.x /= v, ls.y /= v, ls.z /= v, ls.i /= v, ls.j /= v, ls.k /= v, ls.u /= v, ls.v /= v, ls.w /= v ); return ls; } + FI XYZEval operator>>(const int &v) const { XYZEval ls = *this; LOGICAL_AXIS_CODE(_RS(ls.e), _RS(ls.x), _RS(ls.y), _RS(ls.z), _RS(ls.i), _RS(ls.j), _RS(ls.k), _RS(ls.u), _RS(ls.v), _RS(ls.w) ); return ls; } + FI XYZEval operator>>(const int &v) { XYZEval ls = *this; LOGICAL_AXIS_CODE(_RS(ls.e), _RS(ls.x), _RS(ls.y), _RS(ls.z), _RS(ls.i), _RS(ls.j), _RS(ls.k), _RS(ls.u), _RS(ls.v), _RS(ls.w) ); return ls; } + FI XYZEval operator<<(const int &v) const { XYZEval ls = *this; LOGICAL_AXIS_CODE(_LS(ls.e), _LS(ls.x), _LS(ls.y), _LS(ls.z), _LS(ls.i), _LS(ls.j), _LS(ls.k), _LS(ls.u), _LS(ls.v), _LS(ls.w) ); return ls; } + FI XYZEval operator<<(const int &v) { XYZEval ls = *this; LOGICAL_AXIS_CODE(_LS(ls.e), _LS(ls.x), _LS(ls.y), _LS(ls.z), _LS(ls.i), _LS(ls.j), _LS(ls.k), _LS(ls.u), _LS(ls.v), _LS(ls.w) ); return ls; } + FI const XYZEval operator-() const { return LOGICAL_AXIS_ARRAY(-e, -x, -y, -z, -i, -j, -k, -u, -v, -w); } + FI XYZEval operator-() { return LOGICAL_AXIS_ARRAY(-e, -x, -y, -z, -i, -j, -k, -u, -v, -w); } // Modifier operators FI XYZEval& operator+=(const XYval &rs) { x += rs.x; y += rs.y; return *this; } FI XYZEval& operator-=(const XYval &rs) { x -= rs.x; y -= rs.y; return *this; } FI XYZEval& operator*=(const XYval &rs) { x *= rs.x; y *= rs.y; return *this; } FI XYZEval& operator/=(const XYval &rs) { x /= rs.x; y /= rs.y; return *this; } - FI XYZEval& operator+=(const XYZval &rs) { LINEAR_AXIS_CODE(x += rs.x, y += rs.y, z += rs.z, i += rs.i, j += rs.j, k += rs.k); return *this; } - FI XYZEval& operator-=(const XYZval &rs) { LINEAR_AXIS_CODE(x -= rs.x, y -= rs.y, z -= rs.z, i -= rs.i, j -= rs.j, k -= rs.k); return *this; } - FI XYZEval& operator*=(const XYZval &rs) { LINEAR_AXIS_CODE(x *= rs.x, y *= rs.y, z *= rs.z, i *= rs.i, j *= rs.j, k *= rs.k); return *this; } - FI XYZEval& operator/=(const XYZval &rs) { LINEAR_AXIS_CODE(x /= rs.x, y /= rs.y, z /= rs.z, i /= rs.i, j /= rs.j, k /= rs.k); return *this; } - FI XYZEval& operator+=(const XYZEval &rs) { LOGICAL_AXIS_CODE(e += rs.e, x += rs.x, y += rs.y, z += rs.z, i += rs.i, j += rs.j, k += rs.k); return *this; } - FI XYZEval& operator-=(const XYZEval &rs) { LOGICAL_AXIS_CODE(e -= rs.e, x -= rs.x, y -= rs.y, z -= rs.z, i -= rs.i, j -= rs.j, k -= rs.k); return *this; } - FI XYZEval& operator*=(const XYZEval &rs) { LOGICAL_AXIS_CODE(e *= rs.e, x *= rs.x, y *= rs.y, z *= rs.z, i *= rs.i, j *= rs.j, k *= rs.k); return *this; } - FI XYZEval& operator/=(const XYZEval &rs) { LOGICAL_AXIS_CODE(e /= rs.e, x /= rs.x, y /= rs.y, z /= rs.z, i /= rs.i, j /= rs.j, k /= rs.k); return *this; } - FI XYZEval& operator*=(const T &v) { LOGICAL_AXIS_CODE(e *= v, x *= v, y *= v, z *= v, i *= v, j *= v, k *= v); return *this; } - FI XYZEval& operator>>=(const int &v) { LOGICAL_AXIS_CODE(_RS(e), _RS(x), _RS(y), _RS(z), _RS(i), _RS(j), _RS(k)); return *this; } - FI XYZEval& operator<<=(const int &v) { LOGICAL_AXIS_CODE(_LS(e), _LS(x), _LS(y), _LS(z), _LS(i), _LS(j), _LS(k)); return *this; } + FI XYZEval& operator+=(const XYZval &rs) { NUM_AXIS_CODE(x += rs.x, y += rs.y, z += rs.z, i += rs.i, j += rs.j, k += rs.k, u += rs.u, v += rs.v, w += rs.w); return *this; } + FI XYZEval& operator-=(const XYZval &rs) { NUM_AXIS_CODE(x -= rs.x, y -= rs.y, z -= rs.z, i -= rs.i, j -= rs.j, k -= rs.k, u -= rs.u, v -= rs.v, w -= rs.w); return *this; } + FI XYZEval& operator*=(const XYZval &rs) { NUM_AXIS_CODE(x *= rs.x, y *= rs.y, z *= rs.z, i *= rs.i, j *= rs.j, k *= rs.k, u *= rs.u, v *= rs.v, w *= rs.w); return *this; } + FI XYZEval& operator/=(const XYZval &rs) { NUM_AXIS_CODE(x /= rs.x, y /= rs.y, z /= rs.z, i /= rs.i, j /= rs.j, k /= rs.k, u /= rs.u, v /= rs.v, w /= rs.w); return *this; } + FI XYZEval& operator+=(const XYZEval &rs) { LOGICAL_AXIS_CODE(e += rs.e, x += rs.x, y += rs.y, z += rs.z, i += rs.i, j += rs.j, k += rs.k, u += rs.u, v += rs.v, w += rs.w); return *this; } + FI XYZEval& operator-=(const XYZEval &rs) { LOGICAL_AXIS_CODE(e -= rs.e, x -= rs.x, y -= rs.y, z -= rs.z, i -= rs.i, j -= rs.j, k -= rs.k, u -= rs.u, v -= rs.v, w -= rs.w); return *this; } + FI XYZEval& operator*=(const XYZEval &rs) { LOGICAL_AXIS_CODE(e *= rs.e, x *= rs.x, y *= rs.y, z *= rs.z, i *= rs.i, j *= rs.j, k *= rs.k, u *= rs.u, v *= rs.v, w *= rs.w); return *this; } + FI XYZEval& operator/=(const XYZEval &rs) { LOGICAL_AXIS_CODE(e /= rs.e, x /= rs.x, y /= rs.y, z /= rs.z, i /= rs.i, j /= rs.j, k /= rs.k, u /= rs.u, v /= rs.v, w /= rs.w); return *this; } + FI XYZEval& operator*=(const T &v) { LOGICAL_AXIS_CODE(e *= v, x *= v, y *= v, z *= v, i *= v, j *= v, k *= v, u *= v, v *= v, w *= v); return *this; } + FI XYZEval& operator>>=(const int &v) { LOGICAL_AXIS_CODE(_RS(e), _RS(x), _RS(y), _RS(z), _RS(i), _RS(j), _RS(k), _RS(u), _RS(v), _RS(w)); return *this; } + FI XYZEval& operator<<=(const int &v) { LOGICAL_AXIS_CODE(_LS(e), _LS(x), _LS(y), _LS(z), _LS(i), _LS(j), _LS(k), _LS(u), _LS(v), _LS(w)); return *this; } // Exact comparisons. For floats a "NEAR" operation may be better. - FI bool operator==(const XYZval &rs) { return true LINEAR_AXIS_GANG(&& x == rs.x, && y == rs.y, && z == rs.z, && i == rs.i, && j == rs.j, && k == rs.k); } - FI bool operator==(const XYZval &rs) const { return true LINEAR_AXIS_GANG(&& x == rs.x, && y == rs.y, && z == rs.z, && i == rs.i, && j == rs.j, && k == rs.k); } + FI bool operator==(const XYZval &rs) { return true NUM_AXIS_GANG(&& x == rs.x, && y == rs.y, && z == rs.z, && i == rs.i, && j == rs.j, && k == rs.k, && u == rs.u, && v == rs.v, && w == rs.w); } + FI bool operator==(const XYZval &rs) const { return true NUM_AXIS_GANG(&& x == rs.x, && y == rs.y, && z == rs.z, && i == rs.i, && j == rs.j, && k == rs.k, && u == rs.u, && v == rs.v, && w == rs.w); } FI bool operator!=(const XYZval &rs) { return !operator==(rs); } FI bool operator!=(const XYZval &rs) const { return !operator==(rs); } }; diff --git a/Marlin/src/core/utility.cpp b/Marlin/src/core/utility.cpp index 19e7626744..986869aa07 100644 --- a/Marlin/src/core/utility.cpp +++ b/Marlin/src/core/utility.cpp @@ -94,9 +94,9 @@ void safe_delay(millis_t ms) { SERIAL_ECHOPGM(" (Aligned With"); if (probe.offset_xy.y > 0) - SERIAL_ECHOF(F(TERN(IS_SCARA, "-Distal", "-Back"))); + SERIAL_ECHOPGM(TERN(IS_SCARA, "-Distal", "-Back")); else if (probe.offset_xy.y < 0) - SERIAL_ECHOF(F(TERN(IS_SCARA, "-Proximal", "-Front"))); + SERIAL_ECHOPGM(TERN(IS_SCARA, "-Proximal", "-Front")); else if (probe.offset_xy.x != 0) SERIAL_ECHOPGM("-Center"); @@ -125,11 +125,9 @@ void safe_delay(millis_t ms) { #endif #if ABL_PLANAR SERIAL_ECHOPGM("ABL Adjustment"); - LOOP_LINEAR_AXES(a) { - const float v = planner.get_axis_position_mm(AxisEnum(a)) - current_position[a]; + LOOP_NUM_AXES(a) { SERIAL_CHAR(' ', AXIS_CHAR(a)); - if (v > 0) SERIAL_CHAR('+'); - SERIAL_DECIMAL(v); + serial_offset(planner.get_axis_position_mm(AxisEnum(a)) - current_position[a]); } #else #if ENABLED(AUTO_BED_LEVELING_UBL) @@ -137,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) diff --git a/Marlin/src/core/utility.h b/Marlin/src/core/utility.h index d248091ce5..b845cd0412 100644 --- a/Marlin/src/core/utility.h +++ b/Marlin/src/core/utility.h @@ -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 diff --git a/Marlin/src/feature/backlash.cpp b/Marlin/src/feature/backlash.cpp index 84382cf856..876d28a8fe 100644 --- a/Marlin/src/feature/backlash.cpp +++ b/Marlin/src/feature/backlash.cpp @@ -97,7 +97,7 @@ void Backlash::add_correction_steps(const int32_t &da, const int32_t &db, const const float f_corr = float(correction) / all_on; - LOOP_LINEAR_AXES(axis) { + LOOP_NUM_AXES(axis) { if (distance_mm[axis]) { const bool reverse = TEST(dm, axis); @@ -145,7 +145,7 @@ void Backlash::add_correction_steps(const int32_t &da, const int32_t &db, const } int32_t Backlash::get_applied_steps(const AxisEnum axis) { - if (axis >= LINEAR_AXES) return 0; + if (axis >= NUM_AXES) return 0; const bool reverse = TEST(last_direction_bits, axis); @@ -165,11 +165,11 @@ class Backlash::StepAdjuster { xyz_long_t applied_steps; public: StepAdjuster() { - LOOP_LINEAR_AXES(axis) applied_steps[axis] = backlash.get_applied_steps((AxisEnum)axis); + LOOP_NUM_AXES(axis) applied_steps[axis] = backlash.get_applied_steps((AxisEnum)axis); } ~StepAdjuster() { // after backlash compensation parameter changes, ensure applied step count does not change - LOOP_LINEAR_AXES(axis) residual_error[axis] += backlash.get_applied_steps((AxisEnum)axis) - applied_steps[axis]; + LOOP_NUM_AXES(axis) residual_error[axis] += backlash.get_applied_steps((AxisEnum)axis) - applied_steps[axis]; } }; diff --git a/Marlin/src/feature/bedlevel/abl/abl.h b/Marlin/src/feature/bedlevel/abl/abl.h deleted file mode 100644 index 3d54c55695..0000000000 --- a/Marlin/src/feature/bedlevel/abl/abl.h +++ /dev/null @@ -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 . - * - */ -#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 diff --git a/Marlin/src/feature/bedlevel/abl/abl.cpp b/Marlin/src/feature/bedlevel/abl/bbl.cpp similarity index 78% rename from Marlin/src/feature/bedlevel/abl/abl.cpp rename to Marlin/src/feature/bedlevel/abl/bbl.cpp index ece7481981..9dcd669128 100644 --- a/Marlin/src/feature/bedlevel/abl/abl.cpp +++ b/Marlin/src/feature/bedlevel/abl/bbl.cpp @@ -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 diff --git a/Marlin/src/feature/bedlevel/abl/bbl.h b/Marlin/src/feature/bedlevel/abl/bbl.h new file mode 100644 index 0000000000..86da5aea10 --- /dev/null +++ b/Marlin/src/feature/bedlevel/abl/bbl.h @@ -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 . + * + */ +#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() diff --git a/Marlin/src/feature/bedlevel/bedlevel.cpp b/Marlin/src/feature/bedlevel/bedlevel.cpp index 8e03632de4..2405905d4e 100644 --- a/Marlin/src/feature/bedlevel/bedlevel.cpp +++ b/Marlin/src/feature/bedlevel/bedlevel.cpp @@ -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)); diff --git a/Marlin/src/feature/bedlevel/bedlevel.h b/Marlin/src/feature/bedlevel/bedlevel.h index 63f032eee8..f295da1d03 100644 --- a/Marlin/src/feature/bedlevel/bedlevel.h +++ b/Marlin/src/feature/bedlevel/bedlevel.h @@ -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 diff --git a/Marlin/src/feature/bedlevel/mbl/mesh_bed_leveling.cpp b/Marlin/src/feature/bedlevel/mbl/mesh_bed_leveling.cpp index 51cf28f890..fbc3f2785e 100644 --- a/Marlin/src/feature/bedlevel/mbl/mesh_bed_leveling.cpp +++ b/Marlin/src/feature/bedlevel/mbl/mesh_bed_leveling.cpp @@ -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 diff --git a/Marlin/src/feature/bedlevel/ubl/ubl.cpp b/Marlin/src/feature/bedlevel/ubl/ubl.cpp index 964f1123fe..c162062f86 100644 --- a/Marlin/src/feature/bedlevel/ubl/ubl.cpp +++ b/Marlin/src/feature/bedlevel/ubl/ubl.cpp @@ -213,8 +213,8 @@ void unified_bed_leveling::display_map(const uint8_t map_type) { else if (isnan(f)) SERIAL_ECHOF(human ? F(" . ") : F("NAN")); else if (human || csv) { - if (human && f >= 0.0) SERIAL_CHAR(f > 0 ? '+' : ' '); // Display sign also for positive numbers (' ' for 0) - SERIAL_ECHO_F(f, 3); // Positive: 5 digits, Negative: 6 digits + if (human && f >= 0) SERIAL_CHAR(f > 0 ? '+' : ' '); // Display sign also for positive numbers (' ' for 0) + SERIAL_DECIMAL(f); // Positive: 5 digits, Negative: 6 digits } if (csv && i < (GRID_MAX_POINTS_X) - 1) SERIAL_CHAR('\t'); diff --git a/Marlin/src/feature/bedlevel/ubl/ubl_G29.cpp b/Marlin/src/feature/bedlevel/ubl/ubl_G29.cpp index 023d0c5b1d..9d2aaf8247 100644 --- a/Marlin/src/feature/bedlevel/ubl/ubl_G29.cpp +++ b/Marlin/src/feature/bedlevel/ubl/ubl_G29.cpp @@ -317,6 +317,42 @@ void unified_bed_leveling::G29() { // Send 'N' to force homing before G29 (internal only) if (axes_should_home() || parser.seen_test('N')) gcode.home_all_axes(); TERN_(HAS_MULTI_HOTEND, if (active_extruder != 0) tool_change(0, true)); + + // Position bed horizontally and Z probe vertically. + #if defined(SAFE_BED_LEVELING_START_X) || defined(SAFE_BED_LEVELING_START_Y) || defined(SAFE_BED_LEVELING_START_Z) \ + || defined(SAFE_BED_LEVELING_START_I) || defined(SAFE_BED_LEVELING_START_J) || defined(SAFE_BED_LEVELING_START_K) \ + || defined(SAFE_BED_LEVELING_START_U) || defined(SAFE_BED_LEVELING_START_V) || defined(SAFE_BED_LEVELING_START_W) + xyze_pos_t safe_position = current_position; + #ifdef SAFE_BED_LEVELING_START_X + safe_position.x = SAFE_BED_LEVELING_START_X; + #endif + #ifdef SAFE_BED_LEVELING_START_Y + safe_position.y = SAFE_BED_LEVELING_START_Y; + #endif + #ifdef SAFE_BED_LEVELING_START_Z + safe_position.z = SAFE_BED_LEVELING_START_Z; + #endif + #ifdef SAFE_BED_LEVELING_START_I + safe_position.i = SAFE_BED_LEVELING_START_I; + #endif + #ifdef SAFE_BED_LEVELING_START_J + safe_position.j = SAFE_BED_LEVELING_START_J; + #endif + #ifdef SAFE_BED_LEVELING_START_K + safe_position.k = SAFE_BED_LEVELING_START_K; + #endif + #ifdef SAFE_BED_LEVELING_START_U + safe_position.u = SAFE_BED_LEVELING_START_U; + #endif + #ifdef SAFE_BED_LEVELING_START_V + safe_position.v = SAFE_BED_LEVELING_START_V; + #endif + #ifdef SAFE_BED_LEVELING_START_W + safe_position.w = SAFE_BED_LEVELING_START_W; + #endif + + do_blocking_move_to(safe_position); + #endif } // Invalidate one or more nearby mesh points, possibly all. @@ -367,13 +403,13 @@ void unified_bed_leveling::G29() { case 1: LOOP_L_N(x, GRID_MAX_POINTS_X) { // Create a diagonal line several Mesh cells thick that is raised + const uint8_t x2 = x + (x < (GRID_MAX_POINTS_Y) - 1 ? 1 : -1); z_values[x][x] += 9.999f; - z_values[x][x + (x < (GRID_MAX_POINTS_Y) - 1) ? 1 : -1] += 9.999f; // We want the altered line several mesh points thick + z_values[x][x2] += 9.999f; // We want the altered line several mesh points thick #if ENABLED(EXTENSIBLE_UI) ExtUI::onMeshUpdate(x, x, z_values[x][x]); - ExtUI::onMeshUpdate(x, (x + (x < (GRID_MAX_POINTS_Y) - 1) ? 1 : -1), z_values[x][x + (x < (GRID_MAX_POINTS_Y) - 1) ? 1 : -1]); + ExtUI::onMeshUpdate(x, (x2), z_values[x][x2]); #endif - } break; @@ -1219,6 +1255,7 @@ void unified_bed_leveling::restore_ubl_active_state_and_leave() { } #endif set_bed_leveling_enabled(ubl_state_at_invocation); + TERN_(EXTENSIBLE_UI, ExtUI::onLevelingDone()); } mesh_index_pair unified_bed_leveling::find_furthest_invalid_mesh_point() { diff --git a/Marlin/src/feature/digipot/digipot_mcp4018.cpp b/Marlin/src/feature/digipot/digipot_mcp4018.cpp index 37853ff428..3f2ecbfcdc 100644 --- a/Marlin/src/feature/digipot/digipot_mcp4018.cpp +++ b/Marlin/src/feature/digipot/digipot_mcp4018.cpp @@ -31,9 +31,13 @@ // Settings for the I2C based DIGIPOT (MCP4018) based on WT150 -#define DIGIPOT_A4988_Rsx 0.250 -#define DIGIPOT_A4988_Vrefmax 1.666 -#define DIGIPOT_MCP4018_MAX_VALUE 127 +#ifndef DIGIPOT_A4988_Rsx + #define DIGIPOT_A4988_Rsx 0.250 +#endif +#ifndef DIGIPOT_A4988_Vrefmax + #define DIGIPOT_A4988_Vrefmax 1.666 +#endif +#define DIGIPOT_MCP4018_MAX_VALUE 127 #define DIGIPOT_A4988_Itripmax(Vref) ((Vref) / (8.0 * DIGIPOT_A4988_Rsx)) diff --git a/Marlin/src/feature/encoder_i2c.cpp b/Marlin/src/feature/encoder_i2c.cpp index 2ccd686a99..c1dbb906fd 100644 --- a/Marlin/src/feature/encoder_i2c.cpp +++ b/Marlin/src/feature/encoder_i2c.cpp @@ -337,7 +337,7 @@ bool I2CPositionEncoder::test_axis() { ec = false; xyze_pos_t startCoord, endCoord; - LOOP_LINEAR_AXES(a) { + LOOP_NUM_AXES(a) { startCoord[a] = planner.get_axis_position_mm((AxisEnum)a); endCoord[a] = planner.get_axis_position_mm((AxisEnum)a); } @@ -395,7 +395,7 @@ void I2CPositionEncoder::calibrate_steps_mm(const uint8_t iter) { travelDistance = endDistance - startDistance; xyze_pos_t startCoord, endCoord; - LOOP_LINEAR_AXES(a) { + LOOP_NUM_AXES(a) { startCoord[a] = planner.get_axis_position_mm((AxisEnum)a); endCoord[a] = planner.get_axis_position_mm((AxisEnum)a); } @@ -489,7 +489,7 @@ void I2CPositionEncodersMgr::init() { encoders[i].set_stepper_ticks(I2CPE_ENC_1_TICKS_REV); #endif #ifdef I2CPE_ENC_1_INVERT - encoders[i].set_inverted(I2CPE_ENC_1_INVERT); + encoders[i].set_inverted(ENABLED(I2CPE_ENC_1_INVERT)); #endif #ifdef I2CPE_ENC_1_EC_METHOD encoders[i].set_ec_method(I2CPE_ENC_1_EC_METHOD); @@ -518,7 +518,7 @@ void I2CPositionEncodersMgr::init() { encoders[i].set_stepper_ticks(I2CPE_ENC_2_TICKS_REV); #endif #ifdef I2CPE_ENC_2_INVERT - encoders[i].set_inverted(I2CPE_ENC_2_INVERT); + encoders[i].set_inverted(ENABLED(I2CPE_ENC_2_INVERT)); #endif #ifdef I2CPE_ENC_2_EC_METHOD encoders[i].set_ec_method(I2CPE_ENC_2_EC_METHOD); @@ -547,7 +547,7 @@ void I2CPositionEncodersMgr::init() { encoders[i].set_stepper_ticks(I2CPE_ENC_3_TICKS_REV); #endif #ifdef I2CPE_ENC_3_INVERT - encoders[i].set_inverted(I2CPE_ENC_3_INVERT); + encoders[i].set_inverted(ENABLED(I2CPE_ENC_3_INVERT)); #endif #ifdef I2CPE_ENC_3_EC_METHOD encoders[i].set_ec_method(I2CPE_ENC_3_EC_METHOD); @@ -576,7 +576,7 @@ void I2CPositionEncodersMgr::init() { encoders[i].set_stepper_ticks(I2CPE_ENC_4_TICKS_REV); #endif #ifdef I2CPE_ENC_4_INVERT - encoders[i].set_inverted(I2CPE_ENC_4_INVERT); + encoders[i].set_inverted(ENABLED(I2CPE_ENC_4_INVERT)); #endif #ifdef I2CPE_ENC_4_EC_METHOD encoders[i].set_ec_method(I2CPE_ENC_4_EC_METHOD); @@ -605,7 +605,7 @@ void I2CPositionEncodersMgr::init() { encoders[i].set_stepper_ticks(I2CPE_ENC_5_TICKS_REV); #endif #ifdef I2CPE_ENC_5_INVERT - encoders[i].set_inverted(I2CPE_ENC_5_INVERT); + encoders[i].set_inverted(ENABLED(I2CPE_ENC_5_INVERT)); #endif #ifdef I2CPE_ENC_5_EC_METHOD encoders[i].set_ec_method(I2CPE_ENC_5_EC_METHOD); @@ -634,7 +634,7 @@ void I2CPositionEncodersMgr::init() { encoders[i].set_stepper_ticks(I2CPE_ENC_6_TICKS_REV); #endif #ifdef I2CPE_ENC_6_INVERT - encoders[i].set_inverted(I2CPE_ENC_6_INVERT); + encoders[i].set_inverted(ENABLED(I2CPE_ENC_6_INVERT)); #endif #ifdef I2CPE_ENC_6_EC_METHOD encoders[i].set_ec_method(I2CPE_ENC_6_EC_METHOD); diff --git a/Marlin/src/feature/filwidth.h b/Marlin/src/feature/filwidth.h index e234380e98..9eb1e77762 100644 --- a/Marlin/src/feature/filwidth.h +++ b/Marlin/src/feature/filwidth.h @@ -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 diff --git a/Marlin/src/feature/fwretract.cpp b/Marlin/src/feature/fwretract.cpp index 4077d8d1c2..bf47a6b2d5 100644 --- a/Marlin/src/feature/fwretract.cpp +++ b/Marlin/src/feature/fwretract.cpp @@ -73,10 +73,10 @@ void FWRetract::reset() { settings.swap_retract_recover_feedrate_mm_s = RETRACT_RECOVER_FEEDRATE_SWAP; current_hop = 0.0; - LOOP_L_N(i, EXTRUDERS) { - retracted[i] = false; - E_TERN_(retracted_swap[i] = false); - current_retract[i] = 0.0; + EXTRUDER_LOOP() { + retracted[e] = false; + E_TERN_(retracted_swap[e] = false); + current_retract[e] = 0.0; } } @@ -111,10 +111,10 @@ void FWRetract::retract(const bool retracting E_OPTARG(bool swapping/*=false*/)) " swapping ", swapping, " active extruder ", active_extruder ); - LOOP_L_N(i, EXTRUDERS) { - SERIAL_ECHOLNPGM("retracted[", i, "] ", AS_DIGIT(retracted[i])); + EXTRUDER_LOOP() { + SERIAL_ECHOLNPGM("retracted[", e, "] ", AS_DIGIT(retracted[e])); #if HAS_MULTI_EXTRUDER - SERIAL_ECHOLNPGM("retracted_swap[", i, "] ", AS_DIGIT(retracted_swap[i])); + SERIAL_ECHOLNPGM("retracted_swap[", e, "] ", AS_DIGIT(retracted_swap[e])); #endif } SERIAL_ECHOLNPGM("current_position.z ", current_position.z); @@ -184,10 +184,10 @@ void FWRetract::retract(const bool retracting E_OPTARG(bool swapping/*=false*/)) SERIAL_ECHOLNPGM("retracting ", AS_DIGIT(retracting)); SERIAL_ECHOLNPGM("swapping ", AS_DIGIT(swapping)); SERIAL_ECHOLNPGM("active_extruder ", active_extruder); - LOOP_L_N(i, EXTRUDERS) { - SERIAL_ECHOLNPGM("retracted[", i, "] ", AS_DIGIT(retracted[i])); + EXTRUDER_LOOP() { + SERIAL_ECHOLNPGM("retracted[", e, "] ", AS_DIGIT(retracted[e])); #if HAS_MULTI_EXTRUDER - SERIAL_ECHOLNPGM("retracted_swap[", i, "] ", AS_DIGIT(retracted_swap[i])); + SERIAL_ECHOLNPGM("retracted_swap[", e, "] ", AS_DIGIT(retracted_swap[e])); #endif } SERIAL_ECHOLNPGM("current_position.z ", current_position.z); diff --git a/Marlin/src/feature/fwretract.h b/Marlin/src/feature/fwretract.h index d6d0432e3a..081ec44c05 100644 --- a/Marlin/src/feature/fwretract.h +++ b/Marlin/src/feature/fwretract.h @@ -64,7 +64,7 @@ public: static void reset(); static void refresh_autoretract() { - LOOP_L_N(i, EXTRUDERS) retracted[i] = false; + EXTRUDER_LOOP() retracted[e] = false; } static void enable_autoretract(const bool enable) { diff --git a/Marlin/src/feature/host_actions.cpp b/Marlin/src/feature/host_actions.cpp index c03a6bc597..3385076701 100644 --- a/Marlin/src/feature/host_actions.cpp +++ b/Marlin/src/feature/host_actions.cpp @@ -177,7 +177,7 @@ void HostUI::action(FSTR_P const fstr, const bool eol) { #endif #if HAS_FILAMENT_SENSOR if (runout.filament_ran_out) { // Disable a triggered sensor - runout.enabled = false; + runout.enabled[active_extruder] = false; runout.reset(); } #endif diff --git a/Marlin/src/feature/joystick.cpp b/Marlin/src/feature/joystick.cpp index 7f91c1549b..daa642d32e 100644 --- a/Marlin/src/feature/joystick.cpp +++ b/Marlin/src/feature/joystick.cpp @@ -68,13 +68,13 @@ Joystick joystick; void Joystick::report() { SERIAL_ECHOPGM("Joystick"); #if HAS_JOY_ADC_X - SERIAL_ECHOPGM_P(SP_X_STR, JOY_X(x.raw)); + SERIAL_ECHOPGM_P(SP_X_STR, JOY_X(x.getraw())); #endif #if HAS_JOY_ADC_Y - SERIAL_ECHOPGM_P(SP_Y_STR, JOY_Y(y.raw)); + SERIAL_ECHOPGM_P(SP_Y_STR, JOY_Y(y.getraw())); #endif #if HAS_JOY_ADC_Z - SERIAL_ECHOPGM_P(SP_Z_STR, JOY_Z(z.raw)); + SERIAL_ECHOPGM_P(SP_Z_STR, JOY_Z(z.getraw())); #endif #if HAS_JOY_ADC_EN SERIAL_ECHO_TERNARY(READ(JOY_EN_PIN), " EN=", "HIGH (dis", "LOW (en", "abled)"); @@ -91,29 +91,29 @@ Joystick joystick; if (READ(JOY_EN_PIN)) return; #endif - auto _normalize_joy = [](float &axis_jog, const int16_t raw, const int16_t (&joy_limits)[4]) { + auto _normalize_joy = [](float &axis_jog, const raw_adc_t raw, const raw_adc_t (&joy_limits)[4]) { if (WITHIN(raw, joy_limits[0], joy_limits[3])) { // within limits, check deadzone if (raw > joy_limits[2]) axis_jog = (raw - joy_limits[2]) / float(joy_limits[3] - joy_limits[2]); else if (raw < joy_limits[1]) - axis_jog = (raw - joy_limits[1]) / float(joy_limits[1] - joy_limits[0]); // negative value + axis_jog = int16_t(raw - joy_limits[1]) / float(joy_limits[1] - joy_limits[0]); // negative value // Map normal to jog value via quadratic relationship axis_jog = SIGN(axis_jog) * sq(axis_jog); } }; #if HAS_JOY_ADC_X - static constexpr int16_t joy_x_limits[4] = JOY_X_LIMITS; - _normalize_joy(norm_jog.x, JOY_X(x.raw), joy_x_limits); + static constexpr raw_adc_t joy_x_limits[4] = JOY_X_LIMITS; + _normalize_joy(norm_jog.x, JOY_X(x.getraw()), joy_x_limits); #endif #if HAS_JOY_ADC_Y - static constexpr int16_t joy_y_limits[4] = JOY_Y_LIMITS; - _normalize_joy(norm_jog.y, JOY_Y(y.raw), joy_y_limits); + static constexpr raw_adc_t joy_y_limits[4] = JOY_Y_LIMITS; + _normalize_joy(norm_jog.y, JOY_Y(y.getraw()), joy_y_limits); #endif #if HAS_JOY_ADC_Z - static constexpr int16_t joy_z_limits[4] = JOY_Z_LIMITS; - _normalize_joy(norm_jog.z, JOY_Z(z.raw), joy_z_limits); + static constexpr raw_adc_t joy_z_limits[4] = JOY_Z_LIMITS; + _normalize_joy(norm_jog.z, JOY_Z(z.getraw()), joy_z_limits); #endif } @@ -163,7 +163,7 @@ Joystick joystick; // norm_jog values of [-1 .. 1] maps linearly to [-feedrate .. feedrate] xyz_float_t move_dist{0}; float hypot2 = 0; - LOOP_LINEAR_AXES(i) if (norm_jog[i]) { + LOOP_NUM_AXES(i) if (norm_jog[i]) { move_dist[i] = seg_time * norm_jog[i] * TERN(EXTENSIBLE_UI, manual_feedrate_mm_s, planner.settings.max_feedrate_mm_s)[i]; hypot2 += sq(move_dist[i]); } diff --git a/Marlin/src/feature/leds/neopixel.cpp b/Marlin/src/feature/leds/neopixel.cpp index 3569cb180d..4f104234f1 100644 --- a/Marlin/src/feature/leds/neopixel.cpp +++ b/Marlin/src/feature/leds/neopixel.cpp @@ -44,14 +44,14 @@ Adafruit_NeoPixel Marlin_NeoPixel::adaneo1(NEOPIXEL_PIXELS, NEOPIXEL_PIN, NEOPIX #ifdef NEOPIXEL_BKGD_INDEX_FIRST - void Marlin_NeoPixel::set_background_color(uint8_t r, uint8_t g, uint8_t b, uint8_t w) { - for (int background_led = NEOPIXEL_BKGD_INDEX_FIRST; background_led <= NEOPIXEL_BKGD_INDEX_LAST; background_led++) + void Marlin_NeoPixel::set_background_color(const uint8_t r, const uint8_t g, const uint8_t b, const uint8_t w) { + for (int background_led = NEOPIXEL_BKGD_INDEX_FIRST; background_led <= NEOPIXEL_BKGD_INDEX_LAST; background_led++) set_pixel_color(background_led, adaneo1.Color(r, g, b, w)); } void Marlin_NeoPixel::reset_background_color() { constexpr uint8_t background_color[4] = NEOPIXEL_BKGD_COLOR; - set_background_color(background_color[0], background_color[1], background_color[2], background_color[3]); + set_background_color(background_color); } #endif @@ -108,7 +108,7 @@ void Marlin_NeoPixel::init() { set_color(adaneo1.Color TERN(LED_USER_PRESET_STARTUP, (LED_USER_PRESET_RED, LED_USER_PRESET_GREEN, LED_USER_PRESET_BLUE, LED_USER_PRESET_WHITE), - (0, 0, 0, 0)) + (255, 255, 255, 255)) ); } diff --git a/Marlin/src/feature/leds/neopixel.h b/Marlin/src/feature/leds/neopixel.h index 1a38ed1a19..d71aa25770 100644 --- a/Marlin/src/feature/leds/neopixel.h +++ b/Marlin/src/feature/leds/neopixel.h @@ -88,7 +88,8 @@ public: static void set_color(const uint32_t c); #ifdef NEOPIXEL_BKGD_INDEX_FIRST - static void set_background_color(uint8_t r, uint8_t g, uint8_t b, uint8_t w); + static void set_background_color(const uint8_t r, const uint8_t g, const uint8_t b, const uint8_t w); + static void set_background_color(const uint8_t (&rgbw)[4]) { set_background_color(rgbw[0], rgbw[1], rgbw[2], rgbw[3]); } static void reset_background_color(); #endif diff --git a/Marlin/src/feature/mixing.cpp b/Marlin/src/feature/mixing.cpp index 9ebc90127f..b1a069e320 100644 --- a/Marlin/src/feature/mixing.cpp +++ b/Marlin/src/feature/mixing.cpp @@ -63,7 +63,7 @@ void Mixer::normalize(const uint8_t tool_index) { #ifdef MIXER_NORMALIZER_DEBUG SERIAL_ECHOPGM("Mixer: Old relation : [ "); MIXER_STEPPER_LOOP(i) { - SERIAL_ECHO_F(collector[i] / csum, 3); + SERIAL_DECIMAL(collector[i] / csum); SERIAL_CHAR(' '); } SERIAL_ECHOLNPGM("]"); diff --git a/Marlin/src/feature/mmu/mmu2.cpp b/Marlin/src/feature/mmu/mmu2.cpp index 2813337c63..63fd8ae059 100644 --- a/Marlin/src/feature/mmu/mmu2.cpp +++ b/Marlin/src/feature/mmu/mmu2.cpp @@ -140,9 +140,14 @@ uint8_t MMU2::get_current_tool() { } #if EITHER(HAS_PRUSA_MMU2S, MMU_EXTRUDER_SENSOR) - #define FILAMENT_PRESENT() (READ(FIL_RUNOUT1_PIN) != FIL_RUNOUT1_STATE) + #define FILAMENT_PRESENT() (READ(FIL_RUNOUT1_PIN) != runout.out_state()) #endif +void mmu2_attn_buzz(const bool two=false) { + BUZZ(200, 404); + if (two) { BUZZ(10, 0); BUZZ(200, 404); } +} + void MMU2::mmu_loop() { switch (state) { @@ -525,7 +530,7 @@ static void mmu2_not_responding() { while (!thermalManager.wait_for_hotend(active_extruder, false)) safe_delay(100); load_filament_to_nozzle(index); #else - BUZZ(400, 40); + ERR_BUZZ(); #endif } break; @@ -544,7 +549,7 @@ static void mmu2_not_responding() { active_extruder = 0; } #else - BUZZ(400, 40); + ERR_BUZZ(); #endif } break; @@ -613,7 +618,7 @@ static void mmu2_not_responding() { while (!thermalManager.wait_for_hotend(active_extruder, false)) safe_delay(100); load_filament_to_nozzle(index); #else - BUZZ(400, 40); + ERR_BUZZ(); #endif } break; @@ -633,7 +638,7 @@ static void mmu2_not_responding() { extruder = index; active_extruder = 0; #else - BUZZ(400, 40); + ERR_BUZZ(); #endif } break; @@ -707,7 +712,7 @@ static void mmu2_not_responding() { while (!thermalManager.wait_for_hotend(active_extruder, false)) safe_delay(100); load_filament_to_nozzle(index); #else - BUZZ(400, 40); + ERR_BUZZ(); #endif } break; @@ -726,7 +731,7 @@ static void mmu2_not_responding() { extruder = index; active_extruder = 0; #else - BUZZ(400, 40); + ERR_BUZZ(); #endif } break; @@ -811,25 +816,26 @@ void MMU2::manage_response(const bool move_axes, const bool turn_off_nozzle) { if (turn_off_nozzle && resume_hotend_temp) { thermalManager.setTargetHotend(resume_hotend_temp, active_extruder); LCD_MESSAGE(MSG_HEATING); - BUZZ(200, 40); + ERR_BUZZ(); while (!thermalManager.wait_for_hotend(active_extruder, false)) safe_delay(1000); } - if (move_axes && all_axes_homed()) { - LCD_MESSAGE(MSG_MMU2_RESUMING); - BUZZ(198, 404); BUZZ(4, 0); BUZZ(198, 404); + LCD_MESSAGE(MSG_MMU2_RESUMING); + mmu2_attn_buzz(true); + #pragma GCC diagnostic push + #pragma GCC diagnostic ignored "-Wmaybe-uninitialized" + + if (move_axes && all_axes_homed()) { // Move XY to starting position, then Z do_blocking_move_to_xy(resume_position, feedRate_t(NOZZLE_PARK_XY_FEEDRATE)); // Move Z_AXIS to saved position do_blocking_move_to_z(resume_position.z, feedRate_t(NOZZLE_PARK_Z_FEEDRATE)); } - else { - BUZZ(198, 404); BUZZ(4, 0); BUZZ(198, 404); - LCD_MESSAGE(MSG_MMU2_RESUMING); - } + + #pragma GCC diagnostic pop } } } @@ -898,7 +904,7 @@ void MMU2::load_filament(const uint8_t index) { command(MMU_CMD_L0 + index); manage_response(false, false); - BUZZ(200, 404); + mmu2_attn_buzz(); } /** @@ -909,7 +915,7 @@ bool MMU2::load_filament_to_nozzle(const uint8_t index) { if (!_enabled) return false; if (thermalManager.tooColdToExtrude(active_extruder)) { - BUZZ(200, 404); + mmu2_attn_buzz(); LCD_ALERTMESSAGE(MSG_HOTEND_TOO_COLD); return false; } @@ -924,7 +930,7 @@ bool MMU2::load_filament_to_nozzle(const uint8_t index) { extruder = index; active_extruder = 0; load_to_nozzle(); - BUZZ(200, 404); + mmu2_attn_buzz(); } return success; } @@ -945,7 +951,7 @@ bool MMU2::eject_filament(const uint8_t index, const bool recover) { if (!_enabled) return false; if (thermalManager.tooColdToExtrude(active_extruder)) { - BUZZ(200, 404); + mmu2_attn_buzz(); LCD_ALERTMESSAGE(MSG_HOTEND_TOO_COLD); return false; } @@ -961,12 +967,11 @@ bool MMU2::eject_filament(const uint8_t index, const bool recover) { if (recover) { LCD_MESSAGE(MSG_MMU2_EJECT_RECOVER); - BUZZ(200, 404); + mmu2_attn_buzz(); TERN_(HOST_PROMPT_SUPPORT, hostui.prompt_do(PROMPT_USER_CONTINUE, F("MMU2 Eject Recover"), FPSTR(CONTINUE_STR))); TERN_(EXTENSIBLE_UI, ExtUI::onUserConfirmRequired(F("MMU2 Eject Recover"))); TERN_(HAS_RESUME_CONTINUE, wait_for_user_response()); - BUZZ(200, 404); - BUZZ(200, 404); + mmu2_attn_buzz(true); command(MMU_CMD_R0); manage_response(false, false); @@ -979,7 +984,7 @@ bool MMU2::eject_filament(const uint8_t index, const bool recover) { set_runout_valid(false); - BUZZ(200, 404); + mmu2_attn_buzz(); stepper.disable_extruder(); @@ -994,7 +999,7 @@ bool MMU2::unload() { if (!_enabled) return false; if (thermalManager.tooColdToExtrude(active_extruder)) { - BUZZ(200, 404); + mmu2_attn_buzz(); LCD_ALERTMESSAGE(MSG_HOTEND_TOO_COLD); return false; } @@ -1005,7 +1010,7 @@ bool MMU2::unload() { command(MMU_CMD_U0); manage_response(false, true); - BUZZ(200, 404); + mmu2_attn_buzz(); // no active tool extruder = MMU2_NO_TOOL; diff --git a/Marlin/src/feature/pause.cpp b/Marlin/src/feature/pause.cpp index 69c25cbe33..8aa1ff4f03 100644 --- a/Marlin/src/feature/pause.cpp +++ b/Marlin/src/feature/pause.cpp @@ -57,7 +57,7 @@ #if ENABLED(EXTENSIBLE_UI) #include "../lcd/extui/ui_api.h" -#elif ENABLED(DWIN_CREALITY_LCD_ENHANCED) +#elif ENABLED(DWIN_LCD_PROUI) #include "../lcd/e3v2/proui/dwin.h" #endif @@ -208,13 +208,22 @@ bool load_filament(const_float_t slow_load_length/*=0*/, const_float_t fast_load while (wait_for_user) { impatient_beep(max_beep_count); #if BOTH(FILAMENT_CHANGE_RESUME_ON_INSERT, FILAMENT_RUNOUT_SENSOR) - #if ENABLED(MULTI_FILAMENT_SENSOR) - #define _CASE_INSERTED(N) case N-1: if (READ(FIL_RUNOUT##N##_PIN) != FIL_RUNOUT##N##_STATE) wait_for_user = false; break; - switch (active_extruder) { - REPEAT_1(NUM_RUNOUT_SENSORS, _CASE_INSERTED) + #if MULTI_FILAMENT_SENSOR + LOOP_S_LE_N(i, 1, NUM_RUNOUT_SENSORS) { + pin_t pin; + switch (i) { + default: continue; + #define _CASE_RUNOUT(N) case N: pin = FIL_RUNOUT##N##_PIN; break; + REPEAT_1(NUM_RUNOUT_SENSORS, _CASE_RUNOUT) + #undef _CASE_RUNOUT + } + const RunoutMode rm = runout.mode[i - 1]; + if (rm != RM_NONE && rm != RM_MOTION_SENSOR && extDigitalRead(pin) != runout.out_state(i - 1)) + wait_for_user = false; } #else - if (READ(FIL_RUNOUT_PIN) != FIL_RUNOUT_STATE) wait_for_user = false; + if (READ(FIL_RUNOUT_PIN) != runout.out_state(active_extruder)) + wait_for_user = false; #endif #endif idle_no_sleep(); @@ -281,7 +290,7 @@ bool load_filament(const_float_t slow_load_length/*=0*/, const_float_t fast_load // Show "Purge More" / "Resume" menu and wait for reply KEEPALIVE_STATE(PAUSED_FOR_USER); wait_for_user = false; - #if EITHER(HAS_MARLINUI_MENU, DWIN_CREALITY_LCD_ENHANCED) + #if EITHER(HAS_MARLINUI_MENU, DWIN_LCD_PROUI) ui.pause_show_message(PAUSE_MESSAGE_OPTION); // Also sets PAUSE_RESPONSE_WAIT_FOR #else pause_menu_response = PAUSE_RESPONSE_WAIT_FOR; @@ -407,6 +416,7 @@ bool pause_print(const_float_t retract, const xyz_pos_t &park_point, const bool #endif TERN_(HOST_PROMPT_SUPPORT, hostui.prompt_open(PROMPT_INFO, F("Pause"), FPSTR(DISMISS_STR))); + TERN_(DWIN_LCD_PROUI, DWIN_Print_Pause()); // Indicate that the printer is paused ++did_pause_print; @@ -549,7 +559,7 @@ void wait_for_confirmation(const bool is_reload/*=false*/, const int8_t max_beep TERN_(EXTENSIBLE_UI, ExtUI::onStatusChanged(GET_TEXT_F(MSG_REHEATING))); - TERN_(DWIN_CREALITY_LCD_ENHANCED, LCD_MESSAGE(MSG_REHEATING)); + TERN_(DWIN_LCD_PROUI, LCD_MESSAGE(MSG_REHEATING)); // Re-enable the heaters if they timed out HOTEND_LOOP() thermalManager.reset_hotend_idle_timer(e); @@ -567,7 +577,7 @@ void wait_for_confirmation(const bool is_reload/*=false*/, const int8_t max_beep TERN_(HOST_PROMPT_SUPPORT, hostui.prompt_do(PROMPT_USER_CONTINUE, GET_TEXT_F(MSG_REHEATDONE), FPSTR(CONTINUE_STR))); TERN_(EXTENSIBLE_UI, ExtUI::onUserConfirmRequired(GET_TEXT_F(MSG_REHEATDONE))); - TERN_(DWIN_CREALITY_LCD_ENHANCED, LCD_MESSAGE(MSG_REHEATDONE)); + TERN_(DWIN_LCD_PROUI, LCD_MESSAGE(MSG_REHEATDONE)); IF_DISABLED(PAUSE_REHEAT_FAST_RESUME, wait_for_user = true); @@ -709,9 +719,9 @@ void resume_print(const_float_t slow_load_length/*=0*/, const_float_t fast_load_ TERN_(HAS_FILAMENT_SENSOR, runout.reset()); - TERN_(HAS_STATUS_MESSAGE, ui.reset_status()); + TERN(DWIN_LCD_PROUI, DWIN_Print_Resume(), ui.reset_status()); TERN_(HAS_MARLINUI_MENU, ui.return_to_status()); - TERN_(DWIN_CREALITY_LCD_ENHANCED, HMI_ReturnScreen()); + TERN_(DWIN_LCD_PROUI, HMI_ReturnScreen()); } #endif // ADVANCED_PAUSE_FEATURE diff --git a/Marlin/src/feature/powerloss.cpp b/Marlin/src/feature/powerloss.cpp index 214c248d35..0fc195e7dd 100644 --- a/Marlin/src/feature/powerloss.cpp +++ b/Marlin/src/feature/powerloss.cpp @@ -196,7 +196,7 @@ void PrintJobRecovery::save(const bool force/*=false*/, const float zraise/*=POW #if DISABLED(NO_VOLUMETRICS) info.flag.volumetric_enabled = parser.volumetric_enabled; #if HAS_MULTI_EXTRUDER - for (int8_t e = 0; e < EXTRUDERS; e++) info.filament_size[e] = planner.filament_size[e]; + EXTRUDER_LOOP() info.filament_size[e] = planner.filament_size[e]; #else if (parser.volumetric_enabled) info.filament_size[0] = planner.filament_size[active_extruder]; #endif @@ -461,7 +461,7 @@ void PrintJobRecovery::resume() { // Recover volumetric extrusion state #if DISABLED(NO_VOLUMETRICS) #if HAS_MULTI_EXTRUDER - for (int8_t e = 0; e < EXTRUDERS; e++) { + EXTRUDER_LOOP() { sprintf_P(cmd, PSTR("M200T%iD%s"), e, dtostrf(info.filament_size[e], 1, 3, str_1)); gcode.process_subcommands_now(cmd); } @@ -511,7 +511,7 @@ void PrintJobRecovery::resume() { // Restore retract and hop state from an active `G10` command #if ENABLED(FWRETRACT) - LOOP_L_N(e, EXTRUDERS) { + EXTRUDER_LOOP() { if (info.retract[e] != 0.0) { fwretract.current_retract[e] = info.retract[e]; fwretract.retracted[e] = true; @@ -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]); } @@ -634,7 +634,7 @@ void PrintJobRecovery::resume() { #if DISABLED(NO_VOLUMETRICS) DEBUG_ECHOPGM("filament_size:"); - LOOP_L_N(i, EXTRUDERS) DEBUG_ECHOLNPGM(" ", info.filament_size[i]); + EXTRUDER_LOOP() DEBUG_ECHOLNPGM(" ", info.filament_size[e]); DEBUG_EOL(); #endif @@ -666,7 +666,7 @@ void PrintJobRecovery::resume() { #if ENABLED(FWRETRACT) DEBUG_ECHOPGM("retract: "); - for (int8_t e = 0; e < EXTRUDERS; e++) { + EXTRUDER_LOOP() { DEBUG_ECHO(info.retract[e]); if (e < EXTRUDERS - 1) DEBUG_CHAR(','); } diff --git a/Marlin/src/feature/runout.cpp b/Marlin/src/feature/runout.cpp index f8e8e9d309..d6317edb46 100644 --- a/Marlin/src/feature/runout.cpp +++ b/Marlin/src/feature/runout.cpp @@ -32,9 +32,9 @@ FilamentMonitor runout; -bool FilamentMonitorBase::enabled = true, - FilamentMonitorBase::filament_ran_out; // = false - +bool FilamentMonitorBase::enabled[NUM_RUNOUT_SENSORS], // Initialized by settings.load + FilamentMonitorBase::filament_ran_out; // = false +RunoutMode FilamentMonitorBase::mode[NUM_RUNOUT_SENSORS]; // Initialized by settings.load #if ENABLED(HOST_ACTION_COMMANDS) bool FilamentMonitorBase::host_handling; // = false #endif @@ -46,15 +46,9 @@ bool FilamentMonitorBase::enabled = true, #include "../core/debug_out.h" #endif -#if HAS_FILAMENT_RUNOUT_DISTANCE - float RunoutResponseDelayed::runout_distance_mm = FILAMENT_RUNOUT_DISTANCE_MM; - volatile float RunoutResponseDelayed::runout_mm_countdown[NUM_RUNOUT_SENSORS]; - #if ENABLED(FILAMENT_MOTION_SENSOR) - uint8_t FilamentSensorEncoder::motion_detected; - #endif -#else - int8_t RunoutResponseDebounced::runout_count[NUM_RUNOUT_SENSORS]; // = 0 -#endif +float RunoutResponseDelayed::runout_distance_mm[NUM_RUNOUT_SENSORS]; // Initialized by settings.load +volatile float RunoutResponseDelayed::runout_mm_countdown[NUM_RUNOUT_SENSORS]; +uint8_t FilamentSensorCore::motion_detected; // // Filament Runout event handler @@ -69,7 +63,7 @@ bool FilamentMonitorBase::enabled = true, #if ENABLED(EXTENSIBLE_UI) #include "../lcd/extui/ui_api.h" -#elif ENABLED(DWIN_CREALITY_LCD_ENHANCED) +#elif ENABLED(DWIN_LCD_PROUI) #include "../lcd/e3v2/proui/dwin.h" #endif @@ -89,7 +83,7 @@ void event_filament_runout(const uint8_t extruder) { #endif TERN_(EXTENSIBLE_UI, ExtUI::onFilamentRunout(ExtUI::getTool(extruder))); - TERN_(DWIN_CREALITY_LCD_ENHANCED, DWIN_FilamentRunout(extruder)); + TERN_(DWIN_LCD_PROUI, DWIN_FilamentRunout(extruder)); #if ANY(HOST_PROMPT_SUPPORT, HOST_ACTION_COMMANDS, MULTI_FILAMENT_SENSOR) const char tool = '0' + TERN0(MULTI_FILAMENT_SENSOR, extruder); diff --git a/Marlin/src/feature/runout.h b/Marlin/src/feature/runout.h index e74d857a79..261831403b 100644 --- a/Marlin/src/feature/runout.h +++ b/Marlin/src/feature/runout.h @@ -47,25 +47,37 @@ void event_filament_runout(const uint8_t extruder); template class TFilamentMonitor; -class FilamentSensorEncoder; -class FilamentSensorSwitch; +class FilamentSensorCore; class RunoutResponseDelayed; -class RunoutResponseDebounced; /********************************* TEMPLATE SPECIALIZATION *********************************/ typedef TFilamentMonitor< - TERN(HAS_FILAMENT_RUNOUT_DISTANCE, RunoutResponseDelayed, RunoutResponseDebounced), - TERN(FILAMENT_MOTION_SENSOR, FilamentSensorEncoder, FilamentSensorSwitch) + RunoutResponseDelayed, + FilamentSensorCore > FilamentMonitor; extern FilamentMonitor runout; /*******************************************************************************************/ +enum RunoutMode : uint8_t { + RM_NONE, + RM_OUT_ON_LOW, + RM_OUT_ON_HIGH, + RM_RESERVED3, + RM_RESERVED4, + RM_RESERVED5, + RM_RESERVED6, + RM_MOTION_SENSOR +}; + class FilamentMonitorBase { public: - static bool enabled, filament_ran_out; + static bool enabled[NUM_RUNOUT_SENSORS], filament_ran_out; + static RunoutMode mode[NUM_RUNOUT_SENSORS]; + + static uint8_t out_state(const uint8_t e=0) { return mode[e] == RM_OUT_ON_HIGH ? HIGH : LOW; } #if ENABLED(HOST_ACTION_COMMANDS) static bool host_handling; @@ -95,19 +107,14 @@ class TFilamentMonitor : public FilamentMonitorBase { // Call this method when filament is present, // so the response can reset its counter. - static void filament_present(const uint8_t extruder) { - response.filament_present(extruder); - } - - #if HAS_FILAMENT_RUNOUT_DISTANCE - static float& runout_distance() { return response.runout_distance_mm; } - static void set_runout_distance(const_float_t mm) { response.runout_distance_mm = mm; } - #endif + static void filament_present(const uint8_t e) { response.filament_present(e); } + static float& runout_distance(const uint8_t e=0) { return response.runout_distance_mm[e]; } + static void set_runout_distance(const_float_t mm, const uint8_t e=0) { response.runout_distance_mm[e] = mm; } // Handle a block completion. RunoutResponseDelayed uses this to // add up the length of filament moved while the filament is out. static void block_completed(const block_t * const b) { - if (enabled) { + if (enabled[active_extruder]) { response.block_completed(b); sensor.block_completed(b); } @@ -115,12 +122,12 @@ class TFilamentMonitor : public FilamentMonitorBase { // Give the response a chance to update its counter. static void run() { - if (enabled && !filament_ran_out && (printingIsActive() || did_pause_print)) { - TERN_(HAS_FILAMENT_RUNOUT_DISTANCE, cli()); // Prevent RunoutResponseDelayed::block_completed from accumulating here + if (enabled[active_extruder] && mode[active_extruder] != RM_NONE && !filament_ran_out && (printingIsActive() || did_pause_print)) { + cli(); // Prevent RunoutResponseDelayed::block_completed from accumulating here response.run(); sensor.run(); const uint8_t runout_flags = response.has_run_out(); - TERN_(HAS_FILAMENT_RUNOUT_DISTANCE, sei()); + sei(); #if MULTI_FILAMENT_SENSOR #if ENABLED(WATCH_ALL_RUNOUT_SENSORS) const bool ran_out = !!runout_flags; // any sensor triggers @@ -203,6 +210,7 @@ class FilamentSensorBase { #undef _INIT_RUNOUT_PIN #undef INIT_RUNOUT_PIN } + // Return a bitmask of runout pin states static uint8_t poll_runout_pins() { @@ -213,103 +221,64 @@ class FilamentSensorBase { // Return a bitmask of runout flag states (1 bits always indicates runout) static uint8_t poll_runout_states() { - return poll_runout_pins() ^ uint8_t(0 - #if NUM_RUNOUT_SENSORS >= 1 - | (FIL_RUNOUT1_STATE ? 0 : _BV(1 - 1)) - #endif - #if NUM_RUNOUT_SENSORS >= 2 - | (FIL_RUNOUT2_STATE ? 0 : _BV(2 - 1)) - #endif - #if NUM_RUNOUT_SENSORS >= 3 - | (FIL_RUNOUT3_STATE ? 0 : _BV(3 - 1)) - #endif - #if NUM_RUNOUT_SENSORS >= 4 - | (FIL_RUNOUT4_STATE ? 0 : _BV(4 - 1)) - #endif - #if NUM_RUNOUT_SENSORS >= 5 - | (FIL_RUNOUT5_STATE ? 0 : _BV(5 - 1)) - #endif - #if NUM_RUNOUT_SENSORS >= 6 - | (FIL_RUNOUT6_STATE ? 0 : _BV(6 - 1)) - #endif - #if NUM_RUNOUT_SENSORS >= 7 - | (FIL_RUNOUT7_STATE ? 0 : _BV(7 - 1)) - #endif - #if NUM_RUNOUT_SENSORS >= 8 - | (FIL_RUNOUT8_STATE ? 0 : _BV(8 - 1)) - #endif - ); + #define _OR_INVERT(N) | (runout.out_state(N-1) ? 0 : _BV(N-1)) + return poll_runout_pins() ^ uint8_t(0 REPEAT_1(NUM_RUNOUT_SENSORS, _OR_INVERT)); + #undef _OR_INVERT } }; -#if ENABLED(FILAMENT_MOTION_SENSOR) +class FilamentSensorCore : public FilamentSensorBase { + private: + static uint8_t motion_detected; - /** - * This sensor uses a magnetic encoder disc and a Hall effect - * sensor (or a slotted disc and optical sensor). The state - * will toggle between 0 and 1 on filament movement. It can detect - * filament runout and stripouts or jams. - */ - class FilamentSensorEncoder : public FilamentSensorBase { - private: - static uint8_t motion_detected; + static bool poll_runout_state(const uint8_t extruder) { + const uint8_t runout_states = poll_runout_states(); + #if MULTI_FILAMENT_SENSOR + if ( !TERN0(DUAL_X_CARRIAGE, idex_is_duplicating()) + && !TERN0(MULTI_NOZZLE_DUPLICATION, extruder_duplication_enabled) + ) return TEST(runout_states, extruder); // A specific extruder ran out + #else + UNUSED(extruder); + #endif + return !!runout_states; // Any extruder ran out + } - static void poll_motion_sensor() { - static uint8_t old_state; - const uint8_t new_state = poll_runout_pins(), - change = old_state ^ new_state; - old_state = new_state; + static void poll_motion_sensor() { + static uint8_t old_state; + const uint8_t new_state = poll_runout_pins(), + change = old_state ^ new_state; + old_state = new_state; - #if ENABLED(FILAMENT_RUNOUT_SENSOR_DEBUG) - if (change) { - SERIAL_ECHOPGM("Motion detected:"); - LOOP_L_N(e, NUM_RUNOUT_SENSORS) - if (TEST(change, e)) SERIAL_CHAR(' ', '0' + e); - SERIAL_EOL(); - } - #endif + #if ENABLED(FILAMENT_RUNOUT_SENSOR_DEBUG) + if (change) { + SERIAL_ECHOPGM("Motion detected:"); + LOOP_L_N(e, NUM_RUNOUT_SENSORS) + if (TEST(change, e)) SERIAL_CHAR(' ', '0' + e); + SERIAL_EOL(); + } + #endif - motion_detected |= change; + motion_detected |= change; + } + + public: + static void block_completed(const block_t * const b) { + if (runout.mode[active_extruder] != RM_MOTION_SENSOR) return; + + // If the sensor wheel has moved since the last call to + // this method reset the runout counter for the extruder. + if (TEST(motion_detected, b->extruder)) + filament_present(b->extruder); + + // Clear motion triggers for next block + motion_detected = 0; + } + + static void run() { + if (runout.mode[active_extruder] == RM_MOTION_SENSOR) { + poll_motion_sensor(); } - - public: - static void block_completed(const block_t * const b) { - // If the sensor wheel has moved since the last call to - // this method reset the runout counter for the extruder. - if (TEST(motion_detected, b->extruder)) - filament_present(b->extruder); - - // Clear motion triggers for next block - motion_detected = 0; - } - - static void run() { poll_motion_sensor(); } - }; - -#else - - /** - * This is a simple endstop switch in the path of the filament. - * It can detect filament runout, but not stripouts or jams. - */ - class FilamentSensorSwitch : public FilamentSensorBase { - private: - static bool poll_runout_state(const uint8_t extruder) { - const uint8_t runout_states = poll_runout_states(); - #if MULTI_FILAMENT_SENSOR - if ( !TERN0(DUAL_X_CARRIAGE, idex_is_duplicating()) - && !TERN0(MULTI_NOZZLE_DUPLICATION, extruder_duplication_enabled) - ) return TEST(runout_states, extruder); // A specific extruder ran out - #else - UNUSED(extruder); - #endif - return !!runout_states; // Any extruder ran out - } - - public: - static void block_completed(const block_t * const) {} - - static void run() { + else if (runout.mode[active_extruder] != RM_NONE) { LOOP_L_N(s, NUM_RUNOUT_SENSORS) { const bool out = poll_runout_state(s); if (!out) filament_present(s); @@ -322,92 +291,55 @@ class FilamentSensorBase { #endif } } - }; + } +}; -#endif // !FILAMENT_MOTION_SENSOR - /********************************* RESPONSE TYPE *********************************/ -#if HAS_FILAMENT_RUNOUT_DISTANCE +// RunoutResponseDelayed triggers a runout event only if the length +// of filament specified by FIL_RUNOUT_DISTANCE_MM has been fed +// during a runout condition. +class RunoutResponseDelayed { + private: + static volatile float runout_mm_countdown[NUM_RUNOUT_SENSORS]; - // RunoutResponseDelayed triggers a runout event only if the length - // of filament specified by FILAMENT_RUNOUT_DISTANCE_MM has been fed - // during a runout condition. - class RunoutResponseDelayed { - private: - static volatile float runout_mm_countdown[NUM_RUNOUT_SENSORS]; + public: + static float runout_distance_mm[NUM_RUNOUT_SENSORS]; - public: - static float runout_distance_mm; + static void reset() { + LOOP_L_N(i, NUM_RUNOUT_SENSORS) filament_present(i); + } - static void reset() { - LOOP_L_N(i, NUM_RUNOUT_SENSORS) filament_present(i); - } - - static void run() { - #if ENABLED(FILAMENT_RUNOUT_SENSOR_DEBUG) - static millis_t t = 0; - const millis_t ms = millis(); - if (ELAPSED(ms, t)) { - t = millis() + 1000UL; - LOOP_L_N(i, NUM_RUNOUT_SENSORS) - SERIAL_ECHOF(i ? F(", ") : F("Remaining mm: "), runout_mm_countdown[i]); - SERIAL_EOL(); - } - #endif - } - - static uint8_t has_run_out() { - uint8_t runout_flags = 0; - LOOP_L_N(i, NUM_RUNOUT_SENSORS) if (runout_mm_countdown[i] < 0) SBI(runout_flags, i); - return runout_flags; - } - - static void filament_present(const uint8_t extruder) { - runout_mm_countdown[extruder] = runout_distance_mm; - } - - static void block_completed(const block_t * const b) { - if (b->steps.x || b->steps.y || b->steps.z || did_pause_print) { // Allow pause purge move to re-trigger runout state - // Only trigger on extrusion with XYZ movement to allow filament change and retract/recover. - const uint8_t e = b->extruder; - const int32_t steps = b->steps.e; - runout_mm_countdown[e] -= (TEST(b->direction_bits, E_AXIS) ? -steps : steps) * planner.mm_per_step[E_AXIS_N(e)]; + static void run() { + #if ENABLED(FILAMENT_RUNOUT_SENSOR_DEBUG) + static millis_t t = 0; + const millis_t ms = millis(); + if (ELAPSED(ms, t)) { + t = millis() + 1000UL; + LOOP_L_N(i, NUM_RUNOUT_SENSORS) + SERIAL_ECHOF(i ? F(", ") : F("Remaining mm: "), runout_mm_countdown[i]); + SERIAL_EOL(); } + #endif + } + + static uint8_t has_run_out() { + uint8_t runout_flags = 0; + LOOP_L_N(i, NUM_RUNOUT_SENSORS) if (runout_mm_countdown[i] < 0) SBI(runout_flags, i); + return runout_flags; + } + + static void filament_present(const uint8_t extruder) { + runout_mm_countdown[extruder] = runout_distance_mm[extruder]; + } + + static void block_completed(const block_t * const b) { + if (b->steps.x || b->steps.y || b->steps.z || did_pause_print) { // Allow pause purge move to re-trigger runout state + // Only trigger on extrusion with XYZ movement to allow filament change and retract/recover. + const uint8_t e = b->extruder; + const int32_t steps = b->steps.e; + runout_mm_countdown[e] -= (TEST(b->direction_bits, E_AXIS) ? -steps : steps) * planner.mm_per_step[E_AXIS_N(e)]; } - }; - -#else // !HAS_FILAMENT_RUNOUT_DISTANCE - - // RunoutResponseDebounced triggers a runout event after a runout - // condition has been detected runout_threshold times in a row. - - class RunoutResponseDebounced { - private: - static constexpr int8_t runout_threshold = FILAMENT_RUNOUT_THRESHOLD; - static int8_t runout_count[NUM_RUNOUT_SENSORS]; - - public: - static void reset() { - LOOP_L_N(i, NUM_RUNOUT_SENSORS) filament_present(i); - } - - static void run() { - LOOP_L_N(i, NUM_RUNOUT_SENSORS) if (runout_count[i] >= 0) runout_count[i]--; - } - - static uint8_t has_run_out() { - uint8_t runout_flags = 0; - LOOP_L_N(i, NUM_RUNOUT_SENSORS) if (runout_count[i] < 0) SBI(runout_flags, i); - return runout_flags; - } - - static void block_completed(const block_t * const) { } - - static void filament_present(const uint8_t extruder) { - runout_count[extruder] = runout_threshold; - } - }; - -#endif // !HAS_FILAMENT_RUNOUT_DISTANCE + } +}; diff --git a/Marlin/src/feature/solenoid.cpp b/Marlin/src/feature/solenoid.cpp index b6795d1a1e..861e44ed05 100644 --- a/Marlin/src/feature/solenoid.cpp +++ b/Marlin/src/feature/solenoid.cpp @@ -27,31 +27,25 @@ #include "solenoid.h" #include "../module/motion.h" // for active_extruder - -// PARKING_EXTRUDER options alter the default behavior of solenoids, this ensures compliance of M380-381 - -#if ENABLED(PARKING_EXTRUDER) - #include "../module/tool_change.h" -#endif +#include "../module/tool_change.h" // Used primarily with MANUAL_SOLENOID_CONTROL -static void set_solenoid(const uint8_t num, const bool active) { - const uint8_t value = active ? PE_MAGNET_ON_STATE : !PE_MAGNET_ON_STATE; - #define _SOL_CASE(N) case N: TERN_(HAS_SOLENOID_##N, OUT_WRITE(SOL##N##_PIN, value)); break; +static void set_solenoid(const uint8_t num, const uint8_t state) { + #define _SOL_CASE(N) case N: TERN_(HAS_SOLENOID_##N, OUT_WRITE(SOL##N##_PIN, state)); break; switch (num) { REPEAT(8, _SOL_CASE) default: SERIAL_ECHO_MSG(STR_INVALID_SOLENOID); break; } #if ENABLED(PARKING_EXTRUDER) - if (!active && active_extruder == num) // If active extruder's solenoid is disabled, carriage is considered parked + if (state == LOW && active_extruder == num) // If active extruder's solenoid is disabled, carriage is considered parked parking_extruder_set_parked(true); #endif } -void enable_solenoid(const uint8_t num) { set_solenoid(num, true); } -void disable_solenoid(const uint8_t num) { set_solenoid(num, false); } -void enable_solenoid_on_active_extruder() { } +// PARKING_EXTRUDER options alter the default behavior of solenoids to ensure compliance of M380-381 +void enable_solenoid(const uint8_t num) { set_solenoid(num, TERN1(PARKING_EXTRUDER, PE_MAGNET_ON_STATE)); } +void disable_solenoid(const uint8_t num) { set_solenoid(num, TERN0(PARKING_EXTRUDER, !PE_MAGNET_ON_STATE)); } void disable_all_solenoids() { #define _SOL_DISABLE(N) TERN_(HAS_SOLENOID_##N, disable_solenoid(N)); diff --git a/Marlin/src/feature/solenoid.h b/Marlin/src/feature/solenoid.h index 2ba4983fb0..3131aeb868 100644 --- a/Marlin/src/feature/solenoid.h +++ b/Marlin/src/feature/solenoid.h @@ -21,7 +21,6 @@ */ #pragma once -void enable_solenoid_on_active_extruder(); void disable_all_solenoids(); void enable_solenoid(const uint8_t num); void disable_solenoid(const uint8_t num); diff --git a/Marlin/src/feature/stepper_driver_safety.cpp b/Marlin/src/feature/stepper_driver_safety.cpp index 11b90954b4..b8762da9b0 100644 --- a/Marlin/src/feature/stepper_driver_safety.cpp +++ b/Marlin/src/feature/stepper_driver_safety.cpp @@ -65,15 +65,18 @@ void stepper_driver_backward_check() { TEST_BACKWARD(I, 8); TEST_BACKWARD(J, 9); TEST_BACKWARD(K, 10); + TEST_BACKWARD(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 diff --git a/Marlin/src/feature/tmc_util.cpp b/Marlin/src/feature/tmc_util.cpp index c69772bebc..cb970c7ebc 100644 --- a/Marlin/src/feature/tmc_util.cpp +++ b/Marlin/src/feature/tmc_util.cpp @@ -429,6 +429,18 @@ if (monitor_tmc_driver(stepperK, need_update_error_counters, need_debug_reporting)) step_current_down(stepperK); #endif + #if AXIS_IS_TMC(U) + if (monitor_tmc_driver(stepperU, need_update_error_counters, need_debug_reporting)) + step_current_down(stepperU); + #endif + #if AXIS_IS_TMC(V) + if (monitor_tmc_driver(stepperV, need_update_error_counters, need_debug_reporting)) + step_current_down(stepperV); + #endif + #if AXIS_IS_TMC(W) + if (monitor_tmc_driver(stepperW, need_update_error_counters, need_debug_reporting)) + step_current_down(stepperW); + #endif #if AXIS_IS_TMC(E0) (void)monitor_tmc_driver(stepperE0, need_update_error_counters, need_debug_reporting); @@ -809,6 +821,15 @@ #if AXIS_IS_TMC(K) if (k) tmc_status(stepperK, n); #endif + #if AXIS_IS_TMC(U) + if (u) tmc_status(stepperU, n); + #endif + #if AXIS_IS_TMC(V) + if (v) tmc_status(stepperV, n); + #endif + #if AXIS_IS_TMC(W) + if (w) tmc_status(stepperW, n); + #endif if (TERN0(HAS_EXTRUDERS, e)) { #if AXIS_IS_TMC(E0) @@ -883,6 +904,15 @@ #if AXIS_IS_TMC(K) if (k) tmc_parse_drv_status(stepperK, n); #endif + #if AXIS_IS_TMC(U) + if (u) tmc_parse_drv_status(stepperU, n); + #endif + #if AXIS_IS_TMC(V) + if (v) tmc_parse_drv_status(stepperV, n); + #endif + #if AXIS_IS_TMC(W) + if (w) tmc_parse_drv_status(stepperW, n); + #endif if (TERN0(HAS_EXTRUDERS, e)) { #if AXIS_IS_TMC(E0) @@ -1088,6 +1118,15 @@ #if AXIS_IS_TMC(K) if (k) tmc_get_registers(stepperK, n); #endif + #if AXIS_IS_TMC(U) + if (u) tmc_get_registers(stepperU, n); + #endif + #if AXIS_IS_TMC(V) + if (v) tmc_get_registers(stepperV, n); + #endif + #if AXIS_IS_TMC(W) + if (w) tmc_get_registers(stepperW, n); + #endif if (TERN0(HAS_EXTRUDERS, e)) { #if AXIS_IS_TMC(E0) @@ -1244,6 +1283,15 @@ void test_tmc_connection(LOGICAL_AXIS_ARGS(const bool)) { #if AXIS_IS_TMC(K) if (k) axis_connection += test_connection(stepperK); #endif + #if AXIS_IS_TMC(U) + if (u) axis_connection += test_connection(stepperU); + #endif + #if AXIS_IS_TMC(V) + if (v) axis_connection += test_connection(stepperV); + #endif + #if AXIS_IS_TMC(W) + if (w) axis_connection += test_connection(stepperW); + #endif if (TERN0(HAS_EXTRUDERS, e)) { #if AXIS_IS_TMC(E0) @@ -1313,6 +1361,15 @@ void test_tmc_connection(LOGICAL_AXIS_ARGS(const bool)) { #if AXIS_HAS_SPI(K) SET_CS_PIN(K); #endif + #if AXIS_HAS_SPI(U) + SET_CS_PIN(U); + #endif + #if AXIS_HAS_SPI(V) + SET_CS_PIN(V); + #endif + #if AXIS_HAS_SPI(W) + SET_CS_PIN(W); + #endif #if AXIS_HAS_SPI(E0) SET_CS_PIN(E0); #endif diff --git a/Marlin/src/feature/tmc_util.h b/Marlin/src/feature/tmc_util.h index fc333b09dd..c10bab6274 100644 --- a/Marlin/src/feature/tmc_util.h +++ b/Marlin/src/feature/tmc_util.h @@ -348,7 +348,7 @@ void test_tmc_connection(LOGICAL_AXIS_DECL(const bool, true)); #if USE_SENSORLESS // Track enabled status of stealthChop and only re-enable where applicable - struct sensorless_t { bool LINEAR_AXIS_ARGS(), x2, y2, z2, z3, z4; }; + struct sensorless_t { bool NUM_AXIS_ARGS(), x2, y2, z2, z3, z4; }; #if ENABLED(IMPROVE_HOMING_RELIABILITY) extern millis_t sg_guard_period; diff --git a/Marlin/src/feature/x_twist.cpp b/Marlin/src/feature/x_twist.cpp index 8910091239..b5ad25cba8 100644 --- a/Marlin/src/feature/x_twist.cpp +++ b/Marlin/src/feature/x_twist.cpp @@ -36,8 +36,8 @@ void XATC::reset() { constexpr float xzo[] = XATC_Z_OFFSETS; static_assert(COUNT(xzo) == XATC_MAX_POINTS, "XATC_Z_OFFSETS is the wrong size."); COPY(z_offset, xzo); - xatc.spacing = (probe.max_x() - probe.min_x()) / (XATC_MAX_POINTS - 1); - xatc.start = probe.min_x(); + start = probe.min_x(); + spacing = (probe.max_x() - start) / (XATC_MAX_POINTS - 1); enabled = true; } @@ -45,14 +45,10 @@ void XATC::print_points() { SERIAL_ECHOLNPGM(" X-Twist Correction:"); LOOP_L_N(x, XATC_MAX_POINTS) { SERIAL_CHAR(' '); - if (!isnan(z_offset[x])) { - if (z_offset[x] >= 0) SERIAL_CHAR('+'); - SERIAL_ECHO_F(z_offset[x], 3); - } - else { - LOOP_L_N(i, 6) - SERIAL_CHAR(i ? '=' : ' '); - } + if (!isnan(z_offset[x])) + serial_offset(z_offset[x]); + else + LOOP_L_N(i, 6) SERIAL_CHAR(i ? '=' : ' '); } SERIAL_EOL(); } @@ -63,8 +59,7 @@ float XATC::compensation(const xy_pos_t &raw) { if (!enabled) return 0; if (NEAR_ZERO(spacing)) return 0; float t = (raw.x - start) / spacing; - int i = FLOOR(t); - LIMIT(i, 0, XATC_MAX_POINTS - 2); + const int i = constrain(FLOOR(t), 0, XATC_MAX_POINTS - 2); t -= i; return lerp(t, z_offset[i], z_offset[i + 1]); } diff --git a/Marlin/src/gcode/bedlevel/M420.cpp b/Marlin/src/gcode/bedlevel/M420.cpp index 3c23e85a1d..c8325b1fc5 100644 --- a/Marlin/src/gcode/bedlevel/M420.cpp +++ b/Marlin/src/gcode/bedlevel/M420.cpp @@ -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(); diff --git a/Marlin/src/gcode/bedlevel/abl/G29.cpp b/Marlin/src/gcode/bedlevel/abl/G29.cpp index 20f2369b03..ac8eff0e95 100644 --- a/Marlin/src/gcode/bedlevel/abl/G29.cpp +++ b/Marlin/src/gcode/bedlevel/abl/G29.cpp @@ -36,10 +36,6 @@ #include "../../../module/probe.h" #include "../../queue.h" -#if HAS_STATUS_MESSAGE - #include "../../../lcd/marlinui.h" -#endif - #if ENABLED(AUTO_BED_LEVELING_LINEAR) #include "../../../libs/least_squares_fit.h" #endif @@ -48,14 +44,12 @@ #include "../../../libs/vector_3.h" #endif -#define DEBUG_OUT ENABLED(DEBUG_LEVELING_FEATURE) -#include "../../../core/debug_out.h" - +#include "../../../lcd/marlinui.h" #if ENABLED(EXTENSIBLE_UI) #include "../../../lcd/extui/ui_api.h" #elif ENABLED(DWIN_CREALITY_LCD) #include "../../../lcd/e3v2/creality/dwin.h" -#elif ENABLED(DWIN_CREALITY_LCD_ENHANCED) +#elif ENABLED(DWIN_LCD_PROUI) #include "../../../lcd/e3v2/proui/dwin.h" #endif @@ -63,6 +57,9 @@ #include "../../../module/tool_change.h" #endif +#define DEBUG_OUT ENABLED(DEBUG_LEVELING_FEATURE) +#include "../../../core/debug_out.h" + #if ABL_USES_GRID #if ENABLED(PROBE_Y_FIRST) #define PR_OUTER_VAR abl.meshCount.x @@ -127,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) @@ -311,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); } @@ -321,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(); @@ -422,12 +420,13 @@ G29_TYPE GcodeSuite::G29() { planner.synchronize(); + TERN_(EXTENSIBLE_UI, ExtUI::onLevelingStart()); + #if ENABLED(AUTO_BED_LEVELING_3POINT) if (DEBUGGING(LEVELING)) DEBUG_ECHOLNPGM("> 3-point Leveling"); points[0].z = points[1].z = points[2].z = 0; // Probe at 3 arbitrary points #elif ENABLED(AUTO_BED_LEVELING_BILINEAR) - TERN_(EXTENSIBLE_UI, ExtUI::onMeshLevelingStart()); - TERN_(DWIN_CREALITY_LCD_ENHANCED, DWIN_MeshLevelingStart()); + TERN_(DWIN_CREALITY_LCD_ENHANCED, DWIN_LevelingStart()); #endif if (!faux) { @@ -438,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); @@ -453,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; } @@ -533,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); @@ -580,6 +611,7 @@ G29_TYPE GcodeSuite::G29() { SERIAL_ECHOLNPGM("Grid probing done."); // Re-enable software endstops, if needed SET_SOFT_ENDSTOP_LOOSE(false); + TERN_(EXTENSIBLE_UI, ExtUI::onLevelingDone()); } #elif ENABLED(AUTO_BED_LEVELING_3POINT) @@ -609,6 +641,8 @@ G29_TYPE GcodeSuite::G29() { abl.reenable = false; } + TERN_(EXTENSIBLE_UI, ExtUI::onLevelingDone()); + } #endif // AUTO_BED_LEVELING_3POINT @@ -681,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 @@ -752,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) @@ -877,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); } @@ -902,7 +940,7 @@ G29_TYPE GcodeSuite::G29() { process_subcommands_now(F(Z_PROBE_END_SCRIPT)); #endif - TERN_(HAS_DWIN_E3V2_BASIC, DWIN_CompletedLeveling()); + TERN_(HAS_DWIN_E3V2_BASIC, DWIN_LevelingDone()); TERN_(HAS_MULTI_HOTEND, if (abl.tool_index != 0) tool_change(abl.tool_index)); diff --git a/Marlin/src/gcode/bedlevel/abl/M421.cpp b/Marlin/src/gcode/bedlevel/abl/M421.cpp index 182dc32515..0c12268cb1 100644 --- a/Marlin/src/gcode/bedlevel/abl/M421.cpp +++ b/Marlin/src/gcode/bedlevel/abl/M421.cpp @@ -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); diff --git a/Marlin/src/gcode/bedlevel/mbl/G29.cpp b/Marlin/src/gcode/bedlevel/mbl/G29.cpp index 4ffeec6eec..e04073b122 100644 --- a/Marlin/src/gcode/bedlevel/mbl/G29.cpp +++ b/Marlin/src/gcode/bedlevel/mbl/G29.cpp @@ -40,7 +40,7 @@ #if ENABLED(EXTENSIBLE_UI) #include "../../../lcd/extui/ui_api.h" -#elif ENABLED(DWIN_CREALITY_LCD_ENHANCED) +#elif ENABLED(DWIN_LCD_PROUI) #include "../../../lcd/e3v2/proui/dwin.h" #endif @@ -104,7 +104,45 @@ void GcodeSuite::G29() { mbl_probe_index = 0; if (!ui.wait_for_move) { queue.inject(parser.seen_test('N') ? F("G28" TERN(CAN_SET_LEVELING_AFTER_G28, "L0", "") "\nG29S2") : F("G29S2")); - TERN_(EXTENSIBLE_UI, ExtUI::onMeshLevelingStart()); + 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; @@ -117,9 +155,11 @@ void GcodeSuite::G29() { // For each G29 S2... if (mbl_probe_index == 0) { // Move close to the bed before the first point - do_blocking_move_to_z(0.4f + do_blocking_move_to_z( #ifdef MANUAL_PROBE_START_Z - + (MANUAL_PROBE_START_Z) - 0.4f + MANUAL_PROBE_START_Z + #else + 0.4f #endif ); } @@ -127,6 +167,7 @@ void GcodeSuite::G29() { // Save Z for the previous mesh position mbl.set_zigzag_z(mbl_probe_index - 1, current_position.z); TERN_(EXTENSIBLE_UI, ExtUI::onMeshUpdate(ix, iy, current_position.z)); + TERN_(DWIN_LCD_PROUI, DWIN_MeshUpdate(_MIN(mbl_probe_index, GRID_MAX_POINTS), int(GRID_MAX_POINTS), current_position.z)); SET_SOFT_ENDSTOP_LOOSE(false); } // If there's another point to sample, move there with optional lift. @@ -153,8 +194,7 @@ void GcodeSuite::G29() { mbl_probe_index = -1; SERIAL_ECHOLNPGM("Mesh probing done."); TERN_(HAS_STATUS_MESSAGE, LCD_MESSAGE(MSG_MESH_DONE)); - BUZZ(100, 659); - BUZZ(100, 698); + OKAY_BUZZ(); home_all_axes(); set_bed_leveling_enabled(true); @@ -166,6 +206,7 @@ void GcodeSuite::G29() { #endif TERN_(LCD_BED_LEVELING, ui.wait_for_move = false); + TERN_(EXTENSIBLE_UI, ExtUI::onLevelingDone()); } break; @@ -193,7 +234,7 @@ void GcodeSuite::G29() { if (parser.seenval('Z')) { mbl.z_values[ix][iy] = parser.value_linear_units(); TERN_(EXTENSIBLE_UI, ExtUI::onMeshUpdate(ix, iy, mbl.z_values[ix][iy])); - TERN_(DWIN_CREALITY_LCD_ENHANCED, DWIN_MeshUpdate(ix, iy, mbl.z_values[ix][iy])); + TERN_(DWIN_LCD_PROUI, DWIN_MeshUpdate(ix, iy, mbl.z_values[ix][iy])); } else return echo_not_entered('Z'); diff --git a/Marlin/src/gcode/bedlevel/ubl/M421.cpp b/Marlin/src/gcode/bedlevel/ubl/M421.cpp index ac6f97b00a..c11a20ebf3 100644 --- a/Marlin/src/gcode/bedlevel/ubl/M421.cpp +++ b/Marlin/src/gcode/bedlevel/ubl/M421.cpp @@ -33,7 +33,7 @@ #if ENABLED(EXTENSIBLE_UI) #include "../../../lcd/extui/ui_api.h" -#elif ENABLED(DWIN_CREALITY_LCD_ENHANCED) +#elif ENABLED(DWIN_LCD_PROUI) #include "../../../lcd/e3v2/proui/dwin.h" #endif @@ -69,7 +69,7 @@ void GcodeSuite::M421() { float &zval = ubl.z_values[ij.x][ij.y]; // Altering this Mesh Point zval = hasN ? NAN : parser.value_linear_units() + (hasQ ? zval : 0); // N=NAN, Z=NEWVAL, or Q=ADDVAL TERN_(EXTENSIBLE_UI, ExtUI::onMeshUpdate(ij.x, ij.y, zval)); // Ping ExtUI in case it's showing the mesh - TERN_(DWIN_CREALITY_LCD_ENHANCED, DWIN_MeshUpdate(ij.x, ij.y, zval)); + TERN_(DWIN_LCD_PROUI, DWIN_MeshUpdate(ij.x, ij.y, zval)); } } diff --git a/Marlin/src/gcode/calibrate/G28.cpp b/Marlin/src/gcode/calibrate/G28.cpp index 4d8891d55b..07896856a1 100644 --- a/Marlin/src/gcode/calibrate/G28.cpp +++ b/Marlin/src/gcode/calibrate/G28.cpp @@ -51,7 +51,7 @@ #include "../../lcd/extui/ui_api.h" #elif ENABLED(DWIN_CREALITY_LCD) #include "../../lcd/e3v2/creality/dwin.h" -#elif ENABLED(DWIN_CREALITY_LCD_ENHANCED) +#elif ENABLED(DWIN_LCD_PROUI) #include "../../lcd/e3v2/proui/dwin.h" #endif @@ -82,15 +82,13 @@ #if ENABLED(SENSORLESS_HOMING) sensorless_t stealth_states { - LINEAR_AXIS_LIST(tmc_enable_stallguard(stepperX), tmc_enable_stallguard(stepperY), false, false, false, false) - , false - #if AXIS_HAS_STALLGUARD(X2) - || tmc_enable_stallguard(stepperX2) - #endif - , false - #if AXIS_HAS_STALLGUARD(Y2) - || tmc_enable_stallguard(stepperY2) - #endif + NUM_AXIS_LIST( + TERN0(X_SENSORLESS, tmc_enable_stallguard(stepperX)), + TERN0(Y_SENSORLESS, tmc_enable_stallguard(stepperY)), + false, false, false, false + ) + , TERN0(X2_SENSORLESS, tmc_enable_stallguard(stepperX2)) + , TERN0(Y2_SENSORLESS, tmc_enable_stallguard(stepperY2)) }; #endif @@ -101,14 +99,10 @@ current_position.set(0.0, 0.0); #if ENABLED(SENSORLESS_HOMING) && DISABLED(ENDSTOPS_ALWAYS_ON_DEFAULT) - tmc_disable_stallguard(stepperX, stealth_states.x); - tmc_disable_stallguard(stepperY, stealth_states.y); - #if AXIS_HAS_STALLGUARD(X2) - tmc_disable_stallguard(stepperX2, stealth_states.x2); - #endif - #if AXIS_HAS_STALLGUARD(Y2) - tmc_disable_stallguard(stepperY2, stealth_states.y2); - #endif + TERN_(X_SENSORLESS, tmc_disable_stallguard(stepperX, stealth_states.x)); + TERN_(X2_SENSORLESS, tmc_disable_stallguard(stepperX2, stealth_states.x2)); + TERN_(Y_SENSORLESS, tmc_disable_stallguard(stepperY, stealth_states.y)); + TERN_(Y2_SENSORLESS, tmc_disable_stallguard(stepperY2, stealth_states.y2)); #endif } @@ -220,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(); @@ -239,7 +233,7 @@ void GcodeSuite::G28() { set_and_report_grblstate(M_HOMING); #endif - TERN_(HAS_DWIN_E3V2_BASIC, DWIN_StartHoming()); + TERN_(HAS_DWIN_E3V2_BASIC, DWIN_HomingStart()); TERN_(EXTENSIBLE_UI, ExtUI::onHomingStart()); planner.synchronize(); // Wait for planner moves to finish! @@ -264,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 @@ -292,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); @@ -327,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) @@ -370,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 @@ -400,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); @@ -440,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(); @@ -548,12 +567,21 @@ 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(); - TERN_(HAS_DWIN_E3V2_BASIC, DWIN_CompletedHoming()); - TERN_(EXTENSIBLE_UI, ExtUI::onHomingComplete()); + TERN_(HAS_DWIN_E3V2_BASIC, DWIN_HomingDone()); + TERN_(EXTENSIBLE_UI, ExtUI::onHomingDone()); report_current_position(); @@ -568,7 +596,7 @@ void GcodeSuite::G28() { // If not, this will need a PROGMEM directive and an accessor. #define _EN_ITEM(N) , E_AXIS static constexpr AxisEnum L64XX_axis_xref[MAX_L64XX] = { - LINEAR_AXIS_LIST(X_AXIS, Y_AXIS, Z_AXIS, I_AXIS, J_AXIS, K_AXIS), + NUM_AXIS_LIST(X_AXIS, Y_AXIS, Z_AXIS, I_AXIS, J_AXIS, K_AXIS, U_AXIS, V_AXIS, W_AXIS), X_AXIS, Y_AXIS, Z_AXIS, Z_AXIS, Z_AXIS REPEAT(E_STEPPERS, _EN_ITEM) }; diff --git a/Marlin/src/gcode/calibrate/G33.cpp b/Marlin/src/gcode/calibrate/G33.cpp index a4b9aec01b..7f487abd6b 100644 --- a/Marlin/src/gcode/calibrate/G33.cpp +++ b/Marlin/src/gcode/calibrate/G33.cpp @@ -98,8 +98,7 @@ void ac_cleanup(TERN_(HAS_MULTI_HOTEND, const uint8_t old_tool_index)) { void print_signed_float(FSTR_P const prefix, const_float_t f) { SERIAL_ECHOPGM(" "); SERIAL_ECHOF(prefix, AS_CHAR(':')); - if (f >= 0) SERIAL_CHAR('+'); - SERIAL_ECHO_F(f, 2); + serial_offset(f); } /** @@ -344,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; @@ -537,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: @@ -585,14 +584,14 @@ void GcodeSuite::G33() { // Normalize angles to least-squares if (_angle_results) { float a_sum = 0.0f; - LOOP_LINEAR_AXES(axis) a_sum += delta_tower_angle_trim[axis]; - LOOP_LINEAR_AXES(axis) delta_tower_angle_trim[axis] -= a_sum / 3.0f; + LOOP_NUM_AXES(axis) a_sum += delta_tower_angle_trim[axis]; + LOOP_NUM_AXES(axis) delta_tower_angle_trim[axis] -= a_sum / 3.0f; } // adjust delta_height and endstops by the max amount const float z_temp = _MAX(delta_endstop_adj.a, delta_endstop_adj.b, delta_endstop_adj.c); delta_height -= z_temp; - LOOP_LINEAR_AXES(axis) delta_endstop_adj[axis] -= z_temp; + LOOP_NUM_AXES(axis) delta_endstop_adj[axis] -= z_temp; } recalc_delta_settings(); NOMORE(zero_std_dev_min, zero_std_dev); diff --git a/Marlin/src/gcode/calibrate/G34_M422.cpp b/Marlin/src/gcode/calibrate/G34_M422.cpp index 61e817fe94..d1f82e7e98 100644 --- a/Marlin/src/gcode/calibrate/G34_M422.cpp +++ b/Marlin/src/gcode/calibrate/G34_M422.cpp @@ -493,7 +493,7 @@ void GcodeSuite::M422() { return; } - xy_pos_t *pos_dest = ( + xy_pos_t * const pos_dest = ( TERN_(HAS_Z_STEPPER_ALIGN_STEPPER_XY, !is_probe_point ? z_stepper_align.stepper_xy :) z_stepper_align.xy ); @@ -504,24 +504,25 @@ void GcodeSuite::M422() { } // Get the Probe Position Index or Z Stepper Index - int8_t position_index; - if (is_probe_point) { - position_index = parser.intval('S') - 1; - if (!WITHIN(position_index, 0, int8_t(NUM_Z_STEPPER_DRIVERS) - 1)) { - SERIAL_ECHOLNPGM("?(S) Probe-position index invalid."); - return; - } - } + int8_t position_index = 1; + FSTR_P err_string = F("?(S) Probe-position"); + if (is_probe_point) + position_index = parser.intval('S'); else { #if HAS_Z_STEPPER_ALIGN_STEPPER_XY - position_index = parser.intval('W') - 1; - if (!WITHIN(position_index, 0, NUM_Z_STEPPER_DRIVERS - 1)) { - SERIAL_ECHOLNPGM("?(W) Z-stepper index invalid."); - return; - } + err_string = F("?(W) Z-stepper"); + position_index = parser.intval('W'); #endif } + if (!WITHIN(position_index, 1, NUM_Z_STEPPER_DRIVERS)) { + SERIAL_ECHOF(err_string); + SERIAL_ECHOLNPGM(" index invalid (1.." STRINGIFY(NUM_Z_STEPPER_DRIVERS) ")."); + return; + } + + --position_index; + const xy_pos_t pos = { parser.floatval('X', pos_dest[position_index].x), parser.floatval('Y', pos_dest[position_index].y) diff --git a/Marlin/src/gcode/calibrate/G425.cpp b/Marlin/src/gcode/calibrate/G425.cpp index a2dec64bc3..450a715117 100644 --- a/Marlin/src/gcode/calibrate/G425.cpp +++ b/Marlin/src/gcode/calibrate/G425.cpp @@ -85,10 +85,19 @@ #if ALL(HAS_K_AXIS, CALIBRATION_MEASURE_KMIN, CALIBRATION_MEASURE_KMAX) #define HAS_K_CENTER 1 #endif +#if ALL(HAS_U_AXIS, CALIBRATION_MEASURE_UMIN, CALIBRATION_MEASURE_UMAX) + #define HAS_U_CENTER 1 +#endif +#if ALL(HAS_V_AXIS, CALIBRATION_MEASURE_VMIN, CALIBRATION_MEASURE_VMAX) + #define HAS_V_CENTER 1 +#endif +#if ALL(HAS_W_AXIS, CALIBRATION_MEASURE_WMIN, CALIBRATION_MEASURE_WMAX) + #define HAS_W_CENTER 1 +#endif enum side_t : uint8_t { TOP, RIGHT, FRONT, LEFT, BACK, NUM_SIDES, - LIST_N(DOUBLE(SUB3(LINEAR_AXES)), IMINIMUM, IMAXIMUM, JMINIMUM, JMAXIMUM, KMINIMUM, KMAXIMUM) + LIST_N(DOUBLE(SECONDARY_AXES), IMINIMUM, IMAXIMUM, JMINIMUM, JMAXIMUM, KMINIMUM, KMAXIMUM, UMINIMUM, UMAXIMUM, VMINIMUM, VMAXIMUM, WMINIMUM, WMAXIMUM) }; static constexpr xyz_pos_t true_center CALIBRATION_OBJECT_CENTER; @@ -282,6 +291,15 @@ inline void probe_side(measurements_t &m, const float uncertainty, const side_t #if HAS_K_AXIS && AXIS_CAN_CALIBRATE(K) _PCASE(K); #endif + #if HAS_U_AXIS && AXIS_CAN_CALIBRATE(U) + _PCASE(U); + #endif + #if HAS_V_AXIS && AXIS_CAN_CALIBRATE(V) + _PCASE(V); + #endif + #if HAS_W_AXIS && AXIS_CAN_CALIBRATE(W) + _PCASE(W); + #endif default: return; } @@ -335,6 +353,12 @@ inline void probe_sides(measurements_t &m, const float uncertainty) { TERN_(CALIBRATION_MEASURE_JMAX, probe_side(m, uncertainty, JMAXIMUM, probe_top_at_edge)); TERN_(CALIBRATION_MEASURE_KMIN, probe_side(m, uncertainty, KMINIMUM, probe_top_at_edge)); TERN_(CALIBRATION_MEASURE_KMAX, probe_side(m, uncertainty, KMAXIMUM, probe_top_at_edge)); + TERN_(CALIBRATION_MEASURE_UMIN, probe_side(m, uncertainty, UMINIMUM, probe_top_at_edge)); + TERN_(CALIBRATION_MEASURE_UMAX, probe_side(m, uncertainty, UMAXIMUM, probe_top_at_edge)); + TERN_(CALIBRATION_MEASURE_VMIN, probe_side(m, uncertainty, VMINIMUM, probe_top_at_edge)); + TERN_(CALIBRATION_MEASURE_VMAX, probe_side(m, uncertainty, VMAXIMUM, probe_top_at_edge)); + TERN_(CALIBRATION_MEASURE_WMIN, probe_side(m, uncertainty, WMINIMUM, probe_top_at_edge)); + TERN_(CALIBRATION_MEASURE_WMAX, probe_side(m, uncertainty, WMAXIMUM, probe_top_at_edge)); // Compute the measured center of the calibration object. TERN_(HAS_X_CENTER, m.obj_center.x = (m.obj_side[LEFT] + m.obj_side[RIGHT]) / 2); @@ -342,6 +366,9 @@ inline void probe_sides(measurements_t &m, const float uncertainty) { TERN_(HAS_I_CENTER, m.obj_center.i = (m.obj_side[IMINIMUM] + m.obj_side[IMAXIMUM]) / 2); TERN_(HAS_J_CENTER, m.obj_center.j = (m.obj_side[JMINIMUM] + m.obj_side[JMAXIMUM]) / 2); TERN_(HAS_K_CENTER, m.obj_center.k = (m.obj_side[KMINIMUM] + m.obj_side[KMAXIMUM]) / 2); + TERN_(HAS_U_CENTER, m.obj_center.u = (m.obj_side[UMINIMUM] + m.obj_side[UMAXIMUM]) / 2); + TERN_(HAS_V_CENTER, m.obj_center.v = (m.obj_side[VMINIMUM] + m.obj_side[VMAXIMUM]) / 2); + TERN_(HAS_W_CENTER, m.obj_center.w = (m.obj_side[WMINIMUM] + m.obj_side[WMAXIMUM]) / 2); // Compute the outside diameter of the nozzle at the height // at which it makes contact with the calibration object @@ -352,13 +379,16 @@ inline void probe_sides(measurements_t &m, const float uncertainty) { // The difference between the known and the measured location // of the calibration object is the positional error - LINEAR_AXIS_CODE( + NUM_AXIS_CODE( m.pos_error.x = TERN0(HAS_X_CENTER, true_center.x - m.obj_center.x), m.pos_error.y = TERN0(HAS_Y_CENTER, true_center.y - m.obj_center.y), m.pos_error.z = true_center.z - m.obj_center.z, m.pos_error.i = TERN0(HAS_I_CENTER, true_center.i - m.obj_center.i), m.pos_error.j = TERN0(HAS_J_CENTER, true_center.j - m.obj_center.j), - m.pos_error.k = TERN0(HAS_K_CENTER, true_center.k - m.obj_center.k) + m.pos_error.k = TERN0(HAS_K_CENTER, true_center.k - m.obj_center.k), + m.pos_error.u = TERN0(HAS_U_CENTER, true_center.u - m.obj_center.u), + m.pos_error.v = TERN0(HAS_V_CENTER, true_center.v - m.obj_center.v), + m.pos_error.w = TERN0(HAS_W_CENTER, true_center.w - m.obj_center.w) ); } @@ -406,6 +436,30 @@ inline void probe_sides(measurements_t &m, const float uncertainty) { SERIAL_ECHOLNPGM(" " STR_K_MAX ": ", m.obj_side[KMAXIMUM]); #endif #endif + #if HAS_U_AXIS + #if ENABLED(CALIBRATION_MEASURE_UMIN) + SERIAL_ECHOLNPAIR(" " STR_U_MIN ": ", m.obj_side[UMINIMUM]); + #endif + #if ENABLED(CALIBRATION_MEASURE_UMAX) + SERIAL_ECHOLNPAIR(" " STR_U_MAX ": ", m.obj_side[UMAXIMUM]); + #endif + #endif + #if HAS_V_AXIS + #if ENABLED(CALIBRATION_MEASURE_VMIN) + SERIAL_ECHOLNPAIR(" " STR_V_MIN ": ", m.obj_side[VMINIMUM]); + #endif + #if ENABLED(CALIBRATION_MEASURE_VMAX) + SERIAL_ECHOLNPAIR(" " STR_V_MAX ": ", m.obj_side[VMAXIMUM]); + #endif + #endif + #if HAS_W_AXIS + #if ENABLED(CALIBRATION_MEASURE_WMIN) + SERIAL_ECHOLNPAIR(" " STR_W_MIN ": ", m.obj_side[WMINIMUM]); + #endif + #if ENABLED(CALIBRATION_MEASURE_WMAX) + SERIAL_ECHOLNPAIR(" " STR_W_MAX ": ", m.obj_side[WMAXIMUM]); + #endif + #endif SERIAL_EOL(); } @@ -427,6 +481,15 @@ inline void probe_sides(measurements_t &m, const float uncertainty) { #if HAS_K_CENTER SERIAL_ECHOLNPGM_P(SP_K_STR, m.obj_center.k); #endif + #if HAS_U_CENTER + SERIAL_ECHOLNPGM_P(SP_U_STR, m.obj_center.u); + #endif + #if HAS_V_CENTER + SERIAL_ECHOLNPGM_P(SP_V_STR, m.obj_center.v); + #endif + #if HAS_W_CENTER + SERIAL_ECHOLNPGM_P(SP_W_STR, m.obj_center.w); + #endif SERIAL_EOL(); } @@ -475,6 +538,30 @@ inline void probe_sides(measurements_t &m, const float uncertainty) { SERIAL_ECHOLNPGM(" " STR_K_MAX ": ", m.backlash[KMAXIMUM]); #endif #endif + #if HAS_U_AXIS && AXIS_CAN_CALIBRATE(U) + #if ENABLED(CALIBRATION_MEASURE_UMIN) + SERIAL_ECHOLNPGM(" " STR_U_MIN ": ", m.backlash[UMINIMUM]); + #endif + #if ENABLED(CALIBRATION_MEASURE_UMAX) + SERIAL_ECHOLNPGM(" " STR_U_MAX ": ", m.backlash[UMAXIMUM]); + #endif + #endif + #if HAS_V_AXIS && AXIS_CAN_CALIBRATE(V) + #if ENABLED(CALIBRATION_MEASURE_VMIN) + SERIAL_ECHOLNPGM(" " STR_V_MIN ": ", m.backlash[VMINIMUM]); + #endif + #if ENABLED(CALIBRATION_MEASURE_VMAX) + SERIAL_ECHOLNPGM(" " STR_V_MAX ": ", m.backlash[VMAXIMUM]); + #endif + #endif + #if HAS_W_AXIS && AXIS_CAN_CALIBRATE(W) + #if ENABLED(CALIBRATION_MEASURE_WMIN) + SERIAL_ECHOLNPGM(" " STR_W_MIN ": ", m.backlash[WMINIMUM]); + #endif + #if ENABLED(CALIBRATION_MEASURE_WMAX) + SERIAL_ECHOLNPGM(" " STR_W_MAX ": ", m.backlash[WMAXIMUM]); + #endif + #endif SERIAL_EOL(); } @@ -498,7 +585,16 @@ inline void probe_sides(measurements_t &m, const float uncertainty) { SERIAL_ECHOLNPGM_P(SP_J_STR, m.pos_error.j); #endif #if HAS_K_CENTER && AXIS_CAN_CALIBRATE(K) - SERIAL_ECHOLNPGM_P(SP_Z_STR, m.pos_error.z); + SERIAL_ECHOLNPGM_P(SP_K_STR, m.pos_error.k); + #endif + #if HAS_U_CENTER && AXIS_CAN_CALIBRATE(U) + SERIAL_ECHOLNPGM_P(SP_U_STR, m.pos_error.u); + #endif + #if HAS_V_CENTER && AXIS_CAN_CALIBRATE(V) + SERIAL_ECHOLNPGM_P(SP_V_STR, m.pos_error.v); + #endif + #if HAS_W_CENTER && AXIS_CAN_CALIBRATE(W) + SERIAL_ECHOLNPGM_P(SP_W_STR, m.pos_error.w); #endif SERIAL_EOL(); } @@ -587,6 +683,30 @@ inline void calibrate_backlash(measurements_t &m, const float uncertainty) { backlash.set_distance_mm(K_AXIS, m.backlash[KMAXIMUM]); #endif + #if HAS_U_CENTER + backlash.distance_mm.u = (m.backlash[UMINIMUM] + m.backlash[UMAXIMUM]) / 2; + #elif ENABLED(CALIBRATION_MEASURE_UMIN) + backlash.distance_mm.u = m.backlash[UMINIMUM]; + #elif ENABLED(CALIBRATION_MEASURE_UMAX) + backlash.distance_mm.u = m.backlash[UMAXIMUM]; + #endif + + #if HAS_V_CENTER + backlash.distance_mm.v = (m.backlash[VMINIMUM] + m.backlash[VMAXIMUM]) / 2; + #elif ENABLED(CALIBRATION_MEASURE_VMIN) + backlash.distance_mm.v = m.backlash[VMINIMUM]; + #elif ENABLED(CALIBRATION_MEASURE_UMAX) + backlash.distance_mm.v = m.backlash[VMAXIMUM]; + #endif + + #if HAS_W_CENTER + backlash.distance_mm.w = (m.backlash[WMINIMUM] + m.backlash[WMAXIMUM]) / 2; + #elif ENABLED(CALIBRATION_MEASURE_WMIN) + backlash.distance_mm.w = m.backlash[WMINIMUM]; + #elif ENABLED(CALIBRATION_MEASURE_WMAX) + backlash.distance_mm.w = m.backlash[WMAXIMUM]; + #endif + #endif // BACKLASH_GCODE } @@ -597,9 +717,10 @@ inline void calibrate_backlash(measurements_t &m, const float uncertainty) { // New scope for TEMPORARY_BACKLASH_CORRECTION TEMPORARY_BACKLASH_CORRECTION(backlash.all_on); TEMPORARY_BACKLASH_SMOOTHING(0.0f); - const xyz_float_t move = LINEAR_AXIS_ARRAY( + const xyz_float_t move = NUM_AXIS_ARRAY( AXIS_CAN_CALIBRATE(X) * 3, AXIS_CAN_CALIBRATE(Y) * 3, AXIS_CAN_CALIBRATE(Z) * 3, - AXIS_CAN_CALIBRATE(I) * 3, AXIS_CAN_CALIBRATE(J) * 3, AXIS_CAN_CALIBRATE(K) * 3 + AXIS_CAN_CALIBRATE(I) * 3, AXIS_CAN_CALIBRATE(J) * 3, AXIS_CAN_CALIBRATE(K) * 3, + AXIS_CAN_CALIBRATE(U) * 3, AXIS_CAN_CALIBRATE(V) * 3, AXIS_CAN_CALIBRATE(W) * 3 ); current_position += move; calibration_move(); current_position -= move; calibration_move(); @@ -650,6 +771,9 @@ inline void calibrate_toolhead(measurements_t &m, const float uncertainty, const TERN_(HAS_I_CENTER, update_measurements(m, I_AXIS)); TERN_(HAS_J_CENTER, update_measurements(m, J_AXIS)); TERN_(HAS_K_CENTER, update_measurements(m, K_AXIS)); + TERN_(HAS_U_CENTER, update_measurements(m, U_AXIS)); + TERN_(HAS_V_CENTER, update_measurements(m, V_AXIS)); + TERN_(HAS_W_CENTER, update_measurements(m, W_AXIS)); sync_plan_position(); } diff --git a/Marlin/src/gcode/calibrate/M425.cpp b/Marlin/src/gcode/calibrate/M425.cpp index 6b1f56fcf6..bfceefdbe2 100644 --- a/Marlin/src/gcode/calibrate/M425.cpp +++ b/Marlin/src/gcode/calibrate/M425.cpp @@ -49,21 +49,24 @@ void GcodeSuite::M425() { auto axis_can_calibrate = [](const uint8_t a) { switch (a) { default: return false; - LINEAR_AXIS_CODE( + NUM_AXIS_CODE( case X_AXIS: return AXIS_CAN_CALIBRATE(X), case Y_AXIS: return AXIS_CAN_CALIBRATE(Y), case Z_AXIS: return AXIS_CAN_CALIBRATE(Z), case I_AXIS: return AXIS_CAN_CALIBRATE(I), case J_AXIS: return AXIS_CAN_CALIBRATE(J), - case K_AXIS: return AXIS_CAN_CALIBRATE(K) + case K_AXIS: return AXIS_CAN_CALIBRATE(K), + case U_AXIS: return AXIS_CAN_CALIBRATE(U), + case V_AXIS: return AXIS_CAN_CALIBRATE(V), + case W_AXIS: return AXIS_CAN_CALIBRATE(W) ); } }; - LOOP_LINEAR_AXES(a) { + LOOP_NUM_AXES(a) { if (axis_can_calibrate(a) && parser.seen(AXIS_CHAR(a))) { planner.synchronize(); - backlash.set_distance_mm(AxisEnum(a), parser.has_value() ? parser.value_linear_units() : backlash.get_measurement(AxisEnum(a))); + backlash.set_distance_mm(AxisEnum(a), parser.has_value() ? parser.value_axis_units(AxisEnum(a)) : backlash.get_measurement(AxisEnum(a))); noArgs = false; } } @@ -88,7 +91,7 @@ void GcodeSuite::M425() { SERIAL_ECHOLNPGM("active:"); SERIAL_ECHOLNPGM(" Correction Amount/Fade-out: F", backlash.get_correction(), " (F1.0 = full, F0.0 = none)"); SERIAL_ECHOPGM(" Backlash Distance (mm): "); - LOOP_LINEAR_AXES(a) if (axis_can_calibrate(a)) { + LOOP_NUM_AXES(a) if (axis_can_calibrate(a)) { SERIAL_CHAR(' ', AXIS_CHAR(a)); SERIAL_ECHO(backlash.get_distance_mm(AxisEnum(a))); SERIAL_EOL(); @@ -101,7 +104,7 @@ void GcodeSuite::M425() { #if ENABLED(MEASURE_BACKLASH_WHEN_PROBING) SERIAL_ECHOPGM(" Average measured backlash (mm):"); if (backlash.has_any_measurement()) { - LOOP_LINEAR_AXES(a) if (axis_can_calibrate(a) && backlash.has_measurement(AxisEnum(a))) { + LOOP_NUM_AXES(a) if (axis_can_calibrate(a) && backlash.has_measurement(AxisEnum(a))) { SERIAL_CHAR(' ', AXIS_CHAR(a)); SERIAL_ECHO(backlash.get_measurement(AxisEnum(a))); } @@ -120,13 +123,16 @@ void GcodeSuite::M425_report(const bool forReplay/*=true*/) { #ifdef BACKLASH_SMOOTHING_MM , PSTR(" S"), LINEAR_UNIT(backlash.get_smoothing_mm()) #endif - , LIST_N(DOUBLE(LINEAR_AXES), + , LIST_N(DOUBLE(NUM_AXES), SP_X_STR, LINEAR_UNIT(backlash.get_distance_mm(X_AXIS)), SP_Y_STR, LINEAR_UNIT(backlash.get_distance_mm(Y_AXIS)), SP_Z_STR, LINEAR_UNIT(backlash.get_distance_mm(Z_AXIS)), - SP_I_STR, LINEAR_UNIT(backlash.get_distance_mm(I_AXIS)), - SP_J_STR, LINEAR_UNIT(backlash.get_distance_mm(J_AXIS)), - SP_K_STR, LINEAR_UNIT(backlash.get_distance_mm(K_AXIS)) + SP_I_STR, I_AXIS_UNIT(backlash.get_distance_mm(I_AXIS)), + SP_J_STR, J_AXIS_UNIT(backlash.get_distance_mm(J_AXIS)), + SP_K_STR, K_AXIS_UNIT(backlash.get_distance_mm(K_AXIS)), + SP_U_STR, U_AXIS_UNIT(backlash.get_distance_mm(U_AXIS)), + SP_V_STR, V_AXIS_UNIT(backlash.get_distance_mm(V_AXIS)), + SP_W_STR, W_AXIS_UNIT(backlash.get_distance_mm(W_AXIS)) ) ); } diff --git a/Marlin/src/gcode/calibrate/M666.cpp b/Marlin/src/gcode/calibrate/M666.cpp index 15f8baf109..fe244b21f7 100644 --- a/Marlin/src/gcode/calibrate/M666.cpp +++ b/Marlin/src/gcode/calibrate/M666.cpp @@ -44,7 +44,7 @@ void GcodeSuite::M666() { DEBUG_SECTION(log_M666, "M666", DEBUGGING(LEVELING)); bool is_err = false, is_set = false; - LOOP_LINEAR_AXES(i) { + LOOP_NUM_AXES(i) { if (parser.seen(AXIS_CHAR(i))) { is_set = true; const float v = parser.value_linear_units(); diff --git a/Marlin/src/gcode/config/M200-M205.cpp b/Marlin/src/gcode/config/M200-M205.cpp index 9490e3c625..5e15ff65e8 100644 --- a/Marlin/src/gcode/config/M200-M205.cpp +++ b/Marlin/src/gcode/config/M200-M205.cpp @@ -93,12 +93,12 @@ } #else SERIAL_ECHOLNPGM(" M200 S", parser.volumetric_enabled); - LOOP_L_N(i, EXTRUDERS) { + EXTRUDER_LOOP() { report_echo_start(forReplay); SERIAL_ECHOLNPGM( - " M200 T", i, " D", LINEAR_UNIT(planner.filament_size[i]) + " M200 T", e, " D", LINEAR_UNIT(planner.filament_size[e]) #if ENABLED(VOLUMETRIC_EXTRUDER_LIMIT) - , " L", LINEAR_UNIT(planner.volumetric_extruder_limit[i]) + , " L", LINEAR_UNIT(planner.volumetric_extruder_limit[e]) #endif ); } @@ -135,13 +135,16 @@ void GcodeSuite::M201() { void GcodeSuite::M201_report(const bool forReplay/*=true*/) { report_heading_etc(forReplay, F(STR_MAX_ACCELERATION)); SERIAL_ECHOLNPGM_P( - LIST_N(DOUBLE(LINEAR_AXES), + LIST_N(DOUBLE(NUM_AXES), PSTR(" M201 X"), LINEAR_UNIT(planner.settings.max_acceleration_mm_per_s2[X_AXIS]), SP_Y_STR, LINEAR_UNIT(planner.settings.max_acceleration_mm_per_s2[Y_AXIS]), SP_Z_STR, LINEAR_UNIT(planner.settings.max_acceleration_mm_per_s2[Z_AXIS]), - SP_I_STR, LINEAR_UNIT(planner.settings.max_acceleration_mm_per_s2[I_AXIS]), - SP_J_STR, LINEAR_UNIT(planner.settings.max_acceleration_mm_per_s2[J_AXIS]), - SP_K_STR, LINEAR_UNIT(planner.settings.max_acceleration_mm_per_s2[K_AXIS]) + SP_I_STR, I_AXIS_UNIT(planner.settings.max_acceleration_mm_per_s2[I_AXIS]), + SP_J_STR, J_AXIS_UNIT(planner.settings.max_acceleration_mm_per_s2[J_AXIS]), + SP_K_STR, K_AXIS_UNIT(planner.settings.max_acceleration_mm_per_s2[K_AXIS]), + SP_U_STR, U_AXIS_UNIT(planner.settings.max_acceleration_mm_per_s2[U_AXIS]), + SP_V_STR, V_AXIS_UNIT(planner.settings.max_acceleration_mm_per_s2[V_AXIS]), + SP_W_STR, W_AXIS_UNIT(planner.settings.max_acceleration_mm_per_s2[W_AXIS]), ) #if HAS_EXTRUDERS && DISABLED(DISTINCT_E_FACTORS) , SP_E_STR, VOLUMETRIC_UNIT(planner.settings.max_acceleration_mm_per_s2[E_AXIS]) @@ -180,13 +183,16 @@ void GcodeSuite::M203() { void GcodeSuite::M203_report(const bool forReplay/*=true*/) { report_heading_etc(forReplay, F(STR_MAX_FEEDRATES)); SERIAL_ECHOLNPGM_P( - LIST_N(DOUBLE(LINEAR_AXES), + LIST_N(DOUBLE(NUM_AXES), PSTR(" M203 X"), LINEAR_UNIT(planner.settings.max_feedrate_mm_s[X_AXIS]), SP_Y_STR, LINEAR_UNIT(planner.settings.max_feedrate_mm_s[Y_AXIS]), SP_Z_STR, LINEAR_UNIT(planner.settings.max_feedrate_mm_s[Z_AXIS]), SP_I_STR, LINEAR_UNIT(planner.settings.max_feedrate_mm_s[I_AXIS]), SP_J_STR, LINEAR_UNIT(planner.settings.max_feedrate_mm_s[J_AXIS]), - SP_K_STR, LINEAR_UNIT(planner.settings.max_feedrate_mm_s[K_AXIS]) + SP_K_STR, LINEAR_UNIT(planner.settings.max_feedrate_mm_s[K_AXIS]), + SP_U_STR, LINEAR_UNIT(planner.settings.max_feedrate_mm_s[U_AXIS]), + SP_V_STR, LINEAR_UNIT(planner.settings.max_feedrate_mm_s[V_AXIS]), + SP_W_STR, LINEAR_UNIT(planner.settings.max_feedrate_mm_s[W_AXIS]) ) #if HAS_EXTRUDERS && DISABLED(DISTINCT_E_FACTORS) , SP_E_STR, VOLUMETRIC_UNIT(planner.settings.max_feedrate_mm_s[E_AXIS]) @@ -273,9 +279,12 @@ void GcodeSuite::M205() { if (parser.seenval('X')) planner.set_max_jerk(X_AXIS, parser.value_linear_units()), if (parser.seenval('Y')) planner.set_max_jerk(Y_AXIS, parser.value_linear_units()), if ((seenZ = parser.seenval('Z'))) planner.set_max_jerk(Z_AXIS, parser.value_linear_units()), - if (parser.seenval(AXIS4_NAME)) planner.set_max_jerk(I_AXIS, parser.value_linear_units()), - if (parser.seenval(AXIS5_NAME)) planner.set_max_jerk(J_AXIS, parser.value_linear_units()), - if (parser.seenval(AXIS6_NAME)) planner.set_max_jerk(K_AXIS, parser.value_linear_units()) + if (parser.seenval(AXIS4_NAME)) planner.set_max_jerk(I_AXIS, parser.TERN(AXIS4_ROTATES, value_float, value_linear_units)()), + if (parser.seenval(AXIS5_NAME)) planner.set_max_jerk(J_AXIS, parser.TERN(AXIS5_ROTATES, value_float, value_linear_units)()), + if (parser.seenval(AXIS6_NAME)) planner.set_max_jerk(K_AXIS, parser.TERN(AXIS6_ROTATES, value_float, value_linear_units)()), + if (parser.seenval(AXIS7_NAME)) planner.set_max_jerk(U_AXIS, parser.TERN(AXIS7_ROTATES, value_float, value_linear_units)()), + if (parser.seenval(AXIS8_NAME)) planner.set_max_jerk(V_AXIS, parser.TERN(AXIS8_ROTATES, value_float, value_linear_units)()), + if (parser.seenval(AXIS9_NAME)) planner.set_max_jerk(W_AXIS, parser.TERN(AXIS9_ROTATES, value_float, value_linear_units)()) ); #if HAS_MESH && DISABLED(LIMITED_JERK_EDITING) if (seenZ && planner.max_jerk.z <= 0.1f) @@ -289,9 +298,10 @@ void GcodeSuite::M205_report(const bool forReplay/*=true*/) { "Advanced (B S T" TERN_(HAS_JUNCTION_DEVIATION, " J") #if HAS_CLASSIC_JERK - LINEAR_AXIS_GANG( + NUM_AXIS_GANG( " X", " Y", " Z", - " " STR_I "", " " STR_J "", " " STR_K "" + " " STR_I "", " " STR_J "", " " STR_K "", + " " STR_U "", " " STR_V "", " " STR_W "" ) #endif TERN_(HAS_CLASSIC_E_JERK, " E") @@ -305,13 +315,16 @@ void GcodeSuite::M205_report(const bool forReplay/*=true*/) { , PSTR(" J"), LINEAR_UNIT(planner.junction_deviation_mm) #endif #if HAS_CLASSIC_JERK - , LIST_N(DOUBLE(LINEAR_AXES), + , LIST_N(DOUBLE(NUM_AXES), SP_X_STR, LINEAR_UNIT(planner.max_jerk.x), SP_Y_STR, LINEAR_UNIT(planner.max_jerk.y), SP_Z_STR, LINEAR_UNIT(planner.max_jerk.z), - SP_I_STR, LINEAR_UNIT(planner.max_jerk.i), - SP_J_STR, LINEAR_UNIT(planner.max_jerk.j), - SP_K_STR, LINEAR_UNIT(planner.max_jerk.k) + SP_I_STR, I_AXIS_UNIT(planner.max_jerk.i), + SP_J_STR, J_AXIS_UNIT(planner.max_jerk.j), + SP_K_STR, K_AXIS_UNIT(planner.max_jerk.k), + SP_U_STR, U_AXIS_UNIT(planner.max_jerk.u), + SP_V_STR, V_AXIS_UNIT(planner.max_jerk.v), + SP_W_STR, W_AXIS_UNIT(planner.max_jerk.w) ) #if HAS_CLASSIC_E_JERK , SP_E_STR, LINEAR_UNIT(planner.max_jerk.e) diff --git a/Marlin/src/gcode/config/M217.cpp b/Marlin/src/gcode/config/M217.cpp index 344adc34e3..ad96b2b659 100644 --- a/Marlin/src/gcode/config/M217.cpp +++ b/Marlin/src/gcode/config/M217.cpp @@ -50,9 +50,12 @@ * W[linear] 0/1 Enable park & Z Raise * X[linear] Park X (Requires TOOLCHANGE_PARK) * Y[linear] Park Y (Requires TOOLCHANGE_PARK) - * I[linear] Park I (Requires TOOLCHANGE_PARK and LINEAR_AXES >= 4) - * J[linear] Park J (Requires TOOLCHANGE_PARK and LINEAR_AXES >= 5) - * K[linear] Park K (Requires TOOLCHANGE_PARK and LINEAR_AXES >= 6) + * I[linear] Park I (Requires TOOLCHANGE_PARK and NUM_AXES >= 4) + * J[linear] Park J (Requires TOOLCHANGE_PARK and NUM_AXES >= 5) + * K[linear] Park K (Requires TOOLCHANGE_PARK and NUM_AXES >= 6) + * C[linear] Park U (Requires TOOLCHANGE_PARK and NUM_AXES >= 7) + * H[linear] Park V (Requires TOOLCHANGE_PARK and NUM_AXES >= 8) + * O[linear] Park W (Requires TOOLCHANGE_PARK and NUM_AXES >= 9) * Z[linear] Z Raise * F[linear] Fan Speed 0-255 * G[linear/s] Fan time @@ -95,13 +98,22 @@ void GcodeSuite::M217() { if (parser.seenval('Y')) { const int16_t v = parser.value_linear_units(); toolchange_settings.change_point.y = constrain(v, Y_MIN_POS, Y_MAX_POS); } #endif #if HAS_I_AXIS - if (parser.seenval('I')) { const int16_t v = parser.value_linear_units(); toolchange_settings.change_point.i = constrain(v, I_MIN_POS, I_MAX_POS); } + if (parser.seenval('I')) { const int16_t v = parser.TERN(AXIS4_ROTATES, value_int, value_linear_units)(); toolchange_settings.change_point.i = constrain(v, I_MIN_POS, I_MAX_POS); } #endif #if HAS_J_AXIS - if (parser.seenval('J')) { const int16_t v = parser.value_linear_units(); toolchange_settings.change_point.j = constrain(v, J_MIN_POS, J_MAX_POS); } + if (parser.seenval('J')) { const int16_t v = parser.TERN(AXIS5_ROTATES, value_int, value_linear_units)(); toolchange_settings.change_point.j = constrain(v, J_MIN_POS, J_MAX_POS); } #endif #if HAS_K_AXIS - if (parser.seenval('K')) { const int16_t v = parser.value_linear_units(); toolchange_settings.change_point.k = constrain(v, K_MIN_POS, K_MAX_POS); } + if (parser.seenval('K')) { const int16_t v = parser.TERN(AXIS6_ROTATES, value_int, value_linear_units)(); toolchange_settings.change_point.k = constrain(v, K_MIN_POS, K_MAX_POS); } + #endif + #if HAS_U_AXIS + if (parser.seenval('C')) { const int16_t v = parser.TERN(AXIS7_ROTATES, value_int, value_linear_units)(); toolchange_settings.change_point.u = constrain(v, U_MIN_POS, U_MAX_POS); } + #endif + #if HAS_V_AXIS + if (parser.seenval('H')) { const int16_t v = parser.TERN(AXIS8_ROTATES, value_int, value_linear_units)(); toolchange_settings.change_point.v = constrain(v, V_MIN_POS, V_MAX_POS); } + #endif + #if HAS_W_AXIS + if (parser.seenval('O')) { const int16_t v = parser.TERN(AXIS9_ROTATES, value_int, value_linear_units)(); toolchange_settings.change_point.w = constrain(v, W_MIN_POS, W_MAX_POS); } #endif #endif @@ -167,24 +179,23 @@ void GcodeSuite::M217_report(const bool forReplay/*=true*/) { #endif #if ENABLED(TOOLCHANGE_PARK) - { SERIAL_ECHOPGM(" W", LINEAR_UNIT(toolchange_settings.enable_park)); SERIAL_ECHOPGM_P( SP_X_STR, LINEAR_UNIT(toolchange_settings.change_point.x) #if HAS_Y_AXIS , SP_Y_STR, LINEAR_UNIT(toolchange_settings.change_point.y) #endif - #if HAS_I_AXIS - , SP_I_STR, LINEAR_UNIT(toolchange_settings.change_point.i) - #endif - #if HAS_J_AXIS - , SP_J_STR, LINEAR_UNIT(toolchange_settings.change_point.j) - #endif - #if HAS_K_AXIS - , SP_K_STR, LINEAR_UNIT(toolchange_settings.change_point.k) + #if SECONDARY_AXES >= 1 + , LIST_N(DOUBLE(SECONDARY_AXES), + PSTR(" I"), I_AXIS_UNIT(toolchange_settings.change_point.i), + PSTR(" J"), J_AXIS_UNIT(toolchange_settings.change_point.j), + PSTR(" K"), K_AXIS_UNIT(toolchange_settings.change_point.k), + SP_C_STR, U_AXIS_UNIT(toolchange_settings.change_point.u), + PSTR(" H"), V_AXIS_UNIT(toolchange_settings.change_point.v), + PSTR(" O"), W_AXIS_UNIT(toolchange_settings.change_point.w), + ) #endif ); - } #endif #if ENABLED(TOOLCHANGE_FS_PRIME_FIRST_USED) diff --git a/Marlin/src/gcode/config/M302.cpp b/Marlin/src/gcode/config/M302.cpp index e271dcd469..9f4d569d7b 100644 --- a/Marlin/src/gcode/config/M302.cpp +++ b/Marlin/src/gcode/config/M302.cpp @@ -27,6 +27,10 @@ #include "../gcode.h" #include "../../module/temperature.h" +#if ENABLED(DWIN_LCD_PROUI) + #include "../../lcd/e3v2/proui/dwin_defines.h" +#endif + /** * M302: Allow cold extrudes, or set the minimum extrude temperature * @@ -47,6 +51,7 @@ void GcodeSuite::M302() { if (seen_S) { thermalManager.extrude_min_temp = parser.value_celsius(); thermalManager.allow_cold_extrude = (thermalManager.extrude_min_temp == 0); + TERN_(DWIN_LCD_PROUI, HMI_data.ExtMinT = thermalManager.extrude_min_temp); } if (parser.seen('P')) diff --git a/Marlin/src/gcode/config/M92.cpp b/Marlin/src/gcode/config/M92.cpp index 8f527919fd..cca4f7f12a 100644 --- a/Marlin/src/gcode/config/M92.cpp +++ b/Marlin/src/gcode/config/M92.cpp @@ -24,7 +24,7 @@ #include "../../module/planner.h" /** - * M92: Set axis steps-per-unit for one or more axes, X, Y, Z, [I, [J, [K]]] and E. + * M92: Set axis steps-per-unit for one or more axes, X, Y, Z, [I, [J, [K, [U, [V, [W,]]]]]] and E. * (Follows the same syntax as G92) * * With multiple extruders use T to specify which one. @@ -92,14 +92,17 @@ void GcodeSuite::M92() { void GcodeSuite::M92_report(const bool forReplay/*=true*/, const int8_t e/*=-1*/) { report_heading_etc(forReplay, F(STR_STEPS_PER_UNIT)); - SERIAL_ECHOPGM_P(LIST_N(DOUBLE(LINEAR_AXES), + SERIAL_ECHOPGM_P(LIST_N(DOUBLE(NUM_AXES), PSTR(" M92 X"), LINEAR_UNIT(planner.settings.axis_steps_per_mm[X_AXIS]), SP_Y_STR, LINEAR_UNIT(planner.settings.axis_steps_per_mm[Y_AXIS]), SP_Z_STR, LINEAR_UNIT(planner.settings.axis_steps_per_mm[Z_AXIS]), - SP_I_STR, LINEAR_UNIT(planner.settings.axis_steps_per_mm[I_AXIS]), - SP_J_STR, LINEAR_UNIT(planner.settings.axis_steps_per_mm[J_AXIS]), - SP_K_STR, LINEAR_UNIT(planner.settings.axis_steps_per_mm[K_AXIS])) - ); + SP_I_STR, I_AXIS_UNIT(planner.settings.axis_steps_per_mm[I_AXIS]), + SP_J_STR, J_AXIS_UNIT(planner.settings.axis_steps_per_mm[J_AXIS]), + SP_K_STR, K_AXIS_UNIT(planner.settings.axis_steps_per_mm[K_AXIS]), + SP_U_STR, U_AXIS_UNIT(planner.settings.axis_steps_per_mm[U_AXIS]), + SP_V_STR, V_AXIS_UNIT(planner.settings.axis_steps_per_mm[V_AXIS]), + SP_W_STR, W_AXIS_UNIT(planner.settings.axis_steps_per_mm[W_AXIS]) + )); #if HAS_EXTRUDERS && DISABLED(DISTINCT_E_FACTORS) SERIAL_ECHOPGM_P(SP_E_STR, VOLUMETRIC_UNIT(planner.settings.axis_steps_per_mm[E_AXIS])); #endif diff --git a/Marlin/src/gcode/control/M17_M18_M84.cpp b/Marlin/src/gcode/control/M17_M18_M84.cpp index 4683786f1f..c6473af48f 100644 --- a/Marlin/src/gcode/control/M17_M18_M84.cpp +++ b/Marlin/src/gcode/control/M17_M18_M84.cpp @@ -46,13 +46,16 @@ inline axis_flags_t selected_axis_bits() { selected.bits = selected.e_bits(); } #endif - selected.bits |= LINEAR_AXIS_GANG( + selected.bits |= NUM_AXIS_GANG( (parser.seen_test('X') << X_AXIS), | (parser.seen_test('Y') << Y_AXIS), | (parser.seen_test('Z') << Z_AXIS), | (parser.seen_test(AXIS4_NAME) << I_AXIS), | (parser.seen_test(AXIS5_NAME) << J_AXIS), - | (parser.seen_test(AXIS6_NAME) << K_AXIS) + | (parser.seen_test(AXIS6_NAME) << K_AXIS), + | (parser.seen_test(AXIS7_NAME) << U_AXIS), + | (parser.seen_test(AXIS8_NAME) << V_AXIS), + | (parser.seen_test(AXIS9_NAME) << W_AXIS) ); return selected; } @@ -69,7 +72,7 @@ void do_enable(const axis_flags_t to_enable) { ena_mask_t also_enabled = 0; // Track steppers enabled due to overlap // Enable all flagged axes - LOOP_LINEAR_AXES(a) { + LOOP_NUM_AXES(a) { if (TEST(shall_enable, a)) { stepper.enable_axis(AxisEnum(a)); // Mark and enable the requested axis DEBUG_ECHOLNPGM("Enabled ", axis_codes[a], " (", a, ") with overlap ", hex_word(enable_overlap[a]), " ... Enabled: ", hex_word(stepper.axis_enabled.bits)); @@ -77,7 +80,7 @@ void do_enable(const axis_flags_t to_enable) { } } #if HAS_EXTRUDERS - LOOP_L_N(e, EXTRUDERS) { + EXTRUDER_LOOP() { const uint8_t a = INDEX_OF_AXIS(E_AXIS, e); if (TEST(shall_enable, a)) { stepper.ENABLE_EXTRUDER(e); @@ -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 @@ -161,7 +167,7 @@ void try_to_disable(const axis_flags_t to_disable) { DEBUG_ECHOLNPGM(" ... still_enabled=", hex_word(still_enabled)); } #if HAS_EXTRUDERS - LOOP_L_N(e, EXTRUDERS) { + EXTRUDER_LOOP() { const uint8_t a = INDEX_OF_AXIS(E_AXIS, e); if (TEST(to_disable.bits, a)) { DEBUG_ECHOPGM("Try to disable E", AS_DIGIT(e), " (", a, ") with overlap ", hex_word(enable_overlap[a]), " ... "); @@ -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,14 +193,14 @@ 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]); } } #if HAS_EXTRUDERS - LOOP_L_N(e, EXTRUDERS) { + EXTRUDER_LOOP() { const uint8_t a = INDEX_OF_AXIS(E_AXIS, e); if (TEST(still_enabled, a)) { SERIAL_CHAR('E', '0' + e); @@ -229,13 +235,16 @@ void GcodeSuite::M18_M84() { stepper.disable_e_steppers(); } #endif - LINEAR_AXIS_CODE( + NUM_AXIS_CODE( if (parser.seen_test('X')) stepper.disable_axis(X_AXIS), if (parser.seen_test('Y')) stepper.disable_axis(Y_AXIS), if (parser.seen_test('Z')) stepper.disable_axis(Z_AXIS), if (parser.seen_test(AXIS4_NAME)) stepper.disable_axis(I_AXIS), if (parser.seen_test(AXIS5_NAME)) stepper.disable_axis(J_AXIS), - if (parser.seen_test(AXIS6_NAME)) stepper.disable_axis(K_AXIS) + if (parser.seen_test(AXIS6_NAME)) stepper.disable_axis(K_AXIS), + if (parser.seen_test(AXIS7_NAME)) stepper.disable_axis(U_AXIS), + if (parser.seen_test(AXIS8_NAME)) stepper.disable_axis(V_AXIS), + if (parser.seen_test(AXIS9_NAME)) stepper.disable_axis(W_AXIS) ); } } diff --git a/Marlin/src/gcode/control/M380_M381.cpp b/Marlin/src/gcode/control/M380_M381.cpp index 3f5b252465..6bcec891e2 100644 --- a/Marlin/src/gcode/control/M380_M381.cpp +++ b/Marlin/src/gcode/control/M380_M381.cpp @@ -37,7 +37,7 @@ void GcodeSuite::M380() { #if ENABLED(MANUAL_SOLENOID_CONTROL) enable_solenoid(parser.intval('S', active_extruder)); #else - enable_solenoid_on_active_extruder(); + enable_solenoid(active_extruder); #endif } diff --git a/Marlin/src/gcode/control/M605.cpp b/Marlin/src/gcode/control/M605.cpp index 788659e7e2..a0296bba57 100644 --- a/Marlin/src/gcode/control/M605.cpp +++ b/Marlin/src/gcode/control/M605.cpp @@ -146,7 +146,7 @@ HOTEND_LOOP() { DEBUG_ECHOPGM_P(SP_T_STR, e); - LOOP_LINEAR_AXES(a) DEBUG_ECHOPGM(" hotend_offset[", e, "].", AS_CHAR(AXIS_CHAR(a) | 0x20), "=", hotend_offset[e][a]); + LOOP_NUM_AXES(a) DEBUG_ECHOPGM(" hotend_offset[", e, "].", AS_CHAR(AXIS_CHAR(a) | 0x20), "=", hotend_offset[e][a]); DEBUG_EOL(); } DEBUG_EOL(); diff --git a/Marlin/src/gcode/control/M997.cpp b/Marlin/src/gcode/control/M997.cpp index 359172faad..74ed8b0d07 100644 --- a/Marlin/src/gcode/control/M997.cpp +++ b/Marlin/src/gcode/control/M997.cpp @@ -24,7 +24,7 @@ #if ENABLED(PLATFORM_M997_SUPPORT) -#if ENABLED(DWIN_CREALITY_LCD_ENHANCED) +#if ENABLED(DWIN_LCD_PROUI) #include "../../lcd/e3v2/proui/dwin.h" #endif @@ -33,7 +33,7 @@ */ void GcodeSuite::M997() { - TERN_(DWIN_CREALITY_LCD_ENHANCED, DWIN_RebootScreen()); + TERN_(DWIN_LCD_PROUI, DWIN_RebootScreen()); flashFirmware(parser.intval('S')); diff --git a/Marlin/src/gcode/feature/advance/M900.cpp b/Marlin/src/gcode/feature/advance/M900.cpp index 054ea3617f..8b59e88fb1 100644 --- a/Marlin/src/gcode/feature/advance/M900.cpp +++ b/Marlin/src/gcode/feature/advance/M900.cpp @@ -117,10 +117,10 @@ void GcodeSuite::M900() { #if EXTRUDERS < 2 SERIAL_ECHOLNPGM("Advance S", new_slot, " K", kref, "(S", !new_slot, " K", lref, ")"); #else - LOOP_L_N(i, EXTRUDERS) { - const bool slot = TEST(lin_adv_slot, i); - SERIAL_ECHOLNPGM("Advance T", i, " S", slot, " K", planner.extruder_advance_K[i], - "(S", !slot, " K", other_extruder_advance_K[i], ")"); + EXTRUDER_LOOP() { + const bool slot = TEST(lin_adv_slot, e); + SERIAL_ECHOLNPGM("Advance T", e, " S", slot, " K", planner.extruder_advance_K[e], + "(S", !slot, " K", other_extruder_advance_K[e], ")"); SERIAL_EOL(); } #endif @@ -132,9 +132,9 @@ void GcodeSuite::M900() { SERIAL_ECHOLNPGM("Advance K=", planner.extruder_advance_K[0]); #else SERIAL_ECHOPGM("Advance K"); - LOOP_L_N(i, EXTRUDERS) { - SERIAL_CHAR(' ', '0' + i, ':'); - SERIAL_DECIMAL(planner.extruder_advance_K[i]); + EXTRUDER_LOOP() { + SERIAL_CHAR(' ', '0' + e, ':'); + SERIAL_DECIMAL(planner.extruder_advance_K[e]); } SERIAL_EOL(); #endif @@ -150,9 +150,9 @@ void GcodeSuite::M900_report(const bool forReplay/*=true*/) { report_echo_start(forReplay); SERIAL_ECHOLNPGM(" M900 K", planner.extruder_advance_K[0]); #else - LOOP_L_N(i, EXTRUDERS) { + EXTRUDER_LOOP() { report_echo_start(forReplay); - SERIAL_ECHOLNPGM(" M900 T", i, " K", planner.extruder_advance_K[i]); + SERIAL_ECHOLNPGM(" M900 T", e, " K", planner.extruder_advance_K[e]); } #endif } diff --git a/Marlin/src/gcode/feature/clean/G12.cpp b/Marlin/src/gcode/feature/clean/G12.cpp index a0b87b1abc..999a9b10bd 100644 --- a/Marlin/src/gcode/feature/clean/G12.cpp +++ b/Marlin/src/gcode/feature/clean/G12.cpp @@ -46,7 +46,8 @@ */ void GcodeSuite::G12() { // Don't allow nozzle cleaning without homing first - if (homing_needed_error()) return; + if (homing_needed_error(linear_bits & ~TERN0(NOZZLE_CLEAN_NO_Z, Z_AXIS) & ~TERN0(NOZZLE_CLEAN_NO_Y, Y_AXIS))) + return; #ifdef WIPE_SEQUENCE_COMMANDS if (!parser.seen_any()) { diff --git a/Marlin/src/gcode/feature/digipot/M907-M910.cpp b/Marlin/src/gcode/feature/digipot/M907-M910.cpp index 95adde3ea5..3b66f78593 100644 --- a/Marlin/src/gcode/feature/digipot/M907-M910.cpp +++ b/Marlin/src/gcode/feature/digipot/M907-M910.cpp @@ -39,7 +39,7 @@ #endif /** - * M907: Set digital trimpot motor current using axis codes X [Y] [Z] [E] + * M907: Set digital trimpot motor current using axis codes X [Y] [Z] [I] [J] [K] [U] [V] [W] [E] * B - Special case for 4th (E) axis * S - Special case to set first 3 axes */ @@ -49,15 +49,15 @@ void GcodeSuite::M907() { if (!parser.seen("BS" LOGICAL_AXES_STRING)) return M907_report(); - LOOP_LOGICAL_AXES(i) if (parser.seenval(axis_codes[i])) stepper.set_digipot_current(i, parser.value_int()); + LOOP_LOGICAL_AXES(i) if (parser.seenval(IAXIS_CHAR(i))) stepper.set_digipot_current(i, parser.value_int()); if (parser.seenval('B')) stepper.set_digipot_current(4, parser.value_int()); if (parser.seenval('S')) LOOP_LE_N(i, 4) stepper.set_digipot_current(i, parser.value_int()); #elif HAS_MOTOR_CURRENT_PWM if (!parser.seen( - #if ANY_PIN(MOTOR_CURRENT_PWM_X, MOTOR_CURRENT_PWM_Y, MOTOR_CURRENT_PWM_XY) - "XY" + #if ANY_PIN(MOTOR_CURRENT_PWM_X, MOTOR_CURRENT_PWM_Y, MOTOR_CURRENT_PWM_XY, MOTOR_CURRENT_PWM_I, MOTOR_CURRENT_PWM_J, MOTOR_CURRENT_PWM_K, MOTOR_CURRENT_PWM_U, MOTOR_CURRENT_PWM_V, MOTOR_CURRENT_PWM_W) + "XY" SECONDARY_AXIS_GANG("I", "J", "K", "U", "V", "W") #endif #if PIN_EXISTS(MOTOR_CURRENT_PWM_Z) "Z" @@ -67,8 +67,12 @@ void GcodeSuite::M907() { #endif )) return M907_report(); - #if ANY_PIN(MOTOR_CURRENT_PWM_X, MOTOR_CURRENT_PWM_Y, MOTOR_CURRENT_PWM_XY) - if (parser.seenval('X') || parser.seenval('Y')) stepper.set_digipot_current(0, parser.value_int()); + #if ANY_PIN(MOTOR_CURRENT_PWM_X, MOTOR_CURRENT_PWM_Y, MOTOR_CURRENT_PWM_XY, MOTOR_CURRENT_PWM_I, MOTOR_CURRENT_PWM_J, MOTOR_CURRENT_PWM_K, MOTOR_CURRENT_PWM_U, MOTOR_CURRENT_PWM_V, MOTOR_CURRENT_PWM_W) + if (NUM_AXIS_GANG( + parser.seenval('X'), || parser.seenval('Y'), || false, + || parser.seenval('I'), || parser.seenval('J'), || parser.seenval('K'), + || parser.seenval('U'), || parser.seenval('V'), || parser.seenval('W') + )) stepper.set_digipot_current(0, parser.value_int()); #endif #if PIN_EXISTS(MOTOR_CURRENT_PWM_Z) if (parser.seenval('Z')) stepper.set_digipot_current(1, parser.value_int()); @@ -81,7 +85,7 @@ void GcodeSuite::M907() { #if HAS_MOTOR_CURRENT_I2C // this one uses actual amps in floating point - LOOP_LOGICAL_AXES(i) if (parser.seenval(axis_codes[i])) digipot_i2c.set_current(i, parser.value_float()); + LOOP_LOGICAL_AXES(i) if (parser.seenval(IAXIS_CHAR(i))) digipot_i2c.set_current(i, parser.value_float()); // Additional extruders use B,C,D for channels 4,5,6. // TODO: Change these parameters because 'E' is used. B? #if HAS_EXTRUDERS @@ -95,7 +99,7 @@ void GcodeSuite::M907() { const float dac_percent = parser.value_float(); LOOP_LE_N(i, 4) stepper_dac.set_current_percent(i, dac_percent); } - LOOP_LOGICAL_AXES(i) if (parser.seenval(axis_codes[i])) stepper_dac.set_current_percent(i, parser.value_float()); + LOOP_LOGICAL_AXES(i) if (parser.seenval(IAXIS_CHAR(i))) stepper_dac.set_current_percent(i, parser.value_float()); #endif } @@ -104,15 +108,15 @@ void GcodeSuite::M907() { void GcodeSuite::M907_report(const bool forReplay/*=true*/) { report_heading_etc(forReplay, F(STR_STEPPER_MOTOR_CURRENTS)); #if HAS_MOTOR_CURRENT_PWM - SERIAL_ECHOLNPGM_P( // PWM-based has 3 values: - PSTR(" M907 X"), stepper.motor_current_setting[0] // X and Y + SERIAL_ECHOLNPGM_P( // PWM-based has 3 values: + PSTR(" M907 X"), stepper.motor_current_setting[0] // X, Y, (I, J, K, U, V, W) , SP_Z_STR, stepper.motor_current_setting[1] // Z , SP_E_STR, stepper.motor_current_setting[2] // E ); #elif HAS_MOTOR_CURRENT_SPI SERIAL_ECHOPGM(" M907"); // SPI-based has 5 values: - LOOP_LOGICAL_AXES(q) { // X Y Z (I J K) E (map to X Y Z (I J K) E0 by default) - SERIAL_CHAR(' ', axis_codes[q]); + LOOP_LOGICAL_AXES(q) { // X Y Z (I J K U V W) E (map to X Y Z (I J K U V W) E0 by default) + SERIAL_CHAR(' ', IAXIS_CHAR(q)); SERIAL_ECHO(stepper.motor_current_setting[q]); } SERIAL_CHAR(' ', 'B'); // B (maps to E1 by default) diff --git a/Marlin/src/gcode/feature/pause/G60.cpp b/Marlin/src/gcode/feature/pause/G60.cpp index d4770577a6..9e0962fd34 100644 --- a/Marlin/src/gcode/feature/pause/G60.cpp +++ b/Marlin/src/gcode/feature/pause/G60.cpp @@ -48,10 +48,14 @@ void GcodeSuite::G60() { #if ENABLED(SAVED_POSITIONS_DEBUG) { - DEBUG_ECHOPGM(STR_SAVED_POS " S", slot); const xyze_pos_t &pos = stored_position[slot]; + DEBUG_ECHOPGM(STR_SAVED_POS " S", slot, " :"); DEBUG_ECHOLNPAIR_F_P( - LIST_N(DOUBLE(LINEAR_AXES), PSTR(" : X"), pos.x, SP_Y_STR, pos.y, SP_Z_STR, pos.z, SP_I_STR, pos.i, SP_J_STR, pos.j, SP_K_STR, pos.k) + LIST_N(DOUBLE(NUM_AXES), + SP_Y_STR, pos.x, SP_Y_STR, pos.y, SP_Z_STR, pos.z, + SP_I_STR, pos.i, SP_J_STR, pos.j, SP_K_STR, pos.k, + SP_U_STR, pos.u, SP_V_STR, pos.v, SP_W_STR, pos.w + ) #if HAS_EXTRUDERS , SP_E_STR, pos.e #endif diff --git a/Marlin/src/gcode/feature/pause/G61.cpp b/Marlin/src/gcode/feature/pause/G61.cpp index e0e1983a25..baf96f0d0a 100644 --- a/Marlin/src/gcode/feature/pause/G61.cpp +++ b/Marlin/src/gcode/feature/pause/G61.cpp @@ -68,9 +68,9 @@ void GcodeSuite::G61() { SYNC_E(stored_position[slot].e); } else { - if (parser.seen(LINEAR_AXIS_GANG("X", "Y", "Z", STR_I, STR_J, STR_K))) { + if (parser.seen(NUM_AXIS_GANG("X", "Y", "Z", STR_I, STR_J, STR_K, STR_U, STR_V, STR_W))) { DEBUG_ECHOPGM(STR_RESTORING_POS " S", slot); - LOOP_LINEAR_AXES(i) { + LOOP_NUM_AXES(i) { destination[i] = parser.seen(AXIS_CHAR(i)) ? stored_position[slot][i] + parser.value_axis_units((AxisEnum)i) : current_position[i]; diff --git a/Marlin/src/gcode/feature/pause/M125.cpp b/Marlin/src/gcode/feature/pause/M125.cpp index 940e1b369b..ae450cc5e9 100644 --- a/Marlin/src/gcode/feature/pause/M125.cpp +++ b/Marlin/src/gcode/feature/pause/M125.cpp @@ -52,6 +52,9 @@ * A = Override park position A (requires AXIS*_NAME 'A') * B = Override park position B (requires AXIS*_NAME 'B') * C = Override park position C (requires AXIS*_NAME 'C') + * U = Override park position U (requires AXIS*_NAME 'U') + * V = Override park position V (requires AXIS*_NAME 'V') + * W = Override park position W (requires AXIS*_NAME 'W') * Z = Override Z raise * * With an LCD menu: @@ -64,17 +67,22 @@ void GcodeSuite::M125() { xyz_pos_t park_point = NOZZLE_PARK_POINT; // Move to filament change position or given position - LINEAR_AXIS_CODE( + NUM_AXIS_CODE( if (parser.seenval('X')) park_point.x = RAW_X_POSITION(parser.linearval('X')), if (parser.seenval('Y')) park_point.y = RAW_Y_POSITION(parser.linearval('Y')), NOOP, - if (parser.seenval(AXIS4_NAME)) park_point.i = RAW_I_POSITION(parser.linearval(AXIS4_NAME)), - if (parser.seenval(AXIS5_NAME)) park_point.j = RAW_J_POSITION(parser.linearval(AXIS5_NAME)), - if (parser.seenval(AXIS6_NAME)) park_point.k = RAW_K_POSITION(parser.linearval(AXIS6_NAME)) + if (parser.seenval(AXIS4_NAME)) park_point.i = RAW_X_POSITION(parser.linearval(AXIS4_NAME)), + if (parser.seenval(AXIS5_NAME)) park_point.j = RAW_X_POSITION(parser.linearval(AXIS5_NAME)), + if (parser.seenval(AXIS6_NAME)) park_point.k = RAW_X_POSITION(parser.linearval(AXIS6_NAME)), + if (parser.seenval(AXIS7_NAME)) park_point.u = RAW_X_POSITION(parser.linearval(AXIS7_NAME)), + if (parser.seenval(AXIS8_NAME)) park_point.v = RAW_X_POSITION(parser.linearval(AXIS8_NAME)), + if (parser.seenval(AXIS9_NAME)) park_point.w = RAW_X_POSITION(parser.linearval(AXIS9_NAME)) ); // Lift Z axis - if (parser.seenval('Z')) park_point.z = parser.linearval('Z'); + #if HAS_Z_AXIS + if (parser.seenval('Z')) park_point.z = parser.linearval('Z'); + #endif #if HAS_HOTEND_OFFSET && NONE(DUAL_X_CARRIAGE, DELTA) park_point += hotend_offset[active_extruder]; diff --git a/Marlin/src/gcode/feature/pause/M600.cpp b/Marlin/src/gcode/feature/pause/M600.cpp index 1679c90687..90ebb61832 100644 --- a/Marlin/src/gcode/feature/pause/M600.cpp +++ b/Marlin/src/gcode/feature/pause/M600.cpp @@ -54,8 +54,14 @@ * * E[distance] - Retract the filament this far * Z[distance] - Move the Z axis by this distance - * X[position] - Move to this X position, with Y - * Y[position] - Move to this Y position, with X + * X[position] - Move to this X position (instead of NOZZLE_PARK_POINT.x) + * Y[position] - Move to this Y position (instead of NOZZLE_PARK_POINT.y) + * I[position] - Move to this I position (instead of NOZZLE_PARK_POINT.i) + * J[position] - Move to this J position (instead of NOZZLE_PARK_POINT.j) + * K[position] - Move to this K position (instead of NOZZLE_PARK_POINT.k) + * C[position] - Move to this U position (instead of NOZZLE_PARK_POINT.u) + * H[position] - Move to this V position (instead of NOZZLE_PARK_POINT.v) + * O[position] - Move to this W position (instead of NOZZLE_PARK_POINT.w) * U[distance] - Retract distance for removal (manual reload) * L[distance] - Extrude distance for insertion (manual reload) * B[count] - Number of times to beep, -1 for indefinite (if equipped with a buzzer) @@ -88,7 +94,7 @@ void GcodeSuite::M600() { // In this case, for duplicating modes set DXC_ext to the extruder that ran out. #if MULTI_FILAMENT_SENSOR if (idex_is_duplicating()) - DXC_ext = (READ(FIL_RUNOUT2_PIN) == FIL_RUNOUT2_STATE) ? 1 : 0; + DXC_ext = (READ(FIL_RUNOUT2_PIN) == runout.out_state(1)) ? 1 : 0; #else DXC_ext = active_extruder; #endif @@ -117,26 +123,25 @@ void GcodeSuite::M600() { xyz_pos_t park_point NOZZLE_PARK_POINT; // Move XY axes to filament change position or given position - LINEAR_AXIS_CODE( + NUM_AXIS_CODE( if (parser.seenval('X')) park_point.x = parser.linearval('X'), if (parser.seenval('Y')) park_point.y = parser.linearval('Y'), if (parser.seenval('Z')) park_point.z = parser.linearval('Z'), // Lift Z axis - if (parser.seenval(AXIS4_NAME)) park_point.i = parser.linearval(AXIS4_NAME), - if (parser.seenval(AXIS5_NAME)) park_point.j = parser.linearval(AXIS5_NAME), - if (parser.seenval(AXIS6_NAME)) park_point.k = parser.linearval(AXIS6_NAME) + if (parser.seenval('I')) park_point.i = parser.linearval('I'), + if (parser.seenval('J')) park_point.j = parser.linearval('J'), + if (parser.seenval('K')) park_point.k = parser.linearval('K'), + if (parser.seenval('C')) park_point.u = parser.linearval('C'), // U axis + if (parser.seenval('H')) park_point.v = parser.linearval('H'), // V axis + if (parser.seenval('O')) park_point.w = parser.linearval('O') // W axis ); #if HAS_HOTEND_OFFSET && NONE(DUAL_X_CARRIAGE, DELTA) park_point += hotend_offset[active_extruder]; #endif - #if ENABLED(MMU2_MENUS) - // For MMU2, when enabled, reset retract value so it doesn't mess with MMU filament handling - const float unload_length = standardM600 ? -ABS(parser.axisunitsval('U', E_AXIS, fc_settings[active_extruder].unload_length)) : 0.5f; - #else - // Unload filament - const float unload_length = -ABS(parser.axisunitsval('U', E_AXIS, fc_settings[active_extruder].unload_length)); - #endif + // Unload filament + // For MMU2, when enabled, reset retract value so it doesn't mess with MMU filament handling + const float unload_length = standardM600 ? -ABS(parser.axisunitsval('U', E_AXIS, fc_settings[active_extruder].unload_length)) : 0.5f; const int beep_count = parser.intval('B', -1 #ifdef FILAMENT_CHANGE_ALERT_BEEPS diff --git a/Marlin/src/gcode/feature/pause/M603.cpp b/Marlin/src/gcode/feature/pause/M603.cpp index 6689749cfb..10d14012f8 100644 --- a/Marlin/src/gcode/feature/pause/M603.cpp +++ b/Marlin/src/gcode/feature/pause/M603.cpp @@ -72,7 +72,7 @@ void GcodeSuite::M603_report(const bool forReplay/*=true*/) { SERIAL_ECHOPGM(" M603 L", LINEAR_UNIT(fc_settings[0].load_length), " U", LINEAR_UNIT(fc_settings[0].unload_length), " ;"); say_units(); #else - LOOP_L_N(e, EXTRUDERS) { + EXTRUDER_LOOP() { report_echo_start(forReplay); SERIAL_ECHOPGM(" M603 T", e, " L", LINEAR_UNIT(fc_settings[e].load_length), " U", LINEAR_UNIT(fc_settings[e].unload_length), " ;"); say_units(); diff --git a/Marlin/src/gcode/feature/powerloss/M1000.cpp b/Marlin/src/gcode/feature/powerloss/M1000.cpp index 6fb99226ce..1629a154bc 100644 --- a/Marlin/src/gcode/feature/powerloss/M1000.cpp +++ b/Marlin/src/gcode/feature/powerloss/M1000.cpp @@ -33,7 +33,7 @@ #include "../../../lcd/extui/ui_api.h" #elif ENABLED(DWIN_CREALITY_LCD) #include "../../../lcd/e3v2/creality/dwin.h" -#elif ENABLED(DWIN_CREALITY_LCD_ENHANCED) +#elif ENABLED(DWIN_LCD_PROUI) #include "../../../lcd/e3v2/proui/dwin.h" #elif ENABLED(DWIN_CREALITY_LCD_JYERSUI) #include "../../../lcd/e3v2/jyersui/dwin.h" // Temporary fix until it can be better implemented diff --git a/Marlin/src/gcode/feature/runout/M412.cpp b/Marlin/src/gcode/feature/runout/M412.cpp deleted file mode 100644 index bcf1e9f1b1..0000000000 --- a/Marlin/src/gcode/feature/runout/M412.cpp +++ /dev/null @@ -1,81 +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 . - * - */ - -#include "../../../inc/MarlinConfig.h" - -#if HAS_FILAMENT_SENSOR - -#include "../../gcode.h" -#include "../../../feature/runout.h" - -/** - * M412: Enable / Disable filament runout detection - * - * Parameters - * R : Reset the runout sensor - * S : Reset and enable/disable the runout sensor - * H : Enable/disable host handling of filament runout - * D : Extra distance to continue after runout is triggered - */ -void GcodeSuite::M412() { - if (parser.seen("RS" - TERN_(HAS_FILAMENT_RUNOUT_DISTANCE, "D") - TERN_(HOST_ACTION_COMMANDS, "H") - )) { - #if ENABLED(HOST_ACTION_COMMANDS) - if (parser.seen('H')) runout.host_handling = parser.value_bool(); - #endif - const bool seenR = parser.seen_test('R'), seenS = parser.seen('S'); - if (seenR || seenS) runout.reset(); - if (seenS) runout.enabled = parser.value_bool(); - #if HAS_FILAMENT_RUNOUT_DISTANCE - if (parser.seen('D')) runout.set_runout_distance(parser.value_linear_units()); - #endif - } - else { - SERIAL_ECHO_START(); - SERIAL_ECHOPGM("Filament runout "); - serialprint_onoff(runout.enabled); - #if HAS_FILAMENT_RUNOUT_DISTANCE - SERIAL_ECHOPGM(" ; Distance ", runout.runout_distance(), "mm"); - #endif - #if ENABLED(HOST_ACTION_COMMANDS) - SERIAL_ECHOPGM(" ; Host handling "); - serialprint_onoff(runout.host_handling); - #endif - SERIAL_EOL(); - } -} - -void GcodeSuite::M412_report(const bool forReplay/*=true*/) { - report_heading_etc(forReplay, F(STR_FILAMENT_RUNOUT_SENSOR)); - SERIAL_ECHOPGM( - " M412 S", runout.enabled - #if HAS_FILAMENT_RUNOUT_DISTANCE - , " D", LINEAR_UNIT(runout.runout_distance()) - #endif - , " ; Sensor " - ); - serialprintln_onoff(runout.enabled); -} - -#endif // HAS_FILAMENT_SENSOR diff --git a/Marlin/src/gcode/feature/runout/M591.cpp b/Marlin/src/gcode/feature/runout/M591.cpp new file mode 100644 index 0000000000..adb1bb8599 --- /dev/null +++ b/Marlin/src/gcode/feature/runout/M591.cpp @@ -0,0 +1,97 @@ +/** + * 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 . + * + */ + +#include "../../../inc/MarlinConfig.h" + +#if HAS_FILAMENT_SENSOR + +#include "../../gcode.h" +#include "../../../feature/runout.h" + +/** + * M591: Configure filament runout detection + * + * Parameters + * R : Reset the runout sensor + * S : Reset and enable/disable the runout sensor + * H : Enable/disable host handling of filament runout + * L : Extra distance to continue after runout is triggered or motion interval + * D : Alias for L + * P : Mode 0 = NONE + * 1 = Switch NO (HIGH = filament present) + * 2 = Switch NC (LOW = filament present) + * 3 = Encoder / Motion Sensor + */ +void GcodeSuite::M591() { + if (parser.seen("RSDP" TERN_(HOST_ACTION_COMMANDS, "H"))) { + #if ENABLED(HOST_ACTION_COMMANDS) + if (parser.seen('H')) runout.host_handling = parser.value_bool(); + #endif + const bool seenR = parser.seen_test('R'), seenS = parser.seen('S'); + if (seenR || seenS) runout.reset(); + const uint8_t tool = TERN0(MULTI_FILAMENT_SENSOR, parser.ushortval('E', active_extruder)); + if (seenS) runout.enabled[tool] = parser.value_bool(); + if (parser.seen('D') || parser.seen('L')) runout.set_runout_distance(parser.value_linear_units(), tool); + if (parser.seen('P')) { + const RunoutMode tmp_mode = (RunoutMode)parser.value_int(); + switch (tmp_mode) { + case RM_NONE ... RM_OUT_ON_HIGH: + case RM_MOTION_SENSOR: + runout.mode[tool] = tmp_mode; + runout.setup(); + default: break; + } + } + } + else { + #if DISABLED(SLIM_LCD_MENUS) + SERIAL_ECHO_START(); + SERIAL_ECHOPGM("Filament runout "); + serialprint_onoff(runout.enabled[active_extruder]); + SERIAL_ECHOPGM(" ; Distance ", runout.runout_distance(active_extruder), "mm"); + SERIAL_ECHOPGM(" ; Mode ", runout.mode[active_extruder]); + #if ENABLED(HOST_ACTION_COMMANDS) + SERIAL_ECHOPGM(" ; Host handling "); + serialprint_onoff(runout.host_handling); + #endif + SERIAL_EOL(); + #else + M591_report(false); + #endif + } +} + +void GcodeSuite::M591_report(const bool forReplay/*=true*/) { + report_heading_etc(forReplay, F(STR_FILAMENT_RUNOUT_SENSOR)); + LOOP_S_L_N(e, 1, NUM_RUNOUT_SENSORS) + SERIAL_ECHOLNPGM( + " M591" + #if MULTI_FILAMENT_SENSOR + " E", e, + #endif + " S", runout.enabled[e] + , " D", LINEAR_UNIT(runout.runout_distance(e)) + , " P", runout.mode[e] + ); +} + +#endif // HAS_FILAMENT_SENSOR diff --git a/Marlin/src/gcode/feature/trinamic/M569.cpp b/Marlin/src/gcode/feature/trinamic/M569.cpp index 7bfedf8c72..3a325ad264 100644 --- a/Marlin/src/gcode/feature/trinamic/M569.cpp +++ b/Marlin/src/gcode/feature/trinamic/M569.cpp @@ -85,6 +85,15 @@ static void set_stealth_status(const bool enable, const int8_t eindex) { #if K_HAS_STEALTHCHOP case K_AXIS: TMC_SET_STEALTH(K); break; #endif + #if U_HAS_STEALTHCHOP + case U_AXIS: TMC_SET_STEALTH(U); break; + #endif + #if V_HAS_STEALTHCHOP + case V_AXIS: TMC_SET_STEALTH(V); break; + #endif + #if W_HAS_STEALTHCHOP + case W_AXIS: TMC_SET_STEALTH(W); break; + #endif #if E_STEPPERS case E_AXIS: { @@ -115,6 +124,9 @@ static void say_stealth_status() { OPTCODE( I_HAS_STEALTHCHOP, TMC_SAY_STEALTH_STATUS(I)) OPTCODE( J_HAS_STEALTHCHOP, TMC_SAY_STEALTH_STATUS(J)) OPTCODE( K_HAS_STEALTHCHOP, TMC_SAY_STEALTH_STATUS(K)) + OPTCODE( U_HAS_STEALTHCHOP, TMC_SAY_STEALTH_STATUS(U)) + OPTCODE( V_HAS_STEALTHCHOP, TMC_SAY_STEALTH_STATUS(V)) + OPTCODE( W_HAS_STEALTHCHOP, TMC_SAY_STEALTH_STATUS(W)) OPTCODE(E0_HAS_STEALTHCHOP, TMC_SAY_STEALTH_STATUS(E0)) OPTCODE(E1_HAS_STEALTHCHOP, TMC_SAY_STEALTH_STATUS(E1)) OPTCODE(E2_HAS_STEALTHCHOP, TMC_SAY_STEALTH_STATUS(E2)) @@ -157,17 +169,23 @@ void GcodeSuite::M569_report(const bool forReplay/*=true*/) { chop_z = TERN0(Z_HAS_STEALTHCHOP, stepperZ.get_stored_stealthChop()), chop_i = TERN0(I_HAS_STEALTHCHOP, stepperI.get_stored_stealthChop()), chop_j = TERN0(J_HAS_STEALTHCHOP, stepperJ.get_stored_stealthChop()), - chop_k = TERN0(K_HAS_STEALTHCHOP, stepperK.get_stored_stealthChop()); + chop_k = TERN0(K_HAS_STEALTHCHOP, stepperK.get_stored_stealthChop()), + chop_u = TERN0(U_HAS_STEALTHCHOP, stepperU.get_stored_stealthChop()), + chop_v = TERN0(V_HAS_STEALTHCHOP, stepperV.get_stored_stealthChop()), + chop_w = TERN0(W_HAS_STEALTHCHOP, stepperW.get_stored_stealthChop()); - if (chop_x || chop_y || chop_z || chop_i || chop_j || chop_k) { + if (chop_x || chop_y || chop_z || chop_i || chop_j || chop_k || chop_u || chop_v || chop_w) { say_M569(forReplay); - LINEAR_AXIS_CODE( + NUM_AXIS_CODE( if (chop_x) SERIAL_ECHOPGM_P(SP_X_STR), if (chop_y) SERIAL_ECHOPGM_P(SP_Y_STR), if (chop_z) SERIAL_ECHOPGM_P(SP_Z_STR), if (chop_i) SERIAL_ECHOPGM_P(SP_I_STR), if (chop_j) SERIAL_ECHOPGM_P(SP_J_STR), - if (chop_k) SERIAL_ECHOPGM_P(SP_K_STR) + if (chop_k) SERIAL_ECHOPGM_P(SP_K_STR), + if (chop_u) SERIAL_ECHOPGM_P(SP_U_STR), + if (chop_v) SERIAL_ECHOPGM_P(SP_V_STR), + if (chop_w) SERIAL_ECHOPGM_P(SP_W_STR) ); SERIAL_EOL(); } @@ -190,6 +208,9 @@ void GcodeSuite::M569_report(const bool forReplay/*=true*/) { if (TERN0( I_HAS_STEALTHCHOP, stepperI.get_stored_stealthChop())) { say_M569(forReplay, FPSTR(SP_I_STR), true); } if (TERN0( J_HAS_STEALTHCHOP, stepperJ.get_stored_stealthChop())) { say_M569(forReplay, FPSTR(SP_J_STR), true); } if (TERN0( K_HAS_STEALTHCHOP, stepperK.get_stored_stealthChop())) { say_M569(forReplay, FPSTR(SP_K_STR), true); } + if (TERN0( U_HAS_STEALTHCHOP, stepperU.get_stored_stealthChop())) { say_M569(forReplay, FPSTR(SP_U_STR), true); } + if (TERN0( V_HAS_STEALTHCHOP, stepperV.get_stored_stealthChop())) { say_M569(forReplay, FPSTR(SP_V_STR), true); } + if (TERN0( W_HAS_STEALTHCHOP, stepperW.get_stored_stealthChop())) { say_M569(forReplay, FPSTR(SP_W_STR), true); } if (TERN0(E0_HAS_STEALTHCHOP, stepperE0.get_stored_stealthChop())) { say_M569(forReplay, F("T0 E"), true); } if (TERN0(E1_HAS_STEALTHCHOP, stepperE1.get_stored_stealthChop())) { say_M569(forReplay, F("T1 E"), true); } diff --git a/Marlin/src/gcode/feature/trinamic/M906.cpp b/Marlin/src/gcode/feature/trinamic/M906.cpp index 164ff00179..4822b8e268 100644 --- a/Marlin/src/gcode/feature/trinamic/M906.cpp +++ b/Marlin/src/gcode/feature/trinamic/M906.cpp @@ -44,6 +44,9 @@ static void tmc_print_current(TMC &st) { * A[current] - Set mA current for A driver(s) (Requires AXIS*_NAME 'A') * B[current] - Set mA current for B driver(s) (Requires AXIS*_NAME 'B') * C[current] - Set mA current for C driver(s) (Requires AXIS*_NAME 'C') + * U[current] - Set mA current for U driver(s) (Requires AXIS*_NAME 'U') + * V[current] - Set mA current for V driver(s) (Requires AXIS*_NAME 'V') + * W[current] - Set mA current for W driver(s) (Requires AXIS*_NAME 'W') * E[current] - Set mA current for E driver(s) * * I[index] - Axis sub-index (Omit or 0 for X, Y, Z; 1 for X2, Y2, Z2; 2 for Z3; 3 for Z4.) @@ -59,7 +62,7 @@ void GcodeSuite::M906() { #if AXIS_IS_TMC(X2) || AXIS_IS_TMC(Y2) || AXIS_IS_TMC(Z2) || AXIS_IS_TMC(Z3) || AXIS_IS_TMC(Z4) const int8_t index = parser.byteval('I', -1); - #else + #elif AXIS_IS_TMC(X) || AXIS_IS_TMC(Y) || AXIS_IS_TMC(Z) constexpr int8_t index = -1; #endif @@ -114,6 +117,15 @@ void GcodeSuite::M906() { #if AXIS_IS_TMC(K) case K_AXIS: TMC_SET_CURRENT(K); break; #endif + #if AXIS_IS_TMC(U) + case U_AXIS: TMC_SET_CURRENT(U); break; + #endif + #if AXIS_IS_TMC(V) + case V_AXIS: TMC_SET_CURRENT(V); break; + #endif + #if AXIS_IS_TMC(W) + case W_AXIS: TMC_SET_CURRENT(W); break; + #endif #if AXIS_IS_TMC(E0) || AXIS_IS_TMC(E1) || AXIS_IS_TMC(E2) || AXIS_IS_TMC(E3) || AXIS_IS_TMC(E4) || AXIS_IS_TMC(E5) || AXIS_IS_TMC(E6) || AXIS_IS_TMC(E7) case E_AXIS: { @@ -181,6 +193,16 @@ void GcodeSuite::M906() { #if AXIS_IS_TMC(K) TMC_SAY_CURRENT(K); #endif + #if AXIS_IS_TMC(U) + TMC_SAY_CURRENT(U); + #endif + #if AXIS_IS_TMC(V) + TMC_SAY_CURRENT(V); + #endif + #if AXIS_IS_TMC(W) + TMC_SAY_CURRENT(W); + #endif + #if AXIS_IS_TMC(E0) TMC_SAY_CURRENT(E0); #endif @@ -217,7 +239,8 @@ void GcodeSuite::M906_report(const bool forReplay/*=true*/) { }; #if AXIS_IS_TMC(X) || AXIS_IS_TMC(Y) || AXIS_IS_TMC(Z) \ - || AXIS_IS_TMC(I) || AXIS_IS_TMC(J) || AXIS_IS_TMC(K) + || AXIS_IS_TMC(I) || AXIS_IS_TMC(J) || AXIS_IS_TMC(K) \ + || AXIS_IS_TMC(U) || AXIS_IS_TMC(V) || AXIS_IS_TMC(W) say_M906(forReplay); #if AXIS_IS_TMC(X) SERIAL_ECHOPGM_P(SP_X_STR, stepperX.getMilliamps()); @@ -237,6 +260,15 @@ void GcodeSuite::M906_report(const bool forReplay/*=true*/) { #if AXIS_IS_TMC(K) SERIAL_ECHOPGM_P(SP_K_STR, stepperK.getMilliamps()); #endif + #if AXIS_IS_TMC(U) + SERIAL_ECHOPGM_P(SP_U_STR, stepperU.getMilliamps()); + #endif + #if AXIS_IS_TMC(V) + SERIAL_ECHOPGM_P(SP_V_STR, stepperV.getMilliamps()); + #endif + #if AXIS_IS_TMC(W) + SERIAL_ECHOPGM_P(SP_W_STR, stepperW.getMilliamps()); + #endif SERIAL_EOL(); #endif diff --git a/Marlin/src/gcode/feature/trinamic/M911-M914.cpp b/Marlin/src/gcode/feature/trinamic/M911-M914.cpp index 628ae40f48..206e2e456c 100644 --- a/Marlin/src/gcode/feature/trinamic/M911-M914.cpp +++ b/Marlin/src/gcode/feature/trinamic/M911-M914.cpp @@ -53,12 +53,21 @@ #if HAS_K_AXIS && M91x_USE(K) #define M91x_USE_K 1 #endif + #if HAS_U_AXIS && M91x_USE(U) + #define M91x_USE_U 1 + #endif + #if HAS_V_AXIS && M91x_USE(V) + #define M91x_USE_V 1 + #endif + #if HAS_W_AXIS && M91x_USE(W) + #define M91x_USE_W 1 + #endif #if M91x_USE_E(0) || M91x_USE_E(1) || M91x_USE_E(2) || M91x_USE_E(3) || M91x_USE_E(4) || M91x_USE_E(5) || M91x_USE_E(6) || M91x_USE_E(7) #define M91x_SOME_E 1 #endif - #if !M91x_SOME_X && !M91x_SOME_Y && !M91x_SOME_Z && !M91x_USE_I && !M91x_USE_J && !M91x_USE_K && !M91x_SOME_E + #if !M91x_SOME_X && !M91x_SOME_Y && !M91x_SOME_Z && !M91x_USE_I && !M91x_USE_J && !M91x_USE_K && !M91x_USE_U && !M91x_USE_V && !M91x_USE_W && !M91x_SOME_E #error "MONITOR_DRIVER_STATUS requires at least one TMC2130, 2160, 2208, 2209, 2660, 5130, or 5160." #endif @@ -109,6 +118,9 @@ TERN_(M91x_USE_I, tmc_report_otpw(stepperI)); TERN_(M91x_USE_J, tmc_report_otpw(stepperJ)); TERN_(M91x_USE_K, tmc_report_otpw(stepperK)); + TERN_(M91x_USE_U, tmc_report_otpw(stepperU)); + TERN_(M91x_USE_V, tmc_report_otpw(stepperV)); + TERN_(M91x_USE_W, tmc_report_otpw(stepperW)); #if M91x_USE_E(0) tmc_report_otpw(stepperE0); #endif @@ -137,7 +149,7 @@ /** * M912: Clear TMC stepper driver overtemperature pre-warn flag held by the library - * Specify one or more axes with X, Y, Z, X1, Y1, Z1, X2, Y2, Z2, Z3, Z4 and E[index]. + * Specify one or more axes with X, Y, Z, X1, Y1, Z1, X2, Y2, Z2, Z3, Z4, A, B, C, U, V, W, and E[index]. * If no axes are given, clear all. * * Examples: @@ -154,9 +166,12 @@ hasI = TERN0(M91x_USE_I, parser.seen(axis_codes.i)), hasJ = TERN0(M91x_USE_J, parser.seen(axis_codes.j)), hasK = TERN0(M91x_USE_K, parser.seen(axis_codes.k)), + hasU = TERN0(M91x_USE_U, parser.seen(axis_codes.u)), + hasV = TERN0(M91x_USE_V, parser.seen(axis_codes.v)), + hasW = TERN0(M91x_USE_W, parser.seen(axis_codes.w)), hasE = TERN0(M91x_SOME_E, parser.seen(axis_codes.e)); - const bool hasNone = !hasE && !hasX && !hasY && !hasZ && !hasI && !hasJ && !hasK; + const bool hasNone = !hasE && !hasX && !hasY && !hasZ && !hasI && !hasJ && !hasK && !hasU && !hasV && !hasW; #if M91x_SOME_X const int8_t xval = int8_t(parser.byteval(axis_codes.x, 0xFF)); @@ -206,6 +221,18 @@ const int8_t kval = int8_t(parser.byteval(axis_codes.k, 0xFF)); if (hasNone || kval == 1 || (hasK && kval < 0)) tmc_clear_otpw(stepperK); #endif + #if M91x_USE_U + const int8_t uval = int8_t(parser.byteval(axis_codes.u, 0xFF)); + if (hasNone || uval == 1 || (hasU && uval < 0)) tmc_clear_otpw(stepperU); + #endif + #if M91x_USE_V + const int8_t vval = int8_t(parser.byteval(axis_codes.v, 0xFF)); + if (hasNone || vval == 1 || (hasV && vval < 0)) tmc_clear_otpw(stepperV); + #endif + #if M91x_USE_W + const int8_t wval = int8_t(parser.byteval(axis_codes.w, 0xFF)); + if (hasNone || wval == 1 || (hasW && wval < 0)) tmc_clear_otpw(stepperW); + #endif #if M91x_SOME_E const int8_t eval = int8_t(parser.byteval(axis_codes.e, 0xFF)); @@ -258,7 +285,7 @@ bool report = true; #if AXIS_IS_TMC(X2) || AXIS_IS_TMC(Y2) || AXIS_IS_TMC(Z2) || AXIS_IS_TMC(Z3) || AXIS_IS_TMC(Z4) const int8_t index = parser.byteval('I', -1); - #else + #elif AXIS_IS_TMC(X) || AXIS_IS_TMC(Y) || AXIS_IS_TMC(Z) constexpr int8_t index = -1; #endif LOOP_LOGICAL_AXES(i) if (int32_t value = parser.longval(axis_codes[i])) { @@ -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,98 +502,66 @@ 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) { #if X_SENSORLESS case X_AXIS: - #if AXIS_HAS_STALLGUARD(X) - if (index < 2) stepperX.homing_threshold(value); - #endif - #if AXIS_HAS_STALLGUARD(X2) - if (!(index & 1)) stepperX2.homing_threshold(value); - #endif + if (index < 2) stepperX.homing_threshold(value); + TERN_(X2_SENSORLESS, if (!(index & 1)) stepperX2.homing_threshold(value)); break; #endif #if Y_SENSORLESS case Y_AXIS: - #if AXIS_HAS_STALLGUARD(Y) - if (index < 2) stepperY.homing_threshold(value); - #endif - #if AXIS_HAS_STALLGUARD(Y2) - if (!(index & 1)) stepperY2.homing_threshold(value); - #endif + if (index < 2) stepperY.homing_threshold(value); + TERN_(Y2_SENSORLESS, if (!(index & 1)) stepperY2.homing_threshold(value)); break; #endif #if Z_SENSORLESS case Z_AXIS: - #if AXIS_HAS_STALLGUARD(Z) - if (index < 2) stepperZ.homing_threshold(value); - #endif - #if AXIS_HAS_STALLGUARD(Z2) - if (index == 0 || index == 2) stepperZ2.homing_threshold(value); - #endif - #if AXIS_HAS_STALLGUARD(Z3) - if (index == 0 || index == 3) stepperZ3.homing_threshold(value); - #endif - #if AXIS_HAS_STALLGUARD(Z4) - if (index == 0 || index == 4) stepperZ4.homing_threshold(value); - #endif + if (index < 2) stepperZ.homing_threshold(value); + TERN_(Z2_SENSORLESS, if (index == 0 || index == 2) stepperZ2.homing_threshold(value)); + TERN_(Z3_SENSORLESS, if (index == 0 || index == 3) stepperZ3.homing_threshold(value)); + TERN_(Z4_SENSORLESS, if (index == 0 || index == 4) stepperZ4.homing_threshold(value)); break; #endif - #if I_SENSORLESS && AXIS_HAS_STALLGUARD(I) + #if I_SENSORLESS case I_AXIS: stepperI.homing_threshold(value); break; #endif - #if J_SENSORLESS && AXIS_HAS_STALLGUARD(J) + #if J_SENSORLESS case J_AXIS: stepperJ.homing_threshold(value); break; #endif - #if K_SENSORLESS && AXIS_HAS_STALLGUARD(K) + #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 } } if (report) { - #if X_SENSORLESS - #if AXIS_HAS_STALLGUARD(X) - tmc_print_sgt(stepperX); - #endif - #if AXIS_HAS_STALLGUARD(X2) - tmc_print_sgt(stepperX2); - #endif - #endif - #if Y_SENSORLESS - #if AXIS_HAS_STALLGUARD(Y) - tmc_print_sgt(stepperY); - #endif - #if AXIS_HAS_STALLGUARD(Y2) - tmc_print_sgt(stepperY2); - #endif - #endif - #if Z_SENSORLESS - #if AXIS_HAS_STALLGUARD(Z) - tmc_print_sgt(stepperZ); - #endif - #if AXIS_HAS_STALLGUARD(Z2) - tmc_print_sgt(stepperZ2); - #endif - #if AXIS_HAS_STALLGUARD(Z3) - tmc_print_sgt(stepperZ3); - #endif - #if AXIS_HAS_STALLGUARD(Z4) - tmc_print_sgt(stepperZ4); - #endif - #endif - #if I_SENSORLESS && AXIS_HAS_STALLGUARD(I) - tmc_print_sgt(stepperI); - #endif - #if J_SENSORLESS && AXIS_HAS_STALLGUARD(J) - tmc_print_sgt(stepperJ); - #endif - #if K_SENSORLESS && AXIS_HAS_STALLGUARD(K) - tmc_print_sgt(stepperK); - #endif + TERN_(X_SENSORLESS, tmc_print_sgt(stepperX)); + TERN_(X2_SENSORLESS, tmc_print_sgt(stepperX2)); + TERN_(Y_SENSORLESS, tmc_print_sgt(stepperY)); + TERN_(Y2_SENSORLESS, tmc_print_sgt(stepperY2)); + TERN_(Z_SENSORLESS, tmc_print_sgt(stepperZ)); + TERN_(Z2_SENSORLESS, tmc_print_sgt(stepperZ2)); + TERN_(Z3_SENSORLESS, tmc_print_sgt(stepperZ3)); + TERN_(Z4_SENSORLESS, tmc_print_sgt(stepperZ4)); + 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)); } } @@ -605,6 +624,18 @@ say_M914(forReplay); SERIAL_ECHOLNPGM_P(SP_K_STR, stepperK.homing_threshold()); #endif + #if U_SENSORLESS + say_M914(forReplay); + SERIAL_ECHOLNPGM_P(SP_U_STR, stepperU.homing_threshold()); + #endif + #if V_SENSORLESS + say_M914(forReplay); + SERIAL_ECHOLNPGM_P(SP_V_STR, stepperV.homing_threshold()); + #endif + #if W_SENSORLESS + say_M914(forReplay); + SERIAL_ECHOLNPGM_P(SP_W_STR, stepperW.homing_threshold()); + #endif } #endif // USE_SENSORLESS diff --git a/Marlin/src/gcode/feature/trinamic/M919.cpp b/Marlin/src/gcode/feature/trinamic/M919.cpp index 4dce28f0ae..d4ba4f74ea 100644 --- a/Marlin/src/gcode/feature/trinamic/M919.cpp +++ b/Marlin/src/gcode/feature/trinamic/M919.cpp @@ -93,7 +93,7 @@ void GcodeSuite::M919() { #if AXIS_IS_TMC(X2) || AXIS_IS_TMC(Y2) || AXIS_IS_TMC(Z2) || AXIS_IS_TMC(Z3) || AXIS_IS_TMC(Z4) const int8_t index = parser.byteval('I'); - #else + #elif AXIS_IS_TMC(X) || AXIS_IS_TMC(Y) || AXIS_IS_TMC(Z) constexpr int8_t index = -1; #endif diff --git a/Marlin/src/gcode/gcode.cpp b/Marlin/src/gcode/gcode.cpp index c365f8a67b..b16be8eaf0 100644 --- a/Marlin/src/gcode/gcode.cpp +++ b/Marlin/src/gcode/gcode.cpp @@ -85,7 +85,10 @@ axis_bits_t GcodeSuite::axis_relative = 0 LOGICAL_AXIS_GANG( | (ar_init.z << REL_Z), | (ar_init.i << REL_I), | (ar_init.j << REL_J), - | (ar_init.k << REL_K) + | (ar_init.k << REL_K), + | (ar_init.u << REL_U), + | (ar_init.v << REL_V), + | (ar_init.w << REL_W) ); #if EITHER(HAS_AUTO_REPORTING, HOST_KEEPALIVE_FEATURE) @@ -176,7 +179,7 @@ void GcodeSuite::get_destination_from_command() { #endif // Get new XYZ position, whether absolute or relative - LOOP_LINEAR_AXES(i) { + LOOP_NUM_AXES(i) { if ( (seen[i] = parser.seenval(AXIS_CHAR(i))) ) { const float v = parser.value_axis_units((AxisEnum)i); if (skip_move) @@ -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 @@ -822,10 +829,6 @@ void GcodeSuite::process_parsed_command(const bool no_ok/*=false*/) { case 407: M407(); break; // M407: Display measured filament diameter #endif - #if HAS_FILAMENT_SENSOR - case 412: M412(); break; // M412: Enable/Disable filament runout detection - #endif - #if HAS_MULTI_LANGUAGE case 414: M414(); break; // M414: Select multi language menu #endif @@ -892,6 +895,11 @@ void GcodeSuite::process_parsed_command(const bool no_ok/*=false*/) { case 575: M575(); break; // M575: Set serial baudrate #endif + #if HAS_FILAMENT_SENSOR + case 412: M412(); break; // Alias to M591 + case 591: M591(); break; // M591 Configure filament runout detection + #endif + #if ENABLED(ADVANCED_PAUSE_FEATURE) case 600: M600(); break; // M600: Pause for Filament Change case 603: M603(); break; // M603: Configure Filament Change diff --git a/Marlin/src/gcode/gcode.h b/Marlin/src/gcode/gcode.h index a150aca41d..1b2f6ec275 100644 --- a/Marlin/src/gcode/gcode.h +++ b/Marlin/src/gcode/gcode.h @@ -215,12 +215,13 @@ * M303 - PID relay autotune S 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.) * M355 - Set Case Light on/off and set brightness. (Requires CASE_LIGHT_PIN) - * M380 - Activate solenoid on active extruder. (Requires EXT_SOLENOID) - * M381 - Disable all solenoids. (Requires EXT_SOLENOID) + * M380 - Activate solenoid on active tool (Requires EXT_SOLENOID) or the tool specified by 'S' (Requires MANUAL_SOLENOID_CONTROL). + * M381 - Disable solenoids on all tools (Requires EXT_SOLENOID) or the tool specified by 'S' (Requires MANUAL_SOLENOID_CONTROL). * M400 - Finish all moves. * M401 - Deploy and activate Z probe. (Requires a probe) * M402 - Deactivate and stow Z probe. (Requires a probe) @@ -230,7 +231,6 @@ * M406 - Disable Filament Sensor flow control. (Requires FILAMENT_WIDTH_SENSOR) * M407 - Display measured filament diameter in millimeters. (Requires FILAMENT_WIDTH_SENSOR) * M410 - Quickstop. Abort all planned moves. - * M412 - Enable / Disable Filament Runout Detection. (Requires FILAMENT_RUNOUT_SENSOR) * M413 - Enable / Disable Power-Loss Recovery. (Requires POWER_LOSS_RECOVERY) * M414 - Set language by index. (Requires LCD_LANGUAGE_2...) * M420 - Enable/Disable Leveling (with current values) S1=enable S0=disable (Requires MESH_BED_LEVELING or ABL) @@ -255,6 +255,7 @@ * M554 - Get or set IP gateway. (Requires enabled Ethernet port) * M569 - Enable stealthChop on an axis. (Requires at least one _DRIVER_TYPE to be TMC2130/2160/2208/2209/5130/5160) * M575 - Change the serial baud rate. (Requires BAUD_RATE_GCODE) + * M591 - Configure Filament Runout Detection. (Requires FILAMENT_RUNOUT_SENSOR) * M600 - Pause for filament change: "M600 X Y Z E L". (Requires ADVANCED_PAUSE_FEATURE) * M603 - Configure filament change: "M603 T U L". (Requires ADVANCED_PAUSE_FEATURE) * M605 - Set Dual X-Carriage movement mode: "M605 S [X] [R]". (Requires DUAL_X_CARRIAGE) @@ -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); @@ -978,8 +985,9 @@ private: #endif #if HAS_FILAMENT_SENSOR - static void M412(); - static void M412_report(const bool forReplay=true); + static void M412() { M591(); } + static void M591(); + static void M591_report(const bool forReplay=true); #endif #if HAS_MULTI_LANGUAGE @@ -1195,6 +1203,11 @@ private: static void M1000(); #endif + #if ENABLED(X_AXIS_TWIST_COMPENSATION) + static void M423(); + static void M423_report(const bool forReplay=true); + #endif + #if ENABLED(SDSUPPORT) static void M1001(); #endif diff --git a/Marlin/src/gcode/geometry/G53-G59.cpp b/Marlin/src/gcode/geometry/G53-G59.cpp index db2404a28d..092c141228 100644 --- a/Marlin/src/gcode/geometry/G53-G59.cpp +++ b/Marlin/src/gcode/geometry/G53-G59.cpp @@ -39,7 +39,7 @@ bool GcodeSuite::select_coordinate_system(const int8_t _new) { xyz_float_t new_offset{0}; if (WITHIN(_new, 0, MAX_COORDINATE_SYSTEMS - 1)) new_offset = coordinate_system[_new]; - LOOP_LINEAR_AXES(i) { + LOOP_NUM_AXES(i) { if (position_shift[i] != new_offset[i]) { position_shift[i] = new_offset[i]; update_workspace_offset((AxisEnum)i); diff --git a/Marlin/src/gcode/geometry/G92.cpp b/Marlin/src/gcode/geometry/G92.cpp index 3c49fe2a26..2407599239 100644 --- a/Marlin/src/gcode/geometry/G92.cpp +++ b/Marlin/src/gcode/geometry/G92.cpp @@ -29,7 +29,7 @@ #endif /** - * G92: Set the Current Position to the given X [Y [Z [A [B [C [E]]]]]] values. + * G92: Set the Current Position to the given X [Y [Z [A [B [C [U [V [W ]]]]]]]] [E] values. * * Behind the scenes the G92 command may modify the Current Position * or the Position Shift depending on settings and sub-commands. @@ -37,14 +37,14 @@ * Since E has no Workspace Offset, it is always set directly. * * Without Workspace Offsets (e.g., with NO_WORKSPACE_OFFSETS): - * G92 : Set NATIVE Current Position to the given X [Y [Z [A [B [C [E]]]]]]. + * G92 : Set NATIVE Current Position to the given X [Y [Z [A [B [C [U [V [W ]]]]]]]] [E]. * * Using Workspace Offsets (default Marlin behavior): - * G92 : Modify Workspace Offsets so the reported position shows the given X [Y [Z [A [B [C [E]]]]]]. + * G92 : Modify Workspace Offsets so the reported position shows the given X [Y [Z [A [B [C [U [V [W ]]]]]]]] [E]. * G92.1 : Zero XYZ Workspace Offsets (so the reported position = the native position). * * With POWER_LOSS_RECOVERY: - * G92.9 : Set NATIVE Current Position to the given X [Y [Z [A [B [C [E]]]]]]. + * G92.9 : Set NATIVE Current Position to the given X [Y [Z [A [B [C [U [V [W ]]]]]]]] [E]. */ void GcodeSuite::G92() { @@ -64,7 +64,7 @@ void GcodeSuite::G92() { #if ENABLED(CNC_COORDINATE_SYSTEMS) && !IS_SCARA case 1: // G92.1 - Zero the Workspace Offset - LOOP_LINEAR_AXES(i) if (position_shift[i]) { + LOOP_NUM_AXES(i) if (position_shift[i]) { position_shift[i] = 0; update_workspace_offset((AxisEnum)i); } diff --git a/Marlin/src/gcode/geometry/M206_M428.cpp b/Marlin/src/gcode/geometry/M206_M428.cpp index 131dbecf33..f23c83140e 100644 --- a/Marlin/src/gcode/geometry/M206_M428.cpp +++ b/Marlin/src/gcode/geometry/M206_M428.cpp @@ -39,11 +39,17 @@ */ void GcodeSuite::M206() { if (!parser.seen_any()) return M206_report(); - - LOOP_LINEAR_AXES(i) - if (parser.seen(AXIS_CHAR(i))) - set_home_offset((AxisEnum)i, parser.value_linear_units()); - + NUM_AXIS_CODE( + if (parser.seen('X')) set_home_offset(X_AXIS, parser.value_linear_units()), + if (parser.seen('Y')) set_home_offset(Y_AXIS, parser.value_linear_units()), + if (parser.seen('Z')) set_home_offset(Y_AXIS, parser.value_linear_units()), + if (parser.seen(AXIS4_NAME)) set_home_offset(I_AXIS, parser.TERN(AXIS4_ROTATES, value_float, value_linear_units)()), + if (parser.seen(AXIS5_NAME)) set_home_offset(J_AXIS, parser.TERN(AXIS5_ROTATES, value_float, value_linear_units)()), + if (parser.seen(AXIS6_NAME)) set_home_offset(K_AXIS, parser.TERN(AXIS6_ROTATES, value_float, value_linear_units)()), + if (parser.seen(AXIS7_NAME)) set_home_offset(U_AXIS, parser.TERN(AXIS7_ROTATES, value_float, value_linear_units)()), + if (parser.seen(AXIS8_NAME)) set_home_offset(V_AXIS, parser.TERN(AXIS8_ROTATES, value_float, value_linear_units)()), + if (parser.seen(AXIS9_NAME)) set_home_offset(W_AXIS, parser.TERN(AXIS9_ROTATES, value_float, value_linear_units)()) + ); #if ENABLED(MORGAN_SCARA) if (parser.seen('T')) set_home_offset(A_AXIS, parser.value_float()); // Theta if (parser.seen('P')) set_home_offset(B_AXIS, parser.value_float()); // Psi @@ -56,13 +62,16 @@ void GcodeSuite::M206_report(const bool forReplay/*=true*/) { report_heading_etc(forReplay, F(STR_HOME_OFFSET)); SERIAL_ECHOLNPGM_P( #if IS_CARTESIAN - LIST_N(DOUBLE(LINEAR_AXES), + LIST_N(DOUBLE(NUM_AXES), PSTR(" M206 X"), LINEAR_UNIT(home_offset.x), SP_Y_STR, LINEAR_UNIT(home_offset.y), SP_Z_STR, LINEAR_UNIT(home_offset.z), - SP_I_STR, LINEAR_UNIT(home_offset.i), - SP_J_STR, LINEAR_UNIT(home_offset.j), - SP_K_STR, LINEAR_UNIT(home_offset.k) + SP_I_STR, I_AXIS_UNIT(home_offset.i), + SP_J_STR, J_AXIS_UNIT(home_offset.j), + SP_K_STR, K_AXIS_UNIT(home_offset.k), + SP_U_STR, U_AXIS_UNIT(home_offset.u), + SP_V_STR, V_AXIS_UNIT(home_offset.v), + SP_W_STR, W_AXIS_UNIT(home_offset.w) ) #else PSTR(" M206 Z"), LINEAR_UNIT(home_offset.z) @@ -85,23 +94,22 @@ 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]; if (!WITHIN(diff[i], -20, 20)) { SERIAL_ERROR_MSG(STR_ERR_M428_TOO_FAR); LCD_ALERTMESSAGE_F("Err: Too far!"); - BUZZ(200, 40); + ERR_BUZZ(); return; } } - 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); - BUZZ(100, 659); - BUZZ(100, 698); + OKAY_BUZZ(); } #endif // HAS_M206_COMMAND diff --git a/Marlin/src/gcode/host/M114.cpp b/Marlin/src/gcode/host/M114.cpp index cdb9efb71b..41433b510d 100644 --- a/Marlin/src/gcode/host/M114.cpp +++ b/Marlin/src/gcode/host/M114.cpp @@ -47,7 +47,7 @@ void report_linear_axis_pos(const xyz_pos_t &pos, const uint8_t precision=3) { char str[12]; - LOOP_LINEAR_AXES(a) { + LOOP_NUM_AXES(a) { SERIAL_CHAR(' ', AXIS_CHAR(a), ':'); SERIAL_ECHO(dtostrf(pos[a], 1, precision, str)); } @@ -134,6 +134,15 @@ #if AXIS_IS_L64XX(K) REPORT_ABSOLUTE_POS(K); #endif + #if AXIS_IS_L64XX(U) + REPORT_ABSOLUTE_POS(U); + #endif + #if AXIS_IS_L64XX(V) + REPORT_ABSOLUTE_POS(V); + #endif + #if AXIS_IS_L64XX(W) + REPORT_ABSOLUTE_POS(W); + #endif #if AXIS_IS_L64XX(E0) REPORT_ABSOLUTE_POS(E0); #endif @@ -184,7 +193,10 @@ cartes.x, cartes.y, cartes.z, planner.get_axis_position_mm(I_AXIS), planner.get_axis_position_mm(J_AXIS), - planner.get_axis_position_mm(K_AXIS) + planner.get_axis_position_mm(K_AXIS), + planner.get_axis_position_mm(U_AXIS), + planner.get_axis_position_mm(V_AXIS), + planner.get_axis_position_mm(W_AXIS) ); report_all_axis_pos(from_steppers); diff --git a/Marlin/src/gcode/host/M115.cpp b/Marlin/src/gcode/host/M115.cpp index 36731c23da..ca8af796ef 100644 --- a/Marlin/src/gcode/host/M115.cpp +++ b/Marlin/src/gcode/host/M115.cpp @@ -65,8 +65,8 @@ void GcodeSuite::M115() { "PROTOCOL_VERSION:" PROTOCOL_VERSION " " "MACHINE_TYPE:" MACHINE_NAME " " "EXTRUDER_COUNT:" STRINGIFY(EXTRUDERS) " " - #if LINEAR_AXES != XYZ - "AXIS_COUNT:" STRINGIFY(LINEAR_AXES) " " + #if NUM_AXES != XYZ + "AXIS_COUNT:" STRINGIFY(NUM_AXES) " " #endif #ifdef MACHINE_UUID "UUID:" MACHINE_UUID @@ -111,7 +111,7 @@ void GcodeSuite::M115() { // AUTOLEVEL (G29) cap_line(F("AUTOLEVEL"), ENABLED(HAS_AUTOLEVEL)); - // RUNOUT (M412, M600) + // RUNOUT (M591, M600) cap_line(F("RUNOUT"), ENABLED(FILAMENT_RUNOUT_SENSOR)); // Z_PROBE (G30) diff --git a/Marlin/src/gcode/host/M16.cpp b/Marlin/src/gcode/host/M16.cpp index 03e734daaa..07b0c5ef57 100644 --- a/Marlin/src/gcode/host/M16.cpp +++ b/Marlin/src/gcode/host/M16.cpp @@ -26,6 +26,7 @@ #include "../gcode.h" #include "../../MarlinCore.h" +#include "../../lcd/marlinui.h" /** * M16: Expected Printer Check @@ -37,4 +38,4 @@ void GcodeSuite::M16() { } -#endif +#endif // EXPECTED_PRINTER_CHECK diff --git a/Marlin/src/gcode/host/M360.cpp b/Marlin/src/gcode/host/M360.cpp index 1feb57996a..b3a95a35aa 100644 --- a/Marlin/src/gcode/host/M360.cpp +++ b/Marlin/src/gcode/host/M360.cpp @@ -180,7 +180,7 @@ void GcodeSuite::M360() { // config_line(F("NumExtruder"), EXTRUDERS); #if HAS_EXTRUDERS - LOOP_L_N(e, EXTRUDERS) { + EXTRUDER_LOOP() { config_line_e(e, JERK_STR, TERN(HAS_LINEAR_E_JERK, planner.max_e_jerk[E_INDEX_N(e)], TERN(HAS_CLASSIC_JERK, planner.max_jerk.e, DEFAULT_EJERK))); config_line_e(e, F("MaxSpeed"), planner.settings.max_feedrate_mm_s[E_AXIS_N(e)]); config_line_e(e, F("Acceleration"), planner.settings.max_acceleration_mm_per_s2[E_AXIS_N(e)]); diff --git a/Marlin/src/gcode/lcd/M0_M1.cpp b/Marlin/src/gcode/lcd/M0_M1.cpp index a9223dda47..af03fcb0b1 100644 --- a/Marlin/src/gcode/lcd/M0_M1.cpp +++ b/Marlin/src/gcode/lcd/M0_M1.cpp @@ -35,7 +35,7 @@ #include "../../lcd/marlinui.h" #elif ENABLED(EXTENSIBLE_UI) #include "../../lcd/extui/ui_api.h" -#elif ENABLED(DWIN_CREALITY_LCD_ENHANCED) +#elif ENABLED(DWIN_LCD_PROUI) #include "../../lcd/e3v2/proui/dwin_popup.h" #include "../../lcd/e3v2/proui/dwin.h" #endif @@ -71,7 +71,7 @@ void GcodeSuite::M0_M1() { ExtUI::onUserConfirmRequired(parser.string_arg); // String in an SRAM buffer else ExtUI::onUserConfirmRequired(GET_TEXT_F(MSG_USERWAIT)); - #elif ENABLED(DWIN_CREALITY_LCD_ENHANCED) + #elif ENABLED(DWIN_LCD_PROUI) if (parser.string_arg) DWIN_Popup_Confirm(ICON_BLTouch, parser.string_arg, GET_TEXT_F(MSG_USERWAIT)); else diff --git a/Marlin/src/gcode/lcd/M117.cpp b/Marlin/src/gcode/lcd/M117.cpp index f26694bd64..86023e12e3 100644 --- a/Marlin/src/gcode/lcd/M117.cpp +++ b/Marlin/src/gcode/lcd/M117.cpp @@ -33,7 +33,7 @@ void GcodeSuite::M117() { if (parser.string_arg && parser.string_arg[0]) - ui.set_status(parser.string_arg); + ui.set_status(parser.string_arg, true); else ui.reset_status(); diff --git a/Marlin/src/gcode/lcd/M73.cpp b/Marlin/src/gcode/lcd/M73.cpp index c2c5485072..355445c573 100644 --- a/Marlin/src/gcode/lcd/M73.cpp +++ b/Marlin/src/gcode/lcd/M73.cpp @@ -28,7 +28,7 @@ #include "../../lcd/marlinui.h" #include "../../sd/cardreader.h" -#if ENABLED(DWIN_CREALITY_LCD_ENHANCED) +#if ENABLED(DWIN_LCD_PROUI) #include "../../lcd/e3v2/proui/dwin.h" #endif @@ -40,7 +40,7 @@ */ void GcodeSuite::M73() { - #if ENABLED(DWIN_CREALITY_LCD_ENHANCED) + #if ENABLED(DWIN_LCD_PROUI) DWIN_Progress_Update(); diff --git a/Marlin/src/gcode/motion/G0_G1.cpp b/Marlin/src/gcode/motion/G0_G1.cpp index 493fd00da1..d647894d27 100644 --- a/Marlin/src/gcode/motion/G0_G1.cpp +++ b/Marlin/src/gcode/motion/G0_G1.cpp @@ -49,13 +49,16 @@ void GcodeSuite::G0_G1(TERN_(HAS_FAST_MOVES, const bool fast_move/*=false*/)) { if (IsRunning() #if ENABLED(NO_MOTION_BEFORE_HOMING) && !homing_needed_error( - LINEAR_AXIS_GANG( + NUM_AXIS_GANG( (parser.seen_test('X') ? _BV(X_AXIS) : 0), | (parser.seen_test('Y') ? _BV(Y_AXIS) : 0), | (parser.seen_test('Z') ? _BV(Z_AXIS) : 0), | (parser.seen_test(AXIS4_NAME) ? _BV(I_AXIS) : 0), | (parser.seen_test(AXIS5_NAME) ? _BV(J_AXIS) : 0), - | (parser.seen_test(AXIS6_NAME) ? _BV(K_AXIS) : 0)) + | (parser.seen_test(AXIS6_NAME) ? _BV(K_AXIS) : 0), + | (parser.seen_test(AXIS7_NAME) ? _BV(U_AXIS) : 0), + | (parser.seen_test(AXIS8_NAME) ? _BV(V_AXIS) : 0), + | (parser.seen_test(AXIS9_NAME) ? _BV(W_AXIS) : 0)) ) #endif ) { @@ -89,7 +92,7 @@ void GcodeSuite::G0_G1(TERN_(HAS_FAST_MOVES, const bool fast_move/*=false*/)) { if (MIN_AUTORETRACT <= MAX_AUTORETRACT) { // When M209 Autoretract is enabled, convert E-only moves to firmware retract/recover moves if (fwretract.autoretract_enabled && parser.seen_test('E') - && !parser.seen(LINEAR_AXIS_GANG("X", "Y", "Z", STR_I, STR_J, STR_K)) + && !parser.seen(NUM_AXIS_GANG("X", "Y", "Z", STR_I, STR_J, STR_K, STR_U, STR_V, STR_W)) ) { const float echange = destination.e - current_position.e; // Is this a retract or recover move? diff --git a/Marlin/src/gcode/motion/G2_G3.cpp b/Marlin/src/gcode/motion/G2_G3.cpp index 0c7bdc7a3a..dd1c1d1470 100644 --- a/Marlin/src/gcode/motion/G2_G3.cpp +++ b/Marlin/src/gcode/motion/G2_G3.cpp @@ -48,8 +48,8 @@ #define MIN_ARC_SEGMENT_MM MAX_ARC_SEGMENT_MM #endif -#define ARC_LIJK_CODE(L,I,J,K) CODE_N(SUB2(LINEAR_AXES),L,I,J,K) -#define ARC_LIJKE_CODE(L,I,J,K,E) ARC_LIJK_CODE(L,I,J,K); CODE_ITEM_E(E) +#define ARC_LIJKUVW_CODE(L,I,J,K,U,V,W) CODE_N(SUB2(NUM_AXES),L,I,J,K,U,V,W) +#define ARC_LIJKUVWE_CODE(L,I,J,K,U,V,W,E) ARC_LIJKUVW_CODE(L,I,J,K,U,V,W); CODE_ITEM_E(E) /** * Plan an arc in 2 dimensions, with linear motion in the other axes. @@ -82,11 +82,14 @@ void plan_arc( rt_X = cart[axis_p] - center_P, rt_Y = cart[axis_q] - center_Q; - ARC_LIJK_CODE( + ARC_LIJKUVW_CODE( const float start_L = current_position[axis_l], const float start_I = current_position.i, const float start_J = current_position.j, - const float start_K = current_position.k + const float start_K = current_position.k, + const float start_U = current_position.u, + const float start_V = current_position.v, + const float start_W = current_position.w ); // Angle of rotation between position and target from the circle center. @@ -122,11 +125,14 @@ void plan_arc( min_segments = CEIL((MIN_CIRCLE_SEGMENTS) * portion_of_circle); // Minimum segments for the arc } - ARC_LIJKE_CODE( + ARC_LIJKUVWE_CODE( float travel_L = cart[axis_l] - start_L, float travel_I = cart.i - start_I, float travel_J = cart.j - start_J, float travel_K = cart.k - start_K, + float travel_U = cart.u - start_U, + float travel_V = cart.v - start_V, + float travel_W = cart.w - start_W, float travel_E = cart.e - current_position.e ); @@ -135,30 +141,39 @@ void plan_arc( const float total_angular = abs_angular_travel + circles * RADIANS(360), // Total rotation with all circles and remainder part_per_circle = RADIANS(360) / total_angular; // Each circle's part of the total - ARC_LIJKE_CODE( + ARC_LIJKUVWE_CODE( const float per_circle_L = travel_L * part_per_circle, // L movement per circle const float per_circle_I = travel_I * part_per_circle, const float per_circle_J = travel_J * part_per_circle, const float per_circle_K = travel_K * part_per_circle, + const float per_circle_U = travel_U * part_per_circle, + const float per_circle_V = travel_V * part_per_circle, + const float per_circle_W = travel_W * part_per_circle, const float per_circle_E = travel_E * part_per_circle // E movement per circle ); xyze_pos_t temp_position = current_position; for (uint16_t n = circles; n--;) { - ARC_LIJKE_CODE( // Destination Linear Axes + ARC_LIJKUVWE_CODE( // Destination Linear Axes temp_position[axis_l] += per_circle_L, temp_position.i += per_circle_I, temp_position.j += per_circle_J, temp_position.k += per_circle_K, + temp_position.u += per_circle_U, + temp_position.v += per_circle_V, + temp_position.w += per_circle_W, temp_position.e += per_circle_E // Destination E axis ); plan_arc(temp_position, offset, clockwise, 0); // Plan a single whole circle } - ARC_LIJKE_CODE( + ARC_LIJKUVWE_CODE( travel_L = cart[axis_l] - current_position[axis_l], travel_I = cart.i - current_position.i, travel_J = cart.j - current_position.j, travel_K = cart.k - current_position.k, + travel_U = cart.u - current_position.u, + travel_V = cart.v - current_position.v, + travel_W = cart.w - current_position.w, travel_E = cart.e - current_position.e ); } @@ -168,11 +183,14 @@ void plan_arc( // Return if the move is near zero if (flat_mm < 0.0001f - GANG_N(SUB2(LINEAR_AXES), + GANG_N(SUB2(NUM_AXES), && travel_L < 0.0001f, && travel_I < 0.0001f, && travel_J < 0.0001f, - && travel_K < 0.0001f + && travel_K < 0.0001f, + && travel_U < 0.0001f, + && travel_V < 0.0001f, + && travel_W < 0.0001f ) ) return; @@ -236,11 +254,14 @@ void plan_arc( cos_T = 1 - 0.5f * sq_theta_per_segment; // Small angle approximation #if DISABLED(AUTO_BED_LEVELING_UBL) - ARC_LIJK_CODE( + ARC_LIJKUVW_CODE( const float per_segment_L = proportion * travel_L / segments, const float per_segment_I = proportion * travel_I / segments, const float per_segment_J = proportion * travel_J / segments, - const float per_segment_K = proportion * travel_K / segments + const float per_segment_K = proportion * travel_K / segments, + const float per_segment_U = proportion * travel_U / segments, + const float per_segment_V = proportion * travel_V / segments, + const float per_segment_W = proportion * travel_W / segments ); #endif @@ -250,11 +271,14 @@ void plan_arc( if (tooshort) segments++; // Initialize all linear axes and E - ARC_LIJKE_CODE( + ARC_LIJKUVWE_CODE( raw[axis_l] = current_position[axis_l], raw.i = current_position.i, raw.j = current_position.j, raw.k = current_position.k, + raw.u = current_position.u, + raw.v = current_position.v, + raw.w = current_position.w, raw.e = current_position.e ); @@ -303,11 +327,15 @@ void plan_arc( // Update raw location raw[axis_p] = center_P + rvec.a; raw[axis_q] = center_Q + rvec.b; - ARC_LIJKE_CODE( + ARC_LIJKUVWE_CODE( #if ENABLED(AUTO_BED_LEVELING_UBL) - raw[axis_l] = start_L, raw.i = start_I, raw.j = start_J, raw.k = start_K + raw[axis_l] = start_L, + raw.i = start_I, raw.j = start_J, raw.k = start_K, + raw.u = start_U, raw.v = start_V, raw.w = start_V #else - raw[axis_l] += per_segment_L, raw.i += per_segment_I, raw.j += per_segment_J, raw.k += per_segment_K + raw[axis_l] += per_segment_L, + raw.i += per_segment_I, raw.j += per_segment_J, raw.k += per_segment_K, + raw.u += per_segment_U, raw.v += per_segment_V, raw.w += per_segment_W #endif , raw.e += extruder_per_segment ); @@ -325,7 +353,11 @@ void plan_arc( // Ensure last segment arrives at target location. raw = cart; #if ENABLED(AUTO_BED_LEVELING_UBL) - ARC_LIJK_CODE(raw[axis_l] = start_L, raw.i = start_I, raw.j = start_J, raw.k = start_K); + ARC_LIJKUVW_CODE( + raw[axis_l] = start_L, + raw.i = start_I, raw.j = start_J, raw.k = start_K, + raw.u = start_U, raw.v = start_V, raw.w = start_W + ); #endif apply_motion_limits(raw); @@ -337,7 +369,11 @@ void plan_arc( planner.buffer_line(raw, scaled_fr_mm_s, active_extruder, 0 OPTARG(SCARA_FEEDRATE_SCALING, inv_duration)); #if ENABLED(AUTO_BED_LEVELING_UBL) - ARC_LIJK_CODE(raw[axis_l] = start_L, raw.i = start_I, raw.j = start_J, raw.k = start_K); + ARC_LIJKUVW_CODE( + raw[axis_l] = start_L, + raw.i = start_I, raw.j = start_J, raw.k = start_K, + raw.u = start_U, raw.v = start_V, raw.w = start_W + ); #endif current_position = raw; @@ -380,7 +416,7 @@ void GcodeSuite::G2_G3(const bool clockwise) { relative_mode = true; #endif - get_destination_from_command(); // Get X Y [Z[I[J[K]]]] [E] F (and set cutter power) + get_destination_from_command(); // Get X Y [Z[I[J[K...]]]] [E] F (and set cutter power) TERN_(SF_ARC_FIX, relative_mode = relative_mode_backup); diff --git a/Marlin/src/gcode/motion/M290.cpp b/Marlin/src/gcode/motion/M290.cpp index f3d7b7c8dc..8185bf8f78 100644 --- a/Marlin/src/gcode/motion/M290.cpp +++ b/Marlin/src/gcode/motion/M290.cpp @@ -69,7 +69,7 @@ */ void GcodeSuite::M290() { #if ENABLED(BABYSTEP_XY) - LOOP_LINEAR_AXES(a) + LOOP_NUM_AXES(a) if (parser.seenval(AXIS_CHAR(a)) || (a == Z_AXIS && parser.seenval('S'))) { const float offs = constrain(parser.value_axis_units((AxisEnum)a), -2, 2); babystep.add_mm((AxisEnum)a, offs); @@ -87,7 +87,7 @@ void GcodeSuite::M290() { } #endif - if (!parser.seen(LINEAR_AXIS_GANG("X", "Y", "Z", STR_I, STR_J, STR_K)) || parser.seen('R')) { + if (!parser.seen(NUM_AXIS_GANG("X", "Y", "Z", STR_I, STR_J, STR_K, STR_U, STR_V, STR_W)) || parser.seen('R')) { SERIAL_ECHO_START(); #if ENABLED(BABYSTEP_ZPROBE_OFFSET) diff --git a/Marlin/src/gcode/parser.cpp b/Marlin/src/gcode/parser.cpp index 4d4fdae0d6..3fc1fc1625 100644 --- a/Marlin/src/gcode/parser.cpp +++ b/Marlin/src/gcode/parser.cpp @@ -248,7 +248,7 @@ void GCodeParser::parse(char *p) { case 'R': if (!WITHIN(motion_mode_codenum, 2, 3)) return; #endif - LOGICAL_AXIS_GANG(case 'E':, case 'X':, case 'Y':, case 'Z':, case AXIS4_NAME:, case AXIS5_NAME:, case AXIS6_NAME:) + LOGICAL_AXIS_GANG(case 'E':, case 'X':, case 'Y':, case 'Z':, case AXIS4_NAME:, case AXIS5_NAME:, case AXIS6_NAME:, case AXIS7_NAME:, case AXIS8_NAME:, case AXIS9_NAME:) case 'F': if (motion_mode_codenum < 0) return; command_letter = 'G'; diff --git a/Marlin/src/gcode/parser.h b/Marlin/src/gcode/parser.h index 1487c083ec..c91a0de5f2 100644 --- a/Marlin/src/gcode/parser.h +++ b/Marlin/src/gcode/parser.h @@ -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()); } diff --git a/Marlin/src/gcode/probe/G38.cpp b/Marlin/src/gcode/probe/G38.cpp index 6906805fca..ed24ce3258 100644 --- a/Marlin/src/gcode/probe/G38.cpp +++ b/Marlin/src/gcode/probe/G38.cpp @@ -49,7 +49,7 @@ inline bool G38_run_probe() { #if MULTIPLE_PROBING > 1 // Get direction of move and retract xyz_float_t retract_mm; - LOOP_LINEAR_AXES(i) { + LOOP_NUM_AXES(i) { const float dist = destination[i] - current_position[i]; retract_mm[i] = ABS(dist) < G38_MINIMUM_MOVE ? 0 : home_bump_mm((AxisEnum)i) * (dist > 0 ? -1 : 1); } @@ -119,7 +119,7 @@ void GcodeSuite::G38(const int8_t subcode) { ; // If any axis has enough movement, do the move - LOOP_LINEAR_AXES(i) + LOOP_NUM_AXES(i) if (ABS(destination[i] - current_position[i]) >= G38_MINIMUM_MOVE) { if (!parser.seenval('F')) feedrate_mm_s = homing_feedrate((AxisEnum)i); // If G38.2 fails throw an error diff --git a/Marlin/src/gcode/probe/M401_M402.cpp b/Marlin/src/gcode/probe/M401_M402.cpp index 7cbae76f4b..3389574919 100644 --- a/Marlin/src/gcode/probe/M401_M402.cpp +++ b/Marlin/src/gcode/probe/M401_M402.cpp @@ -36,12 +36,18 @@ * M401: Deploy and activate the Z probe * * With BLTOUCH_HS_MODE: + * H Report the current BLTouch HS mode state and exit * S Set High Speed (HS) Mode and exit without deploy */ void GcodeSuite::M401() { - if (parser.seen('S')) { + const bool seenH = parser.seen_test('H'), + seenS = parser.seen('S'); + if (seenH || seenS) { #ifdef BLTOUCH_HS_MODE - bltouch.high_speed_mode = parser.value_bool(); + if (seenS) bltouch.high_speed_mode = parser.value_bool(); + SERIAL_ECHO_START(); + SERIAL_ECHOPGM("BLTouch HS mode "); + serialprintln_onoff(bltouch.high_speed_mode); #endif } else { diff --git a/Marlin/src/gcode/probe/M423.cpp b/Marlin/src/gcode/probe/M423.cpp new file mode 100644 index 0000000000..fde5aaaf87 --- /dev/null +++ b/Marlin/src/gcode/probe/M423.cpp @@ -0,0 +1,99 @@ +/** + * 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 . + * + */ + +/** + * M423.cpp - X-Axis Twist Compensation + */ + +#include "../../inc/MarlinConfig.h" + +#if ENABLED(X_AXIS_TWIST_COMPENSATION) + +#include "../gcode.h" +#include "../../feature/x_twist.h" +#include "../../module/probe.h" + +/** + * M423: Set a Z offset for X-Twist (added to the mesh on future G29). + * M423 [R] [A] [I] [X Z] + * + * R - Reset the twist compensation data + * A - Set the X twist starting X position + * E - Set the X twist ending X position + * I - Set the X twist X-spacing directly + * X - Index of a Z value in the list + * Z - A Z value to set + */ +void GcodeSuite::M423() { + + bool do_report = true; + float new_spacing = 0; + + if (parser.seen_test('R')) { + do_report = false; + xatc.reset(); + } + if (parser.seenval('A')) { + do_report = false; + xatc.start = parser.value_float(); + new_spacing = (probe.max_x() - xatc.start) / (XATC_MAX_POINTS - 1); + } + if (parser.seenval('E')) { + do_report = false; + new_spacing = (parser.value_float() - xatc.start) / (XATC_MAX_POINTS - 1); + } + else if (parser.seenval('I')) { + do_report = false; + new_spacing = parser.value_float(); + } + + if (new_spacing) xatc.spacing = new_spacing; + + if (parser.seenval('X')) { + do_report = false; + const int8_t x = parser.value_int(); + if (!WITHIN(x, 0, XATC_MAX_POINTS - 1)) + SERIAL_ECHOLNPGM("?(X) out of range (0..", XATC_MAX_POINTS - 1, ")."); + else { + if (parser.seenval('Z')) + xatc.z_offset[x] = parser.value_linear_units(); + else + SERIAL_ECHOLNPGM("?(Z) required."); + } + } + + if (do_report) M423_report(); + +} + +void GcodeSuite::M423_report(const bool forReplay/*=true*/) { + report_heading(forReplay, F("X-Twist Correction")); + SERIAL_ECHOLNPGM(" M423 A", xatc.start, " I", xatc.spacing); + LOOP_L_N(x, XATC_MAX_POINTS) { + const float z = xatc.z_offset[x]; + SERIAL_ECHOPGM(" M423 X", x, " Z"); + serial_offset(isnan(z) ? 0 : z); + SERIAL_EOL(); + } +} + +#endif // X_AXIS_TWIST_COMPENSATION diff --git a/Marlin/src/gcode/sd/M1001.cpp b/Marlin/src/gcode/sd/M1001.cpp index 1579efd555..197177882c 100644 --- a/Marlin/src/gcode/sd/M1001.cpp +++ b/Marlin/src/gcode/sd/M1001.cpp @@ -49,7 +49,7 @@ #if ENABLED(EXTENSIBLE_UI) #include "../../lcd/extui/ui_api.h" -#elif ENABLED(DWIN_CREALITY_LCD_ENHANCED) +#elif ENABLED(DWIN_LCD_PROUI) #include "../../lcd/e3v2/proui/dwin.h" #endif @@ -108,8 +108,8 @@ void GcodeSuite::M1001() { process_subcommands_now(F(SD_FINISHED_RELEASECOMMAND)); #endif - TERN_(EXTENSIBLE_UI, ExtUI::onPrintFinished()); - TERN_(DWIN_CREALITY_LCD_ENHANCED, DWIN_Print_Finished()); + TERN_(EXTENSIBLE_UI, ExtUI::onPrintDone()); + TERN_(DWIN_LCD_PROUI, DWIN_Print_Finished()); // Re-select the last printed file in the UI TERN_(SD_REPRINT_LAST_SELECTED_FILE, ui.reselect_last_file()); diff --git a/Marlin/src/gcode/sd/M524.cpp b/Marlin/src/gcode/sd/M524.cpp index e715915565..001a1e1842 100644 --- a/Marlin/src/gcode/sd/M524.cpp +++ b/Marlin/src/gcode/sd/M524.cpp @@ -27,15 +27,27 @@ #include "../gcode.h" #include "../../sd/cardreader.h" +#if ENABLED(DWIN_LCD_PROUI) + #include "../../lcd/e3v2/proui/dwin.h" +#endif + /** * M524: Abort the current SD print job (started with M24) */ void GcodeSuite::M524() { - if (IS_SD_PRINTING()) - card.abortFilePrintSoon(); - else if (card.isMounted()) - card.closefile(); + #if ENABLED(DWIN_LCD_PROUI) + + HMI_flag.abort_flag = true; // The LCD will handle it + + #else + + if (IS_SD_PRINTING()) + card.abortFilePrintSoon(); + else if (card.isMounted()) + card.closefile(); + + #endif } diff --git a/Marlin/src/gcode/stats/M75-M78.cpp b/Marlin/src/gcode/stats/M75-M78.cpp index 368edb65d9..0ed1e66930 100644 --- a/Marlin/src/gcode/stats/M75-M78.cpp +++ b/Marlin/src/gcode/stats/M75-M78.cpp @@ -29,7 +29,7 @@ #include "../../MarlinCore.h" // for startOrResumeJob -#if ENABLED(DWIN_CREALITY_LCD_ENHANCED) +#if ENABLED(DWIN_LCD_PROUI) #include "../../lcd/e3v2/proui/dwin.h" #endif @@ -38,9 +38,9 @@ */ void GcodeSuite::M75() { startOrResumeJob(); - #if ENABLED(DWIN_CREALITY_LCD_ENHANCED) - DWIN_Print_Header(parser.string_arg && parser.string_arg[0] ? parser.string_arg : GET_TEXT(MSG_HOST_START_PRINT)); + #if ENABLED(DWIN_LCD_PROUI) DWIN_Print_Started(false); + if (!IS_SD_PRINTING()) DWIN_Print_Header(parser.string_arg && parser.string_arg[0] ? parser.string_arg : GET_TEXT(MSG_HOST_START_PRINT)); #endif } @@ -50,6 +50,7 @@ void GcodeSuite::M75() { void GcodeSuite::M76() { print_job_timer.pause(); TERN_(HOST_PAUSE_M76, hostui.pause()); + TERN_(DWIN_LCD_PROUI, DWIN_Print_Pause()); } /** @@ -57,7 +58,7 @@ void GcodeSuite::M76() { */ void GcodeSuite::M77() { print_job_timer.stop(); - TERN_(DWIN_CREALITY_LCD_ENHANCED, DWIN_Print_Finished()); + TERN_(DWIN_LCD_PROUI, DWIN_Print_Finished()); } #if ENABLED(PRINTCOUNTER) diff --git a/Marlin/src/gcode/temp/M104_M109.cpp b/Marlin/src/gcode/temp/M104_M109.cpp index baaac02100..331ceeb61d 100644 --- a/Marlin/src/gcode/temp/M104_M109.cpp +++ b/Marlin/src/gcode/temp/M104_M109.cpp @@ -126,7 +126,7 @@ void GcodeSuite::M104_M109(const bool isM109) { #endif if (thermalManager.isHeatingHotend(target_extruder) || !no_wait_for_cooling) - thermalManager.set_heating_message(target_extruder); + thermalManager.set_heating_message(target_extruder, !isM109 && got_temp); } TERN_(AUTOTEMP, planner.autotemp_M104_M109()); diff --git a/Marlin/src/gcode/temp/M140_M190.cpp b/Marlin/src/gcode/temp/M140_M190.cpp index 7532defccd..c5e3c00029 100644 --- a/Marlin/src/gcode/temp/M140_M190.cpp +++ b/Marlin/src/gcode/temp/M140_M190.cpp @@ -82,14 +82,18 @@ void GcodeSuite::M140_M190(const bool isM190) { if (!got_temp) return; thermalManager.setTargetBed(temp); + thermalManager.isHeatingBed() ? LCD_MESSAGE(MSG_BED_HEATING) : LCD_MESSAGE(MSG_BED_COOLING); - ui.set_status(thermalManager.isHeatingBed() ? GET_TEXT_F(MSG_BED_HEATING) : GET_TEXT_F(MSG_BED_COOLING)); - - // with PRINTJOB_TIMER_AUTOSTART, M190 can start the timer, and M140 can stop it + // With PRINTJOB_TIMER_AUTOSTART, M190 can start the timer, and M140 can stop it TERN_(PRINTJOB_TIMER_AUTOSTART, thermalManager.auto_job_check_timer(isM190, !isM190)); if (isM190) thermalManager.wait_for_bed(no_wait_for_cooling); + else + ui.set_status_reset_fn([]{ + const celsius_t c = thermalManager.degTargetBed(); + return c < 30 || thermalManager.degBedNear(c); + }); } #endif // HAS_HEATED_BED diff --git a/Marlin/src/gcode/temp/M192.cpp b/Marlin/src/gcode/temp/M192.cpp index a96e2d34a4..04b36a548c 100644 --- a/Marlin/src/gcode/temp/M192.cpp +++ b/Marlin/src/gcode/temp/M192.cpp @@ -49,7 +49,7 @@ void GcodeSuite::M192() { } const celsius_t target_temp = parser.value_celsius(); - ui.set_status(thermalManager.isProbeBelowTemp(target_temp) ? GET_TEXT_F(MSG_PROBE_HEATING) : GET_TEXT_F(MSG_PROBE_COOLING)); + thermalManager.isProbeBelowTemp(target_temp) ? LCD_MESSAGE(MSG_PROBE_HEATING) : LCD_MESSAGE(MSG_PROBE_COOLING); thermalManager.wait_for_probe(target_temp, no_wait_for_cooling); } diff --git a/Marlin/src/gcode/temp/M303.cpp b/Marlin/src/gcode/temp/M303.cpp index 7b56eb2d6b..c1e400511c 100644 --- a/Marlin/src/gcode/temp/M303.cpp +++ b/Marlin/src/gcode/temp/M303.cpp @@ -30,7 +30,7 @@ #if ENABLED(EXTENSIBLE_UI) #include "../../lcd/extui/ui_api.h" -#elif ENABLED(DWIN_CREALITY_LCD_ENHANCED) +#elif ENABLED(DWIN_LCD_PROUI) #include "../../lcd/e3v2/proui/dwin.h" #endif @@ -73,7 +73,7 @@ void GcodeSuite::M303() { default: SERIAL_ECHOLNPGM(STR_PID_BAD_HEATER_ID); TERN_(EXTENSIBLE_UI, ExtUI::onPidTuning(ExtUI::result_t::PID_BAD_EXTRUDER_NUM)); - TERN_(DWIN_CREALITY_LCD_ENHANCED, DWIN_PidTuning(PID_BAD_EXTRUDER_NUM)); + TERN_(DWIN_LCD_PROUI, DWIN_PidTuning(PID_BAD_EXTRUDER_NUM)); return; } @@ -83,7 +83,7 @@ void GcodeSuite::M303() { const celsius_t temp = seenS ? parser.value_celsius() : default_temp; const bool u = parser.boolval('U'); - #if ENABLED(DWIN_CREALITY_LCD_ENHANCED) + #if ENABLED(DWIN_LCD_PROUI) if (seenC) HMI_data.PidCycles = c; if (seenS) { if (hid == H_BED) HMI_data.BedPidT = temp; else HMI_data.HotendPidT = temp; } #endif diff --git a/Marlin/src/gcode/temp/M306.cpp b/Marlin/src/gcode/temp/M306.cpp new file mode 100644 index 0000000000..9e1a8dd8ef --- /dev/null +++ b/Marlin/src/gcode/temp/M306.cpp @@ -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 . + * + */ + +#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 Ambient heat transfer coefficient (no fan). + * C Block heat capacity. + * E Extruder number to set. (Default: E0) + * F Ambient heat transfer coefficient (fan on full). + * P Heater power. + * R 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 diff --git a/Marlin/src/inc/Conditionals_LCD.h b/Marlin/src/inc/Conditionals_LCD.h index 34a160fc5c..329e585023 100644 --- a/Marlin/src/inc/Conditionals_LCD.h +++ b/Marlin/src/inc/Conditionals_LCD.h @@ -473,12 +473,15 @@ #endif // Aliases for LCD features -#if EITHER(DWIN_CREALITY_LCD, DWIN_CREALITY_LCD_ENHANCED) +#if EITHER(DWIN_CREALITY_LCD, DWIN_LCD_PROUI) #define HAS_DWIN_E3V2_BASIC 1 #endif #if EITHER(HAS_DWIN_E3V2_BASIC, DWIN_CREALITY_LCD_JYERSUI) #define HAS_DWIN_E3V2 1 #endif +#if ENABLED(DWIN_LCD_PROUI) + #define DO_LIST_BIN_FILES 1 +#endif // E3V2 extras #if HAS_DWIN_E3V2 || IS_DWIN_MARLINUI @@ -494,7 +497,7 @@ #endif #define HAS_LCD_BRIGHTNESS 1 #define LCD_BRIGHTNESS_MAX 250 - #if ENABLED(DWIN_CREALITY_LCD_ENHANCED) + #if ENABLED(DWIN_LCD_PROUI) #define LCD_BRIGHTNESS_DEFAULT 127 #endif #endif @@ -513,7 +516,7 @@ #endif #endif -#if ANY(HAS_WIRED_LCD, EXTENSIBLE_UI, DWIN_CREALITY_LCD_JYERSUI) +#if ANY(HAS_WIRED_LCD, EXTENSIBLE_UI, DWIN_LCD_PROUI, DWIN_CREALITY_LCD_JYERSUI) #define HAS_DISPLAY 1 #endif @@ -674,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 @@ -697,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 /** @@ -722,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 @@ -746,6 +802,7 @@ #endif // Helper macros for extruder and hotend arrays +#define EXTRUDER_LOOP() for (int8_t e = 0; e < EXTRUDERS; e++) #define HOTEND_LOOP() for (int8_t e = 0; e < HOTENDS; e++) #define ARRAY_BY_EXTRUDERS(V...) ARRAY_N(EXTRUDERS, V) #define ARRAY_BY_EXTRUDERS1(v1) ARRAY_N_1(EXTRUDERS, v1) @@ -830,10 +887,14 @@ * Fill in undefined Filament Sensor options */ #if ENABLED(FILAMENT_RUNOUT_SENSOR) + #define HAS_FILAMENT_SENSOR 1 + #ifndef NUM_RUNOUT_SENSORS + #define NUM_RUNOUT_SENSORS E_STEPPERS + #endif + #if ENABLED(MIXING_EXTRUDER) + #define WATCH_ALL_RUNOUT_SENSORS + #endif #if NUM_RUNOUT_SENSORS >= 1 - #ifndef FIL_RUNOUT1_STATE - #define FIL_RUNOUT1_STATE FIL_RUNOUT_STATE - #endif #ifndef FIL_RUNOUT1_PULLUP #define FIL_RUNOUT1_PULLUP FIL_RUNOUT_PULLUP #endif @@ -842,9 +903,7 @@ #endif #endif #if NUM_RUNOUT_SENSORS >= 2 - #ifndef FIL_RUNOUT2_STATE - #define FIL_RUNOUT2_STATE FIL_RUNOUT_STATE - #endif + #define MULTI_FILAMENT_SENSOR 1 #ifndef FIL_RUNOUT2_PULLUP #define FIL_RUNOUT2_PULLUP FIL_RUNOUT_PULLUP #endif @@ -853,9 +912,6 @@ #endif #endif #if NUM_RUNOUT_SENSORS >= 3 - #ifndef FIL_RUNOUT3_STATE - #define FIL_RUNOUT3_STATE FIL_RUNOUT_STATE - #endif #ifndef FIL_RUNOUT3_PULLUP #define FIL_RUNOUT3_PULLUP FIL_RUNOUT_PULLUP #endif @@ -864,9 +920,6 @@ #endif #endif #if NUM_RUNOUT_SENSORS >= 4 - #ifndef FIL_RUNOUT4_STATE - #define FIL_RUNOUT4_STATE FIL_RUNOUT_STATE - #endif #ifndef FIL_RUNOUT4_PULLUP #define FIL_RUNOUT4_PULLUP FIL_RUNOUT_PULLUP #endif @@ -875,9 +928,6 @@ #endif #endif #if NUM_RUNOUT_SENSORS >= 5 - #ifndef FIL_RUNOUT5_STATE - #define FIL_RUNOUT5_STATE FIL_RUNOUT_STATE - #endif #ifndef FIL_RUNOUT5_PULLUP #define FIL_RUNOUT5_PULLUP FIL_RUNOUT_PULLUP #endif @@ -886,9 +936,6 @@ #endif #endif #if NUM_RUNOUT_SENSORS >= 6 - #ifndef FIL_RUNOUT6_STATE - #define FIL_RUNOUT6_STATE FIL_RUNOUT_STATE - #endif #ifndef FIL_RUNOUT6_PULLUP #define FIL_RUNOUT6_PULLUP FIL_RUNOUT_PULLUP #endif @@ -897,9 +944,6 @@ #endif #endif #if NUM_RUNOUT_SENSORS >= 7 - #ifndef FIL_RUNOUT7_STATE - #define FIL_RUNOUT7_STATE FIL_RUNOUT_STATE - #endif #ifndef FIL_RUNOUT7_PULLUP #define FIL_RUNOUT7_PULLUP FIL_RUNOUT_PULLUP #endif @@ -908,9 +952,6 @@ #endif #endif #if NUM_RUNOUT_SENSORS >= 8 - #ifndef FIL_RUNOUT8_STATE - #define FIL_RUNOUT8_STATE FIL_RUNOUT_STATE - #endif #ifndef FIL_RUNOUT8_PULLUP #define FIL_RUNOUT8_PULLUP FIL_RUNOUT_PULLUP #endif @@ -951,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 @@ -1224,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 @@ -1424,3 +1489,28 @@ #if defined(NEOPIXEL_BKGD_INDEX_FIRST) && !defined(NEOPIXEL_BKGD_INDEX_LAST) #define NEOPIXEL_BKGD_INDEX_LAST NEOPIXEL_BKGD_INDEX_FIRST #endif + +/*** TEMPORARY COMPATIBILITY ***/ + +#if HAS_FILAMENT_SENSOR + #ifndef FIL_RUNOUT_ENABLED + #if FIL_RUNOUT_ENABLED_DEFAULT + #define FIL_RUNOUT_ENABLED ARRAY_N_1(NUM_RUNOUT_SENSORS, true) + #else + #define FIL_RUNOUT_ENABLED ARRAY_N_1(NUM_RUNOUT_SENSORS, false) + #endif + #endif + #ifndef FIL_RUNOUT_MODE + #if FIL_RUNOUT_STATE + #define FIL_RUNOUT_MODE ARRAY_N_1(NUM_RUNOUT_SENSORS, 1) + #else + #define FIL_RUNOUT_MODE ARRAY_N_1(NUM_RUNOUT_SENSORS, 2) + #endif + #endif + #ifndef FIL_RUNOUT_DISTANCE_MM + #define FIL_RUNOUT_DISTANCE_MM ARRAY_N_1(NUM_RUNOUT_SENSORS, 10) + #endif + #undef FIL_RUNOUT_ENABLED_DEFAULT + #undef FIL_RUNOUT_STATE + #undef FILAMENT_RUNOUT_DISTANCE_MM +#endif diff --git a/Marlin/src/inc/Conditionals_adv.h b/Marlin/src/inc/Conditionals_adv.h index d63395a719..71e74404da 100644 --- a/Marlin/src/inc/Conditionals_adv.h +++ b/Marlin/src/inc/Conditionals_adv.h @@ -95,11 +95,12 @@ #undef PID_EXTRUSION_SCALING #undef LIN_ADVANCE #undef FILAMENT_RUNOUT_SENSOR + #undef FIL_RUNOUT_ENABLED + #undef FIL_RUNOUT_MODE + #undef FIL_RUNOUT_DISTANCE_MM #undef ADVANCED_PAUSE_FEATURE - #undef FILAMENT_RUNOUT_DISTANCE_MM #undef FILAMENT_LOAD_UNLOAD_GCODES #undef DISABLE_INACTIVE_EXTRUDER - #undef FILAMENT_LOAD_UNLOAD_GCODES #undef EXTRUDER_RUNOUT_PREVENT #undef PREVENT_COLD_EXTRUSION #undef PREVENT_LENGTHY_EXTRUDE @@ -543,19 +544,6 @@ #define HAS_SERVICE_INTERVALS 1 #endif -#if ENABLED(FILAMENT_RUNOUT_SENSOR) - #define HAS_FILAMENT_SENSOR 1 - #if NUM_RUNOUT_SENSORS > 1 - #define MULTI_FILAMENT_SENSOR 1 - #endif - #ifdef FILAMENT_RUNOUT_DISTANCE_MM - #define HAS_FILAMENT_RUNOUT_DISTANCE 1 - #endif - #if ENABLED(MIXING_EXTRUDER) - #define WATCH_ALL_RUNOUT_SENSORS - #endif -#endif - // Probe Temperature Compensation #if !TEMP_SENSOR_PROBE #undef PTC_PROBE @@ -587,6 +575,10 @@ #define HAS_PRINT_PROGRESS 1 #endif +#if STATUS_MESSAGE_TIMEOUT_SEC > 0 + #define HAS_STATUS_MESSAGE_TIMEOUT 1 +#endif + #if ENABLED(SDSUPPORT) && SD_PROCEDURE_DEPTH #define HAS_MEDIA_SUBCALLS 1 #endif @@ -910,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 diff --git a/Marlin/src/inc/Conditionals_post.h b/Marlin/src/inc/Conditionals_post.h index fa273cd32e..ada2a512b5 100644 --- a/Marlin/src/inc/Conditionals_post.h +++ b/Marlin/src/inc/Conditionals_post.h @@ -87,6 +87,19 @@ #if HAS_K_AXIS && !defined(AXIS6_NAME) #define AXIS6_NAME 'C' #endif +#if HAS_U_AXIS && !defined(AXIS7_NAME) + #define AXIS7_NAME 'U' +#endif +#if HAS_V_AXIS && !defined(AXIS8_NAME) + #define AXIS8_NAME 'V' +#endif +#if HAS_W_AXIS && !defined(AXIS9_NAME) + #define AXIS9_NAME 'W' +#endif + +#if ANY(AXIS4_ROTATES, AXIS5_ROTATES, AXIS6_ROTATES, AXIS7_ROTATES, AXIS8_ROTATES, AXIS9_ROTATES) + #define HAS_ROTATIONAL_AXES 1 +#endif #define X_MAX_LENGTH (X_MAX_POS - (X_MIN_POS)) #if HAS_Y_AXIS @@ -106,6 +119,15 @@ #if HAS_K_AXIS #define K_MAX_LENGTH (K_MAX_POS - (K_MIN_POS)) #endif +#if HAS_U_AXIS + #define U_MAX_LENGTH (U_MAX_POS - (U_MIN_POS)) +#endif +#if HAS_V_AXIS + #define V_MAX_LENGTH (V_MAX_POS - (V_MIN_POS)) +#endif +#if HAS_W_AXIS + #define W_MAX_LENGTH (W_MAX_POS - (W_MIN_POS)) +#endif // Defined only if the sanity-check is bypassed #ifndef X_BED_SIZE @@ -123,6 +145,15 @@ #if HAS_K_AXIS && !defined(K_BED_SIZE) #define K_BED_SIZE K_MAX_LENGTH #endif +#if HAS_U_AXIS && !defined(U_BED_SIZE) + #define U_BED_SIZE U_MAX_LENGTH +#endif +#if HAS_V_AXIS && !defined(V_BED_SIZE) + #define V_BED_SIZE V_MAX_LENGTH +#endif +#if HAS_W_AXIS && !defined(W_BED_SIZE) + #define W_BED_SIZE W_MAX_LENGTH +#endif // Require 0,0 bed center for Delta and SCARA #if IS_KINEMATIC @@ -143,6 +174,15 @@ #if HAS_K_AXIS #define _K_HALF_KMAX ((K_BED_SIZE) / 2) #endif +#if HAS_U_AXIS + #define _U_HALF_UMAX ((U_BED_SIZE) / 2) +#endif +#if HAS_V_AXIS + #define _V_HALF_VMAX ((V_BED_SIZE) / 2) +#endif +#if HAS_W_AXIS + #define _W_HALF_WMAX ((W_BED_SIZE) / 2) +#endif #define X_CENTER TERN(BED_CENTER_AT_0_0, 0, _X_HALF_BED) #if HAS_Y_AXIS @@ -158,6 +198,15 @@ #if HAS_K_AXIS #define K_CENTER TERN(BED_CENTER_AT_0_0, 0, _K_HALF_BED) #endif +#if HAS_U_AXIS + #define U_CENTER TERN(BED_CENTER_AT_0_0, 0, _U_HALF_BED) +#endif +#if HAS_V_AXIS + #define V_CENTER TERN(BED_CENTER_AT_0_0, 0, _V_HALF_BED) +#endif +#if HAS_W_AXIS + #define W_CENTER TERN(BED_CENTER_AT_0_0, 0, _W_HALF_BED) +#endif // Get the linear boundaries of the bed #define X_MIN_BED (X_CENTER - _X_HALF_BED) @@ -178,6 +227,18 @@ #define K_MINIM (K_CENTER - _K_HALF_BED_SIZE) #define K_MAXIM (K_MINIM + K_BED_SIZE) #endif +#if HAS_U_AXIS + #define U_MINIM (U_CENTER - _U_HALF_BED_SIZE) + #define U_MAXIM (U_MINIM + U_BED_SIZE) +#endif +#if HAS_V_AXIS + #define V_MINIM (V_CENTER - _V_HALF_BED_SIZE) + #define V_MAXIM (V_MINIM + V_BED_SIZE) +#endif +#if HAS_W_AXIS + #define W_MINIM (W_CENTER - _W_HALF_BED_SIZE) + #define W_MAXIM (W_MINIM + W_BED_SIZE) +#endif /** * Dual X Carriage @@ -274,6 +335,27 @@ #define K_HOME_POS TERN(K_HOME_TO_MIN, K_MIN_POS, K_MAX_POS) #endif #endif +#if HAS_U_AXIS + #ifdef MANUAL_U_HOME_POS + #define U_HOME_POS MANUAL_U_HOME_POS + #else + #define U_HOME_POS (U_HOME_DIR < 0 ? U_MIN_POS : U_MAX_POS) + #endif +#endif +#if HAS_V_AXIS + #ifdef MANUAL_V_HOME_POS + #define V_HOME_POS MANUAL_V_HOME_POS + #else + #define V_HOME_POS (V_HOME_DIR < 0 ? V_MIN_POS : V_MAX_POS) + #endif +#endif +#if HAS_W_AXIS + #ifdef MANUAL_W_HOME_POS + #define W_HOME_POS MANUAL_W_HOME_POS + #else + #define W_HOME_POS (W_HOME_DIR < 0 ? W_MIN_POS : W_MAX_POS) + #endif +#endif /** * If DELTA_HEIGHT isn't defined use the old setting @@ -459,7 +541,7 @@ #endif -#if PIN_EXISTS(SD_DETECT) && NONE(HAS_GRAPHICAL_TFT, LCD_USE_DMA_FSMC, HAS_FSMC_GRAPHICAL_TFT, HAS_SPI_GRAPHICAL_TFT, IS_DWIN_MARLINUI, EXTENSIBLE_UI) +#if PIN_EXISTS(SD_DETECT) && NONE(HAS_GRAPHICAL_TFT, LCD_USE_DMA_FSMC, HAS_FSMC_GRAPHICAL_TFT, HAS_SPI_GRAPHICAL_TFT, IS_DWIN_MARLINUI, EXTENSIBLE_UI, HAS_DWIN_E3V2) #define REINIT_NOISY_LCD 1 // Have the LCD re-init on SD insertion #endif @@ -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 @@ -2824,17 +3075,9 @@ #endif // User Interface -#if ENABLED(FREEZE_FEATURE) - #if !PIN_EXISTS(FREEZE) && PIN_EXISTS(KILL) - #define FREEZE_PIN KILL_PIN - #endif - #if PIN_EXISTS(FREEZE) - #define HAS_FREEZE_PIN 1 - #endif -#else - #undef FREEZE_PIN -#endif -#if PIN_EXISTS(KILL) && TERN1(FREEZE_FEATURE, KILL_PIN != FREEZE_PIN) +#if ENABLED(FREEZE_FEATURE) && !PIN_EXISTS(FREEZE) && PIN_EXISTS(KILL) + #define FREEZE_PIN KILL_PIN +#elif PIN_EXISTS(KILL) && TERN1(FREEZE_FEATURE, KILL_PIN != FREEZE_PIN) #define HAS_KILL 1 #endif #if PIN_EXISTS(HOME) @@ -2857,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 @@ -2867,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 @@ -3177,7 +3420,7 @@ * Advanced Pause - Filament Change */ #if ENABLED(ADVANCED_PAUSE_FEATURE) - #if ANY(HAS_MARLINUI_MENU, EXTENSIBLE_UI, DWIN_CREALITY_LCD_ENHANCED, DWIN_CREALITY_LCD_JYERSUI) || BOTH(EMERGENCY_PARSER, HOST_PROMPT_SUPPORT) + #if ANY(HAS_MARLINUI_MENU, EXTENSIBLE_UI, DWIN_LCD_PROUI, DWIN_CREALITY_LCD_JYERSUI) || BOTH(EMERGENCY_PARSER, HOST_PROMPT_SUPPORT) #define M600_PURGE_MORE_RESUMABLE 1 #endif #ifndef FILAMENT_CHANGE_SLOW_LOAD_LENGTH @@ -3507,3 +3750,14 @@ #if PIN_EXISTS(SAFE_POWER) && DISABLED(DISABLE_DRIVER_SAFE_POWER_PROTECT) #define HAS_DRIVER_SAFE_POWER_PROTECT 1 #endif + +#if ANY(ENDSTOPPULLDOWNS, ENDSTOPPULLDOWN_ZMIN_PROBE, \ + ENDSTOPPULLDOWN_XMIN, ENDSTOPPULLDOWN_YMIN, ENDSTOPPULLDOWN_ZMIN, \ + ENDSTOPPULLDOWN_IMIN, ENDSTOPPULLDOWN_JMIN, ENDSTOPPULLDOWN_KMIN, \ + ENDSTOPPULLDOWN_XMAX, ENDSTOPPULLDOWN_YMAX, ENDSTOPPULLDOWN_ZMAX, \ + ENDSTOPPULLDOWN_IMAX, ENDSTOPPULLDOWN_JMAX, ENDSTOPPULLDOWN_KMAX, \ + POWER_LOSS_PULLDOWN, CALIBRATION_PIN_PULLDOWN, FIL_RUNOUT_PULLDOWN, \ + FIL_RUNOUT1_PULLDOWN, FIL_RUNOUT2_PULLDOWN, FIL_RUNOUT3_PULLDOWN, FIL_RUNOUT4_PULLDOWN, \ + FIL_RUNOUT5_PULLDOWN, FIL_RUNOUT6_PULLDOWN, FIL_RUNOUT7_PULLDOWN, FIL_RUNOUT8_PULLDOWN) + #define USING_PULLDOWNS 1 +#endif diff --git a/Marlin/src/inc/SanityCheck.h b/Marlin/src/inc/SanityCheck.h index e8abf1b286..3b1a3363e4 100644 --- a/Marlin/src/inc/SanityCheck.h +++ b/Marlin/src/inc/SanityCheck.h @@ -35,8 +35,8 @@ #endif // Strings for sanity check messages -#define _LINEAR_AXES_STR LINEAR_AXIS_GANG("X ", "Y ", "Z ", "I ", "J ", "K ") -#define _LOGICAL_AXES_STR LOGICAL_AXIS_GANG("E ", "X ", "Y ", "Z ", "I ", "J ", "K ") +#define _NUM_AXES_STR NUM_AXIS_GANG("X ", "Y ", "Z ", "I ", "J ", "K ", "U ", "V ", "W ") +#define _LOGICAL_AXES_STR LOGICAL_AXIS_GANG("E ", "X ", "Y ", "Z ", "I ", "J ", "K ", "U ", "V ", "W ") // Make sure macros aren't borked #define TEST1 @@ -561,9 +561,9 @@ #error "SHORT_MANUAL_Z_MOVE is now FINE_MANUAL_MOVE, applying to Z on most printers." #elif defined(FIL_RUNOUT_INVERTING) #if FIL_RUNOUT_INVERTING - #error "FIL_RUNOUT_INVERTING true is now FIL_RUNOUT_STATE HIGH." + #error "FIL_RUNOUT_INVERTING true is now FIL_RUNOUT_MODE {HIGH}." #else - #error "FIL_RUNOUT_INVERTING false is now FIL_RUNOUT_STATE LOW." + #error "FIL_RUNOUT_INVERTING false is now FIL_RUNOUT_MODE {LOW}." #endif #elif defined(ASSISTED_TRAMMING_MENU_ITEM) #error "ASSISTED_TRAMMING_MENU_ITEM is deprecated and should be removed." @@ -615,6 +615,10 @@ #error "NOZZLE_PARK_X_ONLY is now NOZZLE_PARK_MOVE 2." #elif defined(Z_STEPPER_ALIGN_KNOWN_STEPPER_POSITIONS) #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; @@ -780,15 +784,6 @@ static_assert(Y_MAX_LENGTH >= Y_BED_SIZE, "Movement bounds (Y_MIN_POS, Y_MAX_POS #endif #endif -#if !defined(TARGET_LPC1768) && ANY( \ - ENDSTOPPULLDOWNS, \ - ENDSTOPPULLDOWN_XMAX, ENDSTOPPULLDOWN_YMAX, \ - ENDSTOPPULLDOWN_ZMAX, ENDSTOPPULLDOWN_XMIN, \ - ENDSTOPPULLDOWN_YMIN, ENDSTOPPULLDOWN_ZMIN \ - ) - #error "PULLDOWN pin mode is not available on the selected board." -#endif - #if BOTH(ENDSTOPPULLUPS, ENDSTOPPULLDOWNS) #error "Enable only one of ENDSTOPPULLUPS or ENDSTOPPULLDOWNS." #elif BOTH(FIL_RUNOUT_PULLUP, FIL_RUNOUT_PULLDOWN) @@ -805,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) @@ -817,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 /** @@ -846,7 +853,7 @@ static_assert(Y_MAX_LENGTH >= Y_BED_SIZE, "Movement bounds (Y_MIN_POS, Y_MAX_POS #error "PROGRESS_MSG_EXPIRE must be greater than or equal to 0." #endif #elif ENABLED(LCD_SET_PROGRESS_MANUALLY) && NONE(HAS_MARLINUI_U8GLIB, HAS_GRAPHICAL_TFT, HAS_MARLINUI_HD44780, EXTENSIBLE_UI, HAS_DWIN_E3V2, IS_DWIN_MARLINUI) - #error "LCD_SET_PROGRESS_MANUALLY requires LCD_PROGRESS_BAR, Character LCD, Graphical LCD, TFT, DWIN_CREALITY_LCD, DWIN_CREALITY_LCD_ENHANCED, DWIN_CREALITY_LCD_JYERSUI, DWIN_MARLINUI_*, OR EXTENSIBLE_UI." + #error "LCD_SET_PROGRESS_MANUALLY requires LCD_PROGRESS_BAR, Character LCD, Graphical LCD, TFT, DWIN_CREALITY_LCD, DWIN_LCD_PROUI, DWIN_CREALITY_LCD_JYERSUI, DWIN_MARLINUI_*, OR EXTENSIBLE_UI." #endif #if ENABLED(USE_M73_REMAINING_TIME) && DISABLED(LCD_SET_PROGRESS_MANUALLY) @@ -860,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." @@ -998,10 +1005,71 @@ static_assert(Y_MAX_LENGTH >= Y_BED_SIZE, "Movement bounds (Y_MIN_POS, Y_MAX_POS #error "You can't enable FIL_RUNOUT7_PULLUP and FIL_RUNOUT7_PULLDOWN at the same time." #elif BOTH(FIL_RUNOUT8_PULLUP, FIL_RUNOUT8_PULLDOWN) #error "You can't enable FIL_RUNOUT8_PULLUP and FIL_RUNOUT8_PULLDOWN at the same time." - #elif FILAMENT_RUNOUT_DISTANCE_MM < 0 - #error "FILAMENT_RUNOUT_DISTANCE_MM must be greater than or equal to zero." #elif DISABLED(ADVANCED_PAUSE_FEATURE) static_assert(nullptr == strstr(FILAMENT_RUNOUT_SCRIPT, "M600"), "ADVANCED_PAUSE_FEATURE is required to use M600 with FILAMENT_RUNOUT_SENSOR."); + #elif defined(FIL_RUNOUT_ENABLED_DEFAULT) + #error "FIL_RUNOUT_ENABLED_DEFAULT is now set with the FILAMENT_RUNOUT_ENABLED array." + #elif defined(FILAMENT_RUNOUT_DISTANCE_MM) + #error "FILAMENT_RUNOUT_DISTANCE_MM is now set with the FIL_RUNOUT_DISTANCE_MM array." + #elif defined(FIL_RUNOUT_STATE) || defined(FIL_RUNOUT2_STATE) || defined(FIL_RUNOUT3_STATE) || defined(FIL_RUNOUT4_STATE) || defined(FIL_RUNOUT5_STATE) || defined(FIL_RUNOUT6_STATE) || defined(FIL_RUNOUT7_STATE) || defined(FIL_RUNOUT8_STATE) + #ifdef FIL_RUNOUT_STATE + #if FIL_RUNOUT_STATE + #error "FIL_RUNOUT_STATE HIGH is now set with FIL_RUNOUT_MODE { 2 ... }." + #else + #error "FIL_RUNOUT_STATE LOW is now set with FIL_RUNOUT_MODE { 1 ... }." + #endif + #endif + #ifdef FIL_RUNOUT2_STATE + #if FIL_RUNOUT2_STATE + #error "FIL_RUNOUT2_STATE HIGH is now set with FIL_RUNOUT_MODE { n, 2 ... }." + #else + #error "FIL_RUNOUT2_STATE LOW is now set with FIL_RUNOUT_MODE { n, 1 ... }." + #endif + #endif + #ifdef FIL_RUNOUT3_STATE + #if FIL_RUNOUT3_STATE + #error "FIL_RUNOUT3_STATE HIGH is now set with FIL_RUNOUT_MODE { n, n, 2 ... }." + #else + #error "FIL_RUNOUT3_STATE LOW is now set with FIL_RUNOUT_MODE { n, n, 1 ... }." + #endif + #endif + #ifdef FIL_RUNOUT4_STATE + #if FIL_RUNOUT4_STATE + #error "FIL_RUNOUT4_STATE HIGH is now set with FIL_RUNOUT_MODE { n, n, n, 2 ... }." + #else + #error "FIL_RUNOUT4_STATE LOW is now set with FIL_RUNOUT_MODE { n, n, n, 1 ... }." + #endif + #endif + #ifdef FIL_RUNOUT5_STATE + #if FIL_RUNOUT5_STATE + #error "FIL_RUNOUT5_STATE HIGH is now set with FIL_RUNOUT_MODE { n, n, n, n, 2 ... }." + #else + #error "FIL_RUNOUT5_STATE LOW is now set with FIL_RUNOUT_MODE { n, n, n, n, 1 ... }." + #endif + #endif + #ifdef FIL_RUNOUT6_STATE + #if FIL_RUNOUT6_STATE + #error "FIL_RUNOUT6_STATE HIGH is now set with FIL_RUNOUT_MODE { n, n, n, n, n, 2 ... }." + #else + #error "FIL_RUNOUT6_STATE LOW is now set with FIL_RUNOUT_MODE { n, n, n, n, n, 1 ... }." + #endif + #endif + #ifdef FIL_RUNOUT7_STATE + #if FIL_RUNOUT7_STATE + #error "FIL_RUNOUT7_STATE HIGH is now set with FIL_RUNOUT_MODE { n, n, n, n, n, n, 2 ... }." + #else + #error "FIL_RUNOUT7_STATE LOW is now set with FIL_RUNOUT_MODE { n, n, n, n, n, n, 1 ... }." + #endif + #endif + #ifdef FIL_RUNOUT8_STATE + #if FIL_RUNOUT8_STATE + #error "FIL_RUNOUT8_STATE HIGH is now set with FIL_RUNOUT_MODE { n, n, n, n, n, n, n, 2 ... }." + #else + #error "FIL_RUNOUT8_STATE LOW is now set with FIL_RUNOUT_MODE { n, n, n, n, n, n, n, 1 ... }." + #endif + #endif + #elif ENABLED(FILAMENT_MOTION_SENSOR) + #error "FILAMENT_MOTION_SENSOR is now set with FIL_RUNOUT_MODE { 7 ... }." #endif #endif @@ -1042,8 +1110,8 @@ static_assert(Y_MAX_LENGTH >= Y_BED_SIZE, "Movement bounds (Y_MIN_POS, Y_MAX_POS /** * Instant Freeze */ -#if ENABLED(FREEZE_FEATURE) && !PIN_EXISTS(FREEZE) - #error "FREEZE_FEATURE requires a FREEZE_PIN to be defined." +#if ENABLED(FREEZE_FEATURE) && !(PIN_EXISTS(FREEZE) && defined(FREEZE_STATE)) + #error "FREEZE_FEATURE requires both FREEZE_PIN and FREEZE_STATE." #endif /** @@ -1144,6 +1212,9 @@ static_assert(Y_MAX_LENGTH >= Y_BED_SIZE, "Movement bounds (Y_MIN_POS, Y_MAX_POS #elif ENABLED(SINGLENOZZLE) #error "SINGLENOZZLE requires 2 or more EXTRUDERS." + #if ENABLED(PID_PARAMS_PER_HOTEND) + #error "PID_PARAMS_PER_HOTEND must be disabled when using any SINGLENOZZLE extruder." + #endif #endif @@ -1155,6 +1226,8 @@ static_assert(Y_MAX_LENGTH >= Y_BED_SIZE, "Movement bounds (Y_MIN_POS, Y_MAX_POS #error "SWITCHING_NOZZLE and DUAL_X_CARRIAGE are incompatible." #elif ENABLED(SINGLENOZZLE) #error "SWITCHING_NOZZLE and SINGLENOZZLE are incompatible." + #elif HAS_PRUSA_MMU2 + #error "SWITCHING_NOZZLE and PRUSA_MMU2(S) are incompatible." #elif EXTRUDERS != 2 #error "SWITCHING_NOZZLE requires exactly 2 EXTRUDERS." #elif NUM_SERVOS < 1 @@ -1236,8 +1309,6 @@ static_assert(Y_MAX_LENGTH >= Y_BED_SIZE, "Movement bounds (Y_MIN_POS, Y_MAX_POS #error "MIXING_EXTRUDER is incompatible with SINGLENOZZLE." #elif ENABLED(DISABLE_INACTIVE_EXTRUDER) #error "MIXING_EXTRUDER is incompatible with DISABLE_INACTIVE_EXTRUDER." - #elif HAS_FILAMENT_RUNOUT_DISTANCE - #error "MIXING_EXTRUDER is incompatible with FILAMENT_RUNOUT_DISTANCE_MM." #endif #endif @@ -1393,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 */ @@ -1419,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 /** @@ -1436,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 @@ -1645,9 +1781,9 @@ static_assert(Y_MAX_LENGTH >= Y_BED_SIZE, "Movement bounds (Y_MIN_POS, Y_MAX_POS * Require pin options and pins to be defined */ #if ENABLED(SENSORLESS_PROBING) - #if ENABLED(DELTA) && !(AXIS_HAS_STALLGUARD(X) && AXIS_HAS_STALLGUARD(Y) && AXIS_HAS_STALLGUARD(Z)) + #if ENABLED(DELTA) && !(X_SENSORLESS && Y_SENSORLESS && Z_SENSORLESS) #error "SENSORLESS_PROBING requires TMC2130/2160/2209/5130/5160 drivers on X, Y, and Z." - #elif !AXIS_HAS_STALLGUARD(Z) + #elif !Z_SENSORLESS #error "SENSORLESS_PROBING requires a TMC2130/2160/2209/5130/5160 driver on Z." #endif #elif ENABLED(Z_MIN_PROBE_USES_Z_MIN_ENDSTOP_PIN) @@ -1830,7 +1966,7 @@ static_assert(Y_MAX_LENGTH >= Y_BED_SIZE, "Movement bounds (Y_MIN_POS, Y_MAX_POS * LCD_BED_LEVELING requirements */ #if ENABLED(LCD_BED_LEVELING) - #if NONE(HAS_MARLINUI_MENU, DWIN_CREALITY_LCD, DWIN_CREALITY_LCD_ENHANCED) + #if NONE(HAS_MARLINUI_MENU, DWIN_CREALITY_LCD, DWIN_LCD_PROUI) #error "LCD_BED_LEVELING is not supported by the selected LCD controller." #elif !(ENABLED(MESH_BED_LEVELING) || HAS_ABL_NOT_UBL) #error "LCD_BED_LEVELING requires MESH_BED_LEVELING or AUTO_BED_LEVELING." @@ -1852,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 @@ -1917,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 @@ -2181,9 +2329,9 @@ static_assert(Y_MAX_LENGTH >= Y_BED_SIZE, "Movement bounds (Y_MIN_POS, Y_MAX_POS * Test Sensor & Heater pin combos. * Pins and Sensor IDs must be set for each heater */ -#if !ANY_PIN(TEMP_0, TEMP_0_CS) +#if HAS_EXTRUDERS && !ANY_PIN(TEMP_0, TEMP_0_CS) #error "TEMP_0_PIN or TEMP_0_CS_PIN not defined for this board." -#elif !HAS_HEATER_0 && EXTRUDERS +#elif HAS_EXTRUDERS && !HAS_HEATER_0 #error "HEATER_0_PIN not defined for this board." #elif TEMP_SENSOR_0_IS_MAX_TC && !PIN_EXISTS(TEMP_0_CS) #error "TEMP_SENSOR_0 MAX thermocouple requires TEMP_0_CS_PIN." @@ -2433,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 @@ -2455,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) @@ -2478,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 @@ -2719,7 +2890,7 @@ static_assert(Y_MAX_LENGTH >= Y_BED_SIZE, "Movement bounds (Y_MIN_POS, Y_MAX_POS + COUNT_ENABLED(ANYCUBIC_LCD_I3MEGA, ANYCUBIC_LCD_CHIRON, ANYCUBIC_TFT35) \ + COUNT_ENABLED(DGUS_LCD_UI_ORIGIN, DGUS_LCD_UI_FYSETC, DGUS_LCD_UI_HIPRECY, DGUS_LCD_UI_MKS, DGUS_LCD_UI_RELOADED) \ + COUNT_ENABLED(ENDER2_STOCKDISPLAY, CR10_STOCKDISPLAY) \ - + COUNT_ENABLED(DWIN_CREALITY_LCD, DWIN_CREALITY_LCD_ENHANCED, DWIN_CREALITY_LCD_JYERSUI, DWIN_MARLINUI_PORTRAIT, DWIN_MARLINUI_LANDSCAPE) \ + + COUNT_ENABLED(DWIN_CREALITY_LCD, DWIN_LCD_PROUI, DWIN_CREALITY_LCD_JYERSUI, DWIN_MARLINUI_PORTRAIT, DWIN_MARLINUI_LANDSCAPE) \ + COUNT_ENABLED(FYSETC_MINI_12864_X_X, FYSETC_MINI_12864_1_2, FYSETC_MINI_12864_2_0, FYSETC_GENERIC_12864_1_1) \ + COUNT_ENABLED(LCD_SAINSMART_I2C_1602, LCD_SAINSMART_I2C_2004) \ + COUNT_ENABLED(MKS_12864OLED, MKS_12864OLED_SSD1306) \ @@ -2849,17 +3020,17 @@ static_assert(Y_MAX_LENGTH >= Y_BED_SIZE, "Movement bounds (Y_MIN_POS, Y_MAX_POS #elif BOTH(LCD_BED_LEVELING, PROBE_MANUALLY) #error "DWIN_CREALITY_LCD does not support LCD_BED_LEVELING with PROBE_MANUALLY." #endif -#elif ENABLED(DWIN_CREALITY_LCD_ENHANCED) +#elif ENABLED(DWIN_LCD_PROUI) #if DISABLED(SDSUPPORT) - #error "DWIN_CREALITY_LCD_ENHANCED requires SDSUPPORT to be enabled." + #error "DWIN_LCD_PROUI requires SDSUPPORT to be enabled." #elif ENABLED(PID_EDIT_MENU) - #error "DWIN_CREALITY_LCD_ENHANCED does not support PID_EDIT_MENU." + #error "DWIN_LCD_PROUI does not support PID_EDIT_MENU." #elif ENABLED(PID_AUTOTUNE_MENU) - #error "DWIN_CREALITY_LCD_ENHANCED does not support PID_AUTOTUNE_MENU." + #error "DWIN_LCD_PROUI does not support PID_AUTOTUNE_MENU." #elif ENABLED(LEVEL_BED_CORNERS) - #error "DWIN_CREALITY_LCD_ENHANCED does not support LEVEL_BED_CORNERS." + #error "DWIN_LCD_PROUI does not support LEVEL_BED_CORNERS." #elif BOTH(LCD_BED_LEVELING, PROBE_MANUALLY) - #error "DWIN_CREALITY_LCD_ENHANCED does not support LCD_BED_LEVELING with PROBE_MANUALLY." + #error "DWIN_LCD_PROUI does not support LCD_BED_LEVELING with PROBE_MANUALLY." #endif #endif @@ -2961,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 @@ -3006,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 @@ -3035,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) @@ -3096,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 @@ -3125,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) @@ -3151,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 @@ -3231,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 @@ -3248,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 @@ -3316,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) @@ -3336,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 @@ -3349,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 /** @@ -3374,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; @@ -3393,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 @@ -3438,7 +3702,7 @@ static_assert(_PLUS_TEST(4), "HOMING_FEEDRATE_MM_M values must be positive."); #error "A very large BLOCK_BUFFER_SIZE is not needed and takes longer to drain the buffer on pause / cancel." #endif -#if ENABLED(LED_CONTROL_MENU) && NONE(HAS_MARLINUI_MENU, DWIN_CREALITY_LCD_ENHANCED) +#if ENABLED(LED_CONTROL_MENU) && NONE(HAS_MARLINUI_MENU, DWIN_LCD_PROUI) #error "LED_CONTROL_MENU requires an LCD controller that implements the menu." #endif @@ -3833,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 @@ -3905,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 diff --git a/Marlin/src/inc/Version.h b/Marlin/src/inc/Version.h index 4af25302be..250133c435 100644 --- a/Marlin/src/inc/Version.h +++ b/Marlin/src/inc/Version.h @@ -42,7 +42,7 @@ * version was tagged. */ #ifndef STRING_DISTRIBUTION_DATE - #define STRING_DISTRIBUTION_DATE "2022-03-05" + #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 diff --git a/Marlin/src/inc/Warnings.cpp b/Marlin/src/inc/Warnings.cpp index 9d7b14d763..96f8dc7d54 100644 --- a/Marlin/src/inc/Warnings.cpp +++ b/Marlin/src/inc/Warnings.cpp @@ -532,6 +532,163 @@ #endif #endif + #if AUTO_ASSIGNED_U_STEPPER + #warning "Note: Auto-assigned U STEP/DIR/ENABLE_PINs to unused En_STEP/DIR/ENABLE_PINs. (Define NO_AUTO_ASSIGN_WARNING to suppress this warning.)" + #endif + #if AUTO_ASSIGNED_U_CS + #warning "Note: Auto-assigned U_CS_PIN to an unused En_CS_PIN. (Define NO_AUTO_ASSIGN_WARNING to suppress this warning.)" + #endif + #if AUTO_ASSIGNED_U_MS1 + #warning "Note: Auto-assigned U_MS1_PIN to an unused En_MS1_PIN. (Define NO_AUTO_ASSIGN_WARNING to suppress this warning.)" + #endif + #if AUTO_ASSIGNED_U_MS2 + #warning "Note: Auto-assigned U_MS2_PIN to an unused En_MS2_PIN. (Define NO_AUTO_ASSIGN_WARNING to suppress this warning.)" + #endif + #if AUTO_ASSIGNED_U_MS3 + #warning "Note: Auto-assigned U_MS3_PIN to an unused En_MS3_PIN. (Define NO_AUTO_ASSIGN_WARNING to suppress this warning.)" + #endif + #if AUTO_ASSIGNED_U_DIAG + #if U_USE_ENDSTOP == _XMIN_ + #warning "Note: Auto-assigned U_DIAG_PIN to X_MIN_PIN. (Define NO_AUTO_ASSIGN_WARNING to suppress this warning.)" + #elif U_USE_ENDSTOP == _XMAX_ + #warning "Note: Auto-assigned U_DIAG_PIN to X_MAX_PIN. (Define NO_AUTO_ASSIGN_WARNING to suppress this warning.)" + #elif K_USE_ENDSTOP == _YMIN_ + #warning "Note: Auto-assigned U_DIAG_PIN to Y_MIN_PIN. (Define NO_AUTO_ASSIGN_WARNING to suppress this warning.)" + #elif U_USE_ENDSTOP == _YMAX_ + #warning "Note: Auto-assigned U_DIAG_PIN to Y_MAX_PIN. (Define NO_AUTO_ASSIGN_WARNING to suppress this warning.)" + #elif U_USE_ENDSTOP == _ZMIN_ + #warning "Note: Auto-assigned U_DIAG_PIN to Z_MIN_PIN. (Define NO_AUTO_ASSIGN_WARNING to suppress this warning.)" + #elif U_USE_ENDSTOP == _ZMAX_ + #warning "Note: Auto-assigned U_DIAG_PIN to Z_MAX_PIN. (Define NO_AUTO_ASSIGN_WARNING to suppress this warning.)" + #elif U_USE_ENDSTOP == _XDIAG_ + #warning "Note: Auto-assigned U_DIAG_PIN to X_DIAG_PIN. (Define NO_AUTO_ASSIGN_WARNING to suppress this warning.)" + #elif U_USE_ENDSTOP == _YDIAG_ + #warning "Note: Auto-assigned U_DIAG_PIN to Y_DIAG_PIN. (Define NO_AUTO_ASSIGN_WARNING to suppress this warning.)" + #elif U_USE_ENDSTOP == _ZDIAG_ + #warning "Note: Auto-assigned U_DIAG_PIN to Z_DIAG_PIN. (Define NO_AUTO_ASSIGN_WARNING to suppress this warning.)" + #elif U_USE_ENDSTOP == _E0DIAG_ + #warning "Note: Auto-assigned U_DIAG_PIN to E0_DIAG_PIN. (Define NO_AUTO_ASSIGN_WARNING to suppress this warning.)" + #elif U_USE_ENDSTOP == _E1DIAG_ + #warning "Note: Auto-assigned U_DIAG_PIN to E1_DIAG_PIN. (Define NO_AUTO_ASSIGN_WARNING to suppress this warning.)" + #elif U_USE_ENDSTOP == _E2DIAG_ + #warning "Note: Auto-assigned U_DIAG_PIN to E2_DIAG_PIN. (Define NO_AUTO_ASSIGN_WARNING to suppress this warning.)" + #elif U_USE_ENDSTOP == _E3DIAG_ + #warning "Note: Auto-assigned U_DIAG_PIN to E3_DIAG_PIN. (Define NO_AUTO_ASSIGN_WARNING to suppress this warning.)" + #elif U_USE_ENDSTOP == _E4DIAG_ + #warning "Note: Auto-assigned U_DIAG_PIN to E4_DIAG_PIN. (Define NO_AUTO_ASSIGN_WARNING to suppress this warning.)" + #elif U_USE_ENDSTOP == _E5DIAG_ + #warning "Note: Auto-assigned U_DIAG_PIN to E5_DIAG_PIN. (Define NO_AUTO_ASSIGN_WARNING to suppress this warning.)" + #elif U_USE_ENDSTOP == _E6DIAG_ + #warning "Note: Auto-assigned U_DIAG_PIN to E6_DIAG_PIN. (Define NO_AUTO_ASSIGN_WARNING to suppress this warning.)" + #elif U_USE_ENDSTOP == _E7DIAG_ + #warning "Note: Auto-assigned U_DIAG_PIN to E7_DIAG_PIN. (Define NO_AUTO_ASSIGN_WARNING to suppress this warning.)" + #endif + #endif + #if AUTO_ASSIGNED_V_STEPPER + #warning "Note: Auto-assigned V STEP/DIR/ENABLE_PINs to unused En_STEP/DIR/ENABLE_PINs. (Define NO_AUTO_ASSIGN_WARNING to suppress this warning.)" + #endif + #if AUTO_ASSIGNED_V_CS + #warning "Note: Auto-assigned V_CS_PIN to an unused En_CS_PIN. (Define NO_AUTO_ASSIGN_WARNING to suppress this warning.)" + #endif + #if AUTO_ASSIGNED_V_MS1 + #warning "Note: Auto-assigned V_MS1_PIN to an unused En_MS1_PIN. (Define NO_AUTO_ASSIGN_WARNING to suppress this warning.)" + #endif + #if AUTO_ASSIGNED_V_MS2 + #warning "Note: Auto-assigned V_MS2_PIN to an unused En_MS2_PIN. (Define NO_AUTO_ASSIGN_WARNING to suppress this warning.)" + #endif + #if AUTO_ASSIGNED_V_MS3 + #warning "Note: Auto-assigned V_MS3_PIN to an unused En_MS3_PIN. (Define NO_AUTO_ASSIGN_WARNING to suppress this warning.)" + #endif + #if AUTO_ASSIGNED_V_DIAG + #if V_USE_ENDSTOP == _XMIN_ + #warning "Note: Auto-assigned V_DIAG_PIN to X_MIN_PIN. (Define NO_AUTO_ASSIGN_WARNING to suppress this warning.)" + #elif V_USE_ENDSTOP == _XMAX_ + #warning "Note: Auto-assigned V_DIAG_PIN to X_MAX_PIN. (Define NO_AUTO_ASSIGN_WARNING to suppress this warning.)" + #elif V_USE_ENDSTOP == _YMIN_ + #warning "Note: Auto-assigned V_DIAG_PIN to Y_MIN_PIN. (Define NO_AUTO_ASSIGN_WARNING to suppress this warning.)" + #elif V_USE_ENDSTOP == _YMAX_ + #warning "Note: Auto-assigned V_DIAG_PIN to Y_MAX_PIN. (Define NO_AUTO_ASSIGN_WARNING to suppress this warning.)" + #elif V_USE_ENDSTOP == _ZMIN_ + #warning "Note: Auto-assigned V_DIAG_PIN to Z_MIN_PIN. (Define NO_AUTO_ASSIGN_WARNING to suppress this warning.)" + #elif V_USE_ENDSTOP == _ZMAX_ + #warning "Note: Auto-assigned V_DIAG_PIN to Z_MAX_PIN. (Define NO_AUTO_ASSIGN_WARNING to suppress this warning.)" + #elif V_USE_ENDSTOP == _XDIAG_ + #warning "Note: Auto-assigned V_DIAG_PIN to X_DIAG_PIN. (Define NO_AUTO_ASSIGN_WARNING to suppress this warning.)" + #elif V_USE_ENDSTOP == _YDIAG_ + #warning "Note: Auto-assigned V_DIAG_PIN to Y_DIAG_PIN. (Define NO_AUTO_ASSIGN_WARNING to suppress this warning.)" + #elif V_USE_ENDSTOP == _ZDIAG_ + #warning "Note: Auto-assigned V_DIAG_PIN to Z_DIAG_PIN. (Define NO_AUTO_ASSIGN_WARNING to suppress this warning.)" + #elif V_USE_ENDSTOP == _E0DIAG_ + #warning "Note: Auto-assigned V_DIAG_PIN to E0_DIAG_PIN. (Define NO_AUTO_ASSIGN_WARNING to suppress this warning.)" + #elif V_USE_ENDSTOP == _E1DIAG_ + #warning "Note: Auto-assigned V_DIAG_PIN to E1_DIAG_PIN. (Define NO_AUTO_ASSIGN_WARNING to suppress this warning.)" + #elif V_USE_ENDSTOP == _E2DIAG_ + #warning "Note: Auto-assigned V_DIAG_PIN to E2_DIAG_PIN. (Define NO_AUTO_ASSIGN_WARNING to suppress this warning.)" + #elif V_USE_ENDSTOP == _E3DIAG_ + #warning "Note: Auto-assigned V_DIAG_PIN to E3_DIAG_PIN. (Define NO_AUTO_ASSIGN_WARNING to suppress this warning.)" + #elif V_USE_ENDSTOP == _E4DIAG_ + #warning "Note: Auto-assigned V_DIAG_PIN to E4_DIAG_PIN. (Define NO_AUTO_ASSIGN_WARNING to suppress this warning.)" + #elif V_USE_ENDSTOP == _E5DIAG_ + #warning "Note: Auto-assigned V_DIAG_PIN to E5_DIAG_PIN. (Define NO_AUTO_ASSIGN_WARNING to suppress this warning.)" + #elif V_USE_ENDSTOP == _E6DIAG_ + #warning "Note: Auto-assigned V_DIAG_PIN to E6_DIAG_PIN. (Define NO_AUTO_ASSIGN_WARNING to suppress this warning.)" + #elif V_USE_ENDSTOP == _E7DIAG_ + #warning "Note: Auto-assigned V_DIAG_PIN to E7_DIAG_PIN. (Define NO_AUTO_ASSIGN_WARNING to suppress this warning.)" + #endif + #endif + #if AUTO_ASSIGNED_W_STEPPER + #warning "Note: Auto-assigned W STEP/DIR/ENABLE_PINs to unused En_STEP/DIR/ENABLE_PINs. (Define NO_AUTO_ASSIGN_WARNING to suppress this warning.)" + #endif + #if AUTO_ASSIGNED_W_CS + #warning "Note: Auto-assigned W_CS_PIN to an unused En_CS_PIN. (Define NO_AUTO_ASSIGN_WARNING to suppress this warning.)" + #endif + #if AUTO_ASSIGNED_W_MS1 + #warning "Note: Auto-assigned W_MS1_PIN to an unused En_MS1_PIN. (Define NO_AUTO_ASSIGN_WARNING to suppress this warning.)" + #endif + #if AUTO_ASSIGNED_W_MS2 + #warning "Note: Auto-assigned W_MS2_PIN to an unused En_MS2_PIN. (Define NO_AUTO_ASSIGN_WARNING to suppress this warning.)" + #endif + #if AUTO_ASSIGNED_W_MS3 + #warning "Note: Auto-assigned W_MS3_PIN to an unused En_MS3_PIN. (Define NO_AUTO_ASSIGN_WARNING to suppress this warning.)" + #endif + #if AUTO_ASSIGNED_W_DIAG + #if W_USE_ENDSTOP == _XMIN_ + #warning "Note: Auto-assigned W_DIAG_PIN to X_MIN_PIN. (Define NO_AUTO_ASSIGN_WARNING to suppress this warning.)" + #elif W_USE_ENDSTOP == _XMAX_ + #warning "Note: Auto-assigned W_DIAG_PIN to X_MAX_PIN. (Define NO_AUTO_ASSIGN_WARNING to suppress this warning.)" + #elif W_USE_ENDSTOP == _YMIN_ + #warning "Note: Auto-assigned W_DIAG_PIN to Y_MIN_PIN. (Define NO_AUTO_ASSIGN_WARNING to suppress this warning.)" + #elif W_USE_ENDSTOP == _YMAX_ + #warning "Note: Auto-assigned W_DIAG_PIN to Y_MAX_PIN. (Define NO_AUTO_ASSIGN_WARNING to suppress this warning.)" + #elif W_USE_ENDSTOP == _ZMIN_ + #warning "Note: Auto-assigned W_DIAG_PIN to Z_MIN_PIN. (Define NO_AUTO_ASSIGN_WARNING to suppress this warning.)" + #elif W_USE_ENDSTOP == _ZMAX_ + #warning "Note: Auto-assigned W_DIAG_PIN to Z_MAX_PIN. (Define NO_AUTO_ASSIGN_WARNING to suppress this warning.)" + #elif W_USE_ENDSTOP == _XDIAG_ + #warning "Note: Auto-assigned W_DIAG_PIN to X_DIAG_PIN. (Define NO_AUTO_ASSIGN_WARNING to suppress this warning.)" + #elif W_USE_ENDSTOP == _YDIAG_ + #warning "Note: Auto-assigned W_DIAG_PIN to Y_DIAG_PIN. (Define NO_AUTO_ASSIGN_WARNING to suppress this warning.)" + #elif W_USE_ENDSTOP == _ZDIAG_ + #warning "Note: Auto-assigned W_DIAG_PIN to Z_DIAG_PIN. (Define NO_AUTO_ASSIGN_WARNING to suppress this warning.)" + #elif W_USE_ENDSTOP == _E0DIAG_ + #warning "Note: Auto-assigned W_DIAG_PIN to E0_DIAG_PIN. (Define NO_AUTO_ASSIGN_WARNING to suppress this warning.)" + #elif W_USE_ENDSTOP == _E1DIAG_ + #warning "Note: Auto-assigned W_DIAG_PIN to E1_DIAG_PIN. (Define NO_AUTO_ASSIGN_WARNING to suppress this warning.)" + #elif W_USE_ENDSTOP == _E2DIAG_ + #warning "Note: Auto-assigned W_DIAG_PIN to E2_DIAG_PIN. (Define NO_AUTO_ASSIGN_WARNING to suppress this warning.)" + #elif W_USE_ENDSTOP == _E3DIAG_ + #warning "Note: Auto-assigned W_DIAG_PIN to E3_DIAG_PIN. (Define NO_AUTO_ASSIGN_WARNING to suppress this warning.)" + #elif W_USE_ENDSTOP == _E4DIAG_ + #warning "Note: Auto-assigned W_DIAG_PIN to E4_DIAG_PIN. (Define NO_AUTO_ASSIGN_WARNING to suppress this warning.)" + #elif W_USE_ENDSTOP == _E5DIAG_ + #warning "Note: Auto-assigned W_DIAG_PIN to E5_DIAG_PIN. (Define NO_AUTO_ASSIGN_WARNING to suppress this warning.)" + #elif W_USE_ENDSTOP == _E6DIAG_ + #warning "Note: Auto-assigned W_DIAG_PIN to E6_DIAG_PIN. (Define NO_AUTO_ASSIGN_WARNING to suppress this warning.)" + #elif W_USE_ENDSTOP == _E7DIAG_ + #warning "Note: Auto-assigned W_DIAG_PIN to E7_DIAG_PIN. (Define NO_AUTO_ASSIGN_WARNING to suppress this warning.)" + #endif + #endif + #if ENABLED(CHAMBER_FAN) && !defined(CHAMBER_FAN_INDEX) #warning "Note: Auto-assigned CHAMBER_FAN_INDEX to the first free FAN pin. (Define NO_AUTO_ASSIGN_WARNING to suppress this warning.)" #endif @@ -574,6 +731,10 @@ #warning "Contrast cannot be changed when LCD_CONTRAST_MIN >= LCD_CONTRAST_MAX." #endif +#if PROGRESS_MSG_EXPIRE > 0 && HAS_STATUS_MESSAGE_TIMEOUT + #warning "It is recommended not to combine PROGRESS_MSG_EXPIRE with STATUS_MESSAGE_TIMEOUT_SEC." +#endif + /** * FYSETC backlighting */ diff --git a/Marlin/src/lcd/dogm/dogm_Statusscreen.h b/Marlin/src/lcd/dogm/dogm_Statusscreen.h index f17dd06365..8d0ab4efbe 100644 --- a/Marlin/src/lcd/dogm/dogm_Statusscreen.h +++ b/Marlin/src/lcd/dogm/dogm_Statusscreen.h @@ -37,6 +37,7 @@ #undef STATUS_HEATERS_X #undef STATUS_BED_X + /** * Custom _Statusscreen.h files can define: * - A custom logo image diff --git a/Marlin/src/lcd/dogm/status/combined.h b/Marlin/src/lcd/dogm/status/combined.h index ca18f21af6..070fe6b027 100644 --- a/Marlin/src/lcd/dogm/status/combined.h +++ b/Marlin/src/lcd/dogm/status/combined.h @@ -37,6 +37,7 @@ #if HOTENDS == 0 #define STATUS_HEATERS_WIDTH 96 + #define STATUS_BED_X 74 const unsigned char status_heaters_bmp[] PROGMEM = { B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000100,B00010000,B01000000, @@ -56,6 +57,7 @@ #elif HOTENDS == 1 #define STATUS_HEATERS_WIDTH 96 + #define STATUS_BED_X 74 const unsigned char status_heaters_bmp[] PROGMEM = { B00011111,B11100000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000100,B00010000,B01000000, @@ -75,6 +77,7 @@ #elif HOTENDS == 2 #define STATUS_HEATERS_WIDTH 96 + #define STATUS_BED_X 74 const unsigned char status_heaters_bmp[] PROGMEM = { B00011111,B11100000,B00000000,B00011111,B11100000,B00000000,B00000000,B00000000,B00000000,B00000100,B00010000,B01000000, @@ -104,6 +107,7 @@ #elif HOTENDS == 3 #define STATUS_HEATERS_WIDTH 96 + #define STATUS_BED_X 74 const unsigned char status_heaters_bmp[] PROGMEM = { B00011111,B11100000,B00000000,B00011111,B11100000,B00000000,B00011111,B11100000,B00000000,B00000100,B00010000,B01000000, @@ -133,6 +137,7 @@ #else // HOTENDS > 3 #define STATUS_HEATERS_WIDTH 120 + #define STATUS_BED_X 98 const unsigned char status_heaters_bmp[] PROGMEM = { B00011111,B11100000,B00000000,B00011111,B11100000,B00000000,B00011111,B11100000,B00000000,B00011111,B11100000,B00000000,B00000100,B00010000,B01000000, @@ -161,7 +166,8 @@ #endif // HOTENDS - #define STATUS_BED_TEXT_X (STATUS_HEATERS_WIDTH - 10) + #define STATUS_BED_WIDTH 20 + #define STATUS_BED_TEXT_X (STATUS_BED_X + STATUS_BED_WIDTH / 2) #else // !HAS_HEATED_BED || HOTENDS > 3 diff --git a/Marlin/src/lcd/e3v2/common/dwin_api.cpp b/Marlin/src/lcd/e3v2/common/dwin_api.cpp index f6780bba6c..89d7cb4144 100644 --- a/Marlin/src/lcd/e3v2/common/dwin_api.cpp +++ b/Marlin/src/lcd/e3v2/common/dwin_api.cpp @@ -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 diff --git a/Marlin/src/lcd/e3v2/common/encoder.h b/Marlin/src/lcd/e3v2/common/encoder.h index e5d9645ed4..3ab8c3bf42 100644 --- a/Marlin/src/lcd/e3v2/common/encoder.h +++ b/Marlin/src/lcd/e3v2/common/encoder.h @@ -45,12 +45,32 @@ typedef enum { ENCODER_DIFF_ENTER = 3 // click } EncoderState; +#define ENCODER_WAIT_MS 20 + // Encoder initialization void Encoder_Configuration(); // Analyze encoder value and return state EncoderState Encoder_ReceiveAnalyze(); +inline EncoderState get_encoder_state() { + static millis_t Encoder_ms = 0; + const millis_t ms = millis(); + if (PENDING(ms, Encoder_ms)) return ENCODER_DIFF_NO; + const EncoderState state = Encoder_ReceiveAnalyze(); + if (state != ENCODER_DIFF_NO) Encoder_ms = ms + ENCODER_WAIT_MS; + return state; +} + +template +inline bool Apply_Encoder(const EncoderState &encoder_diffState, T &valref) { + if (encoder_diffState == ENCODER_DIFF_CW) + valref += EncoderRate.encoderMoveValue; + else if (encoder_diffState == ENCODER_DIFF_CCW) + valref -= EncoderRate.encoderMoveValue; + return encoder_diffState == ENCODER_DIFF_ENTER; +} + /*********************** Encoder LED ***********************/ #if PIN_EXISTS(LCD_LED) diff --git a/Marlin/src/lcd/e3v2/creality/dwin.cpp b/Marlin/src/lcd/e3v2/creality/dwin.cpp index f20260e43d..05ac38d226 100644 --- a/Marlin/src/lcd/e3v2/creality/dwin.cpp +++ b/Marlin/src/lcd/e3v2/creality/dwin.cpp @@ -471,15 +471,6 @@ void Draw_Back_First(const bool is_sel=true) { if (is_sel) Draw_Menu_Cursor(0); } -template -inline bool Apply_Encoder(const EncoderState &encoder_diffState, T &valref) { - if (encoder_diffState == ENCODER_DIFF_CW) - valref += EncoderRate.encoderMoveValue; - else if (encoder_diffState == ENCODER_DIFF_CCW) - valref -= EncoderRate.encoderMoveValue; - return encoder_diffState == ENCODER_DIFF_ENTER; -} - // // Draw Menus // @@ -1296,15 +1287,6 @@ void Goto_MainMenu() { TERN(HAS_ONESTEP_LEVELING, ICON_Leveling, ICON_StartInfo)(); } -inline EncoderState get_encoder_state() { - static millis_t Encoder_ms = 0; - const millis_t ms = millis(); - if (PENDING(ms, Encoder_ms)) return ENCODER_DIFF_NO; - const EncoderState state = Encoder_ReceiveAnalyze(); - if (state != ENCODER_DIFF_NO) Encoder_ms = ms + ENCODER_WAIT_MS; - return state; -} - void HMI_Plan_Move(const feedRate_t fr_mm_s) { if (!planner.is_full()) { planner.synchronize(); @@ -4086,6 +4068,13 @@ void HMI_Init() { HMI_SetLanguage(); } +void DWIN_InitScreen() { + Encoder_Configuration(); + HMI_Init(); + HMI_SetLanguageCache(); + HMI_StartFrame(true); +} + void DWIN_Update() { EachMomentUpdate(); // Status update HMI_SDCardUpdate(); // SD card update @@ -4292,7 +4281,7 @@ void DWIN_HandleScreen() { } } -void DWIN_CompletedHoming() { +void DWIN_HomingDone() { HMI_flag.home_flag = false; dwin_zoffset = TERN0(HAS_BED_PROBE, probe.offset.z); if (checkkey == Last_Prepare) { @@ -4308,7 +4297,7 @@ void DWIN_CompletedHoming() { } } -void DWIN_CompletedLeveling() { +void DWIN_LevelingDone() { if (checkkey == Leveling) Goto_MainMenu(); } diff --git a/Marlin/src/lcd/e3v2/creality/dwin.h b/Marlin/src/lcd/e3v2/creality/dwin.h index 3122a6fcba..487f309ed9 100644 --- a/Marlin/src/lcd/e3v2/creality/dwin.h +++ b/Marlin/src/lcd/e3v2/creality/dwin.h @@ -236,13 +236,14 @@ void HMI_MaxJerk(); // Maximum jerk speed submenu void HMI_Step(); // Transmission ratio void HMI_Init(); +void DWIN_InitScreen(); void DWIN_Update(); void EachMomentUpdate(); void DWIN_HandleScreen(); void DWIN_StatusChanged(const char * const cstr=nullptr); void DWIN_StatusChanged(FSTR_P const fstr); -inline void DWIN_StartHoming() { HMI_flag.home_flag = true; } +inline void DWIN_HomingStart() { HMI_flag.home_flag = true; } -void DWIN_CompletedHoming(); -void DWIN_CompletedLeveling(); +void DWIN_HomingDone(); +void DWIN_LevelingDone(); diff --git a/Marlin/src/lcd/e3v2/jyersui/dwin.cpp b/Marlin/src/lcd/e3v2/jyersui/dwin.cpp index d384bae3e3..afe34ac450 100644 --- a/Marlin/src/lcd/e3v2/jyersui/dwin.cpp +++ b/Marlin/src/lcd/e3v2/jyersui/dwin.cpp @@ -958,8 +958,8 @@ void CrealityDWINClass::Update_Status_Bar(bool refresh/*=false*/) { static bool new_msg; static uint8_t msgscrl = 0; static char lastmsg[64]; - if (strcmp_P(lastmsg, statusmsg) != 0 || refresh) { - strcpy_P(lastmsg, statusmsg); + if (strcmp(lastmsg, statusmsg) != 0 || refresh) { + strcpy(lastmsg, statusmsg); msgscrl = 0; new_msg = true; } @@ -2833,7 +2833,7 @@ void CrealityDWINClass::Menu_Item_Handler(uint8_t menu, uint8_t item, bool draw/ #define ADVANCED_UNLOAD (ADVANCED_LOAD + ENABLED(ADVANCED_PAUSE_FEATURE)) #define ADVANCED_COLD_EXTRUDE (ADVANCED_UNLOAD + ENABLED(PREVENT_COLD_EXTRUSION)) #define ADVANCED_FILSENSORENABLED (ADVANCED_COLD_EXTRUDE + ENABLED(FILAMENT_RUNOUT_SENSOR)) - #define ADVANCED_FILSENSORDISTANCE (ADVANCED_FILSENSORENABLED + ENABLED(HAS_FILAMENT_RUNOUT_DISTANCE)) + #define ADVANCED_FILSENSORDISTANCE (ADVANCED_FILSENSORENABLED + 1) #define ADVANCED_POWER_LOSS (ADVANCED_FILSENSORDISTANCE + ENABLED(POWER_LOSS_RECOVERY)) #define ADVANCED_TOTAL ADVANCED_POWER_LOSS @@ -2923,24 +2923,22 @@ void CrealityDWINClass::Menu_Item_Handler(uint8_t menu, uint8_t item, bool draw/ case ADVANCED_FILSENSORENABLED: if (draw) { Draw_Menu_Item(row, ICON_Extruder, F("Filament Sensor")); - Draw_Checkbox(row, runout.enabled); + Draw_Checkbox(row, runout.enabled[0]); } else { - runout.enabled = !runout.enabled; - Draw_Checkbox(row, runout.enabled); + runout.enabled = !runout.enabled[0]; + Draw_Checkbox(row, runout.enabled[0]); } break; - #if ENABLED(HAS_FILAMENT_RUNOUT_DISTANCE) - case ADVANCED_FILSENSORDISTANCE: - if (draw) { - Draw_Menu_Item(row, ICON_MaxAccE, F("Runout Distance")); - Draw_Float(runout.runout_distance(), row, false, 10); - } - else - Modify_Value(runout.runout_distance(), 0, 999, 10); - break; - #endif + case ADVANCED_FILSENSORDISTANCE: + if (draw) { + Draw_Menu_Item(row, ICON_MaxAccE, F("Runout Distance")); + Draw_Float(runout.runout_distance(), row, false, 10); + } + else + Modify_Value(runout.runout_distance(), 0, 999, 10); + break; #endif // FILAMENT_RUNOUT_SENSOR #if ENABLED(POWER_LOSS_RECOVERY) @@ -3417,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; @@ -3829,11 +3827,11 @@ void CrealityDWINClass::Menu_Item_Handler(uint8_t menu, uint8_t item, bool draw/ case TUNE_FILSENSORENABLED: if (draw) { Draw_Menu_Item(row, ICON_Extruder, F("Filament Sensor")); - Draw_Checkbox(row, runout.enabled); + Draw_Checkbox(row, runout.enabled[0]); } else { - runout.enabled = !runout.enabled; - Draw_Checkbox(row, runout.enabled); + runout.enabled = !runout.enabled[0]; + Draw_Checkbox(row, runout.enabled[0]); } break; #endif @@ -4695,10 +4693,7 @@ void CrealityDWINClass::Modify_Option(uint8_t value, const char * const * option /* Main Functions */ void CrealityDWINClass::Update_Status(const char * const text) { - char header[4]; - LOOP_L_N(i, 3) header[i] = text[i]; - header[3] = '\0'; - if (strcmp_P(header, PSTR("")) == 0) { + if (strncmp_P(text, PSTR(""), 3) == 0) { LOOP_L_N(i, _MIN((size_t)LONG_FILENAME_LENGTH, strlen(text))) filename[i] = text[i + 3]; filename[_MIN((size_t)LONG_FILENAME_LENGTH - 1, strlen(text))] = '\0'; Draw_Print_Filename(true); @@ -4722,10 +4717,10 @@ void CrealityDWINClass::Start_Print(bool sd) { card.selectFileByName(fname); } #endif - strcpy_P(filename, card.longest_filename()); + strcpy(filename, card.longest_filename()); } else - strcpy_P(filename, "Host Print"); + strcpy_P(filename, PSTR("Host Print")); TERN_(LCD_SET_PROGRESS_MANUALLY, ui.set_progress(0)); TERN_(USE_M73_REMAINING_TIME, ui.set_remaining_time(0)); Draw_Print_Screen(); @@ -4920,18 +4915,10 @@ void CrealityDWINClass::Screen_Update() { } void CrealityDWINClass::AudioFeedback(const bool success/*=true*/) { - if (success) { - if (ui.buzzer_enabled) { - BUZZ(100, 659); - BUZZ( 10, 0); - BUZZ(100, 698); - } - else Update_Status("Success"); - } - else if (ui.buzzer_enabled) - BUZZ(40, 440); + if (ui.buzzer_enabled) + DONE_BUZZ(success); else - Update_Status("Failed"); + Update_Status(success ? "Success" : "Failed"); } void CrealityDWINClass::Save_Settings(char *buff) { diff --git a/Marlin/src/lcd/e3v2/marlinui/dwin_lcd.cpp b/Marlin/src/lcd/e3v2/marlinui/dwin_lcd.cpp index a4cefe4ab9..7154270bff 100644 --- a/Marlin/src/lcd/e3v2/marlinui/dwin_lcd.cpp +++ b/Marlin/src/lcd/e3v2/marlinui/dwin_lcd.cpp @@ -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(); } diff --git a/Marlin/src/lcd/e3v2/marlinui/ui_common.cpp b/Marlin/src/lcd/e3v2/marlinui/ui_common.cpp index f49d06d396..4e0174705e 100644 --- a/Marlin/src/lcd/e3v2/marlinui/ui_common.cpp +++ b/Marlin/src/lcd/e3v2/marlinui/ui_common.cpp @@ -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); diff --git a/Marlin/src/lcd/e3v2/marlinui/ui_status_480x272.cpp b/Marlin/src/lcd/e3v2/marlinui/ui_status_480x272.cpp index c2948048c1..2a4909d921 100644 --- a/Marlin/src/lcd/e3v2/marlinui/ui_status_480x272.cpp +++ b/Marlin/src/lcd/e3v2/marlinui/ui_status_480x272.cpp @@ -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 diff --git a/Marlin/src/lcd/e3v2/proui/dwin.cpp b/Marlin/src/lcd/e3v2/proui/dwin.cpp index 5af7fc294d..8c4dfb6d74 100644 --- a/Marlin/src/lcd/e3v2/proui/dwin.cpp +++ b/Marlin/src/lcd/e3v2/proui/dwin.cpp @@ -21,19 +21,18 @@ */ /** - * Enhanced DWIN implementation + * DWIN Enhanced implementation for PRO UI * Author: Miguel A. Risco-Castillo (MRISCOC) - * Version: 3.11.2 - * date: 2022/01/19 - * - * Based on the original code provided by Creality under GPL + * Version: 3.15.2 + * Date: 2022/03/01 */ -#include "../../../inc/MarlinConfigPre.h" +#include "../../../inc/MarlinConfig.h" -#if ENABLED(DWIN_CREALITY_LCD_ENHANCED) +#if ENABLED(DWIN_LCD_PROUI) #include "dwin.h" +#include "menus.h" #include "dwin_popup.h" #include "../../fontutils.h" @@ -65,6 +64,10 @@ #include "../../../feature/host_actions.h" #endif +#if ANY(AUTO_BED_LEVELING_BILINEAR, AUTO_BED_LEVELING_LINEAR, AUTO_BED_LEVELING_3POINT) && DISABLED(PROBE_MANUALLY) + #define HAS_ONESTEP_LEVELING 1 +#endif + #if HAS_MESH || HAS_ONESTEP_LEVELING #include "../../../feature/bedlevel/bedlevel.h" #endif @@ -77,8 +80,14 @@ #include "../../../feature/bltouch.h" #endif -#if EITHER(BABYSTEP_ZPROBE_OFFSET, JUST_BABYSTEP) - #include "../../../feature/babystep.h" +#if ANY(BABYSTEPPING, HAS_BED_PROBE, HAS_WORKSPACE_OFFSET) + #define HAS_ZOFFSET_ITEM 1 + #if !HAS_BED_PROBE && ENABLED(BABYSTEPPING) + #define JUST_BABYSTEP 1 + #endif + #if EITHER(BABYSTEP_ZPROBE_OFFSET, JUST_BABYSTEP) + #include "../../../feature/babystep.h" + #endif #endif #if ENABLED(POWER_LOSS_RECOVERY) @@ -171,7 +180,7 @@ enum SelectItem : uint8_t { PAGE_PRINT = 0, PAGE_PREPARE, PAGE_CONTROL, - PAGE_INFO_LEV_ADV, + PAGE_ADVANCE, PAGE_COUNT, PRINT_SETUP = 0, @@ -192,14 +201,13 @@ typedef struct { select_t select_page{0}, select_file{0}, select_print{0}; uint8_t index_file = MROWS; -bool dwin_abort_flag = false; // Flag to reset feedrate, return to Home bool hash_changed = true; // Flag to know if message status was changed -constexpr float default_max_feedrate[] = DEFAULT_MAX_FEEDRATE; -constexpr float default_max_acceleration[] = DEFAULT_MAX_ACCELERATION; +constexpr float max_feedrate_edit_values[] = DEFAULT_MAX_FEEDRATE; +constexpr float max_acceleration_edit_values[] = DEFAULT_MAX_ACCELERATION; #if HAS_CLASSIC_JERK - constexpr float default_max_jerk[] = { DEFAULT_XJERK, DEFAULT_YJERK, DEFAULT_ZJERK, DEFAULT_EJERK }; + constexpr float max_jerk_edit_values[] = { DEFAULT_XJERK, DEFAULT_YJERK, DEFAULT_ZJERK, DEFAULT_EJERK }; #endif static uint8_t _percent_done = 0; @@ -208,18 +216,6 @@ static uint32_t _remain_time = 0; // Additional Aux Host Support static bool sdprint = false; -#if ENABLED(PAUSE_HEAT) - #if HAS_HOTEND - celsius_t resume_hotend_temp = 0; - #endif - #if HAS_HEATED_BED - celsius_t resume_bed_temp = 0; - #endif - #if HAS_FAN - uint16_t resume_fan = 0; - #endif -#endif - #if HAS_ZOFFSET_ITEM float dwin_zoffset = 0, last_zoffset = 0; #endif @@ -348,31 +344,13 @@ void ICON_Control() { ICON_Button(select_page.now == PAGE_CONTROL, ICON_Control_0, ico, txt, GET_TEXT_F(MSG_CONTROL)); } -// -// Main Menu: "Info" -// -void ICON_StartInfo() { - constexpr frame_rect_t ico = { 145, 226, 110, 100 }; - constexpr text_info_t txt = { 91, { 405, TERN(USE_STOCK_DWIN_SET, 446, 447) }, 27, 15 }; - ICON_Button(select_page.now == PAGE_INFO_LEV_ADV, ICON_Info_0, ico, txt, GET_TEXT_F(MSG_BUTTON_INFO)); -} - -// -// Main Menu: "Level" -// -void ICON_Leveling() { - constexpr frame_rect_t ico = { 145, 226, 110, 100 }; - constexpr text_info_t txt = { 211, { 405, TERN(USE_STOCK_DWIN_SET, 446, 447) }, 27, 15 }; - ICON_Button(select_page.now == PAGE_INFO_LEV_ADV, ICON_Leveling_0, ico, txt, GET_TEXT_F(MSG_BUTTON_LEVEL)); -} - // // Main Menu: "Advanced Settings" // void ICON_AdvSettings() { constexpr frame_rect_t ico = { 145, 226, 110, 100 }; constexpr text_info_t txt = { 91, { 405, TERN(USE_STOCK_DWIN_SET, 446, 447) }, 27, 15 }; - ICON_Button(select_page.now == PAGE_INFO_LEV_ADV, ICON_Info_0, ico, txt, GET_TEXT_F(MSG_BUTTON_ADVANCED)); + ICON_Button(select_page.now == PAGE_ADVANCE, ICON_Info_0, ico, txt, GET_TEXT_F(MSG_BUTTON_ADVANCED)); } // @@ -415,14 +393,6 @@ void ICON_Stop() { // Drawing routines //----------------------------------------------------------------------------- -void Draw_Menu_Cursor(const int8_t line) { - DWIN_Draw_Rectangle(1, HMI_data.Cursor_color, 0, MBASE(line) - 18, 14, MBASE(line + 1) - 20); -} - -void Erase_Menu_Cursor(const int8_t line) { - DWIN_Draw_Rectangle(1, HMI_data.Background_Color, 0, MBASE(line) - 18, 14, MBASE(line + 1) - 20); -} - void Move_Highlight(const int8_t from, const int8_t newline) { Erase_Menu_Cursor(newline - from); Draw_Menu_Cursor(newline); @@ -430,7 +400,7 @@ void Move_Highlight(const int8_t from, const int8_t newline) { void Add_Menu_Line() { Move_Highlight(1, MROWS); - DWIN_Draw_Line(HMI_data.SplitLine_Color, 16, MBASE(MROWS + 1) - 20, 256, MBASE(MROWS + 1) - 19); + DWIN_Draw_HLine(HMI_data.SplitLine_Color, 16, MYPOS(MROWS + 1), 240); } void Scroll_Menu(const uint8_t dir) { @@ -449,21 +419,6 @@ void Erase_Menu_Text(const uint8_t line) { DWIN_Draw_Rectangle(1, HMI_data.Background_Color, LBLX, MBASE(line) - 14, 271, MBASE(line) + 28); } -void Draw_Menu_Line(const uint8_t line, const uint8_t icon=0, const char * const label=nullptr, bool more=false) { - if (icon) DWINUI::Draw_Icon(icon, ICOX, MBASE(line) - 3); - if (label) DWINUI::Draw_String(LBLX, MBASE(line) - 1, (char*)label); - if (more) DWINUI::Draw_Icon(ICON_More, VALX + 16, MBASE(line) - 3); - DWIN_Draw_HLine(HMI_data.SplitLine_Color, 16, MYPOS(line + 1), 240); -} - -void Draw_Chkb_Line(const uint8_t line, const bool checked) { - DWINUI::Draw_Checkbox(HMI_data.Text_Color, HMI_data.Background_Color, VALX + 16, MBASE(line) - 1, checked); -} - -void Draw_Menu_IntValue(uint16_t bcolor, const uint8_t line, uint8_t iNum, const uint16_t value=0) { - DWINUI::Draw_Int(HMI_data.Text_Color, bcolor, iNum , VALX, MBASE(line) - 1, value); -} - // Draw "Back" line at the top void Draw_Back_First(const bool is_sel=true) { Draw_Menu_Line(0, ICON_Back); @@ -474,24 +429,6 @@ void Draw_Back_First(const bool is_sel=true) { if (is_sel) Draw_Menu_Cursor(0); } -inline EncoderState get_encoder_state() { - static millis_t Encoder_ms = 0; - const millis_t ms = millis(); - if (PENDING(ms, Encoder_ms)) return ENCODER_DIFF_NO; - const EncoderState state = Encoder_ReceiveAnalyze(); - if (state != ENCODER_DIFF_NO) Encoder_ms = ms + ENCODER_WAIT_MS; - return state; -} - -template -inline bool Apply_Encoder(const EncoderState &encoder_diffState, T &valref) { - if (encoder_diffState == ENCODER_DIFF_CW) - valref += EncoderRate.encoderMoveValue; - else if (encoder_diffState == ENCODER_DIFF_CCW) - valref -= EncoderRate.encoderMoveValue; - return encoder_diffState == ENCODER_DIFF_ENTER; -} - //PopUps void Popup_window_PauseOrStop() { if (HMI_IsChinese()) { @@ -530,9 +467,10 @@ void Popup_window_PauseOrStop() { #if HAS_HOTEND || HAS_HEATED_BED void DWIN_Popup_Temperature(const bool toohigh) { - DWINUI::ClearMenuArea(); - Draw_Popup_Bkgd(); + HMI_SaveProcessID(WaitResponse); if (HMI_IsChinese()) { + DWINUI::ClearMenuArea(); + Draw_Popup_Bkgd(); if (toohigh) { DWINUI::Draw_Icon(ICON_TempTooHigh, 102, 165); DWIN_Frame_AreaCopy(1, 103, 371, 237, 386, 52, 285); @@ -545,23 +483,14 @@ void Popup_window_PauseOrStop() { DWIN_Frame_AreaCopy(1, 189, 389, 271, 402, 95, 310); } } - else { - DWIN_Draw_Popup(toohigh ? ICON_TempTooHigh : ICON_TempTooLow, F("Nozzle or Bed temperature"), toohigh ? F("is too high") : F("is too low")); - } + else DWIN_Show_Popup(toohigh ? ICON_TempTooHigh : ICON_TempTooLow, F("Nozzle or Bed temperature"), toohigh ? F("is too high") : F("is too low"), BTN_Continue); } #endif // Draw status line -void DWIN_DrawStatusLine(const uint16_t color, const uint16_t bgcolor, const char *text, const bool center = true) { - DWIN_Draw_Rectangle(1, bgcolor, 0, STATUS_Y, DWIN_WIDTH, STATUS_Y + 20); - if (text) { - if (center) DWINUI::Draw_CenteredString(color, STATUS_Y + 2, text); - else DWINUI::Draw_String(color, 0, STATUS_Y + 2, text); - } - DWIN_UpdateLCD(); -} -void DWIN_DrawStatusLine(const char *text, const bool center = true) { - DWIN_DrawStatusLine(HMI_data.StatusTxt_Color, HMI_data.StatusBg_Color, text, center); +void DWIN_DrawStatusLine(const char *text) { + DWIN_Draw_Rectangle(1, HMI_data.StatusBg_Color, 0, STATUS_Y, DWIN_WIDTH, STATUS_Y + 20); + if (text) DWINUI::Draw_CenteredString(HMI_data.StatusTxt_Color, STATUS_Y + 2, text); } // Clear & reset status line @@ -582,17 +511,15 @@ void DWIN_CheckStatusMessage() { }; void DWIN_DrawStatusMessage() { - const uint8_t max_status_chars = DWIN_WIDTH / DWINUI::fontWidth(); - #if ENABLED(STATUS_MESSAGE_SCROLLING) // Get the UTF8 character count of the string uint8_t slen = utf8_strlen(ui.status_message); // If the string fits the status line do not scroll it - if (slen <= max_status_chars) { + if (slen <= LCD_WIDTH) { if (hash_changed) { - DWIN_DrawStatusLine(HMI_data.StatusTxt_Color, HMI_data.StatusBg_Color, ui.status_message); + DWIN_DrawStatusLine(ui.status_message); hash_changed = false; } } @@ -605,16 +532,16 @@ void DWIN_DrawStatusMessage() { const char *stat = MarlinUI::status_and_len(rlen); DWIN_Draw_Rectangle(1, HMI_data.StatusBg_Color, 0, STATUS_Y, DWIN_WIDTH, STATUS_Y + 20); DWINUI::MoveTo(0, STATUS_Y + 2); - DWINUI::Draw_String(stat, max_status_chars); + DWINUI::Draw_String(HMI_data.StatusTxt_Color, stat, LCD_WIDTH); // If the string doesn't completely fill the line... - if (rlen < max_status_chars) { - DWINUI::Draw_Char('.'); // Always at 1+ spaces left, draw a dot - uint8_t chars = max_status_chars - rlen; // Amount of space left in characters + if (rlen < LCD_WIDTH) { + DWINUI::Draw_Char(HMI_data.StatusTxt_Color, '.'); // Always at 1+ spaces left, draw a dot + uint8_t chars = LCD_WIDTH - rlen; // Amount of space left in characters if (--chars) { // Draw a second dot if there's space - DWINUI::Draw_Char('.'); + DWINUI::Draw_Char(HMI_data.StatusTxt_Color, '.'); if (--chars) - DWINUI::Draw_String(ui.status_message, chars); // Print a second copy of the message + DWINUI::Draw_String(HMI_data.StatusTxt_Color, ui.status_message, chars); // Print a second copy of the message } } MarlinUI::advance_status_scroll(); @@ -623,8 +550,8 @@ void DWIN_DrawStatusMessage() { #else if (hash_changed) { - ui.status_message[max_status_chars] = 0; - DWIN_DrawStatusLine(HMI_data.StatusTxt_Color, HMI_data.StatusBg_Color, ui.status_message); + ui.status_message[LCD_WIDTH] = 0; + DWIN_DrawStatusLine(ui.status_message); hash_changed = false; } @@ -643,7 +570,7 @@ void Draw_Print_Labels() { } void Draw_Print_ProgressBar() { - DWINUI::Draw_IconWB(ICON_Bar, 15, 93); + DWIN_ICON_Show(true, false, false, ICON, ICON_Bar, 15, 93); DWIN_Draw_Rectangle(1, HMI_data.Barfill_Color, 16 + _percent_done * 240 / 100, 93, 256, 113); DWINUI::Draw_Int(HMI_data.PercentTxt_Color, HMI_data.Background_Color, 3, 117, 133, _percent_done); DWINUI::Draw_String(HMI_data.PercentTxt_Color, 142, 133, F("%")); @@ -663,10 +590,21 @@ void Draw_Print_ProgressRemain() { } void ICON_ResumeOrPause() { - if (printingIsPaused() || HMI_flag.pause_flag || HMI_flag.pause_action) - ICON_Resume(); - else - ICON_Pause(); + if (checkkey == PrintProcess) printingIsPaused() ? ICON_Resume() : ICON_Pause(); +} + +// Update filename on print +void DWIN_Print_Header(const char *text = nullptr) { + static char headertxt[31] = ""; // Print header text + if (text) { + const int8_t size = _MIN(30U, strlen_P(text)); + LOOP_L_N(i, size) headertxt[i] = text[i]; + headertxt[size] = '\0'; + } + if (checkkey == PrintProcess || checkkey == PrintDone) { + DWIN_Draw_Rectangle(1, HMI_data.Background_Color, 0, 60, DWIN_WIDTH, 60+16); + DWINUI::Draw_CenteredString(60, headertxt); + } } void Draw_PrintProcess() { @@ -685,17 +623,16 @@ void Draw_PrintProcess() { ICON_Tune(); ICON_ResumeOrPause(); ICON_Stop(); - DWIN_UpdateLCD(); } void Goto_PrintProcess() { - if (checkkey == PrintProcess) { + if (checkkey == PrintProcess) ICON_ResumeOrPause(); - DWIN_UpdateLCD(); - return; + else { + checkkey = PrintProcess; + Draw_PrintProcess(); } - checkkey = PrintProcess; - Draw_PrintProcess(); + DWIN_UpdateLCD(); } void Draw_PrintDone() { @@ -713,8 +650,16 @@ void Draw_PrintDone() { Draw_Print_ProgressElapsed(); Draw_Print_ProgressRemain(); // show print done confirm - DWINUI::Draw_IconWB(HMI_IsChinese() ? ICON_Confirm_C : ICON_Confirm_E, 86, 273); - DWIN_UpdateLCD(); + DWINUI::Draw_Button(BTN_Confirm, 86, 273); +} + +void Goto_PrintDone() { + wait_for_user = true; + if (checkkey != PrintDone) { + checkkey = PrintDone; + Draw_PrintDone(); + DWIN_UpdateLCD(); + } } void Draw_Main_Menu() { @@ -724,18 +669,18 @@ void Draw_Main_Menu() { else Title.ShowCaption(MACHINE_NAME); DWINUI::Draw_Icon(ICON_LOGO, 71, 52); // CREALITY logo + DWIN_ResetStatusLine(); ICON_Print(); ICON_Prepare(); ICON_Control(); ICON_AdvSettings(); - DWIN_UpdateLCD(); } void Goto_Main_Menu() { if (checkkey == MainMenu) return; checkkey = MainMenu; - ui.reset_status(true); Draw_Main_Menu(); + DWIN_UpdateLCD(); } // Draw X, Y, Z and blink if in an un-homed or un-trusted state @@ -751,9 +696,9 @@ void _update_axis_value(const AxisEnum axis, const uint16_t x, const uint16_t y, if (force || changed || draw_qmark || draw_empty) { if (blink && draw_qmark) - DWINUI::Draw_String(HMI_data.Coordinate_Color, HMI_data.Background_Color, x, y, F(" - ? -")); + DWINUI::Draw_String(HMI_data.Coordinate_Color, HMI_data.Background_Color, x, y, F(" - ? -")); else if (blink && draw_empty) - DWINUI::Draw_String(HMI_data.Coordinate_Color, HMI_data.Background_Color, x, y, F(" ")); + DWINUI::Draw_String(HMI_data.Coordinate_Color, HMI_data.Background_Color, x, y, F(" ")); else DWINUI::Draw_Signed_Float(HMI_data.Coordinate_Color, HMI_data.Background_Color, 3, 2, x, y, p); } @@ -766,9 +711,9 @@ void _draw_xyz_position(const bool force) { if (force || blink != _blink) { _blink = blink; //SERIAL_ECHOPGM(" (blink)"); - _update_axis_value(X_AXIS, 35, 459, blink, true); - _update_axis_value(Y_AXIS, 120, 459, blink, true); - _update_axis_value(Z_AXIS, 205, 459, blink, true); + _update_axis_value(X_AXIS, 27, 459, blink, true); + _update_axis_value(Y_AXIS, 112, 459, blink, true); + _update_axis_value(Z_AXIS, 197, 459, blink, true); } //SERIAL_EOL(); } @@ -852,7 +797,7 @@ void update_variable() { static float _offset = 0; if (BABY_Z_VAR != _offset) { _offset = BABY_Z_VAR; - DWINUI::Draw_Signed_Float(DWIN_FONT_STAT, HMI_data.Indicator_Color, HMI_data.Background_Color, 2, 2, 210, 417, _offset); + DWINUI::Draw_Signed_Float(DWIN_FONT_STAT, HMI_data.Indicator_Color, HMI_data.Background_Color, 2, 2, 204, 417, _offset); } #if HAS_MESH @@ -908,15 +853,6 @@ void make_name_without_ext(char *dst, char *src, size_t maxlen=MENU_CHAR_LIMIT) void HMI_SDCardInit() { card.cdroot(); } -// Initialize or re-initialize the LCD -void MarlinUI::init_lcd() { DWIN_Startup(); } - -void MarlinUI::refresh() { /* Nothing to see here */ } - -#if HAS_LCD_BRIGHTNESS - void MarlinUI::_set_brightness() { DWIN_LCD_Brightness(backlight ? brightness : 0); } -#endif - #if ENABLED(SCROLL_LONG_FILENAMES) char shift_name[LONG_FILENAME_LENGTH + 1]; @@ -966,7 +902,8 @@ void Draw_SDItem(const uint16_t item, int16_t row=-1) { // Draw the file/folder with name aligned left char str[strlen(name) + 1]; make_name_without_ext(str, name); - Draw_Menu_Line(row, card.flag.filenameIsDir ? ICON_Folder : ICON_File, str); + const uint8_t icon = card.flag.filenameIsDir ? ICON_Folder : card.fileIsBinary() ? ICON_Binary : ICON_File; + Draw_Menu_Line(row, icon, str); } #if ENABLED(SCROLL_LONG_FILENAMES) @@ -1045,11 +982,8 @@ void HMI_SDCardUpdate() { Redraw_SD_List(); } else if (sdprint && card.isPrinting() && printingIsActive()) { - // TODO: Move card removed abort handling - // to CardReader::manage_media. - card.abortFilePrintSoon(); wait_for_heatup = wait_for_user = false; - dwin_abort_flag = true; // Reset feedrate, return to Home + HMI_flag.abort_flag = true; // Abort print } } DWIN_UpdateLCD(); @@ -1057,10 +991,10 @@ void HMI_SDCardUpdate() { } // -// The status area is always on-screen, except during -// full-screen modal dialogs. (TODO: Keep alive during dialogs) +// The Dashboard is always on-screen, except during +// full-screen modal dialogs. // -void Draw_Status_Area(const bool with_update) { +void DWIN_Draw_Dashboard() { DWIN_Draw_Rectangle(1, HMI_data.Background_Color, 0, STATUS_Y + 21, DWIN_WIDTH, DWIN_HEIGHT - 1); @@ -1095,7 +1029,7 @@ void Draw_Status_Area(const bool with_update) { DWINUI::Draw_Icon(planner.leveling_active ? ICON_SetZOffset : ICON_Zoffset, 187, 416); #endif - DWINUI::Draw_Signed_Float(DWIN_FONT_STAT, HMI_data.Indicator_Color, HMI_data.Background_Color, 2, 2, 210, 417, BABY_Z_VAR); + DWINUI::Draw_Signed_Float(DWIN_FONT_STAT, HMI_data.Indicator_Color, HMI_data.Background_Color, 2, 2, 204, 417, BABY_Z_VAR); DWIN_Draw_Rectangle(1, HMI_data.SplitLine_Color, 0, 449, DWIN_WIDTH, 451); @@ -1104,16 +1038,6 @@ void Draw_Status_Area(const bool with_update) { DWINUI::Draw_Icon(ICON_MaxSpeedZ, 180, 456); _draw_xyz_position(true); - if (with_update) { - DWIN_UpdateLCD(); - delay(5); - } -} - -void HMI_StartFrame(const bool with_update) { - Goto_Main_Menu(); - DWIN_DrawStatusLine(nullptr); - Draw_Status_Area(with_update); } void Draw_Info_Menu() { @@ -1143,8 +1067,6 @@ void Draw_Info_Menu() { DWINUI::Draw_Icon(ICON_PrintSize + i, ICOX, 99 + i * 73); DWIN_Draw_HLine(HMI_data.SplitLine_Color, 16, MBASE(2) + i * 73, 240); } - - DWIN_UpdateLCD(); } void Draw_Print_File_Menu() { @@ -1166,7 +1088,7 @@ void HMI_MainMenu() { case PAGE_PRINT: ICON_Print(); break; case PAGE_PREPARE: ICON_Print(); ICON_Prepare(); break; case PAGE_CONTROL: ICON_Prepare(); ICON_Control(); break; - case PAGE_INFO_LEV_ADV: ICON_Control(); ICON_AdvSettings(); break; + case PAGE_ADVANCE: ICON_Control(); ICON_AdvSettings(); break; } } } @@ -1176,7 +1098,7 @@ void HMI_MainMenu() { case PAGE_PRINT: ICON_Print(); ICON_Prepare(); break; case PAGE_PREPARE: ICON_Prepare(); ICON_Control(); break; case PAGE_CONTROL: ICON_Control(); ICON_AdvSettings(); break; - case PAGE_INFO_LEV_ADV: ICON_AdvSettings(); break; + case PAGE_ADVANCE: ICON_AdvSettings(); break; } } } @@ -1185,14 +1107,12 @@ void HMI_MainMenu() { case PAGE_PRINT: checkkey = SelectFile; card.mount(); + delay(300); Draw_Print_File_Menu(); break; - case PAGE_PREPARE: Draw_Prepare_Menu(); break; - case PAGE_CONTROL: Draw_Control_Menu(); break; - - case PAGE_INFO_LEV_ADV: Draw_AdvancedSettings_Menu(); break; + case PAGE_ADVANCE: Draw_AdvancedSettings_Menu(); break; } } DWIN_UpdateLCD(); @@ -1277,7 +1197,7 @@ void HMI_SelectFile() { else if (encoder_diffState == ENCODER_DIFF_ENTER) { if (select_file.now == 0) { // Back select_page.set(PAGE_PRINT); - Goto_Main_Menu(); + return Goto_Main_Menu(); } else if (hasUpDir && select_file.now == 1) { // CD-Up SDCard_Up(); @@ -1301,16 +1221,10 @@ void HMI_SelectFile() { HMI_flag.heat_flag = true; HMI_flag.print_finish = false; - card.openAndPrintFile(card.filename); - - #if HAS_FAN - // All fans on for Ender 3 v2 ? - // The slicer should manage this for us. - //for (uint8_t i = 0; i < FAN_COUNT; i++) - // thermalManager.fan_speed[i] = 255; - #endif - - DWIN_Print_Started(true); + if (card.fileIsBinary()) + return DWIN_Popup_Confirm(ICON_Error, F("Please check filenames"), F("Only G-code can be printed")); + else + return Goto_ConfirmToPrint(); } } @@ -1318,6 +1232,16 @@ void HMI_SelectFile() { DWIN_UpdateLCD(); } +// Pause or Stop popup +void onClick_PauseOrStop() { + switch (select_print.now) { + case PRINT_PAUSE_RESUME: if (HMI_flag.select_flag) HMI_flag.pause_flag = true; break; // confirm pause + case PRINT_STOP: if (HMI_flag.select_flag) HMI_flag.abort_flag = true; break; // stop confirmed then abort print + default: break; + } + return Goto_PrintProcess(); +} + // Printing void HMI_Printing() { EncoderState encoder_diffState = get_encoder_state(); @@ -1345,106 +1269,23 @@ void HMI_Printing() { switch (select_print.now) { case PRINT_SETUP: Draw_Tune_Menu(); break; case PRINT_PAUSE_RESUME: - if (HMI_flag.pause_flag) { - ICON_Pause(); - #if DISABLED(ADVANCED_PAUSE_FEATURE) - char cmd[40]; - cmd[0] = '\0'; - #if BOTH(HAS_HEATED_BED, PAUSE_HEAT) - if (resume_bed_temp) sprintf_P(cmd, PSTR("M190 S%i\n"), resume_bed_temp); - #endif - #if BOTH(HAS_HOTEND, PAUSE_HEAT) - if (resume_hotend_temp) sprintf_P(&cmd[strlen(cmd)], PSTR("M109 S%i\n"), resume_hotend_temp); - #endif - #if HAS_FAN - if (resume_fan) thermalManager.fan_speed[0] = resume_fan; - #endif - strcat_P(cmd, M24_STR); - queue.inject(cmd); - #endif + if (printingIsPaused()) { // if printer is already in pause + ui.resume_print(); + break; } - else { - HMI_flag.select_flag = true; - checkkey = PauseOrStop; - Popup_window_PauseOrStop(); - } - break; - + else + return Goto_Popup(Popup_window_PauseOrStop, onClick_PauseOrStop); case PRINT_STOP: - HMI_flag.select_flag = true; - checkkey = PauseOrStop; - Popup_window_PauseOrStop(); - break; - + return Goto_Popup(Popup_window_PauseOrStop, onClick_PauseOrStop); default: break; } } DWIN_UpdateLCD(); } -// Print done -void HMI_PrintDone() { - EncoderState encoder_diffState = get_encoder_state(); - if (encoder_diffState == ENCODER_DIFF_NO) return; - if (encoder_diffState == ENCODER_DIFF_ENTER) { - dwin_abort_flag = true; // Reset feedrate, return to Home - Goto_Main_Menu(); // Return to Main menu after print done - } -} - -// Pause or Stop popup -void HMI_PauseOrStop() { - EncoderState encoder_diffState = get_encoder_state(); - if (encoder_diffState == ENCODER_DIFF_NO) return; - - if (encoder_diffState == ENCODER_DIFF_CW) - Draw_Select_Highlight(false); - else if (encoder_diffState == ENCODER_DIFF_CCW) - Draw_Select_Highlight(true); - else if (encoder_diffState == ENCODER_DIFF_ENTER) { - if (select_print.now == PRINT_PAUSE_RESUME) { - if (HMI_flag.select_flag) { - HMI_flag.pause_action = true; - ICON_Resume(); - queue.inject(F("M25")); - } - else { - // cancel pause - } - Goto_PrintProcess(); - } - else if (select_print.now == PRINT_STOP) { - if (HMI_flag.select_flag) { - checkkey = MainMenu; - if (HMI_flag.home_flag) planner.synchronize(); // Wait for planner moves to finish! - wait_for_heatup = wait_for_user = false; // Stop waiting for heating/user - card.abortFilePrintSoon(); // Let the main loop handle SD abort - dwin_abort_flag = true; // Reset feedrate, return to Home - #ifdef ACTION_ON_CANCEL - hostui.cancel(); - #endif - DWIN_Draw_Popup(ICON_BLTouch, GET_TEXT_F(MSG_STOPPING), GET_TEXT_F(MSG_PLEASE_WAIT)); - } - else - Goto_PrintProcess(); // cancel stop - } - } - DWIN_UpdateLCD(); -} - #include "../../../libs/buzzer.h" -void HMI_AudioFeedback(const bool success/*=true*/) { - #if HAS_BUZZER - if (success) { - BUZZ(100, 659); - BUZZ(10, 0); - BUZZ(100, 698); - } - else - BUZZ(40, 440); - #endif -} +void HMI_AudioFeedback(const bool success/*=true*/) { DONE_BUZZ(success); } void Draw_Main_Area() { switch (checkkey) { @@ -1452,24 +1293,11 @@ void Draw_Main_Area() { case SelectFile: Draw_Print_File_Menu(); break; case PrintProcess: Draw_PrintProcess(); break; case PrintDone: Draw_PrintDone(); break; - case Info: Draw_Info_Menu(); break; #if HAS_ESDIAG case ESDiagProcess: Draw_EndStopDiag(); break; #endif - #if ENABLED(PRINTCOUNTER) - case PrintStatsProcess: Draw_PrintStats(); break; - #endif - case PauseOrStop: Popup_window_PauseOrStop(); break; - #if ENABLED(POWER_LOSS_RECOVERY) - case PwrlossRec: Popup_PowerLossRecovery(); break; - #endif - #if ENABLED(ADVANCED_PAUSE_FEATURE) - case FilamentPurge: Draw_Popup_FilamentPurge(); break; - #endif + case Popup: popupDraw(); break; case Locked: lockScreen.draw(); break; - #if HAS_GCODE_PREVIEW - case ConfirmToPrint: Draw_PreviewFromSD(); break; - #endif case Menu: case SetInt: case SetPInt: @@ -1484,19 +1312,32 @@ void HMI_ReturnScreen() { checkkey = last_checkkey; wait_for_user = false; Draw_Main_Area(); - return; } -void HMI_Popup() { - EncoderState encoder_diffState = get_encoder_state(); - if (encoder_diffState == ENCODER_DIFF_NO) return; - if (encoder_diffState == ENCODER_DIFF_ENTER) { - HMI_ReturnScreen(); +void HMI_WaitForUser() { + get_encoder_state(); + if (!wait_for_user) { + switch (checkkey) { + case PrintDone: + select_page.reset(); + Goto_Main_Menu(); + break; + #if HAS_ONESTEP_LEVELING + case Leveling: + //TERN_(ProUI, ProEx.StopLeveling()); + HMI_ReturnScreen(); + break; + #endif + default: + HMI_ReturnScreen(); + break; + } } } void HMI_Init() { - HMI_SDCardInit(); + DWINUI::Draw_Box(1, Color_Black, {5, 220, DWIN_WIDTH-5, DWINUI::fontHeight()}); + DWINUI::Draw_CenteredString(Color_White, 220, F("Professional Firmware ")); for (uint16_t t = 0; t <= 100; t += 2) { DWINUI::Draw_Icon(ICON_Bar, 15, 260); DWIN_Draw_Rectangle(1, HMI_data.Background_Color, 15 + t * 242 / 100, 260, 257, 280); @@ -1506,12 +1347,6 @@ void HMI_Init() { HMI_SetLanguage(); } -void DWIN_Update() { - EachMomentUpdate(); // Status update - HMI_SDCardUpdate(); // SD card update - DWIN_HandleScreen(); // Rotary encoder update -} - void EachMomentUpdate() { static millis_t next_var_update_ms = 0, next_rts_update_ms = 0, next_status_update_ms = 0; @@ -1538,52 +1373,45 @@ void EachMomentUpdate() { if (PENDING(ms, next_rts_update_ms)) return; next_rts_update_ms = ms + DWIN_SCROLL_UPDATE_INTERVAL; - if (checkkey == PrintProcess) { - // if print done - if (HMI_flag.print_finish) { - HMI_flag.print_finish = false; - TERN_(POWER_LOSS_RECOVERY, recovery.cancel()); - planner.finish_and_disable(); - checkkey = PrintDone; - Draw_PrintDone(); - } - else if (HMI_flag.pause_flag != printingIsPaused()) { - // print status update - HMI_flag.pause_flag = printingIsPaused(); - ICON_ResumeOrPause(); - } - } - - // pause after homing - if (HMI_flag.pause_action && printingIsPaused() && !planner.has_blocks_queued()) { - HMI_flag.pause_action = false; - #if ENABLED(PAUSE_HEAT) - TERN_(HAS_HOTEND, resume_hotend_temp = sdprint ? thermalManager.degTargetHotend(0) : thermalManager.wholeDegHotend(0)); - TERN_(HAS_HEATED_BED, resume_bed_temp = sdprint ? thermalManager.degTargetBed() : thermalManager.wholeDegBed()); - TERN_(HAS_FAN, resume_fan = thermalManager.fan_speed[0]); - #endif - IF_DISABLED(ADVANCED_PAUSE_FEATURE, thermalManager.disable_all_heaters()); - IF_DISABLED(PARK_HEAD_ON_PAUSE, queue.inject(F("G1 F1200 X0 Y0"))); - } - if (checkkey == PrintProcess) { // print process + // Print pause + if (HMI_flag.pause_flag && !HMI_flag.home_flag) { + HMI_flag.pause_flag = false; + if (!HMI_flag.pause_action) { + HMI_flag.pause_action = true; + return ui.pause_print(); + } + } + + // if print done + if (HMI_flag.print_finish && !HMI_flag.home_flag) { + HMI_flag.print_finish = false; + return DWIN_Print_Finished(); + } + + // if print was aborted + if (HMI_flag.abort_flag && !HMI_flag.home_flag) { // Print Stop + HMI_flag.abort_flag = false; + if (!HMI_flag.abort_action) { + HMI_flag.abort_action = true; + ui.abort_print(); + return Goto_PrintDone(); + } + } + duration_t elapsed = print_job_timer.duration(); // print timer if (sdprint && card.isPrinting()) { uint8_t percentDone = card.percentDone(); - static uint8_t last_percentValue = 101; - if (last_percentValue != percentDone) { // print percent - last_percentValue = percentDone; - if (percentDone) { + if (_percent_done != percentDone) { // print percent _percent_done = percentDone; Draw_Print_ProgressBar(); } - } // Estimate remaining time every 20 seconds static millis_t next_remain_time_update = 0; - if (_percent_done > 1 && ELAPSED(ms, next_remain_time_update) && !HMI_flag.heat_flag) { + if (_percent_done > 1 && ELAPSED(ms, next_remain_time_update) && !HMI_flag.heat_flag && !HMI_flag.remain_flag) { _remain_time = (elapsed.value - dwin_heat_time) / (_percent_done * 0.01f) - (elapsed.value - dwin_heat_time); next_remain_time_update += DWIN_REMAIN_TIME_UPDATE_INTERVAL; Draw_Print_ProgressRemain(); @@ -1599,12 +1427,6 @@ void EachMomentUpdate() { } } - else if (dwin_abort_flag && !HMI_flag.home_flag) { // Print Stop - dwin_abort_flag = false; - dwin_zoffset = BABY_Z_VAR; - select_page.set(PAGE_PRINT); - Goto_Main_Menu(); - } #if ENABLED(POWER_LOSS_RECOVERY) else if (DWIN_lcd_sd_status && recovery.dwin_flag) { // resume print before power off @@ -1629,8 +1451,8 @@ void EachMomentUpdate() { DWINUI::Draw_CenteredString(HMI_data.PopupTxt_Color, 70, GET_TEXT_F(MSG_OUTAGE_RECOVERY)); DWINUI::Draw_CenteredString(HMI_data.PopupTxt_Color, 147, F("It looks like the last")); DWINUI::Draw_CenteredString(HMI_data.PopupTxt_Color, 167, F("file was interrupted.")); - DWINUI::Draw_IconWB(ICON_Cancel_E, 26, 280); - DWINUI::Draw_IconWB(ICON_Continue_E, 146, 280); + DWINUI::Draw_Button(BTN_Cancel, 26, 280); + DWINUI::Draw_Button(BTN_Continue, 146, 280); } SdFile *dir = nullptr; const char * const filename = card.diveToFile(true, dir, recovery.info.sd_filename); @@ -1640,35 +1462,26 @@ void EachMomentUpdate() { DWIN_UpdateLCD(); } + void onClick_PowerLossRecovery() { + if (HMI_flag.select_flag) { + queue.inject(F("M1000C")); + select_page.reset(); + return Goto_Main_Menu(); + } + else { + select_print.set(PRINT_SETUP); + queue.inject(F("M1000")); + sdprint = true; + return Goto_PrintProcess(); + } + } + void Goto_PowerLossRecovery() { recovery.dwin_flag = false; LCD_MESSAGE_F(GET_TEXT_F(MSG_CONTINUE_PRINT_JOB)); - HMI_flag.select_flag = false; - Popup_PowerLossRecovery(); - last_checkkey = MainMenu; - checkkey = PwrlossRec; + Goto_Popup(Popup_PowerLossRecovery, onClick_PowerLossRecovery); } - void HMI_PowerlossRecovery() { - EncoderState encoder_diffState = get_encoder_state(); - if (encoder_diffState == ENCODER_DIFF_NO) return; - if (encoder_diffState == ENCODER_DIFF_ENTER) { - if (HMI_flag.select_flag) { - queue.inject(F("M1000C")); - select_page.reset(); - Goto_Main_Menu(); - } - else { - select_print.set(PRINT_SETUP); - queue.inject(F("M1000")); - sdprint = true; - Goto_PrintProcess(); - } - } - else - Draw_Select_Highlight(encoder_diffState != ENCODER_DIFF_CW); - DWIN_UpdateLCD(); - } #endif // POWER_LOSS_RECOVERY @@ -1682,87 +1495,75 @@ void DWIN_HandleScreen() { case SetFloat: HMI_SetFloat(); break; case SetPFloat: HMI_SetPFloat(); break; case SelectFile: HMI_SelectFile(); break; - case Homing: break; - case Leveling: break; case PrintProcess: HMI_Printing(); break; - case PrintDone: HMI_PrintDone(); break; - case PauseOrStop: HMI_PauseOrStop(); break; - case Info: HMI_Popup(); break; - case WaitResponse: HMI_Popup(); break; - #if ENABLED(ADVANCED_PAUSE_FEATURE) - case FilamentPurge: HMI_FilamentPurge(); break; - #endif - case NothingToDo: break; + case Popup: HMI_Popup(); break; + case Leveling: //TERN_(ProUI, HMI_WaitForUser()); + break; case Locked: HMI_LockScreen(); break; - #if ENABLED(POWER_LOSS_RECOVERY) - case PwrlossRec: HMI_PowerlossRecovery(); break; - #endif - #if HAS_GCODE_PREVIEW - case ConfirmToPrint: HMI_ConfirmToPrint(); break; - #endif - #if HAS_ESDIAG - case ESDiagProcess: HMI_Popup(); break; - #endif - #if ENABLED(PRINTCOUNTER) - case PrintStatsProcess: HMI_Popup(); break; - #endif + case PrintDone: + TERN_(HAS_ESDIAG, case ESDiagProcess:) + case WaitResponse: HMI_WaitForUser(); break; + case Homing: + case PidProcess: + case NothingToDo: break; default: break; } } bool IDisPopUp() { // If ID is popup... - return (checkkey == NothingToDo) || - (checkkey == WaitResponse) || - (checkkey == Info) || - (checkkey == Homing) || - (checkkey == Leveling) || - TERN_(HAS_ESDIAG, (checkkey == ESDiagProcess) ||) - TERN_(PRINTCOUNTER, (checkkey == PrintStatsProcess) ||) - (checkkey == PauseOrStop) || - (checkkey == FilamentPurge); + return (checkkey == NothingToDo) + || (checkkey == WaitResponse) + || (checkkey == Homing) + || (checkkey == Leveling) + || (checkkey == PidProcess) + || TERN0(HAS_ESDIAG, (checkkey == ESDiagProcess)) + || (checkkey == Popup); } void HMI_SaveProcessID(const uint8_t id) { if (checkkey != id) { if (!IDisPopUp()) last_checkkey = checkkey; // if previous is not a popup + if ((id == Popup) + || TERN0(HAS_ESDIAG, (id == ESDiagProcess)) + || (id == PrintDone) + || (id == Leveling) + || (id == WaitResponse)) wait_for_user = true; checkkey = id; } } -void DWIN_StartHoming() { +void DWIN_HomingStart() { HMI_flag.home_flag = true; HMI_SaveProcessID(Homing); - Title.ShowCaption(GET_TEXT_F(MSG_LEVEL_BED_HOMING)); - DWIN_Draw_Popup(ICON_BLTouch, GET_TEXT_F(MSG_LEVEL_BED_HOMING), GET_TEXT_F(MSG_PLEASE_WAIT)); + Title.ShowCaption(GET_TEXT_F(MSG_HOMING)); + DWIN_Show_Popup(ICON_BLTouch, GET_TEXT_F(MSG_HOMING), GET_TEXT_F(MSG_PLEASE_WAIT)); } -void DWIN_CompletedHoming() { +void DWIN_HomingDone() { HMI_flag.home_flag = false; dwin_zoffset = TERN0(HAS_BED_PROBE, probe.offset.z); - if (dwin_abort_flag) { - planner.finish_and_disable(); - } - HMI_ReturnScreen(); + if (HMI_flag.abort_action) DWIN_Print_Aborted(); else HMI_ReturnScreen(); } -void DWIN_MeshLevelingStart() { +void DWIN_LevelingStart() { #if HAS_ONESTEP_LEVELING HMI_SaveProcessID(Leveling); Title.ShowCaption(GET_TEXT_F(MSG_BED_LEVELING)); - DWIN_Show_Popup(ICON_AutoLeveling, GET_TEXT_F(MSG_BED_LEVELING), GET_TEXT_F(MSG_PLEASE_WAIT), ICON_Cancel_E); + DWIN_Show_Popup(ICON_AutoLeveling, GET_TEXT_F(MSG_BED_LEVELING), GET_TEXT_F(MSG_PLEASE_WAIT)); #elif ENABLED(MESH_BED_LEVELING) Draw_ManualMesh_Menu(); #endif } -void DWIN_CompletedLeveling() { TERN_(HAS_MESH, DWIN_MeshViewer()); } +void DWIN_LevelingDone() { + TERN_(HAS_ONESTEP_LEVELING, if (planner.leveling_active) Goto_MeshViewer()); +} #if HAS_MESH - void DWIN_MeshUpdate(const int8_t xpos, const int8_t ypos, const float zval) { + void DWIN_MeshUpdate(const int8_t xpos, const int8_t ypos, const_float_t zval) { char msg[33] = ""; char str_1[6] = ""; - sprintf_P(msg, PSTR(S_FMT " %i/%i Z=%s"), GET_TEXT(MSG_PROBING_POINT), xpos, ypos, - dtostrf(zval, 1, 2, str_1)); + sprintf_P(msg, PSTR(S_FMT " %i/%i Z=%s"), GET_TEXT(MSG_PROBING_POINT), xpos, ypos, dtostrf(zval, 1, 2, str_1)); ui.set_status(msg); } #endif @@ -1800,67 +1601,63 @@ void DWIN_PidTuning(pidresult_t result) { } } -// Update filename on print -void DWIN_Print_Header(const char *text = nullptr) { - static char headertxt[31] = ""; // Print header text - - if (text) { - const int8_t size = _MIN((unsigned) 30, strlen_P(text)); - LOOP_L_N(i, size) headertxt[i] = text[i]; - headertxt[size] = '\0'; - } - if (checkkey == PrintProcess || checkkey == PrintDone) { - DWIN_Draw_Rectangle(1, HMI_data.Background_Color, 0, 60, DWIN_WIDTH, 60+16); - DWINUI::Draw_CenteredString(60, headertxt); - } -} - -void Draw_Title(TitleClass* title) { - DWIN_Draw_Rectangle(1, HMI_data.TitleBg_color, 0, 0, DWIN_WIDTH - 1, TITLE_HEIGHT - 1); - if (title->frameid) - DWIN_Frame_AreaCopy(title->frameid, title->frame.left, title->frame.top, title->frame.right, title->frame.bottom, 14, (TITLE_HEIGHT - (title->frame.bottom - title->frame.top)) / 2 - 1); - else - DWIN_Draw_String(false, DWIN_FONT_HEAD, HMI_data.TitleTxt_color, HMI_data.TitleBg_color, 14, (TITLE_HEIGHT - DWINUI::fontHeight(DWIN_FONT_HEAD)) / 2 - 1, title->caption); -} - -void Draw_Menu(MenuClass* menu) { - DWINUI::SetColors(HMI_data.Text_Color, HMI_data.Background_Color); - DWIN_Draw_Rectangle(1, DWINUI::backcolor, 0, TITLE_HEIGHT, DWIN_WIDTH - 1, STATUS_Y - 1); - DWIN_ResetStatusLine(); -} - -// Startup routines -void DWIN_Startup() { - DWINUI::init(); - DWINUI::onCursorDraw = Draw_Menu_Cursor; - DWINUI::onCursorErase = Erase_Menu_Cursor; - DWINUI::onTitleDraw = Draw_Title; - DWINUI::onMenuDraw = Draw_Menu; - DWIN_JPG_ShowAndCache(3); - HMI_SetLanguage(); -} - // Started a Print Job void DWIN_Print_Started(const bool sd) { - sdprint = card.isPrinting() || sd; + sdprint = IS_SD_PRINTING() || sd; _percent_done = 0; _remain_time = 0; + HMI_flag.remain_flag = false; + HMI_flag.pause_flag = false; + HMI_flag.pause_action = false; + HMI_flag.abort_flag = false; + HMI_flag.abort_action = false; HMI_flag.print_finish = false; Goto_PrintProcess(); } +// Pause a print job +void DWIN_Print_Pause() { + ICON_ResumeOrPause(); +} + +// Resume print job +void DWIN_Print_Resume() { + HMI_flag.pause_action = false; + ICON_ResumeOrPause(); + if (printJobOngoing()) { + LCD_MESSAGE(MSG_RESUME_PRINT); + Goto_PrintProcess(); + } +} + // Ended print job void DWIN_Print_Finished() { - if (checkkey == PrintProcess || printingIsActive()) { + if (HMI_flag.abort_flag || checkkey == PrintDone) return; + TERN_(POWER_LOSS_RECOVERY, if (card.isPrinting()) recovery.cancel()); + HMI_flag.pause_flag = false; + wait_for_heatup = false; + planner.finish_and_disable(); thermalManager.cooldown(); - HMI_flag.print_finish = true; - } + Goto_PrintDone(); +} + +// Print was aborted +void DWIN_Print_Aborted() { + TERN_(DEBUG_DWIN, SERIAL_ECHOLNPGM("DWIN_Print_Aborted")); + HMI_flag.abort_action = false; + wait_for_heatup = false; + planner.finish_and_disable(); + thermalManager.cooldown(); + Goto_PrintDone(); } // Progress Bar update void DWIN_Progress_Update() { if (parser.seenval('P')) _percent_done = parser.byteval('P'); - if (parser.seenval('R')) _remain_time = parser.ulongval('R') * 60; + if (parser.seenval('R')) { + _remain_time = parser.ulongval('R') * 60; + HMI_flag.remain_flag = true; + } if (checkkey == PrintProcess) { Draw_Print_ProgressBar(); Draw_Print_ProgressRemain(); @@ -1896,11 +1693,18 @@ void DWIN_SetColorDefaults() { void DWIN_SetDataDefaults() { DWIN_SetColorDefaults(); - DWINUI::SetColors(HMI_data.Text_Color, HMI_data.Background_Color); - TERN_(HAS_HOTEND, HMI_data.HotendPidT = PREHEAT_1_TEMP_HOTEND); - TERN_(HAS_HEATED_BED, HMI_data.BedPidT = PREHEAT_1_TEMP_BED); - TERN_(HAS_HOTEND, HMI_data.PidCycles = 5); - TERN_(PREVENT_COLD_EXTRUSION, HMI_data.ExtMinT = EXTRUDE_MINTEMP); + DWINUI::SetColors(HMI_data.Text_Color, HMI_data.Background_Color, HMI_data.StatusBg_Color); + TERN_(HAS_HOTEND, HMI_data.HotendPidT = PREHEAT_1_TEMP_HOTEND); + TERN_(HAS_HEATED_BED, HMI_data.BedPidT = PREHEAT_1_TEMP_BED); + TERN_(HAS_HOTEND, HMI_data.PidCycles = 5); + #if ENABLED(PREVENT_COLD_EXTRUSION) + HMI_data.ExtMinT = EXTRUDE_MINTEMP; + ApplyExtMinT(); + #endif + #if BOTH(HAS_HEATED_BED, PREHEAT_BEFORE_LEVELING) + HMI_data.BedLevT = PREHEAT_1_TEMP_BED; + #endif + TERN_(BAUD_RATE_GCODE, SetBaud250K()); } void DWIN_StoreSettings(char *buff) { @@ -1912,9 +1716,10 @@ void DWIN_LoadSettings(const char *buff) { memcpy((void *)&HMI_data, buff, _MIN(sizeof(HMI_data), eeprom_data_size)); dwin_zoffset = TERN0(HAS_BED_PROBE, probe.offset.z); if (HMI_data.Text_Color == HMI_data.Background_Color) DWIN_SetColorDefaults(); - DWINUI::SetColors(HMI_data.Text_Color, HMI_data.Background_Color); + DWINUI::SetColors(HMI_data.Text_Color, HMI_data.Background_Color, HMI_data.StatusBg_Color); TERN_(PREVENT_COLD_EXTRUSION, ApplyExtMinT()); feedrate_percentage = 100; + TERN_(BAUD_RATE_GCODE, HMI_SetBaudRate()); #if BOTH(CASE_LIGHT_MENU, CASELIGHT_USES_BRIGHTNESS) // Apply Case light brightness caselight.brightness = HMI_data.CaseLight_Brightness; @@ -1926,6 +1731,37 @@ void DWIN_LoadSettings(const char *buff) { #endif } +// Initialize or re-initialize the LCD +void MarlinUI::init_lcd() { + TERN_(DEBUG_DWIN, SERIAL_ECHOLNPGM("DWIN_Startup")); + DWINUI::init(); + DWIN_JPG_CacheTo1(Language_English); + Encoder_Configuration(); +} + +void DWIN_InitScreen() { + HMI_Init(); // draws boot screen + DWINUI::onCursorDraw = Draw_Menu_Cursor; + DWINUI::onCursorErase = Erase_Menu_Cursor; + DWINUI::onTitleDraw = Draw_Title; + DWINUI::onMenuDraw = Draw_Menu; + DWIN_DrawStatusLine(nullptr); + DWIN_Draw_Dashboard(); + Goto_Main_Menu(); +} + +void MarlinUI::update() { + EachMomentUpdate(); // Status update + HMI_SDCardUpdate(); // SD card update + DWIN_HandleScreen(); // Rotary encoder update +} + +void MarlinUI::refresh() { /* Nothing to see here */ } + +#if HAS_LCD_BRIGHTNESS + void MarlinUI::_set_brightness() { DWIN_LCD_Brightness(backlight ? brightness : 0); } +#endif + void MarlinUI::kill_screen(FSTR_P const lcd_error, FSTR_P const lcd_component) { DWIN_Draw_Popup(ICON_BLTouch, F("Printer killed:"), lcd_error); DWINUI::Draw_CenteredString(HMI_data.PopupTxt_Color, 270, F("Turn off the printer")); @@ -1938,65 +1774,55 @@ void DWIN_RebootScreen() { DWINUI::Draw_CenteredString(Color_White, 220, GET_TEXT_F(MSG_PLEASE_WAIT_REBOOT)); DWIN_UpdateLCD(); delay(500); - DWIN_JPG_ShowAndCache(3); } void DWIN_Redraw_screen() { Draw_Main_Area(); - Draw_Status_Area(false); + hash_changed = true; + DWIN_DrawStatusMessage(); + DWIN_Draw_Dashboard(); } #if ENABLED(ADVANCED_PAUSE_FEATURE) - - void DWIN_Popup_Pause(FSTR_P const fmsg, uint8_t button = 0) { + void DWIN_Popup_Pause(FSTR_P const fmsg, uint8_t button /*= 0*/) { HMI_SaveProcessID(button ? WaitResponse : NothingToDo); - DWIN_Draw_Popup(ICON_BLTouch, GET_TEXT_F(MSG_ADVANCED_PAUSE), fmsg, button); - ui.reset_status(true); + DWIN_Show_Popup(ICON_BLTouch, GET_TEXT_F(MSG_ADVANCED_PAUSE), fmsg, button); } void MarlinUI::pause_show_message(const PauseMessage message, const PauseMode mode/*=PAUSE_MODE_SAME*/, const uint8_t extruder/*=active_extruder*/) { + //if (mode == PAUSE_MODE_SAME) return; + pause_mode = mode; switch (message) { - case PAUSE_MESSAGE_PARKING: DWIN_Popup_Pause(GET_TEXT_F(MSG_PAUSE_PRINT_PARKING)); break; - case PAUSE_MESSAGE_CHANGING: DWIN_Popup_Pause(GET_TEXT_F(MSG_FILAMENT_CHANGE_INIT)); break; - case PAUSE_MESSAGE_UNLOAD: DWIN_Popup_Pause(GET_TEXT_F(MSG_FILAMENT_CHANGE_UNLOAD)); break; - case PAUSE_MESSAGE_WAITING: DWIN_Popup_Pause(GET_TEXT_F(MSG_ADVANCED_PAUSE_WAITING), ICON_Continue_E); break; + case PAUSE_MESSAGE_PARKING: DWIN_Popup_Pause(GET_TEXT_F(MSG_PAUSE_PRINT_PARKING)); break; // M125 + case PAUSE_MESSAGE_CHANGING: DWIN_Popup_Pause(GET_TEXT_F(MSG_FILAMENT_CHANGE_INIT)); break; // pause_print (M125, M600) + case PAUSE_MESSAGE_WAITING: DWIN_Popup_Pause(GET_TEXT_F(MSG_ADVANCED_PAUSE_WAITING), BTN_Continue); break; case PAUSE_MESSAGE_INSERT: DWIN_Popup_Continue(ICON_BLTouch, GET_TEXT_F(MSG_ADVANCED_PAUSE), GET_TEXT_F(MSG_FILAMENT_CHANGE_INSERT)); break; case PAUSE_MESSAGE_LOAD: DWIN_Popup_Pause(GET_TEXT_F(MSG_FILAMENT_CHANGE_LOAD)); break; - case PAUSE_MESSAGE_PURGE: DWIN_Popup_Pause(GET_TEXT_F(MSG_FILAMENT_CHANGE_PURGE)); break; - case PAUSE_MESSAGE_OPTION: DWIN_Popup_FilamentPurge(); break; + case PAUSE_MESSAGE_UNLOAD: DWIN_Popup_Pause(GET_TEXT_F(MSG_FILAMENT_CHANGE_UNLOAD)); break; // Unload of pause and Unload of M702 + case PAUSE_MESSAGE_PURGE: + #if ENABLED(ADVANCED_PAUSE_CONTINUOUS_PURGE) + DWIN_Popup_Pause(GET_TEXT_F(MSG_FILAMENT_CHANGE_CONT_PURGE)); + #else + DWIN_Popup_Pause(GET_TEXT_F(MSG_FILAMENT_CHANGE_PURGE)); + #endif + break; + case PAUSE_MESSAGE_OPTION: Goto_FilamentPurge(); break; case PAUSE_MESSAGE_RESUME: DWIN_Popup_Pause(GET_TEXT_F(MSG_FILAMENT_CHANGE_RESUME)); break; - case PAUSE_MESSAGE_HEAT: DWIN_Popup_Pause(GET_TEXT_F(MSG_FILAMENT_CHANGE_HEAT), ICON_Continue_E); break; + case PAUSE_MESSAGE_HEAT: DWIN_Popup_Pause(GET_TEXT_F(MSG_FILAMENT_CHANGE_HEAT), BTN_Continue); break; case PAUSE_MESSAGE_HEATING: LCD_MESSAGE(MSG_FILAMENT_CHANGE_HEATING); break; - case PAUSE_MESSAGE_STATUS: HMI_ReturnScreen(); break; + case PAUSE_MESSAGE_STATUS: HMI_ReturnScreen(); break; // Exit from Pause, Load and Unload default: break; } } void Draw_Popup_FilamentPurge() { DWIN_Draw_Popup(ICON_BLTouch, GET_TEXT_F(MSG_ADVANCED_PAUSE), F("Purge or Continue?")); - DWINUI::Draw_IconWB(ICON_Confirm_E, 26, 280); - DWINUI::Draw_IconWB(ICON_Continue_E, 146, 280); + DWINUI::Draw_Button(BTN_Confirm, 26, 280); + DWINUI::Draw_Button(BTN_Continue, 146, 280); Draw_Select_Highlight(true); - DWIN_UpdateLCD(); } - // Handle responses such as: - // - Purge More, Continue - // - General "Continue" response - void DWIN_Popup_FilamentPurge() { - HMI_SaveProcessID(FilamentPurge); - pause_menu_response = PAUSE_RESPONSE_WAIT_FOR; - Draw_Popup_FilamentPurge(); - } - - void HMI_FilamentPurge() { - EncoderState encoder_diffState = get_encoder_state(); - if (encoder_diffState == ENCODER_DIFF_NO) return; - if (encoder_diffState == ENCODER_DIFF_CW) - Draw_Select_Highlight(false); - else if (encoder_diffState == ENCODER_DIFF_CCW) - Draw_Select_Highlight(true); - else if (encoder_diffState == ENCODER_DIFF_ENTER) { + void onClick_FilamentPurge() { if (HMI_flag.select_flag) pause_menu_response = PAUSE_RESPONSE_EXTRUDE_MORE; // "Purge More" button else { @@ -2004,7 +1830,10 @@ void DWIN_Redraw_screen() { pause_menu_response = PAUSE_RESPONSE_RESUME_PRINT; // "Continue" button } } - DWIN_UpdateLCD(); + + void Goto_FilamentPurge() { + pause_menu_response = PAUSE_RESPONSE_WAIT_FOR; + Goto_Popup(Draw_Popup_FilamentPurge, onClick_FilamentPurge); } #endif // ADVANCED_PAUSE_FEATURE @@ -2042,39 +1871,10 @@ void HMI_LockScreen() { if (lockScreen.isUnlocked()) DWIN_UnLockScreen(); } -#if HAS_GCODE_PREVIEW - - void HMI_ConfirmToPrint() { - EncoderState encoder_diffState = get_encoder_state(); - if (encoder_diffState == ENCODER_DIFF_NO) return; - if (encoder_diffState == ENCODER_DIFF_CW) - Draw_Select_Highlight(false); - else if (encoder_diffState == ENCODER_DIFF_CCW) - Draw_Select_Highlight(true); - else if (encoder_diffState == ENCODER_DIFF_ENTER) { - if (HMI_flag.select_flag) { // Confirm - card.openAndPrintFile(card.filename); - DWIN_Print_Started(true); - } - else { // Cancel - DWIN_ResetStatusLine(); - checkkey = SelectFile; - Draw_Print_File_Menu(); - } - } - DWIN_UpdateLCD(); - } - -#endif void Goto_ConfirmToPrint() { - #if HAS_GCODE_PREVIEW - HMI_SaveProcessID(ConfirmToPrint); - Draw_PreviewFromSD(); - #else - card.openAndPrintFile(card.filename); - DWIN_Print_Started(true); - #endif + card.openAndPrintFile(card.filename); + DWIN_Print_Started(true); } #if HAS_ESDIAG @@ -2084,103 +1884,11 @@ void Goto_ConfirmToPrint() { } #endif -#if ENABLED(PRINTCOUNTER) - void Draw_PrintStats() { - HMI_SaveProcessID(PrintStatsProcess); - PrintStats.Draw(); - } -#endif - //============================================================================= // NEW MENU SUBSYSTEM //============================================================================= -// On click functions - -// Generic onclick event without draw anything -// process: process id HMI destiny -// lo: low limit -// hi: high limit -// dp: decimal places, 0 for integers -// val: value / scaled value -// LiveUpdate: live update function when the encoder changes -// Apply: update function when the encoder is pressed -void SetOnClick(uint8_t process, const int32_t lo, const int32_t hi, uint8_t dp, const int32_t val, void (*Apply)() = nullptr, void (*LiveUpdate)() = nullptr) { - checkkey = process; - HMI_value.MinValue = lo; - HMI_value.MaxValue = hi; - HMI_value.dp = dp; - HMI_value.Apply = Apply; - HMI_value.LiveUpdate = LiveUpdate; - HMI_value.Value = val; - EncoderRate.enabled = true; -} - -// Generic onclick event for integer values -// process: process id HMI destiny -// lo: scaled low limit -// hi: scaled high limit -// val: value -// LiveUpdate: live update function when the encoder changes -// Apply: update function when the encoder is pressed -void SetValueOnClick(uint8_t process, const int32_t lo, const int32_t hi, const int32_t val, void (*Apply)() = nullptr, void (*LiveUpdate)() = nullptr) { - SetOnClick(process, lo, hi, 0, val, Apply, LiveUpdate); - Draw_Menu_IntValue(HMI_data.Selected_Color, CurrentMenu->line(), 4, HMI_value.Value); -} - -// Generic onclick event for float values -// process: process id HMI destiny -// lo: scaled low limit -// hi: scaled high limit -// val: value -// LiveUpdate: live update function when the encoder changes -// Apply: update function when the encoder is pressed -void SetValueOnClick(uint8_t process, const float lo, const float hi, uint8_t dp, const float val, void (*Apply)() = nullptr, void (*LiveUpdate)() = nullptr) { - const int32_t value = round(val * POW(10, dp)); - SetOnClick(process, lo * POW(10, dp), hi * POW(10, dp), dp, value, Apply, LiveUpdate); - DWINUI::Draw_Signed_Float(HMI_data.Text_Color, HMI_data.Selected_Color, 3, dp, VALX - dp * DWINUI::fontWidth(DWIN_FONT_MENU), MBASE(CurrentMenu->line()), val); -} - -// Generic onclick event for integer values -// lo: scaled low limit -// hi: scaled high limit -// val: value -// LiveUpdate: live update function when the encoder changes -// Apply: update function when the encoder is pressed -inline void SetIntOnClick(const int32_t lo, const int32_t hi, const int32_t val, void (*Apply)() = nullptr, void (*LiveUpdate)() = nullptr) { - SetValueOnClick(SetInt, lo, hi, val, Apply, LiveUpdate); -} - -// Generic onclick event for set pointer to 16 bit uinteger values -// lo: low limit -// hi: high limit -// LiveUpdate: live update function when the encoder changes -// Apply: update function when the encoder is pressed -void SetPIntOnClick(const int32_t lo, const int32_t hi, void (*Apply)() = nullptr, void (*LiveUpdate)() = nullptr) { - HMI_value.P_Int = (int16_t*)static_cast(CurrentMenu->SelectedItem())->value; - const int32_t value = *HMI_value.P_Int; - SetValueOnClick(SetPInt, lo, hi, value, Apply, LiveUpdate); -} - -// Generic onclick event for float values -// process: process id HMI destiny -// lo: low limit -// hi: high limit -// dp: decimal places -// val: value -inline void SetFloatOnClick(const float lo, const float hi, uint8_t dp, const float val, void (*Apply)() = nullptr, void (*LiveUpdate)() = nullptr) { - SetValueOnClick(SetFloat, lo, hi, dp, val, Apply, LiveUpdate); -} - -// Generic onclick event for set pointer to float values -// lo: low limit -// hi: high limit -// LiveUpdate: live update function when the encoder changes -// Apply: update function when the encoder is pressed -void SetPFloatOnClick(const float lo, const float hi, uint8_t dp, void (*Apply)() = nullptr, void (*LiveUpdate)() = nullptr) { - HMI_value.P_Float = (float*)static_cast(CurrentMenu->SelectedItem())->value; - SetValueOnClick(SetPFloat, lo, hi, dp, *HMI_value.P_Float, Apply, LiveUpdate); -} +// Tool functions #if ENABLED(EEPROM_SETTINGS) void WriteEeprom() { @@ -2203,7 +1911,6 @@ void SetPFloatOnClick(const float lo, const float hi, uint8_t dp, void (*Apply)( // Reset Printer void RebootPrinter() { - dwin_abort_flag = true; wait_for_heatup = wait_for_user = false; // Stop waiting for heating/user thermalManager.disable_all_heaters(); planner.finish_and_disable(); @@ -2212,8 +1919,8 @@ void RebootPrinter() { } void Goto_Info_Menu(){ - HMI_SaveProcessID(Info); Draw_Info_Menu(); + HMI_SaveProcessID(WaitResponse); } void Goto_Move_Menu() { @@ -2226,14 +1933,11 @@ void Goto_Move_Menu() { void DisableMotors() { queue.inject(F("M84")); } -void AutoLev() { queue.inject(F("G28Z\nG29")); } // Force to get the current Z home position +void AutoLev() { queue.inject(F("G28XYO\nG28Z\nG29")); } // Force to get the current Z home position void AutoHome() { queue.inject_P(G28_STR); } - void HomeX() { queue.inject(F("G28X")); } - void HomeY() { queue.inject(F("G28Y")); } - void HomeZ() { queue.inject(F("G28Z")); } void SetHome() { @@ -2247,7 +1951,7 @@ void SetHome() { void ApplyZOffset() { TERN_(EEPROM_SETTINGS, settings.save()); } void LiveZOffset() { last_zoffset = dwin_zoffset; - dwin_zoffset = HMI_value.Value / 100.0f; + dwin_zoffset = MenuData.Value / 100.0f; #if EITHER(BABYSTEP_ZPROBE_OFFSET, JUST_BABYSTEP) if (BABYSTEP_ALLOWED()) babystep.add_mm(Z_AXIS, dwin_zoffset - last_zoffset); #endif @@ -2257,6 +1961,24 @@ void SetHome() { SetPFloatOnClick(Z_PROBE_OFFSET_RANGE_MIN, Z_PROBE_OFFSET_RANGE_MAX, 2, ApplyZOffset, LiveZOffset); } #endif + + void SetMoveZto0() { + char cmd[48] = ""; + char str_1[5] = "", str_2[5] = ""; + sprintf_P(cmd, PSTR("G28XYO\nG28Z\nG0X%sY%sF5000\nM420S0\nG0Z0F300"), + #if ENABLED(MESH_BED_LEVELING) + dtostrf(0, 1, 1, str_1), + dtostrf(0, 1, 1, str_2) + #else + dtostrf(X_CENTER, 1, 1, str_1), + dtostrf(Y_CENTER, 1, 1, str_2) + #endif + ); + gcode.process_subcommands_now(cmd); + planner.synchronize(); + LCD_MESSAGE_F("Now adjust Z Offset"); + HMI_AudioFeedback(true); + } #endif #if HAS_PREHEAT @@ -2274,14 +1996,14 @@ void SetLanguage() { } void LiveMove() { - *HMI_value.P_Float = HMI_value.Value / MINUNITMULT; + *MenuData.P_Float = MenuData.Value / MINUNITMULT; if (!planner.is_full()) { planner.synchronize(); planner.buffer_line(current_position, homing_feedrate(HMI_value.axis)); } } void ApplyMoveE() { - last_E = HMI_value.Value / MINUNITMULT; + last_E = MenuData.Value / MINUNITMULT; if (!planner.is_full()) { planner.synchronize(); planner.buffer_line(current_position, MMM_TO_MMS(FEEDRATE_E)); @@ -2294,33 +2016,13 @@ void SetMoveZ() { HMI_value.axis = Z_AXIS; SetPFloatOnClick(Z_MIN_POS, Z_MAX_POS #if HAS_HOTEND void SetMoveE() { #if ENABLED(PREVENT_COLD_EXTRUSION) - if (thermalManager.tooColdToExtrude(0)) { - Popup_Window_ETempTooLow(); - return; - } + if (thermalManager.tooColdToExtrude(0)) + return DWIN_Popup_Confirm(ICON_TempTooLow, GET_TEXT_F(MSG_HOTEND_TOO_COLD), GET_TEXT_F(MSG_PLEASE_PREHEAT)); #endif SetPFloatOnClick(last_E - (EXTRUDE_MAXLENGTH), last_E + (EXTRUDE_MAXLENGTH), UNITFDIGITS, ApplyMoveE); } #endif -void SetMoveZto0() { - char cmd[48] = ""; - char str_1[5] = "", str_2[5] = ""; - sprintf_P(cmd, PSTR("G28Z\nG0X%sY%sF5000\nM420S0\nG0Z0F300"), - #if ENABLED(MESH_BED_LEVELING) - dtostrf(0, 1, 1, str_1), - dtostrf(0, 1, 1, str_2) - #else - dtostrf(X_CENTER, 1, 1, str_1), - dtostrf(Y_CENTER, 1, 1, str_2) - #endif - ); - gcode.process_subcommands_now(cmd); - planner.synchronize(); - LCD_MESSAGE_F("Now adjust Z Offset"); - HMI_AudioFeedback(true); -} - void SetPID(celsius_t t, heater_id_t h) { char cmd[48] = ""; char str_1[5] = "", str_2[5] = ""; @@ -2347,10 +2049,24 @@ void SetPID(celsius_t t, heater_id_t h) { } #endif +#if ENABLED(BAUD_RATE_GCODE) + void HMI_SetBaudRate() { + if (HMI_data.Baud115K) SetBaud115K(); else SetBaud250K(); + } + void SetBaudRate() { + HMI_SetBaudRate(); + Draw_Chkb_Line(CurrentMenu->line(), HMI_data.Baud115K); + DWIN_UpdateLCD(); + } + void SetBaud115K() { queue.inject(F("M575 P0 B115200")); HMI_data.Baud115K = true; } + void SetBaud250K() { queue.inject(F("M575 P0 B250000")); HMI_data.Baud115K = false; } +#endif + #if HAS_LCD_BRIGHTNESS - void ApplyBrightness() { ui.set_brightness(HMI_value.Value); } - void LiveBrightness() { DWIN_LCD_Brightness(HMI_value.Value); } + void ApplyBrightness() { ui.set_brightness(MenuData.Value); } + void LiveBrightness() { DWIN_LCD_Brightness(MenuData.Value); } void SetBrightness() { SetIntOnClick(LCD_BRIGHTNESS_MIN, LCD_BRIGHTNESS_MAX, ui.brightness, ApplyBrightness, LiveBrightness); } + void TurnOffBacklight() { HMI_SaveProcessID(WaitResponse); ui.set_brightness(0); DWIN_Redraw_screen(); } #endif #if ENABLED(CASE_LIGHT_MENU) @@ -2361,7 +2077,7 @@ void SetPID(celsius_t t, heater_id_t h) { DWIN_UpdateLCD(); } #if ENABLED(CASELIGHT_USES_BRIGHTNESS) - void LiveCaseLightBrightness() { HMI_data.CaseLight_Brightness = caselight.brightness = HMI_value.Value; caselight.update_brightness(); } + void LiveCaseLightBrightness() { HMI_data.CaseLight_Brightness = caselight.brightness = MenuData.Value; caselight.update_brightness(); } void SetCaseLightBrightness() { SetIntOnClick(0, 255, caselight.brightness, nullptr, LiveCaseLightBrightness); } #endif #endif @@ -2375,14 +2091,14 @@ void SetPID(celsius_t t, heater_id_t h) { } #endif #if ENABLED(HAS_COLOR_LEDS) - void LiveLedColorR() { leds.color.r = HMI_value.Value; HMI_data.Led_Color = leds.color; leds.update(); } + void LiveLedColorR() { leds.color.r = MenuData.Value; HMI_data.Led_Color = leds.color; leds.update(); } void SetLedColorR() { SetIntOnClick(0, 255, leds.color.r, nullptr, LiveLedColorR); } - void LiveLedColorG() { leds.color.g = HMI_value.Value; HMI_data.Led_Color = leds.color; leds.update(); } + void LiveLedColorG() { leds.color.g = MenuData.Value; HMI_data.Led_Color = leds.color; leds.update(); } void SetLedColorG() { SetIntOnClick(0, 255, leds.color.g, nullptr, LiveLedColorG); } - void LiveLedColorB() { leds.color.b = HMI_value.Value; HMI_data.Led_Color = leds.color; leds.update(); } + void LiveLedColorB() { leds.color.b = MenuData.Value; HMI_data.Led_Color = leds.color; leds.update(); } void SetLedColorB() { SetIntOnClick(0, 255, leds.color.b, nullptr, LiveLedColorB); } #if HAS_WHITE_LED - void LiveLedColorW() { leds.color.w = HMI_value.Value; HMI_data.Led_Color = leds.color; leds.update(); } + void LiveLedColorW() { leds.color.w = MenuData.Value; HMI_data.Led_Color = leds.color; leds.update(); } void SetLedColorW() { SetIntOnClick(0, 255, leds.color.w, nullptr, LiveLedColorW); } #endif #endif @@ -2397,7 +2113,7 @@ void SetPID(celsius_t t, heater_id_t h) { #endif #if HAS_HOME_OFFSET - void ApplyHomeOffset() { set_home_offset(HMI_value.axis, HMI_value.Value / MINUNITMULT); } + void ApplyHomeOffset() { set_home_offset(HMI_value.axis, MenuData.Value / MINUNITMULT); } void SetHomeOffsetX() { HMI_value.axis = X_AXIS; SetPFloatOnClick(-50, 50, UNITFDIGITS, ApplyHomeOffset); } void SetHomeOffsetY() { HMI_value.axis = Y_AXIS; SetPFloatOnClick(-50, 50, UNITFDIGITS, ApplyHomeOffset); } void SetHomeOffsetZ() { HMI_value.axis = Z_AXIS; SetPFloatOnClick( -2, 2, UNITFDIGITS, ApplyHomeOffset); } @@ -2421,25 +2137,22 @@ void SetPID(celsius_t t, heater_id_t h) { DWIN_UpdateLCD(); } #endif -#endif -#if ENABLED(NOZZLE_PARK_FEATURE) - void SetParkPosX() { SetPIntOnClick(0, X_MAX_POS); } - void SetParkPosY() { SetPIntOnClick(0, Y_MAX_POS); } - void SetParkZRaise() { SetPIntOnClick(0, 50); } + #if BOTH(HAS_HEATED_BED, PREHEAT_BEFORE_LEVELING) + void SetBedLevT() { SetPIntOnClick(BED_MINTEMP, BED_MAX_TARGET); } + #endif + #endif #if HAS_FILAMENT_SENSOR void SetRunoutEnable() { runout.reset(); - runout.enabled = !runout.enabled; - Draw_Chkb_Line(CurrentMenu->line(), runout.enabled); + runout.enabled[0] = !runout.enabled[0]; + Draw_Chkb_Line(CurrentMenu->line(), runout.enabled[0]); DWIN_UpdateLCD(); } - #if HAS_FILAMENT_RUNOUT_DISTANCE - void ApplyRunoutDistance() { runout.set_runout_distance(HMI_value.Value / MINUNITMULT); } - void SetRunoutDistance() { SetFloatOnClick(0, 999, UNITFDIGITS, runout.runout_distance(), ApplyRunoutDistance); } - #endif + void ApplyRunoutDistance() { runout.set_runout_distance(MenuData.Value / MINUNITMULT); } + void SetRunoutDistance() { SetFloatOnClick(0, 999, UNITFDIGITS, runout.runout_distance(), ApplyRunoutDistance); } #endif #if ENABLED(ADVANCED_PAUSE_FEATURE) @@ -2454,20 +2167,20 @@ void SetPID(celsius_t t, heater_id_t h) { void RestoreDefaultsColors() { DWIN_SetColorDefaults(); - DWINUI::SetColors(HMI_data.Text_Color, HMI_data.Background_Color); + DWINUI::SetColors(HMI_data.Text_Color, HMI_data.Background_Color, HMI_data.StatusBg_Color); DWIN_Redraw_screen(); } void SelColor() { - HMI_value.P_Int = (int16_t*)static_cast(CurrentMenu->SelectedItem())->value; - HMI_value.Color[0] = GetRColor(*HMI_value.P_Int); // Red - HMI_value.Color[1] = GetGColor(*HMI_value.P_Int); // Green - HMI_value.Color[2] = GetBColor(*HMI_value.P_Int); // Blue + MenuData.P_Int = (int16_t*)static_cast(CurrentMenu->SelectedItem())->value; + HMI_value.Color[0] = GetRColor(*MenuData.P_Int); // Red + HMI_value.Color[1] = GetGColor(*MenuData.P_Int); // Green + HMI_value.Color[2] = GetBColor(*MenuData.P_Int); // Blue Draw_GetColor_Menu(); } void LiveRGBColor() { - HMI_value.Color[CurrentMenu->line() - 2] = HMI_value.Value; + HMI_value.Color[CurrentMenu->line() - 2] = MenuData.Value; uint16_t color = RGB(HMI_value.Color[0], HMI_value.Color[1], HMI_value.Color[2]); DWIN_Draw_Rectangle(1, color, 20, 315, DWIN_WIDTH - 20, 335); } @@ -2477,27 +2190,28 @@ void SetRGBColor() { } void DWIN_ApplyColor() { - *HMI_value.P_Int = RGB(HMI_value.Color[0], HMI_value.Color[1], HMI_value.Color[2]); - DWINUI::SetColors(HMI_data.Text_Color, HMI_data.Background_Color); - Draw_Status_Area(false); + *MenuData.P_Int = RGB(HMI_value.Color[0], HMI_value.Color[1], HMI_value.Color[2]); + DWINUI::SetColors(HMI_data.Text_Color, HMI_data.Background_Color, HMI_data.StatusBg_Color); Draw_SelectColors_Menu(); + hash_changed = true; LCD_MESSAGE_F(GET_TEXT_F(MSG_COLORS_APPLIED)); + DWIN_Draw_Dashboard(); } void SetSpeed() { SetPIntOnClick(MIN_PRINT_SPEED, MAX_PRINT_SPEED); } #if HAS_HOTEND - void ApplyHotendTemp() { thermalManager.setTargetHotend(HMI_value.Value, 0); } + void ApplyHotendTemp() { thermalManager.setTargetHotend(MenuData.Value, 0); } void SetHotendTemp() { SetIntOnClick(MIN_ETEMP, MAX_ETEMP, thermalManager.degTargetHotend(0), ApplyHotendTemp); } #endif #if HAS_HEATED_BED - void ApplyBedTemp() { thermalManager.setTargetBed(HMI_value.Value); } + void ApplyBedTemp() { thermalManager.setTargetBed(MenuData.Value); } void SetBedTemp() { SetIntOnClick(BED_MINTEMP, BED_MAX_TARGET, thermalManager.degTargetBed(), ApplyBedTemp); } #endif #if HAS_FAN - void ApplyFanSpeed() { thermalManager.set_fan_speed(0, HMI_value.Value); } + void ApplyFanSpeed() { thermalManager.set_fan_speed(0, MenuData.Value); } void SetFanSpeed() { SetIntOnClick(0, 255, thermalManager.fan_speed[0], ApplyFanSpeed); } #endif @@ -2531,17 +2245,15 @@ void ApplyFlow() { planner.refresh_e_factor(0); } void SetFlow() { SetPIntOnClick(MIN_PRINT_FLOW, MAX_PRINT_FLOW, ApplyFlow); } // Bed Tramming -void Tram(uint8_t point) { +TERN(HAS_ONESTEP_LEVELING, float, void) Tram(uint8_t point) { char cmd[100] = ""; #if HAS_ONESTEP_LEVELING static bool inLev = false; - if (inLev) return; + float xpos = 0, ypos = 0, zval = 0, margin = 0; char str_1[6] = "", str_2[6] = "", str_3[6] = ""; - #define fmt "X:%s, Y:%s, Z:%s" - float xpos = 0, ypos = 0, zval = 0; - float margin = PROBING_MARGIN; + if (inLev) return NAN; + margin = HMI_data.FullManualTramming ? 30 : PROBING_MARGIN; #else - #define fmt "M420S0\nG28O\nG90\nG0Z5F300\nG0X%iY%iF5000\nG0Z0F300" int16_t xpos = 0, ypos = 0; int16_t margin = 30; #endif @@ -2569,24 +2281,45 @@ void Tram(uint8_t point) { break; } + planner.synchronize(); + #if HAS_ONESTEP_LEVELING - planner.synchronize(); - probe.stow(); - gcode.process_subcommands_now(F("M420S0\nG28O")); - planner.synchronize(); - inLev = true; - zval = probe.probe_at_point(xpos, ypos, PROBE_PT_STOW); - sprintf_P(cmd, PSTR(fmt), - dtostrf(xpos, 1, 1, str_1), - dtostrf(ypos, 1, 1, str_2), - dtostrf(zval, 1, 2, str_3) - ); - ui.set_status(cmd); - inLev = false; + + if (HMI_data.FullManualTramming) { + planner.synchronize(); + sprintf_P(cmd, PSTR("M420S0\nG28O\nG90\nG0Z5F300\nG0X%sY%sF5000\nG0Z0F300"), + dtostrf(xpos, 1, 1, str_1), + dtostrf(ypos, 1, 1, str_2) + ); + queue.inject(cmd); + } + else { + LIMIT(xpos, X_MIN_POS, (X_MAX_POS + probe.offset.x)); + LIMIT(ypos, Y_MIN_POS, (Y_MAX_POS + probe.offset.y)); + probe.stow(); + gcode.process_subcommands_now(F("M420S0\nG28O")); + planner.synchronize(); + inLev = true; + zval = probe.probe_at_point(xpos, ypos, PROBE_PT_STOW); + if (isnan(zval)) + LCD_MESSAGE_F("Position Not Reachable, check offsets"); + else { + sprintf_P(cmd, PSTR("X:%s, Y:%s, Z:%s"), + dtostrf(xpos, 1, 1, str_1), + dtostrf(ypos, 1, 1, str_2), + dtostrf(zval, 1, 2, str_3) + ); + ui.set_status(cmd); + } + inLev = false; + } + return zval; + #else - planner.synchronize(); - sprintf_P(cmd, PSTR(fmt), xpos, ypos); + + sprintf_P(cmd, PSTR("M420S0\nG28O\nG90\nG0Z5F300\nG0X%iY%iF5000\nG0Z0F300"), xpos, ypos); queue.inject(cmd); + #endif } @@ -2596,11 +2329,72 @@ void TramBR() { Tram(2); } void TramBL() { Tram(3); } void TramC () { Tram(4); } +#if HAS_ONESTEP_LEVELING + + void Trammingwizard() { + bed_mesh_t zval = {0}; + if (HMI_data.FullManualTramming) { + LCD_MESSAGE_F("Disable manual tramming"); + return; + } + zval[0][0] = Tram(0); + checkkey = NothingToDo; + MeshViewer.DrawMesh(zval, 2, 2); + zval[1][0] = Tram(1); + MeshViewer.DrawMesh(zval, 2, 2); + zval[1][1] = Tram(2); + MeshViewer.DrawMesh(zval, 2, 2); + zval[0][1] = Tram(3); + MeshViewer.DrawMesh(zval, 2, 2); + char str_1[6] = "", str_2[6] = ""; + ui.status_printf(0, F("Limits minZ: %s, maxZ: %s"), + dtostrf(MeshViewer.min, 1, 2, str_1), + dtostrf(MeshViewer.max, 1, 2, str_2) + ); + if (ABS(MeshViewer.max - MeshViewer.min) < 0.05) { + DWINUI::Draw_CenteredString(140,F("Corners leveled")); + DWINUI::Draw_CenteredString(160,F("Tolerance achieved!")); + } + else { + uint8_t p = 0; + float d, max = 0; + FSTR_P plabel; + LOOP_L_N(x,2) LOOP_L_N(y,2) { + d = ABS(zval[x][y] - MeshViewer.avg); + if (max < d) { + max = d; + p = x + 2 * y; + } + } + switch (p) { + case 0b00 : plabel = GET_TEXT_F(MSG_LEVBED_FL); break; + case 0b01 : plabel = GET_TEXT_F(MSG_LEVBED_FR); break; + case 0b10 : plabel = GET_TEXT_F(MSG_LEVBED_BL); break; + case 0b11 : plabel = GET_TEXT_F(MSG_LEVBED_BR); break; + default : plabel = F(""); break; + } + DWINUI::Draw_CenteredString(130, F("Corners not leveled")); + DWINUI::Draw_CenteredString(150, F("Knob adjustment required")); + DWINUI::Draw_CenteredString(Color_Green, 170, plabel); + } + DWINUI::Draw_Button(BTN_Continue, 86, 305); + checkkey = Menu; + HMI_SaveProcessID(WaitResponse); + } + + void SetManualTramming() { + HMI_data.FullManualTramming = !HMI_data.FullManualTramming; + Draw_Chkb_Line(CurrentMenu->line(), HMI_data.FullManualTramming); + DWIN_UpdateLCD(); + } + +#endif // HAS_ONESTEP_LEVELING + #if ENABLED(MESH_BED_LEVELING) void ManualMeshStart(){ LCD_MESSAGE(MSG_UBL_BUILD_MESH_MENU); - gcode.process_subcommands_now(F("G28Z\nM211S0\nG29S1")); + gcode.process_subcommands_now(F("G28XYO\nG28Z\nM211S0\nG29S1")); planner.synchronize(); #ifdef MANUAL_PROBE_START_Z const uint8_t line = CurrentMenu->line(MMeshMoveZItem->pos); @@ -2609,7 +2403,7 @@ void TramC () { Tram(4); } } void LiveMeshMoveZ() { - *HMI_value.P_Float = HMI_value.Value / POW(10, 2); + *MenuData.P_Float = MenuData.Value / POW(10, 2); if (!planner.is_full()) { planner.synchronize(); planner.buffer_line(current_position, homing_feedrate(Z_AXIS)); @@ -2642,29 +2436,29 @@ void TramC () { Tram(4); } #endif #endif -void ApplyMaxSpeed() { planner.set_max_feedrate(HMI_value.axis, HMI_value.Value / MINUNITMULT); } -void SetMaxSpeedX() { HMI_value.axis = X_AXIS, SetFloatOnClick(MIN_MAXFEEDSPEED, default_max_feedrate[X_AXIS] * 2, UNITFDIGITS, planner.settings.max_feedrate_mm_s[X_AXIS], ApplyMaxSpeed); } -void SetMaxSpeedY() { HMI_value.axis = Y_AXIS, SetFloatOnClick(MIN_MAXFEEDSPEED, default_max_feedrate[Y_AXIS] * 2, UNITFDIGITS, planner.settings.max_feedrate_mm_s[Y_AXIS], ApplyMaxSpeed); } -void SetMaxSpeedZ() { HMI_value.axis = Z_AXIS, SetFloatOnClick(MIN_MAXFEEDSPEED, default_max_feedrate[Z_AXIS] * 2, UNITFDIGITS, planner.settings.max_feedrate_mm_s[Z_AXIS], ApplyMaxSpeed); } +void ApplyMaxSpeed() { planner.set_max_feedrate(HMI_value.axis, MenuData.Value / MINUNITMULT); } +void SetMaxSpeedX() { HMI_value.axis = X_AXIS, SetFloatOnClick(MIN_MAXFEEDSPEED, max_feedrate_edit_values[X_AXIS], UNITFDIGITS, planner.settings.max_feedrate_mm_s[X_AXIS], ApplyMaxSpeed); } +void SetMaxSpeedY() { HMI_value.axis = Y_AXIS, SetFloatOnClick(MIN_MAXFEEDSPEED, max_feedrate_edit_values[Y_AXIS], UNITFDIGITS, planner.settings.max_feedrate_mm_s[Y_AXIS], ApplyMaxSpeed); } +void SetMaxSpeedZ() { HMI_value.axis = Z_AXIS, SetFloatOnClick(MIN_MAXFEEDSPEED, max_feedrate_edit_values[Z_AXIS], UNITFDIGITS, planner.settings.max_feedrate_mm_s[Z_AXIS], ApplyMaxSpeed); } #if HAS_HOTEND - void SetMaxSpeedE() { HMI_value.axis = E_AXIS; SetFloatOnClick(MIN_MAXFEEDSPEED, default_max_feedrate[E_AXIS] * 2, UNITFDIGITS, planner.settings.max_feedrate_mm_s[E_AXIS], ApplyMaxSpeed); } + void SetMaxSpeedE() { HMI_value.axis = E_AXIS; SetFloatOnClick(MIN_MAXFEEDSPEED, max_feedrate_edit_values[E_AXIS], UNITFDIGITS, planner.settings.max_feedrate_mm_s[E_AXIS], ApplyMaxSpeed); } #endif -void ApplyMaxAccel() { planner.set_max_acceleration(HMI_value.axis, HMI_value.Value); } -void SetMaxAccelX() { HMI_value.axis = X_AXIS, SetIntOnClick(MIN_MAXACCELERATION, default_max_acceleration[X_AXIS] * 2, planner.settings.max_acceleration_mm_per_s2[X_AXIS], ApplyMaxAccel); } -void SetMaxAccelY() { HMI_value.axis = Y_AXIS, SetIntOnClick(MIN_MAXACCELERATION, default_max_acceleration[Y_AXIS] * 2, planner.settings.max_acceleration_mm_per_s2[Y_AXIS], ApplyMaxAccel); } -void SetMaxAccelZ() { HMI_value.axis = Z_AXIS, SetIntOnClick(MIN_MAXACCELERATION, default_max_acceleration[Z_AXIS] * 2, planner.settings.max_acceleration_mm_per_s2[Z_AXIS], ApplyMaxAccel); } +void ApplyMaxAccel() { planner.set_max_acceleration(HMI_value.axis, MenuData.Value); } +void SetMaxAccelX() { HMI_value.axis = X_AXIS, SetIntOnClick(MIN_MAXACCELERATION, max_acceleration_edit_values[X_AXIS], planner.settings.max_acceleration_mm_per_s2[X_AXIS], ApplyMaxAccel); } +void SetMaxAccelY() { HMI_value.axis = Y_AXIS, SetIntOnClick(MIN_MAXACCELERATION, max_acceleration_edit_values[Y_AXIS], planner.settings.max_acceleration_mm_per_s2[Y_AXIS], ApplyMaxAccel); } +void SetMaxAccelZ() { HMI_value.axis = Z_AXIS, SetIntOnClick(MIN_MAXACCELERATION, max_acceleration_edit_values[Z_AXIS], planner.settings.max_acceleration_mm_per_s2[Z_AXIS], ApplyMaxAccel); } #if HAS_HOTEND - void SetMaxAccelE() { HMI_value.axis = E_AXIS; SetIntOnClick(MIN_MAXACCELERATION, default_max_acceleration[E_AXIS] * 2, planner.settings.max_acceleration_mm_per_s2[E_AXIS], ApplyMaxAccel); } + void SetMaxAccelE() { HMI_value.axis = E_AXIS; SetIntOnClick(MIN_MAXACCELERATION, max_acceleration_edit_values[E_AXIS], planner.settings.max_acceleration_mm_per_s2[E_AXIS], ApplyMaxAccel); } #endif #if HAS_CLASSIC_JERK - void ApplyMaxJerk() { planner.set_max_jerk(HMI_value.axis, HMI_value.Value / MINUNITMULT); } - void SetMaxJerkX() { HMI_value.axis = X_AXIS, SetFloatOnClick(MIN_MAXJERK, default_max_jerk[X_AXIS] * 2, UNITFDIGITS, planner.max_jerk[X_AXIS], ApplyMaxJerk); } - void SetMaxJerkY() { HMI_value.axis = Y_AXIS, SetFloatOnClick(MIN_MAXJERK, default_max_jerk[Y_AXIS] * 2, UNITFDIGITS, planner.max_jerk[Y_AXIS], ApplyMaxJerk); } - void SetMaxJerkZ() { HMI_value.axis = Z_AXIS, SetFloatOnClick(MIN_MAXJERK, default_max_jerk[Z_AXIS] * 2, UNITFDIGITS, planner.max_jerk[Z_AXIS], ApplyMaxJerk); } + void ApplyMaxJerk() { planner.set_max_jerk(HMI_value.axis, MenuData.Value / MINUNITMULT); } + void SetMaxJerkX() { HMI_value.axis = X_AXIS, SetFloatOnClick(MIN_MAXJERK, max_jerk_edit_values[X_AXIS], UNITFDIGITS, planner.max_jerk[X_AXIS], ApplyMaxJerk); } + void SetMaxJerkY() { HMI_value.axis = Y_AXIS, SetFloatOnClick(MIN_MAXJERK, max_jerk_edit_values[Y_AXIS], UNITFDIGITS, planner.max_jerk[Y_AXIS], ApplyMaxJerk); } + void SetMaxJerkZ() { HMI_value.axis = Z_AXIS, SetFloatOnClick(MIN_MAXJERK, max_jerk_edit_values[Z_AXIS], UNITFDIGITS, planner.max_jerk[Z_AXIS], ApplyMaxJerk); } #if HAS_HOTEND - void SetMaxJerkE() { HMI_value.axis = E_AXIS; SetFloatOnClick(MIN_MAXJERK, default_max_jerk[E_AXIS] * 2, UNITFDIGITS, planner.max_jerk[E_AXIS], ApplyMaxJerk); } + void SetMaxJerkE() { HMI_value.axis = E_AXIS; SetFloatOnClick(MIN_MAXJERK, max_jerk_edit_values[E_AXIS], UNITFDIGITS, planner.max_jerk[E_AXIS], ApplyMaxJerk); } #endif #endif @@ -2683,21 +2477,21 @@ void SetStepsZ() { HMI_value.axis = Z_AXIS, SetPFloatOnClick( MIN_STEP, MAX_STEP void SetPidCycles() { SetPIntOnClick(3, 50); } void SetKp() { SetPFloatOnClick(0, 1000, 2); } void ApplyPIDi() { - *HMI_value.P_Float = scalePID_i(HMI_value.Value / POW(10, 2)); + *MenuData.P_Float = scalePID_i(MenuData.Value / POW(10, 2)); thermalManager.updatePID(); } void ApplyPIDd() { - *HMI_value.P_Float = scalePID_d(HMI_value.Value / POW(10, 2)); + *MenuData.P_Float = scalePID_d(MenuData.Value / POW(10, 2)); thermalManager.updatePID(); } void SetKi() { - HMI_value.P_Float = (float*)static_cast(CurrentMenu->SelectedItem())->value; - const float value = unscalePID_i(*HMI_value.P_Float); + MenuData.P_Float = (float*)static_cast(CurrentMenu->SelectedItem())->value; + const float value = unscalePID_i(*MenuData.P_Float); SetFloatOnClick(0, 1000, 2, value, ApplyPIDi); } void SetKd() { - HMI_value.P_Float = (float*)static_cast(CurrentMenu->SelectedItem())->value; - const float value = unscalePID_d(*HMI_value.P_Float); + MenuData.P_Float = (float*)static_cast(CurrentMenu->SelectedItem())->value; + const float value = unscalePID_d(*MenuData.P_Float); SetFloatOnClick(0, 1000, 2, value, ApplyPIDd); } #endif @@ -2709,62 +2503,7 @@ void SetStepsZ() { HMI_value.axis = Z_AXIS, SetPFloatOnClick( MIN_STEP, MAX_STEP void SetRecoverSpeed() { SetPFloatOnClick( 1, 90, UNITFDIGITS); }; #endif -// Menuitem Drawing functions ================================================= - -void onDrawMenuItem(MenuItemClass* menuitem, int8_t line) { - if (menuitem->icon) DWINUI::Draw_Icon(menuitem->icon, ICOX, MBASE(line) - 3); - if (menuitem->frameid) - DWIN_Frame_AreaCopy(menuitem->frameid, menuitem->frame.left, menuitem->frame.top, menuitem->frame.right, menuitem->frame.bottom, LBLX, MBASE(line)); - else if (menuitem->caption) - DWINUI::Draw_String(LBLX, MBASE(line) - 1, menuitem->caption); - DWIN_Draw_HLine(HMI_data.SplitLine_Color, 16, MYPOS(line + 1), 240); -} - -void onDrawSubMenu(MenuItemClass* menuitem, int8_t line) { - onDrawMenuItem(menuitem, line); - DWINUI::Draw_Icon(ICON_More, VALX + 16, MBASE(line) - 3); -} - -void onDrawIntMenu(MenuItemClass* menuitem, int8_t line, uint16_t value) { - onDrawMenuItem(menuitem, line); - Draw_Menu_IntValue(HMI_data.Background_Color, line, 4, value); -} - -void onDrawPIntMenu(MenuItemClass* menuitem, int8_t line) { - const uint16_t value = *(uint16_t*)static_cast(menuitem)->value; - onDrawIntMenu(menuitem, line, value); -} - -void onDrawPInt8Menu(MenuItemClass* menuitem, int8_t line) { - const uint8_t value = *(uint8_t*)static_cast(menuitem)->value; - onDrawIntMenu(menuitem, line, value); -} - -void onDrawPInt32Menu(MenuItemClass* menuitem, int8_t line) { - const uint32_t value = *(uint32_t*)static_cast(menuitem)->value; - onDrawIntMenu(menuitem, line, value); -} - -void onDrawFloatMenu(MenuItemClass* menuitem, int8_t line, uint8_t dp, const float value) { - onDrawMenuItem(menuitem, line); - DWINUI::Draw_Signed_Float(HMI_data.Text_Color, HMI_data.Background_Color, 3, dp, VALX - dp * DWINUI::fontWidth(DWIN_FONT_MENU), MBASE(line), value); -} - -void onDrawPFloatMenu(MenuItemClass* menuitem, int8_t line) { - const float value = *(float*)static_cast(menuitem)->value; - const int8_t dp = UNITFDIGITS; - onDrawFloatMenu(menuitem, line, dp, value); -} - -void onDrawPFloat2Menu(MenuItemClass* menuitem, int8_t line) { - const float value = *(float*)static_cast(menuitem)->value; - onDrawFloatMenu(menuitem, line, 2, value); -} - -void onDrawChkbMenu(MenuItemClass* menuitem, int8_t line, bool checked) { - onDrawMenuItem(menuitem, line); - Draw_Chkb_Line(line, checked); -} +// Special Menuitem Drawing functions ================================================= void onDrawBack(MenuItemClass* menuitem, int8_t line) { if (HMI_IsChinese()) menuitem->SetFrame(1, 129, 72, 156, 84); @@ -2882,6 +2621,10 @@ void onDrawLanguage(MenuItemClass* menuitem, int8_t line) { void onDrawPwrLossR(MenuItemClass* menuitem, int8_t line) { onDrawChkbMenu(menuitem, line, recovery.enabled); } #endif +#if ENABLED(BAUD_RATE_GCODE) + void onDrawBaudrate(MenuItemClass* menuitem, int8_t line) { onDrawChkbMenu(menuitem, line, HMI_data.Baud115K); } +#endif + #if ENABLED(CASE_LIGHT_MENU) void onDrawCaseLight(MenuItemClass* menuitem, int8_t line) { onDrawChkbMenu(menuitem, line, caselight.on); } #endif @@ -2924,7 +2667,7 @@ void onDrawGetColorItem(MenuItemClass* menuitem, int8_t line) { } #if HAS_FILAMENT_SENSOR - void onDrawRunoutEnable(MenuItemClass* menuitem, int8_t line) { onDrawChkbMenu(menuitem, line, runout.enabled); } + void onDrawRunoutEnable(MenuItemClass* menuitem, int8_t line) { onDrawChkbMenu(menuitem, line, runout.enabled[0]); } #endif void onDrawPIDi(MenuItemClass* menuitem, int8_t line) { onDrawFloatMenu(menuitem, line, 2, unscalePID_i(*(float*)static_cast(menuitem)->value)); } @@ -3172,137 +2915,9 @@ void onDrawStepsZ(MenuItemClass* menuitem, int8_t line) { } #endif -// HMI Control functions ====================================================== - -// Generic menu control using the encoder -void HMI_Menu() { - EncoderState encoder_diffState = get_encoder_state(); - if (encoder_diffState == ENCODER_DIFF_NO) return; - if (CurrentMenu) { - if (encoder_diffState == ENCODER_DIFF_ENTER) - CurrentMenu->onClick(); - else - CurrentMenu->onScroll(encoder_diffState == ENCODER_DIFF_CW); - } -} - -// Get an integer value using the encoder without draw anything -// lo: low limit -// hi: high limit -// Return value: -// 0 : no change -// 1 : live change -// 2 : apply change -int8_t HMI_GetIntNoDraw(const int32_t lo, const int32_t hi) { - EncoderState encoder_diffState = Encoder_ReceiveAnalyze(); - if (encoder_diffState != ENCODER_DIFF_NO) { - if (Apply_Encoder(encoder_diffState, HMI_value.Value)) { - EncoderRate.enabled = false; - checkkey = Menu; - return 2; - } - LIMIT(HMI_value.Value, lo, hi); - return 1; - } - return 0; -} - -// Get an integer value using the encoder -// lo: low limit -// hi: high limit -// Return value: -// 0 : no change -// 1 : live change -// 2 : apply change -int8_t HMI_GetInt(const int32_t lo, const int32_t hi) { - EncoderState encoder_diffState = Encoder_ReceiveAnalyze(); - if (encoder_diffState != ENCODER_DIFF_NO) { - if (Apply_Encoder(encoder_diffState, HMI_value.Value)) { - EncoderRate.enabled = false; - DWINUI::Draw_Int(HMI_data.Text_Color, HMI_data.Background_Color, 4 , VALX, MBASE(CurrentMenu->line()) - 1, HMI_value.Value); - checkkey = Menu; - return 2; - } - LIMIT(HMI_value.Value, lo, hi); - DWINUI::Draw_Int(HMI_data.Text_Color, HMI_data.Selected_Color, 4 , VALX, MBASE(CurrentMenu->line()) - 1, HMI_value.Value); - return 1; - } - return 0; -} - -// Set an integer using the encoder -void HMI_SetInt() { - int8_t val = HMI_GetInt(HMI_value.MinValue, HMI_value.MaxValue); - switch (val) { - case 0: return; break; - case 1: if (HMI_value.LiveUpdate) HMI_value.LiveUpdate(); break; - case 2: if (HMI_value.Apply) HMI_value.Apply(); break; - } -} - -// Set an integer without drawing -void HMI_SetIntNoDraw() { - int8_t val = HMI_GetIntNoDraw(HMI_value.MinValue, HMI_value.MaxValue); - switch (val) { - case 0: return; break; - case 1: if (HMI_value.LiveUpdate) HMI_value.LiveUpdate(); break; - case 2: if (HMI_value.Apply) HMI_value.Apply(); break; - } -} - -// Set an integer pointer variable using the encoder -void HMI_SetPInt() { - int8_t val = HMI_GetInt(HMI_value.MinValue, HMI_value.MaxValue); - switch (val) { - case 0: return; - case 1: if (HMI_value.LiveUpdate) HMI_value.LiveUpdate(); break; - case 2: *HMI_value.P_Int = HMI_value.Value; if (HMI_value.Apply) HMI_value.Apply(); break; - } -} - -// Get a scaled float value using the encoder -// dp: decimal places -// lo: scaled low limit -// hi: scaled high limit -// Return value: -// 0 : no change -// 1 : live change -// 2 : apply change -int8_t HMI_GetFloat(uint8_t dp, int32_t lo, int32_t hi) { - EncoderState encoder_diffState = Encoder_ReceiveAnalyze(); - if (encoder_diffState != ENCODER_DIFF_NO) { - if (Apply_Encoder(encoder_diffState, HMI_value.Value)) { - EncoderRate.enabled = false; - DWINUI::Draw_Signed_Float(HMI_data.Text_Color, HMI_data.Background_Color, 3, dp, VALX - dp * DWINUI::fontWidth(DWIN_FONT_MENU), MBASE(CurrentMenu->line()), HMI_value.Value / POW(10, dp)); - checkkey = Menu; - return 2; - } - LIMIT(HMI_value.Value, lo, hi); - DWINUI::Draw_Signed_Float(HMI_data.Text_Color, HMI_data.Selected_Color, 3, dp, VALX - dp * DWINUI::fontWidth(DWIN_FONT_MENU), MBASE(CurrentMenu->line()), HMI_value.Value / POW(10, dp)); - return 1; - } - return 0; -} - -// Set a scaled float using the encoder -void HMI_SetFloat() { - const int8_t val = HMI_GetFloat(HMI_value.dp, HMI_value.MinValue, HMI_value.MaxValue); - switch (val) { - case 0: return; - case 1: if (HMI_value.LiveUpdate) HMI_value.LiveUpdate(); break; - case 2: if (HMI_value.Apply) HMI_value.Apply(); break; - } -} - -// Set a scaled float pointer variable using the encoder -void HMI_SetPFloat() { - const int8_t val = HMI_GetFloat(HMI_value.dp, HMI_value.MinValue, HMI_value.MaxValue); - switch (val) { - case 0: return; - case 1: if (HMI_value.LiveUpdate) HMI_value.LiveUpdate(); break; - case 2: *HMI_value.P_Float = HMI_value.Value / POW(10, HMI_value.dp); if (HMI_value.Apply) HMI_value.Apply(); break; - } -} +#if HAS_ONESTEP_LEVELING + void onDrawManualTramming(MenuItemClass* menuitem, int8_t line) { onDrawChkbMenu(menuitem, line, HMI_data.FullManualTramming); } +#endif // Menu Creation and Drawing functions ====================================================== @@ -3359,6 +2974,7 @@ void Draw_Prepare_Menu() { MENU_ITEM(ICON_Cool, GET_TEXT_F(MSG_COOLDOWN), onDrawCooldown, DoCoolDown); MENU_ITEM(ICON_Language, PSTR(GET_TEXT_F(MSG_UI_LANGUAGE)), onDrawLanguage, SetLanguage); } + ui.reset_status(true); CurrentMenu->draw(); } @@ -3369,13 +2985,17 @@ void Draw_Tramming_Menu() { if (CurrentMenu != TrammingMenu) { CurrentMenu = TrammingMenu; SetMenuTitle({0}, GET_TEXT_F(MSG_BED_TRAMMING)); // TODO: Chinese, English "Bed Tramming" JPG - DWINUI::MenuItemsPrepare(6); + DWINUI::MenuItemsPrepare(8); MENU_ITEM(ICON_Back, GET_TEXT_F(MSG_BUTTON_BACK), onDrawBack, Draw_Prepare_Menu); MENU_ITEM(ICON_Axis, GET_TEXT_F(MSG_LEVBED_FL), onDrawMenuItem, TramFL); MENU_ITEM(ICON_Axis, GET_TEXT_F(MSG_LEVBED_FR), onDrawMenuItem, TramFR); MENU_ITEM(ICON_Axis, GET_TEXT_F(MSG_LEVBED_BR), onDrawMenuItem, TramBR); MENU_ITEM(ICON_Axis, GET_TEXT_F(MSG_LEVBED_BL), onDrawMenuItem, TramBL); MENU_ITEM(ICON_Axis, GET_TEXT_F(MSG_LEVBED_C ), onDrawMenuItem, TramC ); + #if HAS_ONESTEP_LEVELING + MENU_ITEM(ICON_ProbeSet, F("Bed tramming wizard"), onDrawMenuItem, Trammingwizard); + MENU_ITEM(ICON_ProbeSet, GET_TEXT_F(MSG_BED_TRAMMING_MANUAL), onDrawManualTramming, SetManualTramming); + #endif } CurrentMenu->draw(); } @@ -3386,7 +3006,7 @@ void Draw_Control_Menu() { if (CurrentMenu != ControlMenu) { CurrentMenu = ControlMenu; SetMenuTitle({103, 1, 28, 14}, GET_TEXT_F(MSG_CONTROL)); - DWINUI::MenuItemsPrepare(8); + DWINUI::MenuItemsPrepare(10); MENU_ITEM(ICON_Back, GET_TEXT_F(MSG_BUTTON_BACK), onDrawBack, Goto_Main_Menu); #if ENABLED(CASE_LIGHT_MENU) #if ENABLED(CASELIGHT_USES_BRIGHTNESS) @@ -3408,6 +3028,7 @@ void Draw_Control_Menu() { MENU_ITEM(ICON_Reboot, GET_TEXT_F(MSG_RESET_PRINTER), onDrawMenuItem, RebootPrinter); MENU_ITEM(ICON_Info, GET_TEXT_F(MSG_INFO_SCREEN), onDrawInfoSubMenu, Goto_Info_Menu); } + ui.reset_status(true); CurrentMenu->draw(); } @@ -3417,8 +3038,11 @@ void Draw_AdvancedSettings_Menu() { if (CurrentMenu != AdvancedSettings) { CurrentMenu = AdvancedSettings; SetMenuTitle({0}, GET_TEXT_F(MSG_ADVANCED_SETTINGS)); // TODO: Chinese, English "Advanced Settings" JPG - DWINUI::MenuItemsPrepare(15); + DWINUI::MenuItemsPrepare(17); MENU_ITEM(ICON_Back, GET_TEXT_F(MSG_BUTTON_BACK), onDrawBack, Goto_Main_Menu); + #if ENABLED(EEPROM_SETTINGS) + MENU_ITEM(ICON_WriteEEPROM, GET_TEXT_F(MSG_STORE_EEPROM), onDrawMenuItem, WriteEeprom); + #endif #if HAS_HOME_OFFSET MENU_ITEM(ICON_HomeOffset, GET_TEXT_F(MSG_SET_HOME_OFFSETS), onDrawSubMenu, Draw_HomeOffset_Menu); #endif @@ -3437,6 +3061,9 @@ void Draw_AdvancedSettings_Menu() { #if ENABLED(POWER_LOSS_RECOVERY) MENU_ITEM(ICON_Pwrlossr, GET_TEXT_F(MSG_OUTAGE_RECOVERY), onDrawPwrLossR, SetPwrLossr); #endif + #if ENABLED(BAUD_RATE_GCODE) + MENU_ITEM(ICON_SetBaudRate, F("115K baud"), onDrawBaudrate, SetBaudRate); + #endif #if HAS_LCD_BRIGHTNESS EDIT_ITEM(ICON_Brightness, GET_TEXT_F(MSG_BRIGHTNESS), onDrawPInt8Menu, SetBrightness, &ui.brightness); #endif @@ -3451,11 +3078,12 @@ void Draw_AdvancedSettings_Menu() { MENU_ITEM(ICON_ESDiag, F("End-stops diag."), onDrawSubMenu, Draw_EndStopDiag); #endif #if ENABLED(PRINTCOUNTER) - MENU_ITEM(ICON_PrintStats, GET_TEXT_F(MSG_INFO_STATS_MENU), onDrawSubMenu, Draw_PrintStats); + MENU_ITEM(ICON_PrintStats, GET_TEXT_F(MSG_INFO_STATS_MENU), onDrawSubMenu, Goto_PrintStats); MENU_ITEM(ICON_PrintStatsReset, GET_TEXT_F(MSG_INFO_PRINT_COUNT_RESET), onDrawSubMenu, PrintStats.Reset); #endif MENU_ITEM(ICON_Lock, GET_TEXT_F(MSG_LOCKSCREEN), onDrawMenuItem, DWIN_LockScreen); } + ui.reset_status(true); CurrentMenu->draw(); } @@ -3502,11 +3130,14 @@ void Draw_Move_Menu() { if (CurrentMenu != ProbeSetMenu) { CurrentMenu = ProbeSetMenu; SetMenuTitle({0}, GET_TEXT_F(MSG_ZPROBE_SETTINGS)); // TODO: Chinese, English "Probe Settings" JPG - DWINUI::MenuItemsPrepare(8); + DWINUI::MenuItemsPrepare(9); MENU_ITEM(ICON_Back, GET_TEXT_F(MSG_BUTTON_BACK), onDrawBack, Draw_AdvancedSettings_Menu); EDIT_ITEM(ICON_ProbeOffsetX, GET_TEXT_F(MSG_ZPROBE_XOFFSET), onDrawPFloatMenu, SetProbeOffsetX, &probe.offset.x); EDIT_ITEM(ICON_ProbeOffsetY, GET_TEXT_F(MSG_ZPROBE_YOFFSET), onDrawPFloatMenu, SetProbeOffsetY, &probe.offset.y); EDIT_ITEM(ICON_ProbeOffsetZ, GET_TEXT_F(MSG_ZPROBE_ZOFFSET), onDrawPFloat2Menu, SetProbeOffsetZ, &probe.offset.z); + #if BOTH(HAS_HEATED_BED, PREHEAT_BEFORE_LEVELING) + EDIT_ITEM(ICON_Temperature, GET_TEXT_F(MSG_UBL_SET_TEMP_BED), onDrawPIntMenu, SetBedLevT, &HMI_data.BedLevT); + #endif #ifdef BLTOUCH_HS_MODE MENU_ITEM(ICON_HSMode, F("Enable HS mode"), onDrawHSMode, SetHSMode); #endif @@ -3530,9 +3161,7 @@ void Draw_Move_Menu() { #if HAS_FILAMENT_SENSOR MENU_ITEM(ICON_Runout, GET_TEXT_F(MSG_RUNOUT_ENABLE), onDrawRunoutEnable, SetRunoutEnable); #endif - #if HAS_FILAMENT_RUNOUT_DISTANCE - EDIT_ITEM(ICON_Runout, F("Runout Distance"), onDrawPFloatMenu, SetRunoutDistance, &runout.runout_distance()); - #endif + EDIT_ITEM(ICON_Runout, F("Runout Distance"), onDrawPFloatMenu, SetRunoutDistance, &runout.runout_distance()); #if ENABLED(PREVENT_COLD_EXTRUSION) EDIT_ITEM(ICON_ExtrudeMinT, F("Extrude Min Temp."), onDrawPIntMenu, SetExtMinT, &HMI_data.ExtMinT); #endif @@ -3596,7 +3225,7 @@ void Draw_GetColor_Menu() { MENU_ITEM(2, GET_TEXT_F(MSG_COLORS_BLUE), onDrawGetColorItem, SetRGBColor); } CurrentMenu->draw(); - DWIN_Draw_Rectangle(1, *HMI_value.P_Int, 20, 315, DWIN_WIDTH - 20, 335); + DWIN_Draw_Rectangle(1, *MenuData.P_Int, 20, 315, DWIN_WIDTH - 20, 335); } #if BOTH(CASE_LIGHT_MENU, CASELIGHT_USES_BRIGHTNESS) @@ -3646,7 +3275,7 @@ void Draw_Tune_Menu() { if (CurrentMenu != TuneMenu) { CurrentMenu = TuneMenu; SetMenuTitle({73, 2, 28, 12}, GET_TEXT_F(MSG_TUNE)); // TODO: Chinese, English "Tune" JPG - DWINUI::MenuItemsPrepare(14); + DWINUI::MenuItemsPrepare(16); MENU_ITEM(ICON_Back, GET_TEXT_F(MSG_BUTTON_BACK), onDrawBack, Goto_PrintProcess); #if ENABLED(CASE_LIGHT_MENU) MENU_ITEM(ICON_CaseLight, GET_TEXT_F(MSG_CASE_LIGHT), onDrawCaseLight, SetCaseLight); @@ -3679,6 +3308,7 @@ void Draw_Tune_Menu() { MENU_ITEM(ICON_Lock, GET_TEXT_F(MSG_LOCKSCREEN), onDrawMenuItem, DWIN_LockScreen); #if HAS_LCD_BRIGHTNESS EDIT_ITEM(ICON_Brightness, GET_TEXT_F(MSG_BRIGHTNESS), onDrawPInt8Menu, SetBrightness, &ui.brightness); + MENU_ITEM(ICON_Brightness, GET_TEXT_F(MSG_BRIGHTNESS_OFF), onDrawMenuItem, TurnOffBacklight); #endif } CurrentMenu->draw(); @@ -3974,4 +3604,4 @@ void Draw_Steps_Menu() { } #endif -#endif // DWIN_CREALITY_LCD_ENHANCED +#endif // DWIN_LCD_PROUI diff --git a/Marlin/src/lcd/e3v2/proui/dwin.h b/Marlin/src/lcd/e3v2/proui/dwin.h index 04ac1590eb..b61ed846df 100644 --- a/Marlin/src/lcd/e3v2/proui/dwin.h +++ b/Marlin/src/lcd/e3v2/proui/dwin.h @@ -22,32 +22,18 @@ #pragma once /** - * Enhanced DWIN implementation + * DWIN Enhanced implementation for PRO UI * Author: Miguel A. Risco-Castillo (MRISCOC) - * Version: 3.9.2 - * date: 2021/11/21 - * - * Based on the original code provided by Creality under GPL + * Version: 3.15.2 + * Date: 2022/03/01 */ -#include "../../../inc/MarlinConfigPre.h" +#include "dwin_defines.h" #include "dwinui.h" #include "../common/encoder.h" #include "../../../libs/BL24CXX.h" -#if ANY(AUTO_BED_LEVELING_BILINEAR, AUTO_BED_LEVELING_LINEAR, AUTO_BED_LEVELING_3POINT) && DISABLED(PROBE_MANUALLY) - #define HAS_ONESTEP_LEVELING 1 -#endif - -#if !HAS_BED_PROBE && ENABLED(BABYSTEPPING) - #define JUST_BABYSTEP 1 -#endif - -#if ANY(BABYSTEPPING, HAS_BED_PROBE, HAS_WORKSPACE_OFFSET) - #define HAS_ZOFFSET_ITEM 1 -#endif - -#include "dwin_defines.h" +#include "../../../inc/MarlinConfig.h" enum processID : uint8_t { // Process ID @@ -60,23 +46,16 @@ enum processID : uint8_t { SetPFloat, SelectFile, PrintProcess, - PrintDone, - PwrlossRec, - Reboot, - Info, - ConfirmToPrint, - - // Popup Windows - Homing, + Popup, Leveling, - PidProcess, - ESDiagProcess, - PrintStatsProcess, - PauseOrStop, - FilamentPurge, - WaitResponse, Locked, - NothingToDo, + Reboot, + PrintDone, + ESDiagProcess, + WaitResponse, + Homing, + PidProcess, + NothingToDo }; enum pidresult_t : uint8_t { @@ -93,24 +72,18 @@ enum pidresult_t : uint8_t { typedef struct { int8_t Color[3]; // Color components - uint16_t pidgrphpoints = 0; pidresult_t pidresult = PID_DONE; int8_t Preheat = 0; // Material Select 0: PLA, 1: ABS, 2: Custom AxisEnum axis = X_AXIS; // Axis Select - int32_t MaxValue = 0; // Auxiliar max integer/scaled float value - int32_t MinValue = 0; // Auxiliar min integer/scaled float value - int8_t dp = 0; // Auxiliar decimal places - int32_t Value = 0; // Auxiliar integer / scaled float value - int16_t *P_Int = nullptr; // Auxiliar pointer to 16 bit integer variable - float *P_Float = nullptr; // Auxiliar pointer to float variable - void (*Apply)() = nullptr; // Auxiliar apply function - void (*LiveUpdate)() = nullptr; // Auxiliar live update function } HMI_value_t; typedef struct { uint8_t language; + bool remain_flag:1; // remain was override by M73 bool pause_flag:1; // printing is paused bool pause_action:1; // flag a pause action + bool abort_flag:1; // printing is aborting + bool abort_action:1; // flag a aborting action bool print_finish:1; // print was finished bool select_flag:1; // Popup button selected bool home_flag:1; // homing in course @@ -126,9 +99,6 @@ extern millis_t dwin_heat_time; #if HAS_HOTEND || HAS_HEATED_BED void DWIN_Popup_Temperature(const bool toohigh); #endif -#if HAS_HOTEND - void Popup_Window_ETempTooLow(); -#endif #if ENABLED(POWER_LOSS_RECOVERY) void Popup_PowerLossRecovery(); #endif @@ -143,50 +113,64 @@ void Goto_Main_Menu(); void Goto_Info_Menu(); void Goto_PowerLossRecovery(); void Goto_ConfirmToPrint(); -void Draw_Status_Area(const bool with_update); // Status Area +void DWIN_Draw_Dashboard(const bool with_update); // Status Area void Draw_Main_Area(); // Redraw main area; void DWIN_Redraw_screen(); // Redraw all screen elements -void HMI_StartFrame(const bool with_update); // Prepare the menu view void HMI_MainMenu(); // Main process screen void HMI_SelectFile(); // File page void HMI_Printing(); // Print page void HMI_ReturnScreen(); // Return to previous screen before popups void ApplyExtMinT(); void HMI_SetLanguageCache(); // Set the languaje image cache +void RebootPrinter(); +#if ENABLED(BAUD_RATE_GCODE) + void HMI_SetBaudRate(); + void SetBaud115K(); + void SetBaud250K(); +#endif +#if ENABLED(EEPROM_SETTINGS) + void WriteEeprom(); + void ReadEeprom(); + void ResetEeprom(); +#endif -void HMI_Init(); -void HMI_Popup(); +void HMI_WaitForUser(); void HMI_SaveProcessID(const uint8_t id); void HMI_AudioFeedback(const bool success=true); void EachMomentUpdate(); void update_variable(); +void DWIN_InitScreen(); void DWIN_HandleScreen(); -void DWIN_Update(); void DWIN_CheckStatusMessage(); -void DWIN_StartHoming(); -void DWIN_CompletedHoming(); +void DWIN_HomingStart(); +void DWIN_HomingDone(); #if HAS_MESH - void DWIN_MeshUpdate(const int8_t xpos, const int8_t ypos, const float zval); + void DWIN_MeshUpdate(const int8_t xpos, const int8_t ypos, const_float_t zval); #endif -void DWIN_MeshLevelingStart(); -void DWIN_CompletedLeveling(); +void DWIN_LevelingStart(); +void DWIN_LevelingDone(); void DWIN_PidTuning(pidresult_t result); -void DWIN_Print_Started(const bool sd = false); +void DWIN_Print_Started(const bool sd=false); +void DWIN_Print_Pause(); +void DWIN_Print_Resume(); void DWIN_Print_Finished(); +void DWIN_Print_Aborted(); #if HAS_FILAMENT_SENSOR void DWIN_FilamentRunout(const uint8_t extruder); #endif void DWIN_Progress_Update(); void DWIN_Print_Header(const char *text); void DWIN_SetColorDefaults(); +void DWIN_ApplyColor(); void DWIN_StoreSettings(char *buff); void DWIN_LoadSettings(const char *buff); void DWIN_SetDataDefaults(); void DWIN_RebootScreen(); #if ENABLED(ADVANCED_PAUSE_FEATURE) + void DWIN_Popup_Pause(FSTR_P const fmsg, uint8_t button=0); void Draw_Popup_FilamentPurge(); - void DWIN_Popup_FilamentPurge(); + void Goto_FilamentPurge(); void HMI_FilamentPurge(); #endif @@ -207,14 +191,6 @@ void HMI_LockScreen(); void Draw_PrintStats(); #endif -// HMI user control functions -void HMI_Menu(); -void HMI_SetInt(); -void HMI_SetPInt(); -void HMI_SetIntNoDraw(); -void HMI_SetFloat(); -void HMI_SetPFloat(); - // Menu drawing functions void Draw_Control_Menu(); void Draw_AdvancedSettings_Menu(); diff --git a/Marlin/src/lcd/e3v2/proui/dwin_defines.h b/Marlin/src/lcd/e3v2/proui/dwin_defines.h index 3dc2408f4a..5065bb94d7 100644 --- a/Marlin/src/lcd/e3v2/proui/dwin_defines.h +++ b/Marlin/src/lcd/e3v2/proui/dwin_defines.h @@ -22,18 +22,37 @@ #pragma once /** - * DWIN general defines and data structs + * DWIN general defines and data structs for PRO UI * Author: Miguel A. Risco-Castillo (MRISCOC) - * Version: 3.9.2 - * Date: 2021/11/21 - * - * Based on the original code provided by Creality under GPL + * Version: 3.11.2 + * Date: 2022/02/28 */ -//#define NEED_HEX_PRINT 1 //#define DEBUG_DWIN 1 +//#define NEED_HEX_PRINT 1 + +#include "../../../inc/MarlinConfigPre.h" +#include + +#if DISABLED(INDIVIDUAL_AXIS_HOMING_SUBMENU) + #error "INDIVIDUAL_AXIS_HOMING_SUBMENU is required with ProUI." +#endif +#if DISABLED(LCD_SET_PROGRESS_MANUALLY) + #error "LCD_SET_PROGRESS_MANUALLY is required with ProUI." +#endif +#if DISABLED(STATUS_MESSAGE_SCROLLING) + #error "STATUS_MESSAGE_SCROLLING is required with ProUI." +#endif +#if DISABLED(BAUD_RATE_GCODE) + #error "BAUD_RATE_GCODE is required with ProUI." +#endif +#if DISABLED(SOUND_MENU_ITEM) + #error "SOUND_MENU_ITEM is required with ProUI." +#endif +#if DISABLED(PRINTCOUNTER) + #error "PRINTCOUNTER is required with ProUI." +#endif -#include "../../../core/types.h" #include "../common/dwin_color.h" #if ENABLED(LED_CONTROL_MENU) #include "../../../feature/leds/leds.h" @@ -57,8 +76,8 @@ #define Def_Barfill_Color BarFill_Color #define Def_Indicator_Color Color_White #define Def_Coordinate_Color Color_White +#define Def_Button_Color RGB( 0, 23, 16) -//#define HAS_GCODE_PREVIEW 1 #define HAS_ESDIAG 1 #if ENABLED(LED_CONTROL_MENU, HAS_COLOR_LEDS) @@ -101,6 +120,9 @@ typedef struct { #if ENABLED(PREVENT_COLD_EXTRUSION) int16_t ExtMinT = EXTRUDE_MINTEMP; #endif + int16_t BedLevT = PREHEAT_1_TEMP_BED; + TERN_(BAUD_RATE_GCODE, bool Baud115K = false); + bool FullManualTramming = false; // Led #if BOTH(LED_CONTROL_MENU, HAS_COLOR_LEDS) LEDColor Led_Color = Def_Leds_Color; @@ -113,3 +135,8 @@ typedef struct { static constexpr size_t eeprom_data_size = 64; extern HMI_data_t HMI_data; + +#if PREHEAT_1_TEMP_BED + #undef LEVELING_BED_TEMP + #define LEVELING_BED_TEMP HMI_data.BedLevT +#endif diff --git a/Marlin/src/lcd/e3v2/proui/dwin_lcd.cpp b/Marlin/src/lcd/e3v2/proui/dwin_lcd.cpp index 105f1aaf1c..3da3fc8086 100644 --- a/Marlin/src/lcd/e3v2/proui/dwin_lcd.cpp +++ b/Marlin/src/lcd/e3v2/proui/dwin_lcd.cpp @@ -21,22 +21,68 @@ */ /** - * DWIN UI Enhanced implementation + * DWIN Enhanced implementation for PRO UI * Author: Miguel A. Risco-Castillo (MRISCOC) - * Version: 3.8.1 - * Date: 2021/11/09 - * - * Based on the original code provided by Creality under GPL + * Version: 3.9.1 + * Date: 2022/02/08 */ #include "../../../inc/MarlinConfigPre.h" -#if ENABLED(DWIN_CREALITY_LCD_ENHANCED) +#if ENABLED(DWIN_LCD_PROUI) #include "../../../inc/MarlinConfig.h" #include "dwin_lcd.h" +/*---------------------------------------- Numeric related functions ----------------------------------------*/ + +// Draw a numeric value +// bShow: true=display background color; false=don't display background color +// zeroFill: true=zero fill; false=no zero fill +// signedMode: 1=signed; 0=unsigned +// zeroMode: 1=leading 0 displayed as 0; 0=leading 0 displayed as a space +// size: Font size +// color: Character color +// bColor: Background color +// iNum: Number of digits +// fNum: Number of decimal digits +// x/y: Upper-left coordinate +// value: Integer value +void DWIN_Draw_Value(uint8_t bShow, bool signedMode, bool zeroFill, uint8_t zeroMode, uint8_t size, uint16_t color, + uint16_t bColor, uint8_t iNum, uint8_t fNum, uint16_t x, uint16_t y, int32_t value) { + size_t i = 0; + DWIN_Byte(i, 0x14); + // Bit 7: bshow + // Bit 6: 1 = signed; 0 = unsigned number; + // Bit 5: zeroFill + // Bit 4: zeroMode + // Bit 3-0: size + DWIN_Byte(i, (bShow * 0x80) | (signedMode * 0x40) | (zeroFill * 0x20) | (zeroMode * 0x10) | size); + DWIN_Word(i, color); + DWIN_Word(i, bColor); + DWIN_Byte(i, signedMode && (value >= 0) ? iNum + 1 : iNum); + DWIN_Byte(i, fNum); + DWIN_Word(i, x); + DWIN_Word(i, y); + // Write a big-endian 64 bit integer + const size_t p = i + 1; + for (size_t count = 8; count--;) { // 7..0 + ++i; + DWIN_SendBuf[p + count] = value; + value >>= 8; + } + DWIN_Send(i); +} + +// Draw a numeric value +// value: positive unscaled float value +void DWIN_Draw_Value(uint8_t bShow, bool signedMode, bool zeroFill, uint8_t zeroMode, uint8_t size, uint16_t color, + uint16_t bColor, uint8_t iNum, uint8_t fNum, uint16_t x, uint16_t y, float value) { + const int32_t val = round(value * POW(10, fNum)); + DWIN_Draw_Value(bShow, signedMode, zeroFill, zeroMode, size, color, bColor, iNum, fNum, x, y, val); +} + /*---------------------------------------- Picture related functions ----------------------------------------*/ // Display QR code @@ -159,4 +205,4 @@ void DWIN_SRAMToPic(uint8_t picID) { // DWIN_Send(i); //} -#endif // DWIN_CREALITY_LCD_ENHANCED +#endif // DWIN_LCD_PROUI diff --git a/Marlin/src/lcd/e3v2/proui/dwin_lcd.h b/Marlin/src/lcd/e3v2/proui/dwin_lcd.h index 623a94f09e..cdffb96f2f 100644 --- a/Marlin/src/lcd/e3v2/proui/dwin_lcd.h +++ b/Marlin/src/lcd/e3v2/proui/dwin_lcd.h @@ -22,16 +22,32 @@ #pragma once /** - * DWIN UI Enhanced implementation + * DWIN Enhanced implementation for PRO UI * Author: Miguel A. Risco-Castillo (MRISCOC) - * Version: 3.8.1 - * Date: 2021/11/09 - * - * Based on the original code provided by Creality under GPL + * Version: 3.9.1 + * Date: 2022/02/08 */ #include "../common/dwin_api.h" +// Draw a numeric value +// bShow: true=display background color; false=don't display background color +// zeroFill: true=zero fill; false=no zero fill +// signedMode: 1=signed; 0=unsigned +// zeroMode: 1=leading 0 displayed as 0; 0=leading 0 displayed as a space +// size: Font size +// color: Character color +// bColor: Background color +// iNum: Number of digits +// fNum: Number of decimal digits +// x/y: Upper-left coordinate +// value: Integer value +void DWIN_Draw_Value(uint8_t bShow, bool signedMode, bool zeroFill, uint8_t zeroMode, uint8_t size, uint16_t color, + uint16_t bColor, uint8_t iNum, uint8_t fNum, uint16_t x, uint16_t y, int32_t value); +// value: positive unscaled float value +void DWIN_Draw_Value(uint8_t bShow, bool signedMode, bool zeroFill, uint8_t zeroMode, uint8_t size, uint16_t color, + uint16_t bColor, uint8_t iNum, uint8_t fNum, uint16_t x, uint16_t y, float value); + // Display QR code // The size of the QR code is (46*QR_Pixel)*(46*QR_Pixel) dot matrix // QR_Pixel: The pixel size occupied by each point of the QR code: 0x01-0x0F (1-16) diff --git a/Marlin/src/lcd/e3v2/proui/dwin_popup.cpp b/Marlin/src/lcd/e3v2/proui/dwin_popup.cpp index 34b05328d7..59b6c0d328 100644 --- a/Marlin/src/lcd/e3v2/proui/dwin_popup.cpp +++ b/Marlin/src/lcd/e3v2/proui/dwin_popup.cpp @@ -21,43 +21,75 @@ */ /** - * DWIN UI Enhanced implementation + * DWIN Enhanced implementation for PRO UI * Author: Miguel A. Risco-Castillo (MRISCOC) - * Version: 3.10.1 - * Date: 2022/01/21 - * - * Based on the original code provided by Creality under GPL + * Version: 3.11.1 + * Date: 2022/02/28 */ #include "../../../inc/MarlinConfigPre.h" -#if ENABLED(DWIN_CREALITY_LCD_ENHANCED) +#if ENABLED(DWIN_LCD_PROUI) #include "dwin.h" +#include "dwinui.h" #include "dwin_popup.h" -void Draw_Select_Highlight(const bool sel) { +#include "../../../MarlinCore.h" // for wait_for_user + +popupDrawFunc_t popupDraw = nullptr; +popupClickFunc_t popupClick = nullptr; +popupChangeFunc_t popupChange = nullptr; + +uint16_t HighlightYPos = 280; + +void Draw_Select_Highlight(const bool sel, const uint16_t ypos) { + HighlightYPos = ypos; HMI_flag.select_flag = sel; const uint16_t c1 = sel ? HMI_data.Highlight_Color : HMI_data.PopupBg_color, c2 = sel ? HMI_data.PopupBg_color : HMI_data.Highlight_Color; - DWIN_Draw_Rectangle(0, c1, 25, 279, 126, 318); - DWIN_Draw_Rectangle(0, c1, 24, 278, 127, 319); - DWIN_Draw_Rectangle(0, c2, 145, 279, 246, 318); - DWIN_Draw_Rectangle(0, c2, 144, 278, 247, 319); + DWIN_Draw_Rectangle(0, c1, 25, ypos - 1, 126, ypos + 38); + DWIN_Draw_Rectangle(0, c1, 24, ypos - 2, 127, ypos + 39); + DWIN_Draw_Rectangle(0, c2, 145, ypos - 1, 246, ypos + 38); + DWIN_Draw_Rectangle(0, c2, 144, ypos - 2, 247, ypos + 39); } void DWIN_Popup_Continue(const uint8_t icon, FSTR_P const fmsg1, FSTR_P const fmsg2) { HMI_SaveProcessID(WaitResponse); - DWIN_Draw_Popup(icon, fmsg1, fmsg2, ICON_Continue_E); // Button Continue + DWIN_Draw_Popup(icon, fmsg1, fmsg2, BTN_Continue); // Button Continue DWIN_UpdateLCD(); } void DWIN_Popup_ConfirmCancel(const uint8_t icon, FSTR_P const fmsg2) { DWIN_Draw_Popup(ICON_BLTouch, F("Please confirm"), fmsg2); - DWINUI::Draw_IconWB(ICON_Confirm_E, 26, 280); - DWINUI::Draw_IconWB(ICON_Cancel_E, 146, 280); - Draw_Select_Highlight(true); + DWINUI::Draw_Button(BTN_Confirm, 26, 280); + DWINUI::Draw_Button(BTN_Cancel, 146, 280); + Draw_Select_Highlight(HMI_flag.select_flag); DWIN_UpdateLCD(); } -#endif // DWIN_CREALITY_LCD_ENHANCED +void Goto_Popup(const popupDrawFunc_t fnDraw, const popupClickFunc_t fnClick/*=nullptr*/, const popupChangeFunc_t fnChange/*=nullptr*/) { + popupDraw = fnDraw; + popupClick = fnClick; + popupChange = fnChange; + HMI_SaveProcessID(Popup); + HMI_flag.select_flag = false; + popupDraw(); +} + +void HMI_Popup() { + if (!wait_for_user) { + if (popupClick) popupClick(); + return; + } + else { + EncoderState encoder_diffState = get_encoder_state(); + if (encoder_diffState == ENCODER_DIFF_CW || encoder_diffState == ENCODER_DIFF_CCW) { + const bool change = encoder_diffState != ENCODER_DIFF_CW; + if (popupChange) popupChange(change); else Draw_Select_Highlight(change, HighlightYPos); + DWIN_UpdateLCD(); + } + } +} + +#endif // DWIN_LCD_PROUI diff --git a/Marlin/src/lcd/e3v2/proui/dwin_popup.h b/Marlin/src/lcd/e3v2/proui/dwin_popup.h index 2e952cc1b9..0d86499475 100644 --- a/Marlin/src/lcd/e3v2/proui/dwin_popup.h +++ b/Marlin/src/lcd/e3v2/proui/dwin_popup.h @@ -22,20 +22,26 @@ #pragma once /** - * DWIN UI Enhanced implementation + * DWIN Enhanced implementation for PRO UI * Author: Miguel A. Risco-Castillo (MRISCOC) - * Version: 3.10.1 - * Date: 2022/01/21 - * - * Based on the original code provided by Creality under GPL + * Version: 3.11.1 + * Date: 2022/02/28 */ #include "dwinui.h" #include "dwin.h" -// Popup windows +typedef void (*popupDrawFunc_t)(); +typedef void (*popupClickFunc_t)(); +typedef void (*popupChangeFunc_t)(const bool state); +extern popupDrawFunc_t popupDraw; -void Draw_Select_Highlight(const bool sel); +void Draw_Select_Highlight(const bool sel, const uint16_t ypos); +inline void Draw_Select_Highlight(const bool sel) { Draw_Select_Highlight(sel, 280); }; +void DWIN_Popup_Continue(const uint8_t icon, FSTR_P const fmsg1, FSTR_P const fmsg2); +void DWIN_Popup_ConfirmCancel(const uint8_t icon, FSTR_P const fmsg2); +void Goto_Popup(const popupDrawFunc_t fnDraw, const popupClickFunc_t fnClick=nullptr, const popupChangeFunc_t fnChange=nullptr); +void HMI_Popup(); inline void Draw_Popup_Bkgd() { DWIN_Draw_Rectangle(1, HMI_data.PopupBg_color, 14, 60, 258, 330); @@ -49,7 +55,7 @@ void DWIN_Draw_Popup(const uint8_t icon, T amsg1=nullptr, U amsg2=nullptr, uint8 if (icon) DWINUI::Draw_Icon(icon, 101, 105); if (amsg1) DWINUI::Draw_CenteredString(HMI_data.PopupTxt_Color, 210, amsg1); if (amsg2) DWINUI::Draw_CenteredString(HMI_data.PopupTxt_Color, 240, amsg2); - if (button) DWINUI::Draw_IconWB(button, 86, 280); + if (button) DWINUI::Draw_Button(button, 86, 280); } template @@ -61,10 +67,7 @@ void DWIN_Show_Popup(const uint8_t icon, T amsg1=nullptr, U amsg2=nullptr, uint8 template void DWIN_Popup_Confirm(const uint8_t icon, T amsg1, U amsg2) { HMI_SaveProcessID(WaitResponse); - DWIN_Draw_Popup(icon, amsg1, amsg2, ICON_Confirm_E); // Button Confirm + DWIN_Draw_Popup(icon, amsg1, amsg2, BTN_Confirm); // Button Confirm DWIN_UpdateLCD(); } -void DWIN_Popup_Continue(const uint8_t icon, FSTR_P const fmsg1, FSTR_P const fmsg2); - -void DWIN_Popup_ConfirmCancel(const uint8_t icon, FSTR_P const fmsg2); diff --git a/Marlin/src/lcd/e3v2/proui/dwinui.cpp b/Marlin/src/lcd/e3v2/proui/dwinui.cpp index d3cfc9a3e4..ddc494fc84 100644 --- a/Marlin/src/lcd/e3v2/proui/dwinui.cpp +++ b/Marlin/src/lcd/e3v2/proui/dwinui.cpp @@ -21,17 +21,15 @@ */ /** - * DWIN UI Enhanced implementation + * DWIN Enhanced implementation for PRO UI * Author: Miguel A. Risco-Castillo (MRISCOC) - * Version: 3.8.2 - * Date: 2021/11/09 - * - * Based on the original code provided by Creality under GPL + * Version: 3.15.1 + * Date: 2022/02/25 */ #include "../../../inc/MarlinConfigPre.h" -#if ENABLED(DWIN_CREALITY_LCD_ENHANCED) +#if ENABLED(DWIN_LCD_PROUI) #include "../../../inc/MarlinConfig.h" #include "dwin_lcd.h" @@ -51,7 +49,9 @@ xy_int_t DWINUI::cursor = { 0 }; uint16_t DWINUI::pencolor = Color_White; uint16_t DWINUI::textcolor = Def_Text_Color; uint16_t DWINUI::backcolor = Def_Background_Color; +uint16_t DWINUI::buttoncolor = Def_Button_Color; uint8_t DWINUI::font = font8x16; +FSTR_P const DWINUI::Author = F(STRING_CONFIG_H_AUTHOR); void (*DWINUI::onCursorErase)(const int8_t line)=nullptr; void (*DWINUI::onCursorDraw)(const int8_t line)=nullptr; @@ -59,18 +59,16 @@ void (*DWINUI::onTitleDraw)(TitleClass* title)=nullptr; void (*DWINUI::onMenuDraw)(MenuClass* menu)=nullptr; void DWINUI::init() { - DEBUG_ECHOPGM("\r\nDWIN handshake "); - delay(750); // Delay here or init later in the boot process - const bool success = DWIN_Handshake(); - if (success) DEBUG_ECHOLNPGM("ok."); else DEBUG_ECHOLNPGM("error."); + TERN_(DEBUG_DWIN, SERIAL_ECHOPGM("\r\nDWIN handshake ")); + delay(750); // Delay for wait to wakeup screen + const bool hs = DWIN_Handshake(); + TERN(DEBUG_DWIN, SERIAL_ECHOLNF(hs ? F("ok.") : F("error.")), UNUSED(hs)); DWIN_Frame_SetDir(1); - TERN(SHOW_BOOTSCREEN,,DWIN_Frame_Clear(Color_Bg_Black)); - DWIN_UpdateLCD(); - cursor.x = 0; - cursor.y = 0; + cursor.reset(); pencolor = Color_White; textcolor = Def_Text_Color; backcolor = Def_Background_Color; + buttoncolor = Def_Button_Color; font = font8x16; } @@ -124,9 +122,10 @@ uint16_t DWINUI::RowToY(uint8_t row) { } // Set text/number color -void DWINUI::SetColors(uint16_t fgcolor, uint16_t bgcolor) { +void DWINUI::SetColors(uint16_t fgcolor, uint16_t bgcolor, uint16_t alcolor) { textcolor = fgcolor; backcolor = bgcolor; + buttoncolor = alcolor; } void DWINUI::SetTextColor(uint16_t fgcolor) { textcolor = fgcolor; @@ -159,16 +158,22 @@ void DWINUI::MoveBy(xy_int_t point) { cursor += point; } -// Draw a Centered string using DWIN_WIDTH -void DWINUI::Draw_CenteredString(bool bShow, uint8_t size, uint16_t color, uint16_t bColor, uint16_t y, const char * const string) { - const int8_t x = _MAX(0U, DWIN_WIDTH - strlen_P(string) * fontWidth(size)) / 2 - 1; +// Draw a Centered string using arbitrary x1 and x2 margins +void DWINUI::Draw_CenteredString(bool bShow, uint8_t size, uint16_t color, uint16_t bColor, uint16_t x1, uint16_t x2, uint16_t y, const char * const string) { + const uint16_t x = _MAX(0U, x2 + x1 - strlen_P(string) * fontWidth(size)) / 2 - 1; DWIN_Draw_String(bShow, size, color, bColor, x, y, string); } +// // Draw a Centered string using DWIN_WIDTH +// void DWINUI::Draw_CenteredString(bool bShow, uint8_t size, uint16_t color, uint16_t bColor, uint16_t y, const char * const string) { +// const int8_t x = _MAX(0U, DWIN_WIDTH - strlen_P(string) * fontWidth(size)) / 2 - 1; +// DWIN_Draw_String(bShow, size, color, bColor, x, y, string); +// } + // Draw a char at cursor position -void DWINUI::Draw_Char(const char c) { +void DWINUI::Draw_Char(uint16_t color, const char c) { const char string[2] = { c, 0}; - DWIN_Draw_String(false, font, textcolor, backcolor, cursor.x, cursor.y, string, 1); + DWIN_Draw_String(false, font, color, backcolor, cursor.x, cursor.y, string, 1); MoveBy(fontWidth(font), 0); } @@ -185,21 +190,26 @@ void DWINUI::Draw_String(uint16_t color, const char * const string, uint16_t rli MoveBy(strlen(string) * fontWidth(font), 0); } -// Draw a signed floating point number -// bShow: true=display background color; false=don't display background color -// zeroFill: true=zero fill; false=no zero fill -// zeroMode: 1=leading 0 displayed as 0; 0=leading 0 displayed as a space -// size: Font size -// bColor: Background color -// iNum: Number of whole digits -// fNum: Number of decimal digits -// x/y: Upper-left point -// value: Float value -void DWINUI::Draw_Signed_Float(uint8_t bShow, bool zeroFill, uint8_t zeroMode, uint8_t size, uint16_t color, uint16_t bColor, uint8_t iNum, uint8_t fNum, uint16_t x, uint16_t y, float value) { - DWIN_Draw_FloatValue(bShow, zeroFill, zeroMode, size, color, bColor, iNum, fNum, x, y, value < 0 ? -value : value); - DWIN_Draw_String(bShow, size, color, bColor, x - 6, y, value < 0 ? F("-") : F(" ")); +// ------------------------- Buttons ------------------------------// + +void DWINUI::Draw_Button(uint16_t color, uint16_t bcolor, uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2, const char * const caption) { + DWIN_Draw_Rectangle(1, bcolor, x1, y1, x2, y2); + Draw_CenteredString(0, font, color, bcolor, x1, x2, (y2 + y1 - fontHeight())/2, caption); } +void DWINUI::Draw_Button(uint8_t id, uint16_t x, uint16_t y) { + switch (id) { + case BTN_Cancel : Draw_Button(GET_TEXT_F(MSG_BUTTON_CANCEL), x, y); break; + case BTN_Confirm : Draw_Button(GET_TEXT_F(MSG_BUTTON_CONFIRM), x, y); break; + case BTN_Continue: Draw_Button(GET_TEXT_F(MSG_BUTTON_CONTINUE), x, y); break; + case BTN_Print : Draw_Button(GET_TEXT_F(MSG_BUTTON_PRINT), x, y); break; + case BTN_Save : Draw_Button(GET_TEXT_F(MSG_BUTTON_SAVE), x, y); break; + default: break; + } +} + +// -------------------------- Extra -------------------------------// + // Draw a circle // color: circle color // x: the abscissa of the center of the circle @@ -247,13 +257,12 @@ void DWINUI::Draw_FillCircle(uint16_t bcolor, uint16_t x,uint16_t y,uint8_t r) { // color1 : Start color // color2 : End color uint16_t DWINUI::ColorInt(int16_t val, int16_t minv, int16_t maxv, uint16_t color1, uint16_t color2) { - uint8_t B,G,R; - float n; - n = (float)(val-minv)/(maxv-minv); - R = (1-n)*GetRColor(color1) + n*GetRColor(color2); - G = (1-n)*GetGColor(color1) + n*GetGColor(color2); - B = (1-n)*GetBColor(color1) + n*GetBColor(color2); - return RGB(R,G,B); + uint8_t B, G, R; + const float n = (float)(val - minv) / (maxv - minv); + R = (1 - n) * GetRColor(color1) + n * GetRColor(color2); + G = (1 - n) * GetGColor(color1) + n * GetGColor(color2); + B = (1 - n) * GetBColor(color1) + n * GetBColor(color2); + return RGB(R, G, B); } // Color Interpolator through Red->Yellow->Green->Blue @@ -261,33 +270,27 @@ uint16_t DWINUI::ColorInt(int16_t val, int16_t minv, int16_t maxv, uint16_t colo // minv : Minimum value // maxv : Maximum value uint16_t DWINUI::RainbowInt(int16_t val, int16_t minv, int16_t maxv) { - uint8_t B,G,R; - const uint8_t maxB = 28; - const uint8_t maxR = 28; - const uint8_t maxG = 38; + uint8_t B, G, R; + const uint8_t maxB = 28, maxR = 28, maxG = 38; const int16_t limv = _MAX(abs(minv), abs(maxv)); - float n; - if (minv>=0) { - n = (float)(val-minv)/(maxv-minv); - } else { - n = (float)val/limv; - } - n = _MIN(1, n); - n = _MAX(-1, n); + float n = minv >= 0 ? (float)(val - minv) / (maxv - minv) : (float)val / limv; + LIMIT(n, -1, 1); if (n < 0) { R = 0; - G = (1+n)*maxG; - B = (-n)*maxB; - } else if (n < 0.5) { - R = maxR*n*2; + G = (1 + n) * maxG; + B = (-n) * maxB; + } + else if (n < 0.5) { + R = maxR * n * 2; G = maxG; B = 0; - } else { + } + else { R = maxR; - G = maxG*(1-n); + G = maxG * (1 - n); B = 0; } - return RGB(R,G,B); + return RGB(R, G, B); } // Draw a checkbox @@ -453,4 +456,4 @@ MenuItemPtrClass::MenuItemPtrClass(uint8_t cicon, const char * const text, void value = val; }; -#endif // DWIN_CREALITY_LCD_ENHANCED +#endif // DWIN_LCD_PROUI diff --git a/Marlin/src/lcd/e3v2/proui/dwinui.h b/Marlin/src/lcd/e3v2/proui/dwinui.h index 595c534356..1504dcd305 100644 --- a/Marlin/src/lcd/e3v2/proui/dwinui.h +++ b/Marlin/src/lcd/e3v2/proui/dwinui.h @@ -22,12 +22,10 @@ #pragma once /** - * DWIN UI Enhanced implementation + * DWIN Enhanced implementation for PRO UI * Author: Miguel A. Risco-Castillo (MRISCOC) - * Version: 3.11.1 - * Date: 2022/01/19 - * - * Based on the original code provided by Creality under GPL + * Version: 3.15.1 + * Date: 2022/02/25 */ #include "dwin_lcd.h" @@ -107,6 +105,13 @@ #define ICON_CaseLight ICON_Motion #define ICON_LedControl ICON_Motion +// Buttons +#define BTN_Continue 85 +#define BTN_Cancel 87 +#define BTN_Confirm 89 +#define BTN_Print 90 +#define BTN_Save 91 + // Extended and default UI Colors #define Color_Black 0 #define Color_Green RGB(0,63,0) @@ -119,7 +124,11 @@ #define DWIN_FONT_HEAD font10x20 #define DWIN_FONT_ALERT font10x20 #define STATUS_Y 354 -#define LCD_WIDTH (DWIN_WIDTH / 8) +#define LCD_WIDTH (DWIN_WIDTH / 8) // only if the default font is font8x16 + +// Minimum unit (0.1) : multiple (10) +#define UNITFDIGITS 1 +#define MINUNITMULT POW(10, UNITFDIGITS) constexpr uint16_t TITLE_HEIGHT = 30, // Title bar height MLINE = 53, // Menu line height @@ -212,7 +221,9 @@ namespace DWINUI { extern uint16_t pencolor; extern uint16_t textcolor; extern uint16_t backcolor; + extern uint16_t buttoncolor; extern uint8_t font; + extern FSTR_P const Author; extern void (*onCursorErase)(const int8_t line); extern void (*onCursorDraw)(const int8_t line); @@ -240,7 +251,7 @@ namespace DWINUI { uint16_t RowToY(uint8_t row); // Set text/number color - void SetColors(uint16_t fgcolor, uint16_t bgcolor); + void SetColors(uint16_t fgcolor, uint16_t bgcolor, uint16_t alcolor); void SetTextColor(uint16_t fgcolor); void SetBackgroundColor(uint16_t bgcolor); @@ -268,6 +279,17 @@ namespace DWINUI { DWIN_Draw_Line(pencolor, cursor.x, cursor.y, x, y); } + // Extend a frame box + // v: value to extend + inline frame_rect_t ExtendFrame(frame_rect_t frame, uint8_t v) { + frame_rect_t t; + t.x = frame.x - v; + t.y = frame.y - v; + t.w = frame.w + 2 * v; + t.h = frame.h + 2 * v; + return t; + } + // Draw an Icon with transparent background from the library ICON // icon: Icon ID // x/y: Upper-left point @@ -293,26 +315,56 @@ namespace DWINUI { // x/y: Upper-left coordinate // value: Integer value inline void Draw_Int(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, long value) { - DWIN_Draw_IntValue(bShow, zeroFill, zeroMode, size, color, bColor, iNum, x, y, value); + DWIN_Draw_Value(bShow, 0, zeroFill, zeroMode, size, color, bColor, iNum, 0, x, y, value); } inline void Draw_Int(uint8_t iNum, long value) { - DWIN_Draw_IntValue(false, true, 0, font, textcolor, backcolor, iNum, cursor.x, cursor.y, value); + DWIN_Draw_Value(false, 0, true, 0, font, textcolor, backcolor, iNum, 0, cursor.x, cursor.y, value); MoveBy(iNum * fontWidth(font), 0); } inline void Draw_Int(uint8_t iNum, uint16_t x, uint16_t y, long value) { - DWIN_Draw_IntValue(false, true, 0, font, textcolor, backcolor, iNum, x, y, value); + DWIN_Draw_Value(false, 0, true, 0, font, textcolor, backcolor, iNum, 0, x, y, value); } inline void Draw_Int(uint16_t color, uint8_t iNum, uint16_t x, uint16_t y, long value) { - DWIN_Draw_IntValue(false, true, 0, font, color, backcolor, iNum, x, y, value); + DWIN_Draw_Value(false, 0, true, 0, font, color, backcolor, iNum, 0, x, y, value); } inline void Draw_Int(uint16_t color, uint16_t bColor, uint8_t iNum, uint16_t x, uint16_t y, long value) { - DWIN_Draw_IntValue(true, true, 0, font, color, bColor, iNum, x, y, value); + DWIN_Draw_Value(true, 0, true, 0, font, color, bColor, iNum, 0, x, y, value); } inline void Draw_Int(uint8_t size, uint16_t color, uint16_t bColor, uint8_t iNum, uint16_t x, uint16_t y, long value) { - DWIN_Draw_IntValue(true, true, 0, size, color, bColor, iNum, x, y, value); + DWIN_Draw_Value(true, 0, true, 0, size, color, bColor, iNum, 0, x, y, value); } - // Draw a floating point number + // Draw a signed integer + // bShow: true=display background color; false=don't display background color + // zeroFill: true=zero fill; false=no zero fill + // zeroMode: 1=leading 0 displayed as 0; 0=leading 0 displayed as a space + // size: Font size + // color: Character color + // bColor: Background color + // iNum: Number of digits + // x/y: Upper-left coordinate + // value: Integer value + inline void Draw_Signed_Int(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, long value) { + DWIN_Draw_Value(bShow, 1, zeroFill, zeroMode, size, color, bColor, iNum, 0, x, y, value); + } + inline void Draw_Signed_Int(uint8_t iNum, long value) { + DWIN_Draw_Value(false, 1, true, 0, font, textcolor, backcolor, iNum, 0, cursor.x, cursor.y, value); + MoveBy(iNum * fontWidth(font), 0); + } + inline void Draw_Signed_Int(uint8_t iNum, uint16_t x, uint16_t y, long value) { + DWIN_Draw_Value(false, 1, true, 0, font, textcolor, backcolor, iNum, 0, x, y, value); + } + inline void Draw_Signed_Int(uint16_t color, uint8_t iNum, uint16_t x, uint16_t y, long value) { + DWIN_Draw_Value(false, 1, true, 0, font, color, backcolor, iNum, 0, x, y, value); + } + inline void Draw_Signed_Int(uint16_t color, uint16_t bColor, uint8_t iNum, uint16_t x, uint16_t y, long value) { + DWIN_Draw_Value(true, 1, true, 0, font, color, bColor, iNum, 0, x, y, value); + } + inline void Draw_Signed_Int(uint8_t size, uint16_t color, uint16_t bColor, uint8_t iNum, uint16_t x, uint16_t y, long value) { + DWIN_Draw_Value(true, 1, true, 0, size, color, bColor, iNum, 0, x, y, value); + } + + // Draw a positive floating point number // bShow: true=display background color; false=don't display background color // zeroFill: true=zero fill; false=no zero fill // zeroMode: 1=leading 0 displayed as 0; 0=leading 0 displayed as a space @@ -324,23 +376,23 @@ namespace DWINUI { // x/y: Upper-left point // value: Float value inline void Draw_Float(uint8_t bShow, bool zeroFill, uint8_t zeroMode, uint8_t size, uint16_t color, uint16_t bColor, uint8_t iNum, uint8_t fNum, uint16_t x, uint16_t y, float value) { - DWIN_Draw_FloatValue(bShow, zeroFill, zeroMode, size, color, bColor, iNum, fNum, x, y, value); + DWIN_Draw_Value(bShow, 0, zeroFill, zeroMode, size, color, bColor, iNum, fNum, x, y, value); } inline void Draw_Float(uint8_t iNum, uint8_t fNum, float value) { - DWIN_Draw_FloatValue(false, true, 0, font, textcolor, backcolor, iNum, fNum, cursor.x, cursor.y, value); + DWIN_Draw_Value(false, 0, true, 0, font, textcolor, backcolor, iNum, fNum, cursor.x, cursor.y, value); MoveBy((iNum + fNum + 1) * fontWidth(font), 0); } inline void Draw_Float(uint8_t iNum, uint8_t fNum, uint16_t x, uint16_t y, float value) { - DWIN_Draw_FloatValue(false, true, 0, font, textcolor, backcolor, iNum, fNum, x, y, value); + DWIN_Draw_Value(false, 0, true, 0, font, textcolor, backcolor, iNum, fNum, x, y, value); } inline void Draw_Float(uint16_t color, uint8_t iNum, uint8_t fNum, uint16_t x, uint16_t y, float value) { - DWIN_Draw_FloatValue(false, true, 0, font, color, backcolor, iNum, fNum, x, y, value); + DWIN_Draw_Value(false, 0, true, 0, font, color, backcolor, iNum, fNum, x, y, value); } inline void Draw_Float(uint16_t color, uint16_t bColor, uint8_t iNum, uint8_t fNum, uint16_t x, uint16_t y, float value) { - DWIN_Draw_FloatValue(true, true, 0, font, color, bColor, iNum, fNum, x, y, value); + DWIN_Draw_Value(true, 0, true, 0, font, color, bColor, iNum, fNum, x, y, value); } inline void Draw_Float(uint8_t size, uint16_t color, uint16_t bColor, uint8_t iNum, uint8_t fNum, uint16_t x, uint16_t y, float value) { - DWIN_Draw_FloatValue(true, true, 0, size, color, bColor, iNum, fNum, x, y, value); + DWIN_Draw_Value(true, 0, true, 0, size, color, bColor, iNum, fNum, x, y, value); } // Draw a signed floating point number @@ -348,31 +400,35 @@ namespace DWINUI { // zeroFill: true=zero fill; false=no zero fill // zeroMode: 1=leading 0 displayed as 0; 0=leading 0 displayed as a space // size: Font size + // color: Character color // bColor: Background color // iNum: Number of whole digits // fNum: Number of decimal digits // x/y: Upper-left point // value: Float value - void Draw_Signed_Float(uint8_t bShow, bool zeroFill, uint8_t zeroMode, uint8_t size, uint16_t color, uint16_t bColor, uint8_t iNum, uint8_t fNum, uint16_t x, uint16_t y, float value); + inline void Draw_Signed_Float(uint8_t bShow, bool zeroFill, uint8_t zeroMode, uint8_t size, uint16_t color, uint16_t bColor, uint8_t iNum, uint8_t fNum, uint16_t x, uint16_t y, float value) { + DWIN_Draw_Value(bShow, 1, zeroFill, zeroMode, size, color, bColor, iNum, fNum, x, y, value); + } inline void Draw_Signed_Float(uint8_t iNum, uint8_t fNum, float value) { - Draw_Signed_Float(false, true, 0, font, textcolor, backcolor, iNum, fNum, cursor.x, cursor.y, value); + DWIN_Draw_Value(false, 1, true, 0, font, textcolor, backcolor, iNum, fNum, cursor.x, cursor.y, value); MoveBy((iNum + fNum + 1) * fontWidth(font), 0); } inline void Draw_Signed_Float(uint8_t iNum, uint8_t fNum, uint16_t x, uint16_t y, float value) { - Draw_Signed_Float(false, true, 0, font, textcolor, backcolor, iNum, fNum, x, y, value); + DWIN_Draw_Value(false, 1, true, 0, font, textcolor, backcolor, iNum, fNum, x, y, value); } inline void Draw_Signed_Float(uint8_t size, uint8_t iNum, uint8_t fNum, uint16_t x, uint16_t y, float value) { - Draw_Signed_Float(false, true, 0, size, textcolor, backcolor, iNum, fNum, x, y, value); + DWIN_Draw_Value(false, 1, true, 0, size, textcolor, backcolor, iNum, fNum, x, y, value); } inline void Draw_Signed_Float(uint16_t color, uint16_t bColor, uint8_t iNum, uint8_t fNum, uint16_t x, uint16_t y, float value) { - Draw_Signed_Float(true, true, 0, font, color, bColor, iNum, fNum, x, y, value); + DWIN_Draw_Value(true, 1, true, 0, font, color, bColor, iNum, fNum, x, y, value); } inline void Draw_Signed_Float(uint8_t size, uint16_t color, uint16_t bColor, uint8_t iNum, uint8_t fNum, uint16_t x, uint16_t y, float value) { - Draw_Signed_Float(true, true, 0, size, color, bColor, iNum, fNum, x, y, value); + DWIN_Draw_Value(true, 1, true, 0, size, color, bColor, iNum, fNum, x, y, value); } // Draw a char at cursor position - void Draw_Char(const char c); + void Draw_Char(uint16_t color, const char c); + inline void Draw_Char(const char c) { Draw_Char(textcolor, c); } // Draw a string at cursor position // color: Character color @@ -425,7 +481,10 @@ namespace DWINUI { // bColor: Background color // y: Upper coordinate of the string // *string: The string - void Draw_CenteredString(bool bShow, uint8_t size, uint16_t color, uint16_t bColor, uint16_t y, const char * const string); + void Draw_CenteredString(bool bShow, uint8_t size, uint16_t color, uint16_t bColor, uint16_t x1, uint16_t x2, uint16_t y, const char * const string); + inline void Draw_CenteredString(bool bShow, uint8_t size, uint16_t color, uint16_t bColor, uint16_t y, const char * const string) { + Draw_CenteredString(bShow, size, color, bColor, 0, DWIN_WIDTH, y, string); + } inline void Draw_CenteredString(bool bShow, uint8_t size, uint16_t color, uint16_t bColor, uint16_t y, FSTR_P string) { Draw_CenteredString(bShow, size, color, bColor, y, FTOP(string)); } @@ -487,6 +546,17 @@ namespace DWINUI { // color2 : End color uint16_t ColorInt(int16_t val, int16_t minv, int16_t maxv, uint16_t color1, uint16_t color2); + // ------------------------- Buttons ------------------------------// + + void Draw_Button(uint16_t color, uint16_t bcolor, uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2, const char * const caption); + inline void Draw_Button(uint16_t color, uint16_t bcolor, uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2, FSTR_P caption) { + Draw_Button(color, bcolor, x1, y1, x2, y2, FTOP(caption)); + } + inline void Draw_Button(FSTR_P caption, uint16_t x, uint16_t y) { + Draw_Button(textcolor, buttoncolor, x, y, x + 99, y + 37, caption); + } + void Draw_Button(uint8_t id, uint16_t x, uint16_t y); + // -------------------------- Extra -------------------------------// // Draw a circle filled with color diff --git a/Marlin/src/lcd/e3v2/proui/endstop_diag.cpp b/Marlin/src/lcd/e3v2/proui/endstop_diag.cpp index 6232c89534..4c2e4fa200 100644 --- a/Marlin/src/lcd/e3v2/proui/endstop_diag.cpp +++ b/Marlin/src/lcd/e3v2/proui/endstop_diag.cpp @@ -21,18 +21,19 @@ */ /** - * DWIN End Stops diagnostic page + * DWIN Endstops diagnostic page for PRO UI * Author: Miguel A. Risco-Castillo (MRISCOC) - * Version: 1.0.2 - * Date: 2021/11/06 - * - * Based on the original code provided by Creality under GPL + * Version: 1.2.2 + * Date: 2022/02/24 */ #include "../../../inc/MarlinConfigPre.h" + +#if ENABLED(DWIN_LCD_PROUI) + #include "dwin_defines.h" -#if BOTH(DWIN_CREALITY_LCD_ENHANCED, HAS_ESDIAG) +#if HAS_ESDIAG #include "endstop_diag.h" @@ -72,7 +73,7 @@ void ESDiagClass::Draw() { Title.ShowCaption(F("End-stops Diagnostic")); DWINUI::ClearMenuArea(); Draw_Popup_Bkgd(); - DWINUI::Draw_Icon(ICON_Continue_E, 86, 250); + DWINUI::Draw_Button(BTN_Continue, 86, 250); DWINUI::cursor.y = 80; #define ES_LABEL(S) draw_es_label(F(STR_##S)) #if HAS_X_MIN @@ -103,9 +104,10 @@ void ESDiagClass::Update() { ES_REPORT(Z_MIN); #endif #if HAS_FILAMENT_SENSOR - draw_es_state(READ(FIL_RUNOUT1_PIN) != FIL_RUNOUT1_STATE); + draw_es_state(READ(FIL_RUNOUT1_PIN) != runout.out_state()); #endif DWIN_UpdateLCD(); } -#endif // DWIN_CREALITY_LCD_ENHANCED && HAS_ESDIAG +#endif // HAS_ESDIAG +#endif // DWIN_LCD_PROUI diff --git a/Marlin/src/lcd/e3v2/proui/endstop_diag.h b/Marlin/src/lcd/e3v2/proui/endstop_diag.h index 4694ddb141..316a1e1ed3 100644 --- a/Marlin/src/lcd/e3v2/proui/endstop_diag.h +++ b/Marlin/src/lcd/e3v2/proui/endstop_diag.h @@ -22,12 +22,10 @@ #pragma once /** - * DWIN End Stops diagnostic page + * DWIN End Stops diagnostic page for PRO UI * Author: Miguel A. Risco-Castillo (MRISCOC) - * Version: 1.0 - * Date: 2021/11/06 - * - * Based on the original code provided by Creality under GPL + * Version: 1.2.3 + * Date: 2022/02/24 */ class ESDiagClass { diff --git a/Marlin/src/lcd/e3v2/proui/lockscreen.cpp b/Marlin/src/lcd/e3v2/proui/lockscreen.cpp index 3f8339ad48..2895c01544 100644 --- a/Marlin/src/lcd/e3v2/proui/lockscreen.cpp +++ b/Marlin/src/lcd/e3v2/proui/lockscreen.cpp @@ -21,17 +21,15 @@ */ /** - * Lock screen implementation for DWIN UI Enhanced implementation + * Lock screen implementation for PRO UI * Author: Miguel A. Risco-Castillo (MRISCOC) * Version: 2.1 * Date: 2021/11/09 - * - * Based on the original code provided by Creality under GPL */ #include "../../../inc/MarlinConfigPre.h" -#if ENABLED(DWIN_CREALITY_LCD_ENHANCED) +#if ENABLED(DWIN_LCD_PROUI) #include "../../../core/types.h" #include "dwin_lcd.h" @@ -75,4 +73,4 @@ void LockScreenClass::onEncoder(EncoderState encoder_diffState) { DWIN_UpdateLCD(); } -#endif // DWIN_CREALITY_LCD_ENHANCED +#endif // DWIN_LCD_PROUI diff --git a/Marlin/src/lcd/e3v2/proui/lockscreen.h b/Marlin/src/lcd/e3v2/proui/lockscreen.h index bf2fdb3f4b..ec967fe2db 100644 --- a/Marlin/src/lcd/e3v2/proui/lockscreen.h +++ b/Marlin/src/lcd/e3v2/proui/lockscreen.h @@ -22,12 +22,10 @@ #pragma once /** - * Lock screen implementation for DWIN UI Enhanced implementation + * Lock screen implementation for PRO UI * Author: Miguel A. Risco-Castillo (MRISCOC) * Version: 2.1 * Date: 2021/11/09 - * - * Based on the original code provided by Creality under GPL */ #include "../common/encoder.h" diff --git a/Marlin/src/lcd/e3v2/proui/menus.cpp b/Marlin/src/lcd/e3v2/proui/menus.cpp new file mode 100644 index 0000000000..6dfcb8595c --- /dev/null +++ b/Marlin/src/lcd/e3v2/proui/menus.cpp @@ -0,0 +1,370 @@ +/** + * 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 . + * + */ + +/** + * Menu functions for ProUI + * Author: Miguel A. Risco-Castillo + * Version: 1.2.1 + * Date: 2022/02/25 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser 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 Lesser General Public License + * along with this program. If not, see . + * + */ + +#include "../../../inc/MarlinConfigPre.h" + +#if ENABLED(DWIN_LCD_PROUI) + +#include "../common/encoder.h" +#include "dwin_lcd.h" +#include "dwinui.h" +#include "dwin.h" +#include "menus.h" + +MenuData_t MenuData; + +// Menuitem Drawing functions ================================================= + +void Draw_Title(TitleClass* title) { + DWIN_Draw_Rectangle(1, HMI_data.TitleBg_color, 0, 0, DWIN_WIDTH - 1, TITLE_HEIGHT - 1); + if (title->frameid) + DWIN_Frame_AreaCopy(title->frameid, title->frame.left, title->frame.top, title->frame.right, title->frame.bottom, 14, (TITLE_HEIGHT - (title->frame.bottom - title->frame.top)) / 2 - 1); + else + DWIN_Draw_String(false, DWIN_FONT_HEAD, HMI_data.TitleTxt_color, HMI_data.TitleBg_color, 14, (TITLE_HEIGHT - DWINUI::fontHeight(DWIN_FONT_HEAD)) / 2 - 1, title->caption); +} + +void Draw_Menu(MenuClass* menu) { + DWINUI::SetColors(HMI_data.Text_Color, HMI_data.Background_Color, HMI_data.StatusBg_Color); + DWIN_Draw_Rectangle(1, DWINUI::backcolor, 0, TITLE_HEIGHT, DWIN_WIDTH - 1, STATUS_Y - 1); +} + +void Draw_Menu_Cursor(const int8_t line) { + DWIN_Draw_Rectangle(1, HMI_data.Cursor_color, 0, MBASE(line) - 18, 14, MBASE(line + 1) - 20); +} + +void Erase_Menu_Cursor(const int8_t line) { + DWIN_Draw_Rectangle(1, HMI_data.Background_Color, 0, MBASE(line) - 18, 14, MBASE(line + 1) - 20); +} + +void Draw_Menu_Line(const uint8_t line, const uint8_t icon /*=0*/, const char * const label /*=nullptr*/, bool more /*=false*/) { + if (icon) DWINUI::Draw_Icon(icon, ICOX, MBASE(line) - 3); + if (label) DWINUI::Draw_String(LBLX, MBASE(line) - 1, (char*)label); + if (more) DWINUI::Draw_Icon(ICON_More, VALX + 16, MBASE(line) - 3); + DWIN_Draw_HLine(HMI_data.SplitLine_Color, 16, MYPOS(line + 1), 240); +} + +void Draw_Chkb_Line(const uint8_t line, const bool checked) { + DWINUI::Draw_Checkbox(HMI_data.Text_Color, HMI_data.Background_Color, VALX + 16, MBASE(line) - 1, checked); +} + +void Draw_Menu_IntValue(uint16_t bcolor, const uint8_t line, uint8_t iNum, const int32_t value /*=0*/) { + DWINUI::Draw_Signed_Int(HMI_data.Text_Color, bcolor, iNum , VALX, MBASE(line) - 1, value); +} + +void onDrawMenuItem(MenuItemClass* menuitem, int8_t line) { + if (menuitem->icon) DWINUI::Draw_Icon(menuitem->icon, ICOX, MBASE(line) - 3); + if (menuitem->frameid) + DWIN_Frame_AreaCopy(menuitem->frameid, menuitem->frame.left, menuitem->frame.top, menuitem->frame.right, menuitem->frame.bottom, LBLX, MBASE(line)); + else if (menuitem->caption) + DWINUI::Draw_String(LBLX, MBASE(line) - 1, menuitem->caption); + DWIN_Draw_HLine(HMI_data.SplitLine_Color, 16, MYPOS(line + 1), 240); +} + +void onDrawSubMenu(MenuItemClass* menuitem, int8_t line) { + onDrawMenuItem(menuitem, line); + DWINUI::Draw_Icon(ICON_More, VALX + 16, MBASE(line) - 3); +} + +void onDrawIntMenu(MenuItemClass* menuitem, int8_t line, int32_t value) { + onDrawMenuItem(menuitem, line); + Draw_Menu_IntValue(HMI_data.Background_Color, line, 4, value); +} + +void onDrawPIntMenu(MenuItemClass* menuitem, int8_t line) { + const int16_t value = *(int16_t*)static_cast(menuitem)->value; + onDrawIntMenu(menuitem, line, value); +} + +void onDrawPInt8Menu(MenuItemClass* menuitem, int8_t line) { + const uint8_t value = *(uint8_t*)static_cast(menuitem)->value; + onDrawIntMenu(menuitem, line, value); +} + +void onDrawPInt32Menu(MenuItemClass* menuitem, int8_t line) { + const uint32_t value = *(uint32_t*)static_cast(menuitem)->value; + onDrawIntMenu(menuitem, line, value); +} + +void onDrawFloatMenu(MenuItemClass* menuitem, int8_t line, uint8_t dp, const float value) { + onDrawMenuItem(menuitem, line); + DWINUI::Draw_Signed_Float(HMI_data.Text_Color, HMI_data.Background_Color, 3, dp, VALX - dp * DWINUI::fontWidth(DWIN_FONT_MENU), MBASE(line), value); +} + +void onDrawPFloatMenu(MenuItemClass* menuitem, int8_t line) { + const float value = *(float*)static_cast(menuitem)->value; + const int8_t dp = UNITFDIGITS; + onDrawFloatMenu(menuitem, line, dp, value); +} + +void onDrawPFloat2Menu(MenuItemClass* menuitem, int8_t line) { + const float value = *(float*)static_cast(menuitem)->value; + onDrawFloatMenu(menuitem, line, 2, value); +} + +void onDrawChkbMenu(MenuItemClass* menuitem, int8_t line, bool checked) { + onDrawMenuItem(menuitem, line); + Draw_Chkb_Line(line, checked); +} + +//----------------------------------------------------------------------------- +// On click functions +//----------------------------------------------------------------------------- + +// Generic onclick event without draw +// process: process id HMI destiny +// lo: low limit +// hi: high limit +// dp: decimal places, 0 for integers +// val: value / scaled value +// LiveUpdate: live update function when the encoder changes +// Apply: update function when the encoder is pressed +void SetOnClick(uint8_t process, const int32_t lo, const int32_t hi, uint8_t dp, const int32_t val, void (*Apply)() /*= nullptr*/, void (*LiveUpdate)() /*= nullptr*/) { + checkkey = process; + MenuData.MinValue = lo; + MenuData.MaxValue = hi; + MenuData.dp = dp; + MenuData.Apply = Apply; + MenuData.LiveUpdate = LiveUpdate; + MenuData.Value = val; + EncoderRate.enabled = true; +} + +// Generic onclick event for integer values +// process: process id HMI destiny +// lo: scaled low limit +// hi: scaled high limit +// val: value +// LiveUpdate: live update function when the encoder changes +// Apply: update function when the encoder is pressed +void SetValueOnClick(uint8_t process, const int32_t lo, const int32_t hi, const int32_t val, void (*Apply)() /*= nullptr*/, void (*LiveUpdate)() /*= nullptr*/) { + SetOnClick(process, lo, hi, 0, val, Apply, LiveUpdate); + Draw_Menu_IntValue(HMI_data.Selected_Color, CurrentMenu->line(), 4, MenuData.Value); +} + +// Generic onclick event for float values +// process: process id HMI destiny +// lo: scaled low limit +// hi: scaled high limit +// val: value +// LiveUpdate: live update function when the encoder changes +// Apply: update function when the encoder is pressed +void SetValueOnClick(uint8_t process, const float lo, const float hi, uint8_t dp, const float val, void (*Apply)() /*= nullptr*/, void (*LiveUpdate)() /*= nullptr*/) { + const int32_t value = round(val * POW(10, dp)); + SetOnClick(process, lo * POW(10, dp), hi * POW(10, dp), dp, value, Apply, LiveUpdate); + DWINUI::Draw_Signed_Float(HMI_data.Text_Color, HMI_data.Selected_Color, 3, dp, VALX - dp * DWINUI::fontWidth(DWIN_FONT_MENU), MBASE(CurrentMenu->line()), val); +} + +// Generic onclick event for integer values +// lo: scaled low limit +// hi: scaled high limit +// val: value +// LiveUpdate: live update function when the encoder changes +// Apply: update function when the encoder is pressed +void SetIntOnClick(const int32_t lo, const int32_t hi, const int32_t val, void (*Apply)() /*= nullptr*/, void (*LiveUpdate)() /*= nullptr*/) { + SetValueOnClick(SetInt, lo, hi, val, Apply, LiveUpdate); +} + +// Generic onclick event for set pointer to 16 bit uinteger values +// lo: low limit +// hi: high limit +// LiveUpdate: live update function when the encoder changes +// Apply: update function when the encoder is pressed +void SetPIntOnClick(const int32_t lo, const int32_t hi, void (*Apply)() /*= nullptr*/, void (*LiveUpdate)() /*= nullptr*/) { + MenuData.P_Int = (int16_t*)static_cast(CurrentMenu->SelectedItem())->value; + const int32_t value = *MenuData.P_Int; + SetValueOnClick(SetPInt, lo, hi, value, Apply, LiveUpdate); +} + +// Generic onclick event for float values +// process: process id HMI destiny +// lo: low limit +// hi: high limit +// dp: decimal places +// val: value +void SetFloatOnClick(const float lo, const float hi, uint8_t dp, const float val, void (*Apply)() /*= nullptr*/, void (*LiveUpdate)() /*= nullptr*/) { + SetValueOnClick(SetFloat, lo, hi, dp, val, Apply, LiveUpdate); +} + +// Generic onclick event for set pointer to float values +// lo: low limit +// hi: high limit +// LiveUpdate: live update function when the encoder changes +// Apply: update function when the encoder is pressed +void SetPFloatOnClick(const float lo, const float hi, uint8_t dp, void (*Apply)() /*= nullptr*/, void (*LiveUpdate)() /*= nullptr*/) { + MenuData.P_Float = (float*)static_cast(CurrentMenu->SelectedItem())->value; + SetValueOnClick(SetPFloat, lo, hi, dp, *MenuData.P_Float, Apply, LiveUpdate); +} + +// HMI Control functions ====================================================== + +// Generic menu control using the encoder +void HMI_Menu() { + EncoderState encoder_diffState = get_encoder_state(); + if (encoder_diffState == ENCODER_DIFF_NO) return; + if (CurrentMenu) { + if (encoder_diffState == ENCODER_DIFF_ENTER) + CurrentMenu->onClick(); + else + CurrentMenu->onScroll(encoder_diffState == ENCODER_DIFF_CW); + } +} + +// Get an integer value using the encoder without draw anything +// lo: low limit +// hi: high limit +// Return value: +// 0 : no change +// 1 : live change +// 2 : apply change +int8_t HMI_GetIntNoDraw(const int32_t lo, const int32_t hi) { + EncoderState encoder_diffState = Encoder_ReceiveAnalyze(); + if (encoder_diffState != ENCODER_DIFF_NO) { + if (Apply_Encoder(encoder_diffState, MenuData.Value)) { + EncoderRate.enabled = false; + checkkey = Menu; + return 2; + } + LIMIT(MenuData.Value, lo, hi); + return 1; + } + return 0; +} + +// Get an integer value using the encoder +// lo: low limit +// hi: high limit +// Return value: +// 0 : no change +// 1 : live change +// 2 : apply change +int8_t HMI_GetInt(const int32_t lo, const int32_t hi) { + EncoderState encoder_diffState = Encoder_ReceiveAnalyze(); + if (encoder_diffState != ENCODER_DIFF_NO) { + if (Apply_Encoder(encoder_diffState, MenuData.Value)) { + EncoderRate.enabled = false; + DWINUI::Draw_Signed_Int(HMI_data.Text_Color, HMI_data.Background_Color, 4 , VALX, MBASE(CurrentMenu->line()) - 1, MenuData.Value); + checkkey = Menu; + return 2; + } + LIMIT(MenuData.Value, lo, hi); + DWINUI::Draw_Signed_Int(HMI_data.Text_Color, HMI_data.Selected_Color, 4 , VALX, MBASE(CurrentMenu->line()) - 1, MenuData.Value); + return 1; + } + return 0; +} + +// Set an integer using the encoder +void HMI_SetInt() { + int8_t val = HMI_GetInt(MenuData.MinValue, MenuData.MaxValue); + switch (val) { + case 0: return; break; + case 1: if (MenuData.LiveUpdate) MenuData.LiveUpdate(); break; + case 2: if (MenuData.Apply) MenuData.Apply(); break; + } +} + +// Set an integer without drawing +void HMI_SetIntNoDraw() { + int8_t val = HMI_GetIntNoDraw(MenuData.MinValue, MenuData.MaxValue); + switch (val) { + case 0: return; break; + case 1: if (MenuData.LiveUpdate) MenuData.LiveUpdate(); break; + case 2: if (MenuData.Apply) MenuData.Apply(); break; + } +} + +// Set an integer pointer variable using the encoder +void HMI_SetPInt() { + int8_t val = HMI_GetInt(MenuData.MinValue, MenuData.MaxValue); + switch (val) { + case 0: return; + case 1: if (MenuData.LiveUpdate) MenuData.LiveUpdate(); break; + case 2: *MenuData.P_Int = MenuData.Value; if (MenuData.Apply) MenuData.Apply(); break; + } +} + +// Get a scaled float value using the encoder +// dp: decimal places +// lo: scaled low limit +// hi: scaled high limit +// Return value: +// 0 : no change +// 1 : live change +// 2 : apply change +int8_t HMI_GetFloat(uint8_t dp, int32_t lo, int32_t hi) { + EncoderState encoder_diffState = Encoder_ReceiveAnalyze(); + if (encoder_diffState != ENCODER_DIFF_NO) { + if (Apply_Encoder(encoder_diffState, MenuData.Value)) { + EncoderRate.enabled = false; + DWINUI::Draw_Signed_Float(HMI_data.Text_Color, HMI_data.Background_Color, 3, dp, VALX - dp * DWINUI::fontWidth(DWIN_FONT_MENU), MBASE(CurrentMenu->line()), MenuData.Value / POW(10, dp)); + checkkey = Menu; + return 2; + } + LIMIT(MenuData.Value, lo, hi); + DWINUI::Draw_Signed_Float(HMI_data.Text_Color, HMI_data.Selected_Color, 3, dp, VALX - dp * DWINUI::fontWidth(DWIN_FONT_MENU), MBASE(CurrentMenu->line()), MenuData.Value / POW(10, dp)); + return 1; + } + return 0; +} + +// Set a scaled float using the encoder +void HMI_SetFloat() { + const int8_t val = HMI_GetFloat(MenuData.dp, MenuData.MinValue, MenuData.MaxValue); + switch (val) { + case 0: return; + case 1: if (MenuData.LiveUpdate) MenuData.LiveUpdate(); break; + case 2: if (MenuData.Apply) MenuData.Apply(); break; + } +} + +// Set a scaled float pointer variable using the encoder +void HMI_SetPFloat() { + const int8_t val = HMI_GetFloat(MenuData.dp, MenuData.MinValue, MenuData.MaxValue); + switch (val) { + case 0: return; + case 1: if (MenuData.LiveUpdate) MenuData.LiveUpdate(); break; + case 2: *MenuData.P_Float = MenuData.Value / POW(10, MenuData.dp); if (MenuData.Apply) MenuData.Apply(); break; + } +} + +#endif // DWIN_LCD_PROUI diff --git a/Marlin/src/lcd/e3v2/proui/menus.h b/Marlin/src/lcd/e3v2/proui/menus.h new file mode 100644 index 0000000000..0147c1616b --- /dev/null +++ b/Marlin/src/lcd/e3v2/proui/menus.h @@ -0,0 +1,94 @@ +/** + * 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 . + * + */ + +/** + * Menu functions for ProUI + * Author: Miguel A. Risco-Castillo + * Version: 1.2.1 + * Date: 2022/02/25 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser 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 Lesser General Public License + * along with this program. If not, see . + * + */ +#pragma once + +#include "dwinui.h" + +typedef struct { + int32_t MaxValue = 0; // Auxiliar max integer/scaled float value + int32_t MinValue = 0; // Auxiliar min integer/scaled float value + int8_t dp = 0; // Auxiliar decimal places + int32_t Value = 0; // Auxiliar integer / scaled float value + int16_t *P_Int = nullptr; // Auxiliar pointer to 16 bit integer variable + float *P_Float = nullptr; // Auxiliar pointer to float variable + void (*Apply)() = nullptr; // Auxiliar apply function + void (*LiveUpdate)() = nullptr; // Auxiliar live update function +} MenuData_t; + +extern MenuData_t MenuData; + +// Menuitem Drawing functions ================================================= +void Draw_Title(TitleClass* title); +void Draw_Menu(MenuClass* menu); +void Draw_Menu_Cursor(const int8_t line); +void Erase_Menu_Cursor(const int8_t line); +void Draw_Menu_Line(const uint8_t line, const uint8_t icon=0, const char * const label=nullptr, bool more=false); +void Draw_Chkb_Line(const uint8_t line, const bool checked); +void Draw_Menu_IntValue(uint16_t bcolor, const uint8_t line, uint8_t iNum, const int32_t value=0); +void onDrawMenuItem(MenuItemClass* menuitem, int8_t line); +void onDrawSubMenu(MenuItemClass* menuitem, int8_t line); +void onDrawIntMenu(MenuItemClass* menuitem, int8_t line, int32_t value); +void onDrawPIntMenu(MenuItemClass* menuitem, int8_t line); +void onDrawPInt8Menu(MenuItemClass* menuitem, int8_t line); +void onDrawPInt32Menu(MenuItemClass* menuitem, int8_t line); +void onDrawFloatMenu(MenuItemClass* menuitem, int8_t line, uint8_t dp, const float value); +void onDrawPFloatMenu(MenuItemClass* menuitem, int8_t line); +void onDrawPFloat2Menu(MenuItemClass* menuitem, int8_t line); +void onDrawChkbMenu(MenuItemClass* menuitem, int8_t line, bool checked); + +// On click functions ========================================================= +void SetOnClick(uint8_t process, const int32_t lo, const int32_t hi, uint8_t dp, const int32_t val, void (*Apply)() = nullptr, void (*LiveUpdate)() = nullptr); +void SetValueOnClick(uint8_t process, const int32_t lo, const int32_t hi, const int32_t val, void (*Apply)() = nullptr, void (*LiveUpdate)() = nullptr); +void SetValueOnClick(uint8_t process, const float lo, const float hi, uint8_t dp, const float val, void (*Apply)() = nullptr, void (*LiveUpdate)() = nullptr); +void SetIntOnClick(const int32_t lo, const int32_t hi, const int32_t val, void (*Apply)() = nullptr, void (*LiveUpdate)() = nullptr); +void SetPIntOnClick(const int32_t lo, const int32_t hi, void (*Apply)() = nullptr, void (*LiveUpdate)() = nullptr); +void SetFloatOnClick(const float lo, const float hi, uint8_t dp, const float val, void (*Apply)() = nullptr, void (*LiveUpdate)() = nullptr); +void SetPFloatOnClick(const float lo, const float hi, uint8_t dp, void (*Apply)() = nullptr, void (*LiveUpdate)() = nullptr); + +// HMI user control functions ================================================= +void HMI_Menu(); +void HMI_SetInt(); +void HMI_SetPInt(); +void HMI_SetIntNoDraw(); +void HMI_SetFloat(); +void HMI_SetPFloat(); diff --git a/Marlin/src/lcd/e3v2/proui/meshviewer.cpp b/Marlin/src/lcd/e3v2/proui/meshviewer.cpp index 0f63f77b99..0b22ae98d5 100644 --- a/Marlin/src/lcd/e3v2/proui/meshviewer.cpp +++ b/Marlin/src/lcd/e3v2/proui/meshviewer.cpp @@ -21,17 +21,15 @@ */ /** - * DWIN Mesh Viewer + * Mesh Viewer for PRO UI * Author: Miguel A. Risco-Castillo (MRISCOC) - * Version: 3.9.1 - * Date: 2021/11/09 - * - * Based on the original code provided by Creality under GPL + * version: 3.12.1 + * Date: 2022/02/24 */ #include "../../../inc/MarlinConfigPre.h" -#if BOTH(DWIN_CREALITY_LCD_ENHANCED, HAS_MESH) +#if BOTH(DWIN_LCD_PROUI, HAS_MESH) #include "meshviewer.h" @@ -40,49 +38,53 @@ #include "dwin_lcd.h" #include "dwinui.h" #include "dwin.h" +#include "dwin_popup.h" #include "../../../feature/bedlevel/bedlevel.h" MeshViewerClass MeshViewer; -void MeshViewerClass::Draw() { +void MeshViewerClass::DrawMesh(bed_mesh_t zval, const uint8_t sizex, const uint8_t sizey) { const int8_t mx = 25, my = 25; // Margins - const int16_t stx = (DWIN_WIDTH - 2 * mx) / (GRID_MAX_POINTS_X - 1), // Steps - sty = (DWIN_WIDTH - 2 * my) / (GRID_MAX_POINTS_Y - 1); + const int16_t stx = (DWIN_WIDTH - 2 * mx) / (sizex - 1), // Steps + sty = (DWIN_WIDTH - 2 * my) / (sizey - 1); const int8_t rmax = _MIN(mx - 2, stx / 2); const int8_t rmin = 7; - int16_t zmesh[GRID_MAX_POINTS_X][GRID_MAX_POINTS_Y], maxz =-32000, minz = 32000; + int16_t zmesh[sizex][sizey]; #define px(xp) (mx + (xp) * stx) #define py(yp) (30 + DWIN_WIDTH - my - (yp) * sty) #define rm(z) ((z - minz) * (rmax - rmin) / _MAX(1, (maxz - minz)) + rmin) - #define DrawMeshValue(xp, yp, zv) DWINUI::Draw_Signed_Float(font6x12, 1, 2, px(xp) - 12, py(yp) - 6, zv) + #define DrawMeshValue(xp, yp, zv) DWINUI::Draw_Signed_Float(font6x12, 1, 2, px(xp) - 18, py(yp) - 6, zv) #define DrawMeshHLine(yp) DWIN_Draw_HLine(HMI_data.SplitLine_Color, px(0), py(yp), DWIN_WIDTH - 2 * mx) - #define DrawMeshVLine(xp) DWIN_Draw_VLine(HMI_data.SplitLine_Color, px(xp), py(GRID_MAX_POINTS_Y - 1), DWIN_WIDTH - 2 * my) - GRID_LOOP(x, y) { - const float v = isnan(Z_VALUES(x,y)) ? 0 : round(Z_VALUES(x,y) * 100); + #define DrawMeshVLine(xp) DWIN_Draw_VLine(HMI_data.SplitLine_Color, px(xp), py(sizey - 1), DWIN_WIDTH - 2 * my) + int16_t maxz =-32000; int16_t minz = 32000; avg = 0; + LOOP_L_N(y, sizey) LOOP_L_N(x, sizex) { + const float v = isnan(zval[x][y]) ? 0 : round(zval[x][y] * 100); zmesh[x][y] = v; + avg += v; NOLESS(maxz, v); NOMORE(minz, v); } - Title.ShowCaption(F("Mesh Viewer")); + max = (float)maxz / 100; + min = (float)minz / 100; + avg = avg / (100 * sizex * sizey); DWINUI::ClearMenuArea(); - DWINUI::Draw_Icon(ICON_Continue_E, 86, 305); - DWIN_Draw_Rectangle(0, HMI_data.SplitLine_Color, px(0), py(0), px(GRID_MAX_POINTS_X - 1), py(GRID_MAX_POINTS_Y - 1)); - LOOP_S_L_N(x, 1, GRID_MAX_POINTS_X - 1) DrawMeshVLine(x); - LOOP_S_L_N(y, 1, GRID_MAX_POINTS_Y - 1) DrawMeshHLine(y); - LOOP_L_N(y, GRID_MAX_POINTS_Y) { + DWIN_Draw_Rectangle(0, HMI_data.SplitLine_Color, px(0), py(0), px(sizex - 1), py(sizey - 1)); + LOOP_S_L_N(x, 1, sizex - 1) DrawMeshVLine(x); + LOOP_S_L_N(y, 1, sizey - 1) DrawMeshHLine(y); + LOOP_L_N(y, sizey) { watchdog_refresh(); - LOOP_L_N(x, GRID_MAX_POINTS_X) { + LOOP_L_N(x, sizex) { uint16_t color = DWINUI::RainbowInt(zmesh[x][y], _MIN(-5, minz), _MAX(5, maxz)); uint8_t radius = rm(zmesh[x][y]); DWINUI::Draw_FillCircle(color, px(x), py(y), radius); - if (GRID_MAX_POINTS_X < 9) - DWINUI::Draw_Signed_Float(font6x12, 1, 2, px(x) - 12, py(y) - 6, Z_VALUES(x,y)); + if (sizex < 9) + DWINUI::Draw_Signed_Float(font6x12, 1, 2, px(x) - 18, py(y) - 6, zval[x][y]); else { char str_1[9]; str_1[0] = 0; switch (zmesh[x][y]) { case -999 ... -100: - DWINUI::Draw_Signed_Float(font6x12, 1, 1, px(x) - 12, py(y) - 6, Z_VALUES(x,y)); + DWINUI::Draw_Signed_Float(font6x12, 1, 1, px(x) - 18, py(y) - 6, zval[x][y]); break; case -99 ... -1: sprintf_P(str_1, PSTR("-.%02i"), -zmesh[x][y]); @@ -94,7 +96,7 @@ void MeshViewerClass::Draw() { sprintf_P(str_1, PSTR(".%02i"), zmesh[x][y]); break; case 100 ... 999: - DWINUI::Draw_Signed_Float(font6x12, 1, 1, px(x) - 12, py(y) - 6, Z_VALUES(x,y)); + DWINUI::Draw_Signed_Float(font6x12, 1, 1, px(x) - 18, py(y) - 6, zval[x][y]); break; } if (str_1[0]) @@ -102,11 +104,25 @@ void MeshViewerClass::Draw() { } } } +} + +void MeshViewerClass::Draw(bool withsave /*= false*/) { + Title.ShowCaption(F("Mesh Viewer")); + DrawMesh(Z_VALUES_ARR, GRID_MAX_POINTS_X, GRID_MAX_POINTS_Y); + if (withsave) { + DWINUI::Draw_Button(BTN_Save, 26, 305); + DWINUI::Draw_Button(BTN_Continue, 146, 305); + Draw_Select_Highlight(HMI_flag.select_flag, 305); + } else DWINUI::Draw_Button(BTN_Continue, 86, 305); char str_1[6], str_2[6] = ""; ui.status_printf(0, F("Mesh minZ: %s, maxZ: %s"), - dtostrf((float)minz / 100, 1, 2, str_1), - dtostrf((float)maxz / 100, 1, 2, str_2) + dtostrf(min, 1, 2, str_1), + dtostrf(max, 1, 2, str_2) ); } -#endif // DWIN_CREALITY_LCD_ENHANCED && HAS_MESH +void Draw_MeshViewer() { MeshViewer.Draw(true); } +void onClick_MeshViewer() { if (HMI_flag.select_flag) WriteEeprom(); HMI_ReturnScreen(); } +void Goto_MeshViewer() { if (leveling_is_valid()) Goto_Popup(Draw_MeshViewer, onClick_MeshViewer); else HMI_ReturnScreen(); } + +#endif // DWIN_LCD_PROUI && HAS_MESH diff --git a/Marlin/src/lcd/e3v2/proui/meshviewer.h b/Marlin/src/lcd/e3v2/proui/meshviewer.h index acd5f0d5c4..f914bab4ae 100644 --- a/Marlin/src/lcd/e3v2/proui/meshviewer.h +++ b/Marlin/src/lcd/e3v2/proui/meshviewer.h @@ -21,18 +21,23 @@ */ #pragma once +#include "../../../core/types.h" +#include "../../../feature/bedlevel/bedlevel.h" + /** - * DWIN Mesh Viewer + * Mesh Viewer for PRO UI * Author: Miguel A. Risco-Castillo (MRISCOC) - * Version: 3.9.1 - * Date: 2021/11/09 - * - * Based on the original code provided by Creality under GPL + * version: 3.12.1 + * Date: 2022/02/24 */ class MeshViewerClass { public: - void Draw(); + float avg, max, min; + void Draw(bool withsave = false); + void DrawMesh(bed_mesh_t zval, const uint8_t sizex, const uint8_t sizey); }; extern MeshViewerClass MeshViewer; + +void Goto_MeshViewer(); diff --git a/Marlin/src/lcd/e3v2/proui/printstats.cpp b/Marlin/src/lcd/e3v2/proui/printstats.cpp index ec14ebb8bf..d4ca4ca225 100644 --- a/Marlin/src/lcd/e3v2/proui/printstats.cpp +++ b/Marlin/src/lcd/e3v2/proui/printstats.cpp @@ -21,21 +21,20 @@ */ /** - * DWIN Print Stats page + * Print Stats page for PRO UI * Author: Miguel A. Risco-Castillo (MRISCOC) - * Version: 1.1 - * Date: 2022/01/09 - * - * Based on the original code provided by Creality under GPL + * Version: 1.3.0 + * Date: 2022/02/24 */ #include "../../../inc/MarlinConfigPre.h" -#if BOTH(DWIN_CREALITY_LCD_ENHANCED, PRINTCOUNTER) +#if BOTH(DWIN_LCD_PROUI, PRINTCOUNTER) #include "printstats.h" #include "../../../core/types.h" +#include "../../../MarlinCore.h" #include "../../marlinui.h" #include "../../../module/printcounter.h" #include "dwin_lcd.h" @@ -53,7 +52,7 @@ void PrintStatsClass::Draw() { Title.ShowCaption(GET_TEXT_F(MSG_INFO_STATS_MENU)); DWINUI::ClearMenuArea(); Draw_Popup_Bkgd(); - DWINUI::Draw_Icon(ICON_Continue_E, 86, 250); + DWINUI::Draw_Button(BTN_Continue, 86, 250); printStatistics ps = print_job_timer.getStats(); sprintf_P(buf, PSTR(S_FMT ": %i"), GET_TEXT(MSG_INFO_PRINT_COUNT), ps.totalPrints); @@ -75,4 +74,9 @@ void PrintStatsClass::Reset() { HMI_AudioFeedback(); } -#endif // DWIN_CREALITY_LCD_ENHANCED && PRINTCOUNTER +void Goto_PrintStats() { + PrintStats.Draw(); + HMI_SaveProcessID(WaitResponse); +} + +#endif // DWIN_LCD_PROUI && PRINTCOUNTER diff --git a/Marlin/src/lcd/e3v2/proui/printstats.h b/Marlin/src/lcd/e3v2/proui/printstats.h index f17e4dc9dd..705c923da4 100644 --- a/Marlin/src/lcd/e3v2/proui/printstats.h +++ b/Marlin/src/lcd/e3v2/proui/printstats.h @@ -22,18 +22,18 @@ #pragma once /** - * DWIN Print Stats page + * Print Stats page for PRO UI * Author: Miguel A. Risco-Castillo (MRISCOC) - * Version: 1.1 - * Date: 2022/01/09 - * - * Based on the original code provided by Creality under GPL + * Version: 1.3.0 + * Date: 2022/02/24 */ class PrintStatsClass { public: - void Draw(); + static void Draw(); static void Reset(); }; extern PrintStatsClass PrintStats; + +void Goto_PrintStats(); diff --git a/Marlin/src/lcd/extui/anycubic_chiron/FileNavigator.cpp b/Marlin/src/lcd/extui/anycubic_chiron/FileNavigator.cpp index f49b17acc1..0ef8186668 100644 --- a/Marlin/src/lcd/extui/anycubic_chiron/FileNavigator.cpp +++ b/Marlin/src/lcd/extui/anycubic_chiron/FileNavigator.cpp @@ -155,7 +155,7 @@ void FileNavigator::skiptofileindex(uint16_t skip) { if (currentindex == 0 && currentfolderdepth > 0) { // Add a link to go up a folder // The new panel ignores entries that don't end in .GCO or .gcode so add and pad them. - if (paneltype == AC_panel_new) { + if (paneltype <= AC_panel_new) { TFTSer.println("<<.GCO"); Chiron.SendtoTFTLN(F(".. .gcode")); } @@ -177,7 +177,7 @@ void FileNavigator::skiptofileindex(uint16_t skip) { void FileNavigator::sendFile(panel_type_t paneltype) { if (filelist.isDir()) { // Add mandatory tags for new panel otherwise lines are ignored. - if (paneltype == AC_panel_new) { + if (paneltype <= AC_panel_new) { TFTSer.print(filelist.shortFilename()); TFTSer.println(".GCO"); TFTSer.print(filelist.shortFilename()); diff --git a/Marlin/src/lcd/extui/anycubic_chiron/chiron_extui.cpp b/Marlin/src/lcd/extui/anycubic_chiron/chiron_extui.cpp index 7a58963c11..75061c162a 100644 --- a/Marlin/src/lcd/extui/anycubic_chiron/chiron_extui.cpp +++ b/Marlin/src/lcd/extui/anycubic_chiron/chiron_extui.cpp @@ -57,14 +57,16 @@ namespace ExtUI { void onPrintTimerStarted() { Chiron.TimerEvent(AC_timer_started); } void onPrintTimerPaused() { Chiron.TimerEvent(AC_timer_paused); } - void onPrintTimerStopped() { Chiron.TimerEvent(AC_timer_stopped); } + void onPrintTimerStopped() { Chiron.TimerEvent(AC_timer_stopped); } + void onPrintDone() {} + void onFilamentRunout(const extruder_t) { Chiron.FilamentRunout(); } + void onUserConfirmRequired(const char * const msg) { Chiron.ConfirmationRequest(msg); } void onStatusChanged(const char * const msg) { Chiron.StatusChange(msg); } void onHomingStart() {} - void onHomingComplete() {} - void onPrintFinished() {} + void onHomingDone() {} void onFactoryReset() {} @@ -92,18 +94,19 @@ 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. } #if HAS_MESH - void onMeshLevelingStart() {} + void onLevelingStart() {} + void onLevelingDone() {} void onMeshUpdate(const int8_t xpos, const int8_t ypos, const_float_t zval) { // Called when any mesh points are updated diff --git a/Marlin/src/lcd/extui/anycubic_chiron/chiron_tft.cpp b/Marlin/src/lcd/extui/anycubic_chiron/chiron_tft.cpp index c56d8aa7fb..b2ef733355 100644 --- a/Marlin/src/lcd/extui/anycubic_chiron/chiron_tft.cpp +++ b/Marlin/src/lcd/extui/anycubic_chiron/chiron_tft.cpp @@ -80,19 +80,26 @@ void ChironTFT::Startup() { OUT_WRITE(OUTAGECON_PIN, HIGH); #endif - // Filament runout is handled by Marlin settings in Configuration.h - // opt_set FIL_RUNOUT_STATE HIGH // Pin state indicating that filament is NOT present. - // opt_enable FIL_RUNOUT_PULLUP TFTSer.begin(115200); - // wait for the TFT panel to initialise and finish the animation - delay_ms(250); + // 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 // So we need to know what we are working with. - // Panel type can be defined otherwise detect it automatically - if (panel_type == AC_panel_unknown) DetectPanelType(); + switch (panel_type) { + case AC_panel_new: + SERIAL_ECHOLNF(AC_msg_new_panel_set); + break; + case AC_panel_standard: + SERIAL_ECHOLNF(AC_msg_old_panel_set); + break; + default: + SERIAL_ECHOLNF(AC_msg_auto_panel_detection); + DetectPanelType(); + break; + } // Signal Board has reset SendtoTFTLN(AC_msg_main_board_has_reset); @@ -358,15 +365,14 @@ bool ChironTFT::ReadTFTCommand() { } int8_t ChironTFT::FindToken(char c) { - int8_t pos = 0; - do { + for (int8_t pos = 0; pos < command_len; pos++) { if (panel_command[pos] == c) { #if ACDEBUG(AC_INFO) SERIAL_ECHOLNPGM("Tpos:", pos, " ", c); #endif return pos; } - } while (++pos < command_len); + } #if ACDEBUG(AC_INFO) SERIAL_ECHOLNPGM("Not found: ", c); #endif @@ -433,7 +439,7 @@ void ChironTFT::SendFileList(int8_t startindex) { } void ChironTFT::SelectFile() { - if (panel_type == AC_panel_new) { + if (panel_type <= AC_panel_new) { strncpy(selectedfile, panel_command + 4, command_len - 3); selectedfile[command_len - 4] = '\0'; } @@ -456,7 +462,7 @@ void ChironTFT::SelectFile() { break; default: // enter sub folder // for new panel remove the '.GCO' tag that was added to the end of the path - if (panel_type == AC_panel_new) + if (panel_type <= AC_panel_new) selectedfile[strlen(selectedfile) - 4] = '\0'; filenavigator.changeDIR(selectedfile); SendtoTFTLN(AC_msg_sd_file_open_failed); @@ -469,8 +475,8 @@ void ChironTFT::ProcessPanelRequest() { // Break these up into logical blocks // as its easier to navigate than one huge switch case! int8_t tpos = FindToken('A'); // Panel request are 'A0' - 'A36' - if (tpos != -1) { - const int8_t req = atoi(&panel_command[tpos+1]); + if (tpos >= 0) { + const int8_t req = atoi(&panel_command[tpos + 1]); // Information requests A0 - A8 and A33 if (req <= 8 || req == 33) PanelInfo(req); @@ -486,16 +492,18 @@ void ChironTFT::ProcessPanelRequest() { // This may be a response to a panel type detection query if (panel_type == AC_panel_unknown) { tpos = FindToken('S'); // old panel will respond to 'SIZE' with 'SXY 480 320' - if (tpos != -1) { - if (panel_command[tpos+1]== 'X' && panel_command[tpos+2]=='Y') { + if (tpos >= 0) { + if (panel_command[tpos + 1] == 'X' && panel_command[tpos + 2] =='Y') { panel_type = AC_panel_standard; SERIAL_ECHOLNF(AC_msg_old_panel_detected); } } else { - tpos = FindToken('['); // new panel will respond to 'J200' with '[0]=0' - if (tpos != -1) { - if (panel_command[tpos+1]== '0' && panel_command[tpos+2]==']') { + // new panel will respond to 'J200' with '[0]=0' + // it seems only after a power cycle so detection assumes a new panel + tpos = FindToken('['); + if (tpos >= 0) { + if (panel_command[tpos + 1] == '0' && panel_command[tpos + 2] ==']') { panel_type = AC_panel_new; SERIAL_ECHOLNF(AC_msg_new_panel_detected); } @@ -623,18 +631,18 @@ void ChironTFT::PanelAction(uint8_t req) { SelectFile(); break; - case 14: { // A14 Start Printing + case 14: // A14 Start Printing // Allows printer to restart the job if we don't want to recover if (printer_state == AC_printer_resuming_from_power_outage) { injectCommands(F("M1000 C")); // Cancel recovery printer_state = AC_printer_idle; } #if ACDebugLevel >= 1 - SERIAL_ECHOLNPAIR_F("Print: ", selectedfile); + SERIAL_ECHOLNPGM("Print: ", selectedfile); #endif printFile(selectedfile); SendtoTFTLN(AC_msg_print_from_sd_card); - } break; + break; case 15: // A15 Resuming from outage if (printer_state == AC_printer_resuming_from_power_outage) { @@ -801,28 +809,25 @@ void ChironTFT::PanelProcess(uint8_t req) { } } break; - case 30: { // A30 Auto leveling - if (FindToken('S') != -1) { // Start probing New panel adds spaces.. + case 30: // A30 Auto leveling + if (FindToken('S') >= 0) { // Start probing New panel adds spaces.. // Ignore request if printing if (isPrinting()) SendtoTFTLN(AC_msg_probing_not_allowed); // forbid auto leveling else { - - SendtoTFTLN(AC_msg_start_probing); injectCommands(F("G28\nG29")); printer_state = AC_printer_probing; } } - else { + else SendtoTFTLN(AC_msg_start_probing); // Just enter levelling menu - } - } break; + break; - case 31: { // A31 Adjust all Probe Points + case 31: // A31 Adjust all Probe Points // The tokens can occur in different places on the new panel so we need to find it. - if (FindToken('C') != -1) { // Restore and apply original offsets + if (FindToken('C') >= 0) { // Restore and apply original offsets if (!isPrinting()) { injectCommands(F("M501\nM420 S1")); selectedmeshpoint.x = selectedmeshpoint.y = 99; @@ -830,7 +835,7 @@ void ChironTFT::PanelProcess(uint8_t req) { } } - else if (FindToken('D') != -1) { // Save Z Offset tables and restore leveling state + else if (FindToken('D') >= 0) { // Save Z Offset tables and restore leveling state if (!isPrinting()) { setAxisPosition_mm(1.0,Z); // Lift nozzle before any further movements are made injectCommands(F("M500")); @@ -839,7 +844,7 @@ void ChironTFT::PanelProcess(uint8_t req) { } } - else if (FindToken('G') != -1) { // Get current offset + else if (FindToken('G') >= 0) { // Get current offset SendtoTFT(F("A31V ")); // When printing use the live z Offset position // we will use babystepping to move the print head @@ -853,7 +858,7 @@ void ChironTFT::PanelProcess(uint8_t req) { else { int8_t tokenpos = FindToken('S'); - if (tokenpos != -1) { // Set offset (adjusts all points by value) + if (tokenpos >= 0) { // Set offset (adjusts all points by value) float Zshift = atof(&panel_command[tokenpos+1]); setSoftEndstopState(false); // disable endstops // Allow temporary Z position nudging during print @@ -907,18 +912,18 @@ void ChironTFT::PanelProcess(uint8_t req) { } } } - } break; + break; - case 32: { // A32 clean leveling beep flag + case 32: // A32 clean leveling beep flag // Ignore request if printing //if (isPrinting()) break; //injectCommands(F("M500\nM420 S1\nG1 Z10 F240\nG1 X0 Y0 F6000")); //TFTSer.println(); - } break; + break; // A33 firmware info request see PanelInfo() - case 34: { // A34 Adjust single mesh point A34 C/S X1 Y1 V123 + case 34: // A34 Adjust single mesh point A34 C/S X1 Y1 V123 if (panel_command[3] == 'C') { // Restore original offsets injectCommands(F("M501\nM420 S1")); selectedmeshpoint.x = selectedmeshpoint.y = 99; @@ -950,7 +955,7 @@ void ChironTFT::PanelProcess(uint8_t req) { } } } - } break; + break; case 36: // A36 Auto leveling for new TFT bet that was a typo in the panel code! SendtoTFTLN(AC_msg_start_probing); diff --git a/Marlin/src/lcd/extui/anycubic_chiron/chiron_tft_defs.h b/Marlin/src/lcd/extui/anycubic_chiron/chiron_tft_defs.h index 0fd7770cdd..e3609b5408 100644 --- a/Marlin/src/lcd/extui/anycubic_chiron/chiron_tft_defs.h +++ b/Marlin/src/lcd/extui/anycubic_chiron/chiron_tft_defs.h @@ -89,6 +89,10 @@ #define AC_msg_mesh_changes_saved F("Mesh changes saved.") #define AC_msg_old_panel_detected F("Standard TFT panel detected!") #define AC_msg_new_panel_detected F("New TFT panel detected!") +#define AC_msg_auto_panel_detection F("Auto detect panel type (assuming new panel)") +#define AC_msg_old_panel_set F("Set for standard TFT panel.") +#define AC_msg_new_panel_set F("Set for new TFT panel.") + #define AC_msg_powerloss_recovery F("Resuming from power outage! select the same SD file then press resume") // Error messages must not contain spaces #define AC_msg_error_bed_temp F("Abnormal_bed_temp") @@ -161,10 +165,10 @@ namespace Anycubic { AC_menu_change_to_file, AC_menu_change_to_command }; - enum panel_type_t : uint8_t { + enum panel_type_t : uint8_t { // order is important here as we assume new panel if type is unknown AC_panel_unknown, - AC_panel_standard, - AC_panel_new + AC_panel_new, + AC_panel_standard }; enum last_error_t : uint8_t { AC_error_none, diff --git a/Marlin/src/lcd/extui/anycubic_i3mega/anycubic_extui.cpp b/Marlin/src/lcd/extui/anycubic_i3mega/anycubic_extui.cpp index c0e1b44578..469202ee22 100644 --- a/Marlin/src/lcd/extui/anycubic_i3mega/anycubic_extui.cpp +++ b/Marlin/src/lcd/extui/anycubic_i3mega/anycubic_extui.cpp @@ -54,8 +54,8 @@ namespace ExtUI { void onStatusChanged(const char * const msg) {} void onHomingStart() {} - void onHomingComplete() {} - void onPrintFinished() {} + void onHomingDone() {} + void onPrintDone() {} void onFactoryReset() {} @@ -83,19 +83,20 @@ 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. } #if HAS_MESH - void onMeshLevelingStart() {} + void onLevelingStart() {} + void onLevelingDone() {} void onMeshUpdate(const int8_t xpos, const int8_t ypos, const_float_t zval) { // Called when any mesh points are updated diff --git a/Marlin/src/lcd/extui/anycubic_i3mega/anycubic_i3mega_lcd.cpp b/Marlin/src/lcd/extui/anycubic_i3mega/anycubic_i3mega_lcd.cpp index 729d4547a8..c382af3fe2 100644 --- a/Marlin/src/lcd/extui/anycubic_i3mega/anycubic_i3mega_lcd.cpp +++ b/Marlin/src/lcd/extui/anycubic_i3mega/anycubic_i3mega_lcd.cpp @@ -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 diff --git a/Marlin/src/lcd/extui/dgus/dgus_extui.cpp b/Marlin/src/lcd/extui/dgus/dgus_extui.cpp index 04ba6b95c2..b041687a14 100644 --- a/Marlin/src/lcd/extui/dgus/dgus_extui.cpp +++ b/Marlin/src/lcd/extui/dgus/dgus_extui.cpp @@ -73,8 +73,8 @@ namespace ExtUI { void onStatusChanged(const char * const msg) { ScreenHandler.setstatusmessage(msg); } void onHomingStart() {} - void onHomingComplete() {} - void onPrintFinished() {} + void onHomingDone() {} + void onPrintDone() {} void onFactoryReset() {} @@ -102,18 +102,19 @@ 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. } #if HAS_MESH - void onMeshLevelingStart() {} + void onLevelingStart() {} + void onLevelingDone() {} void onMeshUpdate(const int8_t xpos, const int8_t ypos, const_float_t zval) { // Called when any mesh points are updated diff --git a/Marlin/src/lcd/extui/dgus_reloaded/DGUSTxHandler.cpp b/Marlin/src/lcd/extui/dgus_reloaded/DGUSTxHandler.cpp index 8d57038765..961b29ca22 100644 --- a/Marlin/src/lcd/extui/dgus_reloaded/DGUSTxHandler.cpp +++ b/Marlin/src/lcd/extui/dgus_reloaded/DGUSTxHandler.cpp @@ -286,7 +286,7 @@ void DGUSTxHandler::TempMax(DGUS_VP &vp) { } void DGUSTxHandler::StepperStatus(DGUS_VP &vp) { - const bool motor_on = stepper.axis_enabled.bits & (_BV(LINEAR_AXES) - 1); + const bool motor_on = stepper.axis_enabled.bits & (_BV(NUM_AXES) - 1); dgus_display.Write((uint16_t)vp.addr, Swap16(uint16_t(motor_on ? DGUS_Data::Status::ENABLED : DGUS_Data::Status::DISABLED))); } diff --git a/Marlin/src/lcd/extui/dgus_reloaded/dgus_reloaded_extui.cpp b/Marlin/src/lcd/extui/dgus_reloaded/dgus_reloaded_extui.cpp index 61b072a3f7..f6f2c0f89d 100644 --- a/Marlin/src/lcd/extui/dgus_reloaded/dgus_reloaded_extui.cpp +++ b/Marlin/src/lcd/extui/dgus_reloaded/dgus_reloaded_extui.cpp @@ -83,8 +83,8 @@ namespace ExtUI { } void onHomingStart() {} - void onHomingComplete() {} - void onPrintFinished() {} + void onHomingDone() {} + void onPrintDone() {} void onFactoryReset() { dgus_screen_handler.SettingsReset(); @@ -100,16 +100,17 @@ 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); } #if HAS_MESH - void onMeshLevelingStart() {} + void onLevelingStart() {} + void onLevelingDone() {} void onMeshUpdate(const int8_t xpos, const int8_t ypos, const_float_t zval) { dgus_screen_handler.MeshUpdate(xpos, ypos); diff --git a/Marlin/src/lcd/extui/example/example.cpp b/Marlin/src/lcd/extui/example/example.cpp index 8f38d2aba6..6ef20cf5f0 100644 --- a/Marlin/src/lcd/extui/example/example.cpp +++ b/Marlin/src/lcd/extui/example/example.cpp @@ -59,8 +59,8 @@ namespace ExtUI { void onStatusChanged(const char * const msg) {} void onHomingStart() {} - void onHomingComplete() {} - void onPrintFinished() {} + void onHomingDone() {} + void onPrintDone() {} void onFactoryReset() {} @@ -88,18 +88,19 @@ 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. } #if HAS_MESH - void onMeshLevelingStart() {} + void onLevelingStart() {} + void onLevelingDone() {} void onMeshUpdate(const int8_t xpos, const int8_t ypos, const_float_t zval) { // Called when any mesh points are updated diff --git a/Marlin/src/lcd/extui/ftdi_eve_touch_ui/archim2-flash/flash_storage.cpp b/Marlin/src/lcd/extui/ftdi_eve_touch_ui/archim2-flash/flash_storage.cpp index 8b0c0f877c..dbee1e034b 100644 --- a/Marlin/src/lcd/extui/ftdi_eve_touch_ui/archim2-flash/flash_storage.cpp +++ b/Marlin/src/lcd/extui/ftdi_eve_touch_ui/archim2-flash/flash_storage.cpp @@ -421,7 +421,7 @@ bool UIFlashStorage::is_present = false; uint32_t addr; uint8_t buff[write_page_size]; - strcpy_P( (char*) buff, (const char*) filename); + strcpy_P((char*)buff, FTOP(filename)); MediaFileReader reader; if (!reader.open((char*) buff)) { diff --git a/Marlin/src/lcd/extui/ftdi_eve_touch_ui/bioprinter/printing_dialog_box.cpp b/Marlin/src/lcd/extui/ftdi_eve_touch_ui/bioprinter/printing_dialog_box.cpp index f0c0a59d36..6d177c5a7b 100644 --- a/Marlin/src/lcd/extui/ftdi_eve_touch_ui/bioprinter/printing_dialog_box.cpp +++ b/Marlin/src/lcd/extui/ftdi_eve_touch_ui/bioprinter/printing_dialog_box.cpp @@ -106,8 +106,8 @@ bool BioPrintingDialogBox::onTouchEnd(uint8_t tag) { } void BioPrintingDialogBox::setStatusMessage(FSTR_P message) { - char buff[strlen_P((const char*)message)+1]; - strcpy_P(buff, (const char*) message); + char buff[strlen_P(FTOP(message)) + 1]; + strcpy_P(buff, FTOP(message)); setStatusMessage(buff); } diff --git a/Marlin/src/lcd/extui/ftdi_eve_touch_ui/ftdi_eve_extui.cpp b/Marlin/src/lcd/extui/ftdi_eve_touch_ui/ftdi_eve_extui.cpp index f2ee1e5639..2ce9ed027e 100644 --- a/Marlin/src/lcd/extui/ftdi_eve_touch_ui/ftdi_eve_extui.cpp +++ b/Marlin/src/lcd/extui/ftdi_eve_touch_ui/ftdi_eve_extui.cpp @@ -80,7 +80,7 @@ namespace ExtUI { } void onPrintTimerPaused() {} - void onPrintFinished() {} + void onPrintDone() {} void onFilamentRunout(const extruder_t extruder) { char lcd_msg[30]; @@ -90,14 +90,14 @@ namespace ExtUI { } void onHomingStart() {} - void onHomingComplete() {} + void onHomingDone() {} void onFactoryReset() { InterfaceSettingsScreen::defaultSettings(); } void onStoreSettings(char *buff) { InterfaceSettingsScreen::saveSettings(buff); } 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); } @@ -118,7 +118,8 @@ namespace ExtUI { } #if HAS_LEVELING && HAS_MESH - void onMeshLevelingStart() {} + void onLevelingStart() {} + void onLevelingDone() {} void onMeshUpdate(const int8_t x, const int8_t y, const_float_t val) { BedMeshViewScreen::onMeshUpdate(x, y, val); } void onMeshUpdate(const int8_t x, const int8_t y, const ExtUI::probe_state_t state) { BedMeshViewScreen::onMeshUpdate(x, y, state); } #endif diff --git a/Marlin/src/lcd/extui/ftdi_eve_touch_ui/ftdi_eve_lib/extended/command_processor.h b/Marlin/src/lcd/extui/ftdi_eve_touch_ui/ftdi_eve_lib/extended/command_processor.h index 24e93982c2..648ed5330a 100644 --- a/Marlin/src/lcd/extui/ftdi_eve_touch_ui/ftdi_eve_lib/extended/command_processor.h +++ b/Marlin/src/lcd/extui/ftdi_eve_touch_ui/ftdi_eve_lib/extended/command_processor.h @@ -242,10 +242,10 @@ class CommandProcessor : public CLCD::CommandFifo { } CommandProcessor& toggle2(int16_t x, int16_t y, int16_t w, int16_t h, FSTR_P no, FSTR_P yes, bool state, uint16_t options = FTDI::OPT_3D) { - char text[strlen_P((const char *)no) + strlen_P((const char *)yes) + 2]; - strcpy_P(text, (const char *)no); + char text[strlen_P(FTOP(no)) + strlen_P(FTOP(yes)) + 2]; + strcpy_P(text, FTOP(no)); strcat(text, "\xFF"); - strcat_P(text, (const char *)yes); + strcat_P(text, FTOP(yes)); return toggle(x, y, w, h, text, state, options); } diff --git a/Marlin/src/lcd/extui/ftdi_eve_touch_ui/ftdi_eve_lib/extended/text_box.cpp b/Marlin/src/lcd/extui/ftdi_eve_touch_ui/ftdi_eve_lib/extended/text_box.cpp index b4d8156b39..c75cdf1812 100644 --- a/Marlin/src/lcd/extui/ftdi_eve_touch_ui/ftdi_eve_lib/extended/text_box.cpp +++ b/Marlin/src/lcd/extui/ftdi_eve_touch_ui/ftdi_eve_lib/extended/text_box.cpp @@ -135,9 +135,9 @@ namespace FTDI { } } - void draw_text_box(CommandProcessor& cmd, int x, int y, int w, int h, FSTR_P pstr, uint16_t options, uint8_t font) { - char str[strlen_P((const char*)pstr) + 1]; - strcpy_P(str, (const char*)pstr); + void draw_text_box(CommandProcessor& cmd, int x, int y, int w, int h, FSTR_P fstr, uint16_t options, uint8_t font) { + char str[strlen_P(FTOP(fstr)) + 1]; + strcpy_P(str, FTOP(fstr)); draw_text_box(cmd, x, y, w, h, (const char*) str, options, font); } } // namespace FTDI diff --git a/Marlin/src/lcd/extui/ftdi_eve_touch_ui/ftdi_eve_lib/extended/text_ellipsis.cpp b/Marlin/src/lcd/extui/ftdi_eve_touch_ui/ftdi_eve_lib/extended/text_ellipsis.cpp index 698bcdb150..a6d014b56e 100644 --- a/Marlin/src/lcd/extui/ftdi_eve_touch_ui/ftdi_eve_lib/extended/text_ellipsis.cpp +++ b/Marlin/src/lcd/extui/ftdi_eve_touch_ui/ftdi_eve_lib/extended/text_ellipsis.cpp @@ -33,6 +33,7 @@ namespace FTDI { const bool use_utf8 = has_utf8_chars(str); #define CHAR_WIDTH(c) use_utf8 ? utf8_fm.get_char_width(c) : clcd_fm.char_widths[(uint8_t)c] #else + constexpr bool use_utf8 = false; #define CHAR_WIDTH(c) utf8_fm.get_char_width(c) #endif FontMetrics utf8_fm(font); @@ -53,21 +54,17 @@ namespace FTDI { breakPoint = (char*)next; } - if (lineWidth > w) { - *breakPoint = '\0'; - strcpy_P(breakPoint,PSTR("...")); - } + if (lineWidth > w) + strcpy_P(breakPoint, PSTR("...")); cmd.apply_text_alignment(x, y, w, h, options); - #if ENABLED(TOUCH_UI_USE_UTF8) - if (use_utf8) { - draw_utf8_text(cmd, x, y, str, font_size_t::from_romfont(font), options); - } else - #endif - { - cmd.CLCD::CommandFifo::text(x, y, font, options); - cmd.CLCD::CommandFifo::str(str); - } + if (use_utf8) { + TERN_(TOUCH_UI_USE_UTF8, draw_utf8_text(cmd, x, y, str, font_size_t::from_romfont(font), options)); + } + else { + cmd.CLCD::CommandFifo::text(x, y, font, options); + cmd.CLCD::CommandFifo::str(str); + } } /** @@ -80,9 +77,9 @@ namespace FTDI { _draw_text_with_ellipsis(cmd, x, y, w, h, tmp, options, font); } - void draw_text_with_ellipsis(CommandProcessor& cmd, int x, int y, int w, int h, FSTR_P pstr, uint16_t options, uint8_t font) { - char tmp[strlen_P((const char*)pstr) + 3]; - strcpy_P(tmp, (const char*)pstr); + void draw_text_with_ellipsis(CommandProcessor& cmd, int x, int y, int w, int h, FSTR_P fstr, uint16_t options, uint8_t font) { + char tmp[strlen_P(FTOP(fstr)) + 3]; + strcpy_P(tmp, FTOP(fstr)); _draw_text_with_ellipsis(cmd, x, y, w, h, tmp, options, font); } } // namespace FTDI diff --git a/Marlin/src/lcd/extui/ftdi_eve_touch_ui/ftdi_eve_lib/extended/unicode/unicode.cpp b/Marlin/src/lcd/extui/ftdi_eve_touch_ui/ftdi_eve_lib/extended/unicode/unicode.cpp index ca25dea3ca..d428f686b7 100644 --- a/Marlin/src/lcd/extui/ftdi_eve_touch_ui/ftdi_eve_lib/extended/unicode/unicode.cpp +++ b/Marlin/src/lcd/extui/ftdi_eve_touch_ui/ftdi_eve_lib/extended/unicode/unicode.cpp @@ -191,9 +191,9 @@ return render_utf8_text(nullptr, 0, 0, str, fs, maxlen); } - uint16_t FTDI::get_utf8_text_width(FSTR_P pstr, font_size_t fs) { - char str[strlen_P((const char*)pstr) + 1]; - strcpy_P(str, (const char*)pstr); + uint16_t FTDI::get_utf8_text_width(FSTR_P fstr, font_size_t fs) { + char str[strlen_P(FTOP(fstr)) + 1]; + strcpy_P(str, FTOP(fstr)); return get_utf8_text_width(str, fs); } @@ -234,9 +234,9 @@ cmd.cmd(RESTORE_CONTEXT()); } - void FTDI::draw_utf8_text(CommandProcessor& cmd, int x, int y, FSTR_P pstr, font_size_t fs, uint16_t options) { - char str[strlen_P((const char*)pstr) + 1]; - strcpy_P(str, (const char*)pstr); + void FTDI::draw_utf8_text(CommandProcessor& cmd, int x, int y, FSTR_P fstr, font_size_t fs, uint16_t options) { + char str[strlen_P(FTOP(fstr)) + 1]; + strcpy_P(str, FTOP(fstr)); draw_utf8_text(cmd, x, y, (const char*) str, fs, options); } diff --git a/Marlin/src/lcd/extui/ftdi_eve_touch_ui/generic/base_numeric_adjustment_screen.cpp b/Marlin/src/lcd/extui/ftdi_eve_touch_ui/generic/base_numeric_adjustment_screen.cpp index 4415ed50fc..ce3066ae41 100644 --- a/Marlin/src/lcd/extui/ftdi_eve_touch_ui/generic/base_numeric_adjustment_screen.cpp +++ b/Marlin/src/lcd/extui/ftdi_eve_touch_ui/generic/base_numeric_adjustment_screen.cpp @@ -245,8 +245,8 @@ void BaseNumericAdjustmentScreen::widgets_t::adjuster(uint8_t tag, FSTR_P label, } if (_what & FOREGROUND) { - char b[strlen_P(value)+1]; - strcpy_P(b,value); + char b[strlen(value) + 1]; + strcpy(b, value); adjuster_sram_val(tag, label, b, is_enabled); } } diff --git a/Marlin/src/lcd/extui/ftdi_eve_touch_ui/generic/endstop_state_screen.cpp b/Marlin/src/lcd/extui/ftdi_eve_touch_ui/generic/endstop_state_screen.cpp index c7042e760e..fdc5764db9 100644 --- a/Marlin/src/lcd/extui/ftdi_eve_touch_ui/generic/endstop_state_screen.cpp +++ b/Marlin/src/lcd/extui/ftdi_eve_touch_ui/generic/endstop_state_screen.cpp @@ -51,13 +51,7 @@ void EndstopStatesScreen::onRedraw(draw_mode_t) { #define PIN_ENABLED(X,Y,LABEL,PIN,INV) cmd.enabled(1).colors(READ(PIN##_PIN) != INV ? action_btn : normal_btn).PIN_BTN(X,Y,PIN,LABEL); #define PIN_DISABLED(X,Y,LABEL,PIN) cmd.enabled(0).PIN_BTN(X,Y,PIN,LABEL); - cmd.font( - #if ENABLED(TOUCH_UI_PORTRAIT) - font_large - #else - font_medium - #endif - ) + cmd.font(TERN(TOUCH_UI_PORTRAIT, font_large, font_medium)) .text(BTN_POS(1,1), BTN_SIZE(6,1), GET_TEXT_F(MSG_LCD_ENDSTOPS)) .font(font_tiny); #if HAS_X_MAX @@ -91,12 +85,12 @@ void EndstopStatesScreen::onRedraw(draw_mode_t) { PIN_DISABLED(5, 3, PSTR(STR_Z_MIN), Z_MIN) #endif #if ENABLED(FILAMENT_RUNOUT_SENSOR) && PIN_EXISTS(FIL_RUNOUT) - PIN_ENABLED (1, 4, GET_TEXT_F(MSG_RUNOUT_1), FIL_RUNOUT, FIL_RUNOUT1_STATE) + PIN_ENABLED (1, 4, GET_TEXT_F(MSG_RUNOUT_1), FIL_RUNOUT, !runout.out_state()) #else PIN_DISABLED(1, 4, GET_TEXT_F(MSG_RUNOUT_1), FIL_RUNOUT) #endif #if BOTH(HAS_MULTI_EXTRUDER, FILAMENT_RUNOUT_SENSOR) && PIN_EXISTS(FIL_RUNOUT2) - PIN_ENABLED (3, 4, GET_TEXT_F(MSG_RUNOUT_2), FIL_RUNOUT2, FIL_RUNOUT2_STATE) + PIN_ENABLED (3, 4, GET_TEXT_F(MSG_RUNOUT_2), FIL_RUNOUT2, !runout.out_state(1)) #else PIN_DISABLED(3, 4, GET_TEXT_F(MSG_RUNOUT_2), FIL_RUNOUT2) #endif diff --git a/Marlin/src/lcd/extui/ftdi_eve_touch_ui/generic/filament_runout_screen.cpp b/Marlin/src/lcd/extui/ftdi_eve_touch_ui/generic/filament_runout_screen.cpp index 68948b0c5e..a885d69cf5 100644 --- a/Marlin/src/lcd/extui/ftdi_eve_touch_ui/generic/filament_runout_screen.cpp +++ b/Marlin/src/lcd/extui/ftdi_eve_touch_ui/generic/filament_runout_screen.cpp @@ -34,14 +34,13 @@ void FilamentRunoutScreen::onRedraw(draw_mode_t what) { w.heading( GET_TEXT_F(MSG_FILAMENT)); w.toggle( 2, GET_TEXT_F(MSG_RUNOUT_SENSOR), getFilamentRunoutEnabled()); - #if HAS_FILAMENT_RUNOUT_DISTANCE - w.heading(GET_TEXT_F(MSG_RUNOUT_DISTANCE_MM)); - w.units(GET_TEXT_F(MSG_UNITS_MM)); - w.precision(0); - w.color(e_axis); - w.adjuster( 10, FPSTR(NUL_STR), getFilamentRunoutDistance_mm(), getFilamentRunoutEnabled()); - w.increments(); - #endif + w.heading(GET_TEXT_F(MSG_RUNOUT_DISTANCE_MM)); + w.units(GET_TEXT_F(MSG_UNITS_MM)); + w.precision(0); + w.color(e_axis); + w.adjuster( 10, FPSTR(NUL_STR), getFilamentRunoutDistance_mm(), getFilamentRunoutEnabled()); + w.increments(); + } bool FilamentRunoutScreen::onTouchHeld(uint8_t tag) { @@ -49,10 +48,8 @@ bool FilamentRunoutScreen::onTouchHeld(uint8_t tag) { const float increment = getIncrement(); switch (tag) { case 2: setFilamentRunoutEnabled(!getFilamentRunoutEnabled()); break; - #if HAS_FILAMENT_RUNOUT_DISTANCE - case 10: UI_DECREMENT(FilamentRunoutDistance_mm); break; - case 11: UI_INCREMENT(FilamentRunoutDistance_mm); break; - #endif + case 10: UI_DECREMENT(FilamentRunoutDistance_mm); break; + case 11: UI_INCREMENT(FilamentRunoutDistance_mm); break; default: return false; } diff --git a/Marlin/src/lcd/extui/ftdi_eve_touch_ui/generic/max_acceleration_screen.cpp b/Marlin/src/lcd/extui/ftdi_eve_touch_ui/generic/max_acceleration_screen.cpp index 228bc5f96b..492b908776 100644 --- a/Marlin/src/lcd/extui/ftdi_eve_touch_ui/generic/max_acceleration_screen.cpp +++ b/Marlin/src/lcd/extui/ftdi_eve_touch_ui/generic/max_acceleration_screen.cpp @@ -44,10 +44,10 @@ void MaxAccelerationScreen::onRedraw(draw_mode_t what) { w.color(e_axis).adjuster( 8, F(STR_E0), getAxisMaxAcceleration_mm_s2(E0) ); w.color(e_axis).adjuster(10, F(STR_E1), getAxisMaxAcceleration_mm_s2(E1) ); #if DISTINCT_E > 2 - w.color(e_axis).adjuster(12, F(STR_E2), getAxisMaxAcceleration_mm_s2(E2) ); - #endif - #if DISTINCT_E > 3 - w.color(e_axis).adjuster(14, F(STR_E3), getAxisMaxAcceleration_mm_s2(E3) ); + w.color(e_axis).adjuster(12, F(STR_E2), getAxisMaxAcceleration_mm_s2(E2) ); + #if DISTINCT_E > 3 + w.color(e_axis).adjuster(14, F(STR_E3), getAxisMaxAcceleration_mm_s2(E3) ); + #endif #endif #endif w.increments(); @@ -65,19 +65,18 @@ bool MaxAccelerationScreen::onTouchHeld(uint8_t tag) { case 8: UI_DECREMENT(AxisMaxAcceleration_mm_s2, E0); break; case 9: UI_INCREMENT(AxisMaxAcceleration_mm_s2, E0); break; #if DISTINCT_E > 1 - case 10: UI_DECREMENT(AxisMaxAcceleration_mm_s2, E1); break; - case 11: UI_INCREMENT(AxisMaxAcceleration_mm_s2, E1); break; + case 10: UI_DECREMENT(AxisMaxAcceleration_mm_s2, E1); break; + case 11: UI_INCREMENT(AxisMaxAcceleration_mm_s2, E1); break; + #if DISTINCT_E > 2 + case 12: UI_DECREMENT(AxisMaxAcceleration_mm_s2, E2); break; + case 13: UI_INCREMENT(AxisMaxAcceleration_mm_s2, E2); break; + #if DISTINCT_E > 3 + case 14: UI_DECREMENT(AxisMaxAcceleration_mm_s2, E3); break; + case 15: UI_INCREMENT(AxisMaxAcceleration_mm_s2, E3); break; + #endif + #endif #endif - #if DISTINCT_E > 2 - case 12: UI_DECREMENT(AxisMaxAcceleration_mm_s2, E2); break; - case 13: UI_INCREMENT(AxisMaxAcceleration_mm_s2, E2); break; - #endif - #if DISTINCT_E > 3 - case 14: UI_DECREMENT(AxisMaxAcceleration_mm_s2, E3); break; - case 15: UI_INCREMENT(AxisMaxAcceleration_mm_s2, E3); break; - #endif - default: - return false; + default: return false; } return true; } diff --git a/Marlin/src/lcd/extui/ftdi_eve_touch_ui/generic/max_velocity_screen.cpp b/Marlin/src/lcd/extui/ftdi_eve_touch_ui/generic/max_velocity_screen.cpp index 65dc947b7b..0111276211 100644 --- a/Marlin/src/lcd/extui/ftdi_eve_touch_ui/generic/max_velocity_screen.cpp +++ b/Marlin/src/lcd/extui/ftdi_eve_touch_ui/generic/max_velocity_screen.cpp @@ -46,9 +46,9 @@ void MaxVelocityScreen::onRedraw(draw_mode_t what) { w.color(e_axis) .adjuster( 10, F(STR_E1), getAxisMaxFeedrate_mm_s(E1) ); #if EXTRUDERS > 2 w.color(e_axis).adjuster( 12, F(STR_E2), getAxisMaxFeedrate_mm_s(E2) ); - #endif - #if EXTRUDERS > 3 - w.color(e_axis).adjuster( 14, F(STR_E3), getAxisMaxFeedrate_mm_s(E3) ); + #if EXTRUDERS > 3 + w.color(e_axis).adjuster( 14, F(STR_E3), getAxisMaxFeedrate_mm_s(E3) ); + #endif #endif #endif w.increments(); @@ -63,24 +63,23 @@ bool MaxVelocityScreen::onTouchHeld(uint8_t tag) { case 5: UI_INCREMENT(AxisMaxFeedrate_mm_s, Y); break; case 6: UI_DECREMENT(AxisMaxFeedrate_mm_s, Z); break; case 7: UI_INCREMENT(AxisMaxFeedrate_mm_s, Z); break; - #if DISTINCT_E > 0 - case 8: UI_DECREMENT(AxisMaxFeedrate_mm_s, E0); break; - case 9: UI_INCREMENT(AxisMaxFeedrate_mm_s, E0); break; + #if DISTINCT_E + case 8: UI_DECREMENT(AxisMaxFeedrate_mm_s, E0); break; + case 9: UI_INCREMENT(AxisMaxFeedrate_mm_s, E0); break; + #if DISTINCT_E > 1 + case 10: UI_DECREMENT(AxisMaxFeedrate_mm_s, E1); break; + case 11: UI_INCREMENT(AxisMaxFeedrate_mm_s, E1); break; + #if DISTINCT_E > 2 + case 12: UI_DECREMENT(AxisMaxFeedrate_mm_s, E2); break; + case 13: UI_INCREMENT(AxisMaxFeedrate_mm_s, E2); break; + #if DISTINCT_E > 3 + case 14: UI_DECREMENT(AxisMaxFeedrate_mm_s, E3); break; + case 15: UI_INCREMENT(AxisMaxFeedrate_mm_s, E3); break; + #endif + #endif + #endif #endif - #if DISTINCT_E > 1 - case 10: UI_DECREMENT(AxisMaxFeedrate_mm_s, E1); break; - case 11: UI_INCREMENT(AxisMaxFeedrate_mm_s, E1); break; - #endif - #if DISTINCT_E > 2 - case 12: UI_DECREMENT(AxisMaxFeedrate_mm_s, E2); break; - case 13: UI_INCREMENT(AxisMaxFeedrate_mm_s, E2); break; - #endif - #if DISTINCT_E > 3 - case 14: UI_DECREMENT(AxisMaxFeedrate_mm_s, E3); break; - case 15: UI_INCREMENT(AxisMaxFeedrate_mm_s, E3); break; - #endif - default: - return false; + default: return false; } SaveSettingsDialogBox::settingsChanged(); return true; diff --git a/Marlin/src/lcd/extui/ftdi_eve_touch_ui/generic/status_screen.cpp b/Marlin/src/lcd/extui/ftdi_eve_touch_ui/generic/status_screen.cpp index 4e76450683..7310577995 100644 --- a/Marlin/src/lcd/extui/ftdi_eve_touch_ui/generic/status_screen.cpp +++ b/Marlin/src/lcd/extui/ftdi_eve_touch_ui/generic/status_screen.cpp @@ -345,8 +345,8 @@ void StatusScreen::draw_status_message(draw_mode_t what, const char *message) { } void StatusScreen::setStatusMessage(FSTR_P message) { - char buff[strlen_P((const char * const)message)+1]; - strcpy_P(buff, (const char * const) message); + char buff[strlen_P(FTOP(message)) + 1]; + strcpy_P(buff, FTOP(message)); setStatusMessage((const char *) buff); } diff --git a/Marlin/src/lcd/extui/malyan/malyan_extui.cpp b/Marlin/src/lcd/extui/malyan/malyan_extui.cpp index f323728e27..945ff472e1 100644 --- a/Marlin/src/lcd/extui/malyan/malyan_extui.cpp +++ b/Marlin/src/lcd/extui/malyan/malyan_extui.cpp @@ -141,17 +141,18 @@ namespace ExtUI { void onFilamentRunout(const extruder_t extruder) {} void onUserConfirmRequired(const char * const) {} void onHomingStart() {} - void onHomingComplete() {} - void onPrintFinished() {} + void onHomingDone() {} + void onPrintDone() {} void onFactoryReset() {} 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 onMeshLevelingStart() {} + void onLevelingStart() {} + void onLevelingDone() {} void onMeshUpdate(const int8_t xpos, const int8_t ypos, const_float_t zval) {} void onMeshUpdate(const int8_t xpos, const int8_t ypos, const ExtUI::probe_state_t state) {} #endif diff --git a/Marlin/src/lcd/extui/nextion/nextion_extui.cpp b/Marlin/src/lcd/extui/nextion/nextion_extui.cpp index c19d3aee46..da54fac383 100644 --- a/Marlin/src/lcd/extui/nextion/nextion_extui.cpp +++ b/Marlin/src/lcd/extui/nextion/nextion_extui.cpp @@ -50,8 +50,8 @@ namespace ExtUI { void onStatusChanged(const char * const msg) { nextion.StatusChange(msg); } void onHomingStart() {} - void onHomingComplete() {} - void onPrintFinished() { nextion.PrintFinished(); } + void onHomingDone() {} + void onPrintDone() { nextion.PrintFinished(); } void onFactoryReset() {} @@ -79,18 +79,19 @@ 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. } #if HAS_MESH - void onMeshLevelingStart() {} + void onLevelingStart() {} + void onLevelingDone() {} void onMeshUpdate(const int8_t xpos, const int8_t ypos, const float zval) { // Called when any mesh points are updated @@ -116,6 +117,7 @@ namespace ExtUI { void onSteppersDisabled() {} void onSteppersEnabled() {} + } #endif // NEXTION_TFT diff --git a/Marlin/src/lcd/extui/ui_api.cpp b/Marlin/src/lcd/extui/ui_api.cpp index bfcbc39d7b..1a94eb9ab5 100644 --- a/Marlin/src/lcd/extui/ui_api.cpp +++ b/Marlin/src/lcd/extui/ui_api.cpp @@ -389,8 +389,10 @@ namespace ExtUI { return !thermalManager.tooColdToExtrude(extruder - E0); } - GcodeSuite::MarlinBusyState getHostKeepaliveState() { return TERN0(HOST_KEEPALIVE_FEATURE, gcode.busy_state); } - bool getHostKeepaliveIsPaused() { return TERN0(HOST_KEEPALIVE_FEATURE, gcode.host_keepalive_is_paused()); } + #if ENABLED(HOST_KEEPALIVE_FEATURE) + GcodeSuite::MarlinBusyState getHostKeepaliveState() { return gcode.busy_state; } + bool getHostKeepaliveIsPaused() { return gcode.host_keepalive_is_paused(); } + #endif #if HAS_SOFTWARE_ENDSTOPS bool getSoftEndstopState() { return soft_endstop._enabled; } @@ -418,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 @@ -487,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 @@ -544,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()) @@ -573,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 @@ -651,15 +683,12 @@ namespace ExtUI { } #if HAS_FILAMENT_SENSOR - bool getFilamentRunoutEnabled() { return runout.enabled; } - void setFilamentRunoutEnabled(const bool value) { runout.enabled = value; } + bool getFilamentRunoutEnabled(const extruder_t extruder/*=E0*/) { return runout.enabled[extruder]; } + void setFilamentRunoutEnabled(const bool value, const extruder_t extruder/*=E0*/) { runout.enabled[extruder] = value; } bool getFilamentRunoutState() { return runout.filament_ran_out; } void setFilamentRunoutState(const bool value) { runout.filament_ran_out = value; } - - #if HAS_FILAMENT_RUNOUT_DISTANCE - float getFilamentRunoutDistance_mm() { return runout.runout_distance(); } - void setFilamentRunoutDistance_mm(const_float_t value) { runout.set_runout_distance(constrain(value, 0, 999)); } - #endif + float getFilamentRunoutDistance_mm() { return runout.runout_distance(); } + void setFilamentRunoutDistance_mm(const_float_t value) { runout.set_runout_distance(constrain(value, 0, 999)); } #endif #if ENABLED(CASE_LIGHT_ENABLE) diff --git a/Marlin/src/lcd/extui/ui_api.h b/Marlin/src/lcd/extui/ui_api.h index 6753c53740..da1762830f 100644 --- a/Marlin/src/lcd/extui/ui_api.h +++ b/Marlin/src/lcd/extui/ui_api.h @@ -57,7 +57,7 @@ namespace ExtUI { static constexpr size_t eeprom_data_size = 48; - enum axis_t : uint8_t { X, Y, Z, I, J, K, X2, Y2, Z2, Z3, Z4 }; + enum axis_t : uint8_t { X, Y, Z, I, J, K, U, V, W, X2, Y2, Z2, Z3, Z4 }; enum extruder_t : uint8_t { E0, E1, E2, E3, E4, E5, E6, E7 }; enum heater_t : uint8_t { H0, H1, H2, H3, H4, H5, BED, CHAMBER, COOLER }; enum fan_t : uint8_t { FAN0, FAN1, FAN2, FAN3, FAN4, FAN5, FAN6, FAN7 }; @@ -83,8 +83,10 @@ namespace ExtUI { void injectCommands(char * const); bool commandsInQueue(); - GcodeSuite::MarlinBusyState getHostKeepaliveState(); - bool getHostKeepaliveIsPaused(); + #if ENABLED(HOST_KEEPALIVE_FEATURE) + GcodeSuite::MarlinBusyState getHostKeepaliveState(); + bool getHostKeepaliveIsPaused(); + #endif bool isHeaterIdle(const heater_t); bool isHeaterIdle(const extruder_t); @@ -172,7 +174,8 @@ namespace ExtUI { float getMeshPoint(const xy_uint8_t &pos); void setMeshPoint(const xy_uint8_t &pos, const_float_t zval); void moveToMeshPoint(const xy_uint8_t &pos, const_float_t z); - void onMeshLevelingStart(); + void onLevelingStart(); + void onLevelingDone(); void onMeshUpdate(const int8_t xpos, const int8_t ypos, const_float_t zval); inline void onMeshUpdate(const xy_int8_t &pos, const_float_t zval) { onMeshUpdate(pos.x, pos.y, zval); } @@ -294,15 +297,12 @@ namespace ExtUI { #endif #if HAS_FILAMENT_SENSOR - bool getFilamentRunoutEnabled(); - void setFilamentRunoutEnabled(const bool); + bool getFilamentRunoutEnabled(const extruder_t extruder=E0); + void setFilamentRunoutEnabled(const bool, const extruder_t extruder=E0); bool getFilamentRunoutState(); void setFilamentRunoutState(const bool); - - #if HAS_FILAMENT_RUNOUT_DISTANCE - float getFilamentRunoutDistance_mm(); - void setFilamentRunoutDistance_mm(const_float_t); - #endif + float getFilamentRunoutDistance_mm(); + void setFilamentRunoutDistance_mm(const_float_t); #endif #if ENABLED(CASE_LIGHT_ENABLE) @@ -403,22 +403,22 @@ namespace ExtUI { void onPrintTimerStarted(); void onPrintTimerPaused(); void onPrintTimerStopped(); - void onPrintFinished(); + void onPrintDone(); void onFilamentRunout(const extruder_t extruder); void onUserConfirmRequired(const char * const msg); void onUserConfirmRequired(FSTR_P const fstr); void onStatusChanged(const char * const msg); void onStatusChanged(FSTR_P const fstr); void onHomingStart(); - void onHomingComplete(); + void onHomingDone(); void onSteppersDisabled(); void onSteppersEnabled(); void onFactoryReset(); void onStoreSettings(char *); void onLoadSettings(const char *); void onPostprocessSettings(); - void onConfigurationStoreWritten(bool success); - void onConfigurationStoreRead(bool success); + void onSettingsStored(bool success); + void onSettingsLoaded(bool success); #if ENABLED(POWER_LOSS_RECOVERY) void onPowerLossResume(); #endif diff --git a/Marlin/src/lcd/fontutils.h b/Marlin/src/lcd/fontutils.h index 3901d4439f..21aee1e939 100644 --- a/Marlin/src/lcd/fontutils.h +++ b/Marlin/src/lcd/fontutils.h @@ -63,6 +63,7 @@ uint8_t* get_utf8_value_cb(uint8_t *pstart, read_byte_cb_t cb_read_byte, wchar_t /* Returns length of string in CHARACTERS, NOT BYTES */ uint8_t utf8_strlen(const char *pstart); uint8_t utf8_strlen_P(PGM_P pstart); +inline uint8_t utf8_strlen(FSTR_P fstart) { return utf8_strlen_P(FTOP(fstart)); } /* Returns start byte position of desired char number */ uint8_t utf8_byte_pos_by_char_num(const char *pstart, const uint8_t charnum); diff --git a/Marlin/src/lcd/language/language_de.h b/Marlin/src/lcd/language/language_de.h index bf408d436f..a6782bb0ac 100644 --- a/Marlin/src/lcd/language/language_de.h +++ b/Marlin/src/lcd/language/language_de.h @@ -135,6 +135,7 @@ namespace Language_de { LSTR MSG_BED_LEVELING = _UxGT("Bett-Nivellierung"); LSTR MSG_LEVEL_BED = _UxGT("Bett nivellieren"); LSTR MSG_BED_TRAMMING = _UxGT("Bett ausrichten"); + LSTR MSG_BED_TRAMMING_MANUAL = _UxGT("Manuelles ausrichten"); LSTR MSG_BED_TRAMMING_RAISE = _UxGT("Das Bett anpassen, bis zum auslösen."); LSTR MSG_BED_TRAMMING_IN_RANGE = _UxGT("Ecken in der Toleranz. Bett ausger."); LSTR MSG_BED_TRAMMING_GOOD_POINTS = _UxGT("Gute Punkte: "); @@ -387,8 +388,9 @@ namespace Language_de { LSTR MSG_ADVANCE_K = _UxGT("Vorschubfaktor"); LSTR MSG_ADVANCE_K_E = _UxGT("Vorschubfaktor *"); LSTR MSG_CONTRAST = _UxGT("LCD-Kontrast"); - LSTR MSG_BRIGHTNESS = _UxGT("LCD Helligkeit"); + LSTR MSG_BRIGHTNESS = _UxGT("LCD-Helligkeit"); LSTR MSG_LCD_BKL_TIMEOUT = _UxGT("LCD-Ruhezustand (s)"); + LSTR MSG_BRIGHTNESS_OFF = _UxGT("LCD ausschalten"); LSTR MSG_STORE_EEPROM = _UxGT("Konfig. speichern"); LSTR MSG_LOAD_EEPROM = _UxGT("Konfig. laden"); LSTR MSG_RESTORE_DEFAULTS = _UxGT("Standardwerte laden"); @@ -399,7 +401,7 @@ namespace Language_de { LSTR MSG_SETTINGS_STORED = _UxGT("Einstell. gespei."); LSTR MSG_MEDIA_UPDATE = _UxGT("FW Update vom Medium"); LSTR MSG_RESET_PRINTER = _UxGT("Drucker neustarten"); - LSTR MSG_REFRESH = LCD_STR_REFRESH _UxGT("Aktualisieren"); + LSTR MSG_REFRESH = LCD_STR_REFRESH _UxGT("Aktualisieren"); LSTR MSG_INFO_SCREEN = _UxGT("Info"); LSTR MSG_PREPARE = _UxGT("Vorbereitung"); LSTR MSG_TUNE = _UxGT("Justierung"); @@ -415,6 +417,8 @@ namespace Language_de { LSTR MSG_BUTTON_RESET = _UxGT("Reseten"); LSTR MSG_BUTTON_IGNORE = _UxGT("Ignorieren"); LSTR MSG_BUTTON_CANCEL = _UxGT("Abbrechen"); + LSTR MSG_BUTTON_CONFIRM = _UxGT("Bestätigen"); + LSTR MSG_BUTTON_CONTINUE = _UxGT("Fortsetzen"); LSTR MSG_BUTTON_DONE = _UxGT("Fertig"); LSTR MSG_BUTTON_BACK = _UxGT("Zurück"); LSTR MSG_BUTTON_PROCEED = _UxGT("Weiter"); @@ -424,6 +428,7 @@ namespace Language_de { LSTR MSG_BUTTON_PAUSE = _UxGT("Pause"); LSTR MSG_BUTTON_RESUME = _UxGT("Fortsetzen"); LSTR MSG_BUTTON_ADVANCED = _UxGT("Erweitert"); + LSTR MSG_BUTTON_SAVE = _UxGT("Speichern"); LSTR MSG_PAUSING = _UxGT("Pause..."); LSTR MSG_PAUSE_PRINT = _UxGT("SD-Druck pausieren"); LSTR MSG_ADVANCED_PAUSE = _UxGT("Erweiterte Pause"); diff --git a/Marlin/src/lcd/language/language_en.h b/Marlin/src/lcd/language/language_en.h index 9925f225e3..3e4109de3f 100644 --- a/Marlin/src/lcd/language/language_en.h +++ b/Marlin/src/lcd/language/language_en.h @@ -103,6 +103,9 @@ namespace Language_en { LSTR MSG_HOME_OFFSET_I = _UxGT("Home Offset ") STR_I; LSTR MSG_HOME_OFFSET_J = _UxGT("Home Offset ") STR_J; LSTR MSG_HOME_OFFSET_K = _UxGT("Home Offset ") STR_K; + LSTR MSG_HOME_OFFSET_U = _UxGT("Home Offset ") STR_U; + LSTR MSG_HOME_OFFSET_V = _UxGT("Home Offset ") STR_V; + LSTR MSG_HOME_OFFSET_W = _UxGT("Home Offset ") STR_W; LSTR MSG_HOME_OFFSETS_APPLIED = _UxGT("Offsets Applied"); LSTR MSG_SET_ORIGIN = _UxGT("Set Origin"); LSTR MSG_TRAMMING_WIZARD = _UxGT("Tramming Wizard"); @@ -151,6 +154,7 @@ namespace Language_en { LSTR MSG_BED_LEVELING = _UxGT("Bed Leveling"); LSTR MSG_LEVEL_BED = _UxGT("Level Bed"); LSTR MSG_BED_TRAMMING = _UxGT("Bed Tramming"); + LSTR MSG_BED_TRAMMING_MANUAL = _UxGT("Manual Tramming"); LSTR MSG_BED_TRAMMING_RAISE = _UxGT("Adjust bed until the probe triggers."); LSTR MSG_BED_TRAMMING_IN_RANGE = _UxGT("Corners within tolerance. Bed trammed."); LSTR MSG_BED_TRAMMING_GOOD_POINTS = _UxGT("Good Points: "); @@ -287,6 +291,9 @@ namespace Language_en { LSTR MSG_MOVE_I = _UxGT("Move ") STR_I; LSTR MSG_MOVE_J = _UxGT("Move ") STR_J; LSTR MSG_MOVE_K = _UxGT("Move ") STR_K; + LSTR MSG_MOVE_U = _UxGT("Move ") STR_U; + LSTR MSG_MOVE_V = _UxGT("Move ") STR_V; + LSTR MSG_MOVE_W = _UxGT("Move ") STR_W; LSTR MSG_MOVE_E = _UxGT("Move Extruder"); LSTR MSG_MOVE_EN = _UxGT("Move E*"); LSTR MSG_HOTEND_TOO_COLD = _UxGT("Hotend too cold"); @@ -353,6 +360,9 @@ namespace Language_en { LSTR MSG_VI_JERK = _UxGT("Max ") STR_I _UxGT(" Jerk"); LSTR MSG_VJ_JERK = _UxGT("Max ") STR_J _UxGT(" Jerk"); LSTR MSG_VK_JERK = _UxGT("Max ") STR_K _UxGT(" Jerk"); + LSTR MSG_VU_JERK = _UxGT("Max ") STR_U _UxGT(" Jerk"); + LSTR MSG_VV_JERK = _UxGT("Max ") STR_V _UxGT(" Jerk"); + LSTR MSG_VW_JERK = _UxGT("Max ") STR_W _UxGT(" Jerk"); LSTR MSG_VE_JERK = _UxGT("Max E Jerk"); LSTR MSG_JUNCTION_DEVIATION = _UxGT("Junction Dev"); LSTR MSG_VELOCITY = _UxGT("Velocity"); @@ -362,6 +372,9 @@ namespace Language_en { LSTR MSG_VMAX_I = _UxGT("Max ") STR_I _UxGT(" Vel"); LSTR MSG_VMAX_J = _UxGT("Max ") STR_J _UxGT(" Vel"); LSTR MSG_VMAX_K = _UxGT("Max ") STR_K _UxGT(" Vel"); + LSTR MSG_VMAX_U = _UxGT("Max ") STR_U _UxGT(" Vel"); + LSTR MSG_VMAX_V = _UxGT("Max ") STR_V _UxGT(" Vel"); + LSTR MSG_VMAX_W = _UxGT("Max ") STR_W _UxGT(" Vel"); LSTR MSG_VMAX_E = _UxGT("Max ") STR_E _UxGT(" Vel"); LSTR MSG_VMAX_EN = _UxGT("Max * Vel"); LSTR MSG_VMIN = _UxGT("Min Velocity"); @@ -373,6 +386,9 @@ namespace Language_en { LSTR MSG_AMAX_I = _UxGT("Max ") STR_I _UxGT(" Accel"); LSTR MSG_AMAX_J = _UxGT("Max ") STR_J _UxGT(" Accel"); LSTR MSG_AMAX_K = _UxGT("Max ") STR_K _UxGT(" Accel"); + LSTR MSG_AMAX_U = _UxGT("Max ") STR_U _UxGT(" Accel"); + LSTR MSG_AMAX_V = _UxGT("Max ") STR_V _UxGT(" Accel"); + LSTR MSG_AMAX_W = _UxGT("Max ") STR_W _UxGT(" Accel"); LSTR MSG_AMAX_E = _UxGT("Max ") STR_E _UxGT(" Accel"); LSTR MSG_AMAX_EN = _UxGT("Max * Accel"); LSTR MSG_A_RETRACT = _UxGT("Retract Accel"); @@ -386,6 +402,9 @@ namespace Language_en { LSTR MSG_I_STEPS = STR_I _UxGT(" Steps/mm"); LSTR MSG_J_STEPS = STR_J _UxGT(" Steps/mm"); LSTR MSG_K_STEPS = STR_K _UxGT(" Steps/mm"); + LSTR MSG_U_STEPS = STR_U _UxGT(" Steps/mm"); + LSTR MSG_V_STEPS = STR_V _UxGT(" Steps/mm"); + LSTR MSG_W_STEPS = STR_W _UxGT(" Steps/mm"); LSTR MSG_E_STEPS = _UxGT("E steps/mm"); LSTR MSG_EN_STEPS = _UxGT("* Steps/mm"); LSTR MSG_TEMPERATURE = _UxGT("Temperature"); @@ -402,7 +421,8 @@ namespace Language_en { LSTR MSG_ADVANCE_K_E = _UxGT("Advance K *"); LSTR MSG_CONTRAST = _UxGT("LCD Contrast"); LSTR MSG_BRIGHTNESS = _UxGT("LCD Brightness"); - LSTR MSG_LCD_BKL_TIMEOUT = _UxGT("LCD Sleep (s)"); + LSTR MSG_LCD_BKL_TIMEOUT = _UxGT("LCD Timeout (s)"); + LSTR MSG_BRIGHTNESS_OFF = _UxGT("Backlight Off"); LSTR MSG_STORE_EEPROM = _UxGT("Store Settings"); LSTR MSG_LOAD_EEPROM = _UxGT("Load Settings"); LSTR MSG_RESTORE_DEFAULTS = _UxGT("Restore Defaults"); @@ -429,6 +449,8 @@ namespace Language_en { LSTR MSG_BUTTON_RESET = _UxGT("Reset"); LSTR MSG_BUTTON_IGNORE = _UxGT("Ignore"); LSTR MSG_BUTTON_CANCEL = _UxGT("Cancel"); + LSTR MSG_BUTTON_CONFIRM = _UxGT("Confirm"); + LSTR MSG_BUTTON_CONTINUE = _UxGT("Continue"); LSTR MSG_BUTTON_DONE = _UxGT("Done"); LSTR MSG_BUTTON_BACK = _UxGT("Back"); LSTR MSG_BUTTON_PROCEED = _UxGT("Proceed"); @@ -438,6 +460,7 @@ namespace Language_en { LSTR MSG_BUTTON_PAUSE = _UxGT("Pause"); LSTR MSG_BUTTON_RESUME = _UxGT("Resume"); LSTR MSG_BUTTON_ADVANCED = _UxGT("Advanced"); + LSTR MSG_BUTTON_SAVE = _UxGT("Save"); LSTR MSG_PAUSING = _UxGT("Pausing..."); LSTR MSG_PAUSE_PRINT = _UxGT("Pause Print"); LSTR MSG_ADVANCED_PAUSE = _UxGT("Advanced Pause"); @@ -535,6 +558,9 @@ namespace Language_en { LSTR MSG_BABYSTEP_I = _UxGT("Babystep ") STR_I; LSTR MSG_BABYSTEP_J = _UxGT("Babystep ") STR_J; LSTR MSG_BABYSTEP_K = _UxGT("Babystep ") STR_K; + LSTR MSG_BABYSTEP_U = _UxGT("Babystep ") STR_U; + LSTR MSG_BABYSTEP_V = _UxGT("Babystep ") STR_V; + LSTR MSG_BABYSTEP_W = _UxGT("Babystep ") STR_W; LSTR MSG_BABYSTEP_TOTAL = _UxGT("Total"); LSTR MSG_ENDSTOP_ABORT = _UxGT("Endstop Abort"); LSTR MSG_HEATING_FAILED_LCD = _UxGT("Heating Failed"); @@ -634,6 +660,9 @@ namespace Language_en { LSTR MSG_DAC_PERCENT_I = STR_I _UxGT(" Driver %"); LSTR MSG_DAC_PERCENT_J = STR_J _UxGT(" Driver %"); LSTR MSG_DAC_PERCENT_K = STR_K _UxGT(" Driver %"); + LSTR MSG_DAC_PERCENT_U = STR_U _UxGT(" Driver %"); + LSTR MSG_DAC_PERCENT_V = STR_V _UxGT(" Driver %"); + LSTR MSG_DAC_PERCENT_W = STR_W _UxGT(" Driver %"); LSTR MSG_DAC_PERCENT_E = _UxGT("E Driver %"); LSTR MSG_ERROR_TMC = _UxGT("TMC CONNECTION ERROR"); LSTR MSG_DAC_EEPROM_WRITE = _UxGT("DAC EEPROM Write"); @@ -647,6 +676,11 @@ namespace Language_en { LSTR MSG_FILAMENT_CHANGE_NOZZLE = _UxGT(" Nozzle: "); LSTR MSG_RUNOUT_SENSOR = _UxGT("Runout Sensor"); LSTR MSG_RUNOUT_DISTANCE_MM = _UxGT("Runout Dist mm"); + LSTR MSG_RUNOUT_MODE = _UxGT("Runout Mode"); + LSTR MSG_RUNOUT_MODE_HIGH = _UxGT("Sensor High"); + LSTR MSG_RUNOUT_MODE_LOW = _UxGT("Sensor Low"); + LSTR MSG_RUNOUT_MODE_MOTION = _UxGT("Motion Encoder"); + LSTR MSG_RUNOUT_MODE_NONE = _UxGT("No Sensor"); LSTR MSG_RUNOUT_ENABLE = _UxGT("Enable Runout"); LSTR MSG_FANCHECK = _UxGT("Fan Tacho Check"); LSTR MSG_KILL_HOMING_FAILED = _UxGT("Homing Failed"); @@ -809,6 +843,9 @@ namespace Language_en { LSTR MSG_BACKLASH_I = STR_I; LSTR MSG_BACKLASH_J = STR_J; LSTR MSG_BACKLASH_K = STR_K; + LSTR MSG_BACKLASH_U = STR_U; + LSTR MSG_BACKLASH_V = STR_V; + LSTR MSG_BACKLASH_W = STR_W; } #if FAN_COUNT == 1 diff --git a/Marlin/src/lcd/language/language_fr.h b/Marlin/src/lcd/language/language_fr.h index 02f9d2f549..ca3757f704 100644 --- a/Marlin/src/lcd/language/language_fr.h +++ b/Marlin/src/lcd/language/language_fr.h @@ -336,6 +336,7 @@ namespace Language_fr { LSTR MSG_BRIGHTNESS = _UxGT("Luminosité LCD"); LSTR MSG_CONTRAST = _UxGT("Contraste LCD"); LSTR MSG_LCD_BKL_TIMEOUT = _UxGT("Veille LCD (s)"); + LSTR MSG_BRIGHTNESS_OFF = _UxGT("Éteindre l'écran LCD"); LSTR MSG_STORE_EEPROM = _UxGT("Enregistrer config."); LSTR MSG_LOAD_EEPROM = _UxGT("Charger config."); LSTR MSG_RESTORE_DEFAULTS = _UxGT("Restaurer défauts"); diff --git a/Marlin/src/lcd/language/language_uk.h b/Marlin/src/lcd/language/language_uk.h index 7afc2e031c..e4eef399fe 100644 --- a/Marlin/src/lcd/language/language_uk.h +++ b/Marlin/src/lcd/language/language_uk.h @@ -465,7 +465,15 @@ namespace Language_uk { LSTR MSG_FILAMENT_LOAD = _UxGT("Завантаж., мм"); LSTR MSG_ADVANCE_K = _UxGT("Kоеф. просув."); LSTR MSG_ADVANCE_K_E = _UxGT("Kоеф. просув. *"); - LSTR MSG_CONTRAST = _UxGT("Контраст екрану"); + #if LCD_WIDTH >= 20 || HAS_DWIN_E3V2 + LSTR MSG_CONTRAST = _UxGT("Контраст екрану"); + LSTR MSG_BRIGHTNESS = _UxGT("Яскравість LCD"); + #else + LSTR MSG_CONTRAST = _UxGT("Контраст"); + LSTR MSG_BRIGHTNESS = _UxGT("Яскравість"); + #endif + LSTR MSG_LCD_BKL_TIMEOUT = _UxGT("LCD Таймаут, с"); + LSTR MSG_BRIGHTNESS_OFF = _UxGT("Підсвітка вимк."); LSTR MSG_STORE_EEPROM = _UxGT("Зберегти в EEPROM"); LSTR MSG_LOAD_EEPROM = _UxGT("Зчитати з EEPROM"); LSTR MSG_RESTORE_DEFAULTS = _UxGT("На базові параметри"); @@ -497,10 +505,17 @@ namespace Language_uk { LSTR MSG_BUTTON_RESET = _UxGT("Зкинути"); LSTR MSG_BUTTON_IGNORE = _UxGT("Ігнорув."); LSTR MSG_BUTTON_CANCEL = _UxGT("Відміна"); + LSTR MSG_BUTTON_CONFIRM = _UxGT("Підтвер."); + LSTR MSG_BUTTON_CONTINUE = _UxGT("Продовж."); LSTR MSG_BUTTON_DONE = _UxGT("Готово"); LSTR MSG_BUTTON_BACK = _UxGT("Назад"); - LSTR MSG_BUTTON_PROCEED = _UxGT("Продовжити"); - LSTR MSG_BUTTON_SKIP = _UxGT("Пропустити"); + LSTR MSG_BUTTON_PROCEED = _UxGT("Продовж."); + LSTR MSG_BUTTON_SKIP = _UxGT("Пропуск"); + LSTR MSG_BUTTON_INFO = _UxGT("Інфо"); + LSTR MSG_BUTTON_LEVEL = _UxGT("Рівень"); + LSTR MSG_BUTTON_PAUSE = _UxGT("Пауза"); + LSTR MSG_BUTTON_RESUME = _UxGT("Звіт"); + LSTR MSG_BUTTON_SAVE = _UxGT("Зберегти"); LSTR MSG_PAUSING = _UxGT("Призупинення..."); LSTR MSG_PAUSE_PRINT = _UxGT("Призупинити друк"); @@ -518,6 +533,8 @@ namespace Language_uk { LSTR MSG_USERWAIT = _UxGT("Продовжити..."); LSTR MSG_PRINT_PAUSED = _UxGT("Друк призупинено"); LSTR MSG_PRINTING = _UxGT("Друк..."); + LSTR MSG_STOPPING = _UxGT("Зупинка..."); + LSTR MSG_REMAINING_TIME = _UxGT("Залишилось"); LSTR MSG_PRINT_ABORTED = _UxGT("Друк скасовано"); LSTR MSG_PRINT_DONE = _UxGT("Друк завершено"); LSTR MSG_NO_MOVE = _UxGT("Немає руху."); @@ -702,15 +719,32 @@ namespace Language_uk { LSTR MSG_INFO_COMPLETED_PRINTS = _UxGT("Завершено"); LSTR MSG_INFO_PRINT_FILAMENT = _UxGT("Екструдовано"); + LSTR MSG_PLEASE_PREHEAT = _UxGT("Нагрійте хотенд"); + LSTR MSG_COLORS_GET = _UxGT("Отримати колір"); #if LCD_WIDTH >= 20 || HAS_DWIN_E3V2 + LSTR MSG_MEDIA_NOT_INSERTED = _UxGT("Носій не вставлений"); + LSTR MSG_PLEASE_WAIT_REBOOT = _UxGT("Перезавантаження..."); LSTR MSG_INFO_PRINT_COUNT = _UxGT("Кількість друків"); - LSTR MSG_INFO_PRINT_TIME = _UxGT("Весь час друку"); + LSTR MSG_INFO_PRINT_TIME = _UxGT("Час друку"); LSTR MSG_INFO_PRINT_LONGEST = _UxGT("Найдовший час"); + LSTR MSG_COLORS_SELECT = _UxGT("Обрати кольори"); + LSTR MSG_COLORS_APPLIED = _UxGT("Кольори застосовані"); #else + LSTR MSG_MEDIA_NOT_INSERTED = _UxGT("Немає носія"); + LSTR MSG_PLEASE_WAIT_REBOOT = _UxGT("Перезавантаж..."); LSTR MSG_INFO_PRINT_COUNT = _UxGT("Друків"); LSTR MSG_INFO_PRINT_TIME = _UxGT("Загалом"); LSTR MSG_INFO_PRINT_LONGEST = _UxGT("Найдовше"); + LSTR MSG_COLORS_SELECT = _UxGT("Кольори"); + LSTR MSG_COLORS_APPLIED = _UxGT("Кольори застос."); #endif + LSTR MSG_COLORS_RED = _UxGT("Червоний"); + LSTR MSG_COLORS_GREEN = _UxGT("Зелений"); + LSTR MSG_COLORS_BLUE = _UxGT("Синій"); + LSTR MSG_COLORS_WHITE = _UxGT("Білий"); + LSTR MSG_UI_LANGUAGE = _UxGT("Мова"); + LSTR MSG_SOUND_ENABLE = _UxGT("Дозволити звук"); + LSTR MSG_LOCKSCREEN = _UxGT("Блокувати екран"); LSTR MSG_INFO_MIN_TEMP = _UxGT("Мін. ") LCD_STR_THERMOMETER; LSTR MSG_INFO_MAX_TEMP = _UxGT("Макс. ") LCD_STR_THERMOMETER; diff --git a/Marlin/src/lcd/lcdprint.h b/Marlin/src/lcd/lcdprint.h index c701a59568..d716d035ca 100644 --- a/Marlin/src/lcd/lcdprint.h +++ b/Marlin/src/lcd/lcdprint.h @@ -190,6 +190,9 @@ inline lcd_uint_t lcd_put_u8str_ind_P(const lcd_uint_t col, const lcd_uint_t row lcd_moveto(col, row); return lcd_put_u8str_ind_P(pstr, ind, inStr, maxlen); } +inline lcd_uint_t lcd_put_u8str_ind(FSTR_P const fstr, const int8_t ind, FSTR_P const inFstr=nullptr, const lcd_uint_t maxlen=LCD_WIDTH) { + return lcd_put_u8str_ind_P(FTOP(fstr), ind, FTOP(inFstr), maxlen); +} inline lcd_uint_t lcd_put_u8str_ind(const lcd_uint_t col, const lcd_uint_t row, FSTR_P const fstr, const int8_t ind, FSTR_P const inFstr=nullptr, const lcd_uint_t maxlen=LCD_WIDTH) { return lcd_put_u8str_ind_P(col, row, FTOP(fstr), ind, FTOP(inFstr), maxlen); } diff --git a/Marlin/src/lcd/marlinui.cpp b/Marlin/src/lcd/marlinui.cpp index d2884cc3f1..7c97ef791d 100644 --- a/Marlin/src/lcd/marlinui.cpp +++ b/Marlin/src/lcd/marlinui.cpp @@ -47,8 +47,7 @@ MarlinUI ui; #if ENABLED(DWIN_CREALITY_LCD) #include "e3v2/creality/dwin.h" -#elif ENABLED(DWIN_CREALITY_LCD_ENHANCED) - #include "fontutils.h" +#elif ENABLED(DWIN_LCD_PROUI) #include "e3v2/proui/dwin.h" #elif ENABLED(DWIN_CREALITY_LCD_JYERSUI) #include "e3v2/jyersui/dwin.h" @@ -69,11 +68,15 @@ MarlinUI ui; constexpr uint8_t epps = ENCODER_PULSES_PER_STEP; #if HAS_STATUS_MESSAGE - #if ENABLED(STATUS_MESSAGE_SCROLLING) && EITHER(HAS_WIRED_LCD, DWIN_CREALITY_LCD_ENHANCED) + #if ENABLED(STATUS_MESSAGE_SCROLLING) && EITHER(HAS_WIRED_LCD, DWIN_LCD_PROUI) uint8_t MarlinUI::status_scroll_offset; // = 0 #endif char MarlinUI::status_message[MAX_MESSAGE_LENGTH + 1]; uint8_t MarlinUI::alert_level; // = 0 + #if HAS_STATUS_MESSAGE_TIMEOUT + millis_t MarlinUI::status_message_expire_ms; // = 0 + #endif + statusResetFunc_t MarlinUI::status_reset_callback; // = nullptr #endif #if ENABLED(LCD_SET_PROGRESS_MANUALLY) @@ -594,7 +597,7 @@ void MarlinUI::init() { // share the same line on the display. // - #if DISABLED(PROGRESS_MSG_ONCE) || (PROGRESS_MSG_EXPIRE > 0) + #if DISABLED(PROGRESS_MSG_ONCE) || PROGRESS_MSG_EXPIRE > 0 #define GOT_MS const millis_t ms = millis(); #endif @@ -628,6 +631,18 @@ void MarlinUI::init() { #endif // BASIC_PROGRESS_BAR + bool did_expire = status_reset_callback && (*status_reset_callback)(); + + #if HAS_STATUS_MESSAGE_TIMEOUT + #ifndef GOT_MS + #define GOT_MS + const millis_t ms = millis(); + #endif + did_expire |= status_message_expire_ms && ELAPSED(ms, status_message_expire_ms); + #endif + + if (did_expire) reset_status(); + #if HAS_MARLINUI_MENU if (use_click()) { #if BOTH(FILAMENT_LCD_DISPLAY, SDSUPPORT) @@ -1177,7 +1192,7 @@ void MarlinUI::init() { #if HAS_ADC_BUTTONS typedef struct { - uint16_t ADCKeyValueMin, ADCKeyValueMax; + raw_adc_t ADCKeyValueMin, ADCKeyValueMax; uint8_t ADCKeyNo; } _stADCKeypadTable_; @@ -1204,10 +1219,10 @@ void MarlinUI::init() { #endif // Calculate the ADC value for the voltage divider with specified pull-down resistor value - #define ADC_BUTTON_VALUE(r) int(HAL_ADC_RANGE * (ADC_BUTTONS_VALUE_SCALE) * r / (r + ADC_BUTTONS_R_PULLUP)) + #define ADC_BUTTON_VALUE(r) raw_adc_t(HAL_ADC_RANGE * (ADC_BUTTONS_VALUE_SCALE) * r / (r + ADC_BUTTONS_R_PULLUP)) - static constexpr uint16_t adc_button_tolerance = HAL_ADC_RANGE * 25 / 1024, - adc_other_button = HAL_ADC_RANGE * 1000 / 1024; + static constexpr raw_adc_t adc_button_tolerance = HAL_ADC_RANGE * 25 / 1024, + adc_other_button = raw_adc_t(uint32_t(HAL_ADC_RANGE * 1000UL) / 1024UL); static const _stADCKeypadTable_ stADCKeyTable[] PROGMEM = { // VALUE_MIN, VALUE_MAX, KEY { adc_other_button, HAL_ADC_RANGE, 1 + BLEN_KEYPAD_F1 }, // F1 @@ -1227,13 +1242,13 @@ void MarlinUI::init() { uint8_t get_ADC_keyValue() { if (thermalManager.ADCKey_count >= 16) { - const uint16_t currentkpADCValue = thermalManager.current_ADCKey_raw; + const raw_adc_t currentkpADCValue = thermalManager.current_ADCKey_raw; thermalManager.current_ADCKey_raw = HAL_ADC_RANGE; thermalManager.ADCKey_count = 0; if (currentkpADCValue < adc_other_button) LOOP_L_N(i, ADC_KEY_NUM) { - const uint16_t lo = pgm_read_word(&stADCKeyTable[i].ADCKeyValueMin), - hi = pgm_read_word(&stADCKeyTable[i].ADCKeyValueMax); + const raw_adc_t lo = pgm_read_word(&stADCKeyTable[i].ADCKeyValueMin), + hi = pgm_read_word(&stADCKeyTable[i].ADCKeyValueMax); if (WITHIN(currentkpADCValue, lo, hi)) return pgm_read_byte(&stADCKeyTable[i].ADCKeyNo); } } @@ -1421,6 +1436,7 @@ void MarlinUI::init() { #if SERVICE_INTERVAL_3 > 0 static PGMSTR(service3, "> " SERVICE_NAME_3 "!"); #endif + FSTR_P msg; if (printingIsPaused()) msg = GET_TEXT_F(MSG_PRINT_PAUSED); @@ -1441,21 +1457,28 @@ void MarlinUI::init() { else if (print_job_timer.needsService(3)) msg = FPSTR(service3); #endif - else if (!no_welcome) - msg = GET_TEXT_F(WELCOME_MSG); + else if (!no_welcome) msg = GET_TEXT_F(WELCOME_MSG); + + else if (ENABLED(DWIN_LCD_PROUI)) + msg = F(""); else return; set_status(msg, -1); } + /** + * Set Status with a fixed string and alert level. + * @param fstr A constant F-string to set as the status. + * @param level Alert level. Negative to ignore and reset the level. Non-zero never expires. + */ void MarlinUI::set_status(FSTR_P const fstr, int8_t level) { - PGM_P const pstr = FTOP(fstr); + // Alerts block lower priority messages if (level < 0) level = alert_level = 0; if (level < alert_level) return; alert_level = level; - TERN_(HOST_STATUS_NOTIFICATIONS, hostui.notify(fstr)); + PGM_P const pstr = FTOP(fstr); // Since the message is encoded in UTF8 it must // only be cut on a character boundary. @@ -1475,6 +1498,8 @@ void MarlinUI::init() { strncpy_P(status_message, pstr, maxLen); status_message[maxLen] = '\0'; + TERN_(HOST_STATUS_NOTIFICATIONS, hostui.notify(fstr)); + finish_status(level > 0); } @@ -1486,9 +1511,12 @@ void MarlinUI::init() { #include - void MarlinUI::status_printf(const uint8_t level, FSTR_P const fmt, ...) { + void MarlinUI::status_printf(int8_t level, FSTR_P const fmt, ...) { + // Alerts block lower priority messages + if (level < 0) level = alert_level = 0; if (level < alert_level) return; alert_level = level; + va_list args; va_start(args, FTOP(fmt)); vsnprintf_P(status_message, MAX_MESSAGE_LENGTH, FTOP(fmt), args); @@ -1503,6 +1531,10 @@ void MarlinUI::init() { UNUSED(persist); + set_status_reset_fn(); + + TERN_(HAS_STATUS_MESSAGE_TIMEOUT, status_message_expire_ms = persist ? 0 : millis() + (STATUS_MESSAGE_TIMEOUT_SEC) * 1000UL); + #if HAS_WIRED_LCD #if BASIC_PROGRESS_BAR || BOTH(FILAMENT_LCD_DISPLAY, SDSUPPORT) @@ -1522,13 +1554,13 @@ void MarlinUI::init() { #endif - #if ENABLED(STATUS_MESSAGE_SCROLLING) && EITHER(HAS_WIRED_LCD, DWIN_CREALITY_LCD_ENHANCED) + #if ENABLED(STATUS_MESSAGE_SCROLLING) && EITHER(HAS_WIRED_LCD, DWIN_LCD_PROUI) status_scroll_offset = 0; #endif TERN_(EXTENSIBLE_UI, ExtUI::onStatusChanged(status_message)); TERN_(DWIN_CREALITY_LCD, DWIN_StatusChanged(status_message)); - TERN_(DWIN_CREALITY_LCD_ENHANCED, DWIN_CheckStatusMessage()); + TERN_(DWIN_LCD_PROUI, DWIN_CheckStatusMessage()); TERN_(DWIN_CREALITY_LCD_JYERSUI, CrealityDWIN.Update_Status(status_message)); } @@ -1550,7 +1582,22 @@ void MarlinUI::init() { #endif -#endif +#else // !HAS_STATUS_MESSAGE + + // + // Send the status line as a host notification + // + void MarlinUI::set_status(const char * const cstr, const bool) { + TERN(HOST_PROMPT_SUPPORT, hostui.notify(cstr), UNUSED(cstr)); + } + void MarlinUI::set_status(FSTR_P const fstr, const int8_t) { + TERN(HOST_PROMPT_SUPPORT, hostui.notify(fstr), UNUSED(fstr)); + } + void MarlinUI::status_printf(int8_t, FSTR_P const fstr, ...) { + TERN(HOST_PROMPT_SUPPORT, hostui.notify(fstr), UNUSED(fstr)); + } + +#endif // !HAS_STATUS_MESSAGE #if HAS_DISPLAY @@ -1662,22 +1709,7 @@ void MarlinUI::init() { #endif -#elif !HAS_STATUS_MESSAGE // && !HAS_DISPLAY - - // - // Send the status line as a host notification - // - void MarlinUI::set_status(const char * const cstr, const bool) { - TERN(HOST_PROMPT_SUPPORT, hostui.notify(cstr), UNUSED(cstr)); - } - void MarlinUI::set_status(FSTR_P const fstr, const int8_t) { - TERN(HOST_PROMPT_SUPPORT, hostui.notify(fstr), UNUSED(fstr)); - } - void MarlinUI::status_printf(const uint8_t, FSTR_P const fstr, ...) { - TERN(HOST_PROMPT_SUPPORT, hostui.notify(fstr), UNUSED(fstr)); - } - -#endif // !HAS_DISPLAY && !HAS_STATUS_MESSAGE +#endif // HAS_DISPLAY #if ENABLED(SDSUPPORT) diff --git a/Marlin/src/lcd/marlinui.h b/Marlin/src/lcd/marlinui.h index 15e9f73d65..d9404541d2 100644 --- a/Marlin/src/lcd/marlinui.h +++ b/Marlin/src/lcd/marlinui.h @@ -39,10 +39,6 @@ #define HAS_ENCODER_ACTION 1 #endif -#if HAS_STATUS_MESSAGE - #define START_OF_UTF8_CHAR(C) (((C) & 0xC0u) != 0x80U) -#endif - #if E_MANUAL > 1 #define MULTI_E_MANUAL 1 #endif @@ -57,12 +53,14 @@ #if ENABLED(DWIN_CREALITY_LCD) #include "e3v2/creality/dwin.h" -#elif ENABLED(DWIN_CREALITY_LCD_ENHANCED) +#elif ENABLED(DWIN_LCD_PROUI) #include "e3v2/proui/dwin.h" #endif #define START_OF_UTF8_CHAR(C) (((C) & 0xC0u) != 0x80U) +typedef bool (*statusResetFunc_t)(); + #if HAS_WIRED_LCD enum LCDViewAction : uint8_t { @@ -333,7 +331,7 @@ public: #if HAS_STATUS_MESSAGE - #if EITHER(HAS_WIRED_LCD, DWIN_CREALITY_LCD_ENHANCED) + #if EITHER(HAS_WIRED_LCD, DWIN_LCD_PROUI) #if ENABLED(STATUS_MESSAGE_SCROLLING) #define MAX_MESSAGE_LENGTH _MAX(LONG_FILENAME_LENGTH, MAX_LANG_CHARSIZE * 2 * (LCD_WIDTH)) #else @@ -346,6 +344,10 @@ public: static char status_message[]; static uint8_t alert_level; // Higher levels block lower levels + #if HAS_STATUS_MESSAGE_TIMEOUT + static millis_t status_message_expire_ms; // Reset some status messages after a timeout + #endif + #if ENABLED(STATUS_MESSAGE_SCROLLING) static uint8_t status_scroll_offset; static void advance_status_scroll(); @@ -356,25 +358,20 @@ public: static void reset_status(const bool no_welcome=false); static void set_alert_status(FSTR_P const fstr); static void reset_alert_level() { alert_level = 0; } + + static statusResetFunc_t status_reset_callback; + static void set_status_reset_fn(const statusResetFunc_t fn=nullptr) { status_reset_callback = fn; } #else static constexpr bool has_status() { return false; } static void reset_status(const bool=false) {} static void set_alert_status(FSTR_P const) {} static void reset_alert_level() {} + static void set_status_reset_fn(const statusResetFunc_t=nullptr) {} #endif static void set_status(const char * const cstr, const bool persist=false); static void set_status(FSTR_P const fstr, const int8_t level=0); - static void status_printf(const uint8_t level, FSTR_P const fmt, ...); - - #if EITHER(HAS_DISPLAY, DWIN_CREALITY_LCD_ENHANCED) - static void kill_screen(FSTR_P const lcd_error, FSTR_P const lcd_component); - #if DISABLED(LIGHTWEIGHT_UI) - static void draw_status_message(const bool blink); - #endif - #else - static void kill_screen(FSTR_P const, FSTR_P const) {} - #endif + static void status_printf(int8_t level, FSTR_P const fmt, ...); #if HAS_DISPLAY @@ -489,11 +486,16 @@ public: #endif static void draw_kill_screen(); + static void kill_screen(FSTR_P const lcd_error, FSTR_P const lcd_component); + #if DISABLED(LIGHTWEIGHT_UI) + static void draw_status_message(const bool blink); + #endif #else // No LCD static void update() {} static void return_to_status() {} + static void kill_screen(FSTR_P const, FSTR_P const) {} #endif @@ -619,7 +621,7 @@ public: static bool use_click() { return false; } #endif - #if ENABLED(ADVANCED_PAUSE_FEATURE) && ANY(HAS_MARLINUI_MENU, EXTENSIBLE_UI, DWIN_CREALITY_LCD_ENHANCED, DWIN_CREALITY_LCD_JYERSUI) + #if ENABLED(ADVANCED_PAUSE_FEATURE) && ANY(HAS_MARLINUI_MENU, EXTENSIBLE_UI, DWIN_LCD_PROUI, DWIN_CREALITY_LCD_JYERSUI) static void pause_show_message(const PauseMessage message, const PauseMode mode=PAUSE_MODE_SAME, const uint8_t extruder=active_extruder); #else static void _pause_show_message() {} @@ -684,7 +686,31 @@ public: #endif static void update_buttons(); - static bool button_pressed() { return BUTTON_CLICK() || TERN(TOUCH_SCREEN, touch_pressed(), false); } + + #if HAS_ENCODER_NOISE + #ifndef ENCODER_SAMPLES + #define ENCODER_SAMPLES 10 + #endif + + /** + * Some printers may have issues with EMI noise especially using a motherboard with 3.3V logic levels + * it may cause the logical LOW to float into the undefined region and register as a logical HIGH + * causing it to erroneously register as if someone clicked the button and in worst case make the + * printer unusable in practice. + */ + static bool hw_button_pressed() { + LOOP_L_N(s, ENCODER_SAMPLES) { + if (!BUTTON_CLICK()) return false; + safe_delay(1); + } + return true; + } + #else + static bool hw_button_pressed() { return BUTTON_CLICK(); } + #endif + + static bool button_pressed() { return hw_button_pressed() || TERN0(TOUCH_SCREEN, touch_pressed()); } + #if EITHER(AUTO_BED_LEVELING_UBL, G26_MESH_VALIDATION) static void wait_for_release(); #endif diff --git a/Marlin/src/lcd/menu/menu.cpp b/Marlin/src/lcd/menu/menu.cpp index 2dca6c1b82..52c43ec5e9 100644 --- a/Marlin/src/lcd/menu/menu.cpp +++ b/Marlin/src/lcd/menu/menu.cpp @@ -276,11 +276,7 @@ void scroll_screen(const uint8_t limit, const bool is_menu) { #if HAS_BUZZER void MarlinUI::completion_feedback(const bool good/*=true*/) { TERN_(HAS_TOUCH_SLEEP, wakeup_screen()); // Wake up on rotary encoder click... - if (good) { - BUZZ(100, 659); - BUZZ(100, 698); - } - else BUZZ(20, 440); + if (good) OKAY_BUZZ(); else ERR_BUZZ(); } #endif diff --git a/Marlin/src/lcd/menu/menu.h b/Marlin/src/lcd/menu/menu.h index 72826262f4..b111236d69 100644 --- a/Marlin/src/lcd/menu/menu.h +++ b/Marlin/src/lcd/menu/menu.h @@ -114,8 +114,8 @@ class MenuItem_confirm : public MenuItemBase { selectFunc_t yesFunc, selectFunc_t noFunc, PGM_P const pref, FSTR_P const string, PGM_P const suff=nullptr ) { - char str[strlen_P((PGM_P)string) + 1]; - strcpy_P(str, (PGM_P)string); + char str[strlen_P(FTOP(string)) + 1]; + strcpy_P(str, FTOP(string)); select_screen(yes, no, yesFunc, noFunc, pref, str, suff); } // Shortcut for prompt with "NO"/ "YES" labels diff --git a/Marlin/src/lcd/menu/menu_advanced.cpp b/Marlin/src/lcd/menu/menu_advanced.cpp index 1bc9b9e88e..9acf315c91 100644 --- a/Marlin/src/lcd/menu/menu_advanced.cpp +++ b/Marlin/src/lcd/menu/menu_advanced.cpp @@ -39,11 +39,11 @@ #include "../../module/probe.h" #endif -#if ENABLED(PIDTEMP) +#if ANY(PIDTEMP, PIDTEMPBED, PIDTEMPCHAMBER) #include "../../module/temperature.h" #endif -#if HAS_FILAMENT_RUNOUT_DISTANCE +#if HAS_FILAMENT_SENSOR #include "../../feature/runout.h" #endif @@ -68,7 +68,7 @@ void menu_backlash(); START_MENU(); BACK_ITEM(MSG_ADVANCED_SETTINGS); #define EDIT_DAC_PERCENT(A) EDIT_ITEM(uint8, MSG_DAC_PERCENT_##A, &driverPercent[_AXIS(A)], 0, 100, []{ stepper_dac.set_current_percents(driverPercent); }) - LOGICAL_AXIS_CODE(EDIT_DAC_PERCENT(E), EDIT_DAC_PERCENT(A), EDIT_DAC_PERCENT(B), EDIT_DAC_PERCENT(C), EDIT_DAC_PERCENT(I), EDIT_DAC_PERCENT(J), EDIT_DAC_PERCENT(K)); + LOGICAL_AXIS_CODE(EDIT_DAC_PERCENT(E), EDIT_DAC_PERCENT(A), EDIT_DAC_PERCENT(B), EDIT_DAC_PERCENT(C), EDIT_DAC_PERCENT(I), EDIT_DAC_PERCENT(J), EDIT_DAC_PERCENT(K), EDIT_DAC_PERCENT(U), EDIT_DAC_PERCENT(V), EDIT_DAC_PERCENT(W)); ACTION_ITEM(MSG_DAC_EEPROM_WRITE, stepper_dac.commit_eeprom); END_MENU(); } @@ -97,6 +97,54 @@ void menu_backlash(); #endif +#if HAS_FILAMENT_SENSOR && DISABLED(SLIM_LCD_MENUS) + + void set_runout_mode_none(const uint8_t e) { runout.mode[e] = RM_NONE; runout.setup(); } + void set_runout_mode_high(const uint8_t e) { runout.mode[e] = RM_OUT_ON_HIGH; runout.setup(); } + void set_runout_mode_low(const uint8_t e) { runout.mode[e] = RM_OUT_ON_LOW; runout.setup(); } + void set_runout_mode_motion(const uint8_t e) { runout.mode[e] = RM_MOTION_SENSOR; runout.setup(); } + + #define RUNOUT_EDIT_ITEMS(F) do{ \ + EDIT_ITEM(bool, MSG_RUNOUT_SENSOR, &runout.enabled[F]); \ + ACTION_ITEM(MSG_RUNOUT_MODE_NONE, []{ set_runout_mode_none(F); }); \ + ACTION_ITEM(MSG_RUNOUT_MODE_HIGH, []{ set_runout_mode_high(F); }); \ + ACTION_ITEM(MSG_RUNOUT_MODE_LOW, []{ set_runout_mode_low(F); }); \ + ACTION_ITEM(MSG_RUNOUT_MODE_MOTION, []{ set_runout_mode_motion(F); }); \ + editable.decimal = runout.runout_distance(F); \ + EDIT_ITEM_FAST(float3, MSG_RUNOUT_DISTANCE_MM, &editable.decimal, 1, 999, \ + []{ runout.set_runout_distance(editable.decimal, F); }, true \ + ); \ + }while(0) + + void menu_runout_config() { + START_MENU(); + BACK_ITEM(MSG_CONFIGURATION); + RUNOUT_EDIT_ITEMS(0); + #if NUM_RUNOUT_SENSORS > 1 + RUNOUT_EDIT_ITEMS(1); + #endif + #if NUM_RUNOUT_SENSORS > 2 + RUNOUT_EDIT_ITEMS(2); + #endif + #if NUM_RUNOUT_SENSORS > 3 + RUNOUT_EDIT_ITEMS(3); + #endif + #if NUM_RUNOUT_SENSORS > 4 + RUNOUT_EDIT_ITEMS(4); + #endif + #if NUM_RUNOUT_SENSORS > 5 + RUNOUT_EDIT_ITEMS(5); + #endif + #if NUM_RUNOUT_SENSORS > 6 + RUNOUT_EDIT_ITEMS(6); + #endif + #if NUM_RUNOUT_SENSORS > 7 + RUNOUT_EDIT_ITEMS(7); + #endif + END_MENU(); + } +#endif + #if DISABLED(NO_VOLUMETRICS) || ENABLED(ADVANCED_PAUSE_FEATURE) // // Advanced Settings > Filament @@ -109,8 +157,8 @@ void menu_backlash(); #if EXTRUDERS == 1 EDIT_ITEM(float42_52, MSG_ADVANCE_K, &planner.extruder_advance_K[0], 0, 10); #elif HAS_MULTI_EXTRUDER - LOOP_L_N(n, EXTRUDERS) - EDIT_ITEM_N(float42_52, n, MSG_ADVANCE_K_E, &planner.extruder_advance_K[n], 0, 10); + EXTRUDER_LOOP() + EDIT_ITEM_N(float42_52, e, MSG_ADVANCE_K_E, &planner.extruder_advance_K[e], 0, 10); #endif #endif @@ -120,16 +168,16 @@ void menu_backlash(); #if ENABLED(VOLUMETRIC_EXTRUDER_LIMIT) EDIT_ITEM_FAST(float42_52, MSG_VOLUMETRIC_LIMIT, &planner.volumetric_extruder_limit[active_extruder], 0.0f, 20.0f, planner.calculate_volumetric_extruder_limits); #if HAS_MULTI_EXTRUDER - LOOP_L_N(n, EXTRUDERS) - EDIT_ITEM_FAST_N(float42_52, n, MSG_VOLUMETRIC_LIMIT_E, &planner.volumetric_extruder_limit[n], 0.0f, 20.00f, planner.calculate_volumetric_extruder_limits); + EXTRUDER_LOOP() + EDIT_ITEM_FAST_N(float42_52, e, MSG_VOLUMETRIC_LIMIT_E, &planner.volumetric_extruder_limit[e], 0.0f, 20.00f, planner.calculate_volumetric_extruder_limits); #endif #endif if (parser.volumetric_enabled) { EDIT_ITEM_FAST(float43, MSG_FILAMENT_DIAM, &planner.filament_size[active_extruder], 1.5f, 3.25f, planner.calculate_volumetric_multipliers); #if HAS_MULTI_EXTRUDER - LOOP_L_N(n, EXTRUDERS) - EDIT_ITEM_FAST_N(float43, n, MSG_FILAMENT_DIAM_E, &planner.filament_size[n], 1.5f, 3.25f, planner.calculate_volumetric_multipliers); + EXTRUDER_LOOP() + EDIT_ITEM_FAST_N(float43, e, MSG_FILAMENT_DIAM_E, &planner.filament_size[e], 1.5f, 3.25f, planner.calculate_volumetric_multipliers); #endif } #endif @@ -139,22 +187,19 @@ void menu_backlash(); EDIT_ITEM_FAST(float4, MSG_FILAMENT_UNLOAD, &fc_settings[active_extruder].unload_length, 0, extrude_maxlength); #if HAS_MULTI_EXTRUDER - LOOP_L_N(n, EXTRUDERS) - EDIT_ITEM_FAST_N(float4, n, MSG_FILAMENTUNLOAD_E, &fc_settings[n].unload_length, 0, extrude_maxlength); + EXTRUDER_LOOP() + EDIT_ITEM_FAST_N(float4, e, MSG_FILAMENTUNLOAD_E, &fc_settings[e].unload_length, 0, extrude_maxlength); #endif EDIT_ITEM_FAST(float4, MSG_FILAMENT_LOAD, &fc_settings[active_extruder].load_length, 0, extrude_maxlength); #if HAS_MULTI_EXTRUDER - LOOP_L_N(n, EXTRUDERS) - EDIT_ITEM_FAST_N(float4, n, MSG_FILAMENTLOAD_E, &fc_settings[n].load_length, 0, extrude_maxlength); + EXTRUDER_LOOP() + EDIT_ITEM_FAST_N(float4, e, MSG_FILAMENTLOAD_E, &fc_settings[e].load_length, 0, extrude_maxlength); #endif #endif - #if HAS_FILAMENT_RUNOUT_DISTANCE - editable.decimal = runout.runout_distance(); - EDIT_ITEM_FAST(float3, MSG_RUNOUT_DISTANCE_MM, &editable.decimal, 1, 999, - []{ runout.set_runout_distance(editable.decimal); }, true - ); + #if HAS_FILAMENT_SENSOR && DISABLED(SLIM_LCD_MENUS) + SUBMENU(MSG_RUNOUT_MODE, menu_runout_config); #endif END_MENU(); @@ -190,7 +235,12 @@ void menu_backlash(); #if ENABLED(PIDTEMPCHAMBER) case H_CHAMBER: tune_temp = autotune_temp_chamber; break; #endif - default: tune_temp = autotune_temp[hid]; break; + default: + #if ENABLED(PIDTEMP) + tune_temp = autotune_temp[hid]; break; + #else + return; + #endif } sprintf_P(cmd, PSTR("M303 U1 E%i S%i"), hid, tune_temp); queue.inject(cmd); @@ -206,14 +256,36 @@ void menu_backlash(); // Helpers for editing PID Ki & Kd values // grab the PID value out of the temp variable; scale it; then update the PID driver void copy_and_scalePID_i(int16_t e) { - UNUSED(e); - PID_PARAM(Ki, e) = scalePID_i(raw_Ki); - thermalManager.updatePID(); + switch (e) { + #if ENABLED(PIDTEMPBED) + case H_BED: thermalManager.temp_bed.pid.Ki = scalePID_i(raw_Ki); break; + #endif + #if ENABLED(PIDTEMPCHAMBER) + case H_CHAMBER: thermalManager.temp_chamber.pid.Ki = scalePID_i(raw_Ki); break; + #endif + default: + #if ENABLED(PIDTEMP) + PID_PARAM(Ki, e) = scalePID_i(raw_Ki); + thermalManager.updatePID(); + #endif + break; + } } void copy_and_scalePID_d(int16_t e) { - UNUSED(e); - PID_PARAM(Kd, e) = scalePID_d(raw_Kd); - thermalManager.updatePID(); + switch (e) { + #if ENABLED(PIDTEMPBED) + case H_BED: thermalManager.temp_bed.pid.Kd = scalePID_d(raw_Kd); break; + #endif + #if ENABLED(PIDTEMPCHAMBER) + case H_CHAMBER: thermalManager.temp_chamber.pid.Kd = scalePID_d(raw_Kd); break; + #endif + default: + #if ENABLED(PIDTEMP) + PID_PARAM(Kd, e) = scalePID_d(raw_Kd); + thermalManager.updatePID(); + #endif + break; + } } #define _DEFINE_PIDTEMP_BASE_FUNCS(N) \ @@ -356,7 +428,7 @@ void menu_backlash(); #elif ENABLED(LIMITED_MAX_FR_EDITING) DEFAULT_MAX_FEEDRATE #else - LOGICAL_AXIS_ARRAY(9999, 9999, 9999, 9999, 9999, 9999, 9999) + LOGICAL_AXIS_ARRAY(9999, 9999, 9999, 9999, 9999, 9999, 9999, 9999, 9999, 9999) #endif ; #if ENABLED(LIMITED_MAX_FR_EDITING) && !defined(MAX_FEEDRATE_EDIT_VALUES) @@ -369,7 +441,7 @@ void menu_backlash(); BACK_ITEM(MSG_ADVANCED_SETTINGS); #define EDIT_VMAX(N) EDIT_ITEM_FAST(float5, MSG_VMAX_##N, &planner.settings.max_feedrate_mm_s[_AXIS(N)], 1, max_fr_edit_scaled[_AXIS(N)]) - LINEAR_AXIS_CODE(EDIT_VMAX(A), EDIT_VMAX(B), EDIT_VMAX(C), EDIT_VMAX(I), EDIT_VMAX(J), EDIT_VMAX(K)); + NUM_AXIS_CODE(EDIT_VMAX(A), EDIT_VMAX(B), EDIT_VMAX(C), EDIT_VMAX(I), EDIT_VMAX(J), EDIT_VMAX(K), EDIT_VMAX(U), EDIT_VMAX(V), EDIT_VMAX(W)); #if E_STEPPERS EDIT_ITEM_FAST(float5, MSG_VMAX_E, &planner.settings.max_feedrate_mm_s[E_AXIS_N(active_extruder)], 1, max_fr_edit_scaled.e); @@ -399,7 +471,7 @@ void menu_backlash(); #elif ENABLED(LIMITED_MAX_ACCEL_EDITING) DEFAULT_MAX_ACCELERATION #else - LOGICAL_AXIS_ARRAY(99000, 99000, 99000, 99000, 99000, 99000, 99000) + LOGICAL_AXIS_ARRAY(99000, 99000, 99000, 99000, 99000, 99000, 99000, 99000, 99000, 99000) #endif ; #if ENABLED(LIMITED_MAX_ACCEL_EDITING) && !defined(MAX_ACCEL_EDIT_VALUES) @@ -423,9 +495,10 @@ void menu_backlash(); EDIT_ITEM_FAST(float5_25, MSG_A_TRAVEL, &planner.settings.travel_acceleration, 25, max_accel); #define EDIT_AMAX(Q,L) EDIT_ITEM_FAST(long5_25, MSG_AMAX_##Q, &planner.settings.max_acceleration_mm_per_s2[_AXIS(Q)], L, max_accel_edit_scaled[_AXIS(Q)], []{ planner.reset_acceleration_rates(); }) - LINEAR_AXIS_CODE( + NUM_AXIS_CODE( EDIT_AMAX(A, 100), EDIT_AMAX(B, 100), EDIT_AMAX(C, 10), - EDIT_AMAX(I, 10), EDIT_AMAX(J, 10), EDIT_AMAX(K, 10) + EDIT_AMAX(I, 10), EDIT_AMAX(J, 10), EDIT_AMAX(K, 10), + EDIT_AMAX(U, 10), EDIT_AMAX(V, 10), EDIT_AMAX(W, 10) ); #if ENABLED(DISTINCT_E_FACTORS) @@ -468,9 +541,10 @@ void menu_backlash(); #elif ENABLED(LIMITED_JERK_EDITING) { LOGICAL_AXIS_LIST((DEFAULT_EJERK) * 2, (DEFAULT_XJERK) * 2, (DEFAULT_YJERK) * 2, (DEFAULT_ZJERK) * 2, - (DEFAULT_IJERK) * 2, (DEFAULT_JJERK) * 2, (DEFAULT_KJERK) * 2) } + (DEFAULT_IJERK) * 2, (DEFAULT_JJERK) * 2, (DEFAULT_KJERK) * 2, + (DEFAULT_UJERK) * 2, (DEFAULT_VJERK) * 2, (DEFAULT_WJERK) * 2) } #else - { LOGICAL_AXIS_LIST(990, 990, 990, 990, 990, 990, 990) } + { LOGICAL_AXIS_LIST(990, 990, 990, 990, 990, 990, 990, 990, 990, 990) } #endif ; #define EDIT_JERK(N) EDIT_ITEM_FAST(float3, MSG_V##N##_JERK, &planner.max_jerk[_AXIS(N)], 1, max_jerk_edit[_AXIS(N)]) @@ -479,9 +553,10 @@ void menu_backlash(); #else #define EDIT_JERK_C() EDIT_ITEM_FAST(float52sign, MSG_VC_JERK, &planner.max_jerk.c, 0.1f, max_jerk_edit.c) #endif - LINEAR_AXIS_CODE( + NUM_AXIS_CODE( EDIT_JERK(A), EDIT_JERK(B), EDIT_JERK_C(), - EDIT_JERK(I), EDIT_JERK(J), EDIT_JERK(K) + EDIT_JERK(I), EDIT_JERK(J), EDIT_JERK(K), + EDIT_JERK(U), EDIT_JERK(V), EDIT_JERK(W) ); #if HAS_EXTRUDERS @@ -524,9 +599,10 @@ void menu_advanced_steps_per_mm() { BACK_ITEM(MSG_ADVANCED_SETTINGS); #define EDIT_QSTEPS(Q) EDIT_ITEM_FAST(float61, MSG_##Q##_STEPS, &planner.settings.axis_steps_per_mm[_AXIS(Q)], 5, 9999, []{ planner.refresh_positioning(); }) - LINEAR_AXIS_CODE( + NUM_AXIS_CODE( EDIT_QSTEPS(A), EDIT_QSTEPS(B), EDIT_QSTEPS(C), - EDIT_QSTEPS(I), EDIT_QSTEPS(J), EDIT_QSTEPS(K) + EDIT_QSTEPS(I), EDIT_QSTEPS(J), EDIT_QSTEPS(K), + EDIT_QSTEPS(U), EDIT_QSTEPS(V), EDIT_QSTEPS(W) ); #if ENABLED(DISTINCT_E_FACTORS) diff --git a/Marlin/src/lcd/menu/menu_backlash.cpp b/Marlin/src/lcd/menu/menu_backlash.cpp index faed8cf777..07f3c9d704 100644 --- a/Marlin/src/lcd/menu/menu_backlash.cpp +++ b/Marlin/src/lcd/menu/menu_backlash.cpp @@ -66,6 +66,15 @@ void menu_backlash() { #if HAS_K_AXIS && _CAN_CALI(K) EDIT_BACKLASH_DISTANCE(K); #endif + #if HAS_U_AXIS && _CAN_CALI(U) + EDIT_BACKLASH_DISTANCE(U); + #endif + #if HAS_V_AXIS && _CAN_CALI(V) + EDIT_BACKLASH_DISTANCE(V); + #endif + #if HAS_W_AXIS && _CAN_CALI(W) + EDIT_BACKLASH_DISTANCE(W); + #endif #ifdef BACKLASH_SMOOTHING_MM editable.decimal = backlash.get_smoothing_mm(); diff --git a/Marlin/src/lcd/menu/menu_configuration.cpp b/Marlin/src/lcd/menu/menu_configuration.cpp index b4e9287bd4..349aafbb8a 100644 --- a/Marlin/src/lcd/menu/menu_configuration.cpp +++ b/Marlin/src/lcd/menu/menu_configuration.cpp @@ -145,9 +145,9 @@ void menu_advanced_settings(); EDIT_ITEM(uint8, MSG_TOOL_MIGRATION_END, &migration.last, 0, EXTRUDERS - 1); // Migrate to a chosen extruder - LOOP_L_N(s, EXTRUDERS) { - if (s != active_extruder) { - ACTION_ITEM_N_P(s, msg_migrate, []{ + EXTRUDER_LOOP() { + if (e != active_extruder) { + ACTION_ITEM_N_P(e, msg_migrate, []{ char cmd[12]; sprintf_P(cmd, PSTR("M217 T%i"), int(MenuItemBase::itemIndex)); queue.inject(cmd); @@ -550,7 +550,7 @@ void menu_configuration() { #endif #if HAS_FILAMENT_SENSOR - EDIT_ITEM(bool, MSG_RUNOUT_SENSOR, &runout.enabled, runout.reset); + EDIT_ITEM(bool, MSG_RUNOUT_SENSOR, &runout.enabled[active_extruder], runout.reset); #endif #if HAS_FANCHECK diff --git a/Marlin/src/lcd/menu/menu_filament.cpp b/Marlin/src/lcd/menu/menu_filament.cpp index 9f432c405c..98278e7a6e 100644 --- a/Marlin/src/lcd/menu/menu_filament.cpp +++ b/Marlin/src/lcd/menu/menu_filament.cpp @@ -254,7 +254,7 @@ void menu_pause_option() { #if HAS_FILAMENT_SENSOR const bool still_out = runout.filament_ran_out; if (still_out) - EDIT_ITEM(bool, MSG_RUNOUT_SENSOR, &runout.enabled, runout.reset); + EDIT_ITEM(bool, MSG_RUNOUT_SENSOR, &runout.enabled[active_extruder], runout.reset); #else constexpr bool still_out = false; #endif diff --git a/Marlin/src/lcd/menu/menu_mmu2.cpp b/Marlin/src/lcd/menu/menu_mmu2.cpp index 4f3728b74e..a2412b0f6a 100644 --- a/Marlin/src/lcd/menu/menu_mmu2.cpp +++ b/Marlin/src/lcd/menu/menu_mmu2.cpp @@ -48,7 +48,7 @@ void _mmu2_load_filament(uint8_t index) { ui.reset_status(); } void action_mmu2_load_all() { - LOOP_L_N(i, EXTRUDERS) _mmu2_load_filament(i); + EXTRUDER_LOOP() _mmu2_load_filament(e); ui.return_to_status(); } @@ -56,14 +56,14 @@ void menu_mmu2_load_filament() { START_MENU(); BACK_ITEM(MSG_MMU2_MENU); ACTION_ITEM(MSG_MMU2_ALL, action_mmu2_load_all); - LOOP_L_N(i, EXTRUDERS) ACTION_ITEM_N(i, MSG_MMU2_FILAMENT_N, []{ _mmu2_load_filament(MenuItemBase::itemIndex); }); + EXTRUDER_LOOP() ACTION_ITEM_N(e, MSG_MMU2_FILAMENT_N, []{ _mmu2_load_filament(MenuItemBase::itemIndex); }); END_MENU(); } void menu_mmu2_load_to_nozzle() { START_MENU(); BACK_ITEM(MSG_MMU2_MENU); - LOOP_L_N(i, EXTRUDERS) ACTION_ITEM_N(i, MSG_MMU2_FILAMENT_N, []{ action_mmu2_load_filament_to_nozzle(MenuItemBase::itemIndex); }); + EXTRUDER_LOOP() ACTION_ITEM_N(e, MSG_MMU2_FILAMENT_N, []{ action_mmu2_load_filament_to_nozzle(MenuItemBase::itemIndex); }); END_MENU(); } @@ -89,7 +89,7 @@ void action_mmu2_unload_filament() { void menu_mmu2_eject_filament() { START_MENU(); BACK_ITEM(MSG_MMU2_MENU); - LOOP_L_N(i, EXTRUDERS) ACTION_ITEM_N(i, MSG_MMU2_FILAMENT_N, []{ _mmu2_eject_filament(MenuItemBase::itemIndex); }); + EXTRUDER_LOOP() ACTION_ITEM_N(e, MSG_MMU2_FILAMENT_N, []{ _mmu2_eject_filament(MenuItemBase::itemIndex); }); END_MENU(); } @@ -130,7 +130,7 @@ void menu_mmu2_choose_filament() { #if LCD_HEIGHT > 2 STATIC_ITEM(MSG_MMU2_CHOOSE_FILAMENT_HEADER, SS_DEFAULT|SS_INVERT); #endif - LOOP_L_N(i, EXTRUDERS) ACTION_ITEM_N(i, MSG_MMU2_FILAMENT_N, []{ action_mmu2_chosen(MenuItemBase::itemIndex); }); + EXTRUDER_LOOP() ACTION_ITEM_N(e, MSG_MMU2_FILAMENT_N, []{ action_mmu2_chosen(MenuItemBase::itemIndex); }); END_MENU(); } diff --git a/Marlin/src/lcd/menu/menu_motion.cpp b/Marlin/src/lcd/menu/menu_motion.cpp index 0a446b1349..baed081036 100644 --- a/Marlin/src/lcd/menu/menu_motion.cpp +++ b/Marlin/src/lcd/menu/menu_motion.cpp @@ -106,6 +106,15 @@ void lcd_move_x() { _lcd_move_xyz(GET_TEXT(MSG_MOVE_X), X_AXIS); } #if HAS_K_AXIS void lcd_move_k() { _lcd_move_xyz(GET_TEXT(MSG_MOVE_K), K_AXIS); } #endif +#if HAS_U_AXIS + void lcd_move_u() { _lcd_move_xyz(GET_TEXT(MSG_MOVE_U), U_AXIS); } +#endif +#if HAS_V_AXIS + void lcd_move_v() { _lcd_move_xyz(GET_TEXT(MSG_MOVE_V), V_AXIS); } +#endif +#if HAS_W_AXIS + void lcd_move_w() { _lcd_move_xyz(GET_TEXT(MSG_MOVE_W), W_AXIS); } +#endif #if E_MANUAL @@ -263,6 +272,15 @@ void menu_move() { #if HAS_K_AXIS SUBMENU(MSG_MOVE_K, []{ _menu_move_distance(K_AXIS, lcd_move_k); }); #endif + #if HAS_U_AXIS + SUBMENU(MSG_MOVE_U, []{ _menu_move_distance(U_AXIS, lcd_move_u); }); + #endif + #if HAS_V_AXIS + SUBMENU(MSG_MOVE_V, []{ _menu_move_distance(V_AXIS, lcd_move_v); }); + #endif + #if HAS_W_AXIS + SUBMENU(MSG_MOVE_W, []{ _menu_move_distance(W_AXIS, lcd_move_w); }); + #endif } else GCODES_ITEM(MSG_AUTO_HOME, G28_STR); @@ -354,6 +372,15 @@ void menu_move() { #if HAS_K_AXIS GCODES_ITEM_N(K_AXIS, MSG_AUTO_HOME_A, PSTR("G28" STR_K)); #endif + #if HAS_U_AXIS + GCODES_ITEM_N(U_AXIS, MSG_AUTO_HOME_A, PSTR("G28" STR_U)); + #endif + #if HAS_V_AXIS + GCODES_ITEM_N(V_AXIS, MSG_AUTO_HOME_A, PSTR("G28" STR_V)); + #endif + #if HAS_W_AXIS + GCODES_ITEM_N(W_AXIS, MSG_AUTO_HOME_A, PSTR("G28" STR_W)); + #endif END_MENU(); } @@ -407,6 +434,15 @@ void menu_motion() { #if HAS_K_AXIS GCODES_ITEM_N(K_AXIS, MSG_AUTO_HOME_A, PSTR("G28" STR_K)); #endif + #if HAS_U_AXIS + GCODES_ITEM_N(U_AXIS, MSG_AUTO_HOME_A, PSTR("G28" STR_U)); + #endif + #if HAS_V_AXIS + GCODES_ITEM_N(V_AXIS, MSG_AUTO_HOME_A, PSTR("G28" STR_V)); + #endif + #if HAS_W_AXIS + GCODES_ITEM_N(W_AXIS, MSG_AUTO_HOME_A, PSTR("G28" STR_W)); + #endif #endif #endif diff --git a/Marlin/src/lcd/menu/menu_tmc.cpp b/Marlin/src/lcd/menu/menu_tmc.cpp index 7e206e8d79..995bc3b195 100644 --- a/Marlin/src/lcd/menu/menu_tmc.cpp +++ b/Marlin/src/lcd/menu/menu_tmc.cpp @@ -134,6 +134,9 @@ void menu_tmc_current() { TERN_( I_SENSORLESS, TMC_EDIT_STORED_SGT(I)); TERN_( J_SENSORLESS, TMC_EDIT_STORED_SGT(J)); TERN_( K_SENSORLESS, TMC_EDIT_STORED_SGT(K)); + TERN_( U_SENSORLESS, TMC_EDIT_STORED_SGT(U)); + TERN_( V_SENSORLESS, TMC_EDIT_STORED_SGT(V)); + TERN_( W_SENSORLESS, TMC_EDIT_STORED_SGT(W)); END_MENU(); } diff --git a/Marlin/src/lcd/menu/menu_tune.cpp b/Marlin/src/lcd/menu/menu_tune.cpp index 854f36985f..7954edf5a1 100644 --- a/Marlin/src/lcd/menu/menu_tune.cpp +++ b/Marlin/src/lcd/menu/menu_tune.cpp @@ -199,8 +199,8 @@ void menu_tune() { EDIT_ITEM(int3, MSG_FLOW, &planner.flow_percentage[active_extruder], 10, 999, []{ planner.refresh_e_factor(active_extruder); }); // Flow En: #if HAS_MULTI_EXTRUDER - LOOP_L_N(n, EXTRUDERS) - EDIT_ITEM_N(int3, n, MSG_FLOW_N, &planner.flow_percentage[n], 10, 999, []{ planner.refresh_e_factor(MenuItemBase::itemIndex); }); + EXTRUDER_LOOP() + EDIT_ITEM_N(int3, e, MSG_FLOW_N, &planner.flow_percentage[e], 10, 999, []{ planner.refresh_e_factor(MenuItemBase::itemIndex); }); #endif #endif @@ -211,8 +211,8 @@ void menu_tune() { #if EXTRUDERS == 1 EDIT_ITEM(float42_52, MSG_ADVANCE_K, &planner.extruder_advance_K[0], 0, 10); #elif HAS_MULTI_EXTRUDER - LOOP_L_N(n, EXTRUDERS) - EDIT_ITEM_N(float42_52, n, MSG_ADVANCE_K_E, &planner.extruder_advance_K[n], 0, 10); + EXTRUDER_LOOP() + EDIT_ITEM_N(float42_52, e, MSG_ADVANCE_K_E, &planner.extruder_advance_K[e], 0, 10); #endif #endif diff --git a/Marlin/src/lcd/menu/menu_x_twist.cpp b/Marlin/src/lcd/menu/menu_x_twist.cpp index 93f8de07ad..ce46053dfc 100644 --- a/Marlin/src/lcd/menu/menu_x_twist.cpp +++ b/Marlin/src/lcd/menu/menu_x_twist.cpp @@ -153,7 +153,7 @@ void xatc_wizard_goto_next_point() { measured_z = probe.probe_at_point(x, XATC_Y_POSITION, PROBE_PT_STOW); xatc.set_enabled(true); current_position += probe.offset_xy; - current_position.z = XATC_START_Z - probe.offset.z + measured_z; + current_position.z = (XATC_START_Z) - probe.offset.z + measured_z; line_to_current_position(MMM_TO_MMS(XY_PROBE_FEEDRATE)); ui.wait_for_move = false; } diff --git a/Marlin/src/libs/L64XX/L64XX_Marlin.cpp b/Marlin/src/libs/L64XX/L64XX_Marlin.cpp index a8c2695630..0aa2a85439 100644 --- a/Marlin/src/libs/L64XX/L64XX_Marlin.cpp +++ b/Marlin/src/libs/L64XX/L64XX_Marlin.cpp @@ -37,7 +37,7 @@ L64XX_Marlin L64xxManager; #include "../../module/planner.h" #include "../../HAL/shared/Delay.h" -static const char LINEAR_AXIS_LIST( +static const char NUM_AXIS_LIST( str_X[] PROGMEM = "X ", str_Y[] PROGMEM = "Y ", str_Z[] PROGMEM = "Z ", str_I[] PROGMEM = STR_I " ", str_J[] PROGMEM = STR_J " ", str_K[] PROGMEM = STR_K " " ), @@ -53,7 +53,7 @@ static const char LINEAR_AXIS_LIST( #define _EN_ITEM(N) , str_E##N PGM_P const L64XX_Marlin::index_to_axis[] PROGMEM = { - LINEAR_AXIS_LIST(str_X, str_Y, str_Z, str_I, str_J, str_K), + NUM_AXIS_LIST(str_X, str_Y, str_Z, str_I, str_J, str_K), str_X2, str_Y2, str_Z2, str_Z3, str_Z4 REPEAT(E_STEPPERS, _EN_ITEM) }; @@ -68,7 +68,7 @@ uint8_t L64XX_Marlin::dir_commands[MAX_L64XX]; // array to hold direction comma #define _EN_ITEM(N) , INVERT_E##N##_DIR const uint8_t L64XX_Marlin::index_to_dir[MAX_L64XX] = { - LINEAR_AXIS_LIST(INVERT_X_DIR, INVERT_Y_DIR, INVERT_Z_DIR, INVERT_I_DIR, INVERT_J_DIR, INVERT_K_DIR) + NUM_AXIS_LIST(INVERT_X_DIR, INVERT_Y_DIR, INVERT_Z_DIR, INVERT_I_DIR, INVERT_J_DIR, INVERT_K_DIR) , (INVERT_X_DIR) ^ BOTH(X_DUAL_STEPPER_DRIVERS, INVERT_X2_VS_X_DIR) // X2 , (INVERT_Y_DIR) ^ BOTH(Y_DUAL_STEPPER_DRIVERS, INVERT_Y2_VS_Y_DIR) // Y2 , (INVERT_Z_DIR) ^ ENABLED(INVERT_Z2_VS_Z_DIR) // Z2 diff --git a/Marlin/src/libs/L64XX/L64XX_Marlin.h b/Marlin/src/libs/L64XX/L64XX_Marlin.h index de7c0d6057..d00b5c16cd 100644 --- a/Marlin/src/libs/L64XX/L64XX_Marlin.h +++ b/Marlin/src/libs/L64XX/L64XX_Marlin.h @@ -36,7 +36,7 @@ #define HAS_L64XX_EXTRUDER (AXIS_IS_L64XX(E0) || AXIS_IS_L64XX(E1) || AXIS_IS_L64XX(E2) || AXIS_IS_L64XX(E3) || AXIS_IS_L64XX(E4) || AXIS_IS_L64XX(E5) || AXIS_IS_L64XX(E6) || AXIS_IS_L64XX(E7)) #define _EN_ITEM(N) , E##N -enum L64XX_axis_t : uint8_t { LINEAR_AXIS_LIST(X, Y, Z, I, J, K), X2, Y2, Z2, Z3, Z4 REPEAT(E_STEPPERS, _EN_ITEM), MAX_L64XX }; +enum L64XX_axis_t : uint8_t { NUM_AXIS_LIST(X, Y, Z, I, J, K), X2, Y2, Z2, Z3, Z4 REPEAT(E_STEPPERS, _EN_ITEM), MAX_L64XX }; #undef _EN_ITEM class L64XX_Marlin : public L64XXHelper { diff --git a/Marlin/src/libs/buzzer.h b/Marlin/src/libs/buzzer.h index db5e3ee4ca..73406c0591 100644 --- a/Marlin/src/libs/buzzer.h +++ b/Marlin/src/libs/buzzer.h @@ -127,3 +127,7 @@ #define BUZZ(d,f) NOOP #endif + +#define ERR_BUZZ() BUZZ(400, 40); +#define OKAY_BUZZ() do{ BUZZ(100, 659); BUZZ(10, 0); BUZZ(100, 698); }while(0) +#define DONE_BUZZ(OK) do{ if (OK) OKAY_BUZZ(); else ERR_BUZZ(); }while(0) diff --git a/Marlin/src/libs/vector_3.cpp b/Marlin/src/libs/vector_3.cpp index 614d2121b8..02945fe687 100644 --- a/Marlin/src/libs/vector_3.cpp +++ b/Marlin/src/libs/vector_3.cpp @@ -141,8 +141,7 @@ void matrix_3x3::debug(FSTR_P const title) { if (title) SERIAL_ECHOLNF(title); LOOP_L_N(i, 3) { LOOP_L_N(j, 3) { - if (vectors[i][j] >= 0.0) SERIAL_CHAR('+'); - SERIAL_ECHO_F(vectors[i][j], 6); + serial_offset(vectors[i][j], 2); SERIAL_CHAR(' '); } SERIAL_EOL(); diff --git a/Marlin/src/module/delta.cpp b/Marlin/src/module/delta.cpp index cd40175da4..39eb15f896 100644 --- a/Marlin/src/module/delta.cpp +++ b/Marlin/src/module/delta.cpp @@ -233,6 +233,9 @@ void home_delta() { TERN_(I_SENSORLESS, sensorless_t stealth_states_i = start_sensorless_homing_per_axis(I_AXIS)); TERN_(J_SENSORLESS, sensorless_t stealth_states_j = start_sensorless_homing_per_axis(J_AXIS)); TERN_(K_SENSORLESS, sensorless_t stealth_states_k = start_sensorless_homing_per_axis(K_AXIS)); + TERN_(U_SENSORLESS, sensorless_t stealth_states_u = start_sensorless_homing_per_axis(U_AXIS)); + TERN_(V_SENSORLESS, sensorless_t stealth_states_v = start_sensorless_homing_per_axis(V_AXIS)); + TERN_(W_SENSORLESS, sensorless_t stealth_states_w = start_sensorless_homing_per_axis(W_AXIS)); #endif // Move all carriages together linearly until an endstop is hit. @@ -249,6 +252,9 @@ void home_delta() { TERN_(I_SENSORLESS, end_sensorless_homing_per_axis(I_AXIS, stealth_states_i)); TERN_(J_SENSORLESS, end_sensorless_homing_per_axis(J_AXIS, stealth_states_j)); TERN_(K_SENSORLESS, end_sensorless_homing_per_axis(K_AXIS, stealth_states_k)); + TERN_(U_SENSORLESS, end_sensorless_homing_per_axis(U_AXIS, stealth_states_u)); + TERN_(V_SENSORLESS, end_sensorless_homing_per_axis(V_AXIS, stealth_states_v)); + TERN_(W_SENSORLESS, end_sensorless_homing_per_axis(W_AXIS, stealth_states_w)); #endif endstops.validate_homing_move(); diff --git a/Marlin/src/module/endstops.cpp b/Marlin/src/module/endstops.cpp index 3dd6d8aeb6..68fab98364 100644 --- a/Marlin/src/module/endstops.cpp +++ b/Marlin/src/module/endstops.cpp @@ -47,6 +47,10 @@ #include "../feature/joystick.h" #endif +#if HAS_FILAMENT_SENSOR + #include "../feature/runout.h" +#endif + #if HAS_BED_PROBE #include "probe.h" #endif @@ -319,6 +323,66 @@ void Endstops::init() { #endif #endif + #if HAS_U_MIN + #if ENABLED(ENDSTOPPULLUP_UMIN) + SET_INPUT_PULLUP(U_MIN_PIN); + #elif ENABLED(ENDSTOPPULLDOWN_UMIN) + SET_INPUT_PULLDOWN(U_MIN_PIN); + #else + SET_INPUT(U_MIN_PIN); + #endif + #endif + + #if HAS_U_MAX + #if ENABLED(ENDSTOPPULLUP_UMAX) + SET_INPUT_PULLUP(U_MAX_PIN); + #elif ENABLED(ENDSTOPPULLDOWN_UMIN) + SET_INPUT_PULLDOWN(U_MAX_PIN); + #else + SET_INPUT(U_MAX_PIN); + #endif + #endif + + #if HAS_V_MIN + #if ENABLED(ENDSTOPPULLUP_VMIN) + SET_INPUT_PULLUP(V_MIN_PIN); + #elif ENABLED(ENDSTOPPULLDOWN_VMIN) + SET_INPUT_PULLDOWN(V_MIN_PIN); + #else + SET_INPUT(V_MIN_PIN); + #endif + #endif + + #if HAS_V_MAX + #if ENABLED(ENDSTOPPULLUP_VMAX) + SET_INPUT_PULLUP(V_MAX_PIN); + #elif ENABLED(ENDSTOPPULLDOWN_VMIN) + SET_INPUT_PULLDOWN(V_MAX_PIN); + #else + SET_INPUT(V_MAX_PIN); + #endif + #endif + + #if HAS_W_MIN + #if ENABLED(ENDSTOPPULLUP_WMIN) + SET_INPUT_PULLUP(W_MIN_PIN); + #elif ENABLED(ENDSTOPPULLDOWN_WMIN) + SET_INPUT_PULLDOWN(W_MIN_PIN); + #else + SET_INPUT(W_MIN_PIN); + #endif + #endif + + #if HAS_W_MAX + #if ENABLED(ENDSTOPPULLUP_WMAX) + SET_INPUT_PULLUP(W_MAX_PIN); + #elif ENABLED(ENDSTOPPULLDOWN_WMIN) + SET_INPUT_PULLDOWN(W_MAX_PIN); + #else + SET_INPUT(W_MAX_PIN); + #endif + #endif + #if PIN_EXISTS(CALIBRATION) #if ENABLED(CALIBRATION_PIN_PULLUP) SET_INPUT_PULLUP(CALIBRATION_PIN); @@ -424,7 +488,7 @@ void Endstops::event_handler() { prev_hit_state = hit_state; if (hit_state) { #if HAS_STATUS_MESSAGE - char LINEAR_AXIS_LIST(chrX = ' ', chrY = ' ', chrZ = ' ', chrI = ' ', chrJ = ' ', chrK = ' '), + char NUM_AXIS_LIST(chrX = ' ', chrY = ' ', chrZ = ' ', chrI = ' ', chrJ = ' ', chrK = ' ', chrU = ' ', chrV = ' ', chrW = ' '), chrP = ' '; #define _SET_STOP_CHAR(A,C) (chr## A = C) #else @@ -444,16 +508,22 @@ void Endstops::event_handler() { #define ENDSTOP_HIT_TEST_I() _ENDSTOP_HIT_TEST(I,'I') #define ENDSTOP_HIT_TEST_J() _ENDSTOP_HIT_TEST(J,'J') #define ENDSTOP_HIT_TEST_K() _ENDSTOP_HIT_TEST(K,'K') + #define ENDSTOP_HIT_TEST_U() _ENDSTOP_HIT_TEST(U,'U') + #define ENDSTOP_HIT_TEST_V() _ENDSTOP_HIT_TEST(V,'V') + #define ENDSTOP_HIT_TEST_W() _ENDSTOP_HIT_TEST(W,'W') SERIAL_ECHO_START(); SERIAL_ECHOPGM(STR_ENDSTOPS_HIT); - LINEAR_AXIS_CODE( + NUM_AXIS_CODE( ENDSTOP_HIT_TEST_X(), ENDSTOP_HIT_TEST_Y(), ENDSTOP_HIT_TEST_Z(), _ENDSTOP_HIT_TEST(I,'I'), _ENDSTOP_HIT_TEST(J,'J'), - _ENDSTOP_HIT_TEST(K,'K') + _ENDSTOP_HIT_TEST(K,'K'), + _ENDSTOP_HIT_TEST(U,'U'), + _ENDSTOP_HIT_TEST(V,'V'), + _ENDSTOP_HIT_TEST(W,'W') ); #if USES_Z_MIN_PROBE_PIN @@ -464,9 +534,9 @@ void Endstops::event_handler() { TERN_(HAS_STATUS_MESSAGE, ui.status_printf(0, - F(S_FMT GANG_N_1(LINEAR_AXES, " %c") " %c"), + F(S_FMT GANG_N_1(NUM_AXES, " %c") " %c"), GET_TEXT(MSG_LCD_ENDSTOPS), - LINEAR_AXIS_LIST(chrX, chrY, chrZ, chrI, chrJ, chrK), chrP + NUM_AXIS_LIST(chrX, chrY, chrZ, chrI, chrJ, chrK, chrU, chrV, chrW), chrP ) ); @@ -564,28 +634,59 @@ void _O2 Endstops::report_states() { #if HAS_K_MAX ES_REPORT(K_MAX); #endif + #if HAS_U_MIN + ES_REPORT(U_MIN); + #endif + #if HAS_U_MAX + ES_REPORT(U_MAX); + #endif + #if HAS_V_MIN + ES_REPORT(V_MIN); + #endif + #if HAS_V_MAX + ES_REPORT(V_MAX); + #endif + #if HAS_W_MIN + ES_REPORT(W_MIN); + #endif + #if HAS_W_MAX + ES_REPORT(W_MAX); + #endif #if ENABLED(PROBE_ACTIVATION_SWITCH) print_es_state(probe_switch_activated(), F(STR_PROBE_EN)); #endif #if USES_Z_MIN_PROBE_PIN print_es_state(PROBE_TRIGGERED(), F(STR_Z_PROBE)); #endif - #if MULTI_FILAMENT_SENSOR - #define _CASE_RUNOUT(N) case N: pin = FIL_RUNOUT##N##_PIN; state = FIL_RUNOUT##N##_STATE; break; + #if HAS_FILAMENT_SENSOR LOOP_S_LE_N(i, 1, NUM_RUNOUT_SENSORS) { pin_t pin; - uint8_t state; switch (i) { default: continue; + #define _CASE_RUNOUT(N) case N: pin = FIL_RUNOUT##N##_PIN; break; REPEAT_1(NUM_RUNOUT_SENSORS, _CASE_RUNOUT) + #undef _CASE_RUNOUT } - SERIAL_ECHOPGM(STR_FILAMENT); - if (i > 1) SERIAL_CHAR(' ', '0' + i); - print_es_state(extDigitalRead(pin) != state); + const RunoutMode rm = runout.mode[i - 1]; + const uint8_t outval = runout.out_state(i - 1); + + #if DISABLED(SLIM_LCD_MENUS) + SERIAL_ECHOPGM(STR_FILAMENT); + if (i > 1) SERIAL_CHAR(' ', '0' + i); + SERIAL_ECHOPGM(": "); + if (rm == RM_NONE) + SERIAL_ECHOLNPGM(STR_OFF); + else if (rm == RM_MOTION_SENSOR) { + SERIAL_ECHOPGM("MOTION : "); + print_es_state(extDigitalRead(pin) == outval); + } + else + SERIAL_ECHOLNPGM_P(extDigitalRead(pin) == outval ? PSTR("OUT") : PSTR("PRESENT")); + #else + print_es_state(extDigitalRead(pin) == outval, F(STR_FILAMENT)); + #endif } - #undef _CASE_RUNOUT - #elif HAS_FILAMENT_SENSOR - print_es_state(READ(FIL_RUNOUT1_PIN) != FIL_RUNOUT1_STATE, F(STR_FILAMENT)); + #endif TERN_(BLTOUCH, bltouch._reset_SW_mode()); @@ -649,6 +750,9 @@ void Endstops::update() { #define I_AXIS_HEAD I_AXIS #define J_AXIS_HEAD J_AXIS #define K_AXIS_HEAD K_AXIS + #define U_AXIS_HEAD U_AXIS + #define V_AXIS_HEAD V_AXIS + #define W_AXIS_HEAD W_AXIS /** * Check and update endstops @@ -835,6 +939,82 @@ void Endstops::update() { #endif #endif + #if HAS_U_MIN && !U_SPI_SENSORLESS + #if ENABLED(U_DUAL_ENDSTOPS) + UPDATE_ENDSTOP_BIT(U, MIN); + #if HAS_U2_MIN + UPDATE_ENDSTOP_BIT(U2, MIN); + #else + COPY_LIVE_STATE(U_MIN, U2_MIN); + #endif + #else + UPDATE_ENDSTOP_BIT(U, MIN); + #endif + #endif + + #if HAS_U_MAX && !U_SPI_SENSORLESS + #if ENABLED(U_DUAL_ENDSTOPS) + UPDATE_ENDSTOP_BIT(U, MAX); + #if HAS_U2_MAX + UPDATE_ENDSTOP_BIT(U2, MAX); + #else + COPY_LIVE_STATE(U_MAX, U2_MAX); + #endif + #else + UPDATE_ENDSTOP_BIT(U, MAX); + #endif + #endif + + #if HAS_V_MIN && !V_SPI_SENSORLESS + #if ENABLED(V_DUAL_ENDSTOPS) + UPDATE_ENDSTOP_BIT(V, MIN); + #if HAS_V2_MIN + UPDATE_ENDSTOP_BIT(V2, MIN); + #else + COPY_LIVE_STATE(V_MIN, V2_MIN); + #endif + #else + UPDATE_ENDSTOP_BIT(V, MIN); + #endif + #endif + #if HAS_V_MAX && !V_SPI_SENSORLESS + #if ENABLED(O_DUAL_ENDSTOPS) + UPDATE_ENDSTOP_BIT(V, MAX); + #if HAS_V2_MAX + UPDATE_ENDSTOP_BIT(V2, MAX); + #else + COPY_LIVE_STATE(V_MAX, V2_MAX); + #endif + #else + UPDATE_ENDSTOP_BIT(V, MAX); + #endif + #endif + + #if HAS_W_MIN && !W_SPI_SENSORLESS + #if ENABLED(W_DUAL_ENDSTOPS) + UPDATE_ENDSTOP_BIT(W, MIN); + #if HAS_W2_MIN + UPDATE_ENDSTOP_BIT(W2, MIN); + #else + COPY_LIVE_STATE(W_MIN, W2_MIN); + #endif + #else + UPDATE_ENDSTOP_BIT(W, MIN); + #endif + #endif + #if HAS_W_MAX && !W_SPI_SENSORLESS + #if ENABLED(W_DUAL_ENDSTOPS) + UPDATE_ENDSTOP_BIT(W, MAX); + #if HAS_W2_MAX + UPDATE_ENDSTOP_BIT(W2, MAX); + #else + COPY_LIVE_STATE(W_MAX, W2_MAX); + #endif + #else + UPDATE_ENDSTOP_BIT(W, MAX); + #endif + #endif + #if ENDSTOP_NOISE_THRESHOLD /** @@ -935,7 +1115,7 @@ void Endstops::update() { #define PROCESS_ENDSTOP_Z(MINMAX) PROCESS_DUAL_ENDSTOP(Z, MINMAX) #endif - #if HAS_G38_PROBE + #if HAS_G38_PROBE // TODO (DerAndere): Add support for HAS_I_AXIS #define _G38_OPEN_STATE TERN(G38_PROBE_AWAY, (G38_move >= 4), LOW) // For G38 moves check the probe's pin for ALL movement if (G38_move && TEST_ENDSTOP(_ENDSTOP(Z, TERN(USES_Z_MIN_PROBE_PIN, MIN_PROBE, MIN))) != _G38_OPEN_STATE) { @@ -1105,6 +1285,51 @@ void Endstops::update() { } } #endif + + #if HAS_U_AXIS + if (stepper.axis_is_moving(U_AXIS)) { + if (stepper.motor_direction(U_AXIS_HEAD)) { // -direction + #if HAS_U_MIN || (U_SPI_SENSORLESS && U_HOME_TO_MIN) + PROCESS_ENDSTOP(U, MIN); + #endif + } + else { // +direction + #if HAS_U_MAX || (U_SPI_SENSORLESS && U_HOME_TO_MAX) + PROCESS_ENDSTOP(U, MAX); + #endif + } + } + #endif + + #if HAS_V_AXIS + if (stepper.axis_is_moving(V_AXIS)) { + if (stepper.motor_direction(V_AXIS_HEAD)) { // -direction + #if HAS_V_MIN || (V_SPI_SENSORLESS && V_HOME_TO_MIN) + PROCESS_ENDSTOP(V, MIN); + #endif + } + else { // +direction + #if HAS_V_MAX || (V_SPI_SENSORLESS && V_HOME_TO_MAX) + PROCESS_ENDSTOP(V, MAX); + #endif + } + } + #endif + + #if HAS_W_AXIS + if (stepper.axis_is_moving(W_AXIS)) { + if (stepper.motor_direction(W_AXIS_HEAD)) { // -direction + #if HAS_W_MIN || (W_SPI_SENSORLESS && W_HOME_TO_MIN) + PROCESS_ENDSTOP(W, MIN); + #endif + } + else { // +direction + #if HAS_W_MAX || (W_SPI_SENSORLESS && W_HOME_TO_MAX) + PROCESS_ENDSTOP(W, MAX); + #endif + } + } + #endif } // Endstops::update() #if ENABLED(SPI_ENDSTOPS) @@ -1166,6 +1391,24 @@ void Endstops::update() { hit = true; } #endif + #if U_SPI_SENSORLESS + if (tmc_spi_homing.u && stepperU.test_stall_status()) { + SBI(live_state, U_ENDSTOP); + hit = true; + } + #endif + #if V_SPI_SENSORLESS + if (tmc_spi_homing.v && stepperV.test_stall_status()) { + SBI(live_state, V_ENDSTOP); + hit = true; + } + #endif + #if W_SPI_SENSORLESS + if (tmc_spi_homing.w && stepperW.test_stall_status()) { + SBI(live_state, W_ENDSTOP); + hit = true; + } + #endif if (TERN0(ENDSTOP_INTERRUPTS_FEATURE, hit)) update(); @@ -1179,6 +1422,9 @@ void Endstops::update() { TERN_(I_SPI_SENSORLESS, CBI(live_state, I_ENDSTOP)); TERN_(J_SPI_SENSORLESS, CBI(live_state, J_ENDSTOP)); TERN_(K_SPI_SENSORLESS, CBI(live_state, K_ENDSTOP)); + TERN_(U_SPI_SENSORLESS, CBI(live_state, U_ENDSTOP)); + TERN_(V_SPI_SENSORLESS, CBI(live_state, V_ENDSTOP)); + TERN_(W_SPI_SENSORLESS, CBI(live_state, W_ENDSTOP)); } #endif // SPI_ENDSTOPS @@ -1273,6 +1519,24 @@ void Endstops::update() { #if HAS_K_MIN ES_GET_STATE(K_MIN); #endif + #if HAS_U_MAX + ES_GET_STATE(U_MAX); + #endif + #if HAS_U_MIN + ES_GET_STATE(U_MIN); + #endif + #if HAS_V_MAX + ES_GET_STATE(V_MAX); + #endif + #if HAS_V_MIN + ES_GET_STATE(V_MIN); + #endif + #if HAS_W_MAX + ES_GET_STATE(W_MAX); + #endif + #if HAS_W_MIN + ES_GET_STATE(W_MIN); + #endif uint16_t endstop_change = live_state_local ^ old_live_state_local; #define ES_REPORT_CHANGE(S) if (TEST(endstop_change, S)) SERIAL_ECHOPGM(" " STRINGIFY(S) ":", TEST(live_state_local, S)) @@ -1347,6 +1611,25 @@ void Endstops::update() { #if HAS_K_MAX ES_REPORT_CHANGE(K_MAX); #endif + #if HAS_U_MIN + ES_REPORT_CHANGE(U_MIN); + #endif + #if HAS_U_MAX + ES_REPORT_CHANGE(U_MAX); + #endif + #if HAS_V_MIN + ES_REPORT_CHANGE(V_MIN); + #endif + #if HAS_V_MAX + ES_REPORT_CHANGE(V_MAX); + #endif + #if HAS_W_MIN + ES_REPORT_CHANGE(W_MIN); + #endif + #if HAS_W_MAX + ES_REPORT_CHANGE(W_MAX); + #endif + SERIAL_ECHOLNPGM("\n"); hal.set_pwm_duty(pin_t(LED_PIN), local_LED_status); local_LED_status ^= 255; diff --git a/Marlin/src/module/endstops.h b/Marlin/src/module/endstops.h index 82a44cf95b..1848e6cdcf 100644 --- a/Marlin/src/module/endstops.h +++ b/Marlin/src/module/endstops.h @@ -45,6 +45,12 @@ enum EndstopEnum : char { _ES_ITEM(HAS_J_MAX, J_MAX) _ES_ITEM(HAS_K_MIN, K_MIN) _ES_ITEM(HAS_K_MAX, K_MAX) + _ES_ITEM(HAS_U_MIN, U_MIN) + _ES_ITEM(HAS_U_MAX, U_MAX) + _ES_ITEM(HAS_V_MIN, V_MIN) + _ES_ITEM(HAS_V_MAX, V_MAX) + _ES_ITEM(HAS_W_MIN, W_MIN) + _ES_ITEM(HAS_W_MAX, W_MAX) // Extra Endstops for XYZ #if ENABLED(X_DUAL_ENDSTOPS) @@ -234,7 +240,7 @@ class Endstops { typedef struct { union { bool any; - struct { bool LINEAR_AXIS_LIST(x:1, y:1, z:1, i:1, j:1, k:1); }; + struct { bool NUM_AXIS_LIST(x:1, y:1, z:1, i:1, j:1, k:1); }; }; } tmc_spi_homing_t; static tmc_spi_homing_t tmc_spi_homing; diff --git a/Marlin/src/module/motion.cpp b/Marlin/src/module/motion.cpp index 4b0c6aba7d..3037c38bb0 100644 --- a/Marlin/src/module/motion.cpp +++ b/Marlin/src/module/motion.cpp @@ -29,9 +29,8 @@ #include "stepper.h" #include "planner.h" #include "temperature.h" - #include "../gcode/gcode.h" - +#include "../lcd/marlinui.h" #include "../inc/MarlinConfig.h" #if IS_SCARA @@ -51,10 +50,6 @@ #include "../feature/bltouch.h" #endif -#if HAS_STATUS_MESSAGE - #include "../lcd/marlinui.h" -#endif - #if HAS_FILAMENT_SENSOR #include "../feature/runout.h" #endif @@ -89,7 +84,7 @@ bool relative_mode; // = false; #define Z_INIT_POS Z_HOME_POS #endif -xyze_pos_t current_position = LOGICAL_AXIS_ARRAY(0, X_HOME_POS, Y_HOME_POS, Z_INIT_POS, I_HOME_POS, J_HOME_POS, K_HOME_POS); +xyze_pos_t current_position = LOGICAL_AXIS_ARRAY(0, X_HOME_POS, Y_HOME_POS, Z_INIT_POS, I_HOME_POS, J_HOME_POS, K_HOME_POS, U_HOME_POS, V_HOME_POS, W_HOME_POS); /** * Cartesian Destination @@ -125,9 +120,7 @@ xyze_pos_t destination; // {0} ); // Transpose from [XYZ][HOTENDS] to [HOTENDS][XYZ] HOTEND_LOOP() LOOP_ABC(a) hotend_offset[e][a] = tmp[a][e]; - #if ENABLED(DUAL_X_CARRIAGE) - hotend_offset[1].x = _MAX(X2_HOME_POS, X2_MAX_POS); - #endif + TERN_(DUAL_X_CARRIAGE, hotend_offset[1].x = _MAX(X2_HOME_POS, X2_MAX_POS)); } #endif @@ -196,13 +189,16 @@ inline void report_more_positions() { inline void report_logical_position(const xyze_pos_t &rpos) { const xyze_pos_t lpos = rpos.asLogical(); SERIAL_ECHOPGM_P( - LIST_N(DOUBLE(LINEAR_AXES), + LIST_N(DOUBLE(NUM_AXES), X_LBL, lpos.x, SP_Y_LBL, lpos.y, SP_Z_LBL, lpos.z, SP_I_LBL, lpos.i, SP_J_LBL, lpos.j, - SP_K_LBL, lpos.k + SP_K_LBL, lpos.k, + SP_U_LBL, lpos.u, + SP_V_LBL, lpos.v, + SP_W_LBL, lpos.w ) #if HAS_EXTRUDERS , SP_E_LBL, lpos.e @@ -217,7 +213,8 @@ void report_real_position() { xyze_pos_t npos = LOGICAL_AXIS_ARRAY( planner.get_axis_position_mm(E_AXIS), cartes.x, cartes.y, cartes.z, - cartes.i, cartes.j, cartes.k + cartes.i, cartes.j, cartes.k, + cartes.u, cartes.v, cartes.w ); TERN_(HAS_POSITION_MODIFIERS, planner.unapply_modifiers(npos, true)); @@ -265,13 +262,16 @@ void report_current_position_projected() { const xyz_pos_t lpos = cartes.asLogical(); SERIAL_ECHOPGM_P( - LIST_N(DOUBLE(LINEAR_AXES), + LIST_N(DOUBLE(NUM_AXES), X_LBL, lpos.x, SP_Y_LBL, lpos.y, SP_Z_LBL, lpos.z, SP_I_LBL, lpos.i, SP_J_LBL, lpos.j, - SP_K_LBL, lpos.k + SP_K_LBL, lpos.k, + SP_U_LBL, lpos.u, + SP_V_LBL, lpos.v, + SP_W_LBL, lpos.w ) #if HAS_EXTRUDERS , SP_E_LBL, current_position.e @@ -362,13 +362,16 @@ void get_cartesian_from_steppers() { ); cartes.z = planner.get_axis_position_mm(Z_AXIS); #else - LINEAR_AXIS_CODE( + NUM_AXIS_CODE( cartes.x = planner.get_axis_position_mm(X_AXIS), cartes.y = planner.get_axis_position_mm(Y_AXIS), cartes.z = planner.get_axis_position_mm(Z_AXIS), cartes.i = planner.get_axis_position_mm(I_AXIS), cartes.j = planner.get_axis_position_mm(J_AXIS), - cartes.k = planner.get_axis_position_mm(K_AXIS) + cartes.k = planner.get_axis_position_mm(K_AXIS), + cartes.u = planner.get_axis_position_mm(U_AXIS), + cartes.v = planner.get_axis_position_mm(V_AXIS), + cartes.w = planner.get_axis_position_mm(W_AXIS) ); #endif } @@ -475,24 +478,23 @@ void _internal_move_to_destination(const_feedRate_t fr_mm_s/*=0.0f*/ * - Delta may lower Z first to get into the free motion zone. * - Before returning, wait for the planner buffer to empty. */ -void do_blocking_move_to(LINEAR_AXIS_ARGS(const float), const_feedRate_t fr_mm_s/*=0.0f*/) { +void do_blocking_move_to(NUM_AXIS_ARGS(const float), const_feedRate_t fr_mm_s/*=0.0f*/) { DEBUG_SECTION(log_move, "do_blocking_move_to", DEBUGGING(LEVELING)); - if (DEBUGGING(LEVELING)) DEBUG_XYZ("> ", LINEAR_AXIS_ARGS()); + if (DEBUGGING(LEVELING)) DEBUG_XYZ("> ", NUM_AXIS_ARGS()); const feedRate_t xy_feedrate = fr_mm_s ?: feedRate_t(XY_PROBE_FEEDRATE_MM_S); #if HAS_Z_AXIS const feedRate_t z_feedrate = fr_mm_s ?: homing_feedrate(Z_AXIS); #endif - #if HAS_I_AXIS - const feedRate_t i_feedrate = fr_mm_s ?: homing_feedrate(I_AXIS); - #endif - #if HAS_J_AXIS - const feedRate_t j_feedrate = fr_mm_s ?: homing_feedrate(J_AXIS); - #endif - #if HAS_K_AXIS - const feedRate_t k_feedrate = fr_mm_s ?: homing_feedrate(K_AXIS); - #endif + SECONDARY_AXIS_CODE( + const feedRate_t i_feedrate = fr_mm_s ?: homing_feedrate(I_AXIS), + const feedRate_t j_feedrate = fr_mm_s ?: homing_feedrate(J_AXIS), + const feedRate_t k_feedrate = fr_mm_s ?: homing_feedrate(K_AXIS), + const feedRate_t u_feedrate = fr_mm_s ?: homing_feedrate(U_AXIS), + const feedRate_t v_feedrate = fr_mm_s ?: homing_feedrate(V_AXIS), + const feedRate_t w_feedrate = fr_mm_s ?: homing_feedrate(W_AXIS) + ); #if IS_KINEMATIC if (!position_is_reachable(x, y)) return; @@ -561,7 +563,18 @@ void do_blocking_move_to(LINEAR_AXIS_ARGS(const float), const_feedRate_t fr_mm_s #if HAS_K_AXIS current_position.k = k; line_to_current_position(k_feedrate); #endif - #if HAS_Z_AXIS // If Z needs to lower, do it after moving XY... + #if HAS_U_AXIS + current_position.u = u; line_to_current_position(u_feedrate); + #endif + #if HAS_V_AXIS + current_position.v = v; line_to_current_position(v_feedrate); + #endif + #if HAS_W_AXIS + current_position.w = w; line_to_current_position(w_feedrate); + #endif + + #if HAS_Z_AXIS + // If Z needs to lower, do it after moving XY if (current_position.z > z) { current_position.z = z; line_to_current_position(z_feedrate); } #endif @@ -571,17 +584,19 @@ void do_blocking_move_to(LINEAR_AXIS_ARGS(const float), const_feedRate_t fr_mm_s } void do_blocking_move_to(const xy_pos_t &raw, const_feedRate_t fr_mm_s/*=0.0f*/) { - do_blocking_move_to(LINEAR_AXIS_LIST(raw.x, raw.y, current_position.z, current_position.i, current_position.j, current_position.k), fr_mm_s); + do_blocking_move_to(NUM_AXIS_LIST(raw.x, raw.y, current_position.z, current_position.i, current_position.j, current_position.k, + current_position.u, current_position.v, current_position.w), fr_mm_s); } void do_blocking_move_to(const xyz_pos_t &raw, const_feedRate_t fr_mm_s/*=0.0f*/) { - do_blocking_move_to(LINEAR_AXIS_ELEM(raw), fr_mm_s); + do_blocking_move_to(NUM_AXIS_ELEM(raw), fr_mm_s); } void do_blocking_move_to(const xyze_pos_t &raw, const_feedRate_t fr_mm_s/*=0.0f*/) { - do_blocking_move_to(LINEAR_AXIS_ELEM(raw), fr_mm_s); + do_blocking_move_to(NUM_AXIS_ELEM(raw), fr_mm_s); } void do_blocking_move_to_x(const_float_t rx, const_feedRate_t fr_mm_s/*=0.0*/) { do_blocking_move_to( - LINEAR_AXIS_LIST(rx, current_position.y, current_position.z, current_position.i, current_position.j, current_position.k), + NUM_AXIS_LIST(rx, current_position.y, current_position.z, current_position.i, current_position.j, current_position.k, + current_position.u, current_position.v, current_position.w), fr_mm_s ); } @@ -589,7 +604,8 @@ void do_blocking_move_to_x(const_float_t rx, const_feedRate_t fr_mm_s/*=0.0*/) { #if HAS_Y_AXIS void do_blocking_move_to_y(const_float_t ry, const_feedRate_t fr_mm_s/*=0.0*/) { do_blocking_move_to( - LINEAR_AXIS_LIST(current_position.x, ry, current_position.z, current_position.i, current_position.j, current_position.k), + NUM_AXIS_LIST(current_position.x, ry, current_position.z, current_position.i, current_position.j, current_position.k, + current_position.u, current_position.v, current_position.w), fr_mm_s ); } @@ -607,7 +623,7 @@ void do_blocking_move_to_x(const_float_t rx, const_feedRate_t fr_mm_s/*=0.0*/) { } void do_blocking_move_to_xyz_i(const xyze_pos_t &raw, const_float_t i, const_feedRate_t fr_mm_s/*=0.0f*/) { do_blocking_move_to( - LINEAR_AXIS_LIST(raw.x, raw.y, raw.z, i, raw.j, raw.k), + NUM_AXIS_LIST(raw.x, raw.y, raw.z, i, raw.j, raw.k, raw.u, raw.v, raw.w), fr_mm_s ); } @@ -619,7 +635,7 @@ void do_blocking_move_to_x(const_float_t rx, const_feedRate_t fr_mm_s/*=0.0*/) { } void do_blocking_move_to_xyzi_j(const xyze_pos_t &raw, const_float_t j, const_feedRate_t fr_mm_s/*=0.0f*/) { do_blocking_move_to( - LINEAR_AXIS_LIST(raw.x, raw.y, raw.z, raw.i, j, raw.k), + NUM_AXIS_LIST(raw.x, raw.y, raw.z, raw.i, j, raw.k, raw.u, raw.v, raw.w), fr_mm_s ); } @@ -631,7 +647,43 @@ void do_blocking_move_to_x(const_float_t rx, const_feedRate_t fr_mm_s/*=0.0*/) { } void do_blocking_move_to_xyzij_k(const xyze_pos_t &raw, const_float_t k, const_feedRate_t fr_mm_s/*=0.0f*/) { do_blocking_move_to( - LINEAR_AXIS_LIST(raw.x, raw.y, raw.z, raw.i, raw.j, k), + NUM_AXIS_LIST(raw.x, raw.y, raw.z, raw.i, raw.j, k, raw.u, raw.v, raw.w), + fr_mm_s + ); + } +#endif + +#if HAS_U_AXIS + void do_blocking_move_to_u(const_float_t ru, const_feedRate_t fr_mm_s/*=0.0*/) { + do_blocking_move_to_xyzijk_u(current_position, ru, fr_mm_s); + } + void do_blocking_move_to_xyzijk_u(const xyze_pos_t &raw, const_float_t u, const_feedRate_t fr_mm_s/*=0.0f*/) { + do_blocking_move_to( + NUM_AXIS_LIST(raw.x, raw.y, raw.z, raw.i, raw.j, raw.k, u, raw.v, raw.w), + fr_mm_s + ); + } +#endif + +#if HAS_V_AXIS + void do_blocking_move_to_v(const_float_t rv, const_feedRate_t fr_mm_s/*=0.0*/) { + do_blocking_move_to_xyzijku_v(current_position, rv, fr_mm_s); + } + void do_blocking_move_to_xyzijku_v(const xyze_pos_t &raw, const_float_t v, const_feedRate_t fr_mm_s/*=0.0f*/) { + do_blocking_move_to( + NUM_AXIS_LIST(raw.x, raw.y, raw.z, raw.i, raw.j, raw.k, raw.u, v, raw.w), + fr_mm_s + ); + } +#endif + +#if HAS_W_AXIS + void do_blocking_move_to_w(const_float_t rw, const_feedRate_t fr_mm_s/*=0.0*/) { + do_blocking_move_to_xyzijkuv_w(current_position, rw, fr_mm_s); + } + void do_blocking_move_to_xyzijkuv_w(const xyze_pos_t &raw, const_float_t w, const_feedRate_t fr_mm_s/*=0.0f*/) { + do_blocking_move_to( + NUM_AXIS_LIST(raw.x, raw.y, raw.z, raw.i, raw.j, raw.k, raw.u, raw.v, w), fr_mm_s ); } @@ -640,7 +692,8 @@ void do_blocking_move_to_x(const_float_t rx, const_feedRate_t fr_mm_s/*=0.0*/) { #if HAS_Y_AXIS void do_blocking_move_to_xy(const_float_t rx, const_float_t ry, const_feedRate_t fr_mm_s/*=0.0*/) { do_blocking_move_to( - LINEAR_AXIS_LIST(rx, ry, current_position.z, current_position.i, current_position.j, current_position.k), + NUM_AXIS_LIST(rx, ry, current_position.z, current_position.i, current_position.j, current_position.k, + current_position.u, current_position.v, current_position.w), fr_mm_s ); } @@ -652,7 +705,8 @@ void do_blocking_move_to_x(const_float_t rx, const_feedRate_t fr_mm_s/*=0.0*/) { #if HAS_Z_AXIS void do_blocking_move_to_xy_z(const xy_pos_t &raw, const_float_t z, const_feedRate_t fr_mm_s/*=0.0f*/) { do_blocking_move_to( - LINEAR_AXIS_LIST(raw.x, raw.y, z, current_position.i, current_position.j, current_position.k), + NUM_AXIS_LIST(raw.x, raw.y, z, current_position.i, current_position.j, current_position.k, + current_position.u, current_position.v, current_position.w), fr_mm_s ); } @@ -687,8 +741,8 @@ void restore_feedrate_and_scaling() { // Software Endstops are based on the configured limits. soft_endstops_t soft_endstop = { true, false, - LINEAR_AXIS_ARRAY(X_MIN_POS, Y_MIN_POS, Z_MIN_POS, I_MIN_POS, J_MIN_POS, K_MIN_POS), - LINEAR_AXIS_ARRAY(X_MAX_BED, Y_MAX_BED, Z_MAX_POS, I_MAX_POS, J_MAX_POS, K_MAX_POS) + NUM_AXIS_ARRAY(X_MIN_POS, Y_MIN_POS, Z_MIN_POS, I_MIN_POS, J_MIN_POS, K_MIN_POS, U_MIN_POS, V_MIN_POS, W_MIN_POS), + NUM_AXIS_ARRAY(X_MAX_BED, Y_MAX_BED, Z_MAX_POS, I_MAX_POS, J_MAX_POS, K_MAX_POS, U_MAX_POS, V_MAX_POS, W_MAX_POS) }; /** @@ -867,6 +921,36 @@ void restore_feedrate_and_scaling() { #endif } #endif + #if HAS_U_AXIS + if (axis_was_homed(U_AXIS)) { + #if !HAS_SOFTWARE_ENDSTOPS || ENABLED(MIN_SOFTWARE_ENDSTOP_U) + NOLESS(target.u, soft_endstop.min.u); + #endif + #if !HAS_SOFTWARE_ENDSTOPS || ENABLED(MAX_SOFTWARE_ENDSTOP_U) + NOMORE(target.u, soft_endstop.max.u); + #endif + } + #endif + #if HAS_V_AXIS + if (axis_was_homed(V_AXIS)) { + #if !HAS_SOFTWARE_ENDSTOPS || ENABLED(MIN_SOFTWARE_ENDSTOP_V) + NOLESS(target.v, soft_endstop.min.v); + #endif + #if !HAS_SOFTWARE_ENDSTOPS || ENABLED(MAX_SOFTWARE_ENDSTOP_V) + NOMORE(target.v, soft_endstop.max.v); + #endif + } + #endif + #if HAS_W_AXIS + if (axis_was_homed(W_AXIS)) { + #if !HAS_SOFTWARE_ENDSTOPS || ENABLED(MIN_SOFTWARE_ENDSTOP_W) + NOLESS(target.w, soft_endstop.min.w); + #endif + #if !HAS_SOFTWARE_ENDSTOPS || ENABLED(MAX_SOFTWARE_ENDSTOP_W) + NOMORE(target.w, soft_endstop.max.w); + #endif + } + #endif } #else // !HAS_SOFTWARE_ENDSTOPS @@ -1116,16 +1200,15 @@ FORCE_INLINE void segment_idle(millis_t &next_idle_ms) { bool idex_mirrored_mode = false; // Used in mode 3 float x_home_pos(const uint8_t extruder) { - if (extruder == 0) - return X_HOME_POS; - else - /** - * In dual carriage mode the extruder offset provides an override of the - * second X-carriage position when homed - otherwise X2_HOME_POS is used. - * This allows soft recalibration of the second extruder home position - * without firmware reflash (through the M218 command). - */ - return hotend_offset[1].x > 0 ? hotend_offset[1].x : X2_HOME_POS; + if (extruder == 0) return X_HOME_POS; + + /** + * In dual carriage mode the extruder offset provides an override of the + * second X-carriage position when homed - otherwise X2_HOME_POS is used. + * This allows soft recalibration of the second extruder home position + * (with M218 T1 Xn) without firmware reflash. + */ + return hotend_offset[1].x > 0 ? hotend_offset[1].x : X2_HOME_POS; } void idex_set_mirrored_mode(const bool mirr) { @@ -1305,9 +1388,10 @@ void prepare_line_to_destination() { CBI(b, a); }; // Clear test bits that are trusted - LINEAR_AXIS_CODE( + NUM_AXIS_CODE( set_should(axis_bits, X_AXIS), set_should(axis_bits, Y_AXIS), set_should(axis_bits, Z_AXIS), - set_should(axis_bits, I_AXIS), set_should(axis_bits, J_AXIS), set_should(axis_bits, K_AXIS) + set_should(axis_bits, I_AXIS), set_should(axis_bits, J_AXIS), set_should(axis_bits, K_AXIS), + set_should(axis_bits, U_AXIS), set_should(axis_bits, V_AXIS), set_should(axis_bits, W_AXIS) ); return axis_bits; } @@ -1317,18 +1401,21 @@ void prepare_line_to_destination() { PGM_P home_first = GET_TEXT(MSG_HOME_FIRST); char msg[strlen_P(home_first)+1]; sprintf_P(msg, home_first, - LINEAR_AXIS_LIST( - TEST(axis_bits, X_AXIS) ? "X" : "", - TEST(axis_bits, Y_AXIS) ? "Y" : "", - TEST(axis_bits, Z_AXIS) ? "Z" : "", + NUM_AXIS_LIST( + TEST(axis_bits, X_AXIS) ? STR_A : "", + TEST(axis_bits, Y_AXIS) ? STR_B : "", + TEST(axis_bits, Z_AXIS) ? STR_C : "", TEST(axis_bits, I_AXIS) ? STR_I : "", TEST(axis_bits, J_AXIS) ? STR_J : "", - TEST(axis_bits, K_AXIS) ? STR_K : "" + TEST(axis_bits, K_AXIS) ? STR_K : "", + TEST(axis_bits, U_AXIS) ? STR_U : "", + TEST(axis_bits, V_AXIS) ? STR_V : "", + TEST(axis_bits, W_AXIS) ? STR_W : "" ) ); SERIAL_ECHO_START(); SERIAL_ECHOLN(msg); - TERN_(HAS_STATUS_MESSAGE, ui.set_status(msg)); + ui.set_status(msg); return true; } return false; @@ -1362,9 +1449,7 @@ void prepare_line_to_destination() { #if X_SENSORLESS case X_AXIS: stealth_states.x = tmc_enable_stallguard(stepperX); - #if AXIS_HAS_STALLGUARD(X2) - stealth_states.x2 = tmc_enable_stallguard(stepperX2); - #endif + TERN_(X2_SENSORLESS, stealth_states.x2 = tmc_enable_stallguard(stepperX2)); #if ANY(CORE_IS_XY, MARKFORGED_XY, MARKFORGED_YX) && Y_SENSORLESS stealth_states.y = tmc_enable_stallguard(stepperY); #elif CORE_IS_XZ && Z_SENSORLESS @@ -1375,9 +1460,7 @@ void prepare_line_to_destination() { #if Y_SENSORLESS case Y_AXIS: stealth_states.y = tmc_enable_stallguard(stepperY); - #if AXIS_HAS_STALLGUARD(Y2) - stealth_states.y2 = tmc_enable_stallguard(stepperY2); - #endif + TERN_(Y2_SENSORLESS, stealth_states.y2 = tmc_enable_stallguard(stepperY2)); #if ANY(CORE_IS_XY, MARKFORGED_XY, MARKFORGED_YX) && X_SENSORLESS stealth_states.x = tmc_enable_stallguard(stepperX); #elif CORE_IS_YZ && Z_SENSORLESS @@ -1388,15 +1471,9 @@ void prepare_line_to_destination() { #if Z_SENSORLESS case Z_AXIS: stealth_states.z = tmc_enable_stallguard(stepperZ); - #if AXIS_HAS_STALLGUARD(Z2) - stealth_states.z2 = tmc_enable_stallguard(stepperZ2); - #endif - #if AXIS_HAS_STALLGUARD(Z3) - stealth_states.z3 = tmc_enable_stallguard(stepperZ3); - #endif - #if AXIS_HAS_STALLGUARD(Z4) - stealth_states.z4 = tmc_enable_stallguard(stepperZ4); - #endif + TERN_(Z2_SENSORLESS, stealth_states.z2 = tmc_enable_stallguard(stepperZ2)); + TERN_(Z3_SENSORLESS, stealth_states.z3 = tmc_enable_stallguard(stepperZ3)); + TERN_(Z4_SENSORLESS, stealth_states.z4 = tmc_enable_stallguard(stepperZ4)); #if CORE_IS_XZ && X_SENSORLESS stealth_states.x = tmc_enable_stallguard(stepperX); #elif CORE_IS_YZ && Y_SENSORLESS @@ -1413,6 +1490,15 @@ void prepare_line_to_destination() { #if K_SENSORLESS case K_AXIS: stealth_states.k = tmc_enable_stallguard(stepperK); break; #endif + #if U_SENSORLESS + case U_AXIS: stealth_states.u = tmc_enable_stallguard(stepperU); break; + #endif + #if V_SENSORLESS + case V_AXIS: stealth_states.v = tmc_enable_stallguard(stepperV); break; + #endif + #if W_SENSORLESS + case W_AXIS: stealth_states.w = tmc_enable_stallguard(stepperW); break; + #endif } #if ENABLED(SPI_ENDSTOPS) @@ -1433,6 +1519,15 @@ void prepare_line_to_destination() { #if HAS_K_AXIS case K_AXIS: if (ENABLED(K_SPI_SENSORLESS)) endstops.tmc_spi_homing.k = true; break; #endif + #if HAS_U_AXIS + case U_AXIS: if (ENABLED(U_SPI_SENSORLESS)) endstops.tmc_spi_homing.u = true; break; + #endif + #if HAS_V_AXIS + case V_AXIS: if (ENABLED(V_SPI_SENSORLESS)) endstops.tmc_spi_homing.v = true; break; + #endif + #if HAS_W_AXIS + case W_AXIS: if (ENABLED(W_SPI_SENSORLESS)) endstops.tmc_spi_homing.w = true; break; + #endif default: break; } #endif @@ -1448,9 +1543,7 @@ void prepare_line_to_destination() { #if X_SENSORLESS case X_AXIS: tmc_disable_stallguard(stepperX, enable_stealth.x); - #if AXIS_HAS_STALLGUARD(X2) - tmc_disable_stallguard(stepperX2, enable_stealth.x2); - #endif + TERN_(X2_SENSORLESS, tmc_disable_stallguard(stepperX2, enable_stealth.x2)); #if ANY(CORE_IS_XY, MARKFORGED_XY, MARKFORGED_YX) && Y_SENSORLESS tmc_disable_stallguard(stepperY, enable_stealth.y); #elif CORE_IS_XZ && Z_SENSORLESS @@ -1461,9 +1554,7 @@ void prepare_line_to_destination() { #if Y_SENSORLESS case Y_AXIS: tmc_disable_stallguard(stepperY, enable_stealth.y); - #if AXIS_HAS_STALLGUARD(Y2) - tmc_disable_stallguard(stepperY2, enable_stealth.y2); - #endif + TERN_(Y2_SENSORLESS, tmc_disable_stallguard(stepperY2, enable_stealth.y2)); #if ANY(CORE_IS_XY, MARKFORGED_XY, MARKFORGED_YX) && X_SENSORLESS tmc_disable_stallguard(stepperX, enable_stealth.x); #elif CORE_IS_YZ && Z_SENSORLESS @@ -1474,15 +1565,9 @@ void prepare_line_to_destination() { #if Z_SENSORLESS case Z_AXIS: tmc_disable_stallguard(stepperZ, enable_stealth.z); - #if AXIS_HAS_STALLGUARD(Z2) - tmc_disable_stallguard(stepperZ2, enable_stealth.z2); - #endif - #if AXIS_HAS_STALLGUARD(Z3) - tmc_disable_stallguard(stepperZ3, enable_stealth.z3); - #endif - #if AXIS_HAS_STALLGUARD(Z4) - tmc_disable_stallguard(stepperZ4, enable_stealth.z4); - #endif + TERN_(Z2_SENSORLESS, tmc_disable_stallguard(stepperZ2, enable_stealth.z2)); + TERN_(Z3_SENSORLESS, tmc_disable_stallguard(stepperZ3, enable_stealth.z3)); + TERN_(Z4_SENSORLESS, tmc_disable_stallguard(stepperZ4, enable_stealth.z4)); #if CORE_IS_XZ && X_SENSORLESS tmc_disable_stallguard(stepperX, enable_stealth.x); #elif CORE_IS_YZ && Y_SENSORLESS @@ -1499,6 +1584,15 @@ void prepare_line_to_destination() { #if K_SENSORLESS case K_AXIS: tmc_disable_stallguard(stepperK, enable_stealth.k); break; #endif + #if U_SENSORLESS + case U_AXIS: tmc_disable_stallguard(stepperU, enable_stealth.u); break; + #endif + #if V_SENSORLESS + case V_AXIS: tmc_disable_stallguard(stepperV, enable_stealth.v); break; + #endif + #if W_SENSORLESS + case W_AXIS: tmc_disable_stallguard(stepperW, enable_stealth.w); break; + #endif } #if ENABLED(SPI_ENDSTOPS) @@ -1519,6 +1613,15 @@ void prepare_line_to_destination() { #if HAS_K_AXIS case K_AXIS: if (ENABLED(K_SPI_SENSORLESS)) endstops.tmc_spi_homing.k = false; break; #endif + #if HAS_U_AXIS + case U_AXIS: if (ENABLED(U_SPI_SENSORLESS)) endstops.tmc_spi_homing.u = false; break; + #endif + #if HAS_V_AXIS + case V_AXIS: if (ENABLED(V_SPI_SENSORLESS)) endstops.tmc_spi_homing.v = false; break; + #endif + #if HAS_W_AXIS + case W_AXIS: if (ENABLED(W_SPI_SENSORLESS)) endstops.tmc_spi_homing.w = false; break; + #endif default: break; } #endif @@ -1695,6 +1798,30 @@ void prepare_line_to_destination() { stepperBackoutDir = INVERT_K_DIR ? effectorBackoutDir : -effectorBackoutDir; break; #endif + #ifdef U_MICROSTEPS + case U_AXIS: + phasePerUStep = PHASE_PER_MICROSTEP(U); + phaseCurrent = stepperU.get_microstep_counter(); + effectorBackoutDir = -U_HOME_DIR; + stepperBackoutDir = INVERT_U_DIR ? effectorBackoutDir : -effectorBackoutDir; + break; + #endif + #ifdef V_MICROSTEPS + case V_AXIS: + phasePerUStep = PHASE_PER_MICROSTEP(V); + phaseCurrent = stepperV.get_microstep_counter(); + effectorBackoutDir = -V_HOME_DIR; + stepperBackoutDir = INVERT_V_DIR ? effectorBackoutDir : -effectorBackoutDir; + break; + #endif + #ifdef W_MICROSTEPS + case W_AXIS: + phasePerUStep = PHASE_PER_MICROSTEP(W); + phaseCurrent = stepperW.get_microstep_counter(); + effectorBackoutDir = -W_HOME_DIR; + stepperBackoutDir = INVERT_W_DIR ? effectorBackoutDir : -effectorBackoutDir; + break; + #endif default: return; } @@ -1751,13 +1878,16 @@ void prepare_line_to_destination() { || TERN0(A##_HOME_TO_MIN, A##_MIN_PIN > -1) \ || TERN0(A##_HOME_TO_MAX, A##_MAX_PIN > -1) \ )) - if (LINEAR_AXIS_GANG( + if (NUM_AXIS_GANG( !_CAN_HOME(X), && !_CAN_HOME(Y), && !_CAN_HOME(Z), && !_CAN_HOME(I), && !_CAN_HOME(J), - && !_CAN_HOME(K)) + && !_CAN_HOME(K), + && !_CAN_HOME(U), + && !_CAN_HOME(V), + && !_CAN_HOME(W)) ) return; #endif @@ -1850,6 +1980,15 @@ void prepare_line_to_destination() { #if HAS_K_AXIS case K_AXIS: es = K_ENDSTOP; break; #endif + #if HAS_U_AXIS + case U_AXIS: es = U_ENDSTOP; break; + #endif + #if HAS_V_AXIS + case V_AXIS: es = V_ENDSTOP; break; + #endif + #if HAS_W_AXIS + case W_AXIS: es = W_ENDSTOP; break; + #endif } if (TEST(endstops.state(), es)) { SERIAL_ECHO_MSG("Bad ", AS_CHAR(AXIS_CHAR(axis)), " Endstop?"); diff --git a/Marlin/src/module/motion.h b/Marlin/src/module/motion.h index 2fbb4ce114..45dae5d609 100644 --- a/Marlin/src/module/motion.h +++ b/Marlin/src/module/motion.h @@ -44,7 +44,7 @@ extern xyze_pos_t current_position, // High-level current tool position // G60/G61 Position Save and Return #if SAVED_POSITIONS - extern uint8_t saved_slots[(SAVED_POSITIONS + 7) >> 3]; // TODO: Add support for LINEAR_AXES >= 4 + extern uint8_t saved_slots[(SAVED_POSITIONS + 7) >> 3]; // TODO: Add support for HAS_I_AXIS extern xyze_pos_t stored_position[SAVED_POSITIONS]; #endif @@ -77,13 +77,16 @@ constexpr xyz_feedrate_t homing_feedrate_mm_m = HOMING_FEEDRATE_MM_M; FORCE_INLINE feedRate_t homing_feedrate(const AxisEnum a) { float v = TERN0(HAS_Z_AXIS, homing_feedrate_mm_m.z); #if DISABLED(DELTA) - LINEAR_AXIS_CODE( + NUM_AXIS_CODE( if (a == X_AXIS) v = homing_feedrate_mm_m.x, else if (a == Y_AXIS) v = homing_feedrate_mm_m.y, else if (a == Z_AXIS) v = homing_feedrate_mm_m.z, else if (a == I_AXIS) v = homing_feedrate_mm_m.i, else if (a == J_AXIS) v = homing_feedrate_mm_m.j, - else if (a == K_AXIS) v = homing_feedrate_mm_m.k + else if (a == K_AXIS) v = homing_feedrate_mm_m.k, + else if (a == U_AXIS) v = homing_feedrate_mm_m.u, + else if (a == V_AXIS) v = homing_feedrate_mm_m.v, + else if (a == W_AXIS) v = homing_feedrate_mm_m.w ); #endif return MMM_TO_MMS(v); @@ -124,7 +127,7 @@ inline int8_t pgm_read_any(const int8_t *p) { return TERN(__IMXRT1062__, *p, pgm #define XYZ_DEFS(T, NAME, OPT) \ inline T NAME(const AxisEnum axis) { \ - static const XYZval NAME##_P DEFS_PROGMEM = LINEAR_AXIS_ARRAY(X_##OPT, Y_##OPT, Z_##OPT, I_##OPT, J_##OPT, K_##OPT); \ + static const XYZval NAME##_P DEFS_PROGMEM = NUM_AXIS_ARRAY(X_##OPT, Y_##OPT, Z_##OPT, I_##OPT, J_##OPT, K_##OPT, U_##OPT, V_##OPT, W_##OPT); \ return pgm_read_any(&NAME##_P[axis]); \ } XYZ_DEFS(float, base_min_pos, MIN_POS); @@ -198,6 +201,24 @@ inline float home_bump_mm(const AxisEnum axis) { TERN_(MIN_SOFTWARE_ENDSTOP_K, amax = max.k); break; #endif + #if HAS_U_AXIS + case U_AXIS: + TERN_(MIN_SOFTWARE_ENDSTOP_U, amin = min.u); + TERN_(MIN_SOFTWARE_ENDSTOP_U, amax = max.u); + break; + #endif + #if HAS_V_AXIS + case V_AXIS: + TERN_(MIN_SOFTWARE_ENDSTOP_V, amin = min.v); + TERN_(MIN_SOFTWARE_ENDSTOP_V, amax = max.v); + break; + #endif + #if HAS_W_AXIS + case W_AXIS: + TERN_(MIN_SOFTWARE_ENDSTOP_W, amin = min.w); + TERN_(MIN_SOFTWARE_ENDSTOP_W, amax = max.w); + break; + #endif default: break; } #endif @@ -323,7 +344,7 @@ inline void prepare_internal_move_to_destination(const_feedRate_t fr_mm_s=0.0f) /** * Blocking movement and shorthand functions */ -void do_blocking_move_to(LINEAR_AXIS_ARGS(const float), const_feedRate_t fr_mm_s=0.0f); +void do_blocking_move_to(NUM_AXIS_ARGS(const float), const_feedRate_t fr_mm_s=0.0f); void do_blocking_move_to(const xy_pos_t &raw, const_feedRate_t fr_mm_s=0.0f); void do_blocking_move_to(const xyz_pos_t &raw, const_feedRate_t fr_mm_s=0.0f); void do_blocking_move_to(const xyze_pos_t &raw, const_feedRate_t fr_mm_s=0.0f); @@ -347,6 +368,18 @@ void do_blocking_move_to_x(const_float_t rx, const_feedRate_t fr_mm_s=0.0f); void do_blocking_move_to_k(const_float_t rk, const_feedRate_t fr_mm_s=0.0f); void do_blocking_move_to_xyzij_k(const xyze_pos_t &raw, const_float_t k, const_feedRate_t fr_mm_s=0.0f); #endif +#if HAS_U_AXIS + void do_blocking_move_to_u(const_float_t ru, const_feedRate_t fr_mm_s=0.0f); + void do_blocking_move_to_xyzijk_u(const xyze_pos_t &raw, const_float_t u, const_feedRate_t fr_mm_s=0.0f); +#endif +#if HAS_V_AXIS + void do_blocking_move_to_v(const_float_t rv, const_feedRate_t fr_mm_s=0.0f); + void do_blocking_move_to_xyzijku_v(const xyze_pos_t &raw, const_float_t v, const_feedRate_t fr_mm_s=0.0f); +#endif +#if HAS_W_AXIS + void do_blocking_move_to_w(const float rw, const feedRate_t &fr_mm_s=0.0f); + void do_blocking_move_to_xyzijkuv_w(const xyze_pos_t &raw, const float w, const feedRate_t &fr_mm_s=0.0f); +#endif #if HAS_Y_AXIS void do_blocking_move_to_xy(const_float_t rx, const_float_t ry, const_feedRate_t fr_mm_s=0.0f); @@ -374,8 +407,8 @@ void restore_feedrate_and_scaling(); /** * Homing and Trusted Axes */ -typedef IF<(LINEAR_AXES > 8), uint16_t, uint8_t>::type linear_axis_bits_t; -constexpr linear_axis_bits_t linear_bits = _BV(LINEAR_AXES) - 1; +typedef IF<(NUM_AXES > 8), uint16_t, uint8_t>::type linear_axis_bits_t; +constexpr linear_axis_bits_t linear_bits = _BV(NUM_AXES) - 1; void set_axis_is_at_home(const AxisEnum axis); @@ -404,7 +437,7 @@ void set_axis_is_at_home(const AxisEnum axis); constexpr linear_axis_bits_t axis_homed = linear_bits, axis_trusted = linear_bits; // Zero-endstop machines are always homed and trusted inline void homeaxis(const AxisEnum axis) {} inline void set_axis_never_homed(const AxisEnum) {} - inline linear_axis_bits_t axes_should_home(linear_axis_bits_t=linear_bits) { return false; } + inline linear_axis_bits_t axes_should_home(linear_axis_bits_t=linear_bits) { return 0; } inline bool homing_needed_error(linear_axis_bits_t=linear_bits) { return false; } inline void set_axis_unhomed(const AxisEnum axis) {} inline void set_axis_untrusted(const AxisEnum axis) {} @@ -490,6 +523,18 @@ void home_if_needed(const bool keeplev=false); #define LOGICAL_K_POSITION(POS) NATIVE_TO_LOGICAL(POS, K_AXIS) #define RAW_K_POSITION(POS) LOGICAL_TO_NATIVE(POS, K_AXIS) #endif +#if HAS_U_AXIS + #define LOGICAL_U_POSITION(POS) NATIVE_TO_LOGICAL(POS, U_AXIS) + #define RAW_U_POSITION(POS) LOGICAL_TO_NATIVE(POS, U_AXIS) +#endif +#if HAS_V_AXIS + #define LOGICAL_V_POSITION(POS) NATIVE_TO_LOGICAL(POS, V_AXIS) + #define RAW_V_POSITION(POS) LOGICAL_TO_NATIVE(POS, V_AXIS) +#endif +#if HAS_W_AXIS + #define LOGICAL_W_POSITION(POS) NATIVE_TO_LOGICAL(POS, W_AXIS) + #define RAW_W_POSITION(POS) LOGICAL_TO_NATIVE(POS, W_AXIS) +#endif /** * position_is_reachable family of functions diff --git a/Marlin/src/module/planner.cpp b/Marlin/src/module/planner.cpp index 51440aac26..42a16603d4 100644 --- a/Marlin/src/module/planner.cpp +++ b/Marlin/src/module/planner.cpp @@ -1300,7 +1300,7 @@ void Planner::recalculate() { */ void Planner::check_axes_activity() { - #if ANY(DISABLE_X, DISABLE_Y, DISABLE_Z, DISABLE_I, DISABLE_J, DISABLE_K, DISABLE_E) + #if ANY(DISABLE_X, DISABLE_Y, DISABLE_Z, DISABLE_I, DISABLE_J, DISABLE_K, DISABLE_U, DISABLE_V, DISABLE_W, DISABLE_E) xyze_bool_t axis_active = { false }; #endif @@ -1350,7 +1350,10 @@ void Planner::check_axes_activity() { if (TERN0(DISABLE_Z, block->steps.z)) axis_active.z = true, if (TERN0(DISABLE_I, block->steps.i)) axis_active.i = true, if (TERN0(DISABLE_J, block->steps.j)) axis_active.j = true, - if (TERN0(DISABLE_K, block->steps.k)) axis_active.k = true + if (TERN0(DISABLE_K, block->steps.k)) axis_active.k = true, + if (TERN0(DISABLE_U, block->steps.u)) axis_active.u = true, + if (TERN0(DISABLE_V, block->steps.v)) axis_active.v = true, + if (TERN0(DISABLE_W, block->steps.w)) axis_active.w = true ); } #endif @@ -1385,7 +1388,10 @@ void Planner::check_axes_activity() { if (TERN0(DISABLE_Z, !axis_active.z)) stepper.disable_axis(Z_AXIS), if (TERN0(DISABLE_I, !axis_active.i)) stepper.disable_axis(I_AXIS), if (TERN0(DISABLE_J, !axis_active.j)) stepper.disable_axis(J_AXIS), - if (TERN0(DISABLE_K, !axis_active.k)) stepper.disable_axis(K_AXIS) + if (TERN0(DISABLE_K, !axis_active.k)) stepper.disable_axis(K_AXIS), + if (TERN0(DISABLE_U, !axis_active.u)) stepper.disable_axis(U_AXIS), + if (TERN0(DISABLE_V, !axis_active.v)) stepper.disable_axis(V_AXIS), + if (TERN0(DISABLE_W, !axis_active.w)) stepper.disable_axis(W_AXIS) ); // @@ -1453,7 +1459,7 @@ void Planner::check_axes_activity() { float high = 0.0; for (uint8_t b = block_buffer_tail; b != block_buffer_head; b = next_block_index(b)) { block_t *block = &block_buffer[b]; - if (LINEAR_AXIS_GANG(block->steps.x, || block->steps.y, || block->steps.z, || block->steps.i, || block->steps.j, || block->steps.k)) { + if (NUM_AXIS_GANG(block->steps.x, || block->steps.y, || block->steps.z, || block->steps.i, || block->steps.j, || block->steps.k, || block->steps.u, || block->steps.v, || block->steps.w)) { const float se = (float)block->steps.e / block->step_event_count * SQRT(block->nominal_speed_sqr); // mm/sec; NOLESS(high, se); } @@ -1505,7 +1511,7 @@ void Planner::check_axes_activity() { volumetric_extruder_feedrate_limit[e] = (lim && siz) ? lim / CIRCLE_AREA(siz * 0.5f) : 0; } void Planner::calculate_volumetric_extruder_limits() { - LOOP_L_N(e, EXTRUDERS) calculate_volumetric_extruder_limit(e); + EXTRUDER_LOOP() calculate_volumetric_extruder_limit(e); } #endif @@ -1591,7 +1597,7 @@ void Planner::check_axes_activity() { #elif ENABLED(AUTO_BED_LEVELING_UBL) fade_scaling_factor ? fade_scaling_factor * ubl.get_z_correction(raw) : 0.0 #elif ENABLED(AUTO_BED_LEVELING_BILINEAR) - fade_scaling_factor ? fade_scaling_factor * bilinear_z_offset(raw) : 0.0 + fade_scaling_factor ? fade_scaling_factor * bbl.get_z_correction(raw) : 0.0 #endif ); @@ -1624,7 +1630,7 @@ void Planner::check_axes_activity() { #elif ENABLED(AUTO_BED_LEVELING_UBL) fade_scaling_factor ? fade_scaling_factor * ubl.get_z_correction(raw) : 0.0 #elif ENABLED(AUTO_BED_LEVELING_BILINEAR) - fade_scaling_factor ? fade_scaling_factor * bilinear_z_offset(raw) : 0.0 + fade_scaling_factor ? fade_scaling_factor * bbl.get_z_correction(raw) : 0.0 #endif ); @@ -1856,15 +1862,22 @@ bool Planner::_populate_block(block_t * const block, bool split_move, dc = target.c - position.c, di = target.i - position.i, dj = target.j - position.j, - dk = target.k - position.k + dk = target.k - position.k, + du = target.u - position.u, + dv = target.v - position.v, + dw = target.w - position.w ); /* <-- add a slash to enable SERIAL_ECHOLNPGM( " _populate_block FR:", fr_mm_s, " A:", target.a, " (", da, " steps)" - " B:", target.b, " (", db, " steps)" - " C:", target.c, " (", dc, " steps)" + #if HAS_Y_AXIS + " B:", target.b, " (", db, " steps)" + #endif + #if HAS_Z_AXIS + " C:", target.c, " (", dc, " steps)" + #endif #if HAS_I_AXIS " " STR_I ":", target.i, " (", di, " steps)" #endif @@ -1874,6 +1887,14 @@ bool Planner::_populate_block(block_t * const block, bool split_move, #if HAS_K_AXIS " " STR_K ":", target.k, " (", dk, " steps)" #endif + #if HAS_U_AXIS + " " STR_U ":", target.u, " (", du, " steps)" + #endif + #if HAS_V_AXIS + " " STR_V ":", target.v, " (", dv, " steps)" + #endif + #if HAS_W_AXIS + " " STR_W ":", target.w, " (", dw, " steps)" #if HAS_EXTRUDERS " E:", target.e, " (", de, " steps)" #endif @@ -1938,15 +1959,6 @@ bool Planner::_populate_block(block_t * const block, bool split_move, if (db + dc < 0) SBI(dm, B_AXIS); // Motor B direction if (CORESIGN(db - dc) < 0) SBI(dm, C_AXIS); // Motor C direction #endif - #if HAS_I_AXIS - if (di < 0) SBI(dm, I_AXIS); - #endif - #if HAS_J_AXIS - if (dj < 0) SBI(dm, J_AXIS); - #endif - #if HAS_K_AXIS - if (dk < 0) SBI(dm, K_AXIS); - #endif #elif ENABLED(MARKFORGED_XY) if (da + db < 0) SBI(dm, A_AXIS); // Motor A direction if (db < 0) SBI(dm, B_AXIS); // Motor B direction @@ -1954,16 +1966,22 @@ bool Planner::_populate_block(block_t * const block, bool split_move, if (da < 0) SBI(dm, A_AXIS); // Motor A direction if (db + da < 0) SBI(dm, B_AXIS); // Motor B direction #else - LINEAR_AXIS_CODE( + XYZ_CODE( if (da < 0) SBI(dm, X_AXIS), if (db < 0) SBI(dm, Y_AXIS), - if (dc < 0) SBI(dm, Z_AXIS), - if (di < 0) SBI(dm, I_AXIS), - if (dj < 0) SBI(dm, J_AXIS), - if (dk < 0) SBI(dm, K_AXIS) + if (dc < 0) SBI(dm, Z_AXIS) ); #endif + SECONDARY_AXIS_CODE( + if (di < 0) SBI(dm, I_AXIS), + if (dj < 0) SBI(dm, J_AXIS), + if (dk < 0) SBI(dm, K_AXIS), + if (du < 0) SBI(dm, U_AXIS), + if (dv < 0) SBI(dm, V_AXIS), + if (dw < 0) SBI(dm, W_AXIS) + ); + #if HAS_EXTRUDERS if (de < 0) SBI(dm, E_AXIS); const float esteps_float = de * e_factor[extruder]; @@ -1988,20 +2006,20 @@ bool Planner::_populate_block(block_t * const block, bool split_move, // Number of steps for each axis // See https://www.corexy.com/theory.html #if CORE_IS_XY - block->steps.set(LINEAR_AXIS_LIST(ABS(da + db), ABS(da - db), ABS(dc), ABS(di), ABS(dj), ABS(dk))); + block->steps.set(NUM_AXIS_LIST(ABS(da + db), ABS(da - db), ABS(dc), ABS(di), ABS(dj), ABS(dk), ABS(du), ABS(dv), ABS(dw))); #elif CORE_IS_XZ - block->steps.set(LINEAR_AXIS_LIST(ABS(da + dc), ABS(db), ABS(da - dc), ABS(di), ABS(dj), ABS(dk))); + block->steps.set(NUM_AXIS_LIST(ABS(da + dc), ABS(db), ABS(da - dc), ABS(di), ABS(dj), ABS(dk), ABS(du), ABS(dv), ABS(dw))); #elif CORE_IS_YZ - block->steps.set(LINEAR_AXIS_LIST(ABS(da), ABS(db + dc), ABS(db - dc), ABS(di), ABS(dj), ABS(dk))); + block->steps.set(NUM_AXIS_LIST(ABS(da), ABS(db + dc), ABS(db - dc), ABS(di), ABS(dj), ABS(dk), ABS(du), ABS(dv), ABS(dw))); #elif ENABLED(MARKFORGED_XY) - block->steps.set(LINEAR_AXIS_LIST(ABS(da + db), ABS(db), ABS(dc), ABS(di), ABS(dj), ABS(dk))); + block->steps.set(NUM_AXIS_LIST(ABS(da + db), ABS(db), ABS(dc), ABS(di), ABS(dj), ABS(dk), ABS(du), ABS(dv), ABS(dw))); #elif ENABLED(MARKFORGED_YX) - block->steps.set(LINEAR_AXIS_LIST(ABS(da), ABS(db + da), ABS(dc), ABS(di), ABS(dj), ABS(dk))); + block->steps.set(NUM_AXIS_LIST(ABS(da), ABS(db + da), ABS(dc), ABS(di), ABS(dj), ABS(dk), ABS(du), ABS(dv), ABS(dw))); #elif IS_SCARA - block->steps.set(LINEAR_AXIS_LIST(ABS(da), ABS(db), ABS(dc), ABS(di), ABS(dj), ABS(dk))); + block->steps.set(NUM_AXIS_LIST(ABS(da), ABS(db), ABS(dc), ABS(di), ABS(dj), ABS(dk), ABS(du), ABS(dv), ABS(dw))); #else // default non-h-bot planning - block->steps.set(LINEAR_AXIS_LIST(ABS(da), ABS(db), ABS(dc), ABS(di), ABS(dj), ABS(dk))); + block->steps.set(NUM_AXIS_LIST(ABS(da), ABS(db), ABS(dc), ABS(di), ABS(dj), ABS(dk), ABS(du), ABS(dv), ABS(dw))); #endif /** @@ -2040,9 +2058,6 @@ bool Planner::_populate_block(block_t * const block, bool split_move, steps_dist_mm.b = (db + dc) * mm_per_step[B_AXIS]; steps_dist_mm.c = CORESIGN(db - dc) * mm_per_step[C_AXIS]; #endif - TERN_(HAS_I_AXIS, steps_dist_mm.i = di * mm_per_step[I_AXIS]); - TERN_(HAS_J_AXIS, steps_dist_mm.j = dj * mm_per_step[J_AXIS]); - TERN_(HAS_K_AXIS, steps_dist_mm.k = dk * mm_per_step[K_AXIS]); #elif ENABLED(MARKFORGED_XY) steps_dist_mm.a = (da - db) * mm_per_step[A_AXIS]; steps_dist_mm.b = db * mm_per_step[B_AXIS]; @@ -2050,27 +2065,40 @@ bool Planner::_populate_block(block_t * const block, bool split_move, steps_dist_mm.a = da * mm_per_step[A_AXIS]; steps_dist_mm.b = (db - da) * mm_per_step[B_AXIS]; #else - LINEAR_AXIS_CODE( + XYZ_CODE( steps_dist_mm.a = da * mm_per_step[A_AXIS], steps_dist_mm.b = db * mm_per_step[B_AXIS], - steps_dist_mm.c = dc * mm_per_step[C_AXIS], - steps_dist_mm.i = di * mm_per_step[I_AXIS], - steps_dist_mm.j = dj * mm_per_step[J_AXIS], - steps_dist_mm.k = dk * mm_per_step[K_AXIS] + steps_dist_mm.c = dc * mm_per_step[C_AXIS] ); #endif + SECONDARY_AXIS_CODE( + steps_dist_mm.i = di * mm_per_step[I_AXIS], + steps_dist_mm.j = dj * mm_per_step[J_AXIS], + steps_dist_mm.k = dk * mm_per_step[K_AXIS], + steps_dist_mm.u = du * mm_per_step[U_AXIS], + steps_dist_mm.v = dv * mm_per_step[V_AXIS], + steps_dist_mm.w = dw * mm_per_step[W_AXIS] + ); + TERN_(HAS_EXTRUDERS, steps_dist_mm.e = esteps_float * mm_per_step[E_AXIS_N(extruder)]); TERN_(LCD_SHOW_E_TOTAL, e_move_accumulator += steps_dist_mm.e); - if (true LINEAR_AXIS_GANG( + #if BOTH(HAS_ROTATIONAL_AXES, INCH_MODE_SUPPORT) + bool cartesian_move = true; + #endif + + if (true NUM_AXIS_GANG( && block->steps.a < MIN_STEPS_PER_SEGMENT, && block->steps.b < MIN_STEPS_PER_SEGMENT, && block->steps.c < MIN_STEPS_PER_SEGMENT, && block->steps.i < MIN_STEPS_PER_SEGMENT, && block->steps.j < MIN_STEPS_PER_SEGMENT, - && block->steps.k < MIN_STEPS_PER_SEGMENT + && block->steps.k < MIN_STEPS_PER_SEGMENT, + && block->steps.u < MIN_STEPS_PER_SEGMENT, + && block->steps.v < MIN_STEPS_PER_SEGMENT, + && block->steps.w < MIN_STEPS_PER_SEGMENT ) ) { block->millimeters = TERN0(HAS_EXTRUDERS, ABS(steps_dist_mm.e)); @@ -2079,36 +2107,71 @@ bool Planner::_populate_block(block_t * const block, bool split_move, if (millimeters) block->millimeters = millimeters; else { - block->millimeters = SQRT( - #if ANY(CORE_IS_XY, MARKFORGED_XY, MARKFORGED_YX) - LINEAR_AXIS_GANG( - sq(steps_dist_mm.head.x), + sq(steps_dist_mm.head.y), + sq(steps_dist_mm.z), - + sq(steps_dist_mm.i), + sq(steps_dist_mm.j), + sq(steps_dist_mm.k) - ) - #elif CORE_IS_XZ - LINEAR_AXIS_GANG( - sq(steps_dist_mm.head.x), + sq(steps_dist_mm.y), + sq(steps_dist_mm.head.z), - + sq(steps_dist_mm.i), + sq(steps_dist_mm.j), + sq(steps_dist_mm.k) - ) - #elif CORE_IS_YZ - LINEAR_AXIS_GANG( - sq(steps_dist_mm.x) + sq(steps_dist_mm.head.y) + sq(steps_dist_mm.head.z) - + sq(steps_dist_mm.i), + sq(steps_dist_mm.j), + sq(steps_dist_mm.k) - ) + /** + * Distance for interpretation of feedrate in accordance with LinuxCNC (the successor of NIST + * RS274NGC interpreter - version 3) and its default CANON_XYZ feed reference mode. + * Assume that X, Y, Z are the primary linear axes and U, V, W are secondary linear axes and A, B, C are + * rotational axes. Then dX, dY, dZ are the displacements of the primary linear axes and dU, dV, dW are the displacements of linear axes and + * dA, dB, dC are the displacements of rotational axes. + * The time it takes to execute move command with feedrate F is t = D/F, where D is the total distance, calculated as follows: + * D^2 = dX^2 + dY^2 + dZ^2 + * if D^2 == 0 (none of XYZ move but any secondary linear axes move, whether other axes are moved or not): + * D^2 = dU^2 + dV^2 + dW^2 + * if D^2 == 0 (only rotational axes are moved): + * D^2 = dA^2 + dB^2 + dC^2 + */ + float distance_sqr = ( + #if ENABLED(ARTICULATED_ROBOT_ARM) + // For articulated robots, interpreting feedrate like LinuxCNC would require inverse kinematics. As a workaround, pretend that motors sit on n mutually orthogonal + // axes and assume that we could think of distance as magnitude of an n-vector in an n-dimensional Euclidian space. + NUM_AXIS_GANG( + sq(steps_dist_mm.x), + sq(steps_dist_mm.y), + sq(steps_dist_mm.z), + + sq(steps_dist_mm.i), + sq(steps_dist_mm.j), + sq(steps_dist_mm.k), + + sq(steps_dist_mm.u), + sq(steps_dist_mm.v), + sq(steps_dist_mm.w) + ); #elif ENABLED(FOAMCUTTER_XYUV) - // Return the largest distance move from either X/Y or I/J plane #if HAS_J_AXIS - _MAX(sq(steps_dist_mm.x) + sq(steps_dist_mm.y), sq(steps_dist_mm.i) + sq(steps_dist_mm.j)) - #else + // Special 5 axis kinematics. Return the largest distance move from either X/Y or I/J plane + _MAX(sq(steps_dist_mm.x) + sq(steps_dist_mm.y), sq(steps_dist_mm.i) + sq(steps_dist_mm.j)) + #else // Foamcutter with only two axes (XY) sq(steps_dist_mm.x) + sq(steps_dist_mm.y) #endif + #elif ANY(CORE_IS_XY, MARKFORGED_XY, MARKFORGED_YX) + XYZ_GANG(sq(steps_dist_mm.head.x), + sq(steps_dist_mm.head.y), + sq(steps_dist_mm.z)) + #elif CORE_IS_XZ + XYZ_GANG(sq(steps_dist_mm.head.x), + sq(steps_dist_mm.y), + sq(steps_dist_mm.head.z)) + #elif CORE_IS_YZ + XYZ_GANG(sq(steps_dist_mm.x), + sq(steps_dist_mm.head.y), + sq(steps_dist_mm.head.z)) #else - LINEAR_AXIS_GANG( - sq(steps_dist_mm.x), + sq(steps_dist_mm.y), + sq(steps_dist_mm.z), - + sq(steps_dist_mm.i), + sq(steps_dist_mm.j), + sq(steps_dist_mm.k) - ) + XYZ_GANG(sq(steps_dist_mm.x), + sq(steps_dist_mm.y), + sq(steps_dist_mm.z)) #endif ); + + #if SECONDARY_LINEAR_AXES >= 1 && NONE(FOAMCUTTER_XYUV, ARTICULATED_ROBOT_ARM) + if (NEAR_ZERO(distance_sqr)) { + // Move does not involve any primary linear axes (xyz) but might involve secondary linear axes + distance_sqr = (0.0 + SECONDARY_AXIS_GANG( + IF_DISABLED(AXIS4_ROTATES, + sq(steps_dist_mm.i)), + IF_DISABLED(AXIS5_ROTATES, + sq(steps_dist_mm.j)), + IF_DISABLED(AXIS6_ROTATES, + sq(steps_dist_mm.k)), + IF_DISABLED(AXIS7_ROTATES, + sq(steps_dist_mm.u)), + IF_DISABLED(AXIS8_ROTATES, + sq(steps_dist_mm.v)), + IF_DISABLED(AXIS9_ROTATES, + sq(steps_dist_mm.w)) + ) + ); + } + #endif + + #if HAS_ROTATIONAL_AXES && NONE(FOAMCUTTER_XYUV, ARTICULATED_ROBOT_ARM) + if (NEAR_ZERO(distance_sqr)) { + // Move involves only rotational axes. Calculate angular distance in accordance with LinuxCNC + TERN_(INCH_MODE_SUPPORT, cartesian_move = false); + distance_sqr = ROTATIONAL_AXIS_GANG(sq(steps_dist_mm.i), + sq(steps_dist_mm.j), + sq(steps_dist_mm.k), + sq(steps_dist_mm.u), + sq(steps_dist_mm.v), + sq(steps_dist_mm.w)); + } + #endif + + block->millimeters = SQRT(distance_sqr); } /** @@ -2125,8 +2188,10 @@ bool Planner::_populate_block(block_t * const block, bool split_move, TERN_(HAS_EXTRUDERS, block->steps.e = esteps); - block->step_event_count = _MAX(LOGICAL_AXIS_LIST( - esteps, block->steps.a, block->steps.b, block->steps.c, block->steps.i, block->steps.j, block->steps.k + block->step_event_count = _MAX(LOGICAL_AXIS_LIST(esteps, + block->steps.a, block->steps.b, block->steps.c, + block->steps.i, block->steps.j, block->steps.k, + block->steps.u, block->steps.v, block->steps.w )); // Bail if this is a zero-length block @@ -2148,13 +2213,16 @@ bool Planner::_populate_block(block_t * const block, bool split_move, E_TERN_(block->extruder = extruder); #if ENABLED(AUTO_POWER_CONTROL) - if (LINEAR_AXIS_GANG( + if (NUM_AXIS_GANG( block->steps.x, || block->steps.y, || block->steps.z, || block->steps.i, || block->steps.j, - || block->steps.k + || block->steps.k, + || block->steps.u, + || block->steps.v, + || block->steps.w )) powerManager.power_on(); #endif @@ -2180,19 +2248,27 @@ bool Planner::_populate_block(block_t * const block, bool split_move, } if (block->steps.x) stepper.enable_axis(X_AXIS); #else - LINEAR_AXIS_CODE( + NUM_AXIS_CODE( if (block->steps.x) stepper.enable_axis(X_AXIS), if (block->steps.y) stepper.enable_axis(Y_AXIS), if (TERN(Z_LATE_ENABLE, 0, block->steps.z)) stepper.enable_axis(Z_AXIS), if (block->steps.i) stepper.enable_axis(I_AXIS), if (block->steps.j) stepper.enable_axis(J_AXIS), - if (block->steps.k) stepper.enable_axis(K_AXIS) + if (block->steps.k) stepper.enable_axis(K_AXIS), + if (block->steps.u) stepper.enable_axis(U_AXIS), + if (block->steps.v) stepper.enable_axis(V_AXIS), + if (block->steps.w) stepper.enable_axis(W_AXIS) ); #endif #if ANY(CORE_IS_XY, MARKFORGED_XY, MARKFORGED_YX) - TERN_(HAS_I_AXIS, if (block->steps.i) stepper.enable_axis(I_AXIS)); - TERN_(HAS_J_AXIS, if (block->steps.j) stepper.enable_axis(J_AXIS)); - TERN_(HAS_K_AXIS, if (block->steps.k) stepper.enable_axis(K_AXIS)); + SECONDARY_AXIS_CODE( + if (block->steps.i) stepper.enable_axis(I_AXIS), + if (block->steps.j) stepper.enable_axis(J_AXIS), + if (block->steps.k) stepper.enable_axis(K_AXIS), + if (block->steps.u) stepper.enable_axis(U_AXIS), + if (block->steps.v) stepper.enable_axis(V_AXIS), + if (block->steps.w) stepper.enable_axis(W_AXIS) + ); #endif // Enable extruder(s) @@ -2239,8 +2315,14 @@ bool Planner::_populate_block(block_t * const block, bool split_move, const float inverse_millimeters = 1.0f / block->millimeters; // Inverse millimeters to remove multiple divides // Calculate inverse time for this move. No divide by zero due to previous checks. - // Example: At 120mm/s a 60mm move takes 0.5s. So this will give 2.0. - float inverse_secs = fr_mm_s * inverse_millimeters; + // Example: At 120mm/s a 60mm move involving XYZ axes takes 0.5s. So this will give 2.0. + // Example 2: At 120°/s a 60° move involving only rotational axes takes 0.5s. So this will give 2.0. + float inverse_secs; + #if BOTH(HAS_ROTATIONAL_AXES, INCH_MODE_SUPPORT) + inverse_secs = inverse_millimeters * (cartesian_move ? fr_mm_s : LINEAR_UNIT(fr_mm_s)); + #else + inverse_secs = fr_mm_s * inverse_millimeters; + #endif // Get the number of non busy movements in queue (non busy means that they can be altered) const uint8_t moves_queued = nonbusy_movesplanned(); @@ -2286,13 +2368,13 @@ bool Planner::_populate_block(block_t * const block, bool split_move, filwidth.advance_e(steps_dist_mm.e); #endif - // Calculate and limit speed in mm/sec + // Calculate and limit speed in mm/sec (linear) or degrees/sec (rotational) xyze_float_t current_speed; float speed_factor = 1.0f; // factor <1 decreases speed // Linear axes first with less logic - LOOP_LINEAR_AXES(i) { + LOOP_NUM_AXES(i) { current_speed[i] = steps_dist_mm[i] * inverse_secs; const feedRate_t cs = ABS(current_speed[i]), max_fr = settings.max_feedrate_mm_s[i]; @@ -2380,9 +2462,10 @@ bool Planner::_populate_block(block_t * const block, bool split_move, // Compute and limit the acceleration rate for the trapezoid generator. const float steps_per_mm = block->step_event_count * inverse_millimeters; uint32_t accel; - if (LINEAR_AXIS_GANG( + if (NUM_AXIS_GANG( !block->steps.a, && !block->steps.b, && !block->steps.c, - && !block->steps.i, && !block->steps.j, && !block->steps.k) + && !block->steps.i, && !block->steps.j, && !block->steps.k, + && !block->steps.u, && !block->steps.v, && !block->steps.w) ) { // Is this a retract / recover move? accel = CEIL(settings.retract_acceleration * steps_per_mm); // Convert to: acceleration steps/sec^2 TERN_(LIN_ADVANCE, block->use_advance_lead = false); // No linear advance for simple retract/recover @@ -2455,7 +2538,10 @@ bool Planner::_populate_block(block_t * const block, bool split_move, LIMIT_ACCEL_LONG(C_AXIS, 0), LIMIT_ACCEL_LONG(I_AXIS, 0), LIMIT_ACCEL_LONG(J_AXIS, 0), - LIMIT_ACCEL_LONG(K_AXIS, 0) + LIMIT_ACCEL_LONG(K_AXIS, 0), + LIMIT_ACCEL_LONG(U_AXIS, 0), + LIMIT_ACCEL_LONG(V_AXIS, 0), + LIMIT_ACCEL_LONG(W_AXIS, 0) ); } else { @@ -2466,7 +2552,10 @@ bool Planner::_populate_block(block_t * const block, bool split_move, LIMIT_ACCEL_FLOAT(C_AXIS, 0), LIMIT_ACCEL_FLOAT(I_AXIS, 0), LIMIT_ACCEL_FLOAT(J_AXIS, 0), - LIMIT_ACCEL_FLOAT(K_AXIS, 0) + LIMIT_ACCEL_FLOAT(K_AXIS, 0), + LIMIT_ACCEL_FLOAT(U_AXIS, 0), + LIMIT_ACCEL_FLOAT(V_AXIS, 0), + LIMIT_ACCEL_FLOAT(W_AXIS, 0) ); } } @@ -2531,7 +2620,7 @@ bool Planner::_populate_block(block_t * const block, bool split_move, #if HAS_DIST_MM_ARG cart_dist_mm #else - LOGICAL_AXIS_ARRAY(steps_dist_mm.e, steps_dist_mm.x, steps_dist_mm.y, steps_dist_mm.z, steps_dist_mm.i, steps_dist_mm.j, steps_dist_mm.k) + LOGICAL_AXIS_ARRAY(steps_dist_mm.e, steps_dist_mm.x, steps_dist_mm.y, steps_dist_mm.z, steps_dist_mm.i, steps_dist_mm.j, steps_dist_mm.k, steps_dist_mm.u, steps_dist_mm.v, steps_dist_mm.w) #endif ; @@ -2557,7 +2646,10 @@ bool Planner::_populate_block(block_t * const block, bool split_move, + (-prev_unit_vec.z * unit_vec.z), + (-prev_unit_vec.i * unit_vec.i), + (-prev_unit_vec.j * unit_vec.j), - + (-prev_unit_vec.k * unit_vec.k) + + (-prev_unit_vec.k * unit_vec.k), + + (-prev_unit_vec.u * unit_vec.u), + + (-prev_unit_vec.v * unit_vec.v), + + (-prev_unit_vec.w * unit_vec.w) ); // NOTE: Computed without any expensive trig, sin() or acos(), by trig half angle identity of cos(theta). @@ -2704,7 +2796,7 @@ bool Planner::_populate_block(block_t * const block, bool split_move, const float extra_xyjerk = TERN0(HAS_EXTRUDERS, de <= 0) ? TRAVEL_EXTRA_XYJERK : 0; uint8_t limited = 0; - TERN(HAS_LINEAR_E_JERK, LOOP_LINEAR_AXES, LOOP_LOGICAL_AXES)(i) { + TERN(HAS_LINEAR_E_JERK, LOOP_NUM_AXES, LOOP_LOGICAL_AXES)(i) { const float jerk = ABS(current_speed[i]), // cs : Starting from zero, change in speed for this axis maxj = (max_jerk[i] + (i == X_AXIS || i == Y_AXIS ? extra_xyjerk : 0.0f)); // mj : The max jerk setting for this axis if (jerk > maxj) { // cs > mj : New current speed too fast? @@ -2742,7 +2834,7 @@ bool Planner::_populate_block(block_t * const block, bool split_move, vmax_junction = previous_nominal_speed; // Now limit the jerk in all axes. - TERN(HAS_LINEAR_E_JERK, LOOP_LINEAR_AXES, LOOP_LOGICAL_AXES)(axis) { + TERN(HAS_LINEAR_E_JERK, LOOP_NUM_AXES, LOOP_LOGICAL_AXES)(axis) { // Limit an axis. We have to differentiate: coasting, reversal of an axis, full stop. float v_exit = previous_speed[axis] * smaller_speed_factor, v_entry = current_speed[axis]; @@ -2844,7 +2936,7 @@ void Planner::buffer_sync_block(TERN_(LASER_SYNCHRONOUS_M106_M107, uint8_t sync_ block->position = position; #if ENABLED(BACKLASH_COMPENSATION) - LOOP_LINEAR_AXES(axis) block->position[axis] += backlash.get_applied_steps((AxisEnum)axis); + LOOP_NUM_AXES(axis) block->position[axis] += backlash.get_applied_steps((AxisEnum)axis); #endif #if BOTH(HAS_FAN, LASER_SYNCHRONOUS_M106_M107) @@ -2906,7 +2998,10 @@ bool Planner::buffer_segment(const abce_pos_t &abce int32_t(LROUND(abce.c * settings.axis_steps_per_mm[C_AXIS])), int32_t(LROUND(abce.i * settings.axis_steps_per_mm[I_AXIS])), int32_t(LROUND(abce.j * settings.axis_steps_per_mm[J_AXIS])), - int32_t(LROUND(abce.k * settings.axis_steps_per_mm[K_AXIS])) + int32_t(LROUND(abce.k * settings.axis_steps_per_mm[K_AXIS])), + int32_t(LROUND(abce.u * settings.axis_steps_per_mm[U_AXIS])), + int32_t(LROUND(abce.v * settings.axis_steps_per_mm[V_AXIS])), + int32_t(LROUND(abce.w * settings.axis_steps_per_mm[W_AXIS])) ) }; @@ -2958,6 +3053,21 @@ bool Planner::buffer_segment(const abce_pos_t &abce SERIAL_ECHOPGM(" (", position.k, "->", target.k); SERIAL_CHAR(')'); #endif + #if HAS_U_AXIS + SERIAL_ECHOPGM_P(SP_U_LBL, abce.u); + SERIAL_ECHOPGM(" (", position.u, "->", target.u); + SERIAL_CHAR(')'); + #endif + #if HAS_V_AXIS + SERIAL_ECHOPGM_P(SP_V_LBL, abce.v); + SERIAL_ECHOPGM(" (", position.v, "->", target.v); + SERIAL_CHAR(')'); + #endif + #if HAS_W_AXIS + SERIAL_ECHOPGM_P(SP_W_LBL, abce.w); + SERIAL_ECHOPGM(" (", position.w, "->", target.w); + SERIAL_CHAR(')'); + #endif #if HAS_EXTRUDERS SERIAL_ECHOPGM_P(SP_E_LBL, abce.e); SERIAL_ECHOLNPGM(" (", position.e, "->", target.e, ")"); @@ -3000,12 +3110,14 @@ bool Planner::buffer_line(const xyze_pos_t &cart, const_feedRate_t fr_mm_s, cons const xyze_pos_t cart_dist_mm = LOGICAL_AXIS_ARRAY( cart.e - position_cart.e, cart.x - position_cart.x, cart.y - position_cart.y, cart.z - position_cart.z, - cart.i - position_cart.i, cart.j - position_cart.j, cart.j - position_cart.k + cart.i - position_cart.i, cart.j - position_cart.j, cart.k - position_cart.k, + cart.u - position_cart.u, cart.v - position_cart.v, cart.w - position_cart.w ); #else - const xyz_pos_t cart_dist_mm = LINEAR_AXIS_ARRAY( + const xyz_pos_t cart_dist_mm = NUM_AXIS_ARRAY( cart.x - position_cart.x, cart.y - position_cart.y, cart.z - position_cart.z, - cart.i - position_cart.i, cart.j - position_cart.j, cart.j - position_cart.k + cart.i - position_cart.i, cart.j - position_cart.j, cart.k - position_cart.k, + cart.u - position_cart.u, cart.v - position_cart.v, cart.w - position_cart.w ); #endif @@ -3110,7 +3222,10 @@ void Planner::set_machine_position_mm(const abce_pos_t &abce) { LROUND(abce.c * settings.axis_steps_per_mm[C_AXIS]), LROUND(abce.i * settings.axis_steps_per_mm[I_AXIS]), LROUND(abce.j * settings.axis_steps_per_mm[J_AXIS]), - LROUND(abce.k * settings.axis_steps_per_mm[K_AXIS]) + LROUND(abce.k * settings.axis_steps_per_mm[K_AXIS]), + LROUND(abce.u * settings.axis_steps_per_mm[U_AXIS]), + LROUND(abce.v * settings.axis_steps_per_mm[V_AXIS]), + LROUND(abce.w * settings.axis_steps_per_mm[W_AXIS]) ) ); @@ -3122,7 +3237,7 @@ void Planner::set_machine_position_mm(const abce_pos_t &abce) { else { #if ENABLED(BACKLASH_COMPENSATION) abce_long_t stepper_pos = position; - LOOP_LINEAR_AXES(axis) stepper_pos[axis] += backlash.get_applied_steps((AxisEnum)axis); + LOOP_NUM_AXES(axis) stepper_pos[axis] += backlash.get_applied_steps((AxisEnum)axis); stepper.set_position(stepper_pos); #else stepper.set_position(position); diff --git a/Marlin/src/module/planner.h b/Marlin/src/module/planner.h index f29604bea8..eb4a34cec9 100644 --- a/Marlin/src/module/planner.h +++ b/Marlin/src/module/planner.h @@ -84,7 +84,8 @@ constexpr xyze_feedrate_t _mf = MANUAL_FEEDRATE, manual_feedrate_mm_s = LOGICAL_AXIS_ARRAY(_mf.e / 60.0f, _mf.x / 60.0f, _mf.y / 60.0f, _mf.z / 60.0f, - _mf.i / 60.0f, _mf.j / 60.0f, _mf.k / 60.0f); + _mf.i / 60.0f, _mf.j / 60.0f, _mf.k / 60.0f, + _mf.u / 60.0f, _mf.v / 60.0f, _mf.w / 60.0f); #endif #if IS_KINEMATIC && HAS_JUNCTION_DEVIATION @@ -843,7 +844,8 @@ class Planner { const abce_pos_t out = LOGICAL_AXIS_ARRAY( get_axis_position_mm(E_AXIS), get_axis_position_mm(A_AXIS), get_axis_position_mm(B_AXIS), get_axis_position_mm(C_AXIS), - get_axis_position_mm(I_AXIS), get_axis_position_mm(J_AXIS), get_axis_position_mm(K_AXIS) + get_axis_position_mm(I_AXIS), get_axis_position_mm(J_AXIS), get_axis_position_mm(K_AXIS), + get_axis_position_mm(U_AXIS), get_axis_position_mm(V_AXIS), get_axis_position_mm(W_AXIS) ); return out; } @@ -928,8 +930,8 @@ class Planner { #if HAS_LINEAR_E_JERK FORCE_INLINE static void recalculate_max_e_jerk() { const float prop = junction_deviation_mm * SQRT(0.5) / (1.0f - SQRT(0.5)); - LOOP_L_N(i, EXTRUDERS) - max_e_jerk[E_INDEX_N(i)] = SQRT(prop * settings.max_acceleration_mm_per_s2[E_INDEX_N(i)]); + EXTRUDER_LOOP() + max_e_jerk[E_INDEX_N(e)] = SQRT(prop * settings.max_acceleration_mm_per_s2[E_INDEX_N(e)]); } #endif diff --git a/Marlin/src/module/planner_bezier.cpp b/Marlin/src/module/planner_bezier.cpp index 848906705f..fa7e16a387 100644 --- a/Marlin/src/module/planner_bezier.cpp +++ b/Marlin/src/module/planner_bezier.cpp @@ -188,7 +188,10 @@ void cubic_b_spline( interp(position.z, target.z, t), // FIXME. Wrong, since t is not linear in the distance. interp(position.i, target.i, t), // FIXME. Wrong, since t is not linear in the distance. interp(position.j, target.j, t), // FIXME. Wrong, since t is not linear in the distance. - interp(position.k, target.k, t) // FIXME. Wrong, since t is not linear in the distance. + interp(position.k, target.k, t), // FIXME. Wrong, since t is not linear in the distance. + interp(position.u, target.u, t), // FIXME. Wrong, since t is not linear in the distance. + interp(position.v, target.v, t), // FIXME. Wrong, since t is not linear in the distance. + interp(position.w, target.w, t) // FIXME. Wrong, since t is not linear in the distance. ); apply_motion_limits(new_bez); bez_target = new_bez; diff --git a/Marlin/src/module/printcounter.cpp b/Marlin/src/module/printcounter.cpp index affb608780..fbf5401d67 100644 --- a/Marlin/src/module/printcounter.cpp +++ b/Marlin/src/module/printcounter.cpp @@ -151,7 +151,7 @@ void PrintCounter::loadStats() { if (data.nextService3 == 0) doBuzz = _service_warn(PSTR(" " SERVICE_NAME_3)); #endif #if HAS_BUZZER && SERVICE_WARNING_BUZZES > 0 - if (doBuzz) for (int i = 0; i < SERVICE_WARNING_BUZZES; i++) BUZZ(200, 404); + if (doBuzz) for (int i = 0; i < SERVICE_WARNING_BUZZES; i++) { BUZZ(200, 404); BUZZ(10, 0); } #else UNUSED(doBuzz); #endif @@ -171,7 +171,7 @@ void PrintCounter::saveStats() { persistentStore.write_data(address + sizeof(uint8_t), (uint8_t*)&data, sizeof(printStatistics)); persistentStore.access_finish(); - TERN_(EXTENSIBLE_UI, ExtUI::onConfigurationStoreWritten(true)); + TERN_(EXTENSIBLE_UI, ExtUI::onSettingsStored(true)); } #if HAS_SERVICE_INTERVALS diff --git a/Marlin/src/module/probe.cpp b/Marlin/src/module/probe.cpp index 89d2769247..f9a64a02d3 100644 --- a/Marlin/src/module/probe.cpp +++ b/Marlin/src/module/probe.cpp @@ -87,7 +87,7 @@ #if ENABLED(EXTENSIBLE_UI) #include "../lcd/extui/ui_api.h" -#elif ENABLED(DWIN_CREALITY_LCD_ENHANCED) +#elif ENABLED(DWIN_LCD_PROUI) #include "../lcd/e3v2/proui/dwin.h" #endif @@ -306,17 +306,16 @@ FORCE_INLINE void probe_specific_action(const bool deploy) { if (deploy != PROBE_TRIGGERED()) break; #endif - BUZZ(100, 659); - BUZZ(100, 698); + OKAY_BUZZ(); FSTR_P const ds_str = deploy ? GET_TEXT_F(MSG_MANUAL_DEPLOY) : GET_TEXT_F(MSG_MANUAL_STOW); ui.return_to_status(); // To display the new status message ui.set_status(ds_str, 99); - SERIAL_ECHOLNF(ds_str); + SERIAL_ECHOLNF(deploy ? GET_EN_TEXT_F(MSG_MANUAL_DEPLOY) : GET_EN_TEXT_F(MSG_MANUAL_STOW)); - TERN_(HOST_PROMPT_SUPPORT, hostui.prompt_do(PROMPT_USER_CONTINUE, F("Stow Probe"), FPSTR(CONTINUE_STR))); - TERN_(EXTENSIBLE_UI, ExtUI::onUserConfirmRequired(F("Stow Probe"))); - TERN_(DWIN_CREALITY_LCD_ENHANCED, DWIN_Popup_Confirm(ICON_BLTouch, F("Stow Probe"), FPSTR(CONTINUE_STR))); + TERN_(HOST_PROMPT_SUPPORT, hostui.prompt_do(PROMPT_USER_CONTINUE, ds_str, FPSTR(CONTINUE_STR))); + TERN_(EXTENSIBLE_UI, ExtUI::onUserConfirmRequired(ds_str)); + TERN_(DWIN_LCD_PROUI, DWIN_Popup_Confirm(ICON_BLTouch, ds_str, FPSTR(CONTINUE_STR))); TERN_(HAS_RESUME_CONTINUE, wait_for_user_response()); ui.reset_status(); @@ -795,9 +794,10 @@ float Probe::probe_at_point(const_float_t rx, const_float_t ry, const ProbePtRai #endif // On delta keep Z below clip height or do_blocking_move_to will abort - xyz_pos_t npos = LINEAR_AXIS_ARRAY( + xyz_pos_t npos = NUM_AXIS_ARRAY( rx, ry, TERN(DELTA, _MIN(delta_clip_start_height, current_position.z), current_position.z), - current_position.i, current_position.j, current_position.k + current_position.i, current_position.j, current_position.k, + current_position.u, current_position.v, current_position.w ); if (!can_reach(npos, probe_relative)) { if (DEBUGGING(LEVELING)) DEBUG_ECHOLNPGM("Position Not Reachable"); @@ -889,7 +889,7 @@ float Probe::probe_at_point(const_float_t rx, const_float_t ry, const ProbePtRai */ void Probe::set_homing_current(const bool onoff) { #define HAS_CURRENT_HOME(N) (defined(N##_CURRENT_HOME) && N##_CURRENT_HOME != N##_CURRENT) - #if HAS_CURRENT_HOME(X) || HAS_CURRENT_HOME(Y) || HAS_CURRENT_HOME(Z) + #if HAS_CURRENT_HOME(X) || HAS_CURRENT_HOME(Y) || HAS_CURRENT_HOME(Z) || HAS_CURRENT_HOME(I) || HAS_CURRENT_HOME(J) || HAS_CURRENT_HOME(K) || HAS_CURRENT_HOME(U) || HAS_CURRENT_HOME(V) || HAS_CURRENT_HOME(W) #if ENABLED(DELTA) static int16_t saved_current_X, saved_current_Y; #endif diff --git a/Marlin/src/module/probe.h b/Marlin/src/module/probe.h index 752e83f467..c802411be3 100644 --- a/Marlin/src/module/probe.h +++ b/Marlin/src/module/probe.h @@ -138,7 +138,7 @@ public: #else - static constexpr xyz_pos_t offset = xyz_pos_t(LINEAR_AXIS_ARRAY(0, 0, 0, 0, 0, 0)); // See #16767 + static constexpr xyz_pos_t offset = xyz_pos_t(NUM_AXIS_ARRAY(0, 0, 0, 0, 0, 0)); // See #16767 static bool set_deployed(const bool) { return false; } @@ -188,6 +188,15 @@ public: } #endif + /** + * The nozzle is only able to move within the physical bounds of the machine. + * If the PROBE has an OFFSET Marlin may need to apply additional limits so + * the probe can be prevented from going to unreachable points. + * + * e.g., If the PROBE is to the LEFT of the NOZZLE, it will be limited in how + * close it can get the RIGHT edge of the bed (unless the nozzle is able move + * far enough past the right edge). + */ static constexpr float _min_x(const xy_pos_t &probe_offset_xy=offset_xy) { return TERN(IS_KINEMATIC, (X_CENTER) - probe_radius(probe_offset_xy), diff --git a/Marlin/src/module/scara.cpp b/Marlin/src/module/scara.cpp index 2527292e16..bc42b85fbe 100644 --- a/Marlin/src/module/scara.cpp +++ b/Marlin/src/module/scara.cpp @@ -254,7 +254,7 @@ float segments_per_second = TERN(AXEL_TPARA, TPARA_SEGMENTS_PER_SECOND, SCARA_SE // Do this here all at once for Delta, because // XYZ isn't ABC. Applying this per-tower would // give the impression that they are the same. - LOOP_LINEAR_AXES(i) set_axis_is_at_home((AxisEnum)i); + LOOP_NUM_AXES(i) set_axis_is_at_home((AxisEnum)i); sync_plan_position(); } diff --git a/Marlin/src/module/settings.cpp b/Marlin/src/module/settings.cpp index fed1f67755..5cd592bddc 100644 --- a/Marlin/src/module/settings.cpp +++ b/Marlin/src/module/settings.cpp @@ -36,7 +36,7 @@ */ // Change EEPROM version if the structure changes -#define EEPROM_VERSION "V86" +#define EEPROM_VERSION "V87" #define EEPROM_OFFSET 100 // Check the integrity of data offsets. @@ -74,7 +74,7 @@ #if ENABLED(EXTENSIBLE_UI) #include "../lcd/extui/ui_api.h" -#elif ENABLED(DWIN_CREALITY_LCD_ENHANCED) +#elif ENABLED(DWIN_LCD_PROUI) #include "../lcd/e3v2/proui/dwin.h" #elif ENABLED(DWIN_CREALITY_LCD_JYERSUI) #include "../lcd/e3v2/jyersui/dwin.h" @@ -112,9 +112,6 @@ #if HAS_FILAMENT_SENSOR #include "../feature/runout.h" - #ifndef FIL_RUNOUT_ENABLED_DEFAULT - #define FIL_RUNOUT_ENABLED_DEFAULT true - #endif #endif #if ENABLED(EXTRA_LIN_ADVANCE_K) @@ -179,10 +176,10 @@ #define _EN_ITEM(N) , E##N -typedef struct { uint16_t LINEAR_AXIS_LIST(X, Y, Z, I, J, K), X2, Y2, Z2, Z3, Z4 REPEAT(E_STEPPERS, _EN_ITEM); } tmc_stepper_current_t; -typedef struct { uint32_t LINEAR_AXIS_LIST(X, Y, Z, I, J, K), X2, Y2, Z2, Z3, Z4 REPEAT(E_STEPPERS, _EN_ITEM); } tmc_hybrid_threshold_t; -typedef struct { int16_t LINEAR_AXIS_LIST(X, Y, Z, I, J, K), X2, Y2, Z2, Z3, Z4; } tmc_sgt_t; -typedef struct { bool LINEAR_AXIS_LIST(X, Y, Z, I, J, K), X2, Y2, Z2, Z3, Z4 REPEAT(E_STEPPERS, _EN_ITEM); } tmc_stealth_enabled_t; +typedef struct { uint16_t NUM_AXIS_LIST(X, Y, Z, I, J, K, U, V, W), X2, Y2, Z2, Z3, Z4 REPEAT(E_STEPPERS, _EN_ITEM); } tmc_stepper_current_t; +typedef struct { uint32_t NUM_AXIS_LIST(X, Y, Z, I, J, K, U, V, W), X2, Y2, Z2, Z3, Z4 REPEAT(E_STEPPERS, _EN_ITEM); } tmc_hybrid_threshold_t; +typedef struct { int16_t NUM_AXIS_LIST(X, Y, Z, I, J, K, U, V, W), X2, Y2, Z2, Z3, Z4; } tmc_sgt_t; +typedef struct { bool NUM_AXIS_LIST(X, Y, Z, I, J, K, U, V, W), X2, Y2, Z2, Z3, Z4 REPEAT(E_STEPPERS, _EN_ITEM); } tmc_stealth_enabled_t; #undef _EN_ITEM @@ -210,7 +207,7 @@ typedef struct SettingsDataStruct { // // DISTINCT_E_FACTORS // - uint8_t e_factors; // DISTINCT_AXES - LINEAR_AXES + uint8_t e_factors; // DISTINCT_AXES - NUM_AXES // // Planner settings @@ -235,8 +232,11 @@ typedef struct SettingsDataStruct { // // FILAMENT_RUNOUT_SENSOR // - bool runout_sensor_enabled; // M412 S - float runout_distance_mm; // M412 D + #if HAS_FILAMENT_SENSOR + bool runout_enabled[NUM_RUNOUT_SENSORS]; // M591 S + float runout_distance_mm[NUM_RUNOUT_SENSORS]; // M591 D + uint8_t runout_mode[NUM_RUNOUT_SENSORS]; // M591 P + #endif // // ENABLE_LEVELING_FADE_HEIGHT @@ -277,7 +277,9 @@ typedef struct SettingsDataStruct { // X_AXIS_TWIST_COMPENSATION // #if ENABLED(X_AXIS_TWIST_COMPENSATION) - XATC xatc; // TBD + float xatc_spacing; // M423 X Z + float xatc_start; + xatc_array_t xatc_z_offset; #endif // @@ -442,7 +444,7 @@ typedef struct SettingsDataStruct { // HAS_MOTOR_CURRENT_PWM // #ifndef MOTOR_CURRENT_COUNT - #define MOTOR_CURRENT_COUNT LINEAR_AXES + #define MOTOR_CURRENT_COUNT NUM_AXES #endif uint32_t motor_current_setting[MOTOR_CURRENT_COUNT]; // M907 X Z E ... @@ -487,7 +489,7 @@ typedef struct SettingsDataStruct { // // Ender-3 V2 DWIN // - #if ENABLED(DWIN_CREALITY_LCD_ENHANCED) + #if ENABLED(DWIN_LCD_PROUI) uint8_t dwin_data[eeprom_data_size]; #elif ENABLED(DWIN_CREALITY_LCD_JYERSUI) uint8_t dwin_settings[CrealityDWIN.eeprom_data_size]; @@ -552,6 +554,13 @@ typedef struct SettingsDataStruct { uint8_t ui_language; // M414 S #endif + // + // Model predictive control + // + #if ENABLED(MPCTEMP) + MPC_t mpc_constants[HOTENDS]; // M306 + #endif + } SettingsData; //static_assert(sizeof(SettingsData) <= MARLIN_EEPROM_SIZE, "EEPROM too small to contain SettingsData!"); @@ -588,14 +597,14 @@ void MarlinSettings::postprocess() { #endif // Software endstops depend on home_offset - LOOP_LINEAR_AXES(i) { + LOOP_NUM_AXES(i) { update_workspace_offset((AxisEnum)i); update_software_endstops((AxisEnum)i); } TERN_(ENABLE_LEVELING_FADE_HEIGHT, set_z_fade_height(new_z_fade_height, false)); // false = no report - TERN_(AUTO_BED_LEVELING_BILINEAR, refresh_bed_level()); + TERN_(AUTO_BED_LEVELING_BILINEAR, bbl.refresh_bed_level()); TERN_(HAS_MOTOR_CURRENT_PWM, stepper.refresh_motor_power()); @@ -736,7 +745,7 @@ void MarlinSettings::postprocess() { working_crc = 0; // clear before first "real data" - const uint8_t e_factors = DISTINCT_AXES - (LINEAR_AXES); + const uint8_t e_factors = DISTINCT_AXES - (NUM_AXES); _FIELD_TEST(e_factors); EEPROM_WRITE(e_factors); @@ -753,7 +762,7 @@ void MarlinSettings::postprocess() { EEPROM_WRITE(dummyf); #endif #else - const xyze_pos_t planner_max_jerk = LOGICAL_AXIS_ARRAY(float(DEFAULT_EJERK), 10, 10, 0.4, 0.4, 0.4, 0.4); + const xyze_pos_t planner_max_jerk = LOGICAL_AXIS_ARRAY(float(DEFAULT_EJERK), 10, 10, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4); EEPROM_WRITE(planner_max_jerk); #endif @@ -780,33 +789,23 @@ void MarlinSettings::postprocess() { // // Hotend Offsets, if any // - { - #if HAS_HOTEND_OFFSET - // Skip hotend 0 which must be 0 - LOOP_S_L_N(e, 1, HOTENDS) - EEPROM_WRITE(hotend_offset[e]); - #endif - } + #if HAS_HOTEND_OFFSET + // Skip hotend 0 which must be 0 + LOOP_S_L_N(e, 1, HOTENDS) + EEPROM_WRITE(hotend_offset[e]); + #endif // // Filament Runout Sensor // + #if HAS_FILAMENT_SENSOR { - #if HAS_FILAMENT_SENSOR - const bool &runout_sensor_enabled = runout.enabled; - #else - constexpr int8_t runout_sensor_enabled = -1; - #endif - _FIELD_TEST(runout_sensor_enabled); - EEPROM_WRITE(runout_sensor_enabled); - - #if HAS_FILAMENT_RUNOUT_DISTANCE - const float &runout_distance_mm = runout.runout_distance(); - #else - constexpr float runout_distance_mm = 0; - #endif - EEPROM_WRITE(runout_distance_mm); + _FIELD_TEST(runout_enabled); + LOOP_L_N(e, NUM_RUNOUT_SENSORS) EEPROM_WRITE(runout.enabled[e]); + LOOP_L_N(e, NUM_RUNOUT_SENSORS) EEPROM_WRITE(runout.runout_distance(e)); + LOOP_L_N(e, NUM_RUNOUT_SENSORS) EEPROM_WRITE(runout.mode[e]); } + #endif // // Global Leveling @@ -874,22 +873,26 @@ void MarlinSettings::postprocess() { { #if ENABLED(AUTO_BED_LEVELING_BILINEAR) static_assert( - sizeof(z_values) == (GRID_MAX_POINTS) * sizeof(z_values[0][0]), + sizeof(Z_VALUES_ARR) == (GRID_MAX_POINTS) * sizeof(Z_VALUES_ARR[0][0]), "Bilinear Z array is the wrong size." ); - #else - const xy_pos_t bilinear_start{0}, bilinear_grid_spacing{0}; #endif const uint8_t grid_max_x = TERN(AUTO_BED_LEVELING_BILINEAR, GRID_MAX_POINTS_X, 3), grid_max_y = TERN(AUTO_BED_LEVELING_BILINEAR, GRID_MAX_POINTS_Y, 3); EEPROM_WRITE(grid_max_x); EEPROM_WRITE(grid_max_y); - EEPROM_WRITE(bilinear_grid_spacing); - EEPROM_WRITE(bilinear_start); + #if ENABLED(AUTO_BED_LEVELING_BILINEAR) + EEPROM_WRITE(bbl.get_grid_spacing()); + EEPROM_WRITE(bbl.get_grid_start()); + #else + const xy_pos_t bilinear_start{0}, bilinear_grid_spacing{0}; + EEPROM_WRITE(bilinear_grid_spacing); + EEPROM_WRITE(bilinear_start); + #endif #if ENABLED(AUTO_BED_LEVELING_BILINEAR) - EEPROM_WRITE(z_values); // 9-256 floats + EEPROM_WRITE(Z_VALUES_ARR); // 9-256 floats #else dummyf = 0; for (uint16_t q = grid_max_x * grid_max_y; q--;) EEPROM_WRITE(dummyf); @@ -900,8 +903,10 @@ void MarlinSettings::postprocess() { // X Axis Twist Compensation // #if ENABLED(X_AXIS_TWIST_COMPENSATION) - _FIELD_TEST(xatc); - EEPROM_WRITE(xatc); + _FIELD_TEST(xatc_spacing); + EEPROM_WRITE(xatc.spacing); + EEPROM_WRITE(xatc.start); + EEPROM_WRITE(xatc.z_offset); #endif // @@ -1226,6 +1231,15 @@ void MarlinSettings::postprocess() { #if AXIS_IS_TMC(K) tmc_stepper_current.K = stepperK.getMilliamps(); #endif + #if AXIS_IS_TMC(U) + tmc_stepper_current.U = stepperU.getMilliamps(); + #endif + #if AXIS_IS_TMC(V) + tmc_stepper_current.V = stepperV.getMilliamps(); + #endif + #if AXIS_IS_TMC(W) + tmc_stepper_current.W = stepperW.getMilliamps(); + #endif #if AXIS_IS_TMC(X2) tmc_stepper_current.X2 = stepperX2.getMilliamps(); #endif @@ -1283,6 +1297,9 @@ void MarlinSettings::postprocess() { TERN_(I_HAS_STEALTHCHOP, tmc_hybrid_threshold.I = stepperI.get_pwm_thrs()); TERN_(J_HAS_STEALTHCHOP, tmc_hybrid_threshold.J = stepperJ.get_pwm_thrs()); TERN_(K_HAS_STEALTHCHOP, tmc_hybrid_threshold.K = stepperK.get_pwm_thrs()); + TERN_(U_HAS_STEALTHCHOP, tmc_hybrid_threshold.U = stepperU.get_pwm_thrs()); + TERN_(V_HAS_STEALTHCHOP, tmc_hybrid_threshold.V = stepperV.get_pwm_thrs()); + TERN_(W_HAS_STEALTHCHOP, tmc_hybrid_threshold.W = stepperW.get_pwm_thrs()); TERN_(X2_HAS_STEALTHCHOP, tmc_hybrid_threshold.X2 = stepperX2.get_pwm_thrs()); TERN_(Y2_HAS_STEALTHCHOP, tmc_hybrid_threshold.Y2 = stepperY2.get_pwm_thrs()); TERN_(Z2_HAS_STEALTHCHOP, tmc_hybrid_threshold.Z2 = stepperZ2.get_pwm_thrs()); @@ -1299,7 +1316,7 @@ void MarlinSettings::postprocess() { #else #define _EN_ITEM(N) , .E##N = 30 const tmc_hybrid_threshold_t tmc_hybrid_threshold = { - LINEAR_AXIS_LIST(.X = 100, .Y = 100, .Z = 3, .I = 3, .J = 3, .K = 3), + NUM_AXIS_LIST(.X = 100, .Y = 100, .Z = 3, .I = 3, .J = 3, .K = 3, .U = 3, .V = 3, .W = 3), .X2 = 100, .Y2 = 100, .Z2 = 3, .Z3 = 3, .Z4 = 3 REPEAT(E_STEPPERS, _EN_ITEM) }; @@ -1314,13 +1331,16 @@ void MarlinSettings::postprocess() { { tmc_sgt_t tmc_sgt{0}; #if USE_SENSORLESS - LINEAR_AXIS_CODE( + NUM_AXIS_CODE( TERN_(X_SENSORLESS, tmc_sgt.X = stepperX.homing_threshold()), TERN_(Y_SENSORLESS, tmc_sgt.Y = stepperY.homing_threshold()), TERN_(Z_SENSORLESS, tmc_sgt.Z = stepperZ.homing_threshold()), TERN_(I_SENSORLESS, tmc_sgt.I = stepperI.homing_threshold()), TERN_(J_SENSORLESS, tmc_sgt.J = stepperJ.homing_threshold()), - TERN_(K_SENSORLESS, tmc_sgt.K = stepperK.homing_threshold()) + TERN_(K_SENSORLESS, tmc_sgt.K = stepperK.homing_threshold()), + TERN_(U_SENSORLESS, tmc_sgt.U = stepperU.homing_threshold()), + TERN_(V_SENSORLESS, tmc_sgt.V = stepperV.homing_threshold()), + TERN_(W_SENSORLESS, tmc_sgt.W = stepperW.homing_threshold()) ); TERN_(X2_SENSORLESS, tmc_sgt.X2 = stepperX2.homing_threshold()); TERN_(Y2_SENSORLESS, tmc_sgt.Y2 = stepperY2.homing_threshold()); @@ -1344,6 +1364,9 @@ void MarlinSettings::postprocess() { TERN_(I_HAS_STEALTHCHOP, tmc_stealth_enabled.I = stepperI.get_stored_stealthChop()); TERN_(J_HAS_STEALTHCHOP, tmc_stealth_enabled.J = stepperJ.get_stored_stealthChop()); TERN_(K_HAS_STEALTHCHOP, tmc_stealth_enabled.K = stepperK.get_stored_stealthChop()); + TERN_(U_HAS_STEALTHCHOP, tmc_stealth_enabled.U = stepperU.get_stored_stealthChop()); + TERN_(V_HAS_STEALTHCHOP, tmc_stealth_enabled.V = stepperV.get_stored_stealthChop()); + TERN_(W_HAS_STEALTHCHOP, tmc_stealth_enabled.W = stepperW.get_stored_stealthChop()); TERN_(X2_HAS_STEALTHCHOP, tmc_stealth_enabled.X2 = stepperX2.get_stored_stealthChop()); TERN_(Y2_HAS_STEALTHCHOP, tmc_stealth_enabled.Y2 = stepperY2.get_stored_stealthChop()); TERN_(Z2_HAS_STEALTHCHOP, tmc_stealth_enabled.Z2 = stepperZ2.get_stored_stealthChop()); @@ -1433,7 +1456,7 @@ void MarlinSettings::postprocess() { { #if ENABLED(BACKLASH_GCODE) xyz_float_t backlash_distance_mm; - LOOP_LINEAR_AXES(axis) backlash_distance_mm[axis] = backlash.get_distance_mm((AxisEnum)axis); + LOOP_NUM_AXES(axis) backlash_distance_mm[axis] = backlash.get_distance_mm((AxisEnum)axis); const uint8_t backlash_correction = backlash.get_correction_uint8(); #else const xyz_float_t backlash_distance_mm{0}; @@ -1465,18 +1488,20 @@ void MarlinSettings::postprocess() { // // Creality DWIN User Data // - #if ENABLED(DWIN_CREALITY_LCD_ENHANCED) + #if ENABLED(DWIN_LCD_PROUI) { + _FIELD_TEST(dwin_data); char dwin_data[eeprom_data_size] = { 0 }; DWIN_StoreSettings(dwin_data); - _FIELD_TEST(dwin_data); EEPROM_WRITE(dwin_data); } - #elif ENABLED(DWIN_CREALITY_LCD_JYERSUI) + #endif + + #if ENABLED(DWIN_CREALITY_LCD_JYERSUI) { + _FIELD_TEST(dwin_settings); char dwin_settings[CrealityDWIN.eeprom_data_size] = { 0 }; CrealityDWIN.Save_Settings(dwin_settings); - _FIELD_TEST(dwin_settings); EEPROM_WRITE(dwin_settings); } #endif @@ -1553,6 +1578,14 @@ void MarlinSettings::postprocess() { EEPROM_WRITE(ui.language); #endif + // + // Model predictive control + // + #if ENABLED(MPCTEMP) + HOTEND_LOOP() + EEPROM_WRITE(thermalManager.temp_hotend[e].constants); + #endif + // // Report final CRC and Data Size // @@ -1589,7 +1622,7 @@ void MarlinSettings::postprocess() { TERN_(HOST_PROMPT_SUPPORT, hostui.notify(GET_TEXT_F(MSG_SETTINGS_STORED))); } - TERN_(EXTENSIBLE_UI, ExtUI::onConfigurationStoreWritten(!eeprom_error)); + TERN_(EXTENSIBLE_UI, ExtUI::onSettingsStored(!eeprom_error)); return !eeprom_error; } @@ -1610,7 +1643,7 @@ void MarlinSettings::postprocess() { stored_ver[1] = '\0'; } DEBUG_ECHO_MSG("EEPROM version mismatch (EEPROM=", stored_ver, " Marlin=" EEPROM_VERSION ")"); - TERN_(DWIN_CREALITY_LCD_ENHANCED, LCD_MESSAGE(MSG_ERR_EEPROM_VERSION)); + TERN_(DWIN_LCD_PROUI, LCD_MESSAGE(MSG_ERR_EEPROM_VERSION)); TERN_(HOST_PROMPT_SUPPORT, hostui.notify(GET_TEXT_F(MSG_ERR_EEPROM_VERSION))); IF_DISABLED(EEPROM_AUTO_INIT, ui.eeprom_alert_version()); @@ -1643,16 +1676,16 @@ void MarlinSettings::postprocess() { { // Get only the number of E stepper parameters previously stored // Any steppers added later are set to their defaults - uint32_t tmp1[LINEAR_AXES + e_factors]; - float tmp2[LINEAR_AXES + e_factors]; - feedRate_t tmp3[LINEAR_AXES + e_factors]; + uint32_t tmp1[NUM_AXES + e_factors]; + float tmp2[NUM_AXES + e_factors]; + feedRate_t tmp3[NUM_AXES + e_factors]; EEPROM_READ((uint8_t *)tmp1, sizeof(tmp1)); // max_acceleration_mm_per_s2 EEPROM_READ(planner.settings.min_segment_time_us); EEPROM_READ((uint8_t *)tmp2, sizeof(tmp2)); // axis_steps_per_mm EEPROM_READ((uint8_t *)tmp3, sizeof(tmp3)); // max_feedrate_mm_s if (!validating) LOOP_DISTINCT_AXES(i) { - const bool in = (i < e_factors + LINEAR_AXES); + const bool in = (i < e_factors + NUM_AXES); planner.settings.max_acceleration_mm_per_s2[i] = in ? tmp1[i] : pgm_read_dword(&_DMA[ALIM(i, _DMA)]); planner.settings.axis_steps_per_mm[i] = in ? tmp2[i] : pgm_read_float(&_DASU[ALIM(i, _DASU)]); planner.settings.max_feedrate_mm_s[i] = in ? tmp3[i] : pgm_read_float(&_DMF[ALIM(i, _DMF)]); @@ -1706,22 +1739,28 @@ void MarlinSettings::postprocess() { // // Filament Runout Sensor // + #if HAS_FILAMENT_SENSOR { - int8_t runout_sensor_enabled; - _FIELD_TEST(runout_sensor_enabled); - EEPROM_READ(runout_sensor_enabled); - #if HAS_FILAMENT_SENSOR - runout.enabled = runout_sensor_enabled < 0 ? FIL_RUNOUT_ENABLED_DEFAULT : runout_sensor_enabled; - #endif + _FIELD_TEST(runout_enabled); - TERN_(HAS_FILAMENT_SENSOR, if (runout.enabled) runout.reset()); + bool runout_enabled[NUM_RUNOUT_SENSORS]; + float runout_distance_mm[NUM_RUNOUT_SENSORS]; + RunoutMode runout_mode[NUM_RUNOUT_SENSORS]; - float runout_distance_mm; + EEPROM_READ(runout_enabled); EEPROM_READ(runout_distance_mm); - #if HAS_FILAMENT_RUNOUT_DISTANCE - if (!validating) runout.set_runout_distance(runout_distance_mm); - #endif + EEPROM_READ(runout_mode); + + if (!validating) { + LOOP_S_L_N(e, 0, NUM_RUNOUT_SENSORS) { + runout.enabled[e] = runout_enabled[e]; + runout.set_runout_distance(runout_distance_mm[e], e); + runout.mode[e] = runout_mode[e]; + } + runout.reset(); + } } + #endif // // Global Leveling @@ -1785,20 +1824,19 @@ void MarlinSettings::postprocess() { uint8_t grid_max_x, grid_max_y; EEPROM_READ_ALWAYS(grid_max_x); // 1 byte EEPROM_READ_ALWAYS(grid_max_y); // 1 byte + xy_pos_t spacing, start; + EEPROM_READ(spacing); // 2 ints + EEPROM_READ(start); // 2 ints #if ENABLED(AUTO_BED_LEVELING_BILINEAR) if (grid_max_x == (GRID_MAX_POINTS_X) && grid_max_y == (GRID_MAX_POINTS_Y)) { if (!validating) set_bed_leveling_enabled(false); - EEPROM_READ(bilinear_grid_spacing); // 2 ints - EEPROM_READ(bilinear_start); // 2 ints - EEPROM_READ(z_values); // 9 to 256 floats + bbl.set_grid(spacing, start); + EEPROM_READ(Z_VALUES_ARR); // 9 to 256 floats } else // EEPROM data is stale #endif // AUTO_BED_LEVELING_BILINEAR { // Skip past disabled (or stale) Bilinear Grid data - xy_pos_t bgs, bs; - EEPROM_READ(bgs); - EEPROM_READ(bs); for (uint16_t q = grid_max_x * grid_max_y; q--;) EEPROM_READ(dummyf); } } @@ -1807,7 +1845,10 @@ void MarlinSettings::postprocess() { // X Axis Twist Compensation // #if ENABLED(X_AXIS_TWIST_COMPENSATION) - EEPROM_READ(xatc); + _FIELD_TEST(xatc_spacing); + EEPROM_READ(xatc.spacing); + EEPROM_READ(xatc.start); + EEPROM_READ(xatc.z_offset); #endif // @@ -2163,6 +2204,15 @@ void MarlinSettings::postprocess() { #if AXIS_IS_TMC(K) SET_CURR(K); #endif + #if AXIS_IS_TMC(U) + SET_CURR(U); + #endif + #if AXIS_IS_TMC(V) + SET_CURR(V); + #endif + #if AXIS_IS_TMC(W) + SET_CURR(W); + #endif #if AXIS_IS_TMC(E0) SET_CURR(E0); #endif @@ -2210,6 +2260,9 @@ void MarlinSettings::postprocess() { TERN_(I_HAS_STEALTHCHOP, stepperI.set_pwm_thrs(tmc_hybrid_threshold.I)); TERN_(J_HAS_STEALTHCHOP, stepperJ.set_pwm_thrs(tmc_hybrid_threshold.J)); TERN_(K_HAS_STEALTHCHOP, stepperK.set_pwm_thrs(tmc_hybrid_threshold.K)); + TERN_(U_HAS_STEALTHCHOP, stepperU.set_pwm_thrs(tmc_hybrid_threshold.U)); + TERN_(V_HAS_STEALTHCHOP, stepperV.set_pwm_thrs(tmc_hybrid_threshold.V)); + TERN_(W_HAS_STEALTHCHOP, stepperW.set_pwm_thrs(tmc_hybrid_threshold.W)); TERN_(E0_HAS_STEALTHCHOP, stepperE0.set_pwm_thrs(tmc_hybrid_threshold.E0)); TERN_(E1_HAS_STEALTHCHOP, stepperE1.set_pwm_thrs(tmc_hybrid_threshold.E1)); TERN_(E2_HAS_STEALTHCHOP, stepperE2.set_pwm_thrs(tmc_hybrid_threshold.E2)); @@ -2231,13 +2284,16 @@ void MarlinSettings::postprocess() { EEPROM_READ(tmc_sgt); #if USE_SENSORLESS if (!validating) { - LINEAR_AXIS_CODE( + NUM_AXIS_CODE( TERN_(X_SENSORLESS, stepperX.homing_threshold(tmc_sgt.X)), TERN_(Y_SENSORLESS, stepperY.homing_threshold(tmc_sgt.Y)), TERN_(Z_SENSORLESS, stepperZ.homing_threshold(tmc_sgt.Z)), TERN_(I_SENSORLESS, stepperI.homing_threshold(tmc_sgt.I)), TERN_(J_SENSORLESS, stepperJ.homing_threshold(tmc_sgt.J)), - TERN_(K_SENSORLESS, stepperK.homing_threshold(tmc_sgt.K)) + TERN_(K_SENSORLESS, stepperK.homing_threshold(tmc_sgt.K)), + TERN_(U_SENSORLESS, stepperU.homing_threshold(tmc_sgt.U)), + TERN_(V_SENSORLESS, stepperV.homing_threshold(tmc_sgt.V)), + TERN_(W_SENSORLESS, stepperW.homing_threshold(tmc_sgt.W)) ); TERN_(X2_SENSORLESS, stepperX2.homing_threshold(tmc_sgt.X2)); TERN_(Y2_SENSORLESS, stepperY2.homing_threshold(tmc_sgt.Y2)); @@ -2265,6 +2321,9 @@ void MarlinSettings::postprocess() { TERN_(I_HAS_STEALTHCHOP, SET_STEPPING_MODE(I)); TERN_(J_HAS_STEALTHCHOP, SET_STEPPING_MODE(J)); TERN_(K_HAS_STEALTHCHOP, SET_STEPPING_MODE(K)); + TERN_(U_HAS_STEALTHCHOP, SET_STEPPING_MODE(U)); + TERN_(V_HAS_STEALTHCHOP, SET_STEPPING_MODE(V)); + TERN_(W_HAS_STEALTHCHOP, SET_STEPPING_MODE(W)); TERN_(X2_HAS_STEALTHCHOP, SET_STEPPING_MODE(X2)); TERN_(Y2_HAS_STEALTHCHOP, SET_STEPPING_MODE(Y2)); TERN_(Z2_HAS_STEALTHCHOP, SET_STEPPING_MODE(Z2)); @@ -2385,7 +2444,7 @@ void MarlinSettings::postprocess() { EEPROM_READ(backlash_smoothing_mm); #if ENABLED(BACKLASH_GCODE) - LOOP_LINEAR_AXES(axis) backlash.set_distance_mm((AxisEnum)axis, backlash_distance_mm[axis]); + LOOP_NUM_AXES(axis) backlash.set_distance_mm((AxisEnum)axis, backlash_distance_mm[axis]); backlash.set_correction_uint8(backlash_correction); #ifdef BACKLASH_SMOOTHING_MM backlash.set_smoothing_mm(backlash_smoothing_mm); @@ -2408,7 +2467,7 @@ void MarlinSettings::postprocess() { // // Creality DWIN User Data // - #if ENABLED(DWIN_CREALITY_LCD_ENHANCED) + #if ENABLED(DWIN_LCD_PROUI) { const char dwin_data[eeprom_data_size] = { 0 }; _FIELD_TEST(dwin_data); @@ -2501,6 +2560,16 @@ void MarlinSettings::postprocess() { } #endif + // + // Model predictive control + // + #if ENABLED(MPCTEMP) + { + HOTEND_LOOP() + EEPROM_READ(thermalManager.temp_hotend[e].constants); + } + #endif + // // Validate Final Size and CRC // @@ -2512,7 +2581,7 @@ void MarlinSettings::postprocess() { else if (working_crc != stored_crc) { eeprom_error = true; DEBUG_ERROR_MSG("EEPROM CRC mismatch - (stored) ", stored_crc, " != ", working_crc, " (calculated)!"); - TERN_(DWIN_CREALITY_LCD_ENHANCED, LCD_MESSAGE(MSG_ERR_EEPROM_CRC)); + TERN_(DWIN_LCD_PROUI, LCD_MESSAGE(MSG_ERR_EEPROM_CRC)); TERN_(HOST_EEPROM_CHITCHAT, hostui.notify(GET_TEXT_F(MSG_ERR_EEPROM_CRC))); IF_DISABLED(EEPROM_AUTO_INIT, ui.eeprom_alert_crc()); } @@ -2589,7 +2658,7 @@ void MarlinSettings::postprocess() { bool MarlinSettings::load() { if (validate()) { const bool success = _load(); - TERN_(EXTENSIBLE_UI, ExtUI::onConfigurationStoreRead(success)); + TERN_(EXTENSIBLE_UI, ExtUI::onSettingsLoaded(success)); return success; } reset(); @@ -2761,8 +2830,17 @@ void MarlinSettings::reset() { #if HAS_K_AXIS && !defined(DEFAULT_KJERK) #define DEFAULT_KJERK 0 #endif + #if HAS_U_AXIS && !defined(DEFAULT_UJERK) + #define DEFAULT_UJERK 0 + #endif + #if HAS_V_AXIS && !defined(DEFAULT_VJERK) + #define DEFAULT_VJERK 0 + #endif + #if HAS_W_AXIS && !defined(DEFAULT_WJERK) + #define DEFAULT_WJERK 0 + #endif planner.max_jerk.set( - LINEAR_AXIS_LIST(DEFAULT_XJERK, DEFAULT_YJERK, DEFAULT_ZJERK, DEFAULT_IJERK, DEFAULT_JJERK, DEFAULT_KJERK) + NUM_AXIS_LIST(DEFAULT_XJERK, DEFAULT_YJERK, DEFAULT_ZJERK, DEFAULT_IJERK, DEFAULT_JJERK, DEFAULT_KJERK, DEFAULT_UJERK, DEFAULT_VJERK, DEFAULT_WJERK) ); TERN_(HAS_CLASSIC_E_JERK, planner.max_jerk.e = DEFAULT_EJERK); #endif @@ -2782,9 +2860,16 @@ void MarlinSettings::reset() { // #if HAS_FILAMENT_SENSOR - runout.enabled = FIL_RUNOUT_ENABLED_DEFAULT; + constexpr bool fred[] = FIL_RUNOUT_ENABLED; + constexpr uint8_t frm[] = FIL_RUNOUT_MODE; + constexpr float frd[] = FIL_RUNOUT_DISTANCE_MM; + static_assert(COUNT(fred) == NUM_RUNOUT_SENSORS, "FIL_RUNOUT_ENABLED must have NUM_RUNOUT_SENSORS values."); + static_assert(COUNT(frm) == NUM_RUNOUT_SENSORS, "FIL_RUNOUT_MODE must have NUM_RUNOUT_SENSORS values."); + static_assert(COUNT(frd) == NUM_RUNOUT_SENSORS, "FIL_RUNOUT_DISTANCE_MM must have NUM_RUNOUT_SENSORS values."); + COPY(runout.enabled, fred); + COPY(runout.mode, frm); + LOOP_L_N(e, NUM_RUNOUT_SENSORS) runout.set_runout_distance(frd[e], e); runout.reset(); - TERN_(HAS_FILAMENT_RUNOUT_DISTANCE, runout.set_runout_distance(FILAMENT_RUNOUT_DISTANCE_MM)); #endif // @@ -2824,13 +2909,13 @@ void MarlinSettings::reset() { #if ENABLED(BACKLASH_GCODE) backlash.set_correction(BACKLASH_CORRECTION); constexpr xyz_float_t tmp = BACKLASH_DISTANCE_MM; - LOOP_LINEAR_AXES(axis) backlash.set_distance_mm((AxisEnum)axis, tmp[axis]); + LOOP_NUM_AXES(axis) backlash.set_distance_mm((AxisEnum)axis, tmp[axis]); #ifdef BACKLASH_SMOOTHING_MM backlash.set_smoothing_mm(BACKLASH_SMOOTHING_MM); #endif #endif - TERN_(DWIN_CREALITY_LCD_ENHANCED, DWIN_SetDataDefaults()); + TERN_(DWIN_LCD_PROUI, DWIN_SetDataDefaults()); TERN_(DWIN_CREALITY_LCD_JYERSUI, CrealityDWIN.Reset_Settings()); // @@ -2869,11 +2954,11 @@ void MarlinSettings::reset() { // #if HAS_BED_PROBE constexpr float dpo[] = NOZZLE_TO_PROBE_OFFSET; - static_assert(COUNT(dpo) == LINEAR_AXES, "NOZZLE_TO_PROBE_OFFSET must contain offsets for each linear axis X, Y, Z...."); + static_assert(COUNT(dpo) == NUM_AXES, "NOZZLE_TO_PROBE_OFFSET must contain offsets for each linear axis X, Y, Z...."); #if HAS_PROBE_XY_OFFSET - LOOP_LINEAR_AXES(a) probe.offset[a] = dpo[a]; + LOOP_NUM_AXES(a) probe.offset[a] = dpo[a]; #else - probe.offset.set(LINEAR_AXIS_LIST(0, 0, dpo[Z_AXIS], 0, 0, 0)); + probe.offset.set(NUM_AXIS_LIST(0, 0, dpo[Z_AXIS], 0, 0, 0, 0, 0, 0)); #endif #endif @@ -3129,9 +3214,9 @@ void MarlinSettings::reset() { // #if ENABLED(LIN_ADVANCE) - LOOP_L_N(i, EXTRUDERS) { - planner.extruder_advance_K[i] = LIN_ADVANCE_K; - TERN_(EXTRA_LIN_ADVANCE_K, other_extruder_advance_K[i] = LIN_ADVANCE_K); + EXTRUDER_LOOP() { + planner.extruder_advance_K[e] = LIN_ADVANCE_K; + TERN_(EXTRA_LIN_ADVANCE_K, other_extruder_advance_K[e] = LIN_ADVANCE_K); } #endif @@ -3176,7 +3261,7 @@ void MarlinSettings::reset() { // Advanced Pause filament load & unload lengths // #if ENABLED(ADVANCED_PAUSE_FEATURE) - LOOP_L_N(e, EXTRUDERS) { + EXTRUDER_LOOP() { fc_settings[e].unload_length = FILAMENT_CHANGE_UNLOAD_LENGTH; fc_settings[e].load_length = FILAMENT_CHANGE_FAST_LOAD_LENGTH; } @@ -3203,11 +3288,44 @@ void MarlinSettings::reset() { postprocess(); - FSTR_P const hdsl = F("Hardcoded Default Settings Loaded"); - TERN_(HOST_EEPROM_CHITCHAT, hostui.notify(hdsl)); - DEBUG_ECHO_START(); DEBUG_ECHOLNF(hdsl); + #if EITHER(EEPROM_CHITCHAT, DEBUG_LEVELING_FEATURE) + FSTR_P const hdsl = F("Hardcoded Default Settings Loaded"); + TERN_(HOST_EEPROM_CHITCHAT, hostui.notify(hdsl)); + DEBUG_ECHO_START(); DEBUG_ECHOLNF(hdsl); + #endif TERN_(EXTENSIBLE_UI, ExtUI::onFactoryReset()); + + // + // Model predictive control + // + #if ENABLED(MPCTEMP) + constexpr float _mpc_heater_power[] = MPC_HEATER_POWER; + constexpr float _mpc_block_heat_capacity[] = MPC_BLOCK_HEAT_CAPACITY; + constexpr float _mpc_sensor_responsiveness[] = MPC_SENSOR_RESPONSIVENESS; + constexpr float _mpc_ambient_xfer_coeff[] = MPC_AMBIENT_XFER_COEFF; + #if ENABLED(MPC_INCLUDE_FAN) + constexpr float _mpc_ambient_xfer_coeff_fan255[] = MPC_AMBIENT_XFER_COEFF_FAN255; + #endif + + static_assert(COUNT(_mpc_heater_power) == HOTENDS, "MPC_HEATER_POWER must have HOTENDS items."); + static_assert(COUNT(_mpc_block_heat_capacity) == HOTENDS, "MPC_BLOCK_HEAT_CAPACITY must have HOTENDS items."); + static_assert(COUNT(_mpc_sensor_responsiveness) == HOTENDS, "MPC_SENSOR_RESPONSIVENESS must have HOTENDS items."); + static_assert(COUNT(_mpc_ambient_xfer_coeff) == HOTENDS, "MPC_AMBIENT_XFER_COEFF must have HOTENDS items."); + #if ENABLED(MPC_INCLUDE_FAN) + static_assert(COUNT(_mpc_ambient_xfer_coeff_fan255) == HOTENDS, "MPC_AMBIENT_XFER_COEFF_FAN255 must have HOTENDS items."); + #endif + + HOTEND_LOOP() { + thermalManager.temp_hotend[e].constants.heater_power = _mpc_heater_power[e]; + thermalManager.temp_hotend[e].constants.block_heat_capacity = _mpc_block_heat_capacity[e]; + thermalManager.temp_hotend[e].constants.sensor_responsiveness = _mpc_sensor_responsiveness[e]; + thermalManager.temp_hotend[e].constants.ambient_xfer_coeff_fan0 = _mpc_ambient_xfer_coeff[e]; + #if ENABLED(MPC_INCLUDE_FAN) + thermalManager.temp_hotend[e].constants.fan255_adjustment = _mpc_ambient_xfer_coeff_fan255[e] - _mpc_ambient_xfer_coeff[e]; + #endif + } + #endif } #if DISABLED(DISABLE_M503) @@ -3326,21 +3444,20 @@ void MarlinSettings::reset() { LOOP_L_N(px, GRID_MAX_POINTS_X) { CONFIG_ECHO_START(); SERIAL_ECHOPGM(" G29 W I", px, " J", py); - SERIAL_ECHOLNPAIR_F_P(SP_Z_STR, LINEAR_UNIT(z_values[px][py]), 5); + SERIAL_ECHOLNPAIR_F_P(SP_Z_STR, LINEAR_UNIT(Z_VALUES_ARR[px][py]), 5); } } } #endif - // TODO: Create G-code for settings - //#if ENABLED(X_AXIS_TWIST_COMPENSATION) - // CONFIG_ECHO_START(); - // xatc.print_points(); - //#endif - #endif // HAS_LEVELING + // + // X Axis Twist Compensation + // + TERN_(X_AXIS_TWIST_COMPENSATION, gcode.M423_report(forReplay)); + // // Editable Servo Angles // @@ -3473,7 +3590,7 @@ void MarlinSettings::reset() { // // Filament Runout Sensor // - TERN_(HAS_FILAMENT_SENSOR, gcode.M412_report(forReplay)); + TERN_(HAS_FILAMENT_SENSOR, gcode.M591_report(forReplay)); #if HAS_ETHERNET CONFIG_ECHO_HEADING("Ethernet"); @@ -3485,6 +3602,11 @@ void MarlinSettings::reset() { #endif TERN_(HAS_MULTI_LANGUAGE, gcode.M414_report(forReplay)); + + // + // Model predictive control + // + TERN_(MPCTEMP, gcode.M306_report(forReplay)); } #endif // !DISABLE_M503 diff --git a/Marlin/src/module/stepper.cpp b/Marlin/src/module/stepper.cpp index a96ed3a651..74246a3f10 100644 --- a/Marlin/src/module/stepper.cpp +++ b/Marlin/src/module/stepper.cpp @@ -113,7 +113,7 @@ Stepper stepper; // Singleton #include "../feature/mixing.h" #endif -#if HAS_FILAMENT_RUNOUT_DISTANCE +#if HAS_FILAMENT_SENSOR #include "../feature/runout.h" #endif @@ -189,7 +189,7 @@ bool Stepper::abort_current_block; uint32_t Stepper::acceleration_time, Stepper::deceleration_time; uint8_t Stepper::steps_per_isr; -#if HAS_FREEZE_PIN +#if ENABLED(FREEZE_FEATURE) bool Stepper::frozen; // = false #endif @@ -447,6 +447,18 @@ xyze_int8_t Stepper::count_direction{0}; #define K_APPLY_DIR(v,Q) K_DIR_WRITE(v) #define K_APPLY_STEP(v,Q) K_STEP_WRITE(v) #endif +#if HAS_U_AXIS + #define U_APPLY_DIR(v,Q) U_DIR_WRITE(v) + #define U_APPLY_STEP(v,Q) U_STEP_WRITE(v) +#endif +#if HAS_V_AXIS + #define V_APPLY_DIR(v,Q) V_DIR_WRITE(v) + #define V_APPLY_STEP(v,Q) V_STEP_WRITE(v) +#endif +#if HAS_W_AXIS + #define W_APPLY_DIR(v,Q) W_DIR_WRITE(v) + #define W_APPLY_STEP(v,Q) W_STEP_WRITE(v) +#endif #if DISABLED(MIXING_EXTRUDER) #define E_APPLY_STEP(v,Q) E_STEP_WRITE(stepper_extruder, v) @@ -486,9 +498,10 @@ xyze_int8_t Stepper::count_direction{0}; void Stepper::enable_axis(const AxisEnum axis) { #define _CASE_ENABLE(N) case N##_AXIS: ENABLE_AXIS_##N(); break; switch (axis) { - LINEAR_AXIS_CODE( + NUM_AXIS_CODE( _CASE_ENABLE(X), _CASE_ENABLE(Y), _CASE_ENABLE(Z), - _CASE_ENABLE(I), _CASE_ENABLE(J), _CASE_ENABLE(K) + _CASE_ENABLE(I), _CASE_ENABLE(J), _CASE_ENABLE(K), + _CASE_ENABLE(U), _CASE_ENABLE(V), _CASE_ENABLE(W) ); default: break; } @@ -497,14 +510,18 @@ void Stepper::enable_axis(const AxisEnum axis) { bool Stepper::disable_axis(const AxisEnum axis) { mark_axis_disabled(axis); + + TERN_(DWIN_LCD_PROUI, set_axis_untrusted(axis)); // MRISCOC workaround: https://github.com/MarlinFirmware/Marlin/issues/23095 + // If all the axes that share the enabled bit are disabled const bool can_disable = can_axis_disable(axis); if (can_disable) { #define _CASE_DISABLE(N) case N##_AXIS: DISABLE_AXIS_##N(); break; switch (axis) { - LINEAR_AXIS_CODE( + NUM_AXIS_CODE( _CASE_DISABLE(X), _CASE_DISABLE(Y), _CASE_DISABLE(Z), - _CASE_DISABLE(I), _CASE_DISABLE(J), _CASE_DISABLE(K) + _CASE_DISABLE(I), _CASE_DISABLE(J), _CASE_DISABLE(K), + _CASE_DISABLE(U), _CASE_DISABLE(V), _CASE_DISABLE(W) ); default: break; } @@ -547,9 +564,10 @@ bool Stepper::disable_axis(const AxisEnum axis) { void Stepper::enable_all_steppers() { TERN_(AUTO_POWER_CONTROL, powerManager.power_on()); - LINEAR_AXIS_CODE( + NUM_AXIS_CODE( enable_axis(X_AXIS), enable_axis(Y_AXIS), enable_axis(Z_AXIS), - enable_axis(I_AXIS), enable_axis(J_AXIS), enable_axis(K_AXIS) + enable_axis(I_AXIS), enable_axis(J_AXIS), enable_axis(K_AXIS), + enable_axis(U_AXIS), enable_axis(V_AXIS), enable_axis(W_AXIS) ); enable_e_steppers(); @@ -557,9 +575,10 @@ void Stepper::enable_all_steppers() { } void Stepper::disable_all_steppers() { - LINEAR_AXIS_CODE( + NUM_AXIS_CODE( disable_axis(X_AXIS), disable_axis(Y_AXIS), disable_axis(Z_AXIS), - disable_axis(I_AXIS), disable_axis(J_AXIS), disable_axis(K_AXIS) + disable_axis(I_AXIS), disable_axis(J_AXIS), disable_axis(K_AXIS), + disable_axis(U_AXIS), disable_axis(V_AXIS), disable_axis(W_AXIS) ); disable_e_steppers(); @@ -593,6 +612,9 @@ void Stepper::set_directions() { TERN_(HAS_I_DIR, SET_STEP_DIR(I)); TERN_(HAS_J_DIR, SET_STEP_DIR(J)); TERN_(HAS_K_DIR, SET_STEP_DIR(K)); + TERN_(HAS_U_DIR, SET_STEP_DIR(U)); + TERN_(HAS_V_DIR, SET_STEP_DIR(V)); + TERN_(HAS_W_DIR, SET_STEP_DIR(W)); #if DISABLED(LIN_ADVANCE) #if ENABLED(MIXING_EXTRUDER) @@ -1640,7 +1662,7 @@ void Stepper::pulse_phase_isr() { if (!current_block) return; // Skipping step processing causes motion to freeze - if (TERN0(HAS_FREEZE_PIN, frozen)) return; + if (TERN0(FREEZE_FEATURE, frozen)) return; // Count of pending loops and events for this iteration const uint32_t pending_events = step_event_count - step_events_completed; @@ -1813,6 +1835,15 @@ void Stepper::pulse_phase_isr() { #if HAS_K_STEP PULSE_PREP(K); #endif + #if HAS_U_STEP + PULSE_PREP(U); + #endif + #if HAS_V_STEP + PULSE_PREP(V); + #endif + #if HAS_W_STEP + PULSE_PREP(W); + #endif #if EITHER(LIN_ADVANCE, MIXING_EXTRUDER) delta_error.e += advance_dividend.e; @@ -1857,6 +1888,15 @@ void Stepper::pulse_phase_isr() { #if HAS_K_STEP PULSE_START(K); #endif + #if HAS_U_STEP + PULSE_START(U); + #endif + #if HAS_V_STEP + PULSE_START(V); + #endif + #if HAS_W_STEP + PULSE_START(W); + #endif #if DISABLED(LIN_ADVANCE) #if ENABLED(MIXING_EXTRUDER) @@ -1895,6 +1935,15 @@ void Stepper::pulse_phase_isr() { #if HAS_K_STEP PULSE_STOP(K); #endif + #if HAS_U_STEP + PULSE_STOP(U); + #endif + #if HAS_V_STEP + PULSE_STOP(V); + #endif + #if HAS_W_STEP + PULSE_STOP(W); + #endif #if DISABLED(LIN_ADVANCE) #if ENABLED(MIXING_EXTRUDER) @@ -1945,7 +1994,7 @@ uint32_t Stepper::block_phase_isr() { PAGE_SEGMENT_UPDATE_POS(E); } #endif - TERN_(HAS_FILAMENT_RUNOUT_DISTANCE, runout.block_completed(current_block)); + TERN_(HAS_FILAMENT_SENSOR, runout.block_completed(current_block)); discard_current_block(); } else { @@ -2240,13 +2289,16 @@ uint32_t Stepper::block_phase_isr() { #endif axis_bits_t axis_bits = 0; - LINEAR_AXIS_CODE( + NUM_AXIS_CODE( if (X_MOVE_TEST) SBI(axis_bits, A_AXIS), if (Y_MOVE_TEST) SBI(axis_bits, B_AXIS), if (Z_MOVE_TEST) SBI(axis_bits, C_AXIS), if (current_block->steps.i) SBI(axis_bits, I_AXIS), if (current_block->steps.j) SBI(axis_bits, J_AXIS), - if (current_block->steps.k) SBI(axis_bits, K_AXIS) + if (current_block->steps.k) SBI(axis_bits, K_AXIS), + if (current_block->steps.u) SBI(axis_bits, U_AXIS), + if (current_block->steps.v) SBI(axis_bits, V_AXIS), + if (current_block->steps.w) SBI(axis_bits, W_AXIS) ); //if (current_block->steps.e) SBI(axis_bits, E_AXIS); //if (current_block->steps.a) SBI(axis_bits, X_HEAD); @@ -2586,6 +2638,15 @@ void Stepper::init() { #if HAS_K_DIR K_DIR_INIT(); #endif + #if HAS_U_DIR + U_DIR_INIT(); + #endif + #if HAS_V_DIR + V_DIR_INIT(); + #endif + #if HAS_W_DIR + W_DIR_INIT(); + #endif #if HAS_E0_DIR E0_DIR_INIT(); #endif @@ -2656,6 +2717,18 @@ void Stepper::init() { K_ENABLE_INIT(); if (!K_ENABLE_ON) K_ENABLE_WRITE(HIGH); #endif + #if HAS_U_ENABLE + U_ENABLE_INIT(); + if (!U_ENABLE_ON) U_ENABLE_WRITE(HIGH); + #endif + #if HAS_V_ENABLE + V_ENABLE_INIT(); + if (!V_ENABLE_ON) V_ENABLE_WRITE(HIGH); + #endif + #if HAS_W_ENABLE + W_ENABLE_INIT(); + if (!W_ENABLE_ON) W_ENABLE_WRITE(HIGH); + #endif #if HAS_E0_ENABLE E0_ENABLE_INIT(); if (!E_ENABLE_ON) E0_ENABLE_WRITE(HIGH); @@ -2741,6 +2814,15 @@ void Stepper::init() { #if HAS_K_STEP AXIS_INIT(K, K); #endif + #if HAS_U_STEP + AXIS_INIT(U, U); + #endif + #if HAS_V_STEP + AXIS_INIT(V, V); + #endif + #if HAS_W_STEP + AXIS_INIT(W, W); + #endif #if E_STEPPERS && HAS_E0_STEP E_AXIS_INIT(0); @@ -2775,13 +2857,16 @@ void Stepper::init() { // Init direction bits for first moves set_directions(0 - LINEAR_AXIS_GANG( + NUM_AXIS_GANG( | TERN0(INVERT_X_DIR, _BV(X_AXIS)), | TERN0(INVERT_Y_DIR, _BV(Y_AXIS)), | TERN0(INVERT_Z_DIR, _BV(Z_AXIS)), | TERN0(INVERT_I_DIR, _BV(I_AXIS)), | TERN0(INVERT_J_DIR, _BV(J_AXIS)), - | TERN0(INVERT_K_DIR, _BV(K_AXIS)) + | TERN0(INVERT_K_DIR, _BV(K_AXIS)), + | TERN0(INVERT_U_DIR, _BV(U_AXIS)), + | TERN0(INVERT_V_DIR, _BV(V_AXIS)), + | TERN0(INVERT_W_DIR, _BV(W_AXIS)) ) ); @@ -2817,6 +2902,14 @@ void Stepper::_set_position(const abce_long_t &spos) { #elif ENABLED(MARKFORGED_YX) count_position.set(spos.a, spos.b - spos.a, spos.c); #endif + SECONDARY_AXIS_CODE( + count_position.i = spos.i, + count_position.j = spos.j, + count_position.k = spos.k, + count_position.u = spos.u, + count_position.v = spos.v, + count_position.w = spos.w + ); TERN_(HAS_EXTRUDERS, count_position.e = spos.e); #else // default non-h-bot planning @@ -2931,13 +3024,16 @@ int32_t Stepper::triggered_position(const AxisEnum axis) { void Stepper::report_a_position(const xyz_long_t &pos) { SERIAL_ECHOLNPGM_P( - LIST_N(DOUBLE(LINEAR_AXES), + LIST_N(DOUBLE(NUM_AXES), TERN(SAYS_A, PSTR(STR_COUNT_A), PSTR(STR_COUNT_X)), pos.x, TERN(SAYS_B, PSTR("B:"), SP_Y_LBL), pos.y, TERN(SAYS_C, PSTR("C:"), SP_Z_LBL), pos.z, SP_I_LBL, pos.i, SP_J_LBL, pos.j, - SP_K_LBL, pos.k + SP_K_LBL, pos.k, + SP_U_LBL, pos.u, + SP_V_LBL, pos.v, + SP_W_LBL, pos.w ) ); } @@ -3088,16 +3184,18 @@ void Stepper::report_positions() { const bool z_direction = direction ^ BABYSTEP_INVERT_Z; - LINEAR_AXIS_CODE( + NUM_AXIS_CODE( enable_axis(X_AXIS), enable_axis(Y_AXIS), enable_axis(Z_AXIS), - enable_axis(I_AXIS), enable_axis(J_AXIS), enable_axis(K_AXIS) + enable_axis(I_AXIS), enable_axis(J_AXIS), enable_axis(K_AXIS), + enable_axis(U_AXIS), enable_axis(V_AXIS), enable_axis(W_AXIS) ); DIR_WAIT_BEFORE(); - const xyz_byte_t old_dir = LINEAR_AXIS_ARRAY( + const xyz_byte_t old_dir = NUM_AXIS_ARRAY( X_DIR_READ(), Y_DIR_READ(), Z_DIR_READ(), - I_DIR_READ(), J_DIR_READ(), K_DIR_READ() + I_DIR_READ(), J_DIR_READ(), K_DIR_READ(), + U_DIR_READ(), V_DIR_READ(), W_DIR_READ() ); X_DIR_WRITE(INVERT_X_DIR ^ z_direction); @@ -3116,6 +3214,15 @@ void Stepper::report_positions() { #ifdef K_DIR_WRITE K_DIR_WRITE(INVERT_K_DIR ^ z_direction); #endif + #ifdef U_DIR_WRITE + U_DIR_WRITE(INVERT_U_DIR ^ z_direction); + #endif + #ifdef V_DIR_WRITE + V_DIR_WRITE(INVERT_V_DIR ^ z_direction); + #endif + #ifdef W_DIR_WRITE + W_DIR_WRITE(INVERT_W_DIR ^ z_direction); + #endif DIR_WAIT_AFTER(); @@ -3137,6 +3244,15 @@ void Stepper::report_positions() { #ifdef K_STEP_WRITE K_STEP_WRITE(!INVERT_K_STEP_PIN); #endif + #ifdef U_STEP_WRITE + U_STEP_WRITE(!INVERT_U_STEP_PIN); + #endif + #ifdef V_STEP_WRITE + V_STEP_WRITE(!INVERT_V_STEP_PIN); + #endif + #ifdef W_STEP_WRITE + W_STEP_WRITE(!INVERT_W_STEP_PIN); + #endif _PULSE_WAIT(); @@ -3156,6 +3272,15 @@ void Stepper::report_positions() { #ifdef K_STEP_WRITE K_STEP_WRITE(INVERT_K_STEP_PIN); #endif + #ifdef U_STEP_WRITE + U_STEP_WRITE(INVERT_U_STEP_PIN); + #endif + #ifdef V_STEP_WRITE + V_STEP_WRITE(INVERT_V_STEP_PIN); + #endif + #ifdef W_STEP_WRITE + W_STEP_WRITE(INVERT_W_STEP_PIN); + #endif // Restore direction bits EXTRA_DIR_WAIT_BEFORE(); @@ -3176,6 +3301,15 @@ void Stepper::report_positions() { #ifdef K_DIR_WRITE K_DIR_WRITE(old_dir.k); #endif + #ifdef U_DIR_WRITE + U_DIR_WRITE(old_dir.u); + #endif + #ifdef V_DIR_WRITE + V_DIR_WRITE(old_dir.v); + #endif + #ifdef W_DIR_WRITE + W_DIR_WRITE(old_dir.w); + #endif EXTRA_DIR_WAIT_AFTER(); @@ -3192,6 +3326,15 @@ void Stepper::report_positions() { #if HAS_K_AXIS case K_AXIS: BABYSTEP_AXIS(K, 0, direction); break; #endif + #if HAS_U_AXIS + case U_AXIS: BABYSTEP_AXIS(U, 0, direction); break; + #endif + #if HAS_V_AXIS + case V_AXIS: BABYSTEP_AXIS(V, 0, direction); break; + #endif + #if HAS_W_AXIS + case W_AXIS: BABYSTEP_AXIS(W, 0, direction); break; + #endif default: break; } @@ -3420,6 +3563,24 @@ void Stepper::report_positions() { SET_OUTPUT(K_MS3_PIN); #endif #endif + #if HAS_U_MS_PINS + SET_OUTPUT(U_MS1_PIN); SET_OUTPUT(U_MS2_PIN); + #if PIN_EXISTS(U_MS3) + SET_OUTPUT(U_MS3_PIN); + #endif + #endif + #if HAS_V_MS_PINS + SET_OUTPUT(V_MS1_PIN); SET_OUTPUT(V_MS2_PIN); + #if PIN_EXISTS(V_MS3) + SET_OUTPUT(V_MS3_PIN); + #endif + #endif + #if HAS_W_MS_PINS + SET_OUTPUT(W_MS1_PIN); SET_OUTPUT(W_MS2_PIN); + #if PIN_EXISTS(W_MS3) + SET_OUTPUT(W_MS3_PIN); + #endif + #endif #if HAS_E0_MS_PINS SET_OUTPUT(E0_MS1_PIN); SET_OUTPUT(E0_MS2_PIN); #if PIN_EXISTS(E0_MS3) @@ -3545,6 +3706,15 @@ void Stepper::report_positions() { #if HAS_K_MS_PINS case 13: WRITE(K_MS1_PIN, ms1); break #endif + #if HAS_U_MS_PINS + case 14: WRITE(U_MS1_PIN, ms1); break + #endif + #if HAS_V_MS_PINS + case 15: WRITE(V_MS1_PIN, ms1); break + #endif + #if HAS_W_MS_PINS + case 16: WRITE(W_MS1_PIN, ms1); break + #endif } if (ms2 >= 0) switch (driver) { #if HAS_X_MS_PINS || HAS_X2_MS_PINS @@ -3616,6 +3786,15 @@ void Stepper::report_positions() { #if HAS_K_MS_PINS case 13: WRITE(K_MS2_PIN, ms2); break #endif + #if HAS_U_MS_PINS + case 14: WRITE(U_MS2_PIN, ms2); break + #endif + #if HAS_V_MS_PINS + case 15: WRITE(V_MS2_PIN, ms2); break + #endif + #if HAS_W_MS_PINS + case 16: WRITE(W_MS2_PIN, ms2); break + #endif } if (ms3 >= 0) switch (driver) { #if HAS_X_MS_PINS || HAS_X2_MS_PINS @@ -3752,6 +3931,24 @@ void Stepper::report_positions() { PIN_CHAR(K_MS3); #endif #endif + #if HAS_U_MS_PINS + MS_LINE(U); + #if PIN_EXISTS(U_MS3) + PIN_CHAR(U_MS3); + #endif + #endif + #if HAS_V_MS_PINS + MS_LINE(V); + #if PIN_EXISTS(V_MS3) + PIN_CHAR(V_MS3); + #endif + #endif + #if HAS_W_MS_PINS + MS_LINE(W); + #if PIN_EXISTS(W_MS3) + PIN_CHAR(W_MS3); + #endif + #endif #if HAS_E0_MS_PINS MS_LINE(E0); #if PIN_EXISTS(E0_MS3) diff --git a/Marlin/src/module/stepper.h b/Marlin/src/module/stepper.h index 99aa714ca0..8cc8610fd4 100644 --- a/Marlin/src/module/stepper.h +++ b/Marlin/src/module/stepper.h @@ -159,12 +159,21 @@ #if HAS_K_STEP #define ISR_K_STEPPER_CYCLES ISR_STEPPER_CYCLES #endif +#if HAS_U_STEP + #define ISR_U_STEPPER_CYCLES ISR_STEPPER_CYCLES +#endif +#if HAS_V_STEP + #define ISR_V_STEPPER_CYCLES ISR_STEPPER_CYCLES +#endif +#if HAS_W_STEP + #define ISR_W_STEPPER_CYCLES ISR_STEPPER_CYCLES +#endif #if HAS_EXTRUDERS #define ISR_E_STEPPER_CYCLES ISR_STEPPER_CYCLES // E is always interpolated, even for mixing extruders #endif // And the total minimum loop time, not including the base -#define MIN_ISR_LOOP_CYCLES (ISR_MIXING_STEPPER_CYCLES LOGICAL_AXIS_GANG(+ ISR_E_STEPPER_CYCLES, + ISR_X_STEPPER_CYCLES, + ISR_Y_STEPPER_CYCLES, + ISR_Z_STEPPER_CYCLES, + ISR_I_STEPPER_CYCLES, + ISR_J_STEPPER_CYCLES, + ISR_K_STEPPER_CYCLES)) +#define MIN_ISR_LOOP_CYCLES (ISR_MIXING_STEPPER_CYCLES LOGICAL_AXIS_GANG(+ ISR_E_STEPPER_CYCLES, + ISR_X_STEPPER_CYCLES, + ISR_Y_STEPPER_CYCLES, + ISR_Z_STEPPER_CYCLES, + ISR_I_STEPPER_CYCLES, + ISR_J_STEPPER_CYCLES, + ISR_K_STEPPER_CYCLES, + ISR_U_STEPPER_CYCLES, + ISR_V_STEPPER_CYCLES, + ISR_W_STEPPER_CYCLES)) // Calculate the minimum MPU cycles needed per pulse to enforce, limited to the max stepper rate #define _MIN_STEPPER_PULSE_CYCLES(N) _MAX(uint32_t((F_CPU) / (MAXIMUM_STEPPER_RATE)), ((F_CPU) / 500000UL) * (N)) @@ -236,7 +245,7 @@ // Perhaps DISABLE_MULTI_STEPPING should be required with ADAPTIVE_STEP_SMOOTHING. #define MIN_STEP_ISR_FREQUENCY (MAX_STEP_ISR_FREQUENCY_1X / 2) -#define ENABLE_COUNT (LINEAR_AXES + E_STEPPERS) +#define ENABLE_COUNT (NUM_AXES + E_STEPPERS) typedef IF<(ENABLE_COUNT > 8), uint16_t, uint8_t>::type ena_mask_t; // Axis flags type, for enabled state or other simple state @@ -244,25 +253,25 @@ typedef struct { union { ena_mask_t bits; struct { - bool LINEAR_AXIS_LIST(X:1, Y:1, Z:1, I:1, J:1, K:1); + bool NUM_AXIS_LIST(X:1, Y:1, Z:1, I:1, J:1, K:1, U:1, V:1, W:1); #if HAS_EXTRUDERS bool LIST_N(EXTRUDERS, E0:1, E1:1, E2:1, E3:1, E4:1, E5:1, E6:1, E7:1); #endif }; }; - constexpr ena_mask_t linear_bits() { return _BV(LINEAR_AXES) - 1; } - constexpr ena_mask_t e_bits() { return (_BV(EXTRUDERS) - 1) << LINEAR_AXES; } + constexpr ena_mask_t linear_bits() { return _BV(NUM_AXES) - 1; } + constexpr ena_mask_t e_bits() { return (_BV(EXTRUDERS) - 1) << NUM_AXES; } } axis_flags_t; // All the stepper enable pins constexpr pin_t ena_pins[] = { - LINEAR_AXIS_LIST(X_ENABLE_PIN, Y_ENABLE_PIN, Z_ENABLE_PIN, I_ENABLE_PIN, J_ENABLE_PIN, K_ENABLE_PIN), + NUM_AXIS_LIST(X_ENABLE_PIN, Y_ENABLE_PIN, Z_ENABLE_PIN, I_ENABLE_PIN, J_ENABLE_PIN, K_ENABLE_PIN, U_ENABLE_PIN, V_ENABLE_PIN, W_ENABLE_PIN), LIST_N(E_STEPPERS, E0_ENABLE_PIN, E1_ENABLE_PIN, E2_ENABLE_PIN, E3_ENABLE_PIN, E4_ENABLE_PIN, E5_ENABLE_PIN, E6_ENABLE_PIN, E7_ENABLE_PIN) }; // Index of the axis or extruder element in a combined array constexpr uint8_t index_of_axis(const AxisEnum axis E_OPTARG(const uint8_t eindex=0)) { - return uint8_t(axis) + (E_TERN0(axis < LINEAR_AXES ? 0 : eindex)); + return uint8_t(axis) + (E_TERN0(axis < NUM_AXES ? 0 : eindex)); } //#define __IAX_N(N,V...) _IAX_##N(V) //#define _IAX_N(N,V...) __IAX_N(N,V) @@ -292,7 +301,7 @@ constexpr bool any_enable_overlap(const uint8_t a=0) { // (e.g., CoreXY, Dual XYZ, or E with multiple steppers, etc.). constexpr ena_mask_t enable_overlap[] = { #define _OVERLAP(N) ena_overlap(INDEX_OF_AXIS(AxisEnum(N))), - REPEAT(LINEAR_AXES, _OVERLAP) + REPEAT(NUM_AXES, _OVERLAP) #if HAS_EXTRUDERS #define _E_OVERLAP(N) ena_overlap(INDEX_OF_AXIS(E_AXIS, N)), REPEAT(E_STEPPERS, _E_OVERLAP) @@ -320,7 +329,7 @@ class Stepper { #ifndef MOTOR_CURRENT_PWM_FREQUENCY #define MOTOR_CURRENT_PWM_FREQUENCY 31400 #endif - #define MOTOR_CURRENT_COUNT LINEAR_AXES + #define MOTOR_CURRENT_COUNT NUM_AXES #elif HAS_MOTOR_CURRENT_SPI static constexpr uint32_t digipot_count[] = DIGIPOT_MOTOR_CURRENT; #define MOTOR_CURRENT_COUNT COUNT(Stepper::digipot_count) @@ -336,7 +345,7 @@ class Stepper { static constexpr uint8_t last_moved_extruder = 0; #endif - #if HAS_FREEZE_PIN + #if ENABLED(FREEZE_FEATURE) static bool frozen; // Set this flag to instantly freeze motion #endif diff --git a/Marlin/src/module/stepper/L64xx.cpp b/Marlin/src/module/stepper/L64xx.cpp index 27816fb4f7..5b60746396 100644 --- a/Marlin/src/module/stepper/L64xx.cpp +++ b/Marlin/src/module/stepper/L64xx.cpp @@ -64,6 +64,15 @@ #if AXIS_IS_L64XX(K) L64XX_CLASS(K) stepperK(L6470_CHAIN_SS_PIN); #endif +#if AXIS_IS_L64XX(U) + L64XX_CLASS(u) stepperU(L6470_CHAIN_SS_PIN); +#endif +#if AXIS_IS_L64XX(V) + L64XX_CLASS(v) stepperV(L6470_CHAIN_SS_PIN); +#endif +#if AXIS_IS_L64XX(W) + L64XX_CLASS(w) stepperW(L6470_CHAIN_SS_PIN); +#endif #if AXIS_IS_L64XX(E0) L64XX_CLASS(E0) stepperE0(L6470_CHAIN_SS_PIN); #endif @@ -217,6 +226,15 @@ void L64XX_Marlin::init_to_defaults() { #if AXIS_IS_L64XX(K) L6470_INIT_CHIP(K); #endif + #if AXIS_IS_L64XX(U) + L6470_INIT_CHIP(U); + #endif + #if AXIS_IS_L64XX(V) + L6470_INIT_CHIP(V); + #endif + #if AXIS_IS_L64XX(W) + L6470_INIT_CHIP(W); + #endif #if AXIS_IS_L64XX(E0) L6470_INIT_CHIP(E0); #endif diff --git a/Marlin/src/module/stepper/L64xx.h b/Marlin/src/module/stepper/L64xx.h index 9f7e6623b1..870b0414f8 100644 --- a/Marlin/src/module/stepper/L64xx.h +++ b/Marlin/src/module/stepper/L64xx.h @@ -266,6 +266,72 @@ #endif #endif +// U Stepper +#if HAS_U_AXIS + #if AXIS_IS_L64XX(U) + extern L64XX_CLASS(U) stepperU; + #define U_ENABLE_INIT() NOOP + #define U_ENABLE_WRITE(STATE) (STATE ? stepperU.hardStop() : stepperU.free()) + #define U_ENABLE_READ() (stepperU.getStatus() & STATUS_HIZ) + #if AXIS_DRIVER_TYPE_U(L6474) + #define U_DIR_INIT() SET_OUTPUT(U_DIR_PIN) + #define U_DIR_WRITE(STATE) L6474_DIR_WRITE(U, STATE) + #define U_DIR_READ() READ(U_DIR_PIN) + #else + #define U_DIR_INIT() NOOP + #define U_DIR_WRITE(STATE) L64XX_DIR_WRITE(U, STATE) + #define U_DIR_READ() (stepper##U.getStatus() & STATUS_DIR); + #if AXIS_DRIVER_TYPE_U(L6470) + #define DISABLE_STEPPER_U() stepperU.free() + #endif + #endif + #endif +#endif + +// V Stepper +#if HAS_V_AXIS + #if AXIS_IS_L64XX(V) + extern L64XX_CLASS(V) stepperV; + #define V_ENABLE_INIT() NOOP + #define V_ENABLE_WRITE(STATE) (STATE ? stepperV.hardStop() : stepperV.free()) + #define V_ENABLE_READ() (stepperV.getStatus() & STATUS_HIZ) + #if AXIS_DRIVER_TYPE_V(L6474) + #define V_DIR_INIT() SET_OUTPUT(V_DIR_PIN) + #define V_DIR_WRITE(STATE) L6474_DIR_WRITE(V, STATE) + #define V_DIR_READ() READ(V_DIR_PIN) + #else + #define V_DIR_INIT() NOOP + #define V_DIR_WRITE(STATE) L64XX_DIR_WRITE(V, STATE) + #define V_DIR_READ() (stepper##V.getStatus() & STATUS_DIR); + #if AXIS_DRIVER_TYPE_V(L6470) + #define DISABLE_STEPPER_V() stepperV.free() + #endif + #endif + #endif +#endif + +// W Stepper +#if HAS_W_AXIS + #if AXIS_IS_L64XX(W) + extern L64XX_CLASS(w) stepperW; + #define W_ENABLE_INIT() NOOP + #define W_ENABLE_WRITE(STATE) (STATE ? stepperW.hardStop() : stepperW.free()) + #define W_ENABLE_READ() (stepperW.getStatus() & STATUS_HIZ) + #if AXIS_DRIVER_TYPE_W(L6474) + #define W_DIR_INIT() SET_OUTPUT(W_DIR_PIN) + #define W_DIR_WRITE(STATE) L6474_DIR_WRITE(W, STATE) + #define W_DIR_READ() READ(W_DIR_PIN) + #else + #define W_DIR_INIT() NOOP + #define W_DIR_WRITE(STATE) L64XX_DIR_WRITE(W, STATE) + #define W_DIR_READ() (stepper##W.getStatus() & STATUS_DIR); + #if AXIS_DRIVER_TYPE_W(L6470) + #define DISABLE_STEPPER_W() stepperW.free() + #endif + #endif + #endif +#endif + // E0 Stepper #if AXIS_IS_L64XX(E0) extern L64XX_CLASS(E0) stepperE0; diff --git a/Marlin/src/module/stepper/TMC26X.cpp b/Marlin/src/module/stepper/TMC26X.cpp index 26f91bfeb9..52d84f8410 100644 --- a/Marlin/src/module/stepper/TMC26X.cpp +++ b/Marlin/src/module/stepper/TMC26X.cpp @@ -69,6 +69,15 @@ #if AXIS_DRIVER_TYPE_K(TMC26X) _TMC26X_DEFINE(K); #endif +#if AXIS_DRIVER_TYPE_U(TMC26X) + _TMC26X_DEFINE(U); +#endif +#if AXIS_DRIVER_TYPE_V(TMC26X) + _TMC26X_DEFINE(V); +#endif +#if AXIS_DRIVER_TYPE_W(TMC26X) + _TMC26X_DEFINE(W); +#endif #if AXIS_DRIVER_TYPE_E0(TMC26X) _TMC26X_DEFINE(E0); #endif @@ -133,6 +142,15 @@ void tmc26x_init_to_defaults() { #if AXIS_DRIVER_TYPE_K(TMC26X) _TMC26X_INIT(K); #endif + #if AXIS_DRIVER_TYPE_U(TMC26X) + _TMC26X_INIT(U); + #endif + #if AXIS_DRIVER_TYPE_V(TMC26X) + _TMC26X_INIT(V); + #endif + #if AXIS_DRIVER_TYPE_W(TMC26X) + _TMC26X_INIT(W); + #endif #if AXIS_DRIVER_TYPE_E0(TMC26X) _TMC26X_INIT(E0); #endif diff --git a/Marlin/src/module/stepper/TMC26X.h b/Marlin/src/module/stepper/TMC26X.h index 988bebe0f2..1fd94b26a8 100644 --- a/Marlin/src/module/stepper/TMC26X.h +++ b/Marlin/src/module/stepper/TMC26X.h @@ -123,6 +123,30 @@ void tmc26x_init_to_defaults(); #define K_ENABLE_READ() stepperK.isEnabled() #endif +// U Stepper +#if HAS_U_ENABLE && AXIS_DRIVER_TYPE_U(TMC26X) + extern TMC26XStepper stepperU; + #define U_ENABLE_INIT() NOOP + #define U_ENABLE_WRITE(STATE) stepperU.setEnabled(STATE) + #define U_ENABLE_READ() stepperU.isEnabled() +#endif + +// V Stepper +#if HAS_V_ENABLE && AXIS_DRIVER_TYPE_V(TMC26X) + extern TMC26XStepper stepperV; + #define V_ENABLE_INIT() NOOP + #define V_ENABLE_WRITE(STATE) stepperV.setEnabled(STATE) + #define V_ENABLE_READ() stepperV.isEnabled() +#endif + +// W Stepper +#if HAS_W_ENABLE && AXIS_DRIVER_TYPE_W(TMC26X) + extern TMC26XStepper stepperW; + #define W_ENABLE_INIT() NOOP + #define W_ENABLE_WRITE(STATE) stepperW.setEnabled(STATE) + #define W_ENABLE_READ() stepperW.isEnabled() +#endif + // E0 Stepper #if AXIS_DRIVER_TYPE_E0(TMC26X) extern TMC26XStepper stepperE0; diff --git a/Marlin/src/module/stepper/indirection.h b/Marlin/src/module/stepper/indirection.h index 7aea677534..879185ca14 100644 --- a/Marlin/src/module/stepper/indirection.h +++ b/Marlin/src/module/stepper/indirection.h @@ -262,6 +262,63 @@ void reset_stepper_drivers(); // Called by settings.load / settings.reset #define K_STEP_READ() bool(READ(K_STEP_PIN)) #endif +// U Stepper +#if HAS_U_AXIS + #ifndef U_ENABLE_INIT + #define U_ENABLE_INIT() SET_OUTPUT(U_ENABLE_PIN) + #define U_ENABLE_WRITE(STATE) WRITE(U_ENABLE_PIN,STATE) + #define U_ENABLE_READ() bool(READ(U_ENABLE_PIN)) + #endif + #ifndef U_DIR_INIT + #define U_DIR_INIT() SET_OUTPUT(U_DIR_PIN) + #define U_DIR_WRITE(STATE) WRITE(U_DIR_PIN,STATE) + #define U_DIR_READ() bool(READ(U_DIR_PIN)) + #endif + #define U_STEP_INIT() SET_OUTPUT(U_STEP_PIN) + #ifndef U_STEP_WRITE + #define U_STEP_WRITE(STATE) WRITE(U_STEP_PIN,STATE) + #endif + #define U_STEP_READ() bool(READ(U_STEP_PIN)) +#endif + +// V Stepper +#if HAS_V_AXIS + #ifndef V_ENABLE_INIT + #define V_ENABLE_INIT() SET_OUTPUT(V_ENABLE_PIN) + #define V_ENABLE_WRITE(STATE) WRITE(V_ENABLE_PIN,STATE) + #define V_ENABLE_READ() bool(READ(V_ENABLE_PIN)) + #endif + #ifndef V_DIR_INIT + #define V_DIR_INIT() SET_OUTPUT(V_DIR_PIN) + #define V_DIR_WRITE(STATE) WRITE(V_DIR_PIN,STATE) + #define V_DIR_READ() bool(READ(V_DIR_PIN)) + #endif + #define V_STEP_INIT() SET_OUTPUT(V_STEP_PIN) + #ifndef V_STEP_WRITE + #define V_STEP_WRITE(STATE) WRITE(V_STEP_PIN,STATE) + #endif + #define V_STEP_READ() bool(READ(V_STEP_PIN)) +#endif + +// W Stepper +#if HAS_W_AXIS + #ifndef W_ENABLE_INIT + #define W_ENABLE_INIT() SET_OUTPUT(W_ENABLE_PIN) + #define W_ENABLE_WRITE(STATE) WRITE(W_ENABLE_PIN,STATE) + #define W_ENABLE_READ() bool(READ(W_ENABLE_PIN)) + #endif + #ifndef W_DIR_INIT + #define W_DIR_INIT() SET_OUTPUT(W_DIR_PIN) + #define W_DIR_WRITE(STATE) WRITE(W_DIR_PIN,STATE) + #define W_DIR_READ() bool(READ(W_DIR_PIN)) + #endif + #define W_STEP_INIT() SET_OUTPUT(W_STEP_PIN) + #ifndef W_STEP_WRITE + #define W_STEP_WRITE(STATE) WRITE(W_STEP_PIN,STATE) + #endif + #define W_STEP_READ() bool(READ(W_STEP_PIN)) +#endif + // E0 Stepper #ifndef E0_ENABLE_INIT #define E0_ENABLE_INIT() SET_OUTPUT(E0_ENABLE_PIN) @@ -743,6 +800,51 @@ void reset_stepper_drivers(); // Called by settings.load / settings.reset #define DISABLE_STEPPER_K() TERN(HAS_K_ENABLE, K_ENABLE_WRITE(!K_ENABLE_ON), NOOP) #endif +#ifndef ENABLE_STEPPER_U + #if HAS_U_ENABLE + #define ENABLE_STEPPER_U() U_ENABLE_WRITE( U_ENABLE_ON) + #else + #define ENABLE_STEPPER_U() NOOP + #endif +#endif +#ifndef DISABLE_STEPPER_U + #if HAS_U_ENABLE + #define DISABLE_STEPPER_U() U_ENABLE_WRITE(!U_ENABLE_ON) + #else + #define DISABLE_STEPPER_U() NOOP + #endif +#endif + +#ifndef ENABLE_STEPPER_V + #if HAS_V_ENABLE + #define ENABLE_STEPPER_V() V_ENABLE_WRITE( V_ENABLE_ON) + #else + #define ENABLE_STEPPER_V() NOOP + #endif +#endif +#ifndef DISABLE_STEPPER_V + #if HAS_V_ENABLE + #define DISABLE_STEPPER_V() V_ENABLE_WRITE(!V_ENABLE_ON) + #else + #define DISABLE_STEPPER_V() NOOP + #endif +#endif + +#ifndef ENABLE_STEPPER_W + #if HAS_W_ENABLE + #define ENABLE_STEPPER_W() W_ENABLE_WRITE( W_ENABLE_ON) + #else + #define ENABLE_STEPPER_W() NOOP + #endif +#endif +#ifndef DISABLE_STEPPER_W + #if HAS_W_ENABLE + #define DISABLE_STEPPER_W() W_ENABLE_WRITE(!W_ENABLE_ON) + #else + #define DISABLE_STEPPER_W() NOOP + #endif +#endif + #ifndef ENABLE_STEPPER_E0 #define ENABLE_STEPPER_E0() TERN(HAS_E0_ENABLE, E0_ENABLE_WRITE( E_ENABLE_ON), NOOP) #endif @@ -917,6 +1019,28 @@ void reset_stepper_drivers(); // Called by settings.load / settings.reset #define DISABLE_AXIS_K() NOOP #endif +#if HAS_U_AXIS + #define ENABLE_AXIS_U() if (SHOULD_ENABLE(u)) { ENABLE_STEPPER_U(); AFTER_CHANGE(u, true); } + #define DISABLE_AXIS_U() if (SHOULD_DISABLE(u)) { DISABLE_STEPPER_U(); AFTER_CHANGE(u, false); set_axis_untrusted(U_AXIS); } +#else + #define ENABLE_AXIS_U() NOOP + #define DISABLE_AXIS_U() NOOP +#endif +#if HAS_V_AXIS + #define ENABLE_AXIS_V() if (SHOULD_ENABLE(v)) { ENABLE_STEPPER_V(); AFTER_CHANGE(v, true); } + #define DISABLE_AXIS_V() if (SHOULD_DISABLE(v)) { DISABLE_STEPPER_V(); AFTER_CHANGE(v, false); set_axis_untrusted(V_AXIS); } +#else + #define ENABLE_AXIS_V() NOOP + #define DISABLE_AXIS_V() NOOP +#endif +#if HAS_W_AXIS + #define ENABLE_AXIS_W() if (SHOULD_ENABLE(w)) { ENABLE_STEPPER_W(); AFTER_CHANGE(w, true); } + #define DISABLE_AXIS_W() if (SHOULD_DISABLE(w)) { DISABLE_STEPPER_W(); AFTER_CHANGE(w, false); set_axis_untrusted(W_AXIS); } +#else + #define ENABLE_AXIS_W() NOOP + #define DISABLE_AXIS_W() NOOP +#endif + // // Extruder steppers enable / disable macros // diff --git a/Marlin/src/module/stepper/trinamic.cpp b/Marlin/src/module/stepper/trinamic.cpp index 7baa2108f0..ee156a1986 100644 --- a/Marlin/src/module/stepper/trinamic.cpp +++ b/Marlin/src/module/stepper/trinamic.cpp @@ -36,7 +36,7 @@ #include enum StealthIndex : uint8_t { - LOGICAL_AXIS_LIST(STEALTH_AXIS_E, STEALTH_AXIS_X, STEALTH_AXIS_Y, STEALTH_AXIS_Z, STEALTH_AXIS_I, STEALTH_AXIS_J, STEALTH_AXIS_K) + LOGICAL_AXIS_LIST(STEALTH_AXIS_E, STEALTH_AXIS_X, STEALTH_AXIS_Y, STEALTH_AXIS_Z, STEALTH_AXIS_I, STEALTH_AXIS_J, STEALTH_AXIS_K, STEALTH_AXIS_U, STEALTH_AXIS_V, STEALTH_AXIS_W) }; #define TMC_INIT(ST, STEALTH_INDEX) tmc_init(stepper##ST, ST##_CURRENT, ST##_MICROSTEPS, ST##_HYBRID_THRESHOLD, stealthchop_by_axis[STEALTH_INDEX], chopper_timing_##ST, ST##_INTERPOLATE, ST##_HOLD_MULTIPLIER) @@ -106,6 +106,15 @@ enum StealthIndex : uint8_t { #if AXIS_HAS_SPI(K) TMC_SPI_DEFINE(K, K); #endif +#if AXIS_HAS_SPI(U) + TMC_SPI_DEFINE(U, U); +#endif +#if AXIS_HAS_SPI(V) + TMC_SPI_DEFINE(V, V); +#endif +#if AXIS_HAS_SPI(W) + TMC_SPI_DEFINE(W, W); +#endif #if AXIS_HAS_SPI(E0) TMC_SPI_DEFINE_E(0); #endif @@ -173,6 +182,15 @@ enum StealthIndex : uint8_t { #ifndef TMC_K_BAUD_RATE #define TMC_K_BAUD_RATE TMC_BAUD_RATE #endif +#ifndef TMC_U_BAUD_RATE + #define TMC_U_BAUD_RATE TMC_BAUD_RATE +#endif +#ifndef TMC_V_BAUD_RATE + #define TMC_V_BAUD_RATE TMC_BAUD_RATE +#endif +#ifndef TMC_W_BAUD_RATE + #define TMC_W_BAUD_RATE TMC_BAUD_RATE +#endif #ifndef TMC_E0_BAUD_RATE #define TMC_E0_BAUD_RATE TMC_BAUD_RATE #endif @@ -374,6 +392,32 @@ enum StealthIndex : uint8_t { #define K_HAS_SW_SERIAL 1 #endif #endif + #if AXIS_HAS_UART(U) + #ifdef U_HARDWARE_SERIAL + TMC_UART_DEFINE(HW, U, U); + #define U_HAS_HW_SERIAL 1 + #else + TMC_UART_DEFINE(SW, U, U); + #define U_HAS_SW_SERIAL 1 + #endif + #endif + #if AXIS_HAS_UART(V) + #ifdef V_HARDWARE_SERIAL + TMC_UART_DEFINE(HW, V, V); + #else + TMC_UART_DEFINE(SW, V, V); + #define V_HAS_SW_SERIAL 1 + #endif + #endif + #if AXIS_HAS_UART(W) + #ifdef W_HARDWARE_SERIAL + TMC_UART_DEFINE(HW, W, W); + #define W_HAS_HW_SERIAL 1 + #else + TMC_UART_DEFINE(SW, W, W); + #define W_HAS_SW_SERIAL 1 + #endif + #endif #if AXIS_HAS_UART(E0) #ifdef E0_HARDWARE_SERIAL @@ -449,7 +493,7 @@ enum StealthIndex : uint8_t { #endif #define _EN_ITEM(N) , E##N - enum TMCAxis : uint8_t { LINEAR_AXIS_LIST(X, Y, Z, I, J, K), X2, Y2, Z2, Z3, Z4 REPEAT(EXTRUDERS, _EN_ITEM), TOTAL }; + enum TMCAxis : uint8_t { NUM_AXIS_LIST(X, Y, Z, I, J, K, U, V, W), X2, Y2, Z2, Z3, Z4 REPEAT(EXTRUDERS, _EN_ITEM), TOTAL }; #undef _EN_ITEM void tmc_serial_begin() { @@ -543,6 +587,27 @@ enum StealthIndex : uint8_t { stepperK.beginSerial(TMC_BAUD_RATE); #endif #endif + #if AXIS_HAS_UART(U) + #ifdef U_HARDWARE_SERIAL + HW_SERIAL_BEGIN(U); + #else + stepperU.beginSerial(TMC_BAUD_RATE); + #endif + #endif + #if AXIS_HAS_UART(V) + #ifdef V_HARDWARE_SERIAL + HW_SERIAL_BEGIN(V); + #else + stepperV.beginSerial(TMC_BAUD_RATE); + #endif + #endif + #if AXIS_HAS_UART(W) + #ifdef W_HARDWARE_SERIAL + HW_SERIAL_BEGIN(W); + #else + stepperW.beginSerial(TMC_BAUD_RATE); + #endif + #endif #if AXIS_HAS_UART(E0) #ifdef E0_HARDWARE_SERIAL HW_SERIAL_BEGIN(E0); @@ -814,6 +879,15 @@ void restore_trinamic_drivers() { #if AXIS_IS_TMC(K) stepperK.push(); #endif + #if AXIS_IS_TMC(U) + stepperU.push(); + #endif + #if AXIS_IS_TMC(V) + stepperV.push(); + #endif + #if AXIS_IS_TMC(W) + stepperW.push(); + #endif #if AXIS_IS_TMC(E0) stepperE0.push(); #endif @@ -844,7 +918,8 @@ void reset_trinamic_drivers() { static constexpr bool stealthchop_by_axis[] = LOGICAL_AXIS_ARRAY( ENABLED(STEALTHCHOP_E), ENABLED(STEALTHCHOP_XY), ENABLED(STEALTHCHOP_XY), ENABLED(STEALTHCHOP_Z), - ENABLED(STEALTHCHOP_I), ENABLED(STEALTHCHOP_J), ENABLED(STEALTHCHOP_K) + ENABLED(STEALTHCHOP_I), ENABLED(STEALTHCHOP_J), ENABLED(STEALTHCHOP_K), + ENABLED(STEALTHCHOP_U), ENABLED(STEALTHCHOP_V), ENABLED(STEALTHCHOP_W) ); #if AXIS_IS_TMC(X) @@ -880,6 +955,15 @@ void reset_trinamic_drivers() { #if AXIS_IS_TMC(K) TMC_INIT(K, STEALTH_AXIS_K); #endif + #if AXIS_IS_TMC(U) + TMC_INIT(U, STEALTH_AXIS_U); + #endif + #if AXIS_IS_TMC(V) + TMC_INIT(V, STEALTH_AXIS_V); + #endif + #if AXIS_IS_TMC(W) + TMC_INIT(W, STEALTH_AXIS_W); + #endif #if AXIS_IS_TMC(E0) TMC_INIT(E0, STEALTH_AXIS_E); #endif @@ -906,49 +990,21 @@ void reset_trinamic_drivers() { #endif #if USE_SENSORLESS - #if X_SENSORLESS - stepperX.homing_threshold(X_STALL_SENSITIVITY); - #if AXIS_HAS_STALLGUARD(X2) - stepperX2.homing_threshold(CAT(TERN(X2_SENSORLESS, X2, X), _STALL_SENSITIVITY)); - #endif - #endif - #if Y_SENSORLESS - stepperY.homing_threshold(Y_STALL_SENSITIVITY); - #if AXIS_HAS_STALLGUARD(Y2) - stepperY2.homing_threshold(CAT(TERN(Y2_SENSORLESS, Y2, Y), _STALL_SENSITIVITY)); - #endif - #endif - #if Z_SENSORLESS - stepperZ.homing_threshold(Z_STALL_SENSITIVITY); - #if AXIS_HAS_STALLGUARD(Z2) - stepperZ2.homing_threshold(CAT(TERN(Z2_SENSORLESS, Z2, Z), _STALL_SENSITIVITY)); - #endif - #if AXIS_HAS_STALLGUARD(Z3) - stepperZ3.homing_threshold(CAT(TERN(Z3_SENSORLESS, Z3, Z), _STALL_SENSITIVITY)); - #endif - #if AXIS_HAS_STALLGUARD(Z4) - stepperZ4.homing_threshold(CAT(TERN(Z4_SENSORLESS, Z4, Z), _STALL_SENSITIVITY)); - #endif - #endif - #if I_SENSORLESS - stepperI.homing_threshold(I_STALL_SENSITIVITY); - #if AXIS_HAS_STALLGUARD(I) - stepperI.homing_threshold(CAT(TERN(I_SENSORLESS, I, I), _STALL_SENSITIVITY)); - #endif - #endif - #if J_SENSORLESS - stepperJ.homing_threshold(J_STALL_SENSITIVITY); - #if AXIS_HAS_STALLGUARD(J) - stepperJ.homing_threshold(CAT(TERN(J_SENSORLESS, J, J), _STALL_SENSITIVITY)); - #endif - #endif - #if K_SENSORLESS - stepperK.homing_threshold(K_STALL_SENSITIVITY); - #if AXIS_HAS_STALLGUARD(K) - stepperK.homing_threshold(CAT(TERN(K_SENSORLESS, K, K), _STALL_SENSITIVITY)); - #endif - #endif - #endif // USE SENSORLESS + TERN_(X_SENSORLESS, stepperX.homing_threshold(X_STALL_SENSITIVITY)); + TERN_(X2_SENSORLESS, stepperX2.homing_threshold(CAT(TERN(X2_SENSORLESS, X2, X), _STALL_SENSITIVITY))); + TERN_(Y_SENSORLESS, stepperY.homing_threshold(Y_STALL_SENSITIVITY)); + TERN_(Y2_SENSORLESS, stepperY2.homing_threshold(CAT(TERN(Y2_SENSORLESS, Y2, Y), _STALL_SENSITIVITY))); + TERN_(Z_SENSORLESS, stepperZ.homing_threshold(Z_STALL_SENSITIVITY)); + TERN_(Z2_SENSORLESS, stepperZ2.homing_threshold(CAT(TERN(Z2_SENSORLESS, Z2, Z), _STALL_SENSITIVITY))); + TERN_(Z3_SENSORLESS, stepperZ3.homing_threshold(CAT(TERN(Z3_SENSORLESS, Z3, Z), _STALL_SENSITIVITY))); + TERN_(Z4_SENSORLESS, stepperZ4.homing_threshold(CAT(TERN(Z4_SENSORLESS, Z4, Z), _STALL_SENSITIVITY))); + TERN_(I_SENSORLESS, stepperI.homing_threshold(I_STALL_SENSITIVITY)); + TERN_(J_SENSORLESS, stepperJ.homing_threshold(J_STALL_SENSITIVITY)); + TERN_(K_SENSORLESS, stepperK.homing_threshold(K_STALL_SENSITIVITY)); + TERN_(U_SENSORLESS, stepperU.homing_threshold(U_STALL_SENSITIVITY)); + TERN_(V_SENSORLESS, stepperV.homing_threshold(V_STALL_SENSITIVITY)); + TERN_(W_SENSORLESS, stepperW.homing_threshold(W_STALL_SENSITIVITY)); + #endif #ifdef TMC_ADV TMC_ADV() @@ -977,7 +1033,7 @@ void reset_trinamic_drivers() { TMC_HW_DETAIL(X), TMC_HW_DETAIL(X2), TMC_HW_DETAIL(Y), TMC_HW_DETAIL(Y2), TMC_HW_DETAIL(Z), TMC_HW_DETAIL(Z2), TMC_HW_DETAIL(Z3), TMC_HW_DETAIL(Z4), - TMC_HW_DETAIL(I), TMC_HW_DETAIL(J), TMC_HW_DETAIL(K), + TMC_HW_DETAIL(I), TMC_HW_DETAIL(J), TMC_HW_DETAIL(K), TMC_HW_DETAIL(U), TMC_HW_DETAIL(V), TMC_HW_DETAIL(W), TMC_HW_DETAIL(E0), TMC_HW_DETAIL(E1), TMC_HW_DETAIL(E2), TMC_HW_DETAIL(E3), TMC_HW_DETAIL(E4), TMC_HW_DETAIL(E5), TMC_HW_DETAIL(E6), TMC_HW_DETAIL(E7) }; @@ -1000,7 +1056,7 @@ void reset_trinamic_drivers() { SA_NO_TMC_HW_C(X); SA_NO_TMC_HW_C(X2); SA_NO_TMC_HW_C(Y); SA_NO_TMC_HW_C(Y2); SA_NO_TMC_HW_C(Z); SA_NO_TMC_HW_C(Z2); SA_NO_TMC_HW_C(Z3); SA_NO_TMC_HW_C(Z4); - SA_NO_TMC_HW_C(I); SA_NO_TMC_HW_C(J); SA_NO_TMC_HW_C(K); + SA_NO_TMC_HW_C(I); SA_NO_TMC_HW_C(J); SA_NO_TMC_HW_C(K); SA_NO_TMC_HW_C(U); SA_NO_TMC_HW_C(V); SA_NO_TMC_HW_C(W); SA_NO_TMC_HW_C(E0); SA_NO_TMC_HW_C(E1); SA_NO_TMC_HW_C(E2); SA_NO_TMC_HW_C(E3); SA_NO_TMC_HW_C(E4); SA_NO_TMC_HW_C(E5); SA_NO_TMC_HW_C(E6); SA_NO_TMC_HW_C(E7); #endif @@ -1012,7 +1068,7 @@ void reset_trinamic_drivers() { TMC_SW_DETAIL(X), TMC_SW_DETAIL(X2), TMC_SW_DETAIL(Y), TMC_SW_DETAIL(Y2), TMC_SW_DETAIL(Z), TMC_SW_DETAIL(Z2), TMC_SW_DETAIL(Z3), TMC_SW_DETAIL(Z4), - TMC_SW_DETAIL(I), TMC_SW_DETAIL(J), TMC_SW_DETAIL(K), + TMC_SW_DETAIL(I), TMC_SW_DETAIL(J), TMC_SW_DETAIL(K), TMC_SW_DETAIL(U), TMC_SW_DETAIL(V), TMC_SW_DETAIL(W), TMC_SW_DETAIL(E0), TMC_SW_DETAIL(E1), TMC_SW_DETAIL(E2), TMC_SW_DETAIL(E3), TMC_SW_DETAIL(E4), TMC_SW_DETAIL(E5), TMC_SW_DETAIL(E6), TMC_SW_DETAIL(E7) }; @@ -1030,7 +1086,7 @@ void reset_trinamic_drivers() { SA_NO_TMC_SW_C(X); SA_NO_TMC_SW_C(X2); SA_NO_TMC_SW_C(Y); SA_NO_TMC_SW_C(Y2); SA_NO_TMC_SW_C(Z); SA_NO_TMC_SW_C(Z2); SA_NO_TMC_SW_C(Z3); SA_NO_TMC_SW_C(Z4); - SA_NO_TMC_SW_C(I); SA_NO_TMC_SW_C(J); SA_NO_TMC_SW_C(K); + SA_NO_TMC_SW_C(I); SA_NO_TMC_SW_C(J); SA_NO_TMC_SW_C(K); SA_NO_TMC_SW_C(U); SA_NO_TMC_SW_C(V); SA_NO_TMC_SW_C(W); SA_NO_TMC_SW_C(E0); SA_NO_TMC_SW_C(E1); SA_NO_TMC_SW_C(E2); SA_NO_TMC_SW_C(E3); SA_NO_TMC_SW_C(E4); SA_NO_TMC_SW_C(E5); SA_NO_TMC_SW_C(E6); SA_NO_TMC_SW_C(E7); #endif diff --git a/Marlin/src/module/stepper/trinamic.h b/Marlin/src/module/stepper/trinamic.h index dd3a64240f..95bab7652c 100644 --- a/Marlin/src/module/stepper/trinamic.h +++ b/Marlin/src/module/stepper/trinamic.h @@ -49,6 +49,9 @@ #define TMC_I_LABEL 'I', '0' #define TMC_J_LABEL 'J', '0' #define TMC_K_LABEL 'K', '0' +#define TMC_U_LABEL 'U', '0' +#define TMC_V_LABEL 'V', '0' +#define TMC_W_LABEL 'W', '0' #define TMC_X2_LABEL 'X', '2' #define TMC_Y2_LABEL 'Y', '2' @@ -92,6 +95,15 @@ #if HAS_K_AXIS && !defined(CHOPPER_TIMING_K) #define CHOPPER_TIMING_K CHOPPER_TIMING #endif +#if HAS_U_AXIS && !defined(CHOPPER_TIMING_U) + #define CHOPPER_TIMING_U CHOPPER_TIMING +#endif +#if HAS_V_AXIS && !defined(CHOPPER_TIMING_V) + #define CHOPPER_TIMING_V CHOPPER_TIMING +#endif +#if HAS_W_AXIS && !defined(CHOPPER_TIMING_W) + #define CHOPPER_TIMING_W CHOPPER_TIMING +#endif #if HAS_EXTRUDERS && !defined(CHOPPER_TIMING_E) #define CHOPPER_TIMING_E CHOPPER_TIMING #endif @@ -274,6 +286,48 @@ void reset_trinamic_drivers(); #endif #endif +// U Stepper +#if AXIS_IS_TMC(U) + extern TMC_CLASS(U, U) stepperU; + static constexpr chopper_timing_t chopper_timing_U = CHOPPER_TIMING_U; + #if ENABLED(SOFTWARE_DRIVER_ENABLE) + #define U_ENABLE_INIT() NOOP + #define U_ENABLE_WRITE(STATE) stepperU.toff((STATE)==U_ENABLE_ON ? chopper_timing_U.toff : 0) + #define U_ENABLE_READ() stepperU.isEnabled() + #endif + #if AXIS_HAS_SQUARE_WAVE(U) + #define U_STEP_WRITE(STATE) do{ if(STATE) TOGGLE(U_STEP_PIN); }while(0) + #endif +#endif + +// V Stepper +#if AXIS_IS_TMC(V) + extern TMC_CLASS(V, V) stepperV; + static constexpr chopper_timing_t chopper_timing_V = CHOPPER_TIMING_V; + #if ENABLED(SOFTWARE_DRIVER_ENABLE) + #define V_ENABLE_INIT() NOOP + #define V_ENABLE_WRITE(STATE) stepperV.toff((STATE)==V_ENABLE_ON ? chopper_timing_V.toff : 0) + #define V_ENABLE_READ() stepperV.isEnabled() + #endif + #if AXIS_HAS_SQUARE_WAVE(V) + #define V_STEP_WRITE(STATE) do{ if(STATE) TOGGLE(V_STEP_PIN); }while(0) + #endif +#endif + +// W Stepper +#if AXIS_IS_TMC(W) + extern TMC_CLASS(W, W) stepperW; + static constexpr chopper_timing_t chopper_timing_W = CHOPPER_TIMING_W; + #if ENABLED(SOFTWARE_DRIVER_ENABLE) + #define W_ENABLE_INIT() NOOP + #define W_ENABLE_WRITE(STATE) stepperW.toff((STATE)==W_ENABLE_ON ? chopper_timing_W.toff : 0) + #define W_ENABLE_READ() stepperW.isEnabled() + #endif + #if AXIS_HAS_SQUARE_WAVE(W) + #define W_STEP_WRITE(STATE) do{ if(STATE) TOGGLE(W_STEP_PIN); }while(0) + #endif +#endif + // E0 Stepper #if AXIS_IS_TMC(E0) extern TMC_CLASS_E(0) stepperE0; diff --git a/Marlin/src/module/temperature.cpp b/Marlin/src/module/temperature.cpp index 19501bce6e..4bd43705ad 100644 --- a/Marlin/src/module/temperature.cpp +++ b/Marlin/src/module/temperature.cpp @@ -51,7 +51,7 @@ #if ENABLED(DWIN_CREALITY_LCD) #include "../lcd/e3v2/creality/dwin.h" -#elif ENABLED(DWIN_CREALITY_LCD_ENHANCED) +#elif ENABLED(DWIN_LCD_PROUI) #include "../lcd/e3v2/proui/dwin.h" #endif @@ -141,7 +141,8 @@ #endif #endif -#if ENABLED(PID_EXTRUSION_SCALING) +#if EITHER(MPCTEMP, PID_EXTRUSION_SCALING) + #include #include "stepper.h" #endif @@ -437,8 +438,8 @@ PGMSTR(str_t_heating_failed, STR_T_HEATING_FAILED); #if HAS_HEATED_BED bed_info_t Temperature::temp_bed; // = { 0 } // Init min and max temp with extreme values to prevent false errors during startup - int16_t Temperature::mintemp_raw_BED = TEMP_SENSOR_BED_RAW_LO_TEMP, - Temperature::maxtemp_raw_BED = TEMP_SENSOR_BED_RAW_HI_TEMP; + raw_adc_t Temperature::mintemp_raw_BED = TEMP_SENSOR_BED_RAW_LO_TEMP, + Temperature::maxtemp_raw_BED = TEMP_SENSOR_BED_RAW_HI_TEMP; TERN_(WATCH_BED, bed_watch_t Temperature::watch_bed); // = { 0 } IF_DISABLED(PIDTEMPBED, millis_t Temperature::next_bed_check_ms); #endif @@ -448,8 +449,8 @@ PGMSTR(str_t_heating_failed, STR_T_HEATING_FAILED); #if HAS_HEATED_CHAMBER millis_t next_cool_check_ms_2 = 0; celsius_float_t old_temp = 9999; - int16_t Temperature::mintemp_raw_CHAMBER = TEMP_SENSOR_CHAMBER_RAW_LO_TEMP, - Temperature::maxtemp_raw_CHAMBER = TEMP_SENSOR_CHAMBER_RAW_HI_TEMP; + raw_adc_t Temperature::mintemp_raw_CHAMBER = TEMP_SENSOR_CHAMBER_RAW_LO_TEMP, + Temperature::maxtemp_raw_CHAMBER = TEMP_SENSOR_CHAMBER_RAW_HI_TEMP; TERN_(WATCH_CHAMBER, chamber_watch_t Temperature::watch_chamber{0}); IF_DISABLED(PIDTEMPCHAMBER, millis_t Temperature::next_chamber_check_ms); #endif @@ -461,8 +462,8 @@ PGMSTR(str_t_heating_failed, STR_T_HEATING_FAILED); bool flag_cooler_state; //bool flag_cooler_excess = false; celsius_float_t previous_temp = 9999; - int16_t Temperature::mintemp_raw_COOLER = TEMP_SENSOR_COOLER_RAW_LO_TEMP, - Temperature::maxtemp_raw_COOLER = TEMP_SENSOR_COOLER_RAW_HI_TEMP; + raw_adc_t Temperature::mintemp_raw_COOLER = TEMP_SENSOR_COOLER_RAW_LO_TEMP, + Temperature::maxtemp_raw_COOLER = TEMP_SENSOR_COOLER_RAW_HI_TEMP; #if WATCH_COOLER cooler_watch_t Temperature::watch_cooler{0}; #endif @@ -477,8 +478,8 @@ PGMSTR(str_t_heating_failed, STR_T_HEATING_FAILED); #if HAS_TEMP_BOARD board_info_t Temperature::temp_board; // = { 0 } #if ENABLED(THERMAL_PROTECTION_BOARD) - int16_t Temperature::mintemp_raw_BOARD = TEMP_SENSOR_BOARD_RAW_LO_TEMP, - Temperature::maxtemp_raw_BOARD = TEMP_SENSOR_BOARD_RAW_HI_TEMP; + raw_adc_t Temperature::mintemp_raw_BOARD = TEMP_SENSOR_BOARD_RAW_LO_TEMP, + Temperature::maxtemp_raw_BOARD = TEMP_SENSOR_BOARD_RAW_HI_TEMP; #endif #endif @@ -503,11 +504,16 @@ PGMSTR(str_t_heating_failed, STR_T_HEATING_FAILED); volatile bool Temperature::raw_temps_ready = false; #if ENABLED(PID_EXTRUSION_SCALING) - int32_t Temperature::last_e_position, Temperature::lpq[LPQ_MAX_LEN]; + int32_t Temperature::pes_e_position, Temperature::lpq[LPQ_MAX_LEN]; lpq_ptr_t Temperature::lpq_ptr = 0; #endif +#if ENABLED(MPCTEMP) + int32_t Temperature::mpc_e_position; // = 0 +#endif + #define TEMPDIR(N) ((TEMP_SENSOR_##N##_RAW_LO_TEMP) < (TEMP_SENSOR_##N##_RAW_HI_TEMP) ? 1 : -1) +#define TP_CMP(S,A,B) (TEMPDIR(S) < 0 ? ((A)<(B)) : ((A)>(B))) #if HAS_HOTEND // Init mintemp and maxtemp with extreme values to prevent false errors during startup @@ -580,8 +586,8 @@ volatile bool Temperature::raw_temps_ready = false; PID_t tune_pid = { 0, 0, 0 }; celsius_float_t maxT = 0, minT = 10000; - const bool isbed = (heater_id == H_BED); - const bool ischamber = (heater_id == H_CHAMBER); + const bool isbed = (heater_id == H_BED), + ischamber = (heater_id == H_CHAMBER); #if ENABLED(PIDTEMPCHAMBER) #define C_TERN(T,A,B) ((T) ? (A) : (B)) @@ -623,12 +629,12 @@ volatile bool Temperature::raw_temps_ready = false; TERN_(HAS_FAN_LOGIC, fan_update_ms = next_temp_ms + fan_update_interval_ms); TERN_(EXTENSIBLE_UI, ExtUI::onPidTuning(ExtUI::result_t::PID_STARTED)); - TERN_(DWIN_CREALITY_LCD_ENHANCED, DWIN_PidTuning(isbed ? PID_BED_START : PID_EXTR_START)); + TERN_(DWIN_LCD_PROUI, DWIN_PidTuning(isbed ? PID_BED_START : PID_EXTR_START)); if (target > GHV(CHAMBER_MAX_TARGET, BED_MAX_TARGET, temp_range[heater_id].maxtemp - (HOTEND_OVERSHOOT))) { SERIAL_ECHOLNPGM(STR_PID_TEMP_TOO_HIGH); TERN_(EXTENSIBLE_UI, ExtUI::onPidTuning(ExtUI::result_t::PID_TEMP_TOO_HIGH)); - TERN_(DWIN_CREALITY_LCD_ENHANCED, DWIN_PidTuning(PID_TEMP_TOO_HIGH)); + TERN_(DWIN_LCD_PROUI, DWIN_PidTuning(PID_TEMP_TOO_HIGH)); TERN_(HOST_PROMPT_SUPPORT, hostui.notify(GET_TEXT_F(MSG_PID_TEMP_TOO_HIGH))); return; } @@ -650,7 +656,7 @@ volatile bool Temperature::raw_temps_ready = false; // PID Tuning loop wait_for_heatup = true; // Can be interrupted with M108 - TERN_(HAS_STATUS_MESSAGE, ui.set_status(F("Wait for heat up..."))); + LCD_MESSAGE(MSG_HEATING); while (wait_for_heatup) { const millis_t ms = millis(); @@ -719,7 +725,7 @@ volatile bool Temperature::raw_temps_ready = false; if (current_temp > target + MAX_OVERSHOOT_PID_AUTOTUNE) { SERIAL_ECHOLNPGM(STR_PID_TEMP_TOO_HIGH); TERN_(EXTENSIBLE_UI, ExtUI::onPidTuning(ExtUI::result_t::PID_TEMP_TOO_HIGH)); - TERN_(DWIN_CREALITY_LCD_ENHANCED, DWIN_PidTuning(PID_TEMP_TOO_HIGH)); + TERN_(DWIN_LCD_PROUI, DWIN_PidTuning(PID_TEMP_TOO_HIGH)); TERN_(HOST_PROMPT_SUPPORT, hostui.notify(GET_TEXT_F(MSG_PID_TEMP_TOO_HIGH))); break; } @@ -756,7 +762,7 @@ volatile bool Temperature::raw_temps_ready = false; #endif if ((ms - _MIN(t1, t2)) > (MAX_CYCLE_TIME_PID_AUTOTUNE * 60L * 1000L)) { TERN_(DWIN_CREALITY_LCD, DWIN_Popup_Temperature(0)); - TERN_(DWIN_CREALITY_LCD_ENHANCED, DWIN_PidTuning(PID_TUNING_TIMEOUT)); + TERN_(DWIN_LCD_PROUI, DWIN_PidTuning(PID_TUNING_TIMEOUT)); TERN_(EXTENSIBLE_UI, ExtUI::onPidTuning(ExtUI::result_t::PID_TUNING_TIMEOUT)); TERN_(HOST_PROMPT_SUPPORT, hostui.notify(GET_TEXT_F(MSG_PID_TIMEOUT))); SERIAL_ECHOLNPGM(STR_PID_TIMEOUT); @@ -812,7 +818,7 @@ volatile bool Temperature::raw_temps_ready = false; TERN_(PRINTER_EVENT_LEDS, printerEventLEDs.onPidTuningDone(color)); TERN_(EXTENSIBLE_UI, ExtUI::onPidTuning(ExtUI::result_t::PID_DONE)); - TERN_(DWIN_CREALITY_LCD_ENHANCED, DWIN_PidTuning(PID_DONE)); + TERN_(DWIN_LCD_PROUI, DWIN_PidTuning(PID_DONE)); goto EXIT_M303; } @@ -821,7 +827,7 @@ volatile bool Temperature::raw_temps_ready = false; hal.idletask(); // Run UI update - TERN(HAS_DWIN_E3V2_BASIC, DWIN_Update(), ui.update()); + TERN(DWIN_CREALITY_LCD, DWIN_Update(), ui.update()); } wait_for_heatup = false; @@ -830,7 +836,7 @@ volatile bool Temperature::raw_temps_ready = false; TERN_(PRINTER_EVENT_LEDS, printerEventLEDs.onPidTuningDone(color)); TERN_(EXTENSIBLE_UI, ExtUI::onPidTuning(ExtUI::result_t::PID_DONE)); - TERN_(DWIN_CREALITY_LCD_ENHANCED, DWIN_PidTuning(PID_DONE)); + TERN_(DWIN_LCD_PROUI, DWIN_PidTuning(PID_DONE)); EXIT_M303: TERN_(NO_FAN_SLOWING_IN_PID_TUNING, adaptive_fan_slowing = true); @@ -839,6 +845,198 @@ volatile bool Temperature::raw_temps_ready = false; #endif // HAS_PID_HEATING +#if ENABLED(MPCTEMP) + + void Temperature::MPC_autotune() { + auto housekeeping = [] (millis_t& ms, celsius_float_t& current_temp, millis_t& next_report_ms) { + ms = millis(); + + if (updateTemperaturesIfReady()) { // temp sample ready + current_temp = degHotend(active_extruder); + TERN_(HAS_FAN_LOGIC, manage_extruder_fans(ms)); + } + + if (ELAPSED(ms, next_report_ms)) { + next_report_ms += 1000UL; + SERIAL_ECHOLNPGM("Temperature ", current_temp); + } + + hal.idletask(); + }; + + SERIAL_ECHOLNPGM("Measuring MPC constants for E", active_extruder); + MPCHeaterInfo& hotend = temp_hotend[active_extruder]; + MPC_t& constants = hotend.constants; + + // move to center of bed, just above bed height and cool with max fan + SERIAL_ECHOLNPGM("Moving to tuning position"); + TERN_(HAS_FAN, zero_fan_speeds()); + disable_all_heaters(); + TERN_(HAS_FAN, set_fan_speed(ANY(MPC_FAN_0_ALL_HOTENDS, MPC_FAN_0_ACTIVE_HOTEND) ? 0 : active_extruder, 255)); + TERN_(HAS_FAN, planner.sync_fan_speeds(fan_speed)); + gcode.home_all_axes(true); + const xyz_pos_t tuningpos = MPC_TUNING_POS; + do_blocking_move_to(tuningpos); + + SERIAL_ECHOLNPGM("Cooling to ambient"); + millis_t ms = millis(), next_report_ms = ms, next_test_ms = ms + 10000UL; + celsius_float_t current_temp = degHotend(active_extruder), + ambient_temp = current_temp; + + wait_for_heatup = true; // Can be interrupted with M108 + while (wait_for_heatup) { + housekeeping(ms, current_temp, next_report_ms); + + if (ELAPSED(ms, next_test_ms)) { + if (current_temp >= ambient_temp) { + ambient_temp = (ambient_temp + current_temp) / 2.0f; + break; + } + ambient_temp = current_temp; + next_test_ms += 10000UL; + } + } + TERN_(HAS_FAN, set_fan_speed(ANY(MPC_FAN_0_ALL_HOTENDS, MPC_FAN_0_ACTIVE_HOTEND) ? 0 : active_extruder, 0)); + TERN_(HAS_FAN, planner.sync_fan_speeds(fan_speed)); + + hotend.modeled_ambient_temp = ambient_temp; + + SERIAL_ECHOLNPGM("Heating to 200C"); + hotend.soft_pwm_amount = MPC_MAX >> 1; + const millis_t heat_start_time = ms; + next_test_ms = ms; + celsius_float_t temp_samples[16]; + uint8_t sample_count = 0; + uint16_t sample_distance = 1; + float t1_time = 0; + + while (wait_for_heatup) { + housekeeping(ms, current_temp, next_report_ms); + + if (ELAPSED(ms, next_test_ms)) { + // record samples between 100C and 200C + if (current_temp >= 100.0f) { + // if there are too many samples, space them more widely + if (sample_count == COUNT(temp_samples)) { + for (uint8_t i = 0; i < COUNT(temp_samples) / 2; i++) + temp_samples[i] = temp_samples[i*2]; + sample_count /= 2; + sample_distance *= 2; + } + + if (sample_count == 0) t1_time = float(ms - heat_start_time) / 1000.0f; + temp_samples[sample_count++] = current_temp; + } + + if (current_temp >= 200.0f) break; + + next_test_ms += 1000UL * sample_distance; + } + } + hotend.soft_pwm_amount = 0; + + // calculate physical constants from three equally spaced samples + sample_count = (sample_count + 1) / 2 * 2 - 1; + const float t1 = temp_samples[0], + t2 = temp_samples[(sample_count - 1) >> 1], + t3 = temp_samples[sample_count - 1], + asymp_temp = (t2 * t2 - t1 * t3) / (2 * t2 - t1 - t3), + block_responsiveness = -log((t2 - asymp_temp) / (t1 - asymp_temp)) / (sample_distance * (sample_count >> 1)); + + constants.ambient_xfer_coeff_fan0 = constants.heater_power * MPC_MAX / 255 / (asymp_temp - ambient_temp); + constants.fan255_adjustment = 0.0f; + constants.block_heat_capacity = constants.ambient_xfer_coeff_fan0 / block_responsiveness; + constants.sensor_responsiveness = block_responsiveness / (1.0f - (ambient_temp - asymp_temp) * exp(-block_responsiveness * t1_time) / (t1 - asymp_temp)); + + hotend.modeled_block_temp = asymp_temp + (ambient_temp - asymp_temp) * exp(-block_responsiveness * (ms - heat_start_time) / 1000.0f); + hotend.modeled_sensor_temp = current_temp; + + // let the system stabilise under MPC control then get a better measure of ambient loss without and with fan + SERIAL_ECHOLNPGM("Measuring ambient heatloss at target ", hotend.modeled_block_temp); + hotend.target = hotend.modeled_block_temp; + next_test_ms = ms + MPC_dT * 1000; + constexpr millis_t settle_time = 20000UL, + test_length = 20000UL; + millis_t settle_end_ms = ms + settle_time, + test_end_ms = settle_end_ms + test_length; + float total_energy_fan0 = 0.0f; + #if HAS_FAN + bool fan0_done = false; + float total_energy_fan255 = 0.0f; + #endif + float last_temp = current_temp; + + while (wait_for_heatup) { + housekeeping(ms, current_temp, next_report_ms); + + if (ELAPSED(ms, next_test_ms)) { + // use MPC to control the temperature, let it settle for 30s and then track power output for 10s + hotend.soft_pwm_amount = (int)get_pid_output_hotend(active_extruder) >> 1; + + if (ELAPSED(ms, settle_end_ms) && !ELAPSED(ms, test_end_ms) && TERN1(HAS_FAN, !fan0_done)) + total_energy_fan0 += constants.heater_power * hotend.soft_pwm_amount / 127 * MPC_dT + (last_temp - current_temp) * constants.block_heat_capacity; + #if HAS_FAN + else if (ELAPSED(ms, test_end_ms) && !fan0_done) { + SERIAL_ECHOLNPGM("Measuring ambient heatloss with full fan"); + set_fan_speed(ANY(MPC_FAN_0_ALL_HOTENDS, MPC_FAN_0_ACTIVE_HOTEND) ? 0 : active_extruder, 255); + planner.sync_fan_speeds(fan_speed); + settle_end_ms = ms + settle_time; + test_end_ms = settle_end_ms + test_length; + fan0_done = true; + } + else if (ELAPSED(ms, settle_end_ms) && !ELAPSED(ms, test_end_ms)) + total_energy_fan255 += constants.heater_power * hotend.soft_pwm_amount / 127 * MPC_dT + (last_temp - current_temp) * constants.block_heat_capacity; + #endif + else if (ELAPSED(ms, test_end_ms)) break; + + last_temp = current_temp; + next_test_ms += MPC_dT * 1000; + } + + if (!WITHIN(current_temp, hotend.target - 15.0f, hotend.target + 15.0f)) { + SERIAL_ECHOLNPGM("Temperature error while measuring ambient loss"); + break; + } + } + + const float power_fan0 = total_energy_fan0 * 1000 / test_length; + constants.ambient_xfer_coeff_fan0 = power_fan0 / (hotend.target - ambient_temp); + + #if HAS_FAN + const float power_fan255 = total_energy_fan255 * 1000 / test_length, + ambient_xfer_coeff_fan255 = power_fan255 / (hotend.target - ambient_temp); + constants.fan255_adjustment = ambient_xfer_coeff_fan255 - constants.ambient_xfer_coeff_fan0; + #endif + + hotend.target = 0.0f; + hotend.soft_pwm_amount = 0; + TERN_(HAS_FAN, set_fan_speed(ANY(MPC_FAN_0_ALL_HOTENDS, MPC_FAN_0_ACTIVE_HOTEND) ? 0 : active_extruder, 0)); + TERN_(HAS_FAN, planner.sync_fan_speeds(fan_speed)); + + if (!wait_for_heatup) SERIAL_ECHOLNPGM("Test was interrupted"); + + wait_for_heatup = false; + + SERIAL_ECHOLNPGM("Done"); + + /* <-- add a slash to enable + SERIAL_ECHOLNPGM("t1_time ", t1_time); + SERIAL_ECHOLNPGM("sample_count ", sample_count); + SERIAL_ECHOLNPGM("sample_distance ", sample_distance); + for (uint8_t i = 0; i < sample_count; i++) + SERIAL_ECHOLNPGM("sample ", i, " : ", temp_samples[i]); + SERIAL_ECHOLNPGM("t1 ", t1, " t2 ", t2, " t3 ", t3); + SERIAL_ECHOLNPGM("asymp_temp ", asymp_temp); + SERIAL_ECHOLNPAIR_F("block_responsiveness ", block_responsiveness, 4); + //*/ + SERIAL_ECHOLNPGM("MPC_BLOCK_HEAT_CAPACITY ", constants.block_heat_capacity); + SERIAL_ECHOLNPAIR_F("MPC_SENSOR_RESPONSIVENESS ", constants.sensor_responsiveness, 4); + SERIAL_ECHOLNPAIR_F("MPC_AMBIENT_XFER_COEFF ", constants.ambient_xfer_coeff_fan0, 4); + TERN_(HAS_FAN, SERIAL_ECHOLNPAIR_F("MPC_AMBIENT_XFER_COEFF_FAN255 ", ambient_xfer_coeff_fan255, 4)); + } + +#endif // MPCTEMP + int16_t Temperature::getHeaterPower(const heater_id_t heater_id) { switch (heater_id) { #if HAS_HEATED_BED @@ -1098,7 +1296,7 @@ void Temperature::min_temp_error(const heater_id_t heater_id) { pid_reset[ee] = true; } else if (pid_error > PID_FUNCTIONAL_RANGE) { - pid_output = BANG_MAX; + pid_output = PID_MAX; pid_reset[ee] = true; } else { @@ -1125,9 +1323,9 @@ void Temperature::min_temp_error(const heater_id_t heater_id) { work_pid[ee].Kc = 0; if (this_hotend) { const long e_position = stepper.position(E_AXIS); - if (e_position > last_e_position) { - lpq[lpq_ptr] = e_position - last_e_position; - last_e_position = e_position; + if (e_position > pes_e_position) { + lpq[lpq_ptr] = e_position - pes_e_position; + pes_e_position = e_position; } else lpq[lpq_ptr] = 0; @@ -1170,7 +1368,86 @@ void Temperature::min_temp_error(const heater_id_t heater_id) { } #endif - #else // No PID enabled + #elif ENABLED(MPCTEMP) + MPCHeaterInfo& hotend = temp_hotend[ee]; + MPC_t& constants = hotend.constants; + + // At startup, initialize modeled temperatures + if (isnan(hotend.modeled_block_temp)) { + hotend.modeled_ambient_temp = min(30.0f, hotend.celsius); // cap initial value at reasonable max room temperature of 30C + hotend.modeled_block_temp = hotend.modeled_sensor_temp = hotend.celsius; + } + + #if HOTENDS == 1 + constexpr bool this_hotend = true; + #else + const bool this_hotend = (ee == active_extruder); + #endif + + float ambient_xfer_coeff = constants.ambient_xfer_coeff_fan0; + #if ENABLED(MPC_INCLUDE_FAN) + const uint8_t fan_index = ANY(MPC_FAN_0_ACTIVE_HOTEND, MPC_FAN_0_ALL_HOTENDS) ? 0 : ee; + const float fan_fraction = TERN_(MPC_FAN_0_ACTIVE_HOTEND, !this_hotend ? 0.0f : ) fan_speed[fan_index] * RECIPROCAL(255); + ambient_xfer_coeff += fan_fraction * constants.fan255_adjustment; + #endif + + if (this_hotend) { + const int32_t e_position = stepper.position(E_AXIS); + const float e_speed = (e_position - mpc_e_position) * planner.mm_per_step[E_AXIS] / MPC_dT; + + // the position can appear to make big jumps when, e.g. homing + if (fabs(e_speed) > planner.settings.max_feedrate_mm_s[E_AXIS]) + mpc_e_position = e_position; + else if (e_speed > 0.0f) { // ignore retract/recover moves + ambient_xfer_coeff += e_speed * FILAMENT_HEAT_CAPACITY_PERMM; + mpc_e_position = e_position; + } + } + + // update the modeled temperatures + float blocktempdelta = hotend.soft_pwm_amount * constants.heater_power * (MPC_dT / 127) / constants.block_heat_capacity; + blocktempdelta += (hotend.modeled_ambient_temp - hotend.modeled_block_temp) * ambient_xfer_coeff * MPC_dT / constants.block_heat_capacity; + hotend.modeled_block_temp += blocktempdelta; + + const float sensortempdelta = (hotend.modeled_block_temp - hotend.modeled_sensor_temp) * (constants.sensor_responsiveness * MPC_dT); + hotend.modeled_sensor_temp += sensortempdelta; + + // Any delta between hotend.modeled_sensor_temp and hotend.celsius is either model + // error diverging slowly or (fast) noise. Slowly correct towards this temperature and noise will average out. + const float delta_to_apply = (hotend.celsius - hotend.modeled_sensor_temp) * (MPC_SMOOTHING_FACTOR); + hotend.modeled_block_temp += delta_to_apply; + hotend.modeled_sensor_temp += delta_to_apply; + + // only correct ambient when close to steady state (output power is not clipped or asymptotic temperature is reached) + if (WITHIN(hotend.soft_pwm_amount, 1, 126) || fabs(blocktempdelta + delta_to_apply) < (MPC_STEADYSTATE * MPC_dT)) + hotend.modeled_ambient_temp += delta_to_apply > 0.f ? max(delta_to_apply, MPC_MIN_AMBIENT_CHANGE * MPC_dT) : min(delta_to_apply, -MPC_MIN_AMBIENT_CHANGE * MPC_dT); + + float power = 0.0; + if (hotend.target != 0 && TERN1(HEATER_IDLE_HANDLER, !heater_idle[ee].timed_out)) { + // plan power level to get to target temperature in 2 seconds + power = (hotend.target - hotend.modeled_block_temp) * constants.block_heat_capacity / 2.0f; + power -= (hotend.modeled_ambient_temp - hotend.modeled_block_temp) * ambient_xfer_coeff; + } + + float pid_output = power * 254.0f / constants.heater_power + 1.0f; // ensure correct quantization into a range of 0 to 127 + pid_output = constrain(pid_output, 0, MPC_MAX); + + /* <-- add a slash to enable + static uint32_t nexttime = millis() + 1000; + if (ELAPSED(millis(), nexttime)) { + nexttime += 1000; + SERIAL_ECHOLNPGM("block temp ", hotend.modeled_block_temp, + ", celsius ", hotend.celsius, + ", blocktempdelta ", blocktempdelta, + ", delta_to_apply ", delta_to_apply, + ", ambient ", hotend.modeled_ambient_temp, + ", power ", power, + ", pid_output ", pid_output, + ", pwm ", (int)pid_output >> 1); + } + //*/ + + #else // No PID or MPC enabled const bool is_idling = TERN0(HEATER_IDLE_HANDLER, heater_idle[ee].timed_out); const float pid_output = (!is_idling && temp_hotend[ee].celsius < temp_hotend[ee].target) ? BANG_MAX : 0; @@ -1689,8 +1966,8 @@ void Temperature::manage_heater() { m = (l + r) >> 1; \ if (!m) return celsius_t(pgm_read_word(&TBL[0].celsius)); \ if (m == l || m == r) return celsius_t(pgm_read_word(&TBL[LEN-1].celsius)); \ - int16_t v00 = pgm_read_word(&TBL[m-1].value), \ - v10 = pgm_read_word(&TBL[m-0].value); \ + raw_adc_t v00 = pgm_read_word(&TBL[m-1].value), \ + v10 = pgm_read_word(&TBL[m-0].value); \ if (raw < v00) r = m; \ else if (raw > v10) l = m; \ else { \ @@ -1784,7 +2061,7 @@ void Temperature::manage_heater() { SERIAL_EOL(); } - celsius_float_t Temperature::user_thermistor_to_deg_c(const uint8_t t_index, const int16_t raw) { + celsius_float_t Temperature::user_thermistor_to_deg_c(const uint8_t t_index, const raw_adc_t raw) { if (!WITHIN(t_index, 0, COUNT(user_thermistor) - 1)) return 25; @@ -1799,8 +2076,8 @@ void Temperature::manage_heater() { } // maximum adc value .. take into account the over sampling - const int adc_max = MAX_RAW_THERMISTOR_VALUE, - adc_raw = constrain(raw, 1, adc_max - 1); // constrain to prevent divide-by-zero + constexpr raw_adc_t adc_max = MAX_RAW_THERMISTOR_VALUE; + const raw_adc_t adc_raw = constrain(raw, 1, adc_max - 1); // constrain to prevent divide-by-zero const float adc_inverse = (adc_max - adc_raw) - 0.5f, resistance = t.series_res * (adc_raw + 0.5f) / adc_inverse, @@ -1820,7 +2097,7 @@ void Temperature::manage_heater() { #if HAS_HOTEND // Derived from RepRap FiveD extruder::getTemperature() // For hot end temperature measurement. - celsius_float_t Temperature::analog_to_celsius_hotend(const int16_t raw, const uint8_t e) { + celsius_float_t Temperature::analog_to_celsius_hotend(const raw_adc_t raw, const uint8_t e) { if (e >= HOTENDS) { SERIAL_ERROR_START(); SERIAL_ECHO(e); @@ -1836,11 +2113,11 @@ void Temperature::manage_heater() { #elif TEMP_SENSOR_0_IS_MAX_TC #if TEMP_SENSOR_0_IS_MAX31865 return TERN(LIB_INTERNAL_MAX31865, - max31865_0.temperature((uint16_t)raw), + max31865_0.temperature(raw), max31865_0.temperature(MAX31865_SENSOR_OHMS_0, MAX31865_CALIBRATION_OHMS_0) ); #else - return raw * 0.25; + return (int16_t)raw * 0.25; #endif #elif TEMP_SENSOR_0_IS_AD595 return TEMP_AD595(raw); @@ -1855,11 +2132,11 @@ void Temperature::manage_heater() { #elif TEMP_SENSOR_1_IS_MAX_TC #if TEMP_SENSOR_0_IS_MAX31865 return TERN(LIB_INTERNAL_MAX31865, - max31865_1.temperature((uint16_t)raw), + max31865_1.temperature(raw), max31865_1.temperature(MAX31865_SENSOR_OHMS_1, MAX31865_CALIBRATION_OHMS_1) ); #else - return raw * 0.25; + return (int16_t)raw * 0.25; #endif #elif TEMP_SENSOR_1_IS_AD595 return TEMP_AD595(raw); @@ -1943,7 +2220,7 @@ void Temperature::manage_heater() { #if HAS_HEATED_BED // For bed temperature measurement. - celsius_float_t Temperature::analog_to_celsius_bed(const int16_t raw) { + celsius_float_t Temperature::analog_to_celsius_bed(const raw_adc_t raw) { #if TEMP_SENSOR_BED_IS_CUSTOM return user_thermistor_to_deg_c(CTI_BED, raw); #elif TEMP_SENSOR_BED_IS_THERMISTOR @@ -1961,7 +2238,7 @@ void Temperature::manage_heater() { #if HAS_TEMP_CHAMBER // For chamber temperature measurement. - celsius_float_t Temperature::analog_to_celsius_chamber(const int16_t raw) { + celsius_float_t Temperature::analog_to_celsius_chamber(const raw_adc_t raw) { #if TEMP_SENSOR_CHAMBER_IS_CUSTOM return user_thermistor_to_deg_c(CTI_CHAMBER, raw); #elif TEMP_SENSOR_CHAMBER_IS_THERMISTOR @@ -1979,7 +2256,7 @@ void Temperature::manage_heater() { #if HAS_TEMP_COOLER // For cooler temperature measurement. - celsius_float_t Temperature::analog_to_celsius_cooler(const int16_t raw) { + celsius_float_t Temperature::analog_to_celsius_cooler(const raw_adc_t raw) { #if TEMP_SENSOR_COOLER_IS_CUSTOM return user_thermistor_to_deg_c(CTI_COOLER, raw); #elif TEMP_SENSOR_COOLER_IS_THERMISTOR @@ -1997,7 +2274,7 @@ void Temperature::manage_heater() { #if HAS_TEMP_PROBE // For probe temperature measurement. - celsius_float_t Temperature::analog_to_celsius_probe(const int16_t raw) { + celsius_float_t Temperature::analog_to_celsius_probe(const raw_adc_t raw) { #if TEMP_SENSOR_PROBE_IS_CUSTOM return user_thermistor_to_deg_c(CTI_PROBE, raw); #elif TEMP_SENSOR_PROBE_IS_THERMISTOR @@ -2015,7 +2292,7 @@ void Temperature::manage_heater() { #if HAS_TEMP_BOARD // For motherboard temperature measurement. - celsius_float_t Temperature::analog_to_celsius_board(const int16_t raw) { + celsius_float_t Temperature::analog_to_celsius_board(const raw_adc_t raw) { #if TEMP_SENSOR_BOARD_IS_CUSTOM return user_thermistor_to_deg_c(CTI_BOARD, raw); #elif TEMP_SENSOR_BOARD_IS_THERMISTOR @@ -2033,13 +2310,13 @@ void Temperature::manage_heater() { #if HAS_TEMP_REDUNDANT // For redundant temperature measurement. - celsius_float_t Temperature::analog_to_celsius_redundant(const int16_t raw) { + celsius_float_t Temperature::analog_to_celsius_redundant(const raw_adc_t raw) { #if TEMP_SENSOR_REDUNDANT_IS_CUSTOM return user_thermistor_to_deg_c(CTI_REDUNDANT, raw); #elif TEMP_SENSOR_REDUNDANT_IS_MAX_TC && REDUNDANT_TEMP_MATCH(SOURCE, E0) - return TERN(TEMP_SENSOR_REDUNDANT_IS_MAX31865, max31865_0.temperature((uint16_t)raw), raw * 0.25); + return TERN(TEMP_SENSOR_REDUNDANT_IS_MAX31865, max31865_0.temperature(raw), (int16_t)raw * 0.25); #elif TEMP_SENSOR_REDUNDANT_IS_MAX_TC && REDUNDANT_TEMP_MATCH(SOURCE, E1) - return TERN(TEMP_SENSOR_REDUNDANT_IS_MAX31865, max31865_1.temperature((uint16_t)raw), raw * 0.25); + return TERN(TEMP_SENSOR_REDUNDANT_IS_MAX31865, max31865_1.temperature(raw), (int16_t)raw * 0.25); #elif TEMP_SENSOR_REDUNDANT_IS_THERMISTOR SCAN_THERMISTOR_TABLE(TEMPTABLE_REDUNDANT, TEMPTABLE_REDUNDANT_LEN); #elif TEMP_SENSOR_REDUNDANT_IS_AD595 @@ -2069,20 +2346,20 @@ void Temperature::updateTemperaturesFromRawValues() { watchdog_refresh(); // Reset because raw_temps_ready was set by the interrupt - TERN_(TEMP_SENSOR_0_IS_MAX_TC, temp_hotend[0].raw = READ_MAX_TC(0)); - TERN_(TEMP_SENSOR_1_IS_MAX_TC, temp_hotend[1].raw = READ_MAX_TC(1)); - TERN_(TEMP_SENSOR_REDUNDANT_IS_MAX_TC, temp_redundant.raw = READ_MAX_TC(HEATER_ID(TEMP_SENSOR_REDUNDANT_SOURCE))); + TERN_(TEMP_SENSOR_0_IS_MAX_TC, temp_hotend[0].setraw(READ_MAX_TC(0))); + TERN_(TEMP_SENSOR_1_IS_MAX_TC, temp_hotend[1].setraw(READ_MAX_TC(1))); + TERN_(TEMP_SENSOR_REDUNDANT_IS_MAX_TC, temp_redundant.setraw(READ_MAX_TC(HEATER_ID(TEMP_SENSOR_REDUNDANT_SOURCE)))); #if HAS_HOTEND - HOTEND_LOOP() temp_hotend[e].celsius = analog_to_celsius_hotend(temp_hotend[e].raw, e); + HOTEND_LOOP() temp_hotend[e].celsius = analog_to_celsius_hotend(temp_hotend[e].getraw(), e); #endif - TERN_(HAS_HEATED_BED, temp_bed.celsius = analog_to_celsius_bed(temp_bed.raw)); - TERN_(HAS_TEMP_CHAMBER, temp_chamber.celsius = analog_to_celsius_chamber(temp_chamber.raw)); - TERN_(HAS_TEMP_COOLER, temp_cooler.celsius = analog_to_celsius_cooler(temp_cooler.raw)); - TERN_(HAS_TEMP_PROBE, temp_probe.celsius = analog_to_celsius_probe(temp_probe.raw)); - TERN_(HAS_TEMP_BOARD, temp_board.celsius = analog_to_celsius_board(temp_board.raw)); - TERN_(HAS_TEMP_REDUNDANT, temp_redundant.celsius = analog_to_celsius_redundant(temp_redundant.raw)); + TERN_(HAS_HEATED_BED, temp_bed.celsius = analog_to_celsius_bed(temp_bed.getraw())); + TERN_(HAS_TEMP_CHAMBER, temp_chamber.celsius = analog_to_celsius_chamber(temp_chamber.getraw())); + TERN_(HAS_TEMP_COOLER, temp_cooler.celsius = analog_to_celsius_cooler(temp_cooler.getraw())); + TERN_(HAS_TEMP_PROBE, temp_probe.celsius = analog_to_celsius_probe(temp_probe.getraw())); + TERN_(HAS_TEMP_BOARD, temp_board.celsius = analog_to_celsius_board(temp_board.getraw())); + TERN_(HAS_TEMP_REDUNDANT, temp_redundant.celsius = analog_to_celsius_redundant(temp_redundant.getraw())); TERN_(FILAMENT_WIDTH_SENSOR, filwidth.update_measured_mm()); TERN_(HAS_POWER_MONITOR, power_monitor.capture_values()); @@ -2108,46 +2385,45 @@ void Temperature::updateTemperaturesFromRawValues() { }; LOOP_L_N(e, COUNT(temp_dir)) { - const int8_t tdir = temp_dir[e]; - if (tdir) { - const int16_t rawtemp = temp_hotend[e].raw * tdir; // normal direction, +rawtemp, else -rawtemp - if (rawtemp > temp_range[e].raw_max * tdir) max_temp_error((heater_id_t)e); + const raw_adc_t r = temp_hotend[e].getraw(); + const bool neg = temp_dir[e] < 0, pos = temp_dir[e] > 0; + if ((neg && r < temp_range[e].raw_max) || (pos && r > temp_range[e].raw_max)) + max_temp_error((heater_id_t)e); - const bool heater_on = temp_hotend[e].target > 0; - if (heater_on && rawtemp < temp_range[e].raw_min * tdir && !is_preheating(e)) { - #if MAX_CONSECUTIVE_LOW_TEMPERATURE_ERROR_ALLOWED > 1 - if (++consecutive_low_temperature_error[e] >= MAX_CONSECUTIVE_LOW_TEMPERATURE_ERROR_ALLOWED) - #endif - min_temp_error((heater_id_t)e); - } + const bool heater_on = temp_hotend[e].target > 0; + if (heater_on && ((neg && r > temp_range[e].raw_min) || (pos && r < temp_range[e].raw_min))) { #if MAX_CONSECUTIVE_LOW_TEMPERATURE_ERROR_ALLOWED > 1 - else - consecutive_low_temperature_error[e] = 0; + if (++consecutive_low_temperature_error[e] >= MAX_CONSECUTIVE_LOW_TEMPERATURE_ERROR_ALLOWED) #endif + min_temp_error((heater_id_t)e); } + #if MAX_CONSECUTIVE_LOW_TEMPERATURE_ERROR_ALLOWED > 1 + else + consecutive_low_temperature_error[e] = 0; + #endif } #endif // HAS_HOTEND #define TP_CMP(S,A,B) (TEMPDIR(S) < 0 ? ((A)<(B)) : ((A)>(B))) #if ENABLED(THERMAL_PROTECTION_BED) - if (TP_CMP(BED, temp_bed.raw, maxtemp_raw_BED)) max_temp_error(H_BED); - if (temp_bed.target > 0 && TP_CMP(BED, mintemp_raw_BED, temp_bed.raw)) min_temp_error(H_BED); + if (TP_CMP(BED, temp_bed.getraw(), maxtemp_raw_BED)) max_temp_error(H_BED); + if (temp_bed.target > 0 && TP_CMP(BED, mintemp_raw_BED, temp_bed.getraw())) min_temp_error(H_BED); #endif #if BOTH(HAS_HEATED_CHAMBER, THERMAL_PROTECTION_CHAMBER) - if (TP_CMP(CHAMBER, temp_chamber.raw, maxtemp_raw_CHAMBER)) max_temp_error(H_CHAMBER); - if (temp_chamber.target > 0 && TP_CMP(CHAMBER, mintemp_raw_CHAMBER, temp_chamber.raw)) min_temp_error(H_CHAMBER); + if (TP_CMP(CHAMBER, temp_chamber.getraw(), maxtemp_raw_CHAMBER)) max_temp_error(H_CHAMBER); + if (temp_chamber.target > 0 && TP_CMP(CHAMBER, mintemp_raw_CHAMBER, temp_chamber.getraw())) min_temp_error(H_CHAMBER); #endif #if BOTH(HAS_COOLER, THERMAL_PROTECTION_COOLER) - if (cutter.unitPower > 0 && TP_CMP(COOLER, temp_cooler.raw, maxtemp_raw_COOLER)) max_temp_error(H_COOLER); - if (TP_CMP(COOLER, mintemp_raw_COOLER, temp_cooler.raw)) min_temp_error(H_COOLER); + if (cutter.unitPower > 0 && TP_CMP(COOLER, temp_cooler.getraw(), maxtemp_raw_COOLER)) max_temp_error(H_COOLER); + if (TP_CMP(COOLER, mintemp_raw_COOLER, temp_cooler.getraw())) min_temp_error(H_COOLER); #endif #if BOTH(HAS_TEMP_BOARD, THERMAL_PROTECTION_BOARD) - if (TP_CMP(BOARD, temp_board.raw, maxtemp_raw_BOARD)) max_temp_error(H_BOARD); - if (TP_CMP(BOARD, mintemp_raw_BOARD, temp_board.raw)) min_temp_error(H_BOARD); + if (TP_CMP(BOARD, temp_board.getraw(), maxtemp_raw_BOARD)) max_temp_error(H_BOARD); + if (TP_CMP(BOARD, mintemp_raw_BOARD, temp_board.getraw())) min_temp_error(H_BOARD); #endif #undef TP_CMP @@ -2176,7 +2452,7 @@ void Temperature::init() { TERN_(PROBING_HEATERS_OFF, paused_for_probing = false); #if BOTH(PIDTEMP, PID_EXTRUSION_SCALING) - last_e_position = 0; + pes_e_position = 0; #endif // Init (and disable) SPI thermocouples @@ -2246,6 +2522,10 @@ void Temperature::init() { )); #endif + #if ENABLED(MPCTEMP) + HOTEND_LOOP() temp_hotend[e].modeled_block_temp = NAN; + #endif + #if HAS_HEATER_0 #ifdef BOARD_OPENDRAIN_MOSFETS OUT_WRITE_OD(HEATER_0_PIN, HEATER_0_INVERTING); @@ -2731,7 +3011,7 @@ void Temperature::disable_all_heaters() { * @param hindex the hotend we're referencing (if MULTI_MAX_TC) * @return integer representing the board's buffer, to be converted later if needed */ - int16_t Temperature::read_max_tc(TERN_(HAS_MULTI_MAX_TC, const uint8_t hindex/*=0*/)) { + raw_adc_t Temperature::read_max_tc(TERN_(HAS_MULTI_MAX_TC, const uint8_t hindex/*=0*/)) { #define MAXTC_HEAT_INTERVAL 250UL #if HAS_MAX31855 @@ -2750,7 +3030,7 @@ void Temperature::disable_all_heaters() { #if HAS_MULTI_MAX_TC // Needed to return the correct temp when this is called between readings - static int16_t max_tc_temp_previous[MAX_TC_COUNT] = { 0 }; + static raw_adc_t max_tc_temp_previous[MAX_TC_COUNT] = { 0 }; #define THERMO_TEMP(I) max_tc_temp_previous[I] #define THERMO_SEL(A,B) (hindex ? (B) : (A)) #define MAXTC_CS_WRITE(V) do{ switch (hindex) { case 1: WRITE(TEMP_1_CS_PIN, V); break; default: WRITE(TEMP_0_CS_PIN, V); } }while(0) @@ -2779,7 +3059,7 @@ void Temperature::disable_all_heaters() { // Return last-read value between readings millis_t ms = millis(); if (PENDING(ms, next_max_tc_ms[hindex])) - return (int16_t)THERMO_TEMP(hindex); + return THERMO_TEMP(hindex); next_max_tc_ms[hindex] = ms + MAXTC_HEAT_INTERVAL; @@ -2876,7 +3156,7 @@ void Temperature::disable_all_heaters() { THERMO_TEMP(hindex) = max_tc_temp; - return (int16_t)max_tc_temp; + return max_tc_temp; } #endif // HAS_MAX_TC @@ -3017,7 +3297,7 @@ void Temperature::isr() { uint8_t pwm_count_tmp = pwm_count; #if HAS_ADC_BUTTONS - static unsigned int raw_ADCKey_value = 0; + static raw_adc_t raw_ADCKey_value = 0; static bool ADCKey_pressed = false; #endif @@ -3631,7 +3911,7 @@ void Temperature::isr() { #endif #if HAS_HOTEND && HAS_STATUS_MESSAGE - void Temperature::set_heating_message(const uint8_t e) { + void Temperature::set_heating_message(const uint8_t e, const bool isM104/*=false*/) { const bool heating = isHeatingHotend(e); ui.status_printf(0, #if HAS_MULTI_HOTEND @@ -3641,6 +3921,14 @@ void Temperature::isr() { #endif , heating ? GET_TEXT(MSG_HEATING) : GET_TEXT(MSG_COOLING) ); + + if (isM104) { + static uint8_t wait_e; wait_e = e; + ui.set_status_reset_fn([]{ + const celsius_t c = degTargetHotend(wait_e); + return c < 30 || degHotendNear(wait_e, c); + }); + } } #endif diff --git a/Marlin/src/module/temperature.h b/Marlin/src/module/temperature.h index eb2f4337c0..aa80bd0a23 100644 --- a/Marlin/src/module/temperature.h +++ b/Marlin/src/module/temperature.h @@ -94,6 +94,18 @@ hotend_pid_t; #define _PID_Kf(H) 0 #endif +#if ENABLED(MPCTEMP) + typedef struct { + float heater_power; // M306 P + float block_heat_capacity; // M306 C + float sensor_responsiveness; // M306 R + float ambient_xfer_coeff_fan0; // M306 A + #if ENABLED(MPC_INCLUDE_FAN) + float fan255_adjustment; // M306 F + #endif + } MPC_t; +#endif + /** * States for ADC reading in the ISR */ @@ -177,7 +189,7 @@ enum ADCSensorState : char { #if HAS_PID_HEATING #define PID_K2 (1-float(PID_K1)) - #define PID_dT ((OVERSAMPLENR * float(ACTUAL_ADC_SAMPLES)) / TEMP_TIMER_FREQUENCY) + #define PID_dT ((OVERSAMPLENR * float(ACTUAL_ADC_SAMPLES)) / (TEMP_TIMER_FREQUENCY)) // Apply the scale factors to the PID values #define scalePID_i(i) ( float(i) * PID_dT ) @@ -186,18 +198,26 @@ enum ADCSensorState : char { #define unscalePID_d(d) ( float(d) * PID_dT ) #endif +#if ENABLED(MPCTEMP) + #define MPC_dT ((OVERSAMPLENR * float(ACTUAL_ADC_SAMPLES)) / (TEMP_TIMER_FREQUENCY)) +#endif + #if ENABLED(G26_MESH_VALIDATION) && EITHER(HAS_MARLINUI_MENU, EXTENSIBLE_UI) #define G26_CLICK_CAN_CANCEL 1 #endif // A temperature sensor typedef struct TempInfo { - uint16_t acc; - int16_t raw; +private: + raw_adc_t acc; + raw_adc_t raw; +public: celsius_float_t celsius; inline void reset() { acc = 0; } - inline void sample(const uint16_t s) { acc += s; } + inline void sample(const raw_adc_t s) { acc += s; } inline void update() { raw = acc; } + void setraw(const raw_adc_t r) { raw = r; } + raw_adc_t getraw() { return raw; } } temp_info_t; #if HAS_TEMP_REDUNDANT @@ -219,8 +239,19 @@ struct PIDHeaterInfo : public HeaterInfo { T pid; // Initialized by settings.load() }; +#if ENABLED(MPCTEMP) + struct MPCHeaterInfo : public HeaterInfo { + MPC_t constants; + float modeled_ambient_temp, + modeled_block_temp, + modeled_sensor_temp; + }; +#endif + #if ENABLED(PIDTEMP) typedef struct PIDHeaterInfo hotend_info_t; +#elif ENABLED(MPCTEMP) + typedef struct MPCHeaterInfo hotend_info_t; #else typedef heater_info_t hotend_info_t; #endif @@ -287,9 +318,7 @@ struct HeaterWatch { #endif // Temperature sensor read value ranges -typedef struct { int16_t raw_min, raw_max; } raw_range_t; -typedef struct { celsius_t mintemp, maxtemp; } celsius_range_t; -typedef struct { int16_t raw_min, raw_max; celsius_t mintemp, maxtemp; } temp_range_t; +typedef struct { raw_adc_t raw_min, raw_max; celsius_t mintemp, maxtemp; } temp_range_t; #define THERMISTOR_ABS_ZERO_C -273.15f // bbbbrrrrr cold ! #define THERMISTOR_RESISTANCE_NOMINAL_C 25.0f // mmmmm comfortable @@ -479,10 +508,14 @@ class Temperature { #endif #if ENABLED(PID_EXTRUSION_SCALING) - static int32_t last_e_position, lpq[LPQ_MAX_LEN]; + static int32_t pes_e_position, lpq[LPQ_MAX_LEN]; static lpq_ptr_t lpq_ptr; #endif + #if ENABLED(MPCTEMP) + static int32_t mpc_e_position; + #endif + #if HAS_HOTEND static temp_range_t temp_range[HOTENDS]; #endif @@ -492,7 +525,7 @@ class Temperature { static bed_watch_t watch_bed; #endif IF_DISABLED(PIDTEMPBED, static millis_t next_bed_check_ms); - static int16_t mintemp_raw_BED, maxtemp_raw_BED; + static raw_adc_t mintemp_raw_BED, maxtemp_raw_BED; #endif #if HAS_HEATED_CHAMBER @@ -500,7 +533,7 @@ class Temperature { static chamber_watch_t watch_chamber; #endif TERN(PIDTEMPCHAMBER,,static millis_t next_chamber_check_ms); - static int16_t mintemp_raw_CHAMBER, maxtemp_raw_CHAMBER; + static raw_adc_t mintemp_raw_CHAMBER, maxtemp_raw_CHAMBER; #endif #if HAS_COOLER @@ -508,11 +541,11 @@ class Temperature { static cooler_watch_t watch_cooler; #endif static millis_t next_cooler_check_ms, cooler_fan_flush_ms; - static int16_t mintemp_raw_COOLER, maxtemp_raw_COOLER; + static raw_adc_t mintemp_raw_COOLER, maxtemp_raw_COOLER; #endif #if HAS_TEMP_BOARD && ENABLED(THERMAL_PROTECTION_BOARD) - static int16_t mintemp_raw_BOARD, maxtemp_raw_BOARD; + static raw_adc_t mintemp_raw_BOARD, maxtemp_raw_BOARD; #endif #if MAX_CONSECUTIVE_LOW_TEMPERATURE_ERROR_ALLOWED > 1 @@ -566,7 +599,7 @@ class Temperature { static user_thermistor_t user_thermistor[USER_THERMISTORS]; static void M305_report(const uint8_t t_index, const bool forReplay=true); static void reset_user_thermistors(); - static celsius_float_t user_thermistor_to_deg_c(const uint8_t t_index, const int16_t raw); + static celsius_float_t user_thermistor_to_deg_c(const uint8_t t_index, const raw_adc_t raw); static bool set_pull_up_res(int8_t t_index, float value) { //if (!WITHIN(t_index, 0, USER_THERMISTORS - 1)) return false; if (!WITHIN(value, 1, 1000000)) return false; @@ -594,25 +627,25 @@ class Temperature { #endif #if HAS_HOTEND - static celsius_float_t analog_to_celsius_hotend(const int16_t raw, const uint8_t e); + static celsius_float_t analog_to_celsius_hotend(const raw_adc_t raw, const uint8_t e); #endif #if HAS_HEATED_BED - static celsius_float_t analog_to_celsius_bed(const int16_t raw); + static celsius_float_t analog_to_celsius_bed(const raw_adc_t raw); #endif #if HAS_TEMP_CHAMBER - static celsius_float_t analog_to_celsius_chamber(const int16_t raw); + static celsius_float_t analog_to_celsius_chamber(const raw_adc_t raw); #endif #if HAS_TEMP_PROBE - static celsius_float_t analog_to_celsius_probe(const int16_t raw); + static celsius_float_t analog_to_celsius_probe(const raw_adc_t raw); #endif #if HAS_TEMP_COOLER - static celsius_float_t analog_to_celsius_cooler(const int16_t raw); + static celsius_float_t analog_to_celsius_cooler(const raw_adc_t raw); #endif #if HAS_TEMP_BOARD - static celsius_float_t analog_to_celsius_board(const int16_t raw); + static celsius_float_t analog_to_celsius_board(const raw_adc_t raw); #endif #if HAS_TEMP_REDUNDANT - static celsius_float_t analog_to_celsius_redundant(const int16_t raw); + static celsius_float_t analog_to_celsius_redundant(const raw_adc_t raw); #endif #if HAS_FAN @@ -707,8 +740,8 @@ class Temperature { } #if ENABLED(SHOW_TEMP_ADC_VALUES) - static int16_t rawHotendTemp(const uint8_t E_NAME) { - return TERN0(HAS_HOTEND, temp_hotend[HOTEND_INDEX].raw); + static raw_adc_t rawHotendTemp(const uint8_t E_NAME) { + return TERN0(HAS_HOTEND, temp_hotend[HOTEND_INDEX].getraw()); } #endif @@ -770,7 +803,7 @@ class Temperature { #if HAS_HEATED_BED #if ENABLED(SHOW_TEMP_ADC_VALUES) - static int16_t rawBedTemp() { return temp_bed.raw; } + static raw_adc_t rawBedTemp() { return temp_bed.getraw(); } #endif static celsius_float_t degBed() { return temp_bed.celsius; } static celsius_t wholeDegBed() { return static_cast(degBed() + 0.5f); } @@ -801,7 +834,7 @@ class Temperature { #if HAS_TEMP_PROBE #if ENABLED(SHOW_TEMP_ADC_VALUES) - static int16_t rawProbeTemp() { return temp_probe.raw; } + static raw_adc_t rawProbeTemp() { return temp_probe.getraw(); } #endif static celsius_float_t degProbe() { return temp_probe.celsius; } static celsius_t wholeDegProbe() { return static_cast(degProbe() + 0.5f); } @@ -812,7 +845,7 @@ class Temperature { #if HAS_TEMP_CHAMBER #if ENABLED(SHOW_TEMP_ADC_VALUES) - static int16_t rawChamberTemp() { return temp_chamber.raw; } + static raw_adc_t rawChamberTemp() { return temp_chamber.getraw(); } #endif static celsius_float_t degChamber() { return temp_chamber.celsius; } static celsius_t wholeDegChamber() { return static_cast(degChamber() + 0.5f); } @@ -835,7 +868,7 @@ class Temperature { #if HAS_TEMP_COOLER #if ENABLED(SHOW_TEMP_ADC_VALUES) - static int16_t rawCoolerTemp() { return temp_cooler.raw; } + static raw_adc_t rawCoolerTemp() { return temp_cooler.getraw(); } #endif static celsius_float_t degCooler() { return temp_cooler.celsius; } static celsius_t wholeDegCooler() { return static_cast(temp_cooler.celsius + 0.5f); } @@ -849,7 +882,7 @@ class Temperature { #if HAS_TEMP_BOARD #if ENABLED(SHOW_TEMP_ADC_VALUES) - static int16_t rawBoardTemp() { return temp_board.raw; } + static raw_adc_t rawBoardTemp() { return temp_board.getraw(); } #endif static celsius_float_t degBoard() { return temp_board.celsius; } static celsius_t wholeDegBoard() { return static_cast(temp_board.celsius + 0.5f); } @@ -857,8 +890,7 @@ class Temperature { #if HAS_TEMP_REDUNDANT #if ENABLED(SHOW_TEMP_ADC_VALUES) - static int16_t rawRedundantTemp() { return temp_redundant.raw; } - static int16_t rawRedundanTargetTemp() { return (*temp_redundant.target).raw; } + static raw_adc_t rawRedundantTemp() { return temp_redundant.getraw(); } #endif static celsius_float_t degRedundant() { return temp_redundant.celsius; } static celsius_float_t degRedundantTarget() { return (*temp_redundant.target).celsius; } @@ -923,12 +955,16 @@ class Temperature { */ #if ENABLED(PIDTEMP) static void updatePID() { - TERN_(PID_EXTRUSION_SCALING, last_e_position = 0); + TERN_(PID_EXTRUSION_SCALING, pes_e_position = 0); } #endif #endif + #if ENABLED(MPCTEMP) + void MPC_autotune(); + #endif + #if ENABLED(PROBING_HEATERS_OFF) static void pause_heaters(const bool p); #endif @@ -960,9 +996,9 @@ class Temperature { #endif #if HAS_HOTEND && HAS_STATUS_MESSAGE - static void set_heating_message(const uint8_t e); + static void set_heating_message(const uint8_t e, const bool isM104=false); #else - static void set_heating_message(const uint8_t) {} + static void set_heating_message(const uint8_t, const bool=false) {} #endif #if HAS_MARLINUI_MENU && HAS_TEMPERATURE @@ -991,7 +1027,7 @@ class Temperature { #else #define READ_MAX_TC(N) read_max_tc() #endif - static int16_t read_max_tc(TERN_(HAS_MULTI_MAX_TC, const uint8_t hindex=0)); + static raw_adc_t read_max_tc(TERN_(HAS_MULTI_MAX_TC, const uint8_t hindex=0)); #endif #if HAS_AUTO_FAN diff --git a/Marlin/src/module/thermistor/thermistors.h b/Marlin/src/module/thermistor/thermistors.h index 9f2ebce49a..a38b7f381f 100644 --- a/Marlin/src/module/thermistor/thermistors.h +++ b/Marlin/src/module/thermistor/thermistors.h @@ -27,22 +27,20 @@ #define THERMISTOR_TABLE_SCALE (HAL_ADC_RANGE / _BV(THERMISTOR_TABLE_ADC_RESOLUTION)) #if ENABLED(HAL_ADC_FILTERED) #define OVERSAMPLENR 1 -#elif HAL_ADC_RESOLUTION > 10 - #define OVERSAMPLENR (20 - HAL_ADC_RESOLUTION) #else #define OVERSAMPLENR 16 #endif -#define MAX_RAW_THERMISTOR_VALUE (HAL_ADC_RANGE * (OVERSAMPLENR) - 1) -// Currently Marlin stores all oversampled ADC values as int16_t, make sure the HAL settings do not overflow 15bit -#if MAX_RAW_THERMISTOR_VALUE > ((1 << 15) - 1) - #error "MAX_RAW_THERMISTOR_VALUE is too large for int16_t. Reduce OVERSAMPLENR or HAL_ADC_RESOLUTION." +// Currently Marlin stores all oversampled ADC values as uint16_t, make sure the HAL settings do not overflow 16 bit +#if (HAL_ADC_RANGE) * (OVERSAMPLENR) > 1 << 16 + #error "MAX_RAW_THERMISTOR_VALUE is too large for uint16_t. Reduce OVERSAMPLENR or HAL_ADC_RESOLUTION." #endif +#define MAX_RAW_THERMISTOR_VALUE (uint16_t(HAL_ADC_RANGE) * (OVERSAMPLENR) - 1) -#define OV_SCALE(N) (N) -#define OV(N) int16_t(OV_SCALE(N) * (OVERSAMPLENR) * (THERMISTOR_TABLE_SCALE)) +#define OV_SCALE(N) float(N) +#define OV(N) raw_adc_t(OV_SCALE(N) * (OVERSAMPLENR) * (THERMISTOR_TABLE_SCALE)) -typedef struct { int16_t value; celsius_t celsius; } temp_entry_t; +typedef struct { raw_adc_t value; celsius_t celsius; } temp_entry_t; // Pt1000 and Pt100 handling // diff --git a/Marlin/src/module/tool_change.cpp b/Marlin/src/module/tool_change.cpp index f2767f2b5b..8a62d00782 100644 --- a/Marlin/src/module/tool_change.cpp +++ b/Marlin/src/module/tool_change.cpp @@ -385,65 +385,59 @@ void fast_line_to_current(const AxisEnum fr_axis) { _line_to_current(fr_axis, 0. #endif // PARKING_EXTRUDER -#if ENABLED(SWITCHING_TOOLHEAD) +#if ENABLED(TOOL_SENSOR) + + bool tool_sensor_disabled; // = false // Return a bitmask of tool sensor states inline uint8_t poll_tool_sensor_pins() { return (0 - #if ENABLED(TOOL_SENSOR) - #if PIN_EXISTS(TOOL_SENSOR1) - | (READ(TOOL_SENSOR1_PIN) << 0) - #endif - #if PIN_EXISTS(TOOL_SENSOR2) - | (READ(TOOL_SENSOR2_PIN) << 1) - #endif - #if PIN_EXISTS(TOOL_SENSOR3) - | (READ(TOOL_SENSOR3_PIN) << 2) - #endif - #if PIN_EXISTS(TOOL_SENSOR4) - | (READ(TOOL_SENSOR4_PIN) << 3) - #endif - #if PIN_EXISTS(TOOL_SENSOR5) - | (READ(TOOL_SENSOR5_PIN) << 4) - #endif - #if PIN_EXISTS(TOOL_SENSOR6) - | (READ(TOOL_SENSOR6_PIN) << 5) - #endif - #if PIN_EXISTS(TOOL_SENSOR7) - | (READ(TOOL_SENSOR7_PIN) << 6) - #endif - #if PIN_EXISTS(TOOL_SENSOR8) - | (READ(TOOL_SENSOR8_PIN) << 7) - #endif + #if PIN_EXISTS(TOOL_SENSOR1) + | (READ(TOOL_SENSOR1_PIN) << 0) + #endif + #if PIN_EXISTS(TOOL_SENSOR2) + | (READ(TOOL_SENSOR2_PIN) << 1) + #endif + #if PIN_EXISTS(TOOL_SENSOR3) + | (READ(TOOL_SENSOR3_PIN) << 2) + #endif + #if PIN_EXISTS(TOOL_SENSOR4) + | (READ(TOOL_SENSOR4_PIN) << 3) + #endif + #if PIN_EXISTS(TOOL_SENSOR5) + | (READ(TOOL_SENSOR5_PIN) << 4) + #endif + #if PIN_EXISTS(TOOL_SENSOR6) + | (READ(TOOL_SENSOR6_PIN) << 5) + #endif + #if PIN_EXISTS(TOOL_SENSOR7) + | (READ(TOOL_SENSOR7_PIN) << 6) + #endif + #if PIN_EXISTS(TOOL_SENSOR8) + | (READ(TOOL_SENSOR8_PIN) << 7) #endif ); } - #if ENABLED(TOOL_SENSOR) - - bool tool_sensor_disabled; // = false - - uint8_t check_tool_sensor_stats(const uint8_t tool_index, const bool kill_on_error/*=false*/, const bool disable/*=false*/) { - static uint8_t sensor_tries; // = 0 - for (;;) { - if (poll_tool_sensor_pins() == _BV(tool_index)) { - sensor_tries = 0; - return tool_index; - } - else if (kill_on_error && (!tool_sensor_disabled || disable)) { - sensor_tries++; - if (sensor_tries > 10) kill(F("Tool Sensor error")); - safe_delay(5); - } - else { - sensor_tries++; - if (sensor_tries > 10) return -1; - safe_delay(5); - } + uint8_t check_tool_sensor_stats(const uint8_t tool_index, const bool kill_on_error/*=false*/, const bool disable/*=false*/) { + static uint8_t sensor_tries; // = 0 + for (;;) { + if (poll_tool_sensor_pins() == _BV(tool_index)) { + sensor_tries = 0; + return tool_index; + } + else if (kill_on_error && (!tool_sensor_disabled || disable)) { + sensor_tries++; + if (sensor_tries > 10) kill(F("Tool Sensor error")); + safe_delay(5); + } + else { + sensor_tries++; + if (sensor_tries > 10) return -1; + safe_delay(5); } } - - #endif + } inline void switching_toolhead_lock(const bool locked) { #ifdef SWITCHING_TOOLHEAD_SERVO_ANGLES @@ -496,9 +490,13 @@ void fast_line_to_current(const AxisEnum fr_axis) { _line_to_current(fr_axis, 0. switching_toolhead_lock(true); } LCD_MESSAGE_F("TC Success"); - #endif + #endif // TOOL_SENSOR } +#endif // TOOL_SENSOR + +#if ENABLED(SWITCHING_TOOLHEAD) + inline void switching_toolhead_tool_change(const uint8_t new_tool, bool no_move/*=false*/) { if (no_move) return; @@ -928,6 +926,16 @@ void fast_line_to_current(const AxisEnum fr_axis) { _line_to_current(fr_axis, 0. if (ok) { IF_DISABLED(TOOLCHANGE_PARK_Y_ONLY, current_position.x = toolchange_settings.change_point.x); IF_DISABLED(TOOLCHANGE_PARK_X_ONLY, current_position.y = toolchange_settings.change_point.y); + #if NONE(TOOLCHANGE_PARK_X_ONLY, TOOLCHANGE_PARK_Y_ONLY) + SECONDARY_AXIS_CODE( + current_position.i = toolchange_settings.change_point.i, + current_position.j = toolchange_settings.change_point.j, + current_position.k = toolchange_settings.change_point.k, + current_position.u = toolchange_settings.change_point.u, + current_position.v = toolchange_settings.change_point.v, + current_position.w = toolchange_settings.change_point.w, + ); + #endif planner.buffer_line(current_position, MMM_TO_MMS(TOOLCHANGE_PARK_XY_FEEDRATE), active_extruder); planner.synchronize(); } @@ -1123,6 +1131,16 @@ void tool_change(const uint8_t new_tool, bool no_move/*=false*/) { if (can_move_away && toolchange_settings.enable_park) { IF_DISABLED(TOOLCHANGE_PARK_Y_ONLY, current_position.x = toolchange_settings.change_point.x); IF_DISABLED(TOOLCHANGE_PARK_X_ONLY, current_position.y = toolchange_settings.change_point.y); + #if NONE(TOOLCHANGE_PARK_X_ONLY, TOOLCHANGE_PARK_Y_ONLY) + SECONDARY_AXIS_CODE( + current_position.i = toolchange_settings.change_point.i, + current_position.j = toolchange_settings.change_point.j, + current_position.k = toolchange_settings.change_point.k, + current_position.u = toolchange_settings.change_point.u, + current_position.v = toolchange_settings.change_point.v, + current_position.w = toolchange_settings.change_point.w, + ); + #endif planner.buffer_line(current_position, MMM_TO_MMS(TOOLCHANGE_PARK_XY_FEEDRATE), old_tool); planner.synchronize(); } @@ -1177,7 +1195,7 @@ void tool_change(const uint8_t new_tool, bool no_move/*=false*/) { sync_plan_position(); #if ENABLED(DELTA) - //LOOP_LINEAR_AXES(i) update_software_endstops(i); // or modify the constrain function + //LOOP_NUM_AXES(i) update_software_endstops(i); // or modify the constrain function const bool safe_to_move = current_position.z < delta_clip_start_height - 1; #else constexpr bool safe_to_move = true; @@ -1292,7 +1310,7 @@ void tool_change(const uint8_t new_tool, bool no_move/*=false*/) { #if ENABLED(EXT_SOLENOID) && DISABLED(PARKING_EXTRUDER) disable_all_solenoids(); - enable_solenoid_on_active_extruder(); + enable_solenoid(active_extruder); #endif #if HAS_PRUSA_MMU1 diff --git a/Marlin/src/module/tool_change.h b/Marlin/src/module/tool_change.h index bbdc0b6862..82ed0d6105 100644 --- a/Marlin/src/module/tool_change.h +++ b/Marlin/src/module/tool_change.h @@ -34,7 +34,7 @@ #endif #if ENABLED(TOOLCHANGE_PARK) bool enable_park; - xy_pos_t change_point; + xyz_pos_t change_point; #endif float z_raise; } toolchange_settings_t; diff --git a/Marlin/src/pins/esp32/pins_MKS_TINYBEE.h b/Marlin/src/pins/esp32/pins_MKS_TINYBEE.h index 122dad2146..68b8ed4ac8 100644 --- a/Marlin/src/pins/esp32/pins_MKS_TINYBEE.h +++ b/Marlin/src/pins/esp32/pins_MKS_TINYBEE.h @@ -113,6 +113,11 @@ //#define E0_AUTO_FAN_PIN 148 // need to update Configuration_adv.h @section extruder //#define E1_AUTO_FAN_PIN 149 // need to update Configuration_adv.h @section extruder +// +// ADC Reference Voltage +// +#define ADC_REFERENCE_VOLTAGE 2.5 // 2.5V reference VDDA + // // MicroSD card // diff --git a/Marlin/src/pins/esp32/pins_MRR_ESPE.h b/Marlin/src/pins/esp32/pins_MRR_ESPE.h index 60c8405dfe..9b9b54e3ae 100644 --- a/Marlin/src/pins/esp32/pins_MRR_ESPE.h +++ b/Marlin/src/pins/esp32/pins_MRR_ESPE.h @@ -55,7 +55,9 @@ #define I2S_WS 26 #define I2S_BCK 25 #define I2S_DATA 27 -#undef LIN_ADVANCE // Currently, I2S stream does not work with linear advance +#if ENABLED(LIN_ADVANCE) + #error "I2S stream is currently incompatible with LIN_ADVANCE." +#endif // // Steppers diff --git a/Marlin/src/pins/mega/pins_MIGHTYBOARD_REVE.h b/Marlin/src/pins/mega/pins_MIGHTYBOARD_REVE.h index f2a95baf01..13ffc94486 100644 --- a/Marlin/src/pins/mega/pins_MIGHTYBOARD_REVE.h +++ b/Marlin/src/pins/mega/pins_MIGHTYBOARD_REVE.h @@ -149,10 +149,10 @@ #define MOSFET_1_PIN 6 // Plug EX1 Pin 1-2 -> PH3 #15 -> Logical 06 #define MOSFET_2_PIN 7 // Plug EX1 Pin 3-4 -> PH4 #16 -> Logical 07 -#define MOSFET_3_PIN 12 // Plug EX2 1-2 -> PB5 #25 -> Logical 12 -#define MOSFET_4_PIN 11 // Plug EX2 3-4 -> PB6 #24 -> Logical 11 +#define MOSFET_3_PIN 11 // Plug EX2 1-2 -> PB6 #24 -> Logical 11 +#define MOSFET_4_PIN 12 // Plug EX2 3-4 -> PB5 #25 -> Logical 12 #define MOSFET_5_PIN 45 // Plug HBD 1-2 -> PL4 #39 -> Logical 45 -#define MOSFET_6_PIN 13 // Plug Extra 1-2 -> PL5 #40 -> Logical 44 (FET not soldered in all boards) +#define MOSFET_6_PIN 44 // Plug Extra 1-2 -> PL5 #40 -> Logical 44 (FET not soldered in all boards) // // Heaters / Fans (24V) diff --git a/Marlin/src/pins/pins.h b/Marlin/src/pins/pins.h index 7f0eac8c88..426ce1e48e 100644 --- a/Marlin/src/pins/pins.h +++ b/Marlin/src/pins/pins.h @@ -601,6 +601,8 @@ #include "stm32f1/pins_ZM3E4_V2_0.h" // STM32F1 env:STM32F103VE_ZM3E4V2_USB env:STM32F103VE_ZM3E4V2_USB_maple #elif MB(ERYONE_ERY32_MINI) #include "stm32f1/pins_ERYONE_ERY32_MINI.h" // STM32F103VET6 env:ERYONE_ERY32_MINI_maple +#elif MB(PANDA_PI_V29) + #include "stm32f1/pins_PANDA_PI_V29.h" // STM32F103RCT6 env:PANDA_PI_V29 // // ARM Cortex-M4F diff --git a/Marlin/src/pins/pinsDebug.h b/Marlin/src/pins/pinsDebug.h index e5db7f7b54..b662f09ba9 100644 --- a/Marlin/src/pins/pinsDebug.h +++ b/Marlin/src/pins/pinsDebug.h @@ -19,6 +19,7 @@ * along with this program. If not, see . * */ +#pragma once #include "../inc/MarlinConfig.h" diff --git a/Marlin/src/pins/pinsDebug_list.h b/Marlin/src/pins/pinsDebug_list.h index 2328a826ef..8969997e9a 100644 --- a/Marlin/src/pins/pinsDebug_list.h +++ b/Marlin/src/pins/pinsDebug_list.h @@ -823,7 +823,7 @@ #if HAS_KILL REPORT_NAME_DIGITAL(__LINE__, KILL_PIN) #endif -#if HAS_FREEZE_PIN +#if PIN_EXISTS(FREEZE) REPORT_NAME_DIGITAL(__LINE__, FREEZE_PIN) #endif #if PIN_EXISTS(LCD_BACKLIGHT) @@ -1547,6 +1547,105 @@ #if PIN_EXISTS(K_STOP) REPORT_NAME_DIGITAL(__LINE__, K_STOP_PIN) #endif +#if PIN_EXISTS(U_ATT) + REPORT_NAME_DIGITAL(__LINE__, U_ATT_PIN) +#endif +#if PIN_EXISTS(U_CS) + REPORT_NAME_DIGITAL(__LINE__, U_CS_PIN) +#endif +#if PIN_EXISTS(U_DIR) + REPORT_NAME_DIGITAL(__LINE__, U_DIR_PIN) +#endif +#if PIN_EXISTS(U_ENABLE) + REPORT_NAME_DIGITAL(__LINE__, U_ENABLE_PIN) +#endif +#if PIN_EXISTS(U_MAX) + REPORT_NAME_DIGITAL(__LINE__, U_MAX_PIN) +#endif +#if PIN_EXISTS(U_MIN) + REPORT_NAME_DIGITAL(__LINE__, U_MIN_PIN) +#endif +#if PIN_EXISTS(U_MS1) + REPORT_NAME_DIGITAL(__LINE__, U_MS1_PIN) +#endif +#if PIN_EXISTS(U_MS2) + REPORT_NAME_DIGITAL(__LINE__, U_MS2_PIN) +#endif +#if PIN_EXISTS(U_MS3) + REPORT_NAME_DIGITAL(__LINE__, U_MS3_PIN) +#endif +#if PIN_EXISTS(U_STEP) + REPORT_NAME_DIGITAL(__LINE__, U_STEP_PIN) +#endif +#if PIN_EXISTS(U_STOP) + REPORT_NAME_DIGITAL(__LINE__, U_STOP_PIN) +#endif +#if PIN_EXISTS(V_ATT) + REPORT_NAME_DIGITAL(__LINE__, V_ATT_PIN) +#endif +#if PIN_EXISTS(V_CS) + REPORT_NAME_DIGITAL(__LINE__, V_CS_PIN) +#endif +#if PIN_EXISTS(V_DIR) + REPORT_NAME_DIGITAL(__LINE__, V_DIR_PIN) +#endif +#if PIN_EXISTS(V_ENABLE) + REPORT_NAME_DIGITAL(__LINE__, V_ENABLE_PIN) +#endif +#if PIN_EXISTS(V_MAX) + REPORT_NAME_DIGITAL(__LINE__, V_MAX_PIN) +#endif +#if PIN_EXISTS(V_MIN) + REPORT_NAME_DIGITAL(__LINE__, V_MIN_PIN) +#endif +#if PIN_EXISTS(V_MS1) + REPORT_NAME_DIGITAL(__LINE__, V_MS1_PIN) +#endif +#if PIN_EXISTS(V_MS2) + REPORT_NAME_DIGITAL(__LINE__, V_MS2_PIN) +#endif +#if PIN_EXISTS(V_MS3) + REPORT_NAME_DIGITAL(__LINE__, V_MS3_PIN) +#endif +#if PIN_EXISTS(V_STEP) + REPORT_NAME_DIGITAL(__LINE__, V_STEP_PIN) +#endif +#if PIN_EXISTS(V_STOP) + REPORT_NAME_DIGITAL(__LINE__, V_STOP_PIN) +#endif +#if PIN_EXISTS(W_ATT) + REPORT_NAME_DIGITAL(__LINE__, W_ATT_PIN) +#endif +#if PIN_EXISTS(W_CS) + REPORT_NAME_DIGITAL(__LINE__, W_CS_PIN) +#endif +#if PIN_EXISTS(W_DIR) + REPORT_NAME_DIGITAL(__LINE__, W_DIR_PIN) +#endif +#if PIN_EXISTS(W_ENABLE) + REPORT_NAME_DIGITAL(__LINE__, W_ENABLE_PIN) +#endif +#if PIN_EXISTS(W_MAX) + REPORT_NAME_DIGITAL(__LINE__, W_MAX_PIN) +#endif +#if PIN_EXISTS(W_MIN) + REPORT_NAME_DIGITAL(__LINE__, W_MIN_PIN) +#endif +#if PIN_EXISTS(W_MS1) + REPORT_NAME_DIGITAL(__LINE__, W_MS1_PIN) +#endif +#if PIN_EXISTS(W_MS2) + REPORT_NAME_DIGITAL(__LINE__, W_MS2_PIN) +#endif +#if PIN_EXISTS(W_MS3) + REPORT_NAME_DIGITAL(__LINE__, W_MS3_PIN) +#endif +#if PIN_EXISTS(W_STEP) + REPORT_NAME_DIGITAL(__LINE__, W_STEP_PIN) +#endif +#if PIN_EXISTS(W_STOP) + REPORT_NAME_DIGITAL(__LINE__, W_STOP_PIN) +#endif #if PIN_EXISTS(ZRIB_V20_D6) REPORT_NAME_DIGITAL(__LINE__, ZRIB_V20_D6_PIN) #endif @@ -1619,6 +1718,24 @@ #if PIN_EXISTS(K_SERIAL_RX) REPORT_NAME_DIGITAL(__LINE__, K_SERIAL_RX_PIN) #endif +#if PIN_EXISTS(U_SERIAL_TX) + REPORT_NAME_DIGITAL(__LINE__, U_SERIAL_TX_PIN) +#endif +#if PIN_EXISTS(U_SERIAL_RX) + REPORT_NAME_DIGITAL(__LINE__, U_SERIAL_RX_PIN) +#endif +#if PIN_EXISTS(V_SERIAL_TX) + REPORT_NAME_DIGITAL(__LINE__, V_SERIAL_TX_PIN) +#endif +#if PIN_EXISTS(V_SERIAL_RX) + REPORT_NAME_DIGITAL(__LINE__, V_SERIAL_RX_PIN) +#endif +#if PIN_EXISTS(W_SERIAL_TX) + REPORT_NAME_DIGITAL(__LINE__, W_SERIAL_TX_PIN) +#endif +#if PIN_EXISTS(W_SERIAL_RX) + REPORT_NAME_DIGITAL(__LINE__, W_SERIAL_RX_PIN) +#endif #if PIN_EXISTS(E0_DIAG) REPORT_NAME_DIGITAL(__LINE__, E0_DIAG_PIN) #endif diff --git a/Marlin/src/pins/pins_postprocess.h b/Marlin/src/pins/pins_postprocess.h index aabe0da858..8da2b969bc 100644 --- a/Marlin/src/pins/pins_postprocess.h +++ b/Marlin/src/pins/pins_postprocess.h @@ -221,6 +221,15 @@ #if !AXIS_HAS_SPI(K) #undef K_CS_PIN #endif +#if !AXIS_HAS_SPI(U) + #undef U_CS_PIN +#endif +#if !AXIS_HAS_SPI(V) + #undef V_CS_PIN +#endif +#if !AXIS_HAS_SPI(W) + #undef W_CS_PIN +#endif #if E_STEPPERS && !AXIS_HAS_SPI(E0) #undef E0_CS_PIN #endif @@ -264,6 +273,15 @@ #ifndef K_CS_PIN #define K_CS_PIN -1 #endif +#ifndef U_CS_PIN + #define U_CS_PIN -1 +#endif +#ifndef V_CS_PIN + #define V_CS_PIN -1 +#endif +#ifndef W_CS_PIN + #define W_CS_PIN -1 +#endif #ifndef E0_CS_PIN #define E0_CS_PIN -1 #endif @@ -546,6 +564,75 @@ #undef K_MAX_PIN #endif +#if HAS_U_AXIS + #ifdef U_STOP_PIN + #if U_HOME_TO_MIN + #define U_MIN_PIN U_STOP_PIN + #ifndef U_MAX_PIN + #define U_MAX_PIN -1 + #endif + #else + #define U_MAX_PIN U_STOP_PIN + #ifndef U_MIN_PIN + #define U_MIN_PIN -1 + #endif + #endif + #elif U_HOME_TO_MIN + #define U_STOP_PIN U_MIN_PIN + #else + #define U_STOP_PIN U_MAX_PIN + #endif +#else + #undef U_MIN_PIN + #undef U_MAX_PIN +#endif + +#if HAS_V_AXIS + #ifdef V_STOP_PIN + #if V_HOME_TO_MIN + #define V_MIN_PIN V_STOP_PIN + #ifndef V_MAX_PIN + #define V_MAX_PIN -1 + #endif + #else + #define V_MAX_PIN V_STOP_PIN + #ifndef V_MIN_PIN + #define V_MIN_PIN -1 + #endif + #endif + #elif V_HOME_TO_MIN + #define V_STOP_PIN V_MIN_PIN + #else + #define V_STOP_PIN V_MAX_PIN + #endif +#else + #undef V_MIN_PIN + #undef V_MAX_PIN +#endif + +#if HAS_W_AXIS + #ifdef W_STOP_PIN + #if W_HOME_TO_MIN + #define W_MIN_PIN W_STOP_PIN + #ifndef W_MAX_PIN + #define W_MAX_PIN -1 + #endif + #else + #define W_MAX_PIN W_STOP_PIN + #ifndef W_MIN_PIN + #define W_MIN_PIN -1 + #endif + #endif + #elif W_HOME_TO_MIN + #define W_STOP_PIN W_MIN_PIN + #else + #define W_STOP_PIN W_MAX_PIN + #endif +#else + #undef W_MIN_PIN + #undef W_MAX_PIN +#endif + // Filament Sensor first pin alias #if HAS_FILAMENT_SENSOR #define FIL_RUNOUT1_PIN FIL_RUNOUT_PIN // Filament Sensor first pin alias @@ -1204,6 +1291,12 @@ #define J_MS3_PIN -1 #endif +#if HAS_K_AXIS && !defined(K_DIAG_PIN) && !defined(K_STEP_PIN) && !PIN_EXISTS(K_CS_PIN) + #define U_E_INDEX INCREMENT(K_E_INDEX) +#else + #define U_E_INDEX K_E_INDEX +#endif + // The K axis, if any, should be the next open extruder port #if HAS_K_AXIS #ifndef K_STEP_PIN @@ -1284,6 +1377,258 @@ #define K_MS3_PIN -1 #endif +#if HAS_U_AXIS && !defined(U_DIAG_PIN) && !defined(U_STEP_PIN) && !PIN_EXISTS(U_CS_PIN) + #define V_E_INDEX INCREMENT(U_E_INDEX) +#else + #define V_E_INDEX U_E_INDEX +#endif + +// The U axis, if any, should be the next open extruder port +#if HAS_U_AXIS + #ifndef U_STEP_PIN + #define U_STEP_PIN _EPIN(U_E_INDEX, STEP) + #define U_DIR_PIN _EPIN(U_E_INDEX, DIR) + #define U_ENABLE_PIN _EPIN(U_E_INDEX, ENABLE) + #if M_E_INDEX >= MAX_E_STEPPERS || !PIN_EXISTS(U_STEP) + #error "No E stepper plug left for U!" + #else + #define AUTO_ASSIGNED_U_STEPPER 1 + #endif + #endif + #if AXIS_HAS_SPI(U) && !defined(U_CS_PIN) + #define U_CS_PIN _EPIN(U_E_INDEX, CS) + #if PIN_EXISTS(U_CS) + #define AUTO_ASSIGNED_U_CS 1 + #endif + #endif + #ifndef U_MS1_PIN + #define U_MS1_PIN _EPIN(U_E_INDEX, MS1) + #if PIN_EXISTS(U_MS1) + #define AUTO_ASSIGNED_U_MS1 1 + #endif + #endif + #ifndef U_MS2_PIN + #define U_MS2_PIN _EPIN(U_E_INDEX, MS2) + #if PIN_EXISTS(U_MS2) + #define AUTO_ASSIGNED_U_MS2 1 + #endif + #endif + #ifndef U_MS3_PIN + #define U_MS3_PIN _EPIN(U_E_INDEX, MS3) + #if PIN_EXISTS(U_MS3) + #define AUTO_ASSIGNED_U_MS3 1 + #endif + #endif + #if AXIS_HAS_UART(U) + #ifndef U_SERIAL_TX_PIN + #define U_SERIAL_TX_PIN _EPIN(U_E_INDEX, SERIAL_TX) + #endif + #ifndef U_SERIAL_RX_PIN + #define U_SERIAL_RX_PIN _EPIN(U_E_INDEX, SERIAL_RX) + #endif + #endif + // Auto-assign pins for stallGuard sensorless homing + #if !defined(U_DIAG_PIN) && !defined(U_USE_ENDSTOP) && defined(U_STALL_SENSITIVITY) && _PEXI(U_E_INDEX, DIAG) + #define U_DIAG_PIN _EPIN(U_E_INDEX, DIAG) + #if DIAG_REMAPPED(U, X_MIN) + #define U_USE_ENDSTOP _XMIN_ + #elif DIAG_REMAPPED(U, Y_MIN) + #define U_USE_ENDSTOP _YMIN_ + #elif DIAG_REMAPPED(U, Z_MIN) + #define U_USE_ENDSTOP _ZMIN_ + #elif DIAG_REMAPPED(U, X_MAX) + #define U_USE_ENDSTOP _XMAX_ + #elif DIAG_REMAPPED(U, Y_MAX) + #define U_USE_ENDSTOP _YMAX_ + #elif DIAG_REMAPPED(U, Z_MAX) + #define U_USE_ENDSTOP _ZMAX_ + #else + #define U_USE_ENDSTOP _En_DIAG_(U_E_INDEX) + #endif + #define AUTO_ASSIGNED_U_DIAG 1 + #undef U_DIAG_PIN // Defined in Conditionals_post.h based on U_USE_ENDSTOP + #endif +#endif + +#ifndef U_CS_PIN + #define U_CS_PIN -1 +#endif +#ifndef U_MS1_PIN + #define U_MS1_PIN -1 +#endif +#ifndef U_MS2_PIN + #define U_MS2_PIN -1 +#endif +#ifndef U_MS3_PIN + #define U_MS3_PIN -1 +#endif + +#if HAS_V_AXIS && !defined(V_DIAG_PIN) && !defined(V_STEP_PIN) && !PIN_EXISTS(V_CS_PIN) + #define W_E_INDEX INCREMENT(V_E_INDEX) +#else + #define W_E_INDEX V_E_INDEX +#endif + +// The V axis, if any, should be the next open extruder port +#if HAS_V_AXIS + #ifndef V_STEP_PIN + #define V_STEP_PIN _EPIN(V_E_INDEX, STEP) + #define V_DIR_PIN _EPIN(V_E_INDEX, DIR) + #define V_ENABLE_PIN _EPIN(V_E_INDEX, ENABLE) + #if V_E_INDEX >= MAX_E_STEPPERS || !PIN_EXISTS(V_STEP) + #error "No E stepper plug left for V!" + #else + #define AUTO_ASSIGNED_V_STEPPER 1 + #endif + #endif + #if AXIS_HAS_SPI(V) && !defined(V_CS_PIN) + #define V_CS_PIN _EPIN(V_E_INDEX, CS) + #if PIN_EXISTS(V_CS) + #define AUTO_ASSIGNED_V_CS 1 + #endif + #endif + #ifndef V_MS1_PIN + #define V_MS1_PIN _EPIN(V_E_INDEX, MS1) + #if PIN_EXISTS(V_MS1) + #define AUTO_ASSIGNED_V_MS1 1 + #endif + #endif + #ifndef V_MS2_PIN + #define V_MS2_PIN _EPIN(V_E_INDEX, MS2) + #if PIN_EXISTS(V_MS2) + #define AUTO_ASSIGNED_V_MS2 1 + #endif + #endif + #ifndef V_MS3_PIN + #define V_MS3_PIN _EPIN(V_E_INDEX, MS3) + #if PIN_EXISTS(V_MS3) + #define AUTO_ASSIGNED_V_MS3 1 + #endif + #endif + #if AXIS_HAS_UART(V) + #ifndef V_SERIAL_TX_PIN + #define V_SERIAL_TX_PIN _EPIN(V_E_INDEX, SERIAL_TX) + #endif + #ifndef V_SERIAL_RX_PIN + #define V_SERIAL_RX_PIN _EPIN(V_E_INDEX, SERIAL_RX) + #endif + #endif + // Auto-assign pins for stallGuard sensorless homing + #if !defined(V_DIAG_PIN) && !defined(V_USE_ENDSTOP) && defined(V_STALL_SENSITIVITY) && _PEXI(V_E_INDEX, DIAG) + #define V_DIAG_PIN _EPIN(V_E_INDEX, DIAG) + #if DIAG_REMAPPED(V, X_MIN) + #define V_USE_ENDSTOP _XMIN_ + #elif DIAG_REMAPPED(V, Y_MIN) + #define V_USE_ENDSTOP _YMIN_ + #elif DIAG_REMAPPED(V, Z_MIN) + #define V_USE_ENDSTOP _ZMIN_ + #elif DIAG_REMAPPED(V, X_MAX) + #define V_USE_ENDSTOP _XMAX_ + #elif DIAG_REMAPPED(V, Y_MAX) + #define V_USE_ENDSTOP _YMAX_ + #elif DIAG_REMAPPED(V, Z_MAX) + #define V_USE_ENDSTOP _ZMAX_ + #else + #define V_USE_ENDSTOP _En_DIAG_(V_E_INDEX) + #endif + #define AUTO_ASSIGNED_V_DIAG 1 + #undef V_DIAG_PIN // Defined in Conditionals_post.h based on O_USE_ENDSTOP + #endif +#endif + +#ifndef V_CS_PIN + #define V_CS_PIN -1 +#endif +#ifndef V_MS1_PIN + #define V_MS1_PIN -1 +#endif +#ifndef V_MS2_PIN + #define V_MS2_PIN -1 +#endif +#ifndef V_MS3_PIN + #define V_MS3_PIN -1 +#endif + +// The W axis, if any, should be the next open extruder port +#if HAS_W_AXIS + #ifndef W_STEP_PIN + #define W_STEP_PIN _EPIN(W_E_INDEX, STEP) + #define W_DIR_PIN _EPIN(W_E_INDEX, DIR) + #define W_ENABLE_PIN _EPIN(W_E_INDEX, ENABLE) + #if W_E_INDEX >= MAX_E_STEPPERS || !PIN_EXISTS(W_STEP) + #error "No E stepper plug left for W!" + #else + #define AUTO_ASSIGNED_W_STEPPER 1 + #endif + #endif + #if AXIS_HAS_SPI(W) && !defined(W_CS_PIN) + #define W_CS_PIN _EPIN(W_E_INDEX, CS) + #if PIN_EXISTS(W_CS) + #define AUTO_ASSIGNED_W_CS 1 + #endif + #endif + #ifndef W_MS1_PIN + #define W_MS1_PIN _EPIN(W_E_INDEX, MS1) + #if PIN_EXISTS(W_MS1) + #define AUTO_ASSIGNED_W_MS1 1 + #endif + #endif + #ifndef W_MS2_PIN + #define W_MS2_PIN _EPIN(W_E_INDEX, MS2) + #if PIN_EXISTS(W_MS2) + #define AUTO_ASSIGNED_W_MS2 1 + #endif + #endif + #ifndef W_MS3_PIN + #define W_MS3_PIN _EPIN(W_E_INDEX, MS3) + #if PIN_EXISTS(W_MS3) + #define AUTO_ASSIGNED_W_MS3 1 + #endif + #endif + #if AXIS_HAS_UART(W) + #ifndef W_SERIAL_TX_PIN + #define W_SERIAL_TX_PIN _EPIN(W_E_INDEX, SERIAL_TX) + #endif + #ifndef W_SERIAL_RX_PIN + #define W_SERIAL_RX_PIN _EPIN(W_E_INDEX, SERIAL_RX) + #endif + #endif + // Auto-assign pins for stallGuard sensorless homing + #if !defined(W_DIAG_PIN) && !defined(W_USE_ENDSTOP) && defined(W_STALL_SENSITIVITY) && _PEXI(W_E_INDEX, DIAG) + #define W_DIAG_PIN _EPIN(W_E_INDEX, DIAG) + #if DIAG_REMAPPED(W, X_MIN) + #define W_USE_ENDSTOP _XMIN_ + #elif DIAG_REMAPPED(W, Y_MIN) + #define W_USE_ENDSTOP _YMIN_ + #elif DIAG_REMAPPED(W, Z_MIN) + #define W_USE_ENDSTOP _ZMIN_ + #elif DIAG_REMAPPED(W, X_MAX) + #define W_USE_ENDSTOP _XMAX_ + #elif DIAG_REMAPPED(W, Y_MAX) + #define W_USE_ENDSTOP _YMAX_ + #elif DIAG_REMAPPED(W, Z_MAX) + #define W_USE_ENDSTOP _ZMAX_ + #else + #define W_USE_ENDSTOP _En_DIAG_(W_E_INDEX) + #endif + #define AUTO_ASSIGNED_W_DIAG 1 + #undef W_DIAG_PIN // Defined in Conditionals_post.h based on Q_USE_ENDSTOP + #endif +#endif + +#ifndef W_CS_PIN + #define W_CS_PIN -1 +#endif +#ifndef W_MS1_PIN + #define W_MS1_PIN -1 +#endif +#ifndef W_MS2_PIN + #define W_MS2_PIN -1 +#endif +#ifndef W_MS3_PIN + #define W_MS3_PIN -1 +#endif + // // Disable unused endstop / probe pins // @@ -1359,6 +1704,30 @@ #undef K_MAX_PIN #define K_MAX_PIN -1 #endif +#if DISABLED(USE_UMIN_PLUG) + #undef U_MIN_PIN + #define U_MIN_PIN -1 +#endif +#if DISABLED(USE_UMAX_PLUG) + #undef U_MAX_PIN + #define U_MAX_PIN -1 +#endif +#if DISABLED(USE_VMIN_PLUG) + #undef V_MIN_PIN + #define V_MIN_PIN -1 +#endif +#if DISABLED(USE_VMAX_PLUG) + #undef V_MAX_PIN + #define V_MAX_PIN -1 +#endif +#if DISABLED(USE_WMIN_PLUG) + #undef W_MIN_PIN + #define W_MIN_PIN -1 +#endif +#if DISABLED(USE_WMAX_PLUG) + #undef W_MAX_PIN + #define W_MAX_PIN -1 +#endif #if DISABLED(X_DUAL_ENDSTOPS) || X_HOME_TO_MAX #undef X2_MIN_PIN diff --git a/Marlin/src/pins/ramps/pins_MKS_GEN_L.h b/Marlin/src/pins/ramps/pins_MKS_GEN_L.h index 522a34cda1..4dca1ca187 100644 --- a/Marlin/src/pins/ramps/pins_MKS_GEN_L.h +++ b/Marlin/src/pins/ramps/pins_MKS_GEN_L.h @@ -37,6 +37,12 @@ // Power outputs EFBF or EFBE #define MOSFET_D_PIN 7 +// Hotend, Hotend, Bed + Fan on D9 +#if FET_ORDER_EEB + #define MOSFET_B_PIN 7 + #define FAN_PIN 9 +#endif + // // CS Pins wired to avoid conflict with the LCD // See https://www.thingiverse.com/asset:66604 diff --git a/Marlin/src/pins/ramps/pins_RAMPS.h b/Marlin/src/pins/ramps/pins_RAMPS.h index 29caaf0533..c7ef0be99e 100644 --- a/Marlin/src/pins/ramps/pins_RAMPS.h +++ b/Marlin/src/pins/ramps/pins_RAMPS.h @@ -270,7 +270,7 @@ // M3/M4/M5 - Spindle/Laser Control // #if HAS_CUTTER && !defined(SPINDLE_LASER_ENA_PIN) - #if !NUM_SERVOS // Use servo connector if possible + #if NUM_SERVOS < 2 // Use servo connector if possible #define SPINDLE_LASER_ENA_PIN 4 // Pullup or pulldown! #define SPINDLE_LASER_PWM_PIN 6 // Hardware PWM #define SPINDLE_DIR_PIN 5 diff --git a/Marlin/src/pins/sensitive_pins.h b/Marlin/src/pins/sensitive_pins.h index f9911cc863..db6cb2353b 100644 --- a/Marlin/src/pins/sensitive_pins.h +++ b/Marlin/src/pins/sensitive_pins.h @@ -293,6 +293,126 @@ #endif +#if HAS_U_AXIS + #if PIN_EXISTS(U_MIN) + #define _U_MIN U_MIN_PIN, + #else + #define _U_MIN + #endif + #if PIN_EXISTS(U_MAX) + #define _U_MAX U_MAX_PIN, + #else + #define _U_MAX + #endif + #if PIN_EXISTS(U_CS) && AXIS_HAS_SPI(U) + #define _U_CS U_CS_PIN, + #else + #define _U_CS + #endif + #if PIN_EXISTS(U_MS1) + #define _U_MS1 U_MS1_PIN, + #else + #define _U_MS1 + #endif + #if PIN_EXISTS(U_MS2) + #define _U_MS2 U_MS2_PIN, + #else + #define _U_MS2 + #endif + #if PIN_EXISTS(U_MS3) + #define _U_MS3 U_MS3_PIN, + #else + #define _U_MS3 + #endif + + #define _U_PINS U_STEP_PIN, U_DIR_PIN, U_ENABLE_PIN, _U_MIN _U_MAX _U_MS1 _U_MS2 _U_MS3 _U_CS + +#else + + #define _U_PINS + +#endif + +#if HAS_V_AXIS + #if PIN_EXISTS(V_MIN) + #define _V_MIN V_MIN_PIN, + #else + #define _V_MIN + #endif + #if PIN_EXISTS(V_MAX) + #define _V_MAX V_MAX_PIN, + #else + #define _V_MAX + #endif + #if PIN_EXISTS(V_CS) && AXIS_HAS_SPI(V) + #define _V_CS V_CS_PIN, + #else + #define _V_CS + #endif + #if PIN_EXISTS(V_MS1) + #define _V_MS1 V_MS1_PIN, + #else + #define _V_MS1 + #endif + #if PIN_EXISTS(V_MS2) + #define _V_MS2 V_MS2_PIN, + #else + #define _V_MS2 + #endif + #if PIN_EXISTS(V_MS3) + #define _V_MS3 V_MS3_PIN, + #else + #define _V_MS3 + #endif + + #define _V_PINS V_STEP_PIN, V_DIR_PIN, V_ENABLE_PIN, _V_MIN _V_MAX _V_MS1 _V_MS2 _V_MS3 _V_CS + +#else + + #define _V_PINS + +#endif + +#if HAS_W_AXIS + #if PIN_EXISTS(W_MIN) + #define _W_MIN W_MIN_PIN, + #else + #define _W_MIN + #endif + #if PIN_EXISTS(W_MAX) + #define _W_MAX W_MAX_PIN, + #else + #define _W_MAX + #endif + #if PIN_EXISTS(W_CS) && AXIS_HAS_SPI(W) + #define _W_CS W_CS_PIN, + #else + #define _W_CS + #endif + #if PIN_EXISTS(W_MS1) + #define _W_MS1 W_MS1_PIN, + #else + #define _W_MS1 + #endif + #if PIN_EXISTS(W_MS2) + #define _W_MS2 W_MS2_PIN, + #else + #define _W_MS2 + #endif + #if PIN_EXISTS(W_MS3) + #define _W_MS3 W_MS3_PIN, + #else + #define _W_MS3 + #endif + + #define _W_PINS W_STEP_PIN, W_DIR_PIN, W_ENABLE_PIN, _W_MIN _W_MAX _W_MS1 _W_MS2 _W_MS3 _W_CS + +#else + + #define _W_PINS + +#endif + // // Extruder Chip Select, Digital Micro-steps // @@ -886,7 +1006,7 @@ #endif #define SENSITIVE_PINS \ - _X_PINS _Y_PINS _Z_PINS _I_PINS _J_PINS _K_PINS \ + _X_PINS _Y_PINS _Z_PINS _I_PINS _J_PINS _K_PINS _U_PINS _V_PINS _W_PINS \ _X2_PINS _Y2_PINS _Z2_PINS _Z3_PINS _Z4_PINS _Z_PROBE \ _E0_PINS _E1_PINS _E2_PINS _E3_PINS _E4_PINS _E5_PINS _E6_PINS _E7_PINS \ _H0_PINS _H1_PINS _H2_PINS _H3_PINS _H4_PINS _H5_PINS _H6_PINS _H7_PINS \ diff --git a/Marlin/src/pins/stm32f1/pins_BTT_SKR_MINI_E3_common.h b/Marlin/src/pins/stm32f1/pins_BTT_SKR_MINI_E3_common.h index 92d65babfa..5b48d7cadb 100644 --- a/Marlin/src/pins/stm32f1/pins_BTT_SKR_MINI_E3_common.h +++ b/Marlin/src/pins/stm32f1/pins_BTT_SKR_MINI_E3_common.h @@ -235,7 +235,7 @@ #define TFTGLCD_CS PA9 #endif - + #elif ENABLED(FYSETC_MINI_12864_2_1) #error "CAUTION! FYSETC_MINI_12864_2_1 / MKS_MINI_12864_V3 / BTT_MINI_12864_V1 requires wiring modifications. See 'pins_BTT_SKR_MINI_E3_common.h' for details. Comment out this line to continue." diff --git a/Marlin/src/pins/stm32f1/pins_BTT_SKR_MINI_V1_1.h b/Marlin/src/pins/stm32f1/pins_BTT_SKR_MINI_V1_1.h index a92de805f7..4f52dfb4fc 100644 --- a/Marlin/src/pins/stm32f1/pins_BTT_SKR_MINI_V1_1.h +++ b/Marlin/src/pins/stm32f1/pins_BTT_SKR_MINI_V1_1.h @@ -80,6 +80,23 @@ #endif #endif +#if HAS_TMC_UART // Shared with EXP1 + #define X_SERIAL_TX_PIN PC10 + #define X_SERIAL_RX_PIN X_SERIAL_TX_PIN + + #define Y_SERIAL_TX_PIN PC11 + #define Y_SERIAL_RX_PIN Y_SERIAL_TX_PIN + + #define Z_SERIAL_TX_PIN PC12 + #define Z_SERIAL_RX_PIN Z_SERIAL_TX_PIN + + #define E0_SERIAL_TX_PIN PC14 + #define E0_SERIAL_RX_PIN E0_SERIAL_TX_PIN + + // Reduce baud rate to improve software serial reliability + #define TMC_BAUD_RATE 19200 +#endif + // // Heaters / Fans // diff --git a/Marlin/src/pins/stm32f1/pins_CREALITY_V24S1_301.h b/Marlin/src/pins/stm32f1/pins_CREALITY_V24S1_301.h index 8616a8fb34..fb7198e57c 100644 --- a/Marlin/src/pins/stm32f1/pins_CREALITY_V24S1_301.h +++ b/Marlin/src/pins/stm32f1/pins_CREALITY_V24S1_301.h @@ -28,7 +28,11 @@ #include "env_validate.h" #if HAS_MULTI_HOTEND || E_STEPPERS > 1 - #error "Creality V4 only supports one hotend / E-stepper. Comment out this line to continue." + #error "Creality V24S1 only supports one hotend / E-stepper. Comment out this line to continue." +#endif + +#if BOTH(BLTOUCH, Z_MIN_PROBE_USES_Z_MIN_ENDSTOP_PIN) + #error "Disable Z_MIN_PROBE_USES_Z_MIN_ENDSTOP_PIN when using BLTOUCH with Creality V24S1-301." #endif #define BOARD_INFO_NAME "Creality V24S1-301" @@ -44,7 +48,7 @@ // // Limit Switches // -#define Z_STOP_PIN PC14 +#define Z_STOP_PIN PA15 #ifndef Z_MIN_PROBE_PIN #define Z_MIN_PROBE_PIN PC14 // BLTouch IN @@ -63,4 +67,22 @@ #define HEATER_BED_PIN PA7 // HOT BED #define FAN1_PIN PC0 // extruder fan +// +// SD Card +// +#define ONBOARD_SPI_DEVICE 1 +#define ONBOARD_SD_CS_PIN PA4 // SDSS + +// +// M3/M4/M5 - Spindle/Laser Control +// +#if HAS_CUTTER + //#define HEATER_0_PIN -1 + //#define HEATER_BED_PIN -1 + #define FAN_PIN -1 + #define SPINDLE_LASER_ENA_PIN PA0 // FET 1 + #define SPINDLE_LASER_PWM_PIN PA0 // Bed FET + #define SPINDLE_DIR_PIN PA0 // FET 4 +#endif + #include "pins_CREALITY_V4.h" diff --git a/Marlin/src/pins/stm32f1/pins_PANDA_PI_V29.h b/Marlin/src/pins/stm32f1/pins_PANDA_PI_V29.h new file mode 100644 index 0000000000..7f4aa563b0 --- /dev/null +++ b/Marlin/src/pins/stm32f1/pins_PANDA_PI_V29.h @@ -0,0 +1,222 @@ +/** + * 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 . + * + */ +#pragma once + +#include "env_validate.h" + +#define BOARD_INFO_NAME "PANDA PI V2.9" + +// Release PB3/PB4 (TMC_SW Pins) from JTAG pins +#define DISABLE_JTAG + +// Ignore temp readings during development. +//#define BOGUS_TEMPERATURE_GRACE_PERIOD 2000 + +#if EITHER(NO_EEPROM_SELECTED, FLASH_EEPROM_EMULATION) + #define FLASH_EEPROM_EMULATION + #define EEPROM_PAGE_SIZE (0x800U) // 2KB + #define EEPROM_START_ADDRESS (0x8000000UL + (STM32_FLASH_SIZE) * 1024UL - (EEPROM_PAGE_SIZE) * 2UL) + #define MARLIN_EEPROM_SIZE EEPROM_PAGE_SIZE // 2KB +#endif + +// +// Servos +// +#define SERVO0_PIN PA11 // SERVOS + +// +// Limit Switches +// +#define X_STOP_PIN PA3 // X-STOP +#define Y_STOP_PIN PC9 // Y-STOP +#define Z_STOP_PIN PA1 // Z-STOP + +// +// Z Probe must be this pin +// +//#define Z_MIN_PROBE_PIN PA1 // PROBE + +// +// Filament Runout Sensor +// +//#ifndef FIL_RUNOUT_PIN +// #define FIL_RUNOUT_PIN PC2 // E0-STOP +//#endif + +// +// Steppers +// +#define X_ENABLE_PIN PC12 +#define X_STEP_PIN PC11 +#define X_DIR_PIN PB6 + +#define Y_ENABLE_PIN PC12 +#define Y_STEP_PIN PB5 +#define Y_DIR_PIN PB4 + +#define Z_ENABLE_PIN PC12 +#define Z_STEP_PIN PB3 +#define Z_DIR_PIN PA15 + +#define E0_ENABLE_PIN PC12 +#define E0_STEP_PIN PB15 +#define E0_DIR_PIN PB14 + +// +// Software SPI pins for TMC2130 stepper drivers +// +#if ENABLED(TMC_USE_SW_SPI) + #ifndef TMC_SW_MOSI + #define TMC_SW_MOSI PB5 + #endif + #ifndef TMC_SW_MISO + #define TMC_SW_MISO PB4 + #endif + #ifndef TMC_SW_SCK + #define TMC_SW_SCK PB3 + #endif +#endif + +#if HAS_TMC_UART + /** + * TMC2208/TMC2209 stepper drivers + * + * Hardware serial communication ports. + * If undefined software serial is used according to the pins below + */ + //#define X_HARDWARE_SERIAL MSerial1 + //#define Y_HARDWARE_SERIAL MSerial1 + //#define Z_HARDWARE_SERIAL MSerial1 + //#define E0_HARDWARE_SERIAL MSerial1 + + #define X_SERIAL_TX_PIN PC10 + #define X_SERIAL_RX_PIN X_SERIAL_TX_PIN + + #define Y_SERIAL_TX_PIN PC11 + #define Y_SERIAL_RX_PIN Y_SERIAL_TX_PIN + + #define Z_SERIAL_TX_PIN PC12 + #define Z_SERIAL_RX_PIN Z_SERIAL_TX_PIN + + #define E0_SERIAL_TX_PIN PD2 + #define E0_SERIAL_RX_PIN E0_SERIAL_TX_PIN + + // Reduce baud rate to improve software serial reliability + #define TMC_BAUD_RATE 19200 +#endif + +// +// Temperature Sensors +// +#define TEMP_0_PIN PB0 // Analog Input "TH0" +#define TEMP_BED_PIN PB1 // Analog Input "TB0" +#define TEMP_1_PIN PA2 + +// +// Heaters / Fans +// +#define HEATER_0_PIN PB12 // "HE" +#define HEATER_BED_PIN PB13 // "HB" +#define FAN_PIN PA8 // "FAN0" +#define HEATER_1_PIN PA12 + +// +// SD Support +// +#define ONBOARD_SPI_DEVICE 1 // SPI1 +#define ONBOARD_SD_CS_PIN PA4 // Chip select for "System" SD card +#define SDSS ONBOARD_SD_CS_PIN + +#ifndef SDCARD_CONNECTION + #define SDCARD_CONNECTION ONBOARD +#endif +#if SD_CONNECTION_IS(ONBOARD) + //#define SD_DETECT_PIN PA4 + #define SD_SCK_PIN PA5 + #define SD_MISO_PIN PA6 + #define SD_MOSI_PIN PA7 +#elif SD_CONNECTION_IS(CUSTOM_CABLE) + #error "SD CUSTOM_CABLE is not compatible with SKR E3 DIP." +#endif + +// +// LCD / Controller +// +#if HAS_WIRED_LCD + #define BTN_ENC PA0 + #define BTN_EN1 PC4 + #define BTN_EN2 PC5 + + #define LCD_PINS_RS PC0 + #define LCD_PINS_ENABLE PC2 + #define LCD_PINS_D4 PC1 +#endif + +#if BOTH(TOUCH_UI_FTDI_EVE, LCD_FYSETC_TFT81050) + + #error "CAUTION! LCD_FYSETC_TFT81050 requires wiring modifications. See 'pins_BTT_SKR_E3_DIP.h' for details. Comment out this line to continue." + + /** FYSETC TFT TFT81050 display pinout + * + * Board Display + * ----- ----- + * 5V | 1 2 | GND (SPI1-MISO) MISO | 1 2 | SCK (SPI1-SCK) + * (FREE) PB7 | 3 4 | PB8 (LCD_CS) (PA9) MOD_RESET | 3 4 | SD_CS (PA10) + * (FREE) PB9 | 5 6 PA10 (SD_CS) (PB8) LCD_CS | 5 6 MOSI (SPI1-MOSI) + * RESET | 7 8 | PA9 (MOD_RESET) (PA15) SD_DET | 7 8 | RESET + * (BEEPER) PB6 | 9 10| PA15 (SD_DET) GND | 9 10| 5V + * ----- ----- + * EXP1 EXP1 + * + * Needs custom cable: + * + * Board Adapter Display + * _________ + * EXP1-1 ----------- EXP1-10 + * EXP1-2 ----------- EXP1-9 + * SPI1-4 ----------- EXP1-6 + * EXP1-4 ----------- EXP1-5 + * SP11-3 ----------- EXP1-2 + * EXP1-6 ----------- EXP1-4 + * EXP1-7 ----------- EXP1-8 + * EXP1-8 ----------- EXP1-3 + * SPI1-1 ----------- EXP1-1 + * EXP1-10 ----------- EXP1-7 + */ + + #define CLCD_SPI_BUS 1 // SPI1 connector + + #define BEEPER_PIN PB6 + + #define CLCD_MOD_RESET PA9 + #define CLCD_SPI_CS PB8 + + #if SD_CONNECTION_IS(LCD) && BOTH(TOUCH_UI_FTDI_EVE, LCD_FYSETC_TFT81050) + #define SD_DETECT_PIN PA15 + #define SD_SS_PIN PA10 + #endif + +#elif HAS_WIRED_LCD + + #define BEEPER_PIN PC3 + +#endif diff --git a/Marlin/src/pins/stm32f4/pins_BTT_SKR_V2_0_common.h b/Marlin/src/pins/stm32f4/pins_BTT_SKR_V2_0_common.h index 4f5ed6c1b4..d526c75b63 100644 --- a/Marlin/src/pins/stm32f4/pins_BTT_SKR_V2_0_common.h +++ b/Marlin/src/pins/stm32f4/pins_BTT_SKR_V2_0_common.h @@ -23,6 +23,8 @@ #include "env_validate.h" +#define USES_DIAG_JUMPERS + // If you have the BigTreeTech driver expansion module, enable BTT_MOTOR_EXPANSION // https://github.com/bigtreetech/BTT-Expansion-module/tree/master/BTT%20EXP-MOT //#define BTT_MOTOR_EXPANSION diff --git a/Marlin/src/pins/stm32f4/pins_INDEX_REV03.h b/Marlin/src/pins/stm32f4/pins_INDEX_REV03.h index a9828c5bda..977f476343 100644 --- a/Marlin/src/pins/stm32f4/pins_INDEX_REV03.h +++ b/Marlin/src/pins/stm32f4/pins_INDEX_REV03.h @@ -60,12 +60,12 @@ // None of these require limit switches by default, so we leave these commented // here for your reference. -// #define I_MIN_PIN PA8 -// #define I_MAX_PIN PA8 -// #define J_MIN_PIN PD13 -// #define J_MAX_PIN PD13 -// #define K_MIN_PIN PC9 -// #define K_MAX_PIN PC9 +//#define I_MIN_PIN PA8 +//#define I_MAX_PIN PA8 +//#define J_MIN_PIN PD13 +//#define J_MAX_PIN PD13 +//#define K_MIN_PIN PC9 +//#define K_MAX_PIN PC9 // // Steppers @@ -73,47 +73,81 @@ #define X_STEP_PIN PB15 #define X_DIR_PIN PB14 #define X_ENABLE_PIN PD9 -#define X_SERIAL_TX_PIN PD8 -#define X_SERIAL_RX_PIN PD8 #define Y_STEP_PIN PE15 #define Y_DIR_PIN PE14 #define Y_ENABLE_PIN PB13 -#define Y_SERIAL_TX_PIN PB12 -#define Y_SERIAL_RX_PIN PB12 #define Z_STEP_PIN PE7 #define Z_DIR_PIN PB1 #define Z_ENABLE_PIN PE9 -#define Z_SERIAL_TX_PIN PE8 -#define Z_SERIAL_RX_PIN PE8 #define I_STEP_PIN PC4 #define I_DIR_PIN PA4 #define I_ENABLE_PIN PB0 -#define I_SERIAL_TX_PIN PC5 -#define I_SERIAL_RX_PIN PC5 #define J_STEP_PIN PE11 #define J_DIR_PIN PE10 #define J_ENABLE_PIN PE13 -#define J_SERIAL_TX_PIN PE12 -#define J_SERIAL_RX_PIN PE12 -#define K_SERIAL_TX_PIN PA2 -#define K_SERIAL_RX_PIN PA2 #define K_STEP_PIN PD6 #define K_DIR_PIN PD7 #define K_ENABLE_PIN PA3 -// Reduce baud rate to improve software serial reliability -#define TMC_BAUD_RATE 19200 +#if HAS_TMC_SPI + /** + * Make sure to configure the jumpers on the back side of the Mobo according to + * this diagram: https://github.com/MarlinFirmware/Marlin/pull/23851 + */ + #error "SPI drivers require a custom jumper configuration, see comment above! Comment out this line to continue." -// Not required for this board. Fails to compile otherwise. -// PD0 is not connected on this board. -#define TEMP_0_PIN PD0 + #if AXIS_HAS_SPI(X) + #define X_CS_PIN PD8 + #endif + #if AXIS_HAS_SPI(Y) + #define Y_CS_PIN PB12 + #endif + #if AXIS_HAS_SPI(Z) + #define Z_CS_PIN PE8 + #endif + #if AXIS_HAS_SPI(I) + #define I_CS_PIN PC5 + #endif + #if AXIS_HAS_SPI(J) + #define J_CS_PIN PE12 + #endif + #if AXIS_HAS_SPI(K) + #define K_CS_PIN PA2 + #endif -// General use mosfets, useful for things like pumps and solenoids +#elif HAS_TMC_UART + + #define X_SERIAL_TX_PIN PD8 + #define X_SERIAL_RX_PIN X_SERIAL_TX_PIN + + #define Y_SERIAL_TX_PIN PB12 + #define Y_SERIAL_RX_PIN Y_SERIAL_TX_PIN + + #define Z_SERIAL_TX_PIN PE8 + #define Z_SERIAL_RX_PIN Z_SERIAL_TX_PIN + + #define I_SERIAL_TX_PIN PC5 + #define I_SERIAL_RX_PIN I_SERIAL_TX_PIN + + #define J_SERIAL_TX_PIN PE12 + #define J_SERIAL_RX_PIN J_SERIAL_TX_PIN + + #define K_SERIAL_TX_PIN PA2 + #define K_SERIAL_RX_PIN K_SERIAL_TX_PIN + + // Reduce baud rate to improve software serial reliability + #define TMC_BAUD_RATE 19200 + +#endif + +// +// Heaters / Fans +// #define FAN_PIN PE2 #define FAN1_PIN PE3 #define FAN2_PIN PE4 @@ -121,16 +155,26 @@ #define FAN_SOFT_PWM_REQUIRED -// Neopixel Rings +// +// Neopixel +// #define NEOPIXEL_PIN PC7 #define NEOPIXEL2_PIN PC8 +// // SPI +// #define MISO_PIN PB4 #define MOSI_PIN PB5 #define SCK_PIN PB3 +#define TMC_SW_MISO MISO_PIN +#define TMC_SW_MOSI MOSI_PIN +#define TMC_SW_SCK SCK_PIN + +// // I2C +// #define I2C_SDA_PIN PB7 #define I2C_SCL_PIN PB6 diff --git a/Marlin/src/pins/stm32f4/pins_TH3D_EZBOARD_V2.h b/Marlin/src/pins/stm32f4/pins_TH3D_EZBOARD_V2.h index bd4798209e..fd6b960542 100644 --- a/Marlin/src/pins/stm32f4/pins_TH3D_EZBOARD_V2.h +++ b/Marlin/src/pins/stm32f4/pins_TH3D_EZBOARD_V2.h @@ -130,6 +130,20 @@ // Reduce baud rate to improve software serial reliability #define TMC_BAUD_RATE 19200 + + // Default TMC slave addresses + #ifndef X_SLAVE_ADDRESS + #define X_SLAVE_ADDRESS 0 + #endif + #ifndef Y_SLAVE_ADDRESS + #define Y_SLAVE_ADDRESS 1 + #endif + #ifndef Z_SLAVE_ADDRESS + #define Z_SLAVE_ADDRESS 2 + #endif + #ifndef E0_SLAVE_ADDRESS + #define E0_SLAVE_ADDRESS 3 + #endif #endif // diff --git a/Marlin/src/pins/stm32g0/pins_BTT_SKR_MINI_E3_V3_0.h b/Marlin/src/pins/stm32g0/pins_BTT_SKR_MINI_E3_V3_0.h index 2589a316b6..2fddb68a7c 100644 --- a/Marlin/src/pins/stm32g0/pins_BTT_SKR_MINI_E3_V3_0.h +++ b/Marlin/src/pins/stm32g0/pins_BTT_SKR_MINI_E3_V3_0.h @@ -256,8 +256,51 @@ #endif + #elif ENABLED(FYSETC_MINI_12864_2_1) + + #error "CAUTION! FYSETC_MINI_12864_2_1 and clones require wiring modifications. See 'pins_BTT_SKR_MINI_E3_V3_0.h' for details. Comment out this line to continue." + + /** + * + * Board Display + * ------ ------ + * (EN2) PB5 |10 9 | PA15(BTN_ENC) 5V |10 9 | GND + * (LCD_CS) PA9 | 8 7 | RST (RESET) -- | 8 7 | -- + * (LCD_A0) PA10 |#6 5 | PB9 (EN1) (DIN) | 6 5#| (RESET) + * (LCD_SCK)PB8 | 4 3 | PD6 (MOSI) (LCD_A0) | 4 3 | (LCD_CS) + * GND | 2 1 | 5V (BTN_ENC) | 2 1 | -- + * ------ ------ + * EXP1 EXP1 + * + * ------ + * -- |10 9 | -- + * --- (RESET) | 8 7 | -- + * | 3 | (MOSI) | 6 5#| (EN2) + * | 2 | (DIN) -- | 4 3 | (EN1) + * | 1 | (LCD_SCK)| 2 1 | -- + * --- ------ + * Neopixel EXP2 + * + * Needs custom cable. Connect EN2-EN2, LCD_CS-LCD_CS and so on. + * + * Check twice index position!!! (marked as # here) + * On BTT boards pins from IDC10 connector are numbered in unusual order. + */ + #define BTN_ENC EXP1_09_PIN + #define BTN_EN1 PB9 + #define BTN_EN2 PB5 + #define BEEPER_PIN -1 + + #define DOGLCD_CS PA9 + #define DOGLCD_A0 PA10 + #define DOGLCD_SCK PB8 + #define DOGLCD_MOSI PD6 + + #define FORCE_SOFT_SPI + #define LCD_BACKLIGHT_PIN -1 + #else - #error "Only CR10_STOCKDISPLAY, ZONESTAR_LCD, ENDER2_STOCKDISPLAY, MKS_MINI_12864, and TFTGLCD_PANEL_(SPI|I2C) are currently supported on the BIGTREE_SKR_MINI_E3." + #error "Only CR10_STOCKDISPLAY, ZONESTAR_LCD, ENDER2_STOCKDISPLAY, MKS_MINI_12864, FYSETC_MINI_12864_2_1, and TFTGLCD_PANEL_(SPI|I2C) are currently supported on the BIGTREE_SKR_MINI_E3." #endif #endif // HAS_WIRED_LCD diff --git a/Marlin/src/sd/cardreader.cpp b/Marlin/src/sd/cardreader.cpp index 9966773418..652a44e526 100644 --- a/Marlin/src/sd/cardreader.cpp +++ b/Marlin/src/sd/cardreader.cpp @@ -33,7 +33,7 @@ #if ENABLED(DWIN_CREALITY_LCD) #include "../lcd/e3v2/creality/dwin.h" -#elif ENABLED(DWIN_CREALITY_LCD_ENHANCED) +#elif ENABLED(DWIN_LCD_PROUI) #include "../lcd/e3v2/proui/dwin.h" #endif @@ -195,7 +195,7 @@ char *createFilename(char * const buffer, const dir_t &p) { } // -// Return 'true' if the item is something Marlin can read +// Return 'true' if the item is a folder, G-code file or Binary file // bool CardReader::is_visible_entity(const dir_t &p OPTARG(CUSTOM_FIRMWARE_UPLOAD, bool onlyBin/*=false*/)) { //uint8_t pn0 = p.name[0]; @@ -212,14 +212,15 @@ bool CardReader::is_visible_entity(const dir_t &p OPTARG(CUSTOM_FIRMWARE_UPLOAD, ) return false; flag.filenameIsDir = DIR_IS_SUBDIR(&p); // We know it's a File or Folder + setBinFlag(p.name[8] == 'B' && // List .bin files (a firmware file for flashing) + p.name[9] == 'I' && + p.name[10]== 'N'); return ( flag.filenameIsDir // All Directories are ok + || fileIsBinary() // BIN files are accepted || (!onlyBin && p.name[8] == 'G' && p.name[9] != '~') // Non-backup *.G* files are accepted - || ( onlyBin && p.name[8] == 'B' - && p.name[9] == 'I' - && p.name[10] == 'N') // BIN files are accepted ); } @@ -457,7 +458,7 @@ void CardReader::mount() { cdroot(); #if ENABLED(USB_FLASH_DRIVE_SUPPORT) || PIN_EXISTS(SD_DETECT) else if (marlin_state != MF_INITIALIZING) - ui.set_status(GET_TEXT_F(MSG_MEDIA_INIT_FAIL), -1); + LCD_ALERTMESSAGE(MSG_MEDIA_INIT_FAIL); #endif ui.refresh(); @@ -867,6 +868,7 @@ void CardReader::selectFileByIndex(const uint16_t nr) { strcpy(filename, sortshort[nr]); strcpy(longFilename, sortnames[nr]); flag.filenameIsDir = IS_DIR(nr); + setBinFlag(strcmp_P(strrchr(filename, '.'), PSTR(".BIN")) == 0); return; } #endif @@ -884,6 +886,7 @@ void CardReader::selectFileByName(const char * const match) { strcpy(filename, sortshort[nr]); strcpy(longFilename, sortnames[nr]); flag.filenameIsDir = IS_DIR(nr); + setBinFlag(strcmp_P(strrchr(filename, '.'), PSTR(".BIN")) == 0); return; } #endif diff --git a/Marlin/src/sd/cardreader.h b/Marlin/src/sd/cardreader.h index 2b3dcd00fb..483ab81395 100644 --- a/Marlin/src/sd/cardreader.h +++ b/Marlin/src/sd/cardreader.h @@ -80,6 +80,9 @@ typedef struct { filenameIsDir:1, workDirIsRoot:1, abort_sd_printing:1 + #if DO_LIST_BIN_FILES + , filenameIsBin:1 + #endif #if ENABLED(BINARY_FILE_TRANSFER) , binary_mode:1 #endif @@ -218,6 +221,10 @@ public: static void removeJobRecoveryFile(); #endif + // Binary flag for the current file + static bool fileIsBinary() { return TERN0(DO_LIST_BIN_FILES, flag.filenameIsBin); } + static void setBinFlag(const bool bin) { TERN(DO_LIST_BIN_FILES, flag.filenameIsBin = bin, UNUSED(bin)); } + // Current Working Dir - Set by cd, cdup, cdroot, and diveToFile(true, ...) static char* getWorkDirName() { workDir.getDosName(filename); return filename; } static SdFile& getWorkDir() { return workDir.isOpen() ? workDir : root; } diff --git a/buildroot/bin/build_example b/buildroot/bin/build_example index 8ebb58f972..cff8ea253e 100755 --- a/buildroot/bin/build_example +++ b/buildroot/bin/build_example @@ -24,6 +24,6 @@ cp "$SUB"/_Statusscreen.h Marlin/ 2>/dev/null echo "Building the firmware now..." HERE=`dirname "$0"` -$HERE/mftest -a -n1 || { echo "Failed"; exit 1; } +$HERE/mftest -s -a -n1 || { echo "Failed"; exit 1; } echo "Success" diff --git a/buildroot/bin/mftest b/buildroot/bin/mftest index 77e53ff9ac..9aa5e12732 100755 --- a/buildroot/bin/mftest +++ b/buildroot/bin/mftest @@ -17,6 +17,7 @@ usage() { Usage: mftest [-t|--env=] [-n|--num=] [-m|--make] [-y|--build=] mftest [-a|--autobuild] mftest [-r|--rebuild] + mftest [-s|--silent] mftest [-u|--autoupload] [-n|--num=] OPTIONS @@ -30,7 +31,7 @@ OPTIONS -v --verbose Extra output for debugging. -s --silent Silence build output from PlatformIO. -env shortcuts: tree due esp lin lpc|lpc8 lpc9 m128 m256|mega stm|f1 f4 f7 s6 teensy|t31|t32 t35|t36 t40|t41 +env shortcuts: tree due esp lin lp8|lpc8 lp9|lpc9 m128 m256|mega stm|f1 f4 f7 s6 teensy|t31|t32 t35|t36 t40|t41 " } @@ -52,7 +53,7 @@ TESTENV='-' CHOICE=0 DEBUG=0 -while getopts 'abhmruvyn:t:-:' OFLAG; do +while getopts 'abhmrsuvyn:t:-:' OFLAG; do case "${OFLAG}" in a) AUTO_BUILD=1 ; bugout "Auto-Build target..." ;; h) EXIT_USAGE=1 ;; @@ -84,6 +85,7 @@ while getopts 'abhmruvyn:t:-:' OFLAG; do esac ;; rebuild) REBUILD=1 ; bugout "Rebuilding previous..." ;; + silent) SILENT_FLAG="-s" ;; make) USE_MAKE=1 ; bugout "Using make with Docker..." ;; debug|verbose) DEBUG=1 ; bugout "Debug ON" ;; build) case "$OVAL" in diff --git a/buildroot/share/PlatformIO/variants/MARLIN_G0B1RE/variant_MARLIN_STM32G0B1RE.cpp b/buildroot/share/PlatformIO/variants/MARLIN_G0B1RE/variant_MARLIN_STM32G0B1RE.cpp index e53fb4182c..8af7150dc7 100644 --- a/buildroot/share/PlatformIO/variants/MARLIN_G0B1RE/variant_MARLIN_STM32G0B1RE.cpp +++ b/buildroot/share/PlatformIO/variants/MARLIN_G0B1RE/variant_MARLIN_STM32G0B1RE.cpp @@ -115,11 +115,11 @@ extern "C" { * AHB Prescaler = 1 * APB1 Prescaler = 1 * PLL_M = 1 - * PLL_N = 16 - * PLL_R = 2 + * PLL_N = 24 + * PLL_R = 3 * PLL_P = 2 - * PLL_Q = 2 - * USB(Hz) = 48000000 (HSI48M) + * PLL_Q = 4 + * USB(Hz) = 48000000 (PLLQ) * @param None * @retval None */ @@ -129,22 +129,31 @@ WEAK void SystemClock_Config(void) RCC_ClkInitTypeDef RCC_ClkInitStruct = {0}; RCC_PeriphCLKInitTypeDef PeriphClkInit = {0}; + // Reset clock registers (in case bootloader has changed them) + RCC->CR |= RCC_CR_HSION; + while (!(RCC->CR & RCC_CR_HSIRDY)) + ; + RCC->CFGR = 0x00000000; + RCC->CR = RCC_CR_HSION; + while (RCC->CR & RCC_CR_PLLRDY) + ; + RCC->PLLCFGR = 0x00001000; + /** Configure the main internal regulator output voltage */ HAL_PWREx_ControlVoltageScaling(PWR_REGULATOR_VOLTAGE_SCALE1); /** Initializes the RCC Oscillators according to the specified parameters * in the RCC_OscInitTypeDef structure. */ - RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE|RCC_OSCILLATORTYPE_HSI48; + RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE; RCC_OscInitStruct.HSEState = RCC_HSE_ON; - RCC_OscInitStruct.HSI48State = RCC_HSI48_ON; RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON; RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE; RCC_OscInitStruct.PLL.PLLM = RCC_PLLM_DIV1; - RCC_OscInitStruct.PLL.PLLN = 16; + RCC_OscInitStruct.PLL.PLLN = 24; RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV2; - RCC_OscInitStruct.PLL.PLLQ = RCC_PLLQ_DIV2; - RCC_OscInitStruct.PLL.PLLR = RCC_PLLR_DIV2; + RCC_OscInitStruct.PLL.PLLQ = RCC_PLLQ_DIV4; + RCC_OscInitStruct.PLL.PLLR = RCC_PLLR_DIV3; if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK) { Error_Handler(); @@ -164,7 +173,7 @@ WEAK void SystemClock_Config(void) /** Initializes the peripherals clocks */ PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_USB; - PeriphClkInit.UsbClockSelection = RCC_USBCLKSOURCE_HSI48; + PeriphClkInit.UsbClockSelection = RCC_USBCLKSOURCE_PLL; if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInit) != HAL_OK) { Error_Handler(); diff --git a/buildroot/tests/BIGTREE_GTR_V1_0 b/buildroot/tests/BIGTREE_GTR_V1_0 index 0a80a6b78c..a64f30b4f9 100755 --- a/buildroot/tests/BIGTREE_GTR_V1_0 +++ b/buildroot/tests/BIGTREE_GTR_V1_0 @@ -12,8 +12,10 @@ opt_set MOTHERBOARD BOARD_BTT_GTR_V1_0 SERIAL_PORT -1 \ # Not necessary to enable auto-fan for all extruders to hit problematic code paths opt_set E0_AUTO_FAN_PIN PC10 E1_AUTO_FAN_PIN PC11 E2_AUTO_FAN_PIN PC12 NEOPIXEL_PIN PF13 \ X_DRIVER_TYPE TMC2208 Y_DRIVER_TYPE TMC2130 \ - NUM_RUNOUT_SENSORS 8 FIL_RUNOUT_PIN 3 FIL_RUNOUT2_PIN 4 FIL_RUNOUT3_PIN 5 FIL_RUNOUT4_PIN 6 FIL_RUNOUT5_PIN 7 \ - FIL_RUNOUT6_PIN 8 FIL_RUNOUT7_PIN 9 FIL_RUNOUT8_PIN 10 FIL_RUNOUT4_STATE HIGH FIL_RUNOUT8_STATE HIGH \ + FIL_RUNOUT_ENABLED '{ true, true, true, true, true, true, true, true }' \ + FIL_RUNOUT_MODE '{ 1, 1, 1, 1, 1, 1, 1, 1 }' \ + FIL_RUNOUT_DISTANCE_MM '{ 0, 1, 5, 10, 5, 5, 5, 5 }' \ + FIL_RUNOUT_PIN 3 FIL_RUNOUT2_PIN 4 FIL_RUNOUT3_PIN 5 FIL_RUNOUT4_PIN 6 FIL_RUNOUT5_PIN 7 FIL_RUNOUT6_PIN 8 FIL_RUNOUT7_PIN 9 FIL_RUNOUT8_PIN 10 \ FILAMENT_RUNOUT_SCRIPT '"M600 T%c"' opt_enable REPRAP_DISCOUNT_FULL_GRAPHIC_SMART_CONTROLLER BLTOUCH NEOPIXEL_LED Z_SAFE_HOMING NOZZLE_PARK_FEATURE ADVANCED_PAUSE_FEATURE \ FILAMENT_RUNOUT_SENSOR FIL_RUNOUT4_PULLUP FIL_RUNOUT8_PULLUP FILAMENT_CHANGE_RESUME_ON_INSERT PAUSE_REHEAT_FAST_RESUME diff --git a/buildroot/tests/BIGTREE_GTR_V1_0_usb_flash_drive b/buildroot/tests/BIGTREE_GTR_V1_0_usb_flash_drive index 34bf77be27..3e819ba85e 100755 --- a/buildroot/tests/BIGTREE_GTR_V1_0_usb_flash_drive +++ b/buildroot/tests/BIGTREE_GTR_V1_0_usb_flash_drive @@ -16,7 +16,7 @@ opt_enable SDSUPPORT USB_FLASH_DRIVE_SUPPORT USE_OTG_USB_HOST \ opt_set E0_AUTO_FAN_PIN PC10 E1_AUTO_FAN_PIN PC11 E2_AUTO_FAN_PIN PC12 NEOPIXEL_PIN PF13 \ X_DRIVER_TYPE TMC2208 Y_DRIVER_TYPE TMC2130 \ FIL_RUNOUT_PIN 3 FIL_RUNOUT2_PIN 4 FIL_RUNOUT3_PIN 5 FIL_RUNOUT4_PIN 6 FIL_RUNOUT5_PIN 7 FIL_RUNOUT6_PIN 8 FIL_RUNOUT7_PIN 9 FIL_RUNOUT8_PIN 10 \ - FIL_RUNOUT4_STATE HIGH FIL_RUNOUT8_STATE HIGH + FIL_RUNOUT_MODE '{ 2, 2, 2, 1, 2, 2, 2, 1 }' FIL_RUNOUT_DISTANCE_MM '{ 0, 1, 5, 10, 5, 5, 5, 5 }' opt_enable FIL_RUNOUT4_PULLUP FIL_RUNOUT8_PULLUP exec_test $1 $2 "GTT GTR | OTG USB Flash Drive | 8 Extruders | Auto-Fan | Mixed TMC Drivers | Runout Sensors (distinct)" "$3" diff --git a/buildroot/tests/DUE b/buildroot/tests/DUE index 9b968cbd8d..7251cd8669 100755 --- a/buildroot/tests/DUE +++ b/buildroot/tests/DUE @@ -19,7 +19,7 @@ opt_enable S_CURVE_ACCELERATION EEPROM_SETTINGS GCODE_MACROS \ EEPROM_SETTINGS SDSUPPORT BINARY_FILE_TRANSFER \ BLINKM PCA9533 PCA9632 RGB_LED RGB_LED_R_PIN RGB_LED_G_PIN RGB_LED_B_PIN \ NEOPIXEL_LED NEOPIXEL_PIN CASE_LIGHT_ENABLE CASE_LIGHT_USE_NEOPIXEL CASE_LIGHT_USE_RGB_LED CASE_LIGHT_MENU \ - NOZZLE_PARK_FEATURE ADVANCED_PAUSE_FEATURE FILAMENT_RUNOUT_DISTANCE_MM FILAMENT_RUNOUT_SENSOR \ + NOZZLE_PARK_FEATURE ADVANCED_PAUSE_FEATURE FILAMENT_RUNOUT_SENSOR FIL_RUNOUT_DISTANCE_MM \ AUTO_BED_LEVELING_BILINEAR Z_MIN_PROBE_REPEATABILITY_TEST DEBUG_LEVELING_FEATURE \ SKEW_CORRECTION SKEW_CORRECTION_FOR_Z SKEW_CORRECTION_GCODE CALIBRATION_GCODE \ BACKLASH_COMPENSATION BACKLASH_GCODE BAUD_RATE_GCODE BEZIER_CURVE_SUPPORT \ diff --git a/buildroot/tests/STM32F103RE_creality b/buildroot/tests/STM32F103RE_creality index 257616ddd1..6440c56792 100755 --- a/buildroot/tests/STM32F103RE_creality +++ b/buildroot/tests/STM32F103RE_creality @@ -15,8 +15,9 @@ exec_test $1 $2 "Ender 3 v2 with CrealityUI" "$3" use_example_configs "Creality/Ender-3 V2/CrealityV422/CrealityUI" opt_disable DWIN_CREALITY_LCD -opt_enable DWIN_CREALITY_LCD_ENHANCED BLTOUCH AUTO_BED_LEVELING_UBL Z_SAFE_HOMING INDIVIDUAL_AXIS_HOMING_SUBMENU LCD_SET_PROGRESS_MANUALLY STATUS_MESSAGE_SCROLLING BAUD_RATE_GCODE -exec_test $1 $2 "Ender 3 v2 with Enhanced UI" "$3" +opt_enable BLTOUCH AUTO_BED_LEVELING_UBL Z_SAFE_HOMING INDIVIDUAL_AXIS_HOMING_SUBMENU LCD_SET_PROGRESS_MANUALLY STATUS_MESSAGE_SCROLLING BAUD_RATE_GCODE \ + DWIN_LCD_PROUI SOUND_MENU_ITEM PRINTCOUNTER +exec_test $1 $2 "Ender 3 v2 with ProUI" "$3" use_example_configs "Creality/Ender-3 V2/CrealityV422/CrealityUI" opt_disable DWIN_CREALITY_LCD diff --git a/buildroot/tests/mega2560 b/buildroot/tests/mega2560 index 5ae9a2dbcf..ad08b7487f 100755 --- a/buildroot/tests/mega2560 +++ b/buildroot/tests/mega2560 @@ -53,7 +53,7 @@ restore_configs opt_set MOTHERBOARD BOARD_AZTEEG_X3_PRO NUM_SERVOS 1 \ EXTRUDERS 5 TEMP_SENSOR_1 1 TEMP_SENSOR_2 1 TEMP_SENSOR_3 1 TEMP_SENSOR_4 1 \ NUM_RUNOUT_SENSORS 5 FIL_RUNOUT2_PIN 44 FIL_RUNOUT3_PIN 45 FIL_RUNOUT4_PIN 46 FIL_RUNOUT5_PIN 47 \ - FIL_RUNOUT3_STATE HIGH + FIL_RUNOUT_ENABLED '{ true, true, true, true, true }' FIL_RUNOUT_MODE '{ 1, 2, 7, 0, 1 }' FIL_RUNOUT_DISTANCE_MM '{ 15, 15, 15, 15, 15 }' opt_enable VIKI2 BOOT_MARLIN_LOGO_ANIMATED SDSUPPORT AUTO_REPORT_SD_STATUS \ Z_PROBE_SERVO_NR Z_SERVO_ANGLES DEACTIVATE_SERVOS_AFTER_MOVE AUTO_BED_LEVELING_3POINT DEBUG_LEVELING_FEATURE \ EEPROM_SETTINGS EEPROM_CHITCHAT M114_DETAIL AUTO_REPORT_POSITION \ @@ -67,9 +67,9 @@ exec_test $1 $2 "Multiple runout sensors (x5) | Distinct runout states" "$3" # Mixing Extruder with 5 steppers, Greek # restore_configs -opt_set MOTHERBOARD BOARD_AZTEEG_X3_PRO MIXING_STEPPERS 5 LCD_LANGUAGE ru \ - NUM_RUNOUT_SENSORS E_STEPPERS REDUNDANT_PART_COOLING_FAN 1 \ - FIL_RUNOUT2_PIN 16 FIL_RUNOUT3_PIN 17 FIL_RUNOUT4_PIN 4 FIL_RUNOUT5_PIN 5 +opt_set MOTHERBOARD BOARD_AZTEEG_X3_PRO MIXING_STEPPERS 5 LCD_LANGUAGE ru REDUNDANT_PART_COOLING_FAN 1 \ + FIL_RUNOUT2_PIN 16 FIL_RUNOUT3_PIN 17 FIL_RUNOUT4_PIN 4 FIL_RUNOUT5_PIN 5 \ + FIL_RUNOUT_ENABLED '{ true, true, true, true, true }' FIL_RUNOUT_MODE '{ 1, 2, 7, 0, 1 }' FIL_RUNOUT_DISTANCE_MM '{ 15, 15, 15, 15, 15 }' opt_enable MIXING_EXTRUDER GRADIENT_MIX GRADIENT_VTOOL CR10_STOCKDISPLAY \ USE_CONTROLLER_FAN CONTROLLER_FAN_EDITABLE CONTROLLER_FAN_IGNORE_Z \ FILAMENT_RUNOUT_SENSOR ADVANCED_PAUSE_FEATURE NOZZLE_PARK_FEATURE diff --git a/buildroot/tests/rambo b/buildroot/tests/rambo index e696dce96e..ae9d8cb295 100755 --- a/buildroot/tests/rambo +++ b/buildroot/tests/rambo @@ -15,7 +15,7 @@ opt_set MOTHERBOARD BOARD_RAMBO \ TEMP_SENSOR_PROBE 1 TEMP_PROBE_PIN 12 \ TEMP_SENSOR_CHAMBER 3 TEMP_CHAMBER_PIN 3 HEATER_CHAMBER_PIN 45 \ GRID_MAX_POINTS_X 16 AUTO_POWER_E_TEMP 80 \ - FANMUX0_PIN 53 + FANMUX0_PIN 53 NUM_RUNOUT_SENSORS 1 opt_disable Z_MIN_PROBE_USES_Z_MIN_ENDSTOP_PIN USE_WATCHDOG opt_enable USE_ZMAX_PLUG REPRAP_DISCOUNT_SMART_CONTROLLER LCD_PROGRESS_BAR LCD_PROGRESS_BAR_TEST \ FIX_MOUNTED_PROBE CODEPENDENT_XY_HOMING PIDTEMPBED PTC_PROBE PTC_BED \ @@ -25,7 +25,7 @@ opt_enable USE_ZMAX_PLUG REPRAP_DISCOUNT_SMART_CONTROLLER LCD_PROGRESS_BAR LCD_P NEOPIXEL_LED NEOPIXEL_PIN CASE_LIGHT_ENABLE CASE_LIGHT_USE_NEOPIXEL CASE_LIGHT_MENU \ PID_PARAMS_PER_HOTEND PID_AUTOTUNE_MENU PID_EDIT_MENU LCD_SHOW_E_TOTAL \ PRINTCOUNTER SERVICE_NAME_1 SERVICE_INTERVAL_1 LEVEL_BED_CORNERS LEVEL_CENTER_TOO \ - NOZZLE_PARK_FEATURE FILAMENT_RUNOUT_SENSOR FILAMENT_RUNOUT_DISTANCE_MM \ + NOZZLE_PARK_FEATURE FILAMENT_RUNOUT_SENSOR FIL_RUNOUT_DISTANCE_MM \ ADVANCED_PAUSE_FEATURE FILAMENT_LOAD_UNLOAD_GCODES FILAMENT_UNLOAD_ALL_EXTRUDERS \ PASSWORD_FEATURE PASSWORD_ON_STARTUP PASSWORD_ON_SD_PRINT_MENU PASSWORD_AFTER_SD_PRINT_END PASSWORD_AFTER_SD_PRINT_ABORT \ AUTO_BED_LEVELING_BILINEAR Z_MIN_PROBE_REPEATABILITY_TEST DISTINCT_E_FACTORS \ diff --git a/ini/features.ini b/ini/features.ini index 4d394e0901..fac9cf9b57 100644 --- a/ini/features.ini +++ b/ini/features.ini @@ -24,7 +24,7 @@ HAS_STEALTHCHOP = src_filter=+ -HAS_TMC26X = TMC26XStepper=https://github.com/trinamic/TMC26XStepper/archive/master.zip +HAS_TMC26X = TMC26XStepper=https://github.com/MarlinFirmware/TMC26XStepper/archive/master.zip src_filter=+ HAS_L64XX = Arduino-L6470@0.8.0 src_filter=+ + + + @@ -47,7 +47,7 @@ SOFT_I2C_EEPROM = SlowSoftI2CMaster, SlowSoftWire=https:/ SPI_EEPROM = src_filter=+ HAS_DWIN_E3V2|IS_DWIN_MARLINUI = src_filter=+ DWIN_CREALITY_LCD = src_filter=+ -DWIN_CREALITY_LCD_ENHANCED = src_filter=+ +DWIN_LCD_PROUI = src_filter=+ DWIN_CREALITY_LCD_JYERSUI = src_filter=+ IS_DWIN_MARLINUI = src_filter=+ HAS_GRAPHICAL_TFT = src_filter=+ @@ -98,7 +98,7 @@ USB_FLASH_DRIVE_SUPPORT = src_filter=+ + AUTO_BED_LEVELING_BILINEAR = src_filter=+ AUTO_BED_LEVELING_(3POINT|(BI)?LINEAR) = src_filter=+ -X_AXIS_TWIST_COMPENSATION = src_filter=+ + +X_AXIS_TWIST_COMPENSATION = src_filter=+ + + MESH_BED_LEVELING = src_filter=+ + AUTO_BED_LEVELING_UBL = src_filter=+ + UBL_HILBERT_CURVE = src_filter=+ @@ -199,11 +199,11 @@ AUTO_REPORT_POSITION = src_filter=+ REPETIER_GCODE_M360 = src_filter=+ HAS_GCODE_M876 = src_filter=+ HAS_RESUME_CONTINUE = src_filter=+ +LCD_SET_PROGRESS_MANUALLY = src_filter=+ HAS_STATUS_MESSAGE = src_filter=+ HAS_LCD_CONTRAST = src_filter=+ HAS_LCD_BRIGHTNESS = src_filter=+ HAS_BUZZER = src_filter=+ -LCD_SET_PROGRESS_MANUALLY = src_filter=+ TOUCH_SCREEN_CALIBRATION = src_filter=+ ARC_SUPPORT = src_filter=+ GCODE_MOTION_MODES = src_filter=+ @@ -218,6 +218,7 @@ HAS_EXTRUDERS = src_filter=+ HAS_COOLER = src_filter=+ AUTO_REPORT_TEMPERATURES = src_filter=+ +MPCTEMP = src_filter=+ INCH_MODE_SUPPORT = src_filter=+ TEMPERATURE_UNITS_SUPPORT = src_filter=+ NEED_HEX_PRINT = src_filter=+ diff --git a/ini/stm32-common.ini b/ini/stm32-common.ini index 54bc746ff4..1d3f858bf8 100644 --- a/ini/stm32-common.ini +++ b/ini/stm32-common.ini @@ -16,6 +16,7 @@ build_flags = ${common.build_flags} -std=gnu++14 -DHAL_STM32 -DUSBCON -DUSBD_USE_CDC -DTIM_IRQ_PRIO=13 + -DADC_RESOLUTION=12 build_unflags = -std=gnu++11 src_filter = ${common.default_src_filter} + + extra_scripts = ${common.extra_scripts} diff --git a/ini/stm32f1.ini b/ini/stm32f1.ini index 07b75e4e94..9002f81a81 100644 --- a/ini/stm32f1.ini +++ b/ini/stm32f1.ini @@ -73,6 +73,17 @@ build_flags = ${env:STM32F103RC_btt.build_flags} -DUSBD_USE_CDC_MSC build_unflags = ${common_stm32.build_unflags} -DUSBD_USE_CDC +# +# Panda Pi V2.9 - Standalone (STM32F103RC) +# Headless, without direct Pi control, but potentially hosting OctoPrint, stepdaemon, etc. +# +[env:PANDA_PI_V29] +extends = common_STM32F103RC_variant +build_flags = ${common_STM32F103RC_variant.build_flags} + -DTIMER_SERVO=TIM1 +board_build.offset = 0x5000 +board_upload.offset_address = 0x08005000 + # # MKS Robin (STM32F103ZET6) # Uses HAL STM32 to support Marlin UI for TFT screen with optional touch panel diff --git a/ini/stm32f4.ini b/ini/stm32f4.ini index 9e6e213427..d7c160d639 100644 --- a/ini/stm32f4.ini +++ b/ini/stm32f4.ini @@ -298,9 +298,8 @@ extends = env:BIGTREE_OCTOPUS_PRO_V1_F429 platform_packages = ${stm_flash_drive.platform_packages} build_unflags = -DUSBD_USE_CDC build_flags = ${stm_flash_drive.build_flags} - -DSTM32F446_5VX -DUSE_USB_HS_IN_FS - -DUSE_USBHOST_HS -DUSBD_IRQ_PRIO=5 - -DUSBD_IRQ_SUBPRIO=6 + -DUSE_USB_HS_IN_FS -DUSE_USBHOST_HS + -DUSBD_IRQ_PRIO=5 -DUSBD_IRQ_SUBPRIO=6 -DUSBD_USE_CDC_MSC # diff --git a/ini/stm32g0.ini b/ini/stm32g0.ini index 171945ffe2..e6094c1e31 100644 --- a/ini/stm32g0.ini +++ b/ini/stm32g0.ini @@ -30,7 +30,6 @@ board = marlin_STM32G0B1RE board_build.offset = 0x2000 board_upload.offset_address = 0x08002000 build_flags = ${stm32_variant.build_flags} - -DADC_RESOLUTION=12 -DPIN_SERIAL4_RX=PC_11 -DPIN_SERIAL4_TX=PC_10 -DSERIAL_RX_BUFFER_SIZE=1024 -DSERIAL_TX_BUFFER_SIZE=1024 -DTIMER_SERVO=TIM3 -DTIMER_TONE=TIM4 diff --git a/platformio.ini b/platformio.ini index 9b64bdd377..79ef54bd47 100644 --- a/platformio.ini +++ b/platformio.ini @@ -150,7 +150,7 @@ default_src_filter = + - - + - - - - - - + - - - - - @@ -215,11 +215,11 @@ default_src_filter = + - - + - - - + - - - - - - - - - - - @@ -239,6 +239,7 @@ default_src_filter = + - - + - - - + - - - -