From b8cc61262f5d4f322f537e7eb2ac75bec9490249 Mon Sep 17 00:00:00 2001
From: InsanityAutomation
 <38436470+InsanityAutomation@users.noreply.github.com>
Date: Wed, 17 Jul 2019 04:41:04 -0400
Subject: [PATCH] Finish G12, update Nozzle::clean (#14642)

---
 Marlin/src/feature/bedlevel/bedlevel.cpp |  4 ++++
 Marlin/src/feature/bedlevel/bedlevel.h   | 12 ++++++++++
 Marlin/src/feature/pause.cpp             |  2 +-
 Marlin/src/feature/prusa_MMU2/mmu2.cpp   |  2 +-
 Marlin/src/gcode/calibrate/G425.cpp      | 15 ------------
 Marlin/src/gcode/feature/clean/G12.cpp   | 29 +++++++++---------------
 Marlin/src/gcode/feature/pause/G27.cpp   |  2 +-
 Marlin/src/libs/nozzle.cpp               | 26 +++++++++++++++------
 Marlin/src/libs/nozzle.h                 |  4 +++-
 Marlin/src/module/tool_change.cpp        | 16 ++++---------
 10 files changed, 57 insertions(+), 55 deletions(-)

diff --git a/Marlin/src/feature/bedlevel/bedlevel.cpp b/Marlin/src/feature/bedlevel/bedlevel.cpp
index 1ce89d1e05..e6bc47a62b 100644
--- a/Marlin/src/feature/bedlevel/bedlevel.cpp
+++ b/Marlin/src/feature/bedlevel/bedlevel.cpp
@@ -100,6 +100,10 @@ void set_bed_leveling_enabled(const bool enable/*=true*/) {
   }
 }
 
