From a3b098b4bee1c44b59e0ab9195ae1640c938ac44 Mon Sep 17 00:00:00 2001
From: Scott Lahteine <github@thinkyhead.com>
Date: Wed, 6 Dec 2017 13:54:58 -0600
Subject: [PATCH 1/7] Whitespace clean

---
 Marlin/src/HAL/HAL_LPC1768/spi_pins.h | 16 ++++++++--------
 Marlin/src/pins/pins_MELZI_CREALITY.h |  2 +-
 2 files changed, 9 insertions(+), 9 deletions(-)

diff --git a/Marlin/src/HAL/HAL_LPC1768/spi_pins.h b/Marlin/src/HAL/HAL_LPC1768/spi_pins.h
index 3eec6d45d8a..4016b1f72dd 100644
--- a/Marlin/src/HAL/HAL_LPC1768/spi_pins.h
+++ b/Marlin/src/HAL/HAL_LPC1768/spi_pins.h
@@ -26,22 +26,22 @@
 #include "../../inc/MarlinConfig.h"
 
 #if MB(MKS_SBASE)
-  
-#define LPC_SOFTWARE_SPI  // MKS_SBASE needs a software SPI because the 
+
+#define LPC_SOFTWARE_SPI  // MKS_SBASE needs a software SPI because the
                           // selected pins are not on a hardware SPI controller
 
-// A custom cable is needed. See the README file in the 
+// A custom cable is needed. See the README file in the
 // Marlin\src\config\examples\Mks\Sbase directory
 
 #define SCK_PIN           P1_22  // J8-2 (moved from EXP2 P0.7)
-#define MISO_PIN          P1_23  // J8-3 (moved from EXP2 P0.8)  
-#define MOSI_PIN          P2_12  // J8-4 (moved from EXP2 P0.5)  
-#define SS_PIN            P0_28  
+#define MISO_PIN          P1_23  // J8-3 (moved from EXP2 P0.8)
+#define MOSI_PIN          P2_12  // J8-4 (moved from EXP2 P0.5)
+#define SS_PIN            P0_28
 
 #else
 
-#define LPC_SOFTWARE_SPI  // Re-ARM board needs a software SPI because using the 
-                          // standard LCD adapter results in the LCD and the 
+#define LPC_SOFTWARE_SPI  // Re-ARM board needs a software SPI because using the
+                          // standard LCD adapter results in the LCD and the
                           // SD card sharing a single SPI when the RepRap Full
                           // Graphic Smart Controller is selected
 
diff --git a/Marlin/src/pins/pins_MELZI_CREALITY.h b/Marlin/src/pins/pins_MELZI_CREALITY.h
index 477a9b8e077..02f8491102a 100644
--- a/Marlin/src/pins/pins_MELZI_CREALITY.h
+++ b/Marlin/src/pins/pins_MELZI_CREALITY.h
@@ -60,7 +60,7 @@
 #define ST7920_DELAY_3 DELAY_2_NOP
 
 #if ENABLED(MINIPANEL)
-  #undef DOGLCD_CS    
+  #undef DOGLCD_CS
   #define DOGLCD_CS        LCD_PINS_RS
 #endif
 

From a4e1d83599f0daeabf7e7096e131b5c66b7bb017 Mon Sep 17 00:00:00 2001
From: Scott Lahteine <github@thinkyhead.com>
Date: Wed, 6 Dec 2017 21:16:00 -0600
Subject: [PATCH 2/7] Fix M503 S parameter

---
 Marlin/src/gcode/eeprom/M500-M503.cpp     | 2 +-
 Marlin/src/module/configuration_store.cpp | 2 +-
 Marlin/src/module/configuration_store.h   | 4 ++--
 3 files changed, 4 insertions(+), 4 deletions(-)

