From c03df89921ba0327dda27c5df52aadd3754074aa Mon Sep 17 00:00:00 2001
From: InsanityAutomation
 <38436470+InsanityAutomation@users.noreply.github.com>
Date: Wed, 13 Mar 2019 01:45:52 -0400
Subject: [PATCH] ExtUI Mesh Leveling Extensions (#13363)

---
 Marlin/src/feature/bedlevel/abl/abl.cpp       |  3 +
 Marlin/src/feature/bedlevel/bedlevel.cpp      |  6 +-
 .../bedlevel/mbl/mesh_bed_leveling.cpp        |  5 ++
 Marlin/src/feature/bedlevel/ubl/ubl.cpp       |  8 +++
 Marlin/src/feature/bedlevel/ubl/ubl_G29.cpp   | 57 ++++++++++++++++++-
 Marlin/src/gcode/bedlevel/M420.cpp            |  9 ++-
 Marlin/src/gcode/bedlevel/abl/G29.cpp         |  9 +++
 Marlin/src/gcode/bedlevel/abl/M421.cpp        |  3 +
 Marlin/src/gcode/bedlevel/mbl/G29.cpp         |  6 +-
 Marlin/src/gcode/bedlevel/ubl/M421.cpp        |  6 +-
 Marlin/src/lcd/extensible_ui/ui_api.cpp       | 21 +++++++
 Marlin/src/lcd/extensible_ui/ui_api.h         | 16 ++++++
 buildroot/share/tests/megaatmega2560-tests    |  2 +-
 13 files changed, 143 insertions(+), 8 deletions(-)

diff --git a/Marlin/src/feature/bedlevel/abl/abl.cpp b/Marlin/src/feature/bedlevel/abl/abl.cpp
index c59c562a83..816a401b8e 100644
--- a/Marlin/src/feature/bedlevel/abl/abl.cpp
+++ b/Marlin/src/feature/bedlevel/abl/abl.cpp
@@ -76,6 +76,9 @@ static void extrapolate_one_point(const uint8_t x, const uint8_t y, const int8_t
 
   // Take the average instead of the median
   z_values[x][y] = (a + b + c) / 3.0;
+  #if ENABLED(EXTENSIBLE_UI)
+    ExtUI::onMeshUpdate(x, y, z_values[x][y]);
+  #endif
 
   // Median is robust (ignores outliers).
   // z_values[x][y] = (a < b) ? ((b < c) ? b : (c < a) ? a : c)
diff --git a/Marlin/src/feature/bedlevel/bedlevel.cpp b/Marlin/src/feature/bedlevel/bedlevel.cpp
index 364e22ed44..dd5a161ee0 100644
--- a/Marlin/src/feature/bedlevel/bedlevel.cpp
+++ b/Marlin/src/feature/bedlevel/bedlevel.cpp
@@ -134,8 +134,12 @@ void reset_bed_level() {
     bilinear_start[X_AXIS] = bilinear_start[Y_AXIS] =
     bilinear_grid_spacing[X_AXIS] = bilinear_grid_spacing[Y_AXIS] = 0;
     for (uint8_t x = 0; x < GRID_MAX_POINTS_X; x++)
-      for (uint8_t y = 0; y < GRID_MAX_POINTS_Y; y++)
+      for (uint8_t y = 0; y < GRID_MAX_POINTS_Y; y++) {
         z_values[x][y] = NAN;
+        #if ENABLED(EXTENSIBLE_UI)
+          ExtUI::onMeshUpdate(x, y, 0);
+        #endif
+      }
   #elif ABL_PLANAR
     planner.bed_level_matrix.set_to_identity();
   #endif
diff --git a/Marlin/src/feature/bedlevel/mbl/mesh_bed_leveling.cpp b/Marlin/src/feature/bedlevel/mbl/mesh_bed_leveling.cpp
index eb1dc4c88a..15899bdee9 100644
--- a/Marlin/src/feature/bedlevel/mbl/mesh_bed_leveling.cpp
+++ b/Marlin/src/feature/bedlevel/mbl/mesh_bed_leveling.cpp
@@ -47,6 +47,11 @@
   void mesh_bed_leveling::reset() {
     z_offset = 0;
     ZERO(z_values);
+    #if ENABLED(EXTENSIBLE_UI)
+      for (uint8_t x = 0; x < GRID_MAX_POINTS_X; x++)
+        for (uint8_t y = 0; y < GRID_MAX_POINTS_Y; y++) 
+            ExtUI::onMeshUpdate(x, y, 0);
+    #endif
   }
 
   #if IS_CARTESIAN && DISABLED(SEGMENT_LEVELED_MOVES)
diff --git a/Marlin/src/feature/bedlevel/ubl/ubl.cpp b/Marlin/src/feature/bedlevel/ubl/ubl.cpp
index 1945f99daf..e1c5c985d0 100644
--- a/Marlin/src/feature/bedlevel/ubl/ubl.cpp
+++ b/Marlin/src/feature/bedlevel/ubl/ubl.cpp
@@ -129,6 +129,11 @@
       planner.set_z_fade_height(10.0);
     #endif
     ZERO(z_values);
+    #if ENABLED(EXTENSIBLE_UI)
+      for (uint8_t x = 0; x < GRID_MAX_POINTS_X; x++)
+        for (uint8_t y = 0; y < GRID_MAX_POINTS_Y; y++) 
+            ExtUI::onMeshUpdate(x, y, 0);
+    #endif
     if (was_enabled) report_current_position();
   }
 
@@ -141,6 +146,9 @@
     for (uint8_t x = 0; x < GRID_MAX_POINTS_X; x++) {
       for (uint8_t y = 0; y < GRID_MAX_POINTS_Y; y++) {
         z_values[x][y] = value;
+        #if ENABLED(EXTENSIBLE_UI)
+          ExtUI::onMeshUpdate(x, y, value);
+        #endif
       }
     }
   }
diff --git a/Marlin/src/feature/bedlevel/ubl/ubl_G29.cpp b/Marlin/src/feature/bedlevel/ubl/ubl_G29.cpp
index b04ffac15d..8cdae56b0e 100644
--- a/Marlin/src/feature/bedlevel/ubl/ubl_G29.cpp
+++ b/Marlin/src/feature/bedlevel/ubl/ubl_G29.cpp
@@ -335,6 +335,9 @@
             break;            // No more invalid Mesh Points to populate
           }
           z_values[location.x_index][location.y_index] = NAN;
