From 2282801172abdbce0b26b993d8d3be9ab4ae3649 Mon Sep 17 00:00:00 2001
From: Scott Lahteine <thinkyhead@users.noreply.github.com>
Date: Wed, 11 Nov 2020 16:58:34 -0600
Subject: [PATCH] Add HOME_Z_FIRST option (#20113)

---
 Marlin/Configuration_adv.h         |  1 +
 Marlin/src/gcode/calibrate/G28.cpp | 13 ++++---------
 Marlin/src/inc/Conditionals_LCD.h  |  4 ++++
 Marlin/src/inc/SanityCheck.h       |  6 +++++-
 4 files changed, 14 insertions(+), 10 deletions(-)

diff --git a/Marlin/Configuration_adv.h b/Marlin/Configuration_adv.h
index d05388075a..0acf2e5f77 100644
--- a/Marlin/Configuration_adv.h
+++ b/Marlin/Configuration_adv.h
@@ -660,6 +660,7 @@
 
 //#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
+//#define HOME_Z_FIRST                        // Home Z first. Requires a Z-MIN endstop (not a probe).
 //#define CODEPENDENT_XY_HOMING               // If X/Y can't home without homing Y/X first
 
 // @section bltouch
diff --git a/Marlin/src/gcode/calibrate/G28.cpp b/Marlin/src/gcode/calibrate/G28.cpp
index a91dd82a2a..ef39290d2d 100644
--- a/Marlin/src/gcode/calibrate/G28.cpp
+++ b/Marlin/src/gcode/calibrate/G28.cpp
@@ -313,7 +313,7 @@ void GcodeSuite::G28() {
                home_all = homeX == homeY && homeX == homeZ, // All or None
                doX = home_all || homeX, doY = home_all || homeY, doZ = home_all || homeZ;
 
-    #if Z_HOME_DIR > 0  // If homing away from BED do Z first
+    #if ENABLED(HOME_Z_FIRST)
 
       if (doZ) homeaxis(Z_AXIS);
 
@@ -373,18 +373,13 @@ void GcodeSuite::G28() {
     TERN_(IMPROVE_HOMING_RELIABILITY, end_slow_homing(slow_homing));
 
     // Home Z last if homing towards the bed
-    #if Z_HOME_DIR < 0
-
+    #if DISABLED(HOME_Z_FIRST)
       if (doZ) {
         TERN_(BLTOUCH, bltouch.init());
-
         TERN(Z_SAFE_HOMING, home_z_safely(), homeaxis(Z_AXIS));
-
         probe.move_z_after_homing();
-
-      } // doZ
-
-    #endif // Z_HOME_DIR < 0
+      }
+    #endif
 
     sync_plan_position();
 
diff --git a/Marlin/src/inc/Conditionals_LCD.h b/Marlin/src/inc/Conditionals_LCD.h
index 865365c0ee..0bb98e9e06 100644
--- a/Marlin/src/inc/Conditionals_LCD.h
+++ b/Marlin/src/inc/Conditionals_LCD.h
@@ -778,6 +778,10 @@
   #undef Z_MIN_PROBE_USES_Z_MIN_ENDSTOP_PIN
 #endif
 
+#if Z_HOME_DIR > 0
+  #define HOME_Z_FIRST // If homing away from BED do Z first
+#endif
+
 /**
  * Set granular options based on the specific type of leveling
  */
diff --git a/Marlin/src/inc/SanityCheck.h b/Marlin/src/inc/SanityCheck.h
index 10f4676aa9..0f98a8badf 100644
--- a/Marlin/src/inc/SanityCheck.h
+++ b/Marlin/src/inc/SanityCheck.h
@@ -1548,7 +1548,7 @@ static_assert(hbm[Z_AXIS] >= 0, "HOMING_BUMP_MM.Z must be greater than or equal
  * Deploying the Allen Key probe uses big moves in z direction. Too dangerous for an unhomed z-axis.
  */
 #if ENABLED(Z_PROBE_ALLEN_KEY) && (Z_HOME_DIR < 0) && ENABLED(Z_MIN_PROBE_USES_Z_MIN_ENDSTOP_PIN)
-  #error "You can't home to a z min endstop with a Z_PROBE_ALLEN_KEY."
+  #error "You can't home to a Z min endstop with a Z_PROBE_ALLEN_KEY."
 #endif
 
 /**
@@ -1965,6 +1965,10 @@ static_assert(hbm[Z_AXIS] >= 0, "HOMING_BUMP_MM.Z must be greater than or equal
   #error "Enable USE_ZMAX_PLUG when homing Z to MAX."
 #endif
 
+#if BOTH(HOME_Z_FIRST, USE_PROBE_FOR_Z_HOMING)
+  #error "HOME_Z_FIRST can't be used when homing Z with a probe."
+#endif
+
 // Dual/multiple endstops requirements
 #if ENABLED(X_DUAL_ENDSTOPS)
   #if !X2_USE_ENDSTOP