Browse Source

Refactor Hilbert curve. Enhance Touch UI Bed Level Screen. (#21453)

Marcio T 3 years ago
parent
commit
c45b91aa94
No account linked to committer's email address

+ 112
- 0
Marlin/src/feature/bedlevel/hilbert_curve.cpp View File

@@ -0,0 +1,112 @@
1
+/*********************
2
+ * hilbert_curve.cpp *
3
+ *********************/
4
+
5
+/****************************************************************************
6
+ *   Written By Marcio Teixeira 2021 - SynDaver Labs, Inc.                  *
7
+ *                                                                          *
8
+ *   This program is free software: you can redistribute it and/or modify   *
9
+ *   it under the terms of the GNU General Public License as published by   *
10
+ *   the Free Software Foundation, either version 3 of the License, or      *
11
+ *   (at your option) any later version.                                    *
12
+ *                                                                          *
13
+ *   This program is distributed in the hope that it will be useful,        *
14
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of         *
15
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the          *
16
+ *   GNU General Public License for more details.                           *
17
+ *                                                                          *
18
+ *   To view a copy of the GNU General Public License, go to the following  *
19
+ *   location: <https://www.gnu.org/licenses/>.                             *
20
+ ****************************************************************************/
21
+
22
+#include "../../inc/MarlinConfig.h"
23
+
24
+#if ENABLED(UBL_HILBERT_CURVE)
25
+
26
+#include "bedlevel.h"
27
+#include "hilbert_curve.h"
28
+
29
+constexpr int8_t  to_fix(int8_t  v) { return v * 2; }
30
+constexpr int8_t  to_int(int8_t  v) { return v / 2; }
31
+constexpr uint8_t   log2(uint8_t n) { return (n > 1) ? 1 + log2(n >> 1) : 0; }
32
+constexpr uint8_t  order(uint8_t n) { return uint8_t(log2(n - 1)) + 1; }
33
+constexpr uint8_t ord = order(_MAX(GRID_MAX_POINTS_X, GRID_MAX_POINTS_Y));
34
+constexpr uint8_t dim = _BV(ord);
35
+
36
+static inline bool eval_candidate(int8_t x, int8_t y, hilbert_curve::callback_ptr func, void *data) {
37
+  // The print bed likely has fewer points than the full Hilbert
38
+  // curve, so cull unecessary points
39
+  return x < GRID_MAX_POINTS_X && y < GRID_MAX_POINTS_Y ? func(x, y, data) : false;
40
+}
41
+
42
+bool hilbert_curve::hilbert(int8_t x, int8_t y, int8_t xi, int8_t xj, int8_t yi, int8_t yj, uint8_t n, hilbert_curve::callback_ptr func, void *data) {
43
+  /**
44
+   * Hilbert space-filling curve implementation
45
+   *
46
+   * x  and y  : coordinates of the bottom left corner
47
+   * xi and xj : i and j components of the unit x vector of the frame
48
+   * yi and yj : i and j components of the unit y vector of the frame
49
+   *
50
+   * From: http://www.fundza.com/algorithmic/space_filling/hilbert/basics/index.html
51
+   */
52
+  if (n)
53
+    return hilbert(x,           y,           yi/2,  yj/2,  xi/2,  xj/2, n-1, func, data) ||
54
+           hilbert(x+xi/2,      y+xj/2,      xi/2,  xj/2,  yi/2,  yj/2, n-1, func, data) ||
55
+           hilbert(x+xi/2+yi/2, y+xj/2+yj/2, xi/2,  xj/2,  yi/2,  yj/2, n-1, func, data) ||
56
+           hilbert(x+xi/2+yi,   y+xj/2+yj,  -yi/2, -yj/2, -xi/2, -xj/2, n-1, func, data);
57
+  else
58
+    return eval_candidate(to_int(x+(xi+yi)/2), to_int(y+(xj+yj)/2), func, data);
59
+}
60
+
61
+/**
62
+ * Calls func(x, y, data) for all points in the Hilbert curve.
63
+ * If that function returns true, the search is terminated.
64
+ */
65
+bool hilbert_curve::search(hilbert_curve::callback_ptr func, void *data) {
66
+  return hilbert(to_fix(0), to_fix(0),to_fix(dim), to_fix(0), to_fix(0), to_fix(dim), ord, func, data);
67
+}
68
+
69
+/* Helper function for starting the search at a particular point */
70
+
71
+typedef struct {
72
+  uint8_t x, y;
73
+  bool found_1st;
74
+  hilbert_curve::callback_ptr func;
75
+  void *data;
76
+} search_from_t;
77
+
78
+static bool search_from_helper(uint8_t x, uint8_t y, void *data) {
79
+  search_from_t *d = (search_from_t *) data;
80
+  if (d->x == x && d->y == y)
81
+    d->found_1st = true;
82
+  return d->found_1st ? d->func(x, y, d->data) : false;
83
+}
84
+
85
+/**
86
+ * Same as search, except start at a specific grid intersection point.
87
+ */
88
+bool hilbert_curve::search_from(uint8_t x, uint8_t y, hilbert_curve::callback_ptr func, void *data) {
89
+  search_from_t d;
90
+  d.x = x;
91
+  d.y = y;
92
+  d.found_1st = false;
93
+  d.func = func;
94
+  d.data = data;
95
+  // Call twice to allow search to wrap back to the beginning and picked up points prior to the start.
96
+  return search(search_from_helper, &d) || search(search_from_helper, &d);
97
+}
98
+
99
+/**
100
+ * Like search_from, but takes a bed position and starts from the nearest
101
+ * point on the Hilbert curve.
102
+ */
103
+bool hilbert_curve::search_from_closest(const xy_pos_t &pos, hilbert_curve::callback_ptr func, void *data) {
104
+  // Find closest grid intersection
105
+  uint8_t grid_x = LROUND(float(pos.x - MESH_MIN_X) / MESH_X_DIST);
106
+  uint8_t grid_y = LROUND(float(pos.y - MESH_MIN_Y) / MESH_Y_DIST);
107
+  LIMIT(grid_x, 0, GRID_MAX_POINTS_X);
108
+  LIMIT(grid_y, 0, GRID_MAX_POINTS_Y);
109
+  return search_from(grid_x, grid_y, func, data);
110
+}
111
+
112
+#endif // UBL_HILBERT_CURVE

+ 32
- 0
Marlin/src/feature/bedlevel/hilbert_curve.h View File

@@ -0,0 +1,32 @@
1
+/*******************
2
+ * hilbert_curve.h *
3
+ *******************/
4
+
5
+/****************************************************************************
6
+ *   Written By Marcio Teixeira 2021 - SynDaver Labs, Inc.                  *
7
+ *                                                                          *
8
+ *   This program is free software: you can redistribute it and/or modify   *
9
+ *   it under the terms of the GNU General Public License as published by   *
10
+ *   the Free Software Foundation, either version 3 of the License, or      *
11
+ *   (at your option) any later version.                                    *
12
+ *                                                                          *
13
+ *   This program is distributed in the hope that it will be useful,        *
14
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of         *
15
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the          *
16
+ *   GNU General Public License for more details.                           *
17
+ *                                                                          *
18
+ *   To view a copy of the GNU General Public License, go to the following  *
19
+ *   location: <https://www.gnu.org/licenses/>.                             *
20
+ ****************************************************************************/
21
+
22
+#pragma once
23
+
24
+class hilbert_curve {
25
+  public:
26
+    typedef bool (*callback_ptr)(uint8_t x, uint8_t y, void *data);
27
+    static bool search(callback_ptr func, void *data);
28
+    static bool search_from(uint8_t x, uint8_t y, callback_ptr func, void *data);
29
+    static bool search_from_closest(const xy_pos_t &pos, callback_ptr func, void *data);
30
+  private:
31
+    static bool hilbert(int8_t x, int8_t y, int8_t xi, int8_t xj, int8_t yi, int8_t yj, uint8_t n, callback_ptr func, void *data);
32
+};

+ 0
- 5
Marlin/src/feature/bedlevel/ubl/ubl.h View File

@@ -101,11 +101,6 @@ public:
101 101
   static void display_map(const int) _O0;
102 102
   static mesh_index_pair find_closest_mesh_point_of_type(const MeshPointType, const xy_pos_t&, const bool=false, MeshFlags *done_flags=nullptr) _O0;
103 103
   static mesh_index_pair find_furthest_invalid_mesh_point() _O0;
104
-  #if ENABLED(UBL_HILBERT_CURVE)
105
-    static void check_if_missing(mesh_index_pair &pt, int x, int y);
106
-    static void hilbert(mesh_index_pair &pt, int8_t x, int8_t y, int8_t xi, int8_t xj, int8_t yi, int8_t yj, uint8_t n);
107
-    static mesh_index_pair find_next_mesh_point();
108
-  #endif
109 104
   static void reset();
110 105
   static void invalidate();
111 106
   static void set_all_mesh_points_to_value(const float value);

+ 77
- 79
Marlin/src/feature/bedlevel/ubl/ubl_G29.cpp View File

@@ -49,6 +49,10 @@
49 49
   #include "../../../lcd/extui/ui_api.h"
50 50
 #endif
51 51
 
52
+#if ENABLED(UBL_HILBERT_CURVE)
53
+  #include "../hilbert_curve.h"
54
+#endif
55
+
52 56
 #include <math.h>
53 57
 
54 58
 #define UBL_G29_P31
@@ -747,11 +751,9 @@ void unified_bed_leveling::shift_mesh_height() {
747 751
         }
748 752
       #endif
749 753
 
750
-      best = do_furthest  ? find_furthest_invalid_mesh_point()
751
-                          : TERN(UBL_HILBERT_CURVE,
752
-                              find_next_mesh_point(),
753
-                              find_closest_mesh_point_of_type(INVALID, nearby, true)
754
-                            );
754
+      best = do_furthest
755
+        ? find_furthest_invalid_mesh_point()
756
+        : find_closest_mesh_point_of_type(INVALID, nearby, true);
755 757
 
756 758
       if (best.pos.x >= 0) {    // mesh point found and is reachable by probe
757 759
         TERN_(EXTENSIBLE_UI, ExtUI::onMeshUpdate(best.pos, ExtUI::PROBE_START));
@@ -1269,97 +1271,93 @@ mesh_index_pair unified_bed_leveling::find_furthest_invalid_mesh_point() {
1269 1271
   return farthest;
1270 1272
 }
1271 1273
 
1272
-mesh_index_pair unified_bed_leveling::find_closest_mesh_point_of_type(const MeshPointType type, const xy_pos_t &pos, const bool probe_relative/*=false*/, MeshFlags *done_flags/*=nullptr*/) {
1273
-  mesh_index_pair closest;
1274
-  closest.invalidate();
1275
-  closest.distance = -99999.9f;
1276
-
1277
-  // Get the reference position, either nozzle or probe
1278
-  const xy_pos_t ref = probe_relative ? pos + probe.offset_xy : pos;
1279
-
1280
-  float best_so_far = 99999.99f;
1274
+#if ENABLED(UBL_HILBERT_CURVE)
1281 1275
 
1282
-  GRID_LOOP(i, j) {
1283
-    if ( (type == (isnan(z_values[i][j]) ? INVALID : REAL))
1284
-      || (type == SET_IN_BITMAP && !done_flags->marked(i, j))
1276
+  typedef struct {
1277
+    MeshPointType   type;
1278
+    MeshFlags       *done_flags;
1279
+    bool            probe_relative;
1280
+    mesh_index_pair closest;
1281
+  } find_closest_t;
1282
+
1283
+  static bool test_func(uint8_t i, uint8_t j, void *data) {
1284
+    find_closest_t *d = (find_closest_t*)data;
1285
+    if ( (d->type == (isnan(ubl.z_values[i][j]) ? INVALID : REAL))
1286
+      || (d->type == SET_IN_BITMAP && !d->done_flags->marked(i, j))
1285 1287
     ) {
1286 1288
       // Found a Mesh Point of the specified type!
1287
-      const xy_pos_t mpos = { mesh_index_to_xpos(i), mesh_index_to_ypos(j) };
1289
+      const xy_pos_t mpos = { ubl.mesh_index_to_xpos(i), ubl.mesh_index_to_ypos(j) };
1288 1290
 
1289 1291
       // If using the probe as the reference there are some unreachable locations.
1290 1292
       // Also for round beds, there are grid points outside the bed the nozzle can't reach.
1291 1293
       // Prune them from the list and ignore them till the next Phase (manual nozzle probing).
1292 1294
 
1293
-      if (!(probe_relative ? probe.can_reach(mpos) : position_is_reachable(mpos)))
1294
-        continue;
1295
+      if (!(d->probe_relative ? probe.can_reach(mpos) : position_is_reachable(mpos)))
1296
+        return false;
1297
+      d->closest.pos.set(i, j);
1298
+      return true;
1299
+    }
1300
+    return false;
1301
+  }
1295 1302
 
1296
-      // Reachable. Check if it's the best_so_far location to the nozzle.
1303
+#endif
1297 1304
 
1298
-      const xy_pos_t diff = current_position - mpos;
1299
-      const float distance = (ref - mpos).magnitude() + diff.magnitude() * 0.1f;
1305
+mesh_index_pair unified_bed_leveling::find_closest_mesh_point_of_type(const MeshPointType type, const xy_pos_t &pos, const bool probe_relative/*=false*/, MeshFlags *done_flags/*=nullptr*/) {
1300 1306
 
1301
-      // factor in the distance from the current location for the normal case
1302
-      // so the nozzle isn't running all over the bed.
1303
-      if (distance < best_so_far) {
1304
-        best_so_far = distance;   // Found a closer location with the desired value type.
1305
-        closest.pos.set(i, j);
1306
-        closest.distance = best_so_far;
1307
-      }
1308
-    }
1309
-  } // GRID_LOOP
1307
+  #if ENABLED(UBL_HILBERT_CURVE)
1310 1308
 
1311
-  return closest;
1312
-}
1309
+    find_closest_t d;
1310
+    d.type           = type;
1311
+    d.done_flags     = done_flags;
1312
+    d.probe_relative = probe_relative;
1313
+    d.closest.invalidate();
1314
+    hilbert_curve::search_from_closest(pos, test_func, &d);
1315
+    return d.closest;
1313 1316
 
1314
-#if ENABLED(UBL_HILBERT_CURVE)
1317
+  #else
1315 1318
 
1316
-  constexpr int8_t  to_fix(int8_t  v) { return v << 1; }
1317
-  constexpr int8_t  to_int(int8_t  v) { return v >> 1; }
1318
-  constexpr uint8_t   log2(uint8_t n) { return (n > 1) ? 1 + log2(n >> 1) : 0; }
1319
-  constexpr uint8_t  order(uint8_t n) { return uint8_t(log2(n - 1)) + 1; }
1320
-
1321
-  void unified_bed_leveling::hilbert(mesh_index_pair &pt, int8_t x, int8_t y, int8_t xi, int8_t xj, int8_t yi, int8_t yj, uint8_t n) {
1322
-    /* Hilbert space filling curve implementation
1323
-     *
1324
-     * x and y are the coordinates of the bottom left corner
1325
-     * xi & xj are the i & j components of the unit x vector of the frame
1326
-     * similarly yi and yj
1327
-     *
1328
-     * From: http://www.fundza.com/algorithmic/space_filling/hilbert/basics/index.html
1329
-     */
1330
-    if (n <= 0)
1331
-      check_if_missing(pt, to_int(x+(xi+yi)/2),to_int(y+(xj+yj)/2));
1332
-    else {
1333
-      hilbert(pt, x,           y,           yi/2,  yj/2,  xi/2,  xj/2, n-1);
1334
-      hilbert(pt, x+xi/2,      y+xj/2,      xi/2,  xj/2,  yi/2,  yj/2, n-1);
1335
-      hilbert(pt, x+xi/2+yi/2, y+xj/2+yj/2, xi/2,  xj/2,  yi/2,  yj/2, n-1);
1336
-      hilbert(pt, x+xi/2+yi,   y+xj/2+yj,  -yi/2, -yj/2, -xi/2, -xj/2, n-1);
1337
-    }
1338
-  }
1319
+    mesh_index_pair closest;
1320
+    closest.invalidate();
1321
+    closest.distance = -99999.9f;
1322
+
1323
+    // Get the reference position, either nozzle or probe
1324
+    const xy_pos_t ref = probe_relative ? pos + probe.offset_xy : pos;
1339 1325
 
1340
-  void unified_bed_leveling::check_if_missing(mesh_index_pair &pt, int x, int y) {
1341
-      if (   pt.distance < 0
1342
-          && x < GRID_MAX_POINTS_X
1343
-          && y < GRID_MAX_POINTS_Y
1344
-          && isnan(z_values[x][y])
1345
-          && probe.can_reach(mesh_index_to_xpos(x), mesh_index_to_ypos(y))
1326
+    float best_so_far = 99999.99f;
1327
+
1328
+    GRID_LOOP(i, j) {
1329
+      if ( (type == (isnan(z_values[i][j]) ? INVALID : REAL))
1330
+        || (type == SET_IN_BITMAP && !done_flags->marked(i, j))
1346 1331
       ) {
1347
-        pt.pos.set(x, y);
1348
-        pt.distance = 1;
1332
+        // Found a Mesh Point of the specified type!
1333
+        const xy_pos_t mpos = { mesh_index_to_xpos(i), mesh_index_to_ypos(j) };
1334
+
1335
+        // If using the probe as the reference there are some unreachable locations.
1336
+        // Also for round beds, there are grid points outside the bed the nozzle can't reach.
1337
+        // Prune them from the list and ignore them till the next Phase (manual nozzle probing).
1338
+
1339
+        if (!(probe_relative ? probe.can_reach(mpos) : position_is_reachable(mpos)))
1340
+          continue;
1341
+
1342
+        // Reachable. Check if it's the best_so_far location to the nozzle.
1343
+
1344
+        const xy_pos_t diff = current_position - mpos;
1345
+        const float distance = (ref - mpos).magnitude() + diff.magnitude() * 0.1f;
1346
+
1347
+        // factor in the distance from the current location for the normal case
1348
+        // so the nozzle isn't running all over the bed.
1349
+        if (distance < best_so_far) {
1350
+          best_so_far = distance;   // Found a closer location with the desired value type.
1351
+          closest.pos.set(i, j);
1352
+          closest.distance = best_so_far;
1353
+        }
1349 1354
       }
1350
-   }
1351
-
1352
-   mesh_index_pair unified_bed_leveling::find_next_mesh_point() {
1353
-     mesh_index_pair pt;
1354
-     pt.invalidate();
1355
-     pt.distance = -99999.9f;
1356
-     constexpr uint8_t ord = order(_MAX(GRID_MAX_POINTS_X, GRID_MAX_POINTS_Y));
1357
-     constexpr uint8_t dim = _BV(ord);
1358
-     hilbert(pt, to_fix(0), to_fix(0), to_fix(dim), to_fix(0), to_fix(0), to_fix(dim), ord);
1359
-     return pt;
1360
-   }
1361
-
1362
-#endif // UBL_HILBERT_CURVE
1355
+    } // GRID_LOOP
1356
+
1357
+    return closest;
1358
+
1359
+  #endif
1360
+}
1363 1361
 
1364 1362
 /**
1365 1363
  * 'Smart Fill': Scan from the outward edges of the mesh towards the center.

+ 23
- 20
Marlin/src/lcd/extui/lib/ftdi_eve_touch_ui/ftdi_eve_lib/extras/adjuster_widget.cpp View File

@@ -30,25 +30,28 @@
30 30
 #define INC_POS           SUB_POS(6,1), SUB_SIZE(2,1)
31 31
 #define DEC_POS           SUB_POS(8,1), SUB_SIZE(2,1)
32 32
 
33
+void draw_adjuster_value(CommandProcessor& cmd, int16_t x, int16_t y, int16_t w, int16_t h, float value, progmem_str units, int8_t width, uint8_t precision) {
34
+  char str[width + precision + 10 + (units ? strlen_P((const char*) units) : 0)];
35
+  if (isnan(value))
36
+    strcpy_P(str, PSTR("-"));
37
+  else
38
+    dtostrf(value, width, precision, str);
39
+
40
+  if (units) {
41
+    strcat_P(str, PSTR(" "));
42
+    strcat_P(str, (const char*) units);
43
+  }
44
+
45
+  cmd.text(VAL_POS, str);
46
+}
47
+
33 48
 void draw_adjuster(CommandProcessor& cmd, int16_t x, int16_t y, int16_t w, int16_t h, uint8_t tag, float value, progmem_str units, int8_t width, uint8_t precision, draw_mode_t what) {
34
-    if (what & BACKGROUND)
35
-      cmd.tag(0).button(VAL_POS, F(""), FTDI::OPT_FLAT);
36
-
37
-    if (what & FOREGROUND) {
38
-      char str[width + precision + 10 + (units ? strlen_P((const char*) units) : 0)];
39
-      if (isnan(value))
40
-        strcpy_P(str, PSTR("-"));
41
-      else
42
-        dtostrf(value, width, precision, str);
43
-
44
-      if (units) {
45
-        strcat_P(str, PSTR(" "));
46
-        strcat_P(str, (const char*) units);
47
-      }
48
-
49
-      cmd.tag(0)
50
-         .text(VAL_POS, str)
51
-         .tag(tag  ).button(INC_POS, F("-"))
52
-         .tag(tag+1).button(DEC_POS, F("+"));
53
-    }
49
+  if (what & BACKGROUND)
50
+    cmd.tag(0).button(VAL_POS, F(""), FTDI::OPT_FLAT);
51
+
52
+  if (what & FOREGROUND) {
53
+    draw_adjuster_value(cmd, x, y, w, h, value, units, width, precision);
54
+    cmd.tag(tag  ).button(INC_POS, F("-"))
55
+       .tag(tag+1).button(DEC_POS, F("+"));
56
+  }
54 57
 }

+ 7
- 0
Marlin/src/lcd/extui/lib/ftdi_eve_touch_ui/ftdi_eve_lib/extras/adjuster_widget.h View File

@@ -22,6 +22,13 @@
22 22
 #pragma once
23 23
 #include "../extended/screen_types.h"
24 24
 
25
+void draw_adjuster_value(
26
+  CommandProcessor& cmd,
27
+  int16_t x, int16_t y, int16_t w, int16_t h,
28
+  float value, progmem_str units = nullptr,
29
+  int8_t width = 5, uint8_t precision = 1
30
+);
31
+
25 32
 void draw_adjuster(
26 33
   CommandProcessor& cmd,
27 34
   int16_t x, int16_t y, int16_t w, int16_t h,

+ 4
- 1
Marlin/src/lcd/extui/lib/ftdi_eve_touch_ui/language/language_en.h View File

@@ -140,10 +140,13 @@ namespace Language_en {
140 140
 
141 141
   PROGMEM Language_Str MSG_TOUCH_CALIBRATION_START  = u8"Release to begin screen calibration";
142 142
   PROGMEM Language_Str MSG_TOUCH_CALIBRATION_PROMPT = u8"Touch the dots to calibrate";
143
-  PROGMEM Language_Str MSG_AUTOLEVEL_X_AXIS         = u8"Level X Axis";
144 143
   PROGMEM Language_Str MSG_BED_MAPPING_DONE         = u8"Bed mapping finished";
145 144
   PROGMEM Language_Str MSG_BED_MAPPING_INCOMPLETE   = u8"Not all points probed";
146 145
   PROGMEM Language_Str MSG_LEVELING                 = u8"Leveling";
146
+  PROGMEM Language_Str MSG_AXIS_LEVELING            = u8"Axis Leveling";
147
+  PROGMEM Language_Str MSG_PROBE_BED                = u8"Probe Mesh";
148
+  PROGMEM Language_Str MSG_SHOW_MESH                = u8"View Mesh";
149
+  PROGMEM Language_Str MSG_PRINT_TEST               = u8"Print Test";
147 150
 
148 151
   #if ENABLED(TOUCH_UI_LULZBOT_BIO)
149 152
     PROGMEM Language_Str MSG_MOVE_TO_HOME           = u8"Move to Home";

+ 17
- 4
Marlin/src/lcd/extui/lib/ftdi_eve_touch_ui/screens/bed_mesh_screen.cpp View File

@@ -225,6 +225,7 @@ bool BedMeshScreen::tagToPoint(uint8_t tag, xy_uint8_t &pt) {
225 225
 }
226 226
 
227 227
 void BedMeshScreen::onEntry() {
228
+  mydata.allowEditing = true;
228 229
   mydata.highlightedTag = 0;
229 230
   mydata.zAdjustment = 0;
230 231
   mydata.count = GRID_MAX_POINTS;
@@ -259,16 +260,16 @@ void BedMeshScreen::adjustHighlightedValue(float increment) {
259 260
 }
260 261
 
261 262
 void BedMeshScreen::saveAdjustedHighlightedValue() {
262
-  if(mydata.zAdjustment) {
263
+  if (mydata.zAdjustment) {
263 264
     BedMeshScreen::setHighlightedValue(BedMeshScreen::getHighlightedValue(true) + mydata.zAdjustment);
264 265
     mydata.zAdjustment = 0;
265 266
   }
266 267
 }
267 268
 
268 269
 void BedMeshScreen::changeHighlightedValue(uint8_t tag) {
269
-  saveAdjustedHighlightedValue();
270
+  if (mydata.allowEditing) saveAdjustedHighlightedValue();
270 271
   mydata.highlightedTag = tag;
271
-  moveToHighlightedValue();
272
+  if (mydata.allowEditing) moveToHighlightedValue();
272 273
 }
273 274
 
274 275
 void BedMeshScreen::drawHighlightedPointValue() {
@@ -277,7 +278,12 @@ void BedMeshScreen::drawHighlightedPointValue() {
277 278
      .colors(normal_btn)
278 279
      .text(Z_LABEL_POS, GET_TEXT_F(MSG_MESH_EDIT_Z))
279 280
      .font(font_small);
280
-  draw_adjuster(cmd, Z_VALUE_POS, 2, getHighlightedValue(true) + mydata.zAdjustment, GET_TEXT_F(MSG_UNITS_MM), 4, 3);
281
+
282
+  if (mydata.allowEditing)
283
+    draw_adjuster(cmd, Z_VALUE_POS, 2, getHighlightedValue(true) + mydata.zAdjustment, GET_TEXT_F(MSG_UNITS_MM), 4, 3);
284
+  else
285
+    draw_adjuster_value(cmd, Z_VALUE_POS, getHighlightedValue(true) + mydata.zAdjustment, GET_TEXT_F(MSG_UNITS_MM), 4, 3);
286
+
281 287
   cmd.colors(action_btn)
282 288
      .tag(1).button(OKAY_POS, GET_TEXT_F(MSG_BUTTON_OKAY))
283 289
      .tag(0);
@@ -347,6 +353,7 @@ void BedMeshScreen::onMeshUpdate(const int8_t, const int8_t, const float) {
347 353
 void BedMeshScreen::onMeshUpdate(const int8_t x, const int8_t y, const ExtUI::probe_state_t state) {
348 354
   switch (state) {
349 355
     case ExtUI::MESH_START:
356
+      mydata.allowEditing = false;
350 357
       mydata.count = 0;
351 358
       mydata.message = mydata.MSG_NONE;
352 359
       break;
@@ -369,10 +376,16 @@ void BedMeshScreen::onMeshUpdate(const int8_t x, const int8_t y, const ExtUI::pr
369 376
 
370 377
 void BedMeshScreen::startMeshProbe() {
371 378
   GOTO_SCREEN(BedMeshScreen);
379
+  mydata.allowEditing = false;
372 380
   mydata.count = 0;
373 381
   injectCommands_P(PSTR(BED_LEVELING_COMMANDS));
374 382
 }
375 383
 
384
+void BedMeshScreen::showMesh() {
385
+  GOTO_SCREEN(BedMeshScreen);
386
+  mydata.allowEditing = false;
387
+}
388
+
376 389
 void BedMeshScreen::showMeshEditor() {
377 390
   SpinnerDialogBox::enqueueAndWait_P(ExtUI::isMachineHomed() ? F("M420 S1") : F("G28\nM420 S1"));
378 391
   // After the spinner, go to this screen.

+ 2
- 0
Marlin/src/lcd/extui/lib/ftdi_eve_touch_ui/screens/bed_mesh_screen.h View File

@@ -33,6 +33,7 @@ struct BedMeshScreenData {
33 33
   uint8_t count;
34 34
   uint8_t highlightedTag;
35 35
   float zAdjustment;
36
+  bool allowEditing;
36 37
 };
37 38
 
38 39
 class BedMeshScreen : public BaseScreen, public CachedScreen<BED_MESH_SCREEN_CACHE> {
@@ -63,5 +64,6 @@ class BedMeshScreen : public BaseScreen, public CachedScreen<BED_MESH_SCREEN_CAC
63 64
     static bool onTouchEnd(uint8_t tag);
64 65
 
65 66
     static void startMeshProbe();
67
+    static void showMesh();
66 68
     static void showMeshEditor();
67 69
 };

+ 43
- 24
Marlin/src/lcd/extui/lib/ftdi_eve_touch_ui/screens/leveling_menu.cpp View File

@@ -34,27 +34,33 @@ using namespace ExtUI;
34 34
 using namespace Theme;
35 35
 
36 36
 #if ENABLED(TOUCH_UI_PORTRAIT)
37
-  #define GRID_ROWS 9
37
+  #define GRID_ROWS 8
38 38
   #define GRID_COLS 2
39
-  #define TITLE_POS          BTN_POS(1,1), BTN_SIZE(2,1)
39
+  #define LEVELING_TITLE_POS BTN_POS(1,1), BTN_SIZE(2,1)
40 40
   #define LEVEL_AXIS_POS     BTN_POS(1,2), BTN_SIZE(2,1)
41
-  #define LEVEL_BED_POS      BTN_POS(1,3), BTN_SIZE(2,1)
42
-  #define EDIT_MESH_POS      BTN_POS(1,4), BTN_SIZE(2,1)
41
+  #define BED_MESH_TITLE_POS BTN_POS(1,3), BTN_SIZE(2,1)
42
+  #define PROBE_BED_POS      BTN_POS(1,4), BTN_SIZE(1,1)
43
+  #define TEST_MESH_POS      BTN_POS(2,4), BTN_SIZE(1,1)
44
+  #define SHOW_MESH_POS      BTN_POS(1,5), BTN_SIZE(1,1)
45
+  #define EDIT_MESH_POS      BTN_POS(2,5), BTN_SIZE(1,1)
43 46
   #define BLTOUCH_TITLE_POS  BTN_POS(1,6), BTN_SIZE(2,1)
44 47
   #define BLTOUCH_RESET_POS  BTN_POS(1,7), BTN_SIZE(1,1)
45 48
   #define BLTOUCH_TEST_POS   BTN_POS(2,7), BTN_SIZE(1,1)
46
-  #define BACK_POS           BTN_POS(1,9), BTN_SIZE(2,1)
49
+  #define BACK_POS           BTN_POS(1,8), BTN_SIZE(2,1)
47 50
 #else
48
-  #define GRID_ROWS 7
49
-  #define GRID_COLS 2
50
-  #define TITLE_POS          BTN_POS(1,1), BTN_SIZE(2,1)
51
-  #define LEVEL_AXIS_POS     BTN_POS(1,2), BTN_SIZE(2,1)
52
-  #define LEVEL_BED_POS      BTN_POS(1,3), BTN_SIZE(2,1)
53
-  #define EDIT_MESH_POS      BTN_POS(1,4), BTN_SIZE(2,1)
54
-  #define BLTOUCH_TITLE_POS  BTN_POS(1,5), BTN_SIZE(2,1)
55
-  #define BLTOUCH_RESET_POS  BTN_POS(1,6), BTN_SIZE(1,1)
56
-  #define BLTOUCH_TEST_POS   BTN_POS(2,6), BTN_SIZE(1,1)
57
-  #define BACK_POS           BTN_POS(1,7), BTN_SIZE(2,1)
51
+  #define GRID_ROWS 6
52
+  #define GRID_COLS 3
53
+  #define LEVELING_TITLE_POS BTN_POS(1,1), BTN_SIZE(3,1)
54
+  #define LEVEL_AXIS_POS     BTN_POS(1,2), BTN_SIZE(3,1)
55
+  #define BED_MESH_TITLE_POS BTN_POS(1,3), BTN_SIZE(2,1)
56
+  #define PROBE_BED_POS      BTN_POS(1,4), BTN_SIZE(1,1)
57
+  #define TEST_MESH_POS      BTN_POS(2,4), BTN_SIZE(1,1)
58
+  #define SHOW_MESH_POS      BTN_POS(1,5), BTN_SIZE(1,1)
59
+  #define EDIT_MESH_POS      BTN_POS(2,5), BTN_SIZE(1,1)
60
+  #define BLTOUCH_TITLE_POS  BTN_POS(3,3), BTN_SIZE(1,1)
61
+  #define BLTOUCH_RESET_POS  BTN_POS(3,4), BTN_SIZE(1,1)
62
+  #define BLTOUCH_TEST_POS   BTN_POS(3,5), BTN_SIZE(1,1)
63
+  #define BACK_POS           BTN_POS(1,6), BTN_SIZE(3,1)
58 64
 #endif
59 65
 
60 66
 void LevelingMenu::onRedraw(draw_mode_t what) {
@@ -69,20 +75,25 @@ void LevelingMenu::onRedraw(draw_mode_t what) {
69 75
     CommandProcessor cmd;
70 76
     cmd.font(font_large)
71 77
        .cmd(COLOR_RGB(bg_text_enabled))
72
-       .text(TITLE_POS, GET_TEXT_F(MSG_LEVELING))
78
+       .text(LEVELING_TITLE_POS, GET_TEXT_F(MSG_AXIS_LEVELING))
79
+       .text(BED_MESH_TITLE_POS, GET_TEXT_F(MSG_BED_LEVELING))
73 80
     #if ENABLED(BLTOUCH)
74 81
        .text(BLTOUCH_TITLE_POS, GET_TEXT_F(MSG_BLTOUCH))
75 82
     #endif
76 83
        .font(font_medium).colors(normal_btn)
77 84
     #if EITHER(Z_STEPPER_AUTO_ALIGN,MECHANICAL_GANTRY_CALIBRATION)
78
-       .tag(2).button(LEVEL_AXIS_POS, GET_TEXT_F(MSG_AUTOLEVEL_X_AXIS))
85
+       .tag(2).button(LEVEL_AXIS_POS, GET_TEXT_F(MSG_LEVEL_X_AXIS))
79 86
     #endif
80
-       .tag(3).button(LEVEL_BED_POS, GET_TEXT_F(MSG_LEVEL_BED))
87
+       .tag(3).button(PROBE_BED_POS, GET_TEXT_F(MSG_PROBE_BED))
88
+       .enabled(ENABLED(HAS_MESH))
89
+       .tag(4).button(SHOW_MESH_POS, GET_TEXT_F(MSG_SHOW_MESH))
81 90
        .enabled(ENABLED(HAS_MESH))
82
-       .tag(4).button(EDIT_MESH_POS, GET_TEXT_F(MSG_EDIT_MESH))
91
+       .tag(5).button(EDIT_MESH_POS, GET_TEXT_F(MSG_EDIT_MESH))
92
+       .enabled(ENABLED(G26_MESH_VALIDATION))
93
+       .tag(6).button(TEST_MESH_POS, GET_TEXT_F(MSG_PRINT_TEST))
83 94
     #if ENABLED(BLTOUCH)
84
-       .tag(5).button(BLTOUCH_RESET_POS, GET_TEXT_F(MSG_BLTOUCH_RESET))
85
-       .tag(6).button(BLTOUCH_TEST_POS,  GET_TEXT_F(MSG_BLTOUCH_SELFTEST))
95
+       .tag(7).button(BLTOUCH_RESET_POS, GET_TEXT_F(MSG_BLTOUCH_RESET))
96
+       .tag(8).button(BLTOUCH_TEST_POS,  GET_TEXT_F(MSG_BLTOUCH_SELFTEST))
86 97
     #endif
87 98
        .colors(action_btn)
88 99
        .tag(1).button(BACK_POS, GET_TEXT_F(MSG_BACK));
@@ -106,11 +117,18 @@ bool LevelingMenu::onTouchEnd(uint8_t tag) {
106 117
     #endif
107 118
     break;
108 119
     #if ENABLED(AUTO_BED_LEVELING_UBL)
109
-    case 4: BedMeshScreen::showMeshEditor(); break;
120
+    case 4: BedMeshScreen::showMesh(); break;
121
+    case 5: BedMeshScreen::showMeshEditor(); break;
122
+    #endif
123
+    #if ENABLED(G26_MESH_VALIDATION)
124
+    case 6:
125
+      GOTO_SCREEN(StatusScreen);
126
+      injectCommands_P(PSTR("M117 Printing Test Pattern\nG28 O\nG26 R"));
127
+      break;
110 128
     #endif
111 129
     #if ENABLED(BLTOUCH)
112
-    case 5: injectCommands_P(PSTR("M280 P0 S60")); break;
113
-    case 6: SpinnerDialogBox::enqueueAndWait_P(F("M280 P0 S90\nG4 P100\nM280 P0 S120")); break;
130
+    case 7: injectCommands_P(PSTR("M280 P0 S60")); break;
131
+    case 8: SpinnerDialogBox::enqueueAndWait_P(F("M280 P0 S90\nG4 P100\nM280 P0 S120")); break;
114 132
     #endif
115 133
     default: return false;
116 134
   }
@@ -118,3 +136,4 @@ bool LevelingMenu::onTouchEnd(uint8_t tag) {
118 136
 }
119 137
 
120 138
 #endif // FTDI_LEVELING_MENU
139
+

+ 1
- 1
Marlin/src/lcd/extui/lib/ftdi_eve_touch_ui/screens/tune_menu.cpp View File

@@ -62,7 +62,7 @@ void TuneMenu::onRedraw(draw_mode_t what) {
62 62
     #define FILAMENT_POS    BTN_POS(1,4), BTN_SIZE(1,1)
63 63
     #define CASE_LIGHT_POS  BTN_POS(2,4), BTN_SIZE(1,1)
64 64
     #define ADVANCED_SETTINGS_POS BTN_POS(1,5), BTN_SIZE(1,1)
65
-    #define BACK_POS        BTN_POS(2,5), BTN_SIZE(2,1)
65
+    #define BACK_POS        BTN_POS(2,5), BTN_SIZE(1,1)
66 66
   #endif
67 67
 
68 68
   if (what & FOREGROUND) {

+ 21
- 10
Marlin/src/lcd/extui/ui_api.cpp View File

@@ -849,10 +849,13 @@ namespace ExtUI {
849 849
   }
850 850
 
851 851
   #if HAS_LEVELING
852
+
852 853
     bool getLevelingActive() { return planner.leveling_active; }
853 854
     void setLevelingActive(const bool state) { set_bed_leveling_enabled(state); }
854 855
     bool getMeshValid() { return leveling_is_valid(); }
856
+
855 857
     #if HAS_MESH
858
+
856 859
       bed_mesh_t& getMeshArray() { return Z_VALUES_ARR; }
857 860
       float getMeshPoint(const xy_uint8_t &pos) { return Z_VALUES(pos.x, pos.y); }
858 861
       void setMeshPoint(const xy_uint8_t &pos, const float &zoff) {
@@ -861,17 +864,23 @@ namespace ExtUI {
861 864
           TERN_(ABL_BILINEAR_SUBDIVISION, bed_level_virt_interpolate());
862 865
         }
863 866
       }
867
+
864 868
       void moveToMeshPoint(const xy_uint8_t &pos, const float &z) {
865 869
         #if EITHER(MESH_BED_LEVELING, AUTO_BED_LEVELING_UBL)
866 870
           const feedRate_t old_feedrate = feedrate_mm_s;
867
-          feedrate_mm_s = Z_PROBE_FEEDRATE_FAST;
868
-          destination = current_position;
869
-          destination[Z_AXIS] = Z_CLEARANCE_BETWEEN_PROBES;
870
-          prepare_line_to_destination();
871
-          feedrate_mm_s = XY_PROBE_FEEDRATE;
872
-          destination[X_AXIS] = MESH_MIN_X + pos.x * MESH_X_DIST;
873
-          destination[Y_AXIS] = MESH_MIN_Y + pos.y * MESH_Y_DIST;
874
-          prepare_line_to_destination();
871
+          const float x_target = MESH_MIN_X + pos.x * (MESH_X_DIST),
872
+                      y_target = MESH_MIN_Y + pos.y * (MESH_Y_DIST);
873
+          if (x_target != current_position[X_AXIS] || y_target != current_position[Y_AXIS]) {
874
+            // If moving across bed, raise nozzle to safe height over bed
875
+            feedrate_mm_s = Z_PROBE_FEEDRATE_FAST;
876
+            destination = current_position;
877
+            destination[Z_AXIS] = Z_CLEARANCE_BETWEEN_PROBES;
878
+            prepare_line_to_destination();
879
+            feedrate_mm_s = XY_PROBE_FEEDRATE;
880
+            destination[X_AXIS] = x_target;
881
+            destination[Y_AXIS] = y_target;
882
+            prepare_line_to_destination();
883
+          }
875 884
           feedrate_mm_s = Z_PROBE_FEEDRATE_FAST;
876 885
           destination[Z_AXIS] = z;
877 886
           prepare_line_to_destination();
@@ -881,8 +890,10 @@ namespace ExtUI {
881 890
           UNUSED(z);
882 891
         #endif
883 892
       }
884
-    #endif
885
-  #endif
893
+
894
+    #endif // HAS_MESH
895
+
896
+  #endif // HAS_LEVELING
886 897
 
887 898
   #if ENABLED(HOST_PROMPT_SUPPORT)
888 899
     void setHostResponse(const uint8_t response) { host_response_handler(response); }

+ 2
- 0
platformio.ini View File

@@ -75,6 +75,7 @@ default_src_filter = +<src/*> -<src/config> -<src/HAL> +<src/HAL/shared>
75 75
   -<src/feature/bedlevel/abl> -<src/gcode/bedlevel/abl>
76 76
   -<src/feature/bedlevel/mbl> -<src/gcode/bedlevel/mbl>
77 77
   -<src/feature/bedlevel/ubl> -<src/gcode/bedlevel/ubl>
78
+  -<src/feature/bedlevel/hilbert_curve.cpp>
78 79
   -<src/feature/binary_stream.cpp> -<src/libs/heatshrink>
79 80
   -<src/feature/bltouch.cpp>
80 81
   -<src/feature/cancel_object.cpp> -<src/gcode/feature/cancel>
@@ -306,6 +307,7 @@ AUTO_BED_LEVELING_BILINEAR = src_filter=+<src/feature/bedlevel/abl>
306 307
 AUTO_BED_LEVELING_(3POINT|(BI)?LINEAR) = src_filter=+<src/gcode/bedlevel/abl>
307 308
 MESH_BED_LEVELING       = src_filter=+<src/feature/bedlevel/mbl> +<src/gcode/bedlevel/mbl>
308 309
 AUTO_BED_LEVELING_UBL   = src_filter=+<src/feature/bedlevel/ubl> +<src/gcode/bedlevel/ubl>
310
+UBL_HILBERT_CURVE       = src_filter=+<src/feature/bedlevel/hilbert_curve.cpp>
309 311
 BACKLASH_COMPENSATION   = src_filter=+<src/feature/backlash.cpp>
310 312
 BARICUDA                = src_filter=+<src/feature/baricuda.cpp> +<src/gcode/feature/baricuda>
311 313
 BINARY_FILE_TRANSFER    = src_filter=+<src/feature/binary_stream.cpp> +<src/libs/heatshrink>

Loading…
Cancel
Save