+          #if ENABLED(EXTENSIBLE_UI)
+            ExtUI::onMeshUpdate(location.x_index, location.y_index, 0);
+          #endif
           cnt++;
         }
       }
@@ -362,6 +365,9 @@
               const float p1 = 0.5f * (GRID_MAX_POINTS_X) - x,
                           p2 = 0.5f * (GRID_MAX_POINTS_Y) - y;
               z_values[x][y] += 2.0f * HYPOT(p1, p2);
+              #if ENABLED(EXTENSIBLE_UI)
+                ExtUI::onMeshUpdate(x, y, z_values[x][y]);
+              #endif
             }
           }
           break;
@@ -370,6 +376,11 @@
           for (uint8_t x = 0; x < GRID_MAX_POINTS_X; x++) {  // Create a diagonal line several Mesh cells thick that is raised
             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
+            #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]);
+            #endif
+
           }
           break;
 
@@ -378,6 +389,9 @@
           for (uint8_t x = (GRID_MAX_POINTS_X) / 3; x < 2 * (GRID_MAX_POINTS_X) / 3; x++)   // Create a rectangular raised area in
             for (uint8_t y = (GRID_MAX_POINTS_Y) / 3; y < 2 * (GRID_MAX_POINTS_Y) / 3; y++) // the center of the bed
               z_values[x][y] += parser.seen('C') ? g29_constant : 9.99f;
+              #if ENABLED(EXTENSIBLE_UI)
+                ExtUI::onMeshUpdate(x, y, z_values[x][y]);
+              #endif
           break;
       }
     }