diff --git a/Marlin/src/gcode/eeprom/M500-M503.cpp b/Marlin/src/gcode/eeprom/M500-M503.cpp
index 61f5aab4ae2..45faa101794 100644
--- a/Marlin/src/gcode/eeprom/M500-M503.cpp
+++ b/Marlin/src/gcode/eeprom/M500-M503.cpp
@@ -51,7 +51,7 @@ void GcodeSuite::M502() {
    * M503: print settings currently in memory
    */
   void GcodeSuite::M503() {
-    (void)settings.report(parser.boolval('S'));
+    (void)settings.report(parser.seen('S') && !parser.value_bool());
   }
 
 #endif // !DISABLE_M503
diff --git a/Marlin/src/module/configuration_store.cpp b/Marlin/src/module/configuration_store.cpp
index 9caebff1ac8..3eef0d8b3d4 100644
--- a/Marlin/src/module/configuration_store.cpp
+++ b/Marlin/src/module/configuration_store.cpp
@@ -1527,7 +1527,7 @@ void MarlinSettings::reset() {
    *
    * Unless specifically disabled, M503 is available even without EEPROM
    */
-  void MarlinSettings::report(bool forReplay) {
+  void MarlinSettings::report(const bool forReplay) {
 
     /**
      * Announce current units, in case inches are being displayed
diff --git a/Marlin/src/module/configuration_store.h b/Marlin/src/module/configuration_store.h
index 03c304d94ab..e23b66a6652 100644
--- a/Marlin/src/module/configuration_store.h
+++ b/Marlin/src/module/configuration_store.h
@@ -52,10 +52,10 @@ class MarlinSettings {
     #endif
 
     #if DISABLED(DISABLE_M503)
-      static void report(bool forReplay=false);
+      static void report(const bool forReplay=false);
     #else
       FORCE_INLINE
-      static void report(bool forReplay=false) { UNUSED(forReplay); }
+      static void report(const bool forReplay=false) { UNUSED(forReplay); }
     #endif
 
   private:

From 6040d4080ee347b5276f93cf09a6cfc75286dc74 Mon Sep 17 00:00:00 2001
From: Scott Lahteine <github@thinkyhead.com>
Date: Wed, 6 Dec 2017 12:43:41 -0600
Subject: [PATCH 3/7] Cleanup stepper ISR. Allow cleaning for endstops.

---
 Marlin/src/module/stepper.cpp | 60 ++++++++++++++++++-----------------
 Marlin/src/module/stepper.h   |  2 +-
 2 files changed, 32 insertions(+), 30 deletions(-)

diff --git a/Marlin/src/module/stepper.cpp b/Marlin/src/module/stepper.cpp
index 47fac7285aa..89429941750 100644
--- a/Marlin/src/module/stepper.cpp
+++ b/Marlin/src/module/stepper.cpp
@@ -94,7 +94,7 @@ block_t* Stepper::current_block = NULL;  // A pointer to the block currently bei
 // private:
 
 uint8_t Stepper::last_direction_bits = 0;        // The next stepping-bits to be output
-uint16_t Stepper::cleaning_buffer_counter = 0;
+int16_t Stepper::cleaning_buffer_counter = 0;
 
 #if ENABLED(X_DUAL_ENDSTOPS)
   bool Stepper::locked_x_motor = false;
@@ -341,10 +341,8 @@ HAL_STEP_TIMER_ISR {
 
 void Stepper::isr() {
 
-  hal_timer_t ocr_val;
-
-  #define ENDSTOP_NOMINAL_OCR_VAL 1500 * HAL_TICKS_PER_US    // check endstops every 1.5ms to guarantee two stepper ISRs within 5ms for BLTouch
-  #define OCR_VAL_TOLERANCE 500 * HAL_TICKS_PER_US           // First max delay is 2.0ms, last min delay is 0.5ms, all others 1.5ms
+  #define ENDSTOP_NOMINAL_OCR_VAL 1500 * HAL_TICKS_PER_US // Check endstops every 1.5ms to guarantee two stepper ISRs within 5ms for BLTouch
+  #define OCR_VAL_TOLERANCE        500 * HAL_TICKS_PER_US // First max delay is 2.0ms, last min delay is 0.5ms, all others 1.5ms
 
   #if DISABLED(LIN_ADVANCE)
     // Disable Timer0 ISRs and enable global ISR again to capture UART events (incoming chars)
@@ -355,6 +353,7 @@ void Stepper::isr() {
     #endif
   #endif
 
+  hal_timer_t ocr_val;
   static uint32_t step_remaining = 0;  // SPLIT function always runs.  This allows 16 bit timers to be
                                        // used to generate the stepper ISR.
   #define SPLIT(L) do { \
@@ -367,42 +366,45 @@ void Stepper::isr() {
       ocr_val = L;\
   }while(0)
 
+  // Time remaining before the next step?
   if (step_remaining) {
-    if (ENDSTOPS_ENABLED)
-      endstops.update();
-    if (step_remaining > ENDSTOP_NOMINAL_OCR_VAL) {
-      step_remaining -= ENDSTOP_NOMINAL_OCR_VAL;
-      ocr_val = ENDSTOP_NOMINAL_OCR_VAL;
-    }
-    else {
-      ocr_val = step_remaining;
-      step_remaining = 0;  //  last one before the ISR that does the step
-    }
 
+    // Make sure endstops are updated
+    if (ENDSTOPS_ENABLED) endstops.update();
+
+    // Next ISR either for endstops or stepping
+    ocr_val = step_remaining <= ENDSTOP_NOMINAL_OCR_VAL ? step_remaining : ENDSTOP_NOMINAL_OCR_VAL;
+    step_remaining -= ocr_val;
     _NEXT_ISR(ocr_val);
 
-  #if DISABLED(LIN_ADVANCE)
-    #ifdef CPU_32_BIT
-      HAL_timer_set_count(STEP_TIMER_NUM, ocr_val);
-    #else
-      NOLESS(OCR1A, TCNT1 + 16);
+    #if DISABLED(LIN_ADVANCE)
+      #ifdef CPU_32_BIT
+        HAL_timer_set_count(STEP_TIMER_NUM, ocr_val);
+      #else
+        NOLESS(OCR1A, TCNT1 + 16);
+      #endif
+      HAL_ENABLE_ISRs(); // re-enable ISRs
     #endif
-    HAL_ENABLE_ISRs(); // re-enable ISRs
-  #endif
 
     return;
   }
 
-
+  //
+  // When cleaning, discard the current block and run fast
+  //
   if (cleaning_buffer_counter) {
-    --cleaning_buffer_counter;
+    if (cleaning_buffer_counter < 0)
+      ++cleaning_buffer_counter;                // Count up for endstop hit
+    else {
+      --cleaning_buffer_counter;                // Count down for abort print
+      #ifdef SD_FINISHED_RELEASECOMMAND
+        if (!cleaning_buffer_counter && (SD_FINISHED_STEPPERRELEASE)) enqueue_and_echo_commands_P(PSTR(SD_FINISHED_RELEASECOMMAND));
+      #endif
+    }
     current_block = NULL;
     planner.discard_current_block();
-    #ifdef SD_FINISHED_RELEASECOMMAND
-      if (!cleaning_buffer_counter && (SD_FINISHED_STEPPERRELEASE)) enqueue_and_echo_commands_P(PSTR(SD_FINISHED_RELEASECOMMAND));
-    #endif
-    _NEXT_ISR(HAL_STEPPER_TIMER_RATE / 10000); // Run at max speed - 10 KHz
-    HAL_ENABLE_ISRs(); // re-enable ISRs
+    _NEXT_ISR(HAL_STEPPER_TIMER_RATE / 10000);  // Run at max speed - 10 KHz
+    HAL_ENABLE_ISRs();                          // Re-enable ISRs
     return;
   }
 
diff --git a/Marlin/src/module/stepper.h b/Marlin/src/module/stepper.h
index 9ccd884bb4f..06dac1cd043 100644
--- a/Marlin/src/module/stepper.h
+++ b/Marlin/src/module/stepper.h
@@ -80,7 +80,7 @@ class Stepper {
   private:
 
     static uint8_t last_direction_bits;        // The next stepping-bits to be output
-    static uint16_t cleaning_buffer_counter;
+    static int16_t cleaning_buffer_counter;
 
     #if ENABLED(X_DUAL_ENDSTOPS)
       static bool locked_x_motor, locked_x2_motor;

From 2fde60da124fddb6cf2a8f15479680f3410b53af Mon Sep 17 00:00:00 2001
From: Scott Lahteine <github@thinkyhead.com>
Date: Wed, 6 Dec 2017 16:56:30 -0600
Subject: [PATCH 4/7] Changes for parity with 1.1.x

---
 Marlin/src/feature/bedlevel/ubl/ubl.cpp     |   2 +-
 Marlin/src/feature/bedlevel/ubl/ubl.h       |  14 ++-
 Marlin/src/feature/bedlevel/ubl/ubl_G29.cpp |  36 +++----
 Marlin/src/gcode/bedlevel/G26.cpp           |  25 +++--
 Marlin/src/inc/SanityCheck.h                |   4 +
 Marlin/src/lcd/ultralcd.cpp                 | 104 ++++++++++----------
 Marlin/src/module/planner.cpp               |  13 ++-
 Marlin/src/module/stepper.cpp               |  11 +--
 8 files changed, 105 insertions(+), 104 deletions(-)

diff --git a/Marlin/src/feature/bedlevel/ubl/ubl.cpp b/Marlin/src/feature/bedlevel/ubl/ubl.cpp
index 91c9f5eff07..f32bfe3fa2e 100644
--- a/Marlin/src/feature/bedlevel/ubl/ubl.cpp
+++ b/Marlin/src/feature/bedlevel/ubl/ubl.cpp
@@ -64,7 +64,7 @@
   constexpr float unified_bed_leveling::_mesh_index_to_xpos[16],
                   unified_bed_leveling::_mesh_index_to_ypos[16];
 
-  #if ENABLED(ULTRA_LCD)
+  #if ENABLED(ULTIPANEL)
     bool unified_bed_leveling::lcd_map_control = false;
   #endif
 
diff --git a/Marlin/src/feature/bedlevel/ubl/ubl.h b/Marlin/src/feature/bedlevel/ubl/ubl.h
index bfebeae967a..20c469780b9 100644
--- a/Marlin/src/feature/bedlevel/ubl/ubl.h
+++ b/Marlin/src/feature/bedlevel/ubl/ubl.h
@@ -76,19 +76,23 @@ class unified_bed_leveling {
       static int  g29_grid_size;
     #endif
 
-    static float measure_point_with_encoder();
-    static float measure_business_card_thickness(float);
+    #if ENABLED(NEWPANEL)
+      static void move_z_with_encoder(const float &multiplier);
+      static float measure_point_with_encoder();
+      static float measure_business_card_thickness(const float&);
+      static void manually_probe_remaining_mesh(const float&, const float&, const float&, const float&, const bool);
+      static void fine_tune_mesh(const float &rx, const float &ry, const bool do_ubl_mesh_map);
+    #endif
+
     static bool g29_parameter_parsing();
     static void find_mean_mesh_height();
     static void shift_mesh_height();
     static void probe_entire_mesh(const float &rx, const float &ry, const bool do_ubl_mesh_map, const bool stow_probe, bool do_furthest);
-    static void manually_probe_remaining_mesh(const float&, const float&, const float&, const float&, const bool);
     static void tilt_mesh_based_on_3pts(const float &z1, const float &z2, const float &z3);
     static void tilt_mesh_based_on_probed_grid(const bool do_ubl_mesh_map);
     static void g29_what_command();
     static void g29_eeprom_dump();
     static void g29_compare_current_mesh_to_stored_mesh();
-    static void fine_tune_mesh(const float &rx, const float &ry, const bool do_ubl_mesh_map);
     static bool smart_fill_one(const uint8_t x, const uint8_t y, const int8_t xdir, const int8_t ydir);
     static void smart_fill_mesh();
 
@@ -137,7 +141,7 @@ class unified_bed_leveling {
                               MESH_MIN_Y + 14 * (MESH_Y_DIST), MESH_MIN_Y + 15 * (MESH_Y_DIST)
                             };
 
-    #if ENABLED(ULTRA_LCD)
+    #if ENABLED(ULTIPANEL)
       static bool lcd_map_control;
     #endif
 
diff --git a/Marlin/src/feature/bedlevel/ubl/ubl_G29.cpp b/Marlin/src/feature/bedlevel/ubl/ubl_G29.cpp
index 641d67ed8f2..573ab10ea8a 100644
--- a/Marlin/src/feature/bedlevel/ubl/ubl_G29.cpp
+++ b/Marlin/src/feature/bedlevel/ubl/ubl_G29.cpp
@@ -458,7 +458,7 @@
                               parser.seen('T'), parser.seen('E'), parser.seen('U'));
             break;
 
-        #endif
+        #endif // HAS_BED_PROBE
 
         case 2: {
           #if ENABLED(NEWPANEL)
@@ -913,7 +913,7 @@
 
     static void echo_and_take_a_measurement() { SERIAL_PROTOCOLLNPGM(" and take a measurement."); }
 
-    float unified_bed_leveling::measure_business_card_thickness(const float in_height) {
+    float unified_bed_leveling::measure_business_card_thickness(const float &in_height) {
       lcd_external_control = true;
       save_ubl_active_state_and_disable();   // Disable bed level correction for probing
 
@@ -1033,7 +1033,6 @@
       KEEPALIVE_STATE(IN_HANDLER);
       do_blocking_move_to(rx, ry, Z_CLEARANCE_DEPLOY_PROBE);
     }
-
   #endif // NEWPANEL
 
   bool unified_bed_leveling::g29_parameter_parsing() {
@@ -1078,11 +1077,11 @@
       #endif
         {
           g29_phase_value = pv;
-           if (!WITHIN(g29_phase_value, 0, 6)) {
-             SERIAL_PROTOCOLLNPGM("?(P)hase value invalid (0-6).\n");
-             err_flag = true;
-           }
-         }
+          if (!WITHIN(g29_phase_value, 0, 6)) {
+            SERIAL_PROTOCOLLNPGM("?(P)hase value invalid (0-6).\n");
+            err_flag = true;
+          }
+        }
     }
 
     if (parser.seen('J')) {
@@ -1341,11 +1340,10 @@
         z_values[x][y] -= tmp_z_values[x][y];
   }
 
-
   mesh_index_pair unified_bed_leveling::find_furthest_invalid_mesh_point() {
 
-    bool found_a_NAN  = false;
-    bool found_a_real = false;
+    bool found_a_NAN  = false, found_a_real = false;
+
     mesh_index_pair out_mesh;
     out_mesh.x_index = out_mesh.y_index = -1;
     out_mesh.distance = -99999.99;
@@ -1353,12 +1351,12 @@
     for (int8_t i = 0; i < GRID_MAX_POINTS_X; i++) {
       for (int8_t j = 0; j < GRID_MAX_POINTS_Y; j++) {
 
-        if ( isnan(z_values[i][j])) { // Check to see if this location holds an invalid mesh point
+        if (isnan(z_values[i][j])) { // Check to see if this location holds an invalid mesh point
 
           const float mx = mesh_index_to_xpos(i),
                       my = mesh_index_to_ypos(j);
 
-          if ( !position_is_reachable_by_probe(mx, my))  // make sure the probe can get to the mesh point
+          if (!position_is_reachable_by_probe(mx, my))  // make sure the probe can get to the mesh point
             continue;
 
           found_a_NAN = true;
@@ -1452,6 +1450,7 @@
         }
       } // for j
     } // for i
+
     return out_mesh;
   }
 
@@ -1499,15 +1498,8 @@
         if (!position_is_reachable(rawx, rawy)) // SHOULD NOT OCCUR because find_closest_mesh_point_of_type will only return reachable
           break;
 
-        float new_z = z_values[location.x_index][location.y_index];
-
-        if (isnan(new_z)) // if the mesh point is invalid, set it to 0.0 so it can be edited
-          new_z = 0.0;
-
         do_blocking_move_to(rawx, rawy, Z_CLEARANCE_BETWEEN_PROBES); // Move the nozzle to the edit point
 
-        new_z = FLOOR(new_z * 1000.0) * 0.001; // Chop off digits after the 1000ths place
-
         KEEPALIVE_STATE(PAUSED_FOR_USER);
         lcd_external_control = true;
 
@@ -1515,6 +1507,10 @@
 
         lcd_refresh();
 
+        float new_z = z_values[location.x_index][location.y_index];
+        if (isnan(new_z)) new_z = 0.0;          // Set invalid mesh points to 0.0 so they can be edited
+        new_z = FLOOR(new_z * 1000.0) * 0.001;  // Chop off digits after the 1000ths place
+
         lcd_mesh_edit_setup(new_z);
 
         do {
diff --git a/Marlin/src/gcode/bedlevel/G26.cpp b/Marlin/src/gcode/bedlevel/G26.cpp
index 98499c7ee19..d5791b97f73 100644
--- a/Marlin/src/gcode/bedlevel/G26.cpp
+++ b/Marlin/src/gcode/bedlevel/G26.cpp
@@ -53,6 +53,9 @@
   #error "SIZE_OF_CROSSHAIRS must be less than SIZE_OF_INTERSECTION_CIRCLES."
 #endif
 
+#define G26_OK false
+#define G26_ERR true
+
 /**
  *   G26 Mesh Validation Tool
  *
@@ -268,9 +271,7 @@ void move_to(const float &rx, const float &ry, const float &z, const float &e_de
   set_destination_from_current();
 }
 
-FORCE_INLINE void move_to(const float where[XYZE], const float &de) {
-  move_to(where[X_AXIS], where[Y_AXIS], where[Z_AXIS], de);
-}
+FORCE_INLINE void move_to(const float where[XYZE], const float &de) { move_to(where[X_AXIS], where[Y_AXIS], where[Z_AXIS], de); }
 
 void retract_filament(const float where[XYZE]) {
   if (!g26_retracted) { // Only retract if we are not already retracted!
@@ -314,9 +315,8 @@ void print_line_from_here_to_there(const float &sx, const float &sy, const float
 
   // If the end point of the line is closer to the nozzle, flip the direction,
   // moving from the end to the start. On very small lines the optimization isn't worth it.
-  if (dist_end < dist_start && (SIZE_OF_INTERSECTION_CIRCLES) < FABS(line_length)) {
+  if (dist_end < dist_start && (SIZE_OF_INTERSECTION_CIRCLES) < FABS(line_length))
     return print_line_from_here_to_there(ex, ey, ez, sx, sy, sz);
-  }
 
   // Decide whether to retract & bump
 
@@ -373,7 +373,6 @@ inline bool look_for_lines_to_connect() {
                 SERIAL_EOL();
                 //debug_current_and_destination(PSTR("Connecting horizontal line."));
               }
-
               print_line_from_here_to_there(sx, sy, g26_layer_height, ex, ey, g26_layer_height);
             }
             bitmap_set(horizontal_mesh_line_flags, i, j);   // Mark it as done so we don't do it again, even if we skipped it
@@ -405,8 +404,8 @@ inline bool look_for_lines_to_connect() {
                   SERIAL_ECHOPAIR(", ey=", ey);
                   SERIAL_CHAR(')');
                   SERIAL_EOL();
+
                   #if ENABLED(AUTO_BED_LEVELING_UBL)
-                    void debug_current_and_destination(const char *title);
                     debug_current_and_destination(PSTR("Connecting vertical line."));
                   #endif
                 }
@@ -678,9 +677,8 @@ void GcodeSuite::G26() {
     return;
   }
 
-  g26_x_pos = parser.seenval('X') ? RAW_X_POSITION(parser.value_linear_units()) : current_position[X_AXIS],
+  g26_x_pos = parser.seenval('X') ? RAW_X_POSITION(parser.value_linear_units()) : current_position[X_AXIS];
   g26_y_pos = parser.seenval('Y') ? RAW_Y_POSITION(parser.value_linear_units()) : current_position[Y_AXIS];
-
   if (!position_is_reachable(g26_x_pos, g26_y_pos)) {
     SERIAL_PROTOCOLLNPGM("?Specified X,Y coordinate out of bounds.");
     return;
@@ -727,6 +725,7 @@ void GcodeSuite::G26() {
   #if ENABLED(ULTRA_LCD)
     lcd_external_control = true;
   #endif
+
   //debug_current_and_destination(PSTR("Starting G26 Mesh Validation Pattern."));
 
   /**
@@ -806,7 +805,7 @@ void GcodeSuite::G26() {
         #if IS_KINEMATIC
           // Check to make sure this segment is entirely on the bed, skip if not.
           if (!position_is_reachable(rx, ry) || !position_is_reachable(xe, ye)) continue;
-        #else                                              // not, we need to skip
+        #else                                               // not, we need to skip
           rx = constrain(rx, X_MIN_POS + 1, X_MAX_POS - 1); // This keeps us from bumping the endstops
           ry = constrain(ry, Y_MIN_POS + 1, Y_MAX_POS - 1);
           xe = constrain(xe, X_MIN_POS + 1, X_MAX_POS - 1);
@@ -842,15 +841,15 @@ void GcodeSuite::G26() {
   move_to(destination, 0); // Raise the nozzle
   //debug_current_and_destination(PSTR("done doing Z-Raise."));
 
-  destination[X_AXIS] = g26_x_pos;                                               // Move back to the starting position
+  destination[X_AXIS] = g26_x_pos;                               // Move back to the starting position
   destination[Y_AXIS] = g26_y_pos;
-  //destination[Z_AXIS] = Z_CLEARANCE_BETWEEN_PROBES;                        // Keep the nozzle where it is
+  //destination[Z_AXIS] = Z_CLEARANCE_BETWEEN_PROBES;            // Keep the nozzle where it is
 
   move_to(destination, 0); // Move back to the starting position
   //debug_current_and_destination(PSTR("done doing X/Y move."));
 
   #if ENABLED(ULTRA_LCD)
-    lcd_external_control = false;   // Give back control of the LCD Panel!
+    lcd_external_control = false;     // Give back control of the LCD Panel!
   #endif
 
   if (!g26_keep_heaters_on) {
diff --git a/Marlin/src/inc/SanityCheck.h b/Marlin/src/inc/SanityCheck.h
index e87780b906c..bc85cf9dc1a 100644
--- a/Marlin/src/inc/SanityCheck.h
+++ b/Marlin/src/inc/SanityCheck.h
@@ -313,11 +313,15 @@ static_assert(X_MAX_LENGTH >= X_BED_SIZE && Y_MAX_LENGTH >= Y_BED_SIZE,
 #if ENABLED(LCD_PROGRESS_BAR)
   #if DISABLED(SDSUPPORT)
     #error "LCD_PROGRESS_BAR requires SDSUPPORT."
+  #elif DISABLED(ULTRA_LCD)
+    #error "LCD_PROGRESS_BAR requires a character LCD."
   #elif ENABLED(DOGLCD)
     #error "LCD_PROGRESS_BAR does not apply to graphical displays."
   #elif ENABLED(FILAMENT_LCD_DISPLAY)
     #error "LCD_PROGRESS_BAR and FILAMENT_LCD_DISPLAY are not fully compatible. Comment out this line to use both."
   #endif
+#elif ENABLED(LCD_SET_PROGRESS_MANUALLY) && DISABLED(DOGLCD)
+  #error "LCD_SET_PROGRESS_MANUALLY requires LCD_PROGRESS_BAR or Graphical LCD."
 #endif
 
 /**
diff --git a/Marlin/src/lcd/ultralcd.cpp b/Marlin/src/lcd/ultralcd.cpp
index 4a3500f0e27..ab784a71f2b 100644
--- a/Marlin/src/lcd/ultralcd.cpp
+++ b/Marlin/src/lcd/ultralcd.cpp
@@ -85,12 +85,13 @@ int16_t lcd_preheat_hotend_temp[2], lcd_preheat_bed_temp[2], lcd_preheat_fan_spe
 #endif
 
 uint8_t lcd_status_update_delay = 1, // First update one loop delayed
-        lcd_status_message_level;    // Higher level overrides lower
+        lcd_status_message_level;    // Higher level blocks lower level
 char lcd_status_message[3 * (LCD_WIDTH) + 1] = WELCOME_MSG; // worst case is kana with up to 3*LCD_WIDTH+1
 
 #if ENABLED(STATUS_MESSAGE_SCROLLING)
   uint8_t status_scroll_pos = 0;
 #endif
+
 #if ENABLED(SCROLL_LONG_FILENAMES)
   uint8_t filename_scroll_pos, filename_scroll_max, filename_scroll_hash;
 #endif
@@ -163,8 +164,6 @@ uint16_t max_display_update_time = 0;
     extern bool powersupply_on;
   #endif
 
-  float move_menu_scale;
-
   ////////////////////////////////////////////
   ///////////////// Menu Tree ////////////////
   ////////////////////////////////////////////
@@ -244,7 +243,6 @@ uint16_t max_display_update_time = 0;
     void menu_action_setting_edit_callback_ ## _name(const char * const pstr, _type * const ptr, const _type minValue, const _type maxValue, const screenFunc_t callback, const bool live=false); \
     typedef void _name##_void
 
-  DECLARE_MENU_EDIT_TYPE(uint32_t, long5);
   DECLARE_MENU_EDIT_TYPE(int16_t, int3);
   DECLARE_MENU_EDIT_TYPE(uint8_t, int8);
   DECLARE_MENU_EDIT_TYPE(float, float3);
@@ -254,6 +252,7 @@ uint16_t max_display_update_time = 0;
   DECLARE_MENU_EDIT_TYPE(float, float51);
   DECLARE_MENU_EDIT_TYPE(float, float52);
   DECLARE_MENU_EDIT_TYPE(float, float62);
+  DECLARE_MENU_EDIT_TYPE(uint32_t, long5);
 
   void menu_action_setting_edit_bool(const char* pstr, bool* ptr);
   void menu_action_setting_edit_callback_bool(const char* pstr, bool* ptr, screenFunc_t callbackFunc);
@@ -566,10 +565,9 @@ uint16_t max_display_update_time = 0;
     static bool no_reentry = false;
     if (lcdDrawUpdate) lcd_implementation_drawmenu_static(LCD_HEIGHT >= 4 ? 1 : 0, sync_message);
     if (no_reentry) return;
-
     // Make this the current handler till all moves are done
     no_reentry = true;
-    screenFunc_t old_screen = currentScreen;
+    const screenFunc_t old_screen = currentScreen;
     lcd_goto_screen(_lcd_synchronize);
     stepper.synchronize();
     no_reentry = false;
@@ -997,7 +995,7 @@ void kill_screen(const char* lcd_msg) {
     #if ENABLED(SDSUPPORT)
       if (card.cardOK) {
         if (card.isFileOpen()) {
-          if (IS_SD_PRINTING)
+          if (card.sdprinting)
             MENU_ITEM(function, MSG_PAUSE_PRINT, lcd_sdcard_pause);
           else
             MENU_ITEM(function, MSG_RESUME_PRINT, lcd_sdcard_resume);
@@ -1074,7 +1072,7 @@ void kill_screen(const char* lcd_msg) {
       if (PAGE_CONTAINS(20, 20)) u8g.drawBitmapP(nozzle + 0, 20, 3, 1, offset_bedline_bmp);
 
       // Draw cw/ccw indicator and up/down arrows.
-      if (PAGE_CONTAINS(47,62)) {
+      if (PAGE_CONTAINS(47, 62)) {
         u8g.drawBitmapP(left  + 0, 47, 3, 16, rot_down);
         u8g.drawBitmapP(right + 0, 47, 3, 16, rot_up);
         u8g.drawBitmapP(right + 20, 48 - dir, 2, 13, up_arrow_bmp);
@@ -1115,6 +1113,8 @@ void kill_screen(const char* lcd_msg) {
         ENCODER_DIRECTION_NORMAL();
         if (encoderPosition) {
           const int16_t babystep_increment = (int32_t)encoderPosition * (BABYSTEP_MULTIPLICATOR);
+          encoderPosition = 0;
+
           const float new_zoffset = zprobe_zoffset + planner.steps_to_mm[Z_AXIS] * babystep_increment;
           if (WITHIN(new_zoffset, Z_PROBE_OFFSET_RANGE_MIN, Z_PROBE_OFFSET_RANGE_MAX)) {
 
@@ -1124,7 +1124,6 @@ void kill_screen(const char* lcd_msg) {
             zprobe_zoffset = new_zoffset;
             lcdDrawUpdate = LCDVIEW_CALL_REDRAW_NEXT;
           }
-          encoderPosition = 0;
         }
         if (lcdDrawUpdate) {
           lcd_implementation_drawedit(PSTR(MSG_ZPROBE_ZOFFSET), ftostr43sign(zprobe_zoffset));
@@ -1164,11 +1163,12 @@ void kill_screen(const char* lcd_msg) {
         mesh_edit_value = float(rounded - (rounded % 5L)) / 1000.0;
       }
 
-      if (lcdDrawUpdate)
+      if (lcdDrawUpdate) {
         lcd_implementation_drawedit(msg, ftostr43sign(mesh_edit_value));
         #if ENABLED(MESH_EDIT_GFX_OVERLAY)
           _lcd_zoffset_overlay_gfx(mesh_edit_value);
         #endif
+      }
     }
 
     void _lcd_mesh_edit_NOP() {
@@ -1182,7 +1182,7 @@ void kill_screen(const char* lcd_msg) {
       return mesh_edit_value;
     }
 
-    void lcd_mesh_edit_setup(float initial) {
+    void lcd_mesh_edit_setup(const float initial) {
       mesh_edit_value = mesh_edit_accumulator = initial;
       lcd_goto_screen(_lcd_mesh_edit_NOP);
     }
@@ -1203,6 +1203,7 @@ void kill_screen(const char* lcd_msg) {
 
   #endif // AUTO_BED_LEVELING_UBL
 
+
   /**
    * Watch temperature callbacks
    */
@@ -2030,8 +2031,8 @@ void kill_screen(const char* lcd_msg) {
      */
     void _lcd_ubl_adjust_height_cmd() {
       char UBL_LCD_GCODE[16];
-      const int ind = ubl_height_amount < 0 ? 6 : 7;
-      strcpy_P(UBL_LCD_GCODE, PSTR("G29 P6-"));
+      const int ind = ubl_height_amount > 0 ? 9 : 10;
+      strcpy_P(UBL_LCD_GCODE, PSTR("G29 P6 C -"));
       sprintf_P(&UBL_LCD_GCODE[ind], PSTR(".%i"), abs(ubl_height_amount));
       enqueue_and_echo_command(UBL_LCD_GCODE);
     }
@@ -2047,8 +2048,7 @@ void kill_screen(const char* lcd_msg) {
     void _lcd_ubl_height_adjust_menu() {
       START_MENU();
       MENU_BACK(MSG_UBL_EDIT_MESH_MENU);
-      MENU_ITEM_EDIT(int3, MSG_UBL_MESH_HEIGHT_AMOUNT, &ubl_height_amount, -9, 9);
-      MENU_ITEM(function, MSG_UBL_MESH_HEIGHT_ADJUST, _lcd_ubl_adjust_height_cmd);
+      MENU_ITEM_EDIT_CALLBACK(int3, MSG_UBL_MESH_HEIGHT_AMOUNT, &ubl_height_amount, -9, 9, _lcd_ubl_adjust_height_cmd);
       MENU_ITEM(function, MSG_WATCH, lcd_return_to_status);
       END_MENU();
     }
@@ -2184,8 +2184,7 @@ void kill_screen(const char* lcd_msg) {
     void _lcd_ubl_fillin_menu() {
       START_MENU();
       MENU_BACK(MSG_UBL_BUILD_MESH_MENU);
-      MENU_ITEM_EDIT(int3, MSG_UBL_FILLIN_AMOUNT, &ubl_fillin_amount, 0, 9);
-      MENU_ITEM(function, MSG_UBL_FILLIN_MESH, _lcd_ubl_fillin_amount_cmd);
+      MENU_ITEM_EDIT_CALLBACK(int3, MSG_UBL_FILLIN_AMOUNT, &ubl_fillin_amount, 0, 9, _lcd_ubl_fillin_amount_cmd);
       MENU_ITEM(function, MSG_UBL_SMART_FILLIN, _lcd_ubl_smart_fillin_cmd);
       MENU_ITEM(gcode, MSG_UBL_MANUAL_FILLIN, PSTR("G29 P2 B T0"));
       MENU_ITEM(function, MSG_WATCH, lcd_return_to_status);
@@ -2644,6 +2643,8 @@ void kill_screen(const char* lcd_msg) {
     END_MENU();
   }
 
+  float move_menu_scale;
+
   #if ENABLED(DELTA_CALIBRATION_MENU) || (ENABLED(DELTA_AUTO_CALIBRATION) && !HAS_BED_PROBE)
 
     void lcd_move_z();
@@ -2653,13 +2654,11 @@ void kill_screen(const char* lcd_msg) {
         reset_bed_level(); // After calibration bed-level data is no longer valid
       #endif
 
-      float z_dest = (Z_CLEARANCE_BETWEEN_PROBES) + (DELTA_PRINTABLE_RADIUS) / 5;
-      line_to_z(z_dest);
+      line_to_z((Z_CLEARANCE_BETWEEN_PROBES) + (DELTA_PRINTABLE_RADIUS) / 5);
       current_position[X_AXIS] = rx;
       current_position[Y_AXIS] = ry;
       line_to_current_z();
-      z_dest = Z_CLEARANCE_BETWEEN_PROBES;
-      line_to_z(z_dest);
+      line_to_z(Z_CLEARANCE_BETWEEN_PROBES);
 
       lcd_synchronize();
       move_menu_scale = PROBE_MANUALLY_STEP;
@@ -2813,7 +2812,6 @@ void kill_screen(const char* lcd_msg) {
       #endif
           manual_move_e_index = eindex >= 0 ? eindex : active_extruder;
     #endif
-
     manual_move_start_time = millis() + (move_menu_scale < 0.99 ? 0UL : 250UL); // delay for bigger moves
     manual_move_axis = (int8_t)axis;
   }
@@ -2830,6 +2828,7 @@ void kill_screen(const char* lcd_msg) {
     if (encoderPosition && !processing_manual_move) {
       gcode.refresh_cmd_timeout();
 
+      // Start with no limits to movement
       float min = current_position[axis] - 1000,
             max = current_position[axis] + 1000;
 
@@ -2867,7 +2866,7 @@ void kill_screen(const char* lcd_msg) {
       // This assumes the center is 0,0
       #if ENABLED(DELTA)
         if (axis != Z_AXIS) {
-          max = SQRT(sq((float)(DELTA_PRINTABLE_RADIUS)) - sq(current_position[Y_AXIS - axis]));
+          max = SQRT(sq((float)(DELTA_PRINTABLE_RADIUS)) - sq(current_position[Y_AXIS - axis])); // (Y_AXIS - axis) == the other axis
           min = -max;
         }
       #endif
@@ -3131,7 +3130,7 @@ void kill_screen(const char* lcd_msg) {
     MENU_ITEM(submenu, MSG_FILAMENT, lcd_control_filament_menu);
 
     #if HAS_LCD_CONTRAST
-      MENU_ITEM_EDIT_CALLBACK(int3, MSG_CONTRAST, (int16_t*)&lcd_contrast, LCD_CONTRAST_MIN, LCD_CONTRAST_MAX, lcd_callback_set_contrast, true);
+      MENU_ITEM_EDIT_CALLBACK(int3, MSG_CONTRAST, &lcd_contrast, LCD_CONTRAST_MIN, LCD_CONTRAST_MAX, lcd_callback_set_contrast, true);
     #endif
     #if ENABLED(FWRETRACT)
       MENU_ITEM(submenu, MSG_RETRACT, lcd_control_retract_menu);
@@ -3724,7 +3723,7 @@ void kill_screen(const char* lcd_msg) {
 
         lcd_goto_screen(lcd_sdcard_menu, last_sdfile_encoderPosition);
         defer_return_to_status = true;
-        last_sdfile_encoderPosition == 0xFFFF;
+        last_sdfile_encoderPosition = 0xFFFF;
 
         #if ENABLED(DOGLCD)
           lcd_update();
@@ -3749,29 +3748,27 @@ void kill_screen(const char* lcd_msg) {
         MENU_ITEM(function, LCD_STR_FOLDER "..", lcd_sd_updir);
       }
 
-      if (fileCnt) {
-        for (uint16_t i = 0; i < fileCnt; i++) {
-          if (_menuLineNr == _thisItemNr) {
-            const uint16_t nr =
-              #if ENABLED(SDCARD_RATHERRECENTFIRST) && DISABLED(SDCARD_SORT_ALPHA)
-                fileCnt - 1 -
-              #endif
-            i;
-
-            #if ENABLED(SDCARD_SORT_ALPHA)
-              card.getfilename_sorted(nr);
-            #else
-              card.getfilename(nr);
+      for (uint16_t i = 0; i < fileCnt; i++) {
+        if (_menuLineNr == _thisItemNr) {
+          const uint16_t nr =
+            #if ENABLED(SDCARD_RATHERRECENTFIRST) && DISABLED(SDCARD_SORT_ALPHA)
+              fileCnt - 1 -
             #endif
+          i;
 
-            if (card.filenameIsDir)
-              MENU_ITEM(sddirectory, MSG_CARD_MENU, card.filename, card.longFilename);
-            else
-              MENU_ITEM(sdfile, MSG_CARD_MENU, card.filename, card.longFilename);
-          }
-          else {
-            MENU_ITEM_DUMMY();
-          }
+          #if ENABLED(SDCARD_SORT_ALPHA)
+            card.getfilename_sorted(nr);
+          #else
+            card.getfilename(nr);
+          #endif
+
+          if (card.filenameIsDir)
+            MENU_ITEM(sddirectory, MSG_CARD_MENU, card.filename, card.longFilename);
+          else
+            MENU_ITEM(sdfile, MSG_CARD_MENU, card.filename, card.longFilename);
+        }
+        else {
+          MENU_ITEM_DUMMY();
         }
       }
       END_MENU();
@@ -4476,13 +4473,14 @@ void lcd_init() {
   lcd_implementation_init();
 
   #if ENABLED(NEWPANEL)
-
     #if BUTTON_EXISTS(EN1)
       SET_INPUT_PULLUP(BTN_EN1);
     #endif
+
     #if BUTTON_EXISTS(EN2)
       SET_INPUT_PULLUP(BTN_EN2);
     #endif
+
     #if BUTTON_EXISTS(ENC)
       SET_INPUT_PULLUP(BTN_ENC);
     #endif
@@ -4684,7 +4682,7 @@ void lcd_update() {
 
       #endif
 
-      bool encoderPastThreshold = (abs(encoderDiff) >= ENCODER_PULSES_PER_STEP);
+      const bool encoderPastThreshold = (abs(encoderDiff) >= ENCODER_PULSES_PER_STEP);
       if (encoderPastThreshold || lcd_clicked) {
         if (encoderPastThreshold) {
           int32_t encoderMultiplier = 1;
@@ -4979,11 +4977,6 @@ void lcd_reset_alert_level() { lcd_status_message_level = 0; }
           if (BUTTON_PRESSED(ENC)) newbutton |= EN_C;
         #endif
 
-        buttons = newbutton;
-        #if ENABLED(LCD_HAS_SLOW_BUTTONS)
-          buttons |= slow_buttons;
-        #endif
-
         //
         // Directional buttons
         //
@@ -5032,6 +5025,11 @@ void lcd_reset_alert_level() { lcd_status_message_level = 0; }
 
         #endif // LCD_HAS_DIRECTIONAL_BUTTONS
 
+        buttons = newbutton;
+        #if ENABLED(LCD_HAS_SLOW_BUTTONS)
+          buttons |= slow_buttons;
+        #endif
+
         #if ENABLED(ADC_KEYPAD)
 
           uint8_t newbutton_reprapworld_keypad = 0;
diff --git a/Marlin/src/module/planner.cpp b/Marlin/src/module/planner.cpp
index 007b1dadfcf..64f11a8e027 100644
--- a/Marlin/src/module/planner.cpp
+++ b/Marlin/src/module/planner.cpp
@@ -135,15 +135,20 @@ float Planner::min_feedrate_mm_s,
           Planner::inverse_z_fade_height,
           Planner::last_fade_z;
   #endif
+#else
+  constexpr bool Planner::leveling_active;
 #endif
 
 #if ENABLED(SKEW_CORRECTION)
   #if ENABLED(SKEW_CORRECTION_GCODE)
-    // Initialized by settings.load()
     float Planner::xy_skew_factor;
-    #if ENABLED(SKEW_CORRECTION_FOR_Z)
-      float Planner::xz_skew_factor, Planner::yz_skew_factor;
-    #endif
+  #else
+    constexpr float Planner::xy_skew_factor;
+  #endif
+  #if ENABLED(SKEW_CORRECTION_FOR_Z) && ENABLED(SKEW_CORRECTION_GCODE)
+    float Planner::xz_skew_factor, Planner::yz_skew_factor;
+  #else
+    constexpr float Planner::xz_skew_factor, Planner::yz_skew_factor;
   #endif
 #endif
 
diff --git a/Marlin/src/module/stepper.cpp b/Marlin/src/module/stepper.cpp
index 89429941750..9a464f1cfd9 100644
--- a/Marlin/src/module/stepper.cpp
+++ b/Marlin/src/module/stepper.cpp
@@ -97,18 +97,13 @@ uint8_t Stepper::last_direction_bits = 0;        // The next stepping-bits to be
 int16_t Stepper::cleaning_buffer_counter = 0;
 
 #if ENABLED(X_DUAL_ENDSTOPS)
-  bool Stepper::locked_x_motor = false;
-  bool Stepper::locked_x2_motor = false;
+  bool Stepper::locked_x_motor = false, Stepper::locked_x2_motor = false;
 #endif
-
 #if ENABLED(Y_DUAL_ENDSTOPS)
-  bool Stepper::locked_y_motor = false;
-  bool Stepper::locked_y2_motor = false;
+  bool Stepper::locked_y_motor = false, Stepper::locked_y2_motor = false;
 #endif
-
 #if ENABLED(Z_DUAL_ENDSTOPS)
-  bool Stepper::locked_z_motor = false;
-  bool Stepper::locked_z2_motor = false;
+  bool Stepper::locked_z_motor = false, Stepper::locked_z2_motor = false;
 #endif
 
 long Stepper::counter_X = 0,

From c846388a65d96e8ce804c7682d226bb67722ac7a Mon Sep 17 00:00:00 2001
From: Scott Lahteine <github@thinkyhead.com>
Date: Wed, 6 Dec 2017 21:28:04 -0600
Subject: [PATCH 5/7] Standardize LCD interface code for UBL a little

---
 Marlin/src/feature/bedlevel/ubl/ubl_G29.cpp | 203 +++++++++++---------
 Marlin/src/gcode/bedlevel/G26.cpp           |  13 +-
 Marlin/src/lcd/ultralcd.cpp                 |   4 +
 Marlin/src/lcd/ultralcd.h                   |   1 +
 4 files changed, 119 insertions(+), 102 deletions(-)

diff --git a/Marlin/src/feature/bedlevel/ubl/ubl_G29.cpp b/Marlin/src/feature/bedlevel/ubl/ubl_G29.cpp
index 573ab10ea8a..a4208a1636f 100644
--- a/Marlin/src/feature/bedlevel/ubl/ubl_G29.cpp
+++ b/Marlin/src/feature/bedlevel/ubl/ubl_G29.cpp
@@ -24,6 +24,8 @@
 
 #if ENABLED(AUTO_BED_LEVELING_UBL)
 
+  //#define UBL_DEVEL_DEBUGGING
+
   #include "ubl.h"
 
   #include "../../../Marlin.h"
@@ -728,8 +730,31 @@
           z_values[x][y] += g29_constant;
   }
 
-  #if HAS_BED_PROBE
+  #if ENABLED(NEWPANEL)
 
+    typedef void (*clickFunc_t)();
+
+    bool click_and_hold(const clickFunc_t func=NULL) {
+      if (is_lcd_clicked()) {
+        lcd_quick_feedback();
+        const millis_t nxt = millis() + 1500UL;
+        while (is_lcd_clicked()) {                // Loop while the encoder is pressed. Uses hardware flag!
+          idle();                                 // idle, of course
+          if (ELAPSED(millis(), nxt)) {           // After 1.5 seconds
+            lcd_quick_feedback();
+            if (func) (*func)();
+            wait_for_release();
+            safe_delay(50);                       // Debounce the Encoder wheel
+            return true;
+          }
+        }
+      }
+      return false;
+    }
+
+  #endif // NEWPANEL
+
+  #if HAS_BED_PROBE
     /**
      * Probe all invalidated locations of the mesh that can be reached by the probe.
      * This attempts to fill in locations closest to the nozzle's start location first.
@@ -754,10 +779,9 @@
             SERIAL_PROTOCOLLNPGM("\nMesh only partially populated.\n");
             lcd_quick_feedback();
             STOW_PROBE();
-            while (is_lcd_clicked()) idle();
+            wait_for_release();
             lcd_external_control = false;
             restore_ubl_active_state_and_leave();
-            safe_delay(50);  // Debounce the Encoder wheel
             return;
           }
         #endif
@@ -894,19 +918,20 @@
 
   #if ENABLED(NEWPANEL)
 
-    float unified_bed_leveling::measure_point_with_encoder() {
-
-      while (is_lcd_clicked()) delay(50);  // wait for user to release encoder wheel
-      delay(50);  // debounce
-
-      KEEPALIVE_STATE(PAUSED_FOR_USER);
-      while (!is_lcd_clicked()) {     // we need the loop to move the nozzle based on the encoder wheel here!
+    void unified_bed_leveling::move_z_with_encoder(const float &multiplier) {
+      wait_for_release();
+      while (!is_lcd_clicked()) {
         idle();
         if (encoder_diff) {
-          do_blocking_move_to_z(current_position[Z_AXIS] + 0.01 * float(encoder_diff));
+          do_blocking_move_to_z(current_position[Z_AXIS] + float(encoder_diff) * multiplier);
           encoder_diff = 0;
         }
       }
+    }
+
+    float unified_bed_leveling::measure_point_with_encoder() {
+      KEEPALIVE_STATE(PAUSED_FOR_USER);
+      move_z_with_encoder(0.01);
       KEEPALIVE_STATE(IN_HANDLER);
       return current_position[Z_AXIS];
     }
@@ -953,12 +978,19 @@
       return thickness;
     }
 
+    void abort_manual_probe_remaining_mesh() {
+      SERIAL_PROTOCOLLNPGM("\nMesh only partially populated.");
+      do_blocking_move_to_z(Z_CLEARANCE_DEPLOY_PROBE);
+      lcd_external_control = false;
+      KEEPALIVE_STATE(IN_HANDLER);
+      ubl.restore_ubl_active_state_and_leave();
+    }
+
     void unified_bed_leveling::manually_probe_remaining_mesh(const float &rx, const float &ry, const float &z_clearance, const float &thick, const bool do_ubl_mesh_map) {
 
       lcd_external_control = true;
 
       save_ubl_active_state_and_disable();   // we don't do bed level correction because we want the raw data when we probe
-
       do_blocking_move_to(rx, ry, Z_CLEARANCE_BETWEEN_PROBES);
 
       lcd_return_to_status();
@@ -989,34 +1021,15 @@
         const float z_step = 0.01;                                        // existing behavior: 0.01mm per click, occasionally step
         //const float z_step = 1.0 / planner.axis_steps_per_mm[Z_AXIS];   // approx one step each click
 
-        while (is_lcd_clicked()) delay(50);             // wait for user to release encoder wheel
-        delay(50);                                       // debounce
-        while (!is_lcd_clicked()) {                     // we need the loop to move the nozzle based on the encoder wheel here!
-          idle();
-          if (encoder_diff) {
-            do_blocking_move_to_z(current_position[Z_AXIS] + float(encoder_diff) * z_step);
-            encoder_diff = 0;
-          }
-        }
+        move_z_with_encoder(z_step);
 
-        // this sequence to detect an is_lcd_clicked() debounce it and leave if it is
-        // a Press and Hold is repeated in a lot of places (including G26_Mesh_Validation.cpp).   This
-        // should be redone and compressed.
-        const millis_t nxt = millis() + 1500L;
-        while (is_lcd_clicked()) {     // debounce and watch for abort
-          idle();
-          if (ELAPSED(millis(), nxt)) {
-            SERIAL_PROTOCOLLNPGM("\nMesh only partially populated.");
-            do_blocking_move_to_z(Z_CLEARANCE_DEPLOY_PROBE);
-
-            lcd_quick_feedback();
-            while (is_lcd_clicked()) idle();
-            lcd_external_control = false;
-
-            KEEPALIVE_STATE(IN_HANDLER);
-            restore_ubl_active_state_and_leave();
-            return;
-          }
+        if (click_and_hold()) {
+          SERIAL_PROTOCOLLNPGM("\nMesh only partially populated.");
+          do_blocking_move_to_z(Z_CLEARANCE_DEPLOY_PROBE);
+          lcd_external_control = false;
+          KEEPALIVE_STATE(IN_HANDLER);
+          restore_ubl_active_state_and_leave();
+          return;
         }
 
         z_values[location.x_index][location.y_index] = current_position[Z_AXIS] - thick;
@@ -1150,36 +1163,39 @@
     return UBL_OK;
   }
 
-  static int ubl_state_at_invocation = 0,
-             ubl_state_recursion_chk = 0;
+  static uint8_t ubl_state_at_invocation = 0;
+
+  #ifdef UBL_DEVEL_DEBUGGING
+    static uint8_t ubl_state_recursion_chk = 0;
+  #endif
 
   void unified_bed_leveling::save_ubl_active_state_and_disable() {
-    ubl_state_recursion_chk++;
-    if (ubl_state_recursion_chk != 1) {
-      SERIAL_ECHOLNPGM("save_ubl_active_state_and_disabled() called multiple times in a row.");
-
-      #if ENABLED(NEWPANEL)
-        LCD_MESSAGEPGM(MSG_UBL_SAVE_ERROR);
-        lcd_quick_feedback();
-      #endif
-
-      return;
-    }
+    #ifdef UBL_DEVEL_DEBUGGING
+      ubl_state_recursion_chk++;
+      if (ubl_state_recursion_chk != 1) {
+        SERIAL_ECHOLNPGM("save_ubl_active_state_and_disabled() called multiple times in a row.");
+        #if ENABLED(NEWPANEL)
+          LCD_MESSAGEPGM(MSG_UBL_SAVE_ERROR);
+          lcd_quick_feedback();
+        #endif
+        return;
+      }
+    #endif
     ubl_state_at_invocation = planner.leveling_active;
     set_bed_leveling_enabled(false);
   }
 
   void unified_bed_leveling::restore_ubl_active_state_and_leave() {
-    if (--ubl_state_recursion_chk) {
-      SERIAL_ECHOLNPGM("restore_ubl_active_state_and_leave() called too many times.");
-
-      #if ENABLED(NEWPANEL)
-        LCD_MESSAGEPGM(MSG_UBL_RESTORE_ERROR);
-        lcd_quick_feedback();
-      #endif
-
-      return;
-    }
+    #ifdef UBL_DEVEL_DEBUGGING
+      if (--ubl_state_recursion_chk) {
+        SERIAL_ECHOLNPGM("restore_ubl_active_state_and_leave() called too many times.");
+        #if ENABLED(NEWPANEL)
+          LCD_MESSAGEPGM(MSG_UBL_RESTORE_ERROR);
+          lcd_quick_feedback();
+        #endif
+        return;
+      }
+    #endif
     set_bed_leveling_enabled(ubl_state_at_invocation);
   }
 
@@ -1249,28 +1265,30 @@
     SERIAL_EOL();
     safe_delay(50);
 
-    SERIAL_PROTOCOLLNPAIR("ubl_state_at_invocation :", ubl_state_at_invocation);
-    SERIAL_EOL();
-    SERIAL_PROTOCOLLNPAIR("ubl_state_recursion_chk :", ubl_state_recursion_chk);
-    SERIAL_EOL();
-    safe_delay(50);
+    #ifdef UBL_DEVEL_DEBUGGING
+      SERIAL_PROTOCOLLNPAIR("ubl_state_at_invocation :", ubl_state_at_invocation);
+      SERIAL_EOL();
+      SERIAL_PROTOCOLLNPAIR("ubl_state_recursion_chk :", ubl_state_recursion_chk);
+      SERIAL_EOL();
+      safe_delay(50);
 
-    SERIAL_PROTOCOLPAIR("Meshes go from ", hex_address((void*)settings.get_start_of_meshes()));
-    SERIAL_PROTOCOLLNPAIR(" to ", hex_address((void*)settings.get_end_of_meshes()));
-    safe_delay(50);
+      SERIAL_PROTOCOLPAIR("Meshes go from ", hex_address((void*)settings.get_start_of_meshes()));
+      SERIAL_PROTOCOLLNPAIR(" to ", hex_address((void*)settings.get_end_of_meshes()));
+      safe_delay(50);
 
-    SERIAL_PROTOCOLLNPAIR("sizeof(ubl) :  ", (int)sizeof(ubl));
-    SERIAL_EOL();
-    SERIAL_PROTOCOLLNPAIR("z_value[][] size: ", (int)sizeof(z_values));
-    SERIAL_EOL();
-    safe_delay(25);
+      SERIAL_PROTOCOLLNPAIR("sizeof(ubl) :  ", (int)sizeof(ubl));
+      SERIAL_EOL();
+      SERIAL_PROTOCOLLNPAIR("z_value[][] size: ", (int)sizeof(z_values));
+      SERIAL_EOL();
+      safe_delay(25);
 
-    SERIAL_PROTOCOLLNPAIR("EEPROM free for UBL: ", hex_address((void*)(settings.get_end_of_meshes() - settings.get_start_of_meshes())));
-    safe_delay(50);
+      SERIAL_PROTOCOLLNPAIR("EEPROM free for UBL: ", hex_address((void*)(settings.get_end_of_meshes() - settings.get_start_of_meshes())));
+      safe_delay(50);
 
-    SERIAL_PROTOCOLPAIR("EEPROM can hold ", settings.calc_num_meshes());
-    SERIAL_PROTOCOLLNPGM(" meshes.\n");
-    safe_delay(25);
+      SERIAL_PROTOCOLPAIR("EEPROM can hold ", settings.calc_num_meshes());
+      SERIAL_PROTOCOLLNPGM(" meshes.\n");
+      safe_delay(25);
+    #endif // UBL_DEVEL_DEBUGGING
 
     if (!sanity_check()) {
       echo_name();
@@ -1456,6 +1474,12 @@
 
   #if ENABLED(NEWPANEL)
 
+    void abort_fine_tune() {
+      lcd_return_to_status();
+      do_blocking_move_to_z(Z_CLEARANCE_BETWEEN_PROBES);
+      LCD_MESSAGEPGM(MSG_EDITING_STOPPED);
+    }
+
     void unified_bed_leveling::fine_tune_mesh(const float &rx, const float &ry, const bool do_ubl_mesh_map) {
       if (!parser.seen('R'))    // fine_tune_mesh() is special. If no repetition count flag is specified
         g29_repetition_cnt = 1;   // do exactly one mesh location. Otherwise use what the parser decided.
@@ -1513,13 +1537,13 @@
 
         lcd_mesh_edit_setup(new_z);
 
-        do {
+        while (!is_lcd_clicked()) {
           new_z = lcd_mesh_edit();
           #if ENABLED(UBL_MESH_EDIT_MOVES_Z)
             do_blocking_move_to_z(h_offset + new_z); // Move the nozzle as the point is edited
           #endif
           idle();
-        } while (!is_lcd_clicked());
+        }
 
         if (!lcd_map_control) lcd_return_to_status();
 
@@ -1531,19 +1555,8 @@
         // this sequence to detect an is_lcd_clicked() debounce it and leave if it is
         // a Press and Hold is repeated in a lot of places (including G26_Mesh_Validation.cpp).   This
         // should be redone and compressed.
-        const millis_t nxt = millis() + 1500UL;
-        while (is_lcd_clicked()) { // debounce and watch for abort
-          idle();
-          if (ELAPSED(millis(), nxt)) {
-            lcd_return_to_status();
-            do_blocking_move_to_z(Z_CLEARANCE_BETWEEN_PROBES);
-            LCD_MESSAGEPGM(MSG_EDITING_STOPPED);
-
-            while (is_lcd_clicked()) idle();
-
-            goto FINE_TUNE_EXIT;
-          }
-        }
+        if (click_and_hold(abort_fine_tune))
+          goto FINE_TUNE_EXIT;
 
         safe_delay(20);                       // We don't want any switch noise.
 
diff --git a/Marlin/src/gcode/bedlevel/G26.cpp b/Marlin/src/gcode/bedlevel/G26.cpp
index d5791b97f73..0e09f2243fb 100644
--- a/Marlin/src/gcode/bedlevel/G26.cpp
+++ b/Marlin/src/gcode/bedlevel/G26.cpp
@@ -162,28 +162,27 @@ int8_t g26_prime_flag;
    * Detect is_lcd_clicked, debounce it, and return true for cancel
    */
   bool user_canceled() {
-    if (!is_lcd_clicked()) return false;
-    safe_delay(10);                       // Wait for click to settle
+    if (!is_lcd_clicked()) return false; // Return if the button isn't pressed
 
     #if ENABLED(ULTRA_LCD)
       lcd_setstatusPGM(PSTR("Mesh Validation Stopped."), 99);
       lcd_quick_feedback();
     #endif
 
-    while (!is_lcd_clicked()) idle();    // Wait for button release
+    safe_delay(10);                      // Wait for click to settle
+    while (!is_lcd_clicked()) idle();    // Wait for button press again?
 
     // If the button is suddenly pressed again,
     // ask the user to resolve the issue
     lcd_setstatusPGM(PSTR("Release button"), 99); // will never appear...
-    while (is_lcd_clicked()) idle();             // unless this loop happens
+    wait_for_release();
     lcd_reset_status();
-
     return true;
   }
 
   bool exit_from_g26() {
     lcd_setstatusPGM(PSTR("Leaving G26"), -1);
-    while (is_lcd_clicked()) idle();
+    wait_for_release();
     return G26_ERR;
   }
 
@@ -514,7 +513,7 @@ inline bool prime_nozzle() {
         idle();
       }
 
-      while (is_lcd_clicked()) idle();           // Debounce Encoder Wheel
+      wait_for_release();
 
       strcpy_P(lcd_status_message, PSTR("Done Priming")); // We can't do lcd_setstatusPGM() without having it continue;
                                                           // So... We cheat to get a message up.
diff --git a/Marlin/src/lcd/ultralcd.cpp b/Marlin/src/lcd/ultralcd.cpp
index ab784a71f2b..ae58c10b174 100644
--- a/Marlin/src/lcd/ultralcd.cpp
+++ b/Marlin/src/lcd/ultralcd.cpp
@@ -5105,6 +5105,10 @@ void lcd_reset_alert_level() { lcd_status_message_level = 0; }
 
   #if ENABLED(AUTO_BED_LEVELING_UBL) || ENABLED(G26_MESH_VALIDATION)
     bool is_lcd_clicked() { return LCD_CLICKED; }
+    void wait_for_release() {
+      while (is_lcd_clicked()) safe_delay(50);
+      safe_delay(50);
+    }
   #endif
 
 #endif // ULTIPANEL
diff --git a/Marlin/src/lcd/ultralcd.h b/Marlin/src/lcd/ultralcd.h
index 5e1c43934a0..23148ae3512 100644
--- a/Marlin/src/lcd/ultralcd.h
+++ b/Marlin/src/lcd/ultralcd.h
@@ -222,6 +222,7 @@
 
   #if ENABLED(AUTO_BED_LEVELING_UBL) || ENABLED(G26_MESH_VALIDATION)
     bool is_lcd_clicked();
+    void wait_for_release();
   #endif
 
 #else // no LCD

From cdfabbc507d6a2655672618839437af78496b5fc Mon Sep 17 00:00:00 2001
From: Scott Lahteine <github@thinkyhead.com>
Date: Wed, 6 Dec 2017 21:44:48 -0600
Subject: [PATCH 6/7] Shorten error text in G29

---
 Marlin/src/feature/bedlevel/ubl/ubl_G29.cpp | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/Marlin/src/feature/bedlevel/ubl/ubl_G29.cpp b/Marlin/src/feature/bedlevel/ubl/ubl_G29.cpp
index a4208a1636f..e70ff6121cb 100644
--- a/Marlin/src/feature/bedlevel/ubl/ubl_G29.cpp
+++ b/Marlin/src/feature/bedlevel/ubl/ubl_G29.cpp
@@ -310,8 +310,7 @@
   void unified_bed_leveling::G29() {
 
     if (!settings.calc_num_meshes()) {
-      SERIAL_PROTOCOLLNPGM("?You need to enable your EEPROM and initialize it");
-      SERIAL_PROTOCOLLNPGM("with M502, M500, M501 in that order.\n");
+      SERIAL_PROTOCOLLNPGM("?Enable EEPROM and init with M502, M500.\n");
       return;
     }
 

From 90cf6a06bede65cd6b7620715f426c2c351ff32e Mon Sep 17 00:00:00 2001
From: Scott Lahteine <github@thinkyhead.com>
Date: Wed, 6 Dec 2017 22:02:54 -0600
Subject: [PATCH 7/7] Simplify G26 user_canceled

---
 Marlin/src/gcode/bedlevel/G26.cpp | 15 +++------------
 1 file changed, 3 insertions(+), 12 deletions(-)

diff --git a/Marlin/src/gcode/bedlevel/G26.cpp b/Marlin/src/gcode/bedlevel/G26.cpp
index 0e09f2243fb..207fe8c5e29 100644
--- a/Marlin/src/gcode/bedlevel/G26.cpp
+++ b/Marlin/src/gcode/bedlevel/G26.cpp
@@ -159,24 +159,15 @@ int8_t g26_prime_flag;
 #if ENABLED(NEWPANEL)
 
   /**
-   * Detect is_lcd_clicked, debounce it, and return true for cancel
+   * If the LCD is clicked, cancel, wait for release, return true
    */
   bool user_canceled() {
     if (!is_lcd_clicked()) return false; // Return if the button isn't pressed
-
-    #if ENABLED(ULTRA_LCD)
-      lcd_setstatusPGM(PSTR("Mesh Validation Stopped."), 99);
+    lcd_setstatusPGM(PSTR("Mesh Validation Stopped."), 99);
+    #if ENABLED(ULTIPANEL)
       lcd_quick_feedback();
     #endif
-
-    safe_delay(10);                      // Wait for click to settle
-    while (!is_lcd_clicked()) idle();    // Wait for button press again?
-
-    // If the button is suddenly pressed again,
-    // ask the user to resolve the issue
-    lcd_setstatusPGM(PSTR("Release button"), 99); // will never appear...
     wait_for_release();
-    lcd_reset_status();
     return true;
   }