+TemporaryBedLevelingState::TemporaryBedLevelingState(const bool enable) : saved(planner.leveling_active) {
+  set_bed_leveling_enabled(enable);
+}
+
 #if ENABLED(ENABLE_LEVELING_FADE_HEIGHT)
 
   void set_z_fade_height(const float zfh, const bool do_report/*=true*/) {
diff --git a/Marlin/src/feature/bedlevel/bedlevel.h b/Marlin/src/feature/bedlevel/bedlevel.h
index 82957c4884..e5f0db47f7 100644
--- a/Marlin/src/feature/bedlevel/bedlevel.h
+++ b/Marlin/src/feature/bedlevel/bedlevel.h
@@ -46,6 +46,18 @@ void reset_bed_level();
   void _manual_goto_xy(const float &x, const float &y);
 #endif
 
+/**
+ * A class to save and change the bed leveling state,
+ * then restore it when it goes out of scope.
+ */
+class TemporaryBedLevelingState {
+  bool saved;
+  public:
+    TemporaryBedLevelingState(const bool enable);
+    ~TemporaryBedLevelingState() { set_bed_leveling_enabled(saved); }
+};
+#define TEMPORARY_BED_LEVELING_STATE(enable) TemporaryBedLevelingState tbls(enable)
+
 #if HAS_MESH
 
   typedef float (&bed_mesh_t)[GRID_MAX_POINTS_X][GRID_MAX_POINTS_Y];
diff --git a/Marlin/src/feature/pause.cpp b/Marlin/src/feature/pause.cpp
index 74009c9f30..fddf42d7b1 100644
--- a/Marlin/src/feature/pause.cpp
+++ b/Marlin/src/feature/pause.cpp
@@ -436,7 +436,7 @@ bool pause_print(const float &retract, const point_t &park_point, const float &u
 
   // Park the nozzle by moving up by z_lift and then moving to (x_pos, y_pos)
   if (!axis_unhomed_error())
-    Nozzle::park(2, park_point);
+    nozzle.park(2, park_point);
 
   #if ENABLED(DUAL_X_CARRIAGE)
     const int8_t saved_ext        = active_extruder;
diff --git a/Marlin/src/feature/prusa_MMU2/mmu2.cpp b/Marlin/src/feature/prusa_MMU2/mmu2.cpp
index 8453afc601..3450e98b3f 100644
--- a/Marlin/src/feature/prusa_MMU2/mmu2.cpp
+++ b/Marlin/src/feature/prusa_MMU2/mmu2.cpp
@@ -573,7 +573,7 @@ void MMU2::manage_response(const bool move_axes, const bool turn_off_nozzle) {
         COPY(resume_position, current_position);
 
         if (move_axes && all_axes_homed())
-          Nozzle::park(2, park_point /*= NOZZLE_PARK_POINT*/);
+          nozzle.park(2, park_point /*= NOZZLE_PARK_POINT*/);
 
         if (turn_off_nozzle) thermalManager.setTargetHotend(0, active_extruder);
 
diff --git a/Marlin/src/gcode/calibrate/G425.cpp b/Marlin/src/gcode/calibrate/G425.cpp
index c3356f0784..996b1515b3 100644
--- a/Marlin/src/gcode/calibrate/G425.cpp
+++ b/Marlin/src/gcode/calibrate/G425.cpp
@@ -74,7 +74,6 @@ struct measurements_t {
   float nozzle_outer_dimension[2] = {CALIBRATION_NOZZLE_OUTER_DIAMETER, CALIBRATION_NOZZLE_OUTER_DIAMETER};
 };
 
-#define TEMPORARY_BED_LEVELING_STATE(enable) TemporaryBedLevelingState tbls(enable)
 #define TEMPORARY_SOFT_ENDSTOP_STATE(enable) REMEMBER(tes, soft_endstops_enabled, enable);
 
 #if ENABLED(BACKLASH_GCODE)
@@ -89,20 +88,6 @@ struct measurements_t {
   #define TEMPORARY_BACKLASH_SMOOTHING(value)
 #endif
 
-/**
- * A class to save and change the bed leveling state,
- * then restore it when it goes out of scope.
- */
-class TemporaryBedLevelingState {
-  bool saved;
-
-  public:
-    TemporaryBedLevelingState(const bool enable) : saved(planner.leveling_active) {
-      set_bed_leveling_enabled(enable);
-    }
-    ~TemporaryBedLevelingState() { set_bed_leveling_enabled(saved); }
-};
-
 /**
  * Move to a particular location. Up to three individual axes
  * and their destinations can be specified, in any order.
diff --git a/Marlin/src/gcode/feature/clean/G12.cpp b/Marlin/src/gcode/feature/clean/G12.cpp
index c831f1fbfc..30c71264eb 100644
--- a/Marlin/src/gcode/feature/clean/G12.cpp
+++ b/Marlin/src/gcode/feature/clean/G12.cpp
@@ -42,32 +42,25 @@ void GcodeSuite::G12() {
   // Don't allow nozzle cleaning without homing first
   if (axis_unhomed_error()) return;
 
-  const bool seenxyz = parser.seen("XYZ"),
-             clean_x = !seenxyz || parser.boolval('X'),
-             clean_y = !seenxyz || parser.boolval('Y');
-
-  #if ENABLED(NOZZLE_CLEAN_NO_Z)
-    static constexpr bool clean_z = false;
-  #else
-    const bool clean_z = !seenxyz || parser.boolval('Z');
-  #endif
-
   const uint8_t pattern = parser.ushortval('P', 0),
                 strokes = parser.ushortval('S', NOZZLE_CLEAN_STROKES),
                 objects = parser.ushortval('T', NOZZLE_CLEAN_TRIANGLES);
   const float radius = parser.floatval('R', NOZZLE_CLEAN_CIRCLE_RADIUS);
 
+  const bool seenxyz = parser.seen("XYZ");
+  const uint8_t cleans =  (!seenxyz || parser.boolval('X') ? _BV(X_AXIS) : 0)
+                        | (!seenxyz || parser.boolval('Y') ? _BV(Y_AXIS) : 0)
+                        #if DISABLED(NOZZLE_CLEAN_NO_Z)
+                          | (!seenxyz || parser.boolval('Z') ? _BV(Z_AXIS) : 0)
+                        #endif
+                      ;
+
   #if HAS_LEVELING
-    const bool was_enabled = planner.leveling_active;
-    if (clean_z) set_bed_leveling_enabled(false);
+    // Disable bed leveling if cleaning Z
+    TEMPORARY_BED_LEVELING_STATE(!TEST(cleans, Z_AXIS) && planner.leveling_active);
   #endif
 
-  Nozzle::clean(pattern, strokes, radius, objects, clean_x, clean_y, clean_z);
-
-  // Re-enable bed level correction if it had been on
-  #if HAS_LEVELING
-    if (clean_z) set_bed_leveling_enabled(was_enabled);
-  #endif
+  nozzle.clean(pattern, strokes, radius, objects, cleans);
 }
 
 #endif // NOZZLE_CLEAN_FEATURE
diff --git a/Marlin/src/gcode/feature/pause/G27.cpp b/Marlin/src/gcode/feature/pause/G27.cpp
index 3b49ae283e..4f4c9e4698 100644
--- a/Marlin/src/gcode/feature/pause/G27.cpp
+++ b/Marlin/src/gcode/feature/pause/G27.cpp
@@ -35,7 +35,7 @@
 void GcodeSuite::G27() {
   // Don't allow nozzle parking without homing first
   if (axis_unhomed_error()) return;
-  Nozzle::park(parser.ushortval('P'));
+  nozzle.park(parser.ushortval('P'));
 }
 
 #endif // NOZZLE_PARK_FEATURE
diff --git a/Marlin/src/libs/nozzle.cpp b/Marlin/src/libs/nozzle.cpp
index 27c214b876..3926bfc93c 100644
--- a/Marlin/src/libs/nozzle.cpp
+++ b/Marlin/src/libs/nozzle.cpp
@@ -26,6 +26,8 @@
 
 #include "nozzle.h"
 
+Nozzle nozzle;
+
 #include "../Marlin.h"
 #include "../module/motion.h"
 #include "point_t.h"
@@ -155,24 +157,34 @@
    * @param pattern one of the available patterns
    * @param argument depends on the cleaning pattern
    */
-  void Nozzle::clean(const uint8_t &pattern, const uint8_t &strokes, const float &radius, const uint8_t &objects, const bool clean_x, const bool clean_y, const bool clean_z) {
+  void Nozzle::clean(const uint8_t &pattern, const uint8_t &strokes, const float &radius, const uint8_t &objects, const uint8_t cleans) {
     point_t start = NOZZLE_CLEAN_START_POINT;
     point_t end = NOZZLE_CLEAN_END_POINT;
-    if (!clean_x) start.x = end.x = current_position[X_AXIS];
-    if (!clean_y) start.y = end.y = current_position[Y_AXIS];
-    if (!clean_z) start.z = end.z = current_position[Z_AXIS];
+
+    if (pattern == 2) {
+      if (!(cleans & (_BV(X_AXIS) | _BV(Y_AXIS)))) {
+        SERIAL_ECHOLNPGM("Warning : Clean Circle requires XY");
+        return;
+      }
+      end = NOZZLE_CLEAN_CIRCLE_MIDDLE;
+    }
+    else {
+      if (!TEST(cleans, X_AXIS)) start.x = end.x = current_position[X_AXIS];
+      if (!TEST(cleans, Y_AXIS)) start.y = end.y = current_position[Y_AXIS];
+    }
+    if (!TEST(cleans, Z_AXIS)) start.z = end.z = current_position[Z_AXIS];
 
     switch (pattern) {
       case 1:
-        zigzag(NOZZLE_CLEAN_START_POINT, NOZZLE_CLEAN_END_POINT, strokes, objects);
+        zigzag(start, end, strokes, objects);
         break;
 
       case 2:
-        circle(NOZZLE_CLEAN_START_POINT, NOZZLE_CLEAN_CIRCLE_MIDDLE, strokes, radius);
+        circle(start, end, strokes, radius);
         break;
 
       default:
-        stroke(NOZZLE_CLEAN_START_POINT, NOZZLE_CLEAN_END_POINT, strokes);
+        stroke(start, end, strokes);
     }
   }
 
diff --git a/Marlin/src/libs/nozzle.h b/Marlin/src/libs/nozzle.h
index dc8513f28b..d20b41de93 100644
--- a/Marlin/src/libs/nozzle.h
+++ b/Marlin/src/libs/nozzle.h
@@ -78,7 +78,7 @@ class Nozzle {
      * @param pattern one of the available patterns
      * @param argument depends on the cleaning pattern
      */
-    static void clean(const uint8_t &pattern, const uint8_t &strokes, const float &radius, const uint8_t &objects, const bool clean_x, const bool clean_y, const bool clean_z) _Os;
+    static void clean(const uint8_t &pattern, const uint8_t &strokes, const float &radius, const uint8_t &objects, const uint8_t cleans) _Os;
 
   #endif // NOZZLE_CLEAN_FEATURE
 
@@ -88,3 +88,5 @@ class Nozzle {
 
   #endif
 };
+
+extern Nozzle nozzle;
diff --git a/Marlin/src/module/tool_change.cpp b/Marlin/src/module/tool_change.cpp
index 73f3716960..7f1f6aab20 100644
--- a/Marlin/src/module/tool_change.cpp
+++ b/Marlin/src/module/tool_change.cpp
@@ -822,12 +822,6 @@ void tool_change(const uint8_t tmp_extruder, bool no_move/*=false*/) {
          return invalid_extruder_error(tmp_extruder);
     #endif
 
-    #if HAS_LEVELING
-      // Set current position to the physical position
-      const bool leveling_was_active = planner.leveling_active;
-      set_bed_leveling_enabled(false);
-    #endif
-
     if (tmp_extruder >= EXTRUDERS)
       return invalid_extruder_error(tmp_extruder);
 
@@ -875,6 +869,11 @@ void tool_change(const uint8_t tmp_extruder, bool no_move/*=false*/) {
       }
     #endif // TOOLCHANGE_FILAMENT_SWAP
 
+    #if HAS_LEVELING
+      // Set current position to the physical position
+      TEMPORARY_BED_LEVELING_STATE(false);
+    #endif
+
     if (tmp_extruder != active_extruder) {
 
       #if SWITCHING_NOZZLE_TWO_SERVOS
@@ -1071,11 +1070,6 @@ void tool_change(const uint8_t tmp_extruder, bool no_move/*=false*/) {
       fanmux_switch(active_extruder);
     #endif
 
-    #if HAS_LEVELING
-      // Restore leveling to re-establish the logical position
-      set_bed_leveling_enabled(leveling_was_active);
-    #endif
-
     SERIAL_ECHO_START();
     SERIAL_ECHOLNPAIR(MSG_ACTIVE_EXTRUDER, int(active_extruder));