@@ -519,6 +533,9 @@
                   break; // No more invalid Mesh Points to populate
                 }
                 z_values[location.x_index][location.y_index] = g29_constant;
+                #if ENABLED(EXTENSIBLE_UI)
+                  ExtUI::onMeshUpdate(location.x_index, location.y_index, z_values[location.x_index][location.y_index]);
+                #endif
               }
             }
           }
@@ -681,15 +698,23 @@
     if (cflag)
       for (uint8_t x = 0; x < GRID_MAX_POINTS_X; x++)
         for (uint8_t y = 0; y < GRID_MAX_POINTS_Y; y++)
-          if (!isnan(z_values[x][y]))
+          if (!isnan(z_values[x][y])) {
             z_values[x][y] -= mean + value;
+            #if ENABLED(EXTENSIBLE_UI)
+              ExtUI::onMeshUpdate(x, y, z_values[x][y]);
+            #endif
+          }
   }
 
   void unified_bed_leveling::shift_mesh_height() {
     for (uint8_t x = 0; x < GRID_MAX_POINTS_X; x++)
       for (uint8_t y = 0; y < GRID_MAX_POINTS_Y; y++)
-        if (!isnan(z_values[x][y]))
+        if (!isnan(z_values[x][y])) {
           z_values[x][y] += g29_constant;
+          #if ENABLED(EXTENSIBLE_UI)
+            ExtUI::onMeshUpdate(x, y, z_values[x][y]);
+          #endif
+        }
   }
 
   #if HAS_BED_PROBE
@@ -736,6 +761,10 @@
 
           const float measured_z = probe_pt(rawx, rawy, stow_probe ? PROBE_PT_STOW : PROBE_PT_RAISE, g29_verbose_level); // TODO: Needs error handling
           z_values[location.x_index][location.y_index] = measured_z;
+          #if ENABLED(EXTENSIBLE_UI)
+            ExtUI::onMeshUpdate(location.x_index, location.y_index, measured_z);
+          #endif
+          
         }
         SERIAL_FLUSH(); // Prevent host M105 buffer overrun.
       } while (location.x_index >= 0 && --count);
@@ -894,6 +923,10 @@
         }
 
         z_values[location.x_index][location.y_index] = current_position[Z_AXIS] - thick;
+        #if ENABLED(EXTENSIBLE_UI)
+          ExtUI::onMeshUpdate(location.x_index, location.y_index, z_values[location.x_index][location.y_index]);
+        #endif
+
         if (g29_verbose_level > 2)
           SERIAL_ECHOLNPAIR_F("Mesh Point Measured at: ", z_values[location.x_index][location.y_index], 6);
         SERIAL_FLUSH(); // Prevent host M105 buffer overrun.
@@ -994,6 +1027,9 @@
         if (click_and_hold(abort_fine_tune)) goto FINE_TUNE_EXIT;   // If the click is held down, abort editing
 
         z_values[location.x_index][location.y_index] = new_z;       // Save the updated Z value
+        #if ENABLED(EXTENSIBLE_UI)
+          ExtUI::onMeshUpdate(location.x_index, location.y_index, new_z);
+        #endif
 
         serial_delay(20);                                           // No switch noise
         ui.refresh();
@@ -1298,6 +1334,11 @@
         z_values[x][y] = z_values[x1][y1];                      // Use nearest (maybe a little too high.)
       else
         z_values[x][y] = 2.0f * z_values[x1][y1] - z_values[x2][y2];   // Angled upward...
+
+      #if ENABLED(EXTENSIBLE_UI)
+        ExtUI::onMeshUpdate(x, y, z_values[x][y]);
+      #endif
+
       return true;
     }
     return false;
@@ -1510,6 +1551,9 @@
           #endif
 
           z_values[i][j] = z_tmp - lsf_results.D;
+          #if ENABLED(EXTENSIBLE_UI)
+            ExtUI::onMeshUpdate(i, j, z_values[i][j]);
+          #endif
         }
       }
 
