Selaa lähdekoodia

G26 Hilbert Curve followup (#21480)

Marcio T 3 vuotta sitten
vanhempi
commit
45c1432946
No account linked to committer's email address

+ 1
- 1
Marlin/src/core/utility.h Näytä tiedosto

@@ -34,7 +34,7 @@ void safe_delay(millis_t ms);
34 34
   inline void serial_delay(const millis_t) {}
35 35
 #endif
36 36
 
37
-#if GRID_MAX_POINTS_X && GRID_MAX_POINTS_Y
37
+#if (GRID_MAX_POINTS_X) && (GRID_MAX_POINTS_Y)
38 38
 
39 39
   // 16x16 bit arrays
40 40
   template <int W, int H>

+ 19
- 19
Marlin/src/feature/bedlevel/abl/abl.cpp Näytä tiedosto

@@ -85,9 +85,9 @@ static void extrapolate_one_point(const uint8_t x, const uint8_t y, const int8_t
85 85
 //#define EXTRAPOLATE_FROM_EDGE
86 86
 
87 87
 #if ENABLED(EXTRAPOLATE_FROM_EDGE)
88
-  #if GRID_MAX_POINTS_X < GRID_MAX_POINTS_Y
88
+  #if (GRID_MAX_POINTS_X) < (GRID_MAX_POINTS_Y)
89 89
     #define HALF_IN_X
90
-  #elif GRID_MAX_POINTS_Y < GRID_MAX_POINTS_X
90
+  #elif (GRID_MAX_POINTS_Y) < (GRID_MAX_POINTS_X)
91 91
     #define HALF_IN_Y
92 92
   #endif
93 93
 #endif
@@ -98,23 +98,23 @@ static void extrapolate_one_point(const uint8_t x, const uint8_t y, const int8_t
98 98
  */
99 99
 void extrapolate_unprobed_bed_level() {
100 100
   #ifdef HALF_IN_X
101
-    constexpr uint8_t ctrx2 = 0, xlen = GRID_MAX_POINTS_X - 1;
101
+    constexpr uint8_t ctrx2 = 0, xend = GRID_MAX_POINTS_X - 1;
102 102
   #else
103
-    constexpr uint8_t ctrx1 = (GRID_MAX_POINTS_X - 1) / 2, // left-of-center
104
-                      ctrx2 = (GRID_MAX_POINTS_X) / 2,     // right-of-center
105
-                      xlen = ctrx1;
103
+    constexpr uint8_t ctrx1 = (GRID_MAX_CELLS_X) / 2, // left-of-center
104
+                      ctrx2 = (GRID_MAX_POINTS_X) / 2,  // right-of-center
105
+                      xend = ctrx1;
106 106
   #endif
107 107
 
108 108
   #ifdef HALF_IN_Y
109
-    constexpr uint8_t ctry2 = 0, ylen = GRID_MAX_POINTS_Y - 1;
109
+    constexpr uint8_t ctry2 = 0, yend = GRID_MAX_POINTS_Y - 1;
110 110
   #else
111
-    constexpr uint8_t ctry1 = (GRID_MAX_POINTS_Y - 1) / 2, // top-of-center
112
-                      ctry2 = (GRID_MAX_POINTS_Y) / 2,     // bottom-of-center
113
-                      ylen = ctry1;
111
+    constexpr uint8_t ctry1 = (GRID_MAX_CELLS_Y) / 2, // top-of-center
112
+                      ctry2 = (GRID_MAX_POINTS_Y) / 2,  // bottom-of-center
113
+                      yend = ctry1;
114 114
   #endif
115 115
 
116
-  LOOP_LE_N(xo, xlen)
117
-    LOOP_LE_N(yo, ylen) {
116
+  LOOP_LE_N(xo, xend)
117
+    LOOP_LE_N(yo, yend) {
118 118
       uint8_t x2 = ctrx2 + xo, y2 = ctry2 + yo;
119 119
       #ifndef HALF_IN_X
120 120
         const uint8_t x1 = ctrx1 - xo;
@@ -143,8 +143,8 @@ void print_bilinear_leveling_grid() {
143 143
 
144 144
 #if ENABLED(ABL_BILINEAR_SUBDIVISION)
145 145
 
146
-  #define ABL_GRID_POINTS_VIRT_X (GRID_MAX_POINTS_X - 1) * (BILINEAR_SUBDIVISIONS) + 1
147
-  #define ABL_GRID_POINTS_VIRT_Y (GRID_MAX_POINTS_Y - 1) * (BILINEAR_SUBDIVISIONS) + 1
146
+  #define ABL_GRID_POINTS_VIRT_X GRID_MAX_CELLS_X * (BILINEAR_SUBDIVISIONS) + 1
147
+  #define ABL_GRID_POINTS_VIRT_Y GRID_MAX_CELLS_Y * (BILINEAR_SUBDIVISIONS) + 1
148 148
   #define ABL_TEMP_POINTS_X (GRID_MAX_POINTS_X + 2)
149 149
   #define ABL_TEMP_POINTS_Y (GRID_MAX_POINTS_Y + 2)
150 150
   float z_values_virt[ABL_GRID_POINTS_VIRT_X][ABL_GRID_POINTS_VIRT_Y];
@@ -161,7 +161,7 @@ void print_bilinear_leveling_grid() {
161 161
   #define LINEAR_EXTRAPOLATION(E, I) ((E) * 2 - (I))
162 162
   float bed_level_virt_coord(const uint8_t x, const uint8_t y) {
163 163
     uint8_t ep = 0, ip = 1;
164
-    if (x > GRID_MAX_POINTS_X + 1 || y > GRID_MAX_POINTS_Y + 1) {
164
+    if (x > (GRID_MAX_POINTS_X) + 1 || y > (GRID_MAX_POINTS_Y) + 1) {
165 165
       // The requested point requires extrapolating two points beyond the mesh.
166 166
       // These values are only requested for the edges of the mesh, which are always an actual mesh point,
167 167
       // and do not require interpolation. When interpolation is not needed, this "Mesh + 2" point is
@@ -171,8 +171,8 @@ void print_bilinear_leveling_grid() {
171 171
     }
172 172
     if (!x || x == ABL_TEMP_POINTS_X - 1) {
173 173
       if (x) {
174
-        ep = GRID_MAX_POINTS_X - 1;
175
-        ip = GRID_MAX_POINTS_X - 2;
174
+        ep = (GRID_MAX_POINTS_X) - 1;
175
+        ip = GRID_MAX_CELLS_X - 1;
176 176
       }
177 177
       if (WITHIN(y, 1, ABL_TEMP_POINTS_Y - 2))
178 178
         return LINEAR_EXTRAPOLATION(
@@ -187,8 +187,8 @@ void print_bilinear_leveling_grid() {
187 187
     }
188 188
     if (!y || y == ABL_TEMP_POINTS_Y - 1) {
189 189
       if (y) {
190
-        ep = GRID_MAX_POINTS_Y - 1;
191
-        ip = GRID_MAX_POINTS_Y - 2;
190
+        ep = (GRID_MAX_POINTS_Y) - 1;
191
+        ip = GRID_MAX_CELLS_Y - 1;
192 192
       }
193 193
       if (WITHIN(x, 1, ABL_TEMP_POINTS_X - 2))
194 194
         return LINEAR_EXTRAPOLATION(

+ 3
- 5
Marlin/src/feature/bedlevel/hilbert_curve.cpp Näytä tiedosto

@@ -36,7 +36,7 @@ constexpr uint8_t dim = _BV(ord);
36 36
 static inline bool eval_candidate(int8_t x, int8_t y, hilbert_curve::callback_ptr func, void *data) {
37 37
   // The print bed likely has fewer points than the full Hilbert
38 38
   // curve, so cull unecessary points
39
-  return x < GRID_MAX_POINTS_X && y < GRID_MAX_POINTS_Y ? func(x, y, data) : false;
39
+  return x < (GRID_MAX_POINTS_X) && y < (GRID_MAX_POINTS_Y) ? func(x, y, data) : false;
40 40
 }
41 41
 
42 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) {
@@ -102,10 +102,8 @@ bool hilbert_curve::search_from(uint8_t x, uint8_t y, hilbert_curve::callback_pt
102 102
  */
103 103
 bool hilbert_curve::search_from_closest(const xy_pos_t &pos, hilbert_curve::callback_ptr func, void *data) {
104 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);
105
+  const uint8_t grid_x = LROUND(constrain(float(pos.x - (MESH_MIN_X)) / (MESH_X_DIST), 0, (GRID_MAX_POINTS_X) - 1));
106
+  const uint8_t grid_y = LROUND(constrain(float(pos.y - (MESH_MIN_Y)) / (MESH_Y_DIST), 0, (GRID_MAX_POINTS_Y) - 1));
109 107
   return search_from(grid_x, grid_y, func, data);
110 108
 }
111 109
 

+ 4
- 4
Marlin/src/feature/bedlevel/mbl/mesh_bed_leveling.cpp Näytä tiedosto

@@ -64,10 +64,10 @@
64 64
     void mesh_bed_leveling::line_to_destination(const_feedRate_t scaled_fr_mm_s, uint8_t x_splits, uint8_t y_splits) {
65 65
       // Get current and destination cells for this line
66 66
       xy_int8_t scel = cell_indexes(current_position), ecel = cell_indexes(destination);
67
-      NOMORE(scel.x, GRID_MAX_POINTS_X - 2);
68
-      NOMORE(scel.y, GRID_MAX_POINTS_Y - 2);
69
-      NOMORE(ecel.x, GRID_MAX_POINTS_X - 2);
70
-      NOMORE(ecel.y, GRID_MAX_POINTS_Y - 2);
67
+      NOMORE(scel.x, GRID_MAX_CELLS_X - 1);
68
+      NOMORE(scel.y, GRID_MAX_CELLS_Y - 1);
69
+      NOMORE(ecel.x, GRID_MAX_CELLS_X - 1);
70
+      NOMORE(ecel.y, GRID_MAX_CELLS_Y - 1);
71 71
 
72 72
       // Start and end in the same cell? No split needed.
73 73
       if (scel == ecel) {

+ 7
- 7
Marlin/src/feature/bedlevel/mbl/mesh_bed_leveling.h Näytä tiedosto

@@ -32,8 +32,8 @@ enum MeshLevelingState : char {
32 32
   MeshReset       // G29 S5
33 33
 };
34 34
 
35
-#define MESH_X_DIST (float(MESH_MAX_X - (MESH_MIN_X)) / float(GRID_MAX_POINTS_X - 1))
36
-#define MESH_Y_DIST (float(MESH_MAX_Y - (MESH_MIN_Y)) / float(GRID_MAX_POINTS_Y - 1))
35
+#define MESH_X_DIST (float(MESH_MAX_X - (MESH_MIN_X)) / (GRID_MAX_CELLS_X))
36
+#define MESH_Y_DIST (float(MESH_MAX_Y - (MESH_MIN_Y)) / (GRID_MAX_CELLS_Y))
37 37
 #define _GET_MESH_X(I) mbl.index_to_xpos[I]
38 38
 #define _GET_MESH_Y(J) mbl.index_to_ypos[J]
39 39
 #define Z_VALUES_ARR mbl.z_values
@@ -61,7 +61,7 @@ public:
61 61
   static inline void zigzag(const int8_t index, int8_t &px, int8_t &py) {
62 62
     px = index % (GRID_MAX_POINTS_X);
63 63
     py = index / (GRID_MAX_POINTS_X);
64
-    if (py & 1) px = (GRID_MAX_POINTS_X - 1) - px; // Zig zag
64
+    if (py & 1) px = (GRID_MAX_POINTS_X) - 1 - px; // Zig zag
65 65
   }
66 66
 
67 67
   static void set_zigzag_z(const int8_t index, const_float_t z) {
@@ -72,11 +72,11 @@ public:
72 72
 
73 73
   static int8_t cell_index_x(const_float_t x) {
74 74
     int8_t cx = (x - (MESH_MIN_X)) * RECIPROCAL(MESH_X_DIST);
75
-    return constrain(cx, 0, (GRID_MAX_POINTS_X) - 2);
75
+    return constrain(cx, 0, GRID_MAX_CELLS_X - 1);
76 76
   }
77 77
   static int8_t cell_index_y(const_float_t y) {
78 78
     int8_t cy = (y - (MESH_MIN_Y)) * RECIPROCAL(MESH_Y_DIST);
79
-    return constrain(cy, 0, (GRID_MAX_POINTS_Y) - 2);
79
+    return constrain(cy, 0, GRID_MAX_CELLS_Y - 1);
80 80
   }
81 81
   static inline xy_int8_t cell_indexes(const_float_t x, const_float_t y) {
82 82
     return { cell_index_x(x), cell_index_y(y) };
@@ -85,11 +85,11 @@ public:
85 85
 
86 86
   static int8_t probe_index_x(const_float_t x) {
87 87
     int8_t px = (x - (MESH_MIN_X) + 0.5f * (MESH_X_DIST)) * RECIPROCAL(MESH_X_DIST);
88
-    return WITHIN(px, 0, GRID_MAX_POINTS_X - 1) ? px : -1;
88
+    return WITHIN(px, 0, (GRID_MAX_POINTS_X) - 1) ? px : -1;
89 89
   }
90 90
   static int8_t probe_index_y(const_float_t y) {
91 91
     int8_t py = (y - (MESH_MIN_Y) + 0.5f * (MESH_Y_DIST)) * RECIPROCAL(MESH_Y_DIST);
92
-    return WITHIN(py, 0, GRID_MAX_POINTS_Y - 1) ? py : -1;
92
+    return WITHIN(py, 0, (GRID_MAX_POINTS_Y) - 1) ? py : -1;
93 93
   }
94 94
   static inline xy_int8_t probe_indexes(const_float_t x, const_float_t y) {
95 95
     return { probe_index_x(x), probe_index_y(y) };

+ 2
- 2
Marlin/src/feature/bedlevel/ubl/ubl.cpp Näytä tiedosto

@@ -190,7 +190,7 @@ void unified_bed_leveling::display_map(const int map_type) {
190 190
   const xy_int8_t curr = closest_indexes(xy_pos_t(current_position) + probe.offset_xy);
191 191
 
192 192
   if (!lcd) SERIAL_EOL();
193
-  for (int8_t j = GRID_MAX_POINTS_Y - 1; j >= 0; j--) {
193
+  for (int8_t j = (GRID_MAX_POINTS_Y) - 1; j >= 0; j--) {
194 194
 
195 195
     // Row Label (J index)
196 196
     if (human) {
@@ -217,7 +217,7 @@ void unified_bed_leveling::display_map(const int map_type) {
217 217
         if (human && f >= 0.0) SERIAL_CHAR(f > 0 ? '+' : ' ');  // Display sign also for positive numbers (' ' for 0)
218 218
         SERIAL_ECHO_F(f, 3);                                    // Positive: 5 digits, Negative: 6 digits
219 219
       }
220
-      if (csv && i < GRID_MAX_POINTS_X - 1) SERIAL_CHAR('\t');
220
+      if (csv && i < (GRID_MAX_POINTS_X) - 1) SERIAL_CHAR('\t');
221 221
 
222 222
       // Closing Brace or Space
223 223
       if (human) SERIAL_CHAR(is_current ? ']' : ' ');

+ 23
- 23
Marlin/src/feature/bedlevel/ubl/ubl.h Näytä tiedosto

@@ -38,8 +38,8 @@ enum MeshPointType : char { INVALID, REAL, SET_IN_BITMAP };
38 38
 
39 39
 struct mesh_index_pair;
40 40
 
41
-#define MESH_X_DIST (float(MESH_MAX_X - (MESH_MIN_X)) / float(GRID_MAX_POINTS_X - 1))
42
-#define MESH_Y_DIST (float(MESH_MAX_Y - (MESH_MIN_Y)) / float(GRID_MAX_POINTS_Y - 1))
41
+#define MESH_X_DIST (float(MESH_MAX_X - (MESH_MIN_X)) / (GRID_MAX_CELLS_X))
42
+#define MESH_Y_DIST (float(MESH_MAX_Y - (MESH_MIN_Y)) / (GRID_MAX_CELLS_Y))
43 43
 
44 44
 #if ENABLED(OPTIMIZED_MESH_STORAGE)
45 45
   typedef int16_t mesh_store_t[GRID_MAX_POINTS_X][GRID_MAX_POINTS_Y];
@@ -142,19 +142,19 @@ public:
142 142
   }
143 143
 
144 144
   static int8_t cell_index_x_valid(const_float_t x) {
145
-    return WITHIN(cell_index_x_raw(x), 0, (GRID_MAX_POINTS_X - 2));
145
+    return WITHIN(cell_index_x_raw(x), 0, GRID_MAX_CELLS_X - 1);
146 146
   }
147 147
 
148 148
   static int8_t cell_index_y_valid(const_float_t y) {
149
-    return WITHIN(cell_index_y_raw(y), 0, (GRID_MAX_POINTS_Y - 2));
149
+    return WITHIN(cell_index_y_raw(y), 0, GRID_MAX_CELLS_Y - 1);
150 150
   }
151 151
 
152 152
   static int8_t cell_index_x(const_float_t x) {
153
-    return constrain(cell_index_x_raw(x), 0, (GRID_MAX_POINTS_X) - 2);
153
+    return constrain(cell_index_x_raw(x), 0, GRID_MAX_CELLS_X - 1);
154 154
   }
155 155
 
156 156
   static int8_t cell_index_y(const_float_t y) {
157
-    return constrain(cell_index_y_raw(y), 0, (GRID_MAX_POINTS_Y) - 2);
157
+    return constrain(cell_index_y_raw(y), 0, GRID_MAX_CELLS_Y - 1);
158 158
   }
159 159
 
160 160
   static inline xy_int8_t cell_indexes(const_float_t x, const_float_t y) {
@@ -164,11 +164,11 @@ public:
164 164
 
165 165
   static int8_t closest_x_index(const_float_t x) {
166 166
     const int8_t px = (x - (MESH_MIN_X) + (MESH_X_DIST) * 0.5) * RECIPROCAL(MESH_X_DIST);
167
-    return WITHIN(px, 0, GRID_MAX_POINTS_X - 1) ? px : -1;
167
+    return WITHIN(px, 0, (GRID_MAX_POINTS_X) - 1) ? px : -1;
168 168
   }
169 169
   static int8_t closest_y_index(const_float_t y) {
170 170
     const int8_t py = (y - (MESH_MIN_Y) + (MESH_Y_DIST) * 0.5) * RECIPROCAL(MESH_Y_DIST);
171
-    return WITHIN(py, 0, GRID_MAX_POINTS_Y - 1) ? py : -1;
171
+    return WITHIN(py, 0, (GRID_MAX_POINTS_Y) - 1) ? py : -1;
172 172
   }
173 173
   static inline xy_int8_t closest_indexes(const xy_pos_t &xy) {
174 174
     return { closest_x_index(xy.x), closest_y_index(xy.y) };
@@ -204,10 +204,10 @@ public:
204 204
    * the case where the printer is making a vertical line that only crosses horizontal mesh lines.
205 205
    */
206 206
   static inline float z_correction_for_x_on_horizontal_mesh_line(const_float_t rx0, const int x1_i, const int yi) {
207
-    if (!WITHIN(x1_i, 0, GRID_MAX_POINTS_X - 1) || !WITHIN(yi, 0, GRID_MAX_POINTS_Y - 1)) {
207
+    if (!WITHIN(x1_i, 0, (GRID_MAX_POINTS_X) - 1) || !WITHIN(yi, 0, (GRID_MAX_POINTS_Y) - 1)) {
208 208
 
209 209
       if (DEBUGGING(LEVELING)) {
210
-        if (WITHIN(x1_i, 0, GRID_MAX_POINTS_X - 1)) DEBUG_ECHOPGM("yi"); else DEBUG_ECHOPGM("x1_i");
210
+        if (WITHIN(x1_i, 0, (GRID_MAX_POINTS_X) - 1)) DEBUG_ECHOPGM("yi"); else DEBUG_ECHOPGM("x1_i");
211 211
         DEBUG_ECHOLNPAIR(" out of bounds in z_correction_for_x_on_horizontal_mesh_line(rx0=", rx0, ",x1_i=", x1_i, ",yi=", yi, ")");
212 212
       }
213 213
 
@@ -218,19 +218,19 @@ public:
218 218
     const float xratio = (rx0 - mesh_index_to_xpos(x1_i)) * RECIPROCAL(MESH_X_DIST),
219 219
                 z1 = z_values[x1_i][yi];
220 220
 
221
-    return z1 + xratio * (z_values[_MIN(x1_i, GRID_MAX_POINTS_X - 2) + 1][yi] - z1); // Don't allow x1_i+1 to be past the end of the array
222
-                                                                                    // If it is, it is clamped to the last element of the
223
-                                                                                    // z_values[][] array and no correction is applied.
221
+    return z1 + xratio * (z_values[_MIN(x1_i, (GRID_MAX_POINTS_X) - 2) + 1][yi] - z1);  // Don't allow x1_i+1 to be past the end of the array
222
+                                                                                        // If it is, it is clamped to the last element of the
223
+                                                                                        // z_values[][] array and no correction is applied.
224 224
   }
225 225
 
226 226
   //
227 227
   // See comments above for z_correction_for_x_on_horizontal_mesh_line
228 228
   //
229 229
   static inline float z_correction_for_y_on_vertical_mesh_line(const_float_t ry0, const int xi, const int y1_i) {
230
-    if (!WITHIN(xi, 0, GRID_MAX_POINTS_X - 1) || !WITHIN(y1_i, 0, GRID_MAX_POINTS_Y - 1)) {
230
+    if (!WITHIN(xi, 0, (GRID_MAX_POINTS_X) - 1) || !WITHIN(y1_i, 0, (GRID_MAX_POINTS_Y) - 1)) {
231 231
 
232 232
       if (DEBUGGING(LEVELING)) {
233
-        if (WITHIN(xi, 0, GRID_MAX_POINTS_X - 1)) DEBUG_ECHOPGM("y1_i"); else DEBUG_ECHOPGM("xi");
233
+        if (WITHIN(xi, 0, (GRID_MAX_POINTS_X) - 1)) DEBUG_ECHOPGM("y1_i"); else DEBUG_ECHOPGM("xi");
234 234
         DEBUG_ECHOLNPAIR(" out of bounds in z_correction_for_y_on_vertical_mesh_line(ry0=", ry0, ", xi=", xi, ", y1_i=", y1_i, ")");
235 235
       }
236 236
 
@@ -241,9 +241,9 @@ public:
241 241
     const float yratio = (ry0 - mesh_index_to_ypos(y1_i)) * RECIPROCAL(MESH_Y_DIST),
242 242
                 z1 = z_values[xi][y1_i];
243 243
 
244
-    return z1 + yratio * (z_values[xi][_MIN(y1_i, GRID_MAX_POINTS_Y - 2) + 1] - z1); // Don't allow y1_i+1 to be past the end of the array
245
-                                                                                    // If it is, it is clamped to the last element of the
246
-                                                                                    // z_values[][] array and no correction is applied.
244
+    return z1 + yratio * (z_values[xi][_MIN(y1_i, (GRID_MAX_POINTS_Y) - 2) + 1] - z1);  // Don't allow y1_i+1 to be past the end of the array
245
+                                                                                        // If it is, it is clamped to the last element of the
246
+                                                                                        // z_values[][] array and no correction is applied.
247 247
   }
248 248
 
249 249
   /**
@@ -266,11 +266,11 @@ public:
266 266
 
267 267
     const float z1 = calc_z0(rx0,
268 268
                              mesh_index_to_xpos(cx), z_values[cx][cy],
269
-                             mesh_index_to_xpos(cx + 1), z_values[_MIN(cx, GRID_MAX_POINTS_X - 2) + 1][cy]);
269
+                             mesh_index_to_xpos(cx + 1), z_values[_MIN(cx, (GRID_MAX_POINTS_X) - 2) + 1][cy]);
270 270
 
271 271
     const float z2 = calc_z0(rx0,
272
-                             mesh_index_to_xpos(cx), z_values[cx][_MIN(cy, GRID_MAX_POINTS_Y - 2) + 1],
273
-                             mesh_index_to_xpos(cx + 1), z_values[_MIN(cx, GRID_MAX_POINTS_X - 2) + 1][_MIN(cy, GRID_MAX_POINTS_Y - 2) + 1]);
272
+                             mesh_index_to_xpos(cx), z_values[cx][_MIN(cy, (GRID_MAX_POINTS_Y) - 2) + 1],
273
+                             mesh_index_to_xpos(cx + 1), z_values[_MIN(cx, (GRID_MAX_POINTS_X) - 2) + 1][_MIN(cy, (GRID_MAX_POINTS_Y) - 2) + 1]);
274 274
 
275 275
     float z0 = calc_z0(ry0,
276 276
                        mesh_index_to_ypos(cy), z1,
@@ -302,10 +302,10 @@ public:
302 302
   static inline float get_z_correction(const xy_pos_t &pos) { return get_z_correction(pos.x, pos.y); }
303 303
 
304 304
   static inline float mesh_index_to_xpos(const uint8_t i) {
305
-    return i < GRID_MAX_POINTS_X ? pgm_read_float(&_mesh_index_to_xpos[i]) : MESH_MIN_X + i * (MESH_X_DIST);
305
+    return i < (GRID_MAX_POINTS_X) ? pgm_read_float(&_mesh_index_to_xpos[i]) : MESH_MIN_X + i * (MESH_X_DIST);
306 306
   }
307 307
   static inline float mesh_index_to_ypos(const uint8_t i) {
308
-    return i < GRID_MAX_POINTS_Y ? pgm_read_float(&_mesh_index_to_ypos[i]) : MESH_MIN_Y + i * (MESH_Y_DIST);
308
+    return i < (GRID_MAX_POINTS_Y) ? pgm_read_float(&_mesh_index_to_ypos[i]) : MESH_MIN_Y + i * (MESH_Y_DIST);
309 309
   }
310 310
 
311 311
   #if UBL_SEGMENTED

+ 4
- 4
Marlin/src/feature/bedlevel/ubl/ubl_G29.cpp Näytä tiedosto

@@ -433,8 +433,7 @@ void unified_bed_leveling::G29() {
433 433
             SERIAL_DECIMAL(param.XY_pos.y);
434 434
             SERIAL_ECHOLNPGM(").\n");
435 435
           }
436
-          const xy_pos_t near_probe_xy = param.XY_pos + probe.offset_xy;
437
-          probe_entire_mesh(near_probe_xy, parser.seen('T'), parser.seen('E'), parser.seen('U'));
436
+          probe_entire_mesh(param.XY_pos, parser.seen('T'), parser.seen('E'), parser.seen('U'));
438 437
 
439 438
           report_current_position();
440 439
           probe_deployed = true;
@@ -1140,8 +1139,9 @@ bool unified_bed_leveling::G29_parse_parameters() {
1140 1139
   }
1141 1140
 
1142 1141
   // If X or Y are not valid, use center of the bed values
1143
-  if (!COORDINATE_OKAY(sx, X_MIN_BED, X_MAX_BED)) sx = X_CENTER;
1144
-  if (!COORDINATE_OKAY(sy, Y_MIN_BED, Y_MAX_BED)) sy = Y_CENTER;
1142
+  // (for UBL_HILBERT_CURVE default to lower-left corner instead)
1143
+  if (!COORDINATE_OKAY(sx, X_MIN_BED, X_MAX_BED)) sx = TERN(UBL_HILBERT_CURVE, 0, X_CENTER);
1144
+  if (!COORDINATE_OKAY(sy, Y_MIN_BED, Y_MAX_BED)) sy = TERN(UBL_HILBERT_CURVE, 0, Y_CENTER);
1145 1145
 
1146 1146
   if (err_flag) return UBL_ERR;
1147 1147
 

+ 2
- 2
Marlin/src/feature/bedlevel/ubl/ubl_motion.cpp Näytä tiedosto

@@ -397,8 +397,8 @@
397 397
         int8_t((raw.x - (MESH_MIN_X)) * RECIPROCAL(MESH_X_DIST)),
398 398
         int8_t((raw.y - (MESH_MIN_Y)) * RECIPROCAL(MESH_Y_DIST))
399 399
       };
400
-      LIMIT(icell.x, 0, (GRID_MAX_POINTS_X) - 1);
401
-      LIMIT(icell.y, 0, (GRID_MAX_POINTS_Y) - 1);
400
+      LIMIT(icell.x, 0, GRID_MAX_CELLS_X);
401
+      LIMIT(icell.y, 0, GRID_MAX_CELLS_Y);
402 402
 
403 403
       float z_x0y0 = z_values[icell.x  ][icell.y  ],  // z at lower left corner
404 404
             z_x1y0 = z_values[icell.x+1][icell.y  ],  // z at upper left corner

+ 295
- 300
Marlin/src/gcode/bedlevel/G26.cpp Näytä tiedosto

@@ -113,6 +113,10 @@
113 113
 #include "../../module/temperature.h"
114 114
 #include "../../lcd/marlinui.h"
115 115
 
116
+#if ENABLED(UBL_HILBERT_CURVE)
117
+  #include "../../feature/bedlevel/hilbert_curve.h"
118
+#endif
119
+
116 120
 #define EXTRUSION_MULTIPLIER 1.0
117 121
 #define PRIME_LENGTH 10.0
118 122
 #define OOZE_AMOUNT 0.3
@@ -145,24 +149,9 @@
145 149
 
146 150
 constexpr float g26_e_axis_feedrate = 0.025;
147 151
 
148
-static MeshFlags circle_flags, horizontal_mesh_line_flags, vertical_mesh_line_flags;
152
+static MeshFlags circle_flags;
149 153
 float g26_random_deviation = 0.0;
150 154
 
151
-static bool g26_retracted = false; // Track the retracted state of the nozzle so mismatched
152
-                                   // retracts/recovers won't result in a bad state.
153
-
154
-float g26_extrusion_multiplier,
155
-      g26_retraction_multiplier,
156
-      g26_layer_height,
157
-      g26_prime_length;
158
-
159
-xy_pos_t g26_xy_pos; // = { 0, 0 }
160
-
161
-int16_t g26_bed_temp,
162
-        g26_hotend_temp;
163
-
164
-int8_t g26_prime_flag;
165
-
166 155
 #if HAS_LCD_MENU
167 156
 
168 157
   /**
@@ -178,52 +167,17 @@ int8_t g26_prime_flag;
178 167
 
179 168
 #endif
180 169
 
181
-mesh_index_pair find_closest_circle_to_print(const xy_pos_t &pos) {
182
-  float closest = 99999.99;
183
-  mesh_index_pair out_point;
184
-
185
-  out_point.pos = -1;
186
-
187
-  GRID_LOOP(i, j) {
188
-    if (!circle_flags.marked(i, j)) {
189
-      // We found a circle that needs to be printed
190
-      const xy_pos_t m = { _GET_MESH_X(i), _GET_MESH_Y(j) };
191
-
192
-      // Get the distance to this intersection
193
-      float f = (pos - m).magnitude();
194
-
195
-      // It is possible that we are being called with the values
196
-      // to let us find the closest circle to the start position.
197
-      // But if this is not the case, add a small weighting to the
198
-      // distance calculation to help it choose a better place to continue.
199
-      f += (g26_xy_pos - m).magnitude() / 15.0f;
200
-
201
-      // Add the specified amount of Random Noise to our search
202
-      if (g26_random_deviation > 1.0) f += random(0.0, g26_random_deviation);
203
-
204
-      if (f < closest) {
205
-        closest = f;          // Found a closer un-printed location
206
-        out_point.pos.set(i, j);  // Save its data
207
-        out_point.distance = closest;
208
-      }
209
-    }
210
-  }
211
-  circle_flags.mark(out_point); // Mark this location as done.
212
-  return out_point;
213
-}
214
-
215 170
 void move_to(const_float_t rx, const_float_t ry, const_float_t z, const_float_t e_delta) {
216 171
   static float last_z = -999.99;
217 172
 
218 173
   const xy_pos_t dest = { rx, ry };
219 174
 
220
-  const bool has_xy_component = dest != current_position; // Check if X or Y is involved in the movement.
221
-  const bool has_e_component = e_delta != 0.0;
222
-
223
-  destination = current_position;
175
+  const bool has_xy_component = dest != current_position, // Check if X or Y is involved in the movement.
176
+             has_e_component = e_delta != 0.0;
224 177
 
225 178
   if (z != last_z) {
226
-    last_z = destination.z = z;
179
+    last_z = z;
180
+    destination.set(current_position.x, current_position.y, z, current_position.e);
227 181
     const feedRate_t fr_mm_s = planner.settings.max_feedrate_mm_s[Z_AXIS] * 0.5f; // Use half of the Z_AXIS max feed rate
228 182
     prepare_internal_move_to_destination(fr_mm_s);
229 183
   }
@@ -239,241 +193,293 @@ void move_to(const_float_t rx, const_float_t ry, const_float_t z, const_float_t
239 193
   prepare_internal_move_to_destination(fr_mm_s);
240 194
 }
241 195
 
242
-FORCE_INLINE void move_to(const xyz_pos_t &where, const_float_t de) { move_to(where.x, where.y, where.z, de); }
196
+void move_to(const xyz_pos_t &where, const_float_t de) { move_to(where.x, where.y, where.z, de); }
243 197
 
244
-void retract_filament(const xyz_pos_t &where) {
245
-  if (!g26_retracted) { // Only retract if we are not already retracted!
246
-    g26_retracted = true;
247
-    move_to(where, -1.0f * g26_retraction_multiplier);
248
-  }
249
-}
198
+typedef struct {
199
+  float extrusion_multiplier  = EXTRUSION_MULTIPLIER,
200
+        retraction_multiplier = G26_RETRACT_MULTIPLIER,
201
+        layer_height          = MESH_TEST_LAYER_HEIGHT,
202
+        prime_length          = PRIME_LENGTH;
250 203
 
251
-// TODO: Parameterize the Z lift with a define
252
-void retract_lift_move(const xyz_pos_t &s) {
253
-  retract_filament(destination);
254
-  move_to(current_position.x, current_position.y, current_position.z + 0.5f, 0.0);  // Z lift to minimize scraping
255
-  move_to(s.x, s.y, s.z + 0.5f, 0.0);  // Get to the starting point with no extrusion while lifted
256
-}
204
+  int16_t bed_temp            = MESH_TEST_BED_TEMP,
205
+          hotend_temp         = MESH_TEST_HOTEND_TEMP;
206
+
207
+  float nozzle                = MESH_TEST_NOZZLE_SIZE,
208
+        filament_diameter     = DEFAULT_NOMINAL_FILAMENT_DIA,
209
+        ooze_amount;            // 'O' ... OOZE_AMOUNT
257 210
 
258
-void recover_filament(const xyz_pos_t &where) {
259
-  if (g26_retracted) { // Only un-retract if we are retracted.
260
-    move_to(where, 1.2f * g26_retraction_multiplier);
261
-    g26_retracted = false;
211
+  bool continue_with_closest,   // 'C'
212
+       keep_heaters_on;         // 'K'
213
+
214
+  xy_pos_t xy_pos; // = { 0, 0 }
215
+
216
+  int8_t prime_flag = 0;
217
+
218
+  bool g26_retracted = false;  // Track the retracted state during G26 so mismatched
219
+                               // retracts/recovers don't result in a bad state.
220
+
221
+  void retract_filament(const xyz_pos_t &where) {
222
+    if (!g26_retracted) { // Only retract if we are not already retracted!
223
+      g26_retracted = true;
224
+      move_to(where, -1.0f * retraction_multiplier);
225
+    }
262 226
   }
263
-}
264 227
 
265
-/**
266
- * print_line_from_here_to_there() takes two cartesian coordinates and draws a line from one
267
- * to the other. But there are really three sets of coordinates involved. The first coordinate
268
- * is the present location of the nozzle. We don't necessarily want to print from this location.
269
- * We first need to move the nozzle to the start of line segment where we want to print. Once
270
- * there, we can use the two coordinates supplied to draw the line.
271
- *
272
- * Note:  Although we assume the first set of coordinates is the start of the line and the second
273
- * set of coordinates is the end of the line, it does not always work out that way. This function
274
- * optimizes the movement to minimize the travel distance before it can start printing. This saves
275
- * a lot of time and eliminates a lot of nonsensical movement of the nozzle. However, it does
276
- * cause a lot of very little short retracement of th nozzle when it draws the very first line
277
- * segment of a 'circle'. The time this requires is very short and is easily saved by the other
278
- * cases where the optimization comes into play.
279
- */
280
-void print_line_from_here_to_there(const xyz_pos_t &s, const xyz_pos_t &e) {
228
+  // TODO: Parameterize the Z lift with a define
229
+  void retract_lift_move(const xyz_pos_t &s) {
230
+    retract_filament(destination);
231
+    move_to(current_position.x, current_position.y, current_position.z + 0.5f, 0.0f);  // Z lift to minimize scraping
232
+    move_to(s.x, s.y, s.z + 0.5f, 0.0f);  // Get to the starting point with no extrusion while lifted
233
+  }
281 234
 
282
-  // Distances to the start / end of the line
283
-  xy_float_t svec = current_position - s, evec = current_position - e;
235
+  void recover_filament(const xyz_pos_t &where) {
236
+    if (g26_retracted) { // Only un-retract if we are retracted.
237
+      move_to(where, 1.2f * retraction_multiplier);
238
+      g26_retracted = false;
239
+    }
240
+  }
284 241
 
285
-  const float dist_start = HYPOT2(svec.x, svec.y),
286
-              dist_end = HYPOT2(evec.x, evec.y),
287
-              line_length = HYPOT(e.x - s.x, e.y - s.y);
242
+  /**
243
+   * print_line_from_here_to_there() takes two cartesian coordinates and draws a line from one
244
+   * to the other. But there are really three sets of coordinates involved. The first coordinate
245
+   * is the present location of the nozzle. We don't necessarily want to print from this location.
246
+   * We first need to move the nozzle to the start of line segment where we want to print. Once
247
+   * there, we can use the two coordinates supplied to draw the line.
248
+   *
249
+   * Note:  Although we assume the first set of coordinates is the start of the line and the second
250
+   * set of coordinates is the end of the line, it does not always work out that way. This function
251
+   * optimizes the movement to minimize the travel distance before it can start printing. This saves
252
+   * a lot of time and eliminates a lot of nonsensical movement of the nozzle. However, it does
253
+   * cause a lot of very little short retracement of th nozzle when it draws the very first line
254
+   * segment of a 'circle'. The time this requires is very short and is easily saved by the other
255
+   * cases where the optimization comes into play.
256
+   */
257
+  void print_line_from_here_to_there(const xyz_pos_t &s, const xyz_pos_t &e) {
288 258
 
289
-  // If the end point of the line is closer to the nozzle, flip the direction,
290
-  // moving from the end to the start. On very small lines the optimization isn't worth it.
291
-  if (dist_end < dist_start && (INTERSECTION_CIRCLE_RADIUS) < ABS(line_length))
292
-    return print_line_from_here_to_there(e, s);
259
+    // Distances to the start / end of the line
260
+    xy_float_t svec = current_position - s, evec = current_position - e;
293 261
 
294
-  // Decide whether to retract & lift
295
-  if (dist_start > 2.0) retract_lift_move(s);
262
+    const float dist_start = HYPOT2(svec.x, svec.y),
263
+                dist_end = HYPOT2(evec.x, evec.y),
264
+                line_length = HYPOT(e.x - s.x, e.y - s.y);
296 265
 
297
-  move_to(s, 0.0); // Get to the starting point with no extrusion / un-Z lift
266
+    // If the end point of the line is closer to the nozzle, flip the direction,
267
+    // moving from the end to the start. On very small lines the optimization isn't worth it.
268
+    if (dist_end < dist_start && (INTERSECTION_CIRCLE_RADIUS) < ABS(line_length))
269
+      return print_line_from_here_to_there(e, s);
298 270
 
299
-  const float e_pos_delta = line_length * g26_e_axis_feedrate * g26_extrusion_multiplier;
271
+    // Decide whether to retract & lift
272
+    if (dist_start > 2.0) retract_lift_move(s);
300 273
 
301
-  recover_filament(destination);
302
-  move_to(e, e_pos_delta);  // Get to the ending point with an appropriate amount of extrusion
303
-}
274
+    move_to(s, 0.0); // Get to the starting point with no extrusion / un-Z lift
304 275
 
305
-inline bool look_for_lines_to_connect() {
306
-  xyz_pos_t s, e;
307
-  s.z = e.z = g26_layer_height;
276
+    const float e_pos_delta = line_length * g26_e_axis_feedrate * extrusion_multiplier;
308 277
 
309
-  GRID_LOOP(i, j) {
278
+    recover_filament(destination);
279
+    move_to(e, e_pos_delta);  // Get to the ending point with an appropriate amount of extrusion
280
+  }
310 281
 
311
-    if (TERN0(HAS_LCD_MENU, user_canceled())) return true;
282
+  void connect_neighbor_with_line(const xy_int8_t &p1, int8_t dx, int8_t dy) {
283
+    xy_int8_t p2;
284
+    p2.x = p1.x + dx;
285
+    p2.y = p1.y + dy;
286
+
287
+    if (p2.x < 0 || p2.x >= (GRID_MAX_POINTS_X)) return;
288
+    if (p2.y < 0 || p2.y >= (GRID_MAX_POINTS_Y)) return;
289
+
290
+    if(circle_flags.marked(p1.x, p1.y) && circle_flags.marked(p2.x, p2.y)) {
291
+      xyz_pos_t s, e;
292
+      s.x = _GET_MESH_X(p1.x) + (INTERSECTION_CIRCLE_RADIUS - (CROSSHAIRS_SIZE)) * dx;
293
+      e.x = _GET_MESH_X(p2.x) - (INTERSECTION_CIRCLE_RADIUS - (CROSSHAIRS_SIZE)) * dx;
294
+      s.y = _GET_MESH_Y(p1.y) + (INTERSECTION_CIRCLE_RADIUS - (CROSSHAIRS_SIZE)) * dy;
295
+      e.y = _GET_MESH_Y(p2.y) - (INTERSECTION_CIRCLE_RADIUS - (CROSSHAIRS_SIZE)) * dy;
296
+      s.z = e.z = layer_height;
297
+
298
+      #if HAS_ENDSTOPS
299
+        LIMIT(s.y, Y_MIN_POS + 1, Y_MAX_POS - 1);
300
+        LIMIT(e.y, Y_MIN_POS + 1, Y_MAX_POS - 1);
301
+        LIMIT(s.x, X_MIN_POS + 1, X_MAX_POS - 1);
302
+        LIMIT(e.x, X_MIN_POS + 1, X_MAX_POS - 1);
303
+      #endif
304
+
305
+      if (position_is_reachable(s.x, s.y) && position_is_reachable(e.x, e.y))
306
+        print_line_from_here_to_there(s, e);
307
+    }
308
+  }
312 309
 
313
-    if (i < (GRID_MAX_POINTS_X)) {  // Can't connect to anything farther to the right than GRID_MAX_POINTS_X.
314
-                                    // Already a half circle at the edge of the bed.
310
+  /**
311
+   * Turn on the bed and nozzle heat and
312
+   * wait for them to get up to temperature.
313
+   */
314
+  bool turn_on_heaters() {
315 315
 
316
-      if (circle_flags.marked(i, j) && circle_flags.marked(i + 1, j)) {   // Test whether a leftward line can be done
317
-        if (!horizontal_mesh_line_flags.marked(i, j)) {
318
-          // Two circles need a horizontal line to connect them
319
-          s.x = _GET_MESH_X(  i  ) + (INTERSECTION_CIRCLE_RADIUS - (CROSSHAIRS_SIZE)); // right edge
320
-          e.x = _GET_MESH_X(i + 1) - (INTERSECTION_CIRCLE_RADIUS - (CROSSHAIRS_SIZE)); // left edge
316
+    SERIAL_ECHOLNPGM("Waiting for heatup.");
321 317
 
322
-          #if HAS_ENDSTOPS
323
-            LIMIT(s.x, X_MIN_POS + 1, X_MAX_POS - 1);
324
-            s.y = e.y = constrain(_GET_MESH_Y(j), Y_MIN_POS + 1, Y_MAX_POS - 1);
325
-            LIMIT(e.x, X_MIN_POS + 1, X_MAX_POS - 1);
326
-          #else
327
-            s.y = e.y = _GET_MESH_Y(j);
328
-          #endif
318
+    #if HAS_HEATED_BED
329 319
 
330
-          if (position_is_reachable(s.x, s.y) && position_is_reachable(e.x, e.y))
331
-            print_line_from_here_to_there(s, e);
320
+      if (bed_temp > 25) {
321
+        #if HAS_WIRED_LCD
322
+          ui.set_status_P(GET_TEXT(MSG_G26_HEATING_BED), 99);
323
+          ui.quick_feedback();
324
+          TERN_(HAS_LCD_MENU, ui.capture());
325
+        #endif
326
+        thermalManager.setTargetBed(bed_temp);
332 327
 
333
-          horizontal_mesh_line_flags.mark(i, j); // Mark done, even if skipped
334
-        }
328
+        // Wait for the temperature to stabilize
329
+        if (!thermalManager.wait_for_bed(true
330
+            #if G26_CLICK_CAN_CANCEL
331
+              , true
332
+            #endif
333
+          )
334
+        ) return G26_ERR;
335 335
       }
336 336
 
337
-      if (j < (GRID_MAX_POINTS_Y)) {  // Can't connect to anything further back than GRID_MAX_POINTS_Y.
338
-                                      // Already a half circle at the edge of the bed.
339
-
340
-        if (circle_flags.marked(i, j) && circle_flags.marked(i, j + 1)) {   // Test whether a downward line can be done
341
-          if (!vertical_mesh_line_flags.marked(i, j)) {
342
-            // Two circles that need a vertical line to connect them
343
-            s.y = _GET_MESH_Y(  j  ) + (INTERSECTION_CIRCLE_RADIUS - (CROSSHAIRS_SIZE)); // top edge
344
-            e.y = _GET_MESH_Y(j + 1) - (INTERSECTION_CIRCLE_RADIUS - (CROSSHAIRS_SIZE)); // bottom edge
345
-
346
-            #if HAS_ENDSTOPS
347
-              s.x = e.x = constrain(_GET_MESH_X(i), X_MIN_POS + 1, X_MAX_POS - 1);
348
-              LIMIT(s.y, Y_MIN_POS + 1, Y_MAX_POS - 1);
349
-              LIMIT(e.y, Y_MIN_POS + 1, Y_MAX_POS - 1);
350
-            #else
351
-              s.x = e.x = _GET_MESH_X(i);
352
-            #endif
337
+    #else
353 338
 
354
-            if (position_is_reachable(s.x, s.y) && position_is_reachable(e.x, e.y))
355
-              print_line_from_here_to_there(s, e);
339
+      UNUSED(bed_temp);
356 340
 
357
-            vertical_mesh_line_flags.mark(i, j); // Mark done, even if skipped
358
-          }
359
-        }
360
-      }
361
-    }
341
+    #endif // HAS_HEATED_BED
342
+
343
+    // Start heating the active nozzle
344
+    #if HAS_WIRED_LCD
345
+      ui.set_status_P(GET_TEXT(MSG_G26_HEATING_NOZZLE), 99);
346
+      ui.quick_feedback();
347
+    #endif
348
+    thermalManager.setTargetHotend(hotend_temp, active_extruder);
349
+
350
+    // Wait for the temperature to stabilize
351
+    if (!thermalManager.wait_for_hotend(active_extruder, true
352
+      #if G26_CLICK_CAN_CANCEL
353
+        , true
354
+      #endif
355
+    )) return G26_ERR;
356
+
357
+    #if HAS_WIRED_LCD
358
+      ui.reset_status();
359
+      ui.quick_feedback();
360
+    #endif
361
+
362
+    return G26_OK;
362 363
   }
363
-  return false;
364
-}
365 364
 
366
-/**
367
- * Turn on the bed and nozzle heat and
368
- * wait for them to get up to temperature.
369
- */
370
-inline bool turn_on_heaters() {
365
+  /**
366
+   * Prime the nozzle if needed. Return true on error.
367
+   */
368
+  bool prime_nozzle() {
371 369
 
372
-  SERIAL_ECHOLNPGM("Waiting for heatup.");
370
+    const feedRate_t fr_slow_e = planner.settings.max_feedrate_mm_s[E_AXIS] / 15.0f;
371
+    #if HAS_LCD_MENU && !HAS_TOUCH_BUTTONS // ui.button_pressed issue with touchscreen
372
+      #if ENABLED(PREVENT_LENGTHY_EXTRUDE)
373
+        float Total_Prime = 0.0;
374
+      #endif
373 375
 
374
-  #if HAS_HEATED_BED
376
+      if (prime_flag == -1) {  // The user wants to control how much filament gets purged
377
+        ui.capture();
378
+        ui.set_status_P(GET_TEXT(MSG_G26_MANUAL_PRIME), 99);
379
+        ui.chirp();
375 380
 
376
-    if (g26_bed_temp > 25) {
381
+        destination = current_position;
382
+
383
+        recover_filament(destination); // Make sure G26 doesn't think the filament is retracted().
384
+
385
+        while (!ui.button_pressed()) {
386
+          ui.chirp();
387
+          destination.e += 0.25;
388
+          #if ENABLED(PREVENT_LENGTHY_EXTRUDE)
389
+            Total_Prime += 0.25;
390
+            if (Total_Prime >= EXTRUDE_MAXLENGTH) {
391
+              ui.release();
392
+              return G26_ERR;
393
+            }
394
+          #endif
395
+          prepare_internal_move_to_destination(fr_slow_e);
396
+          destination = current_position;
397
+          planner.synchronize();    // Without this synchronize, the purge is more consistent,
398
+                                    // but because the planner has a buffer, we won't be able
399
+                                    // to stop as quickly. So we put up with the less smooth
400
+                                    // action to give the user a more responsive 'Stop'.
401
+        }
402
+
403
+        ui.wait_for_release();
404
+
405
+        ui.set_status_P(GET_TEXT(MSG_G26_PRIME_DONE), 99);
406
+        ui.quick_feedback();
407
+        ui.release();
408
+      }
409
+      else
410
+    #endif
411
+    {
377 412
       #if HAS_WIRED_LCD
378
-        ui.set_status_P(GET_TEXT(MSG_G26_HEATING_BED), 99);
413
+        ui.set_status_P(GET_TEXT(MSG_G26_FIXED_LENGTH), 99);
379 414
         ui.quick_feedback();
380
-        TERN_(HAS_LCD_MENU, ui.capture());
381 415
       #endif
382
-      thermalManager.setTargetBed(g26_bed_temp);
383
-
384
-      // Wait for the temperature to stabilize
385
-      if (!thermalManager.wait_for_bed(true
386
-          #if G26_CLICK_CAN_CANCEL
387
-            , true
388
-          #endif
389
-        )
390
-      ) return G26_ERR;
416
+      destination = current_position;
417
+      destination.e += prime_length;
418
+      prepare_internal_move_to_destination(fr_slow_e);
419
+      destination.e -= prime_length;
420
+      retract_filament(destination);
391 421
     }
392 422
 
393
-  #endif // HAS_HEATED_BED
423
+    return G26_OK;
424
+  }
394 425
 
395
-  // Start heating the active nozzle
396
-  #if HAS_WIRED_LCD
397
-    ui.set_status_P(GET_TEXT(MSG_G26_HEATING_NOZZLE), 99);
398
-    ui.quick_feedback();
399
-  #endif
400
-  thermalManager.setTargetHotend(g26_hotend_temp, active_extruder);
426
+  /**
427
+   * Find the nearest point at which to print a circle
428
+   */
429
+  mesh_index_pair find_closest_circle_to_print(const xy_pos_t &pos) {
401 430
 
402
-  // Wait for the temperature to stabilize
403
-  if (!thermalManager.wait_for_hotend(active_extruder, true
404
-    #if G26_CLICK_CAN_CANCEL
405
-      , true
406
-    #endif
407
-  )) return G26_ERR;
431
+    mesh_index_pair out_point;
432
+    out_point.pos = -1;
408 433
 
409
-  #if HAS_WIRED_LCD
410
-    ui.reset_status();
411
-    ui.quick_feedback();
412
-  #endif
434
+    #if ENABLED(UBL_HILBERT_CURVE)
413 435
 
414
-  return G26_OK;
415
-}
436
+      auto test_func = [](uint8_t i, uint8_t j, void *data) -> bool {
437
+        if (!circle_flags.marked(i, j)) {
438
+          mesh_index_pair *out_point = (mesh_index_pair*)data;
439
+          out_point->pos.set(i, j);  // Save its data
440
+          return true;
441
+        }
442
+        return false;
443
+      };
416 444
 
417
-/**
418
- * Prime the nozzle if needed. Return true on error.
419
- */
420
-inline bool prime_nozzle() {
445
+      hilbert_curve::search_from_closest(pos, test_func, &out_point);
421 446
 
422
-  const feedRate_t fr_slow_e = planner.settings.max_feedrate_mm_s[E_AXIS] / 15.0f;
423
-  #if HAS_LCD_MENU && !HAS_TOUCH_BUTTONS // ui.button_pressed issue with touchscreen
424
-    #if ENABLED(PREVENT_LENGTHY_EXTRUDE)
425
-      float Total_Prime = 0.0;
426
-    #endif
447
+    #else
427 448
 
428
-    if (g26_prime_flag == -1) {  // The user wants to control how much filament gets purged
429
-      ui.capture();
430
-      ui.set_status_P(GET_TEXT(MSG_G26_MANUAL_PRIME), 99);
431
-      ui.chirp();
449
+      float closest = 99999.99;
432 450
 
433
-      destination = current_position;
451
+      GRID_LOOP(i, j) {
452
+        if (!circle_flags.marked(i, j)) {
453
+          // We found a circle that needs to be printed
454
+          const xy_pos_t m = { _GET_MESH_X(i), _GET_MESH_Y(j) };
434 455
 
435
-      recover_filament(destination); // Make sure G26 doesn't think the filament is retracted().
456
+          // Get the distance to this intersection
457
+          float f = (pos - m).magnitude();
436 458
 
437
-      while (!ui.button_pressed()) {
438
-        ui.chirp();
439
-        destination.e += 0.25;
440
-        #if ENABLED(PREVENT_LENGTHY_EXTRUDE)
441
-          Total_Prime += 0.25;
442
-          if (Total_Prime >= EXTRUDE_MAXLENGTH) {
443
-            ui.release();
444
-            return G26_ERR;
459
+          // It is possible that we are being called with the values
460
+          // to let us find the closest circle to the start position.
461
+          // But if this is not the case, add a small weighting to the
462
+          // distance calculation to help it choose a better place to continue.
463
+          f += (xy_pos - m).magnitude() / 15.0f;
464
+
465
+          // Add the specified amount of Random Noise to our search
466
+          if (g26_random_deviation > 1.0) f += random(0.0, g26_random_deviation);
467
+
468
+          if (f < closest) {
469
+            closest = f;          // Found a closer un-printed location
470
+            out_point.pos.set(i, j);  // Save its data
471
+            out_point.distance = closest;
445 472
           }
446
-        #endif
447
-        prepare_internal_move_to_destination(fr_slow_e);
448
-        destination = current_position;
449
-        planner.synchronize();    // Without this synchronize, the purge is more consistent,
450
-                                  // but because the planner has a buffer, we won't be able
451
-                                  // to stop as quickly. So we put up with the less smooth
452
-                                  // action to give the user a more responsive 'Stop'.
473
+        }
453 474
       }
454 475
 
455
-      ui.wait_for_release();
456
-
457
-      ui.set_status_P(GET_TEXT(MSG_G26_PRIME_DONE), 99);
458
-      ui.quick_feedback();
459
-      ui.release();
460
-    }
461
-    else
462
-  #endif
463
-  {
464
-    #if HAS_WIRED_LCD
465
-      ui.set_status_P(GET_TEXT(MSG_G26_FIXED_LENGTH), 99);
466
-      ui.quick_feedback();
467 476
     #endif
468
-    destination = current_position;
469
-    destination.e += g26_prime_length;
470
-    prepare_internal_move_to_destination(fr_slow_e);
471
-    destination.e -= g26_prime_length;
472
-    retract_filament(destination);
477
+
478
+    circle_flags.mark(out_point); // Mark this location as done.
479
+    return out_point;
473 480
   }
474 481
 
475
-  return G26_OK;
476
-}
482
+} g26_helper_t;
477 483
 
478 484
 /**
479 485
  * G26: Mesh Validation Pattern generation.
@@ -510,20 +516,11 @@ void GcodeSuite::G26() {
510 516
   // Change the tool first, if specified
511 517
   if (parser.seenval('T')) tool_change(parser.value_int());
512 518
 
513
-  g26_extrusion_multiplier    = EXTRUSION_MULTIPLIER;
514
-  g26_retraction_multiplier   = G26_RETRACT_MULTIPLIER;
515
-  g26_layer_height            = MESH_TEST_LAYER_HEIGHT;
516
-  g26_prime_length            = PRIME_LENGTH;
517
-  g26_bed_temp                = MESH_TEST_BED_TEMP;
518
-  g26_hotend_temp             = MESH_TEST_HOTEND_TEMP;
519
-  g26_prime_flag              = 0;
520
-
521
-  float g26_nozzle            = MESH_TEST_NOZZLE_SIZE,
522
-        g26_filament_diameter = DEFAULT_NOMINAL_FILAMENT_DIA,
523
-        g26_ooze_amount       = parser.linearval('O', OOZE_AMOUNT);
519
+  g26_helper_t g26;
524 520
 
525
-  bool g26_continue_with_closest = parser.boolval('C'),
526
-       g26_keep_heaters_on       = parser.boolval('K');
521
+  g26.ooze_amount           = parser.linearval('O', OOZE_AMOUNT);
522
+  g26.continue_with_closest = parser.boolval('C');
523
+  g26.keep_heaters_on       = parser.boolval('K');
527 524
 
528 525
   // Accept 'I' if temperature presets are defined
529 526
   #if PREHEAT_COUNT
@@ -548,14 +545,14 @@ void GcodeSuite::G26() {
548 545
         SERIAL_ECHOLNPAIR("?Specified bed temperature not plausible (40-", BED_MAX_TARGET, "C).");
549 546
         return;
550 547
       }
551
-      g26_bed_temp = bedtemp;
548
+      g26.bed_temp = bedtemp;
552 549
     }
553 550
 
554 551
   #endif // HAS_HEATED_BED
555 552
 
556 553
   if (parser.seenval('L')) {
557
-    g26_layer_height = parser.value_linear_units();
558
-    if (!WITHIN(g26_layer_height, 0.0, 2.0)) {
554
+    g26.layer_height = parser.value_linear_units();
555
+    if (!WITHIN(g26.layer_height, 0.0, 2.0)) {
559 556
       SERIAL_ECHOLNPGM("?Specified layer height not plausible.");
560 557
       return;
561 558
     }
@@ -563,8 +560,8 @@ void GcodeSuite::G26() {
563 560
 
564 561
   if (parser.seen('Q')) {
565 562
     if (parser.has_value()) {
566
-      g26_retraction_multiplier = parser.value_float();
567
-      if (!WITHIN(g26_retraction_multiplier, 0.05, 15.0)) {
563
+      g26.retraction_multiplier = parser.value_float();
564
+      if (!WITHIN(g26.retraction_multiplier, 0.05, 15.0)) {
568 565
         SERIAL_ECHOLNPGM("?Specified Retraction Multiplier not plausible.");
569 566
         return;
570 567
       }
@@ -576,8 +573,8 @@ void GcodeSuite::G26() {
576 573
   }
577 574
 
578 575
   if (parser.seenval('S')) {
579
-    g26_nozzle = parser.value_float();
580
-    if (!WITHIN(g26_nozzle, 0.1, 2.0)) {
576
+    g26.nozzle = parser.value_float();
577
+    if (!WITHIN(g26.nozzle, 0.1, 2.0)) {
581 578
       SERIAL_ECHOLNPGM("?Specified nozzle size not plausible.");
582 579
       return;
583 580
     }
@@ -586,16 +583,16 @@ void GcodeSuite::G26() {
586 583
   if (parser.seen('P')) {
587 584
     if (!parser.has_value()) {
588 585
       #if HAS_LCD_MENU
589
-        g26_prime_flag = -1;
586
+        g26.prime_flag = -1;
590 587
       #else
591 588
         SERIAL_ECHOLNPGM("?Prime length must be specified when not using an LCD.");
592 589
         return;
593 590
       #endif
594 591
     }
595 592
     else {
596
-      g26_prime_flag++;
597
-      g26_prime_length = parser.value_linear_units();
598
-      if (!WITHIN(g26_prime_length, 0.0, 25.0)) {
593
+      g26.prime_flag++;
594
+      g26.prime_length = parser.value_linear_units();
595
+      if (!WITHIN(g26.prime_length, 0.0, 25.0)) {
599 596
         SERIAL_ECHOLNPGM("?Specified prime length not plausible.");
600 597
         return;
601 598
       }
@@ -603,17 +600,17 @@ void GcodeSuite::G26() {
603 600
   }
604 601
 
605 602
   if (parser.seenval('F')) {
606
-    g26_filament_diameter = parser.value_linear_units();
607
-    if (!WITHIN(g26_filament_diameter, 1.0, 4.0)) {
603
+    g26.filament_diameter = parser.value_linear_units();
604
+    if (!WITHIN(g26.filament_diameter, 1.0, 4.0)) {
608 605
       SERIAL_ECHOLNPGM("?Specified filament size not plausible.");
609 606
       return;
610 607
     }
611 608
   }
612
-  g26_extrusion_multiplier *= sq(1.75) / sq(g26_filament_diameter); // If we aren't using 1.75mm filament, we need to
609
+  g26.extrusion_multiplier *= sq(1.75) / sq(g26.filament_diameter); // If we aren't using 1.75mm filament, we need to
613 610
                                                                     // scale up or down the length needed to get the
614 611
                                                                     // same volume of filament
615 612
 
616
-  g26_extrusion_multiplier *= g26_filament_diameter * sq(g26_nozzle) / sq(0.3); // Scale up by nozzle size
613
+  g26.extrusion_multiplier *= g26.filament_diameter * sq(g26.nozzle) / sq(0.3); // Scale up by nozzle size
617 614
 
618 615
   // Get a temperature from 'I' or 'H'
619 616
   celsius_t noztemp = 0;
@@ -632,7 +629,7 @@ void GcodeSuite::G26() {
632 629
       SERIAL_ECHOLNPGM("?Specified nozzle temperature not plausible.");
633 630
       return;
634 631
     }
635
-    g26_hotend_temp = noztemp;
632
+    g26.hotend_temp = noztemp;
636 633
   }
637 634
 
638 635
   // 'U' to Randomize and optionally set circle deviation
@@ -660,9 +657,9 @@ void GcodeSuite::G26() {
660 657
   }
661 658
 
662 659
   // Set a position with 'X' and/or 'Y'. Default: current_position
663
-  g26_xy_pos.set(parser.seenval('X') ? RAW_X_POSITION(parser.value_linear_units()) : current_position.x,
660
+  g26.xy_pos.set(parser.seenval('X') ? RAW_X_POSITION(parser.value_linear_units()) : current_position.x,
664 661
                  parser.seenval('Y') ? RAW_Y_POSITION(parser.value_linear_units()) : current_position.y);
665
-  if (!position_is_reachable(g26_xy_pos)) {
662
+  if (!position_is_reachable(g26.xy_pos)) {
666 663
     SERIAL_ECHOLNPGM("?Specified X,Y coordinate out of bounds.");
667 664
     return;
668 665
   }
@@ -680,12 +677,12 @@ void GcodeSuite::G26() {
680 677
     planner.calculate_volumetric_multipliers();
681 678
   #endif
682 679
 
683
-  if (turn_on_heaters() != G26_OK) goto LEAVE;
680
+  if (g26.turn_on_heaters() != G26_OK) goto LEAVE;
684 681
 
685 682
   current_position.e = 0.0;
686 683
   sync_plan_position_e();
687 684
 
688
-  if (g26_prime_flag && prime_nozzle() != G26_OK) goto LEAVE;
685
+  if (g26.prime_flag && g26.prime_nozzle() != G26_OK) goto LEAVE;
689 686
 
690 687
   /**
691 688
    *  Bed is preheated
@@ -698,14 +695,12 @@ void GcodeSuite::G26() {
698 695
    */
699 696
 
700 697
   circle_flags.reset();
701
-  horizontal_mesh_line_flags.reset();
702
-  vertical_mesh_line_flags.reset();
703 698
 
704 699
   // Move nozzle to the specified height for the first layer
705 700
   destination = current_position;
706
-  destination.z = g26_layer_height;
701
+  destination.z = g26.layer_height;
707 702
   move_to(destination, 0.0);
708
-  move_to(destination, g26_ooze_amount);
703
+  move_to(destination, g26.ooze_amount);
709 704
 
710 705
   TERN_(HAS_LCD_MENU, ui.capture());
711 706
 
@@ -732,7 +727,7 @@ void GcodeSuite::G26() {
732 727
   mesh_index_pair location;
733 728
   do {
734 729
     // Find the nearest confluence
735
-    location = find_closest_circle_to_print(g26_continue_with_closest ? xy_pos_t(current_position) : g26_xy_pos);
730
+    location = g26.find_closest_circle_to_print(g26.continue_with_closest ? xy_pos_t(current_position) : g26.xy_pos);
736 731
 
737 732
     if (location.valid()) {
738 733
       const xy_pos_t circle = _GET_MESH_POS(location.pos);
@@ -762,7 +757,7 @@ void GcodeSuite::G26() {
762 757
           if (!b) { e.x = circle.x; e.y += INTERSECTION_CIRCLE_RADIUS; }
763 758
           arc_length = (f || b) ? ARC_LENGTH(1) : ARC_LENGTH(2);
764 759
         }
765
-        else if (r) {                             // right edge
760
+        else if (r) {                               // right edge
766 761
           if (b) s.set(circle.x - (INTERSECTION_CIRCLE_RADIUS), circle.y);
767 762
           else   s.set(circle.x, circle.y + INTERSECTION_CIRCLE_RADIUS);
768 763
           if (f) e.set(circle.x - (INTERSECTION_CIRCLE_RADIUS), circle.y);
@@ -782,25 +777,24 @@ void GcodeSuite::G26() {
782 777
         const xy_float_t dist = current_position - s;   // Distance from the start of the actual circle
783 778
         const float dist_start = HYPOT2(dist.x, dist.y);
784 779
         const xyze_pos_t endpoint = {
785
-          e.x, e.y, g26_layer_height,
786
-          current_position.e + (arc_length * g26_e_axis_feedrate * g26_extrusion_multiplier)
780
+          e.x, e.y, g26.layer_height,
781
+          current_position.e + (arc_length * g26_e_axis_feedrate * g26.extrusion_multiplier)
787 782
         };
788 783
 
789 784
         if (dist_start > 2.0) {
790
-          s.z = g26_layer_height + 0.5f;
791
-          retract_lift_move(s);
785
+          s.z = g26.layer_height + 0.5f;
786
+          g26.retract_lift_move(s);
792 787
         }
793 788
 
794
-        s.z = g26_layer_height;
789
+        s.z = g26.layer_height;
795 790
         move_to(s, 0.0);  // Get to the starting point with no extrusion / un-Z lift
796 791
 
797
-        recover_filament(destination);
792
+        g26.recover_filament(destination);
798 793
 
799
-        const feedRate_t old_feedrate = feedrate_mm_s;
800
-        feedrate_mm_s = PLANNER_XY_FEEDRATE() * 0.1f;
801
-        plan_arc(endpoint, arc_offset, false, 0);  // Draw a counter-clockwise arc
802
-        feedrate_mm_s = old_feedrate;
803
-        destination = current_position;
794
+        { REMEMBER(fr, feedrate_mm_s, PLANNER_XY_FEEDRATE() * 0.1f);
795
+          plan_arc(endpoint, arc_offset, false, 0);  // Draw a counter-clockwise arc
796
+          destination = current_position;
797
+        }
804 798
 
805 799
         if (TERN0(HAS_LCD_MENU, user_canceled())) goto LEAVE; // Check if the user wants to stop the Mesh Validation
806 800
 
@@ -828,8 +822,8 @@ void GcodeSuite::G26() {
828 822
 
829 823
           if (TERN0(HAS_LCD_MENU, user_canceled())) goto LEAVE; // Check if the user wants to stop the Mesh Validation
830 824
 
831
-          xyz_float_t p = { circle.x + _COS(ind    ), circle.y + _SIN(ind    ), g26_layer_height },
832
-                      q = { circle.x + _COS(ind + 1), circle.y + _SIN(ind + 1), g26_layer_height };
825
+          xyz_float_t p = { circle.x + _COS(ind    ), circle.y + _SIN(ind    ), g26.layer_height },
826
+                      q = { circle.x + _COS(ind + 1), circle.y + _SIN(ind + 1), g26.layer_height };
833 827
 
834 828
           #if IS_KINEMATIC
835 829
             // Check to make sure this segment is entirely on the bed, skip if not.
@@ -841,13 +835,17 @@ void GcodeSuite::G26() {
841 835
             LIMIT(q.y, Y_MIN_POS + 1, Y_MAX_POS - 1);
842 836
           #endif
843 837
 
844
-          print_line_from_here_to_there(p, q);
838
+          g26.print_line_from_here_to_there(p, q);
845 839
           SERIAL_FLUSH();   // Prevent host M105 buffer overrun.
846 840
         }
847 841
 
848 842
       #endif // !ARC_SUPPORT
849 843
 
850
-      if (look_for_lines_to_connect()) goto LEAVE;
844
+      g26.connect_neighbor_with_line(location.pos, -1,  0);
845
+      g26.connect_neighbor_with_line(location.pos,  1,  0);
846
+      g26.connect_neighbor_with_line(location.pos,  0, -1);
847
+      g26.connect_neighbor_with_line(location.pos,  0,  1);
848
+      if (TERN0(HAS_LCD_MENU, user_canceled())) goto LEAVE;
851 849
     }
852 850
 
853 851
     SERIAL_FLUSH(); // Prevent host M105 buffer overrun.
@@ -857,12 +855,9 @@ void GcodeSuite::G26() {
857 855
   LEAVE:
858 856
   ui.set_status_P(GET_TEXT(MSG_G26_LEAVING), -1);
859 857
 
860
-  retract_filament(destination);
858
+  g26.retract_filament(destination);
861 859
   destination.z = Z_CLEARANCE_BETWEEN_PROBES;
862
-  move_to(destination, 0);                                    // Raise the nozzle
863
-
864
-  destination = g26_xy_pos;                                   // Move back to the starting XY position
865
-  move_to(destination, 0);                                    // Move back to the starting position
860
+  move_to(destination, 0);                                   // Raise the nozzle
866 861
 
867 862
   #if DISABLED(NO_VOLUMETRICS)
868 863
     parser.volumetric_enabled = volumetric_was_enabled;
@@ -871,7 +866,7 @@ void GcodeSuite::G26() {
871 866
 
872 867
   TERN_(HAS_LCD_MENU, ui.release()); // Give back control of the LCD
873 868
 
874
-  if (!g26_keep_heaters_on) {
869
+  if (!g26.keep_heaters_on) {
875 870
     TERN_(HAS_HEATED_BED, thermalManager.setTargetBed(0));
876 871
     thermalManager.setTargetHotend(active_extruder, 0);
877 872
   }

+ 2
- 2
Marlin/src/gcode/bedlevel/M420.cpp Näytä tiedosto

@@ -68,8 +68,8 @@ void GcodeSuite::M420() {
68 68
                   y_min = probe.min_y(), y_max = probe.max_y();
69 69
       #if ENABLED(AUTO_BED_LEVELING_BILINEAR)
70 70
         bilinear_start.set(x_min, y_min);
71
-        bilinear_grid_spacing.set((x_max - x_min) / (GRID_MAX_POINTS_X - 1),
72
-                                  (y_max - y_min) / (GRID_MAX_POINTS_Y - 1));
71
+        bilinear_grid_spacing.set((x_max - x_min) / (GRID_MAX_CELLS_X),
72
+                                  (y_max - y_min) / (GRID_MAX_CELLS_Y));
73 73
       #endif
74 74
       GRID_LOOP(x, y) {
75 75
         Z_VALUES(x, y) = 0.001 * random(-200, 200);

+ 3
- 3
Marlin/src/gcode/bedlevel/abl/G29.cpp Näytä tiedosto

@@ -295,10 +295,10 @@ G29_TYPE GcodeSuite::G29() {
295 295
           // Get nearest i / j from rx / ry
296 296
           i = (rx - bilinear_start.x + 0.5 * abl.gridSpacing.x) / abl.gridSpacing.x;
297 297
           j = (ry - bilinear_start.y + 0.5 * abl.gridSpacing.y) / abl.gridSpacing.y;
298
-          LIMIT(i, 0, GRID_MAX_POINTS_X - 1);
299
-          LIMIT(j, 0, GRID_MAX_POINTS_Y - 1);
298
+          LIMIT(i, 0, (GRID_MAX_POINTS_X) - 1);
299
+          LIMIT(j, 0, (GRID_MAX_POINTS_Y) - 1);
300 300
         }
301
-        if (WITHIN(i, 0, GRID_MAX_POINTS_X - 1) && WITHIN(j, 0, GRID_MAX_POINTS_Y)) {
301
+        if (WITHIN(i, 0, (GRID_MAX_POINTS_X) - 1) && WITHIN(j, 0, (GRID_MAX_POINTS_Y) - 1)) {
302 302
           set_bed_leveling_enabled(false);
303 303
           z_values[i][j] = rz;
304 304
           TERN_(ABL_BILINEAR_SUBDIVISION, bed_level_virt_interpolate());

+ 5
- 5
Marlin/src/gcode/bedlevel/mbl/G29.cpp Näytä tiedosto

@@ -106,7 +106,7 @@ void GcodeSuite::G29() {
106 106
         SET_SOFT_ENDSTOP_LOOSE(false);
107 107
       }
108 108
       // If there's another point to sample, move there with optional lift.
109
-      if (mbl_probe_index < GRID_MAX_POINTS) {
109
+      if (mbl_probe_index < (GRID_MAX_POINTS)) {
110 110
         // Disable software endstops to allow manual adjustment
111 111
         // If G29 is left hanging without completion they won't be re-enabled!
112 112
         SET_SOFT_ENDSTOP_LOOSE(true);
@@ -142,8 +142,8 @@ void GcodeSuite::G29() {
142 142
     case MeshSet:
143 143
       if (parser.seenval('I')) {
144 144
         ix = parser.value_int();
145
-        if (!WITHIN(ix, 0, GRID_MAX_POINTS_X - 1)) {
146
-          SERIAL_ECHOLNPAIR("I out of range (0-", GRID_MAX_POINTS_X - 1, ")");
145
+        if (!WITHIN(ix, 0, (GRID_MAX_POINTS_X) - 1)) {
146
+          SERIAL_ECHOLNPAIR("I out of range (0-", (GRID_MAX_POINTS_X) - 1, ")");
147 147
           return;
148 148
         }
149 149
       }
@@ -152,8 +152,8 @@ void GcodeSuite::G29() {
152 152
 
153 153
       if (parser.seenval('J')) {
154 154
         iy = parser.value_int();
155
-        if (!WITHIN(iy, 0, GRID_MAX_POINTS_Y - 1)) {
156
-          SERIAL_ECHOLNPAIR("J out of range (0-", GRID_MAX_POINTS_Y - 1, ")");
155
+        if (!WITHIN(iy, 0, (GRID_MAX_POINTS_Y) - 1)) {
156
+          SERIAL_ECHOLNPAIR("J out of range (0-", (GRID_MAX_POINTS_Y) - 1, ")");
157 157
           return;
158 158
         }
159 159
       }

+ 5
- 0
Marlin/src/inc/Conditionals_post.h Näytä tiedosto

@@ -224,6 +224,11 @@
224 224
   #endif
225 225
 #endif
226 226
 
227
+#ifdef GRID_MAX_POINTS_X
228
+  #define GRID_MAX_CELLS_X (GRID_MAX_POINTS_X - 1)
229
+  #define GRID_MAX_CELLS_Y (GRID_MAX_POINTS_Y - 1)
230
+#endif
231
+
227 232
 /**
228 233
  * Host keep alive
229 234
  */

+ 3
- 3
Marlin/src/inc/SanityCheck.h Näytä tiedosto

@@ -1263,9 +1263,9 @@ static_assert(Y_MAX_LENGTH >= Y_BED_SIZE, "Movement bounds (Y_MIN_POS, Y_MAX_POS
1263 1263
   #elif ENABLED(DELTA_CALIBRATION_MENU) && !HAS_LCD_MENU
1264 1264
     #error "DELTA_CALIBRATION_MENU requires an LCD Controller."
1265 1265
   #elif ABL_USES_GRID
1266
-    #if (GRID_MAX_POINTS_X & 1) == 0 || (GRID_MAX_POINTS_Y & 1) == 0
1266
+    #if ((GRID_MAX_POINTS_X) & 1) == 0 || ((GRID_MAX_POINTS_Y) & 1) == 0
1267 1267
       #error "DELTA requires GRID_MAX_POINTS_X and GRID_MAX_POINTS_Y to be odd numbers."
1268
-    #elif GRID_MAX_POINTS_X < 3
1268
+    #elif (GRID_MAX_POINTS_X) < 3
1269 1269
       #error "DELTA requires GRID_MAX_POINTS_X and GRID_MAX_POINTS_Y to be 3 or higher."
1270 1270
     #endif
1271 1271
   #endif
@@ -1518,7 +1518,7 @@ static_assert(Y_MAX_LENGTH >= Y_BED_SIZE, "Movement bounds (Y_MIN_POS, Y_MAX_POS
1518 1518
   // Mesh Bed Leveling
1519 1519
   #if ENABLED(DELTA)
1520 1520
     #error "MESH_BED_LEVELING is not compatible with DELTA printers."
1521
-  #elif GRID_MAX_POINTS_X > 9 || GRID_MAX_POINTS_Y > 9
1521
+  #elif (GRID_MAX_POINTS_X) > 9 || (GRID_MAX_POINTS_Y) > 9
1522 1522
     #error "GRID_MAX_POINTS_X and GRID_MAX_POINTS_Y must be less than 10 for MBL."
1523 1523
   #endif
1524 1524
 

+ 1
- 1
Marlin/src/lcd/HD44780/marlinui_HD44780.cpp Näytä tiedosto

@@ -1279,7 +1279,7 @@ void MarlinUI::draw_status_screen() {
1279 1279
                    pixels_per_x_mesh_pnt, pixels_per_y_mesh_pnt,
1280 1280
                    suppress_x_offset = 0, suppress_y_offset = 0;
1281 1281
 
1282
-        const uint8_t y_plot_inv = (GRID_MAX_POINTS_Y - 1) - y_plot;
1282
+        const uint8_t y_plot_inv = (GRID_MAX_POINTS_Y) - 1 - y_plot;
1283 1283
 
1284 1284
         upper_left.column  = 0;
1285 1285
         upper_left.row     = 0;

+ 1
- 1
Marlin/src/lcd/dogm/marlinui_DOGM.cpp Näytä tiedosto

@@ -529,7 +529,7 @@ void MarlinUI::clear_lcd() { } // Automatically cleared by Picture Loop
529 529
 
530 530
       // Fill in the Specified Mesh Point
531 531
 
532
-      const uint8_t y_plot_inv = (GRID_MAX_POINTS_Y - 1) - y_plot;  // The origin is typically in the lower right corner.  We need to
532
+      const uint8_t y_plot_inv = (GRID_MAX_POINTS_Y) - 1 - y_plot;  // The origin is typically in the lower right corner.  We need to
533 533
                                                                     // invert the Y to get it to plot in the right location.
534 534
 
535 535
       const u8g_uint_t by = y_offset + y_plot_inv * pixels_per_y_mesh_pnt;

+ 5
- 5
Marlin/src/lcd/extui/lib/ftdi_eve_touch_ui/screens/bed_mesh_screen.cpp Näytä tiedosto

@@ -53,12 +53,12 @@ constexpr static float gaugeThickness = 0.25;
53 53
 #endif
54 54
 
55 55
 void BedMeshScreen::drawMesh(int16_t x, int16_t y, int16_t w, int16_t h, ExtUI::bed_mesh_t data, uint8_t opts, float autoscale_max) {
56
-  constexpr uint8_t rows       = GRID_MAX_POINTS_Y;
57
-  constexpr uint8_t cols       = GRID_MAX_POINTS_X;
56
+  constexpr uint8_t rows = GRID_MAX_POINTS_Y;
57
+  constexpr uint8_t cols = GRID_MAX_POINTS_X;
58 58
 
59
-  #define VALUE(X,Y)         (data ? data[X][Y] : 0)
60
-  #define ISVAL(X,Y)         (data ? !isnan(VALUE(X,Y)) : true)
61
-  #define HEIGHT(X,Y)        (ISVAL(X,Y) ? (VALUE(X,Y) - val_min) * scale_z : 0)
59
+  #define VALUE(X,Y)  (data ? data[X][Y] : 0)
60
+  #define ISVAL(X,Y)  (data ? !isnan(VALUE(X,Y)) : true)
61
+  #define HEIGHT(X,Y) (ISVAL(X,Y) ? (VALUE(X,Y) - val_min) * scale_z : 0)
62 62
 
63 63
   // Compute the mean, min and max for the points
64 64
 

+ 1
- 1
Marlin/src/lcd/extui/ui_api.cpp Näytä tiedosto

@@ -859,7 +859,7 @@ namespace ExtUI {
859 859
       bed_mesh_t& getMeshArray() { return Z_VALUES_ARR; }
860 860
       float getMeshPoint(const xy_uint8_t &pos) { return Z_VALUES(pos.x, pos.y); }
861 861
       void setMeshPoint(const xy_uint8_t &pos, const_float_t zoff) {
862
-        if (WITHIN(pos.x, 0, GRID_MAX_POINTS_X) && WITHIN(pos.y, 0, GRID_MAX_POINTS_Y)) {
862
+        if (WITHIN(pos.x, 0, (GRID_MAX_POINTS_X) - 1) && WITHIN(pos.y, 0, (GRID_MAX_POINTS_Y) - 1)) {
863 863
           Z_VALUES(pos.x, pos.y) = zoff;
864 864
           TERN_(ABL_BILINEAR_SUBDIVISION, bed_level_virt_interpolate());
865 865
         }

+ 2
- 2
Marlin/src/lcd/menu/menu_bed_leveling.cpp Näytä tiedosto

@@ -214,8 +214,8 @@
214 214
     static uint8_t xind, yind; // =0
215 215
     START_MENU();
216 216
     BACK_ITEM(MSG_BED_LEVELING);
217
-    EDIT_ITEM(uint8, MSG_MESH_X, &xind, 0, GRID_MAX_POINTS_X - 1);
218
-    EDIT_ITEM(uint8, MSG_MESH_Y, &yind, 0, GRID_MAX_POINTS_Y - 1);
217
+    EDIT_ITEM(uint8, MSG_MESH_X, &xind, 0, (GRID_MAX_POINTS_X) - 1);
218
+    EDIT_ITEM(uint8, MSG_MESH_Y, &yind, 0, (GRID_MAX_POINTS_Y) - 1);
219 219
     EDIT_ITEM_FAST(float43, MSG_MESH_EDIT_Z, &Z_VALUES(xind, yind), -(LCD_PROBE_Z_RANGE) * 0.5, (LCD_PROBE_Z_RANGE) * 0.5, refresh_planner);
220 220
     END_MENU();
221 221
   }

+ 2
- 2
Marlin/src/lcd/menu/menu_ubl.cpp Näytä tiedosto

@@ -484,8 +484,8 @@ void ubl_map_screen() {
484 484
     #if IS_KINEMATIC
485 485
       n_edit_pts = 9; // TODO: Delta accessible edit points
486 486
     #else
487
-      const bool xc = WITHIN(x, 1, GRID_MAX_POINTS_X - 2),
488
-                 yc = WITHIN(y, 1, GRID_MAX_POINTS_Y - 2);
487
+      const bool xc = WITHIN(x, 1, (GRID_MAX_POINTS_X) - 2),
488
+                 yc = WITHIN(y, 1, (GRID_MAX_POINTS_Y) - 2);
489 489
       n_edit_pts = yc ? (xc ? 9 : 6) : (xc ? 6 : 4); // Corners
490 490
     #endif
491 491
 

+ 7
- 7
Marlin/src/lcd/tft/ui_320x240.cpp Näytä tiedosto

@@ -462,12 +462,12 @@ void MenuItem_confirm::draw_select_screen(PGM_P const yes, PGM_P const no, const
462 462
     tft.set_background(COLOR_BACKGROUND);
463 463
     tft.add_rectangle(0, 0, GRID_WIDTH, GRID_HEIGHT, COLOR_WHITE);
464 464
 
465
-    for (uint16_t x = 0; x < GRID_MAX_POINTS_X ; x++)
466
-      for (uint16_t y = 0; y < GRID_MAX_POINTS_Y ; y++)
465
+    for (uint16_t x = 0; x < (GRID_MAX_POINTS_X); x++)
466
+      for (uint16_t y = 0; y < (GRID_MAX_POINTS_Y); y++)
467 467
         if (position_is_reachable({ ubl.mesh_index_to_xpos(x), ubl.mesh_index_to_ypos(y) }))
468
-          tft.add_bar(1 + (x * 2 + 1) * (GRID_WIDTH - 4) / GRID_MAX_POINTS_X / 2, GRID_HEIGHT - 3 - ((y * 2 + 1) * (GRID_HEIGHT - 4) / GRID_MAX_POINTS_Y / 2), 2, 2, COLOR_UBL);
468
+          tft.add_bar(1 + (x * 2 + 1) * (GRID_WIDTH - 4) / (GRID_MAX_POINTS_X) / 2, GRID_HEIGHT - 3 - ((y * 2 + 1) * (GRID_HEIGHT - 4) / (GRID_MAX_POINTS_Y) / 2), 2, 2, COLOR_UBL);
469 469
 
470
-    tft.add_rectangle((x_plot * 2 + 1) * (GRID_WIDTH - 4) / GRID_MAX_POINTS_X / 2 - 1, GRID_HEIGHT - 5 - ((y_plot * 2 + 1) * (GRID_HEIGHT - 4) / GRID_MAX_POINTS_Y / 2), 6, 6, COLOR_UBL);
470
+    tft.add_rectangle((x_plot * 2 + 1) * (GRID_WIDTH - 4) / (GRID_MAX_POINTS_X) / 2 - 1, GRID_HEIGHT - 5 - ((y_plot * 2 + 1) * (GRID_HEIGHT - 4) / (GRID_MAX_POINTS_Y) / 2), 6, 6, COLOR_UBL);
471 471
 
472 472
     const xy_pos_t pos = { ubl.mesh_index_to_xpos(x_plot), ubl.mesh_index_to_ypos(y_plot) },
473 473
                    lpos = pos.asLogical();
@@ -512,9 +512,9 @@ void MenuItem_confirm::draw_select_screen(PGM_P const yes, PGM_P const no, const
512 512
     #if ENABLED(TOUCH_SCREEN)
513 513
       touch.clear();
514 514
       draw_menu_navigation = false;
515
-      add_control(GRID_OFFSET_X + GRID_WIDTH + CONTROL_OFFSET,      GRID_OFFSET_Y + CONTROL_OFFSET,                    UBL,   ENCODER_STEPS_PER_MENU_ITEM * GRID_MAX_POINTS_X, imgUp);
516
-      add_control(GRID_OFFSET_X + GRID_WIDTH + CONTROL_OFFSET,      GRID_OFFSET_Y + GRID_HEIGHT - CONTROL_OFFSET - 32, UBL, - ENCODER_STEPS_PER_MENU_ITEM * GRID_MAX_POINTS_X, imgDown);
517
-      add_control(GRID_OFFSET_X + CONTROL_OFFSET,                   GRID_OFFSET_Y + GRID_HEIGHT + CONTROL_OFFSET,      UBL, - ENCODER_STEPS_PER_MENU_ITEM, imgLeft);
515
+      add_control(GRID_OFFSET_X + GRID_WIDTH + CONTROL_OFFSET,      GRID_OFFSET_Y + CONTROL_OFFSET,                    UBL,  (ENCODER_STEPS_PER_MENU_ITEM) * (GRID_MAX_POINTS_X), imgUp);
516
+      add_control(GRID_OFFSET_X + GRID_WIDTH + CONTROL_OFFSET,      GRID_OFFSET_Y + GRID_HEIGHT - CONTROL_OFFSET - 32, UBL, -(ENCODER_STEPS_PER_MENU_ITEM) * (GRID_MAX_POINTS_X), imgDown);
517
+      add_control(GRID_OFFSET_X + CONTROL_OFFSET,                   GRID_OFFSET_Y + GRID_HEIGHT + CONTROL_OFFSET,      UBL, -(ENCODER_STEPS_PER_MENU_ITEM), imgLeft);
518 518
       add_control(GRID_OFFSET_X + GRID_WIDTH - CONTROL_OFFSET - 32, GRID_OFFSET_Y + GRID_HEIGHT + CONTROL_OFFSET,      UBL,   ENCODER_STEPS_PER_MENU_ITEM, imgRight);
519 519
       add_control(224, GRID_OFFSET_Y + GRID_HEIGHT + CONTROL_OFFSET, CLICK, imgLeveling);
520 520
       add_control(144, 206, BACK, imgBack);

+ 7
- 7
Marlin/src/lcd/tft/ui_480x320.cpp Näytä tiedosto

@@ -462,12 +462,12 @@ void MenuItem_confirm::draw_select_screen(PGM_P const yes, PGM_P const no, const
462 462
     tft.set_background(COLOR_BACKGROUND);
463 463
     tft.add_rectangle(0, 0, GRID_WIDTH, GRID_HEIGHT, COLOR_WHITE);
464 464
 
465
-    for (uint16_t x = 0; x < GRID_MAX_POINTS_X ; x++)
466
-      for (uint16_t y = 0; y < GRID_MAX_POINTS_Y ; y++)
465
+    for (uint16_t x = 0; x < (GRID_MAX_POINTS_X); x++)
466
+      for (uint16_t y = 0; y < (GRID_MAX_POINTS_Y); y++)
467 467
         if (position_is_reachable({ ubl.mesh_index_to_xpos(x), ubl.mesh_index_to_ypos(y) }))
468
-          tft.add_bar(1 + (x * 2 + 1) * (GRID_WIDTH - 4) / GRID_MAX_POINTS_X / 2, GRID_HEIGHT - 3 - ((y * 2 + 1) * (GRID_HEIGHT - 4) / GRID_MAX_POINTS_Y / 2), 2, 2, COLOR_UBL);
468
+          tft.add_bar(1 + (x * 2 + 1) * (GRID_WIDTH - 4) / (GRID_MAX_POINTS_X) / 2, GRID_HEIGHT - 3 - ((y * 2 + 1) * (GRID_HEIGHT - 4) / (GRID_MAX_POINTS_Y) / 2), 2, 2, COLOR_UBL);
469 469
 
470
-    tft.add_rectangle((x_plot * 2 + 1) * (GRID_WIDTH - 4) / GRID_MAX_POINTS_X / 2 - 1, GRID_HEIGHT - 5 - ((y_plot * 2 + 1) * (GRID_HEIGHT - 4) / GRID_MAX_POINTS_Y / 2), 6, 6, COLOR_UBL);
470
+    tft.add_rectangle((x_plot * 2 + 1) * (GRID_WIDTH - 4) / (GRID_MAX_POINTS_X) / 2 - 1, GRID_HEIGHT - 5 - ((y_plot * 2 + 1) * (GRID_HEIGHT - 4) / (GRID_MAX_POINTS_Y) / 2), 6, 6, COLOR_UBL);
471 471
 
472 472
     const xy_pos_t pos = { ubl.mesh_index_to_xpos(x_plot), ubl.mesh_index_to_ypos(y_plot) },
473 473
                    lpos = pos.asLogical();
@@ -512,9 +512,9 @@ void MenuItem_confirm::draw_select_screen(PGM_P const yes, PGM_P const no, const
512 512
     #if ENABLED(TOUCH_SCREEN)
513 513
       touch.clear();
514 514
       draw_menu_navigation = false;
515
-      add_control(GRID_OFFSET_X + GRID_WIDTH + CONTROL_OFFSET,      GRID_OFFSET_Y + CONTROL_OFFSET,                    UBL,   ENCODER_STEPS_PER_MENU_ITEM * GRID_MAX_POINTS_X, imgUp);
516
-      add_control(GRID_OFFSET_X + GRID_WIDTH + CONTROL_OFFSET,      GRID_OFFSET_Y + GRID_HEIGHT - CONTROL_OFFSET - 32, UBL, - ENCODER_STEPS_PER_MENU_ITEM * GRID_MAX_POINTS_X, imgDown);
517
-      add_control(GRID_OFFSET_X + CONTROL_OFFSET,                   GRID_OFFSET_Y + GRID_HEIGHT + CONTROL_OFFSET,      UBL, - ENCODER_STEPS_PER_MENU_ITEM, imgLeft);
515
+      add_control(GRID_OFFSET_X + GRID_WIDTH + CONTROL_OFFSET,      GRID_OFFSET_Y + CONTROL_OFFSET,                    UBL,  (ENCODER_STEPS_PER_MENU_ITEM) * (GRID_MAX_POINTS_X), imgUp);
516
+      add_control(GRID_OFFSET_X + GRID_WIDTH + CONTROL_OFFSET,      GRID_OFFSET_Y + GRID_HEIGHT - CONTROL_OFFSET - 32, UBL, -(ENCODER_STEPS_PER_MENU_ITEM) * (GRID_MAX_POINTS_X), imgDown);
517
+      add_control(GRID_OFFSET_X + CONTROL_OFFSET,                   GRID_OFFSET_Y + GRID_HEIGHT + CONTROL_OFFSET,      UBL, -(ENCODER_STEPS_PER_MENU_ITEM), imgLeft);
518 518
       add_control(GRID_OFFSET_X + GRID_WIDTH - CONTROL_OFFSET - 32, GRID_OFFSET_Y + GRID_HEIGHT + CONTROL_OFFSET,      UBL,   ENCODER_STEPS_PER_MENU_ITEM, imgRight);
519 519
       add_control(320, GRID_OFFSET_Y + GRID_HEIGHT + CONTROL_OFFSET, CLICK, imgLeveling);
520 520
       add_control(224, TFT_HEIGHT - 34, BACK, imgBack);

+ 2
- 2
Marlin/src/module/settings.cpp Näytä tiedosto

@@ -1605,7 +1605,7 @@ void MarlinSettings::postprocess() {
1605 1605
 
1606 1606
         #if ENABLED(MESH_BED_LEVELING)
1607 1607
           if (!validating) mbl.z_offset = dummyf;
1608
-          if (mesh_num_x == GRID_MAX_POINTS_X && mesh_num_y == GRID_MAX_POINTS_Y) {
1608
+          if (mesh_num_x == (GRID_MAX_POINTS_X) && mesh_num_y == (GRID_MAX_POINTS_Y)) {
1609 1609
             // EEPROM data fits the current mesh
1610 1610
             EEPROM_READ(mbl.z_values);
1611 1611
           }
@@ -1652,7 +1652,7 @@ void MarlinSettings::postprocess() {
1652 1652
         EEPROM_READ_ALWAYS(grid_max_x);                // 1 byte
1653 1653
         EEPROM_READ_ALWAYS(grid_max_y);                // 1 byte
1654 1654
         #if ENABLED(AUTO_BED_LEVELING_BILINEAR)
1655
-          if (grid_max_x == GRID_MAX_POINTS_X && grid_max_y == GRID_MAX_POINTS_Y) {
1655
+          if (grid_max_x == (GRID_MAX_POINTS_X) && grid_max_y == (GRID_MAX_POINTS_Y)) {
1656 1656
             if (!validating) set_bed_leveling_enabled(false);
1657 1657
             EEPROM_READ(bilinear_grid_spacing);        // 2 ints
1658 1658
             EEPROM_READ(bilinear_start);               // 2 ints

Loading…
Peruuta
Tallenna