@@ -1619,6 +1663,9 @@
             }
             const float ez = -lsf_results.D - lsf_results.A * px - lsf_results.B * py;
             z_values[ix][iy] = ez;
+            #if ENABLED(EXTENSIBLE_UI)
+              ExtUI::onMeshUpdate(ix, iy, z_values[ix][iy]);
+            #endif
             idle();   // housekeeping
           }
         }
@@ -1757,8 +1804,12 @@
       SERIAL_ECHOLNPAIR("Subtracting mesh in slot ", g29_storage_slot, " from current mesh.");
 
       for (uint8_t x = 0; x < GRID_MAX_POINTS_X; x++)
-        for (uint8_t y = 0; y < GRID_MAX_POINTS_Y; y++)
+        for (uint8_t y = 0; y < GRID_MAX_POINTS_Y; y++) {
           z_values[x][y] -= tmp_z_values[x][y];
+          #if ENABLED(EXTENSIBLE_UI)
+            ExtUI::onMeshUpdate(x, y, z_values[x][y]);
+          #endif
+        }
     }
 
   #endif // UBL_DEVEL_DEBUGGING
diff --git a/Marlin/src/gcode/bedlevel/M420.cpp b/Marlin/src/gcode/bedlevel/M420.cpp
index 2ab4806365..f87c60fecb 100644
--- a/Marlin/src/gcode/bedlevel/M420.cpp
+++ b/Marlin/src/gcode/bedlevel/M420.cpp
@@ -66,8 +66,12 @@ void GcodeSuite::M420() {
         bilinear_grid_spacing[Y_AXIS] = (MAX_PROBE_Y - (MIN_PROBE_Y)) / (GRID_MAX_POINTS_Y - 1);
       #endif
       for (uint8_t x = 0; x < GRID_MAX_POINTS_X; x++)
-        for (uint8_t y = 0; y < GRID_MAX_POINTS_Y; y++)
+        for (uint8_t y = 0; y < GRID_MAX_POINTS_Y; y++) {
           Z_VALUES(x, y) = 0.001 * random(-200, 200);
+          #if ENABLED(EXTENSIBLE_UI)
+            ExtUI::onMeshUpdate(x, y, Z_VALUES(x, y));
+          #endif
+        }
       SERIAL_ECHOPGM("Simulated " STRINGIFY(GRID_MAX_POINTS_X) "x" STRINGIFY(GRID_MAX_POINTS_X) " mesh ");
       SERIAL_ECHOPAIR(" (", MIN_PROBE_X);
       SERIAL_CHAR(','); SERIAL_ECHO(MIN_PROBE_Y);
@@ -176,6 +180,9 @@ void GcodeSuite::M420() {
             #if ENABLED(ABL_BILINEAR_SUBDIVISION)
               bed_level_virt_interpolate();
             #endif
+            #if ENABLED(EXTENSIBLE_UI)
+              ExtUI::onMeshUpdate(x, y, Z_VALUES(x, y));
+            #endif
           }
 
         #endif
diff --git a/Marlin/src/gcode/bedlevel/abl/G29.cpp b/Marlin/src/gcode/bedlevel/abl/G29.cpp
index 7d09c41689..a79c35af9a 100644
--- a/Marlin/src/gcode/bedlevel/abl/G29.cpp
+++ b/Marlin/src/gcode/bedlevel/abl/G29.cpp
@@ -321,6 +321,9 @@ G29_TYPE GcodeSuite::G29() {
           #if ENABLED(ABL_BILINEAR_SUBDIVISION)
             bed_level_virt_interpolate();
           #endif
+          #if ENABLED(EXTENSIBLE_UI)
+            ExtUI::onMeshUpdate(i, j, rz);
+          #endif
           set_bed_leveling_enabled(abl_should_enable);
           if (abl_should_enable) report_current_position();
         }
@@ -548,6 +551,9 @@ G29_TYPE GcodeSuite::G29() {
       #elif ENABLED(AUTO_BED_LEVELING_BILINEAR)
 
         z_values[xCount][yCount] = measured_z + zoffset;
+        #if ENABLED(EXTENSIBLE_UI)
+          ExtUI::onMeshUpdate(xCount, yCount, z_values[xCount][yCount]);
+        #endif
 
         #if ENABLED(DEBUG_LEVELING_FEATURE)
           if (DEBUGGING(LEVELING)) {
@@ -723,6 +729,9 @@ G29_TYPE GcodeSuite::G29() {
           #elif ENABLED(AUTO_BED_LEVELING_BILINEAR)
 
             z_values[xCount][yCount] = measured_z + zoffset;
+            #if ENABLED(EXTENSIBLE_UI)
+              ExtUI::onMeshUpdate(xCount, yCount, z_values[xCount][yCount]);
+            #endif
 
           #endif
 
diff --git a/Marlin/src/gcode/bedlevel/abl/M421.cpp b/Marlin/src/gcode/bedlevel/abl/M421.cpp
index 3e2542c24f..cba905b4fb 100644
--- a/Marlin/src/gcode/bedlevel/abl/M421.cpp
+++ b/Marlin/src/gcode/bedlevel/abl/M421.cpp
@@ -54,6 +54,9 @@ void GcodeSuite::M421() {
     #if ENABLED(ABL_BILINEAR_SUBDIVISION)
       bed_level_virt_interpolate();
     #endif
+    #if ENABLED(EXTENSIBLE_UI)
+      ExtUI::onMeshUpdate(ix, iy, z_values[ix][iy]);
+    #endif
   }
 }
 
diff --git a/Marlin/src/gcode/bedlevel/mbl/G29.cpp b/Marlin/src/gcode/bedlevel/mbl/G29.cpp
index df24a58a99..fd42b165f4 100644
--- a/Marlin/src/gcode/bedlevel/mbl/G29.cpp
+++ b/Marlin/src/gcode/bedlevel/mbl/G29.cpp
@@ -173,8 +173,12 @@ void GcodeSuite::G29() {
       else
         return echo_not_entered('J');
 
-      if (parser.seenval('Z'))
+      if (parser.seenval('Z')) {
         mbl.z_values[ix][iy] = parser.value_linear_units();
+        #if ENABLED(EXTENSIBLE_UI)
+          ExtUI::onMeshUpdate(ix, iy, mbl.z_values[ix][iy]);
+        #endif
+      }
       else
         return echo_not_entered('Z');
       break;
diff --git a/Marlin/src/gcode/bedlevel/ubl/M421.cpp b/Marlin/src/gcode/bedlevel/ubl/M421.cpp
index 5e01c659d0..a4bcf33562 100644
--- a/Marlin/src/gcode/bedlevel/ubl/M421.cpp
+++ b/Marlin/src/gcode/bedlevel/ubl/M421.cpp
@@ -60,8 +60,12 @@ void GcodeSuite::M421() {
     SERIAL_ERROR_MSG(MSG_ERR_M421_PARAMETERS);
   else if (!WITHIN(ix, 0, GRID_MAX_POINTS_X - 1) || !WITHIN(iy, 0, GRID_MAX_POINTS_Y - 1))
     SERIAL_ERROR_MSG(MSG_ERR_MESH_XY);
-  else
+  else {
     ubl.z_values[ix][iy] = hasN ? NAN : parser.value_linear_units() + (hasQ ? ubl.z_values[ix][iy] : 0);
+    #if ENABLED(EXTENSIBLE_UI)
+      ExtUI::onMeshUpdate(ix, iy, ubl.z_values[ix][iy]);
+    #endif
+  }
 }
 
 #endif // AUTO_BED_LEVELING_UBL
diff --git a/Marlin/src/lcd/extensible_ui/ui_api.cpp b/Marlin/src/lcd/extensible_ui/ui_api.cpp
index 4d1a1828d0..a7823a10da 100644
--- a/Marlin/src/lcd/extensible_ui/ui_api.cpp
+++ b/Marlin/src/lcd/extensible_ui/ui_api.cpp
@@ -577,6 +577,27 @@ namespace ExtUI {
     return elapsed.value;
   }
 
+  #if HAS_LEVELING
+    bool getLevelingActive() { return planner.leveling_active; }
+    void setLevelingActive(const bool state) { set_bed_leveling_enabled(state) }
+    #if HAS_MESH
+      bool getMeshValid() { return leveling_is_valid(); }
+      bed_mesh_t getMeshArray() { return Z_VALUES; }
+      void setMeshPoint(const uint8_t xpos, const uint8_t ypos, const float zoff) {
+        if (WITHIN(xpos, 0, GRID_MAX_POINTS_X) && WITHIN(ypos, 0, GRID_MAX_POINTS_Y)) {
+          Z_VALUES(xpos, ypos) = zoff;
+          #if ENABLED(ABL_BILINEAR_SUBDIVISION)
+            bed_level_virt_interpolate();
+          #endif
+        }
+      }
+    #endif
+  #endif
+
+  #if ENABLED(HOST_PROMPT_SUPPORT)
+    void setHostResponse(const uint8_t response) { host_response_handler(response); }
+  #endif
+
   #if ENABLED(PRINTCOUNTER)
     char* getTotalPrints_str(char buffer[21])    { strcpy(buffer,i16tostr3left(print_job_timer.getStats().totalPrints));    return buffer; }
     char* getFinishedPrints_str(char buffer[21]) { strcpy(buffer,i16tostr3left(print_job_timer.getStats().finishedPrints)); return buffer; }
diff --git a/Marlin/src/lcd/extensible_ui/ui_api.h b/Marlin/src/lcd/extensible_ui/ui_api.h
index 48b83713ab..c7e33d77b1 100644
--- a/Marlin/src/lcd/extensible_ui/ui_api.h
+++ b/Marlin/src/lcd/extensible_ui/ui_api.h
@@ -90,6 +90,22 @@ namespace ExtUI {
   float getFeedrate_percent();
   uint8_t getProgress_percent();
   uint32_t getProgress_seconds_elapsed();
+  
+  #if HAS_LEVELING
+    bool getLevelingActive();
+    void setLevelingActive(const bool);
+    #if HAS_MESH
+      typedef float (&bed_mesh_t)[GRID_MAX_POINTS_X][GRID_MAX_POINTS_Y];
+      bool getMeshValid();
+      bed_mesh_t getMeshArray();
+      void setMeshPoint(const uint8_t xpos, const uint8_t ypos, const float zval);
+      void onMeshUpdate(const uint8_t xpos, const uint8_t ypos, const float zval);
+    #endif
+  #endif
+
+  #if ENABLED(HOST_PROMPT_SUPPORT)
+    void setHostResponse(const uint8_t);
+  #endif
 
   #if ENABLED(PRINTCOUNTER)
     char* getTotalPrints_str(char buffer[21]);
diff --git a/buildroot/share/tests/megaatmega2560-tests b/buildroot/share/tests/megaatmega2560-tests
index bfb405208a..e892b55c77 100755
--- a/buildroot/share/tests/megaatmega2560-tests
+++ b/buildroot/share/tests/megaatmega2560-tests
@@ -42,7 +42,7 @@ opt_enable PIDTEMPBED FIX_MOUNTED_PROBE Z_SAFE_HOMING \
            MAX7219_DEBUG LED_CONTROL_MENU CASE_LIGHT_ENABLE CASE_LIGHT_USE_NEOPIXEL CODEPENDENT_XY_HOMING BACKLASH_COMPENSATION BACKLASH_GCODE
 opt_enable SLOW_PWM_HEATERS THERMAL_PROTECTION_CHAMBER
 opt_set TEMP_SENSOR_CHAMBER 3
-opt_add CHAMBER_HEATER_PIN 45
+opt_set CHAMBER_HEATER_PIN 45
 exec_test $1 $2 "RAMPS with 2 extruders, RRDFGSC, Linear ABL, LEDs, and many options"
 
 #
-- 
GitLab