Browse Source

More data in UBL class, make it a static class

- Make all `unified_bed_leveling` data/methods static
- Move some UBL-related variables into the class
- Replace `map_[xy]_index_to_bed_location` with `mesh_index_to_[xy]pos`
Scott Lahteine 8 years ago
parent
commit
4902fd4e95

+ 10
- 10
Marlin/G26_Mesh_Validation_Tool.cpp View File

@@ -265,8 +265,8 @@
265 265
         location = find_closest_circle_to_print(x_pos, y_pos); // Find the closest Mesh Intersection to where we are now.
266 266
 
267 267
       if (location.x_index >= 0 && location.y_index >= 0) {
268
-        circle_x = ubl.map_x_index_to_bed_location(location.x_index);
269
-        circle_y = ubl.map_y_index_to_bed_location(location.y_index);
268
+        circle_x = ubl.mesh_index_to_xpos[location.x_index];
269
+        circle_y = ubl.mesh_index_to_ypos[location.y_index];
270 270
 
271 271
         // Let's do a couple of quick sanity checks.  We can pull this code out later if we never see it catch a problem
272 272
         #ifdef DELTA
@@ -415,8 +415,8 @@
415 415
     for (uint8_t i = 0; i < UBL_MESH_NUM_X_POINTS; i++) {
416 416
       for (uint8_t j = 0; j < UBL_MESH_NUM_Y_POINTS; j++) {
417 417
         if (!is_bit_set(circle_flags, i, j)) {
418
-          mx = ubl.map_x_index_to_bed_location(i);  // We found a circle that needs to be printed
419
-          my = ubl.map_y_index_to_bed_location(j);
418
+          mx = ubl.mesh_index_to_xpos[i];  // We found a circle that needs to be printed
419
+          my = ubl.mesh_index_to_ypos[j];
420 420
 
421 421
           dx = X - mx;        // Get the distance to this intersection
422 422
           dy = Y - my;
@@ -461,11 +461,11 @@
461 461
               // We found two circles that need a horizontal line to connect them
462 462
               // Print it!
463 463
               //
464
-              sx = ubl.map_x_index_to_bed_location(i);
464
+              sx = ubl.mesh_index_to_xpos[i];
465 465
               sx = sx + SIZE_OF_INTERSECTION_CIRCLES - SIZE_OF_CROSS_HAIRS; // get the right edge of the circle
466
-              sy = ubl.map_y_index_to_bed_location(j);
466
+              sy = ubl.mesh_index_to_ypos[j];
467 467
 
468
-              ex = ubl.map_x_index_to_bed_location(i + 1);
468
+              ex = ubl.mesh_index_to_xpos[i + 1];
469 469
               ex = ex - SIZE_OF_INTERSECTION_CIRCLES + SIZE_OF_CROSS_HAIRS; // get the left edge of the circle
470 470
               ey = sy;
471 471
 
@@ -498,12 +498,12 @@
498 498
                 // We found two circles that need a vertical line to connect them
499 499
                 // Print it!
500 500
                 //
501
-                sx = ubl.map_x_index_to_bed_location(i);
502
-                sy = ubl.map_y_index_to_bed_location(j);
501
+                sx = ubl.mesh_index_to_xpos[i];
502
+                sy = ubl.mesh_index_to_ypos[j];
503 503
                 sy = sy + SIZE_OF_INTERSECTION_CIRCLES - SIZE_OF_CROSS_HAIRS; // get the top edge of the circle
504 504
 
505 505
                 ex = sx;
506
-                ey = ubl.map_y_index_to_bed_location(j + 1);
506
+                ey = ubl.mesh_index_to_ypos[j + 1];
507 507
                 ey = ey - SIZE_OF_INTERSECTION_CIRCLES + SIZE_OF_CROSS_HAIRS; // get the bottom edge of the circle
508 508
 
509 509
                 sx = constrain(sx, X_MIN_POS + 1, X_MAX_POS - 1);             // This keeps us from bumping the endstops

+ 4
- 0
Marlin/Marlin.h View File

@@ -430,4 +430,8 @@ void do_blocking_move_to_x(const float &x, const float &fr_mm_s=0.0);
430 430
 void do_blocking_move_to_z(const float &z, const float &fr_mm_s=0.0);
431 431
 void do_blocking_move_to_xy(const float &x, const float &y, const float &fr_mm_s=0.0);
432 432
 
433
+#if ENABLED(Z_PROBE_ALLEN_KEY) || ENABLED(Z_PROBE_SLED) || HAS_PROBING_PROCEDURE || HOTENDS > 1 || ENABLED(NOZZLE_CLEAN_FEATURE) || ENABLED(NOZZLE_PARK_FEATURE)
434
+  bool axis_unhomed_error(const bool x, const bool y, const bool z);
435
+#endif
436
+
433 437
 #endif //MARLIN_H

+ 1
- 1
Marlin/Marlin_main.cpp View File

@@ -3221,7 +3221,7 @@ inline void gcode_G4() {
3221 3221
    */
3222 3222
   inline void gcode_G12() {
3223 3223
     // Don't allow nozzle cleaning without homing first
3224
-    if (axis_unhomed_error(true, true, true)) { return; }
3224
+    if (axis_unhomed_error(true, true, true)) return;
3225 3225
 
3226 3226
     const uint8_t pattern = code_seen('P') ? code_value_ushort() : 0,
3227 3227
                   strokes = code_seen('S') ? code_value_ushort() : NOZZLE_CLEAN_STROKES,

+ 228
- 232
Marlin/UBL.h View File

@@ -39,7 +39,6 @@
39 39
 
40 40
     enum MeshPointType { INVALID, REAL, SET_IN_BITMAP };
41 41
 
42
-    bool axis_unhomed_error(bool, bool, bool);
43 42
     void dump(char * const str, const float &f);
44 43
     bool ubl_lcd_clicked();
45 44
     void probe_entire_mesh(const float&, const float&, const bool, const bool, const bool);
@@ -78,275 +77,273 @@
78 77
 
79 78
     enum MBLStatus { MBL_STATUS_NONE = 0, MBL_STATUS_HAS_MESH_BIT = 0, MBL_STATUS_ACTIVE_BIT = 1 };
80 79
 
81
-    #define MESH_X_DIST ((float(UBL_MESH_MAX_X) - float(UBL_MESH_MIN_X)) / (float(UBL_MESH_NUM_X_POINTS) - 1.0))
82
-    #define MESH_Y_DIST ((float(UBL_MESH_MAX_Y) - float(UBL_MESH_MIN_Y)) / (float(UBL_MESH_NUM_Y_POINTS) - 1.0))
80
+    #define MESH_X_DIST (float(UBL_MESH_MAX_X - (UBL_MESH_MIN_X)) / float(UBL_MESH_NUM_X_POINTS - 1))
81
+    #define MESH_Y_DIST (float(UBL_MESH_MAX_Y - (UBL_MESH_MIN_Y)) / float(UBL_MESH_NUM_Y_POINTS - 1))
83 82
 
84
-    extern float mesh_index_to_x_location[UBL_MESH_NUM_X_POINTS + 1]; // +1 just because of paranoia that we might end up on the
85
-    extern float mesh_index_to_y_location[UBL_MESH_NUM_Y_POINTS + 1]; // the last Mesh Line and that is the start of a whole new cell
83
+    typedef struct {
84
+      bool active = false;
85
+      float z_offset = 0.0;
86
+      int8_t eeprom_storage_slot = -1,
87
+             n_x = UBL_MESH_NUM_X_POINTS,
88
+             n_y = UBL_MESH_NUM_Y_POINTS;
89
+
90
+      float mesh_x_min = UBL_MESH_MIN_X,
91
+            mesh_y_min = UBL_MESH_MIN_Y,
92
+            mesh_x_max = UBL_MESH_MAX_X,
93
+            mesh_y_max = UBL_MESH_MAX_Y,
94
+            mesh_x_dist = MESH_X_DIST,
95
+            mesh_y_dist = MESH_Y_DIST;
96
+
97
+      #if ENABLED(ENABLE_LEVELING_FADE_HEIGHT)
98
+        float g29_correction_fade_height = 10.0,
99
+              g29_fade_height_multiplier = 1.0 / 10.0; // It's cheaper to do a floating point multiply than divide,
100
+                                                       // so keep this value and its reciprocal.
101
+      #else
102
+        const float g29_correction_fade_height = 10.0,
103
+                    g29_fade_height_multiplier = 1.0 / 10.0;
104
+      #endif
105
+
106
+      // If you change this struct, adjust TOTAL_STRUCT_SIZE
107
+
108
+      #define TOTAL_STRUCT_SIZE 40 // Total size of the above fields
109
+
110
+      // padding provides space to add state variables without
111
+      // changing the location of data structures in the EEPROM.
112
+      // This is for compatibility with future versions to keep
113
+      // users from having to regenerate their mesh data.
114
+      unsigned char padding[64 - TOTAL_STRUCT_SIZE];
115
+
116
+    } ubl_state;
86 117
 
87 118
     class unified_bed_leveling {
88 119
       private:
89 120
 
90
-      float last_specified_z,
91
-            fade_scaling_factor_for_current_height;
121
+        static float last_specified_z,
122
+                     fade_scaling_factor_for_current_height;
92 123
 
93 124
       public:
94 125
 
95
-      float z_values[UBL_MESH_NUM_X_POINTS][UBL_MESH_NUM_Y_POINTS];
126
+        static ubl_state state, pre_initialized;
96 127
 
97
-      bool g26_debug_flag = false,
98
-           has_control_of_lcd_panel = false;
128
+        static float z_values[UBL_MESH_NUM_X_POINTS][UBL_MESH_NUM_Y_POINTS],
129
+                     mesh_index_to_xpos[UBL_MESH_NUM_X_POINTS + 1], // +1 safety margin for now, until determinism prevails
130
+                     mesh_index_to_ypos[UBL_MESH_NUM_Y_POINTS + 1];
99 131
 
100
-      int8_t eeprom_start = -1;
132
+        static bool g26_debug_flag,
133
+                    has_control_of_lcd_panel;
101 134
 
102
-      volatile int encoder_diff; // Volatile because it's changed at interrupt time.
135
+        static int8_t eeprom_start;
103 136
 
104
-      struct ubl_state {
105
-        bool active = false;
106
-        float z_offset = 0.0;
107
-        int8_t eeprom_storage_slot = -1,
108
-               n_x = UBL_MESH_NUM_X_POINTS,
109
-               n_y = UBL_MESH_NUM_Y_POINTS;
137
+        static volatile int encoder_diff; // Volatile because it's changed at interrupt time.
110 138
 
111
-        float mesh_x_min = UBL_MESH_MIN_X,
112
-              mesh_y_min = UBL_MESH_MIN_Y,
113
-              mesh_x_max = UBL_MESH_MAX_X,
114
-              mesh_y_max = UBL_MESH_MAX_Y,
115
-              mesh_x_dist = MESH_X_DIST,
116
-              mesh_y_dist = MESH_Y_DIST;
139
+        unified_bed_leveling();
117 140
 
118
-        #if ENABLED(ENABLE_LEVELING_FADE_HEIGHT)
119
-          float g29_correction_fade_height = 10.0,
120
-                g29_fade_height_multiplier = 1.0 / 10.0; // It's cheaper to do a floating point multiply than divide,
121
-                                                         // so keep this value and its reciprocal.
122
-        #else
123
-          const float g29_correction_fade_height = 10.0,
124
-                      g29_fade_height_multiplier = 1.0 / 10.0;
125
-        #endif
141
+        static void display_map(const int);
126 142
 
127
-        // If you change this struct, adjust TOTAL_STRUCT_SIZE
128
-
129
-        #define TOTAL_STRUCT_SIZE 43 // Total size of the above fields
130
-
131
-        // padding provides space to add state variables without
132
-        // changing the location of data structures in the EEPROM.
133
-        // This is for compatibility with future versions to keep
134
-        // users from having to regenerate their mesh data.
135
-        unsigned char padding[64 - TOTAL_STRUCT_SIZE];
136
-
137
-      } state, pre_initialized;
138
-
139
-      unified_bed_leveling();
140
-
141
-      void display_map(const int);
142
-
143
-      void reset();
144
-      void invalidate();
145
-
146
-      void store_state();
147
-      void load_state();
148
-      void store_mesh(const int16_t);
149
-      void load_mesh(const int16_t);
150
-
151
-      bool sanity_check();
152
-
153
-      FORCE_INLINE static float map_x_index_to_bed_location(const int8_t i) { return ((float) UBL_MESH_MIN_X) + (((float) MESH_X_DIST) * (float) i); };
154
-      FORCE_INLINE static float map_y_index_to_bed_location(const int8_t i) { return ((float) UBL_MESH_MIN_Y) + (((float) MESH_Y_DIST) * (float) i); };
155
-
156
-      FORCE_INLINE void set_z(const int8_t px, const int8_t py, const float &z) { z_values[px][py] = z; }
157
-
158
-      static int8_t get_cell_index_x(const float &x) {
159
-        const int8_t cx = (x - (UBL_MESH_MIN_X)) * (1.0 / (MESH_X_DIST));
160
-        return constrain(cx, 0, (UBL_MESH_NUM_X_POINTS) - 1);   // -1 is appropriate if we want all movement to the X_MAX
161
-      }                                                         // position. But with this defined this way, it is possible
162
-                                                                // to extrapolate off of this point even further out. Probably
163
-                                                                // that is OK because something else should be keeping that from
164
-                                                                // happening and should not be worried about at this level.
165
-      static int8_t get_cell_index_y(const float &y) {
166
-        const int8_t cy = (y - (UBL_MESH_MIN_Y)) * (1.0 / (MESH_Y_DIST));
167
-        return constrain(cy, 0, (UBL_MESH_NUM_Y_POINTS) - 1);   // -1 is appropriate if we want all movement to the Y_MAX
168
-      }                                                         // position. But with this defined this way, it is possible
169
-                                                                // to extrapolate off of this point even further out. Probably
170
-                                                                // that is OK because something else should be keeping that from
171
-                                                                // happening and should not be worried about at this level.
172
-
173
-      static int8_t find_closest_x_index(const float &x) {
174
-        const int8_t px = (x - (UBL_MESH_MIN_X) + (MESH_X_DIST) * 0.5) * (1.0 / (MESH_X_DIST));
175
-        return (px >= 0 && px < (UBL_MESH_NUM_X_POINTS)) ? px : -1;
176
-      }
177
-
178
-      static int8_t find_closest_y_index(const float &y) {
179
-        const int8_t py = (y - (UBL_MESH_MIN_Y) + (MESH_Y_DIST) * 0.5) * (1.0 / (MESH_Y_DIST));
180
-        return (py >= 0 && py < (UBL_MESH_NUM_Y_POINTS)) ? py : -1;
181
-      }
182
-
183
-      /**
184
-       *                           z2   --|
185
-       *                 z0        |      |
186
-       *                  |        |      + (z2-z1)
187
-       *   z1             |        |      |
188
-       * ---+-------------+--------+--  --|
189
-       *   a1            a0        a2
190
-       *    |<---delta_a---------->|
191
-       *
192
-       *  calc_z0 is the basis for all the Mesh Based correction. It is used to
193
-       *  find the expected Z Height at a position between two known Z-Height locations.
194
-       *
195
-       *  It is fairly expensive with its 4 floating point additions and 2 floating point
196
-       *  multiplications.
197
-       */
198
-      static FORCE_INLINE float calc_z0(const float &a0, const float &a1, const float &z1, const float &a2, const float &z2) {
199
-        const float delta_z = (z2 - z1),
200
-                    delta_a = (a0 - a1) / (a2 - a1);
201
-        return z1 + delta_a * delta_z;
202
-      }
203
-
204
-      /**
205
-       * get_z_correction_at_Y_intercept(float x0, int x1_i, int yi) only takes
206
-       * three parameters. It assumes the x0 point is on a Mesh line denoted by yi. In theory
207
-       * we could use get_cell_index_x(float x) to obtain the 2nd parameter x1_i but any code calling
208
-       * the get_z_correction_along_vertical_mesh_line_at_specific_X routine  will already have
209
-       * the X index of the x0 intersection available and we don't want to perform any extra floating
210
-       * point operations.
211
-       */
212
-      inline float get_z_correction_along_horizontal_mesh_line_at_specific_X(const float &x0, const int x1_i, const int yi) {
213
-        if (x1_i < 0 || yi < 0 || x1_i >= UBL_MESH_NUM_X_POINTS || yi >= UBL_MESH_NUM_Y_POINTS) {
214
-          SERIAL_ECHOPAIR("? in get_z_correction_along_horizontal_mesh_line_at_specific_X(x0=", x0);
215
-          SERIAL_ECHOPAIR(",x1_i=", x1_i);
216
-          SERIAL_ECHOPAIR(",yi=", yi);
217
-          SERIAL_CHAR(')');
218
-          SERIAL_EOL;
219
-          return NAN;
143
+        static void reset();
144
+        static void invalidate();
145
+
146
+        static void store_state();
147
+        static void load_state();
148
+        static void store_mesh(const int16_t);
149
+        static void load_mesh(const int16_t);
150
+
151
+        static bool sanity_check();
152
+
153
+        static FORCE_INLINE void set_z(const int8_t px, const int8_t py, const float &z) { z_values[px][py] = z; }
154
+
155
+        static int8_t get_cell_index_x(const float &x) {
156
+          const int8_t cx = (x - (UBL_MESH_MIN_X)) * (1.0 / (MESH_X_DIST));
157
+          return constrain(cx, 0, (UBL_MESH_NUM_X_POINTS) - 1);   // -1 is appropriate if we want all movement to the X_MAX
158
+        }                                                         // position. But with this defined this way, it is possible
159
+                                                                  // to extrapolate off of this point even further out. Probably
160
+                                                                  // that is OK because something else should be keeping that from
161
+                                                                  // happening and should not be worried about at this level.
162
+        static int8_t get_cell_index_y(const float &y) {
163
+          const int8_t cy = (y - (UBL_MESH_MIN_Y)) * (1.0 / (MESH_Y_DIST));
164
+          return constrain(cy, 0, (UBL_MESH_NUM_Y_POINTS) - 1);   // -1 is appropriate if we want all movement to the Y_MAX
165
+        }                                                         // position. But with this defined this way, it is possible
166
+                                                                  // to extrapolate off of this point even further out. Probably
167
+                                                                  // that is OK because something else should be keeping that from
168
+                                                                  // happening and should not be worried about at this level.
169
+
170
+        static int8_t find_closest_x_index(const float &x) {
171
+          const int8_t px = (x - (UBL_MESH_MIN_X) + (MESH_X_DIST) * 0.5) * (1.0 / (MESH_X_DIST));
172
+          return (px >= 0 && px < (UBL_MESH_NUM_X_POINTS)) ? px : -1;
220 173
         }
221 174
 
222
-        const float xratio = (RAW_X_POSITION(x0) - mesh_index_to_x_location[x1_i]) * (1.0 / (MESH_X_DIST)),
223
-                    z1 = z_values[x1_i][yi],
224
-                    z2 = z_values[x1_i + 1][yi],
225
-                    dz = (z2 - z1);
226
-
227
-        return z1 + xratio * dz;
228
-      }
229
-
230
-      //
231
-      // See comments above for get_z_correction_along_horizontal_mesh_line_at_specific_X
232
-      //
233
-      inline float get_z_correction_along_vertical_mesh_line_at_specific_Y(const float &y0, const int xi, const int y1_i) {
234
-        if (xi < 0 || y1_i < 0 || xi >= UBL_MESH_NUM_X_POINTS || y1_i >= UBL_MESH_NUM_Y_POINTS) {
235
-          SERIAL_ECHOPAIR("? in get_z_correction_along_vertical_mesh_line_at_specific_X(y0=", y0);
236
-          SERIAL_ECHOPAIR(", x1_i=", xi);
237
-          SERIAL_ECHOPAIR(", yi=", y1_i);
238
-          SERIAL_CHAR(')');
239
-          SERIAL_EOL;
240
-          return NAN;
175
+        static int8_t find_closest_y_index(const float &y) {
176
+          const int8_t py = (y - (UBL_MESH_MIN_Y) + (MESH_Y_DIST) * 0.5) * (1.0 / (MESH_Y_DIST));
177
+          return (py >= 0 && py < (UBL_MESH_NUM_Y_POINTS)) ? py : -1;
241 178
         }
242 179
 
243
-        const float yratio = (RAW_Y_POSITION(y0) - mesh_index_to_y_location[y1_i]) * (1.0 / (MESH_Y_DIST)),
244
-                    z1 = z_values[xi][y1_i],
245
-                    z2 = z_values[xi][y1_i + 1],
246
-                    dz = (z2 - z1);
247
-
248
-        return z1 + yratio * dz;
249
-      }
250
-
251
-      /**
252
-       * This is the generic Z-Correction. It works anywhere within a Mesh Cell. It first
253
-       * does a linear interpolation along both of the bounding X-Mesh-Lines to find the
254
-       * Z-Height at both ends. Then it does a linear interpolation of these heights based
255
-       * on the Y position within the cell.
256
-       */
257
-      float get_z_correction(const float &x0, const float &y0) const {
258
-        const int8_t cx = get_cell_index_x(RAW_X_POSITION(x0)),
259
-                     cy = get_cell_index_y(RAW_Y_POSITION(y0));
260
-
261
-        if (cx < 0 || cy < 0 || cx >= UBL_MESH_NUM_X_POINTS || cy >= UBL_MESH_NUM_Y_POINTS) {
262
-
263
-          SERIAL_ECHOPAIR("? in get_z_correction(x0=", x0);
264
-          SERIAL_ECHOPAIR(", y0=", y0);
265
-          SERIAL_CHAR(')');
266
-          SERIAL_EOL;
267
-
268
-          #if ENABLED(ULTRA_LCD)
269
-            strcpy(lcd_status_message, "get_z_correction() indexes out of range.");
270
-            lcd_quick_feedback();
271
-          #endif
272
-          return 0.0; // this used to return state.z_offset
180
+        /**
181
+         *                           z2   --|
182
+         *                 z0        |      |
183
+         *                  |        |      + (z2-z1)
184
+         *   z1             |        |      |
185
+         * ---+-------------+--------+--  --|
186
+         *   a1            a0        a2
187
+         *    |<---delta_a---------->|
188
+         *
189
+         *  calc_z0 is the basis for all the Mesh Based correction. It is used to
190
+         *  find the expected Z Height at a position between two known Z-Height locations.
191
+         *
192
+         *  It is fairly expensive with its 4 floating point additions and 2 floating point
193
+         *  multiplications.
194
+         */
195
+        static FORCE_INLINE float calc_z0(const float &a0, const float &a1, const float &z1, const float &a2, const float &z2) {
196
+          const float delta_z = (z2 - z1),
197
+                      delta_a = (a0 - a1) / (a2 - a1);
198
+          return z1 + delta_a * delta_z;
273 199
         }
274 200
 
275
-        const float z1 = calc_z0(RAW_X_POSITION(x0),
276
-                      map_x_index_to_bed_location(cx), z_values[cx][cy],
277
-                      map_x_index_to_bed_location(cx + 1), z_values[cx + 1][cy]),
278
-                    z2 = calc_z0(RAW_X_POSITION(x0),
279
-                      map_x_index_to_bed_location(cx), z_values[cx][cy + 1],
280
-                      map_x_index_to_bed_location(cx + 1), z_values[cx + 1][cy + 1]);
281
-              float z0 = calc_z0(RAW_Y_POSITION(y0),
282
-                  map_y_index_to_bed_location(cy), z1,
283
-                  map_y_index_to_bed_location(cy + 1), z2);
284
-
285
-        #if ENABLED(DEBUG_LEVELING_FEATURE)
286
-          if (DEBUGGING(MESH_ADJUST)) {
287
-            SERIAL_ECHOPAIR(" raw get_z_correction(", x0);
288
-            SERIAL_CHAR(',')
289
-            SERIAL_ECHO(y0);
290
-            SERIAL_ECHOPGM(") = ");
291
-            SERIAL_ECHO_F(z0, 6);
201
+        /**
202
+         * get_z_correction_at_Y_intercept(float x0, int x1_i, int yi) only takes
203
+         * three parameters. It assumes the x0 point is on a Mesh line denoted by yi. In theory
204
+         * we could use get_cell_index_x(float x) to obtain the 2nd parameter x1_i but any code calling
205
+         * the get_z_correction_along_vertical_mesh_line_at_specific_X routine  will already have
206
+         * the X index of the x0 intersection available and we don't want to perform any extra floating
207
+         * point operations.
208
+         */
209
+        static inline float get_z_correction_along_horizontal_mesh_line_at_specific_X(const float &x0, const int x1_i, const int yi) {
210
+          if (x1_i < 0 || yi < 0 || x1_i >= UBL_MESH_NUM_X_POINTS || yi >= UBL_MESH_NUM_Y_POINTS) {
211
+            SERIAL_ECHOPAIR("? in get_z_correction_along_horizontal_mesh_line_at_specific_X(x0=", x0);
212
+            SERIAL_ECHOPAIR(",x1_i=", x1_i);
213
+            SERIAL_ECHOPAIR(",yi=", yi);
214
+            SERIAL_CHAR(')');
215
+            SERIAL_EOL;
216
+            return NAN;
292 217
           }
293
-        #endif
294 218
 
295
-        #if ENABLED(DEBUG_LEVELING_FEATURE)
296
-          if (DEBUGGING(MESH_ADJUST)) {
297
-            SERIAL_ECHOPGM(" >>>---> ");
298
-            SERIAL_ECHO_F(z0, 6);
219
+          const float xratio = (RAW_X_POSITION(x0) - mesh_index_to_xpos[x1_i]) * (1.0 / (MESH_X_DIST)),
220
+                      z1 = z_values[x1_i][yi],
221
+                      z2 = z_values[x1_i + 1][yi],
222
+                      dz = (z2 - z1);
223
+
224
+          return z1 + xratio * dz;
225
+        }
226
+
227
+        //
228
+        // See comments above for get_z_correction_along_horizontal_mesh_line_at_specific_X
229
+        //
230
+        static inline float get_z_correction_along_vertical_mesh_line_at_specific_Y(const float &y0, const int xi, const int y1_i) {
231
+          if (xi < 0 || y1_i < 0 || xi >= UBL_MESH_NUM_X_POINTS || y1_i >= UBL_MESH_NUM_Y_POINTS) {
232
+            SERIAL_ECHOPAIR("? in get_z_correction_along_vertical_mesh_line_at_specific_X(y0=", y0);
233
+            SERIAL_ECHOPAIR(", x1_i=", xi);
234
+            SERIAL_ECHOPAIR(", yi=", y1_i);
235
+            SERIAL_CHAR(')');
299 236
             SERIAL_EOL;
237
+            return NAN;
300 238
           }
301
-        #endif
302 239
 
303
-        if (isnan(z0)) { // if part of the Mesh is undefined, it will show up as NAN
304
-          z0 = 0.0;      // in ubl.z_values[][] and propagate through the
305
-                         // calculations. If our correction is NAN, we throw it out
306
-                         // because part of the Mesh is undefined and we don't have the
307
-                         // information we need to complete the height correction.
240
+          const float yratio = (RAW_Y_POSITION(y0) - mesh_index_to_ypos[y1_i]) * (1.0 / (MESH_Y_DIST)),
241
+                      z1 = z_values[xi][y1_i],
242
+                      z2 = z_values[xi][y1_i + 1],
243
+                      dz = (z2 - z1);
244
+
245
+          return z1 + yratio * dz;
246
+        }
247
+
248
+        /**
249
+         * This is the generic Z-Correction. It works anywhere within a Mesh Cell. It first
250
+         * does a linear interpolation along both of the bounding X-Mesh-Lines to find the
251
+         * Z-Height at both ends. Then it does a linear interpolation of these heights based
252
+         * on the Y position within the cell.
253
+         */
254
+        static float get_z_correction(const float &x0, const float &y0) {
255
+          const int8_t cx = get_cell_index_x(RAW_X_POSITION(x0)),
256
+                       cy = get_cell_index_y(RAW_Y_POSITION(y0));
257
+
258
+          if (cx < 0 || cy < 0 || cx >= UBL_MESH_NUM_X_POINTS || cy >= UBL_MESH_NUM_Y_POINTS) {
259
+
260
+            SERIAL_ECHOPAIR("? in get_z_correction(x0=", x0);
261
+            SERIAL_ECHOPAIR(", y0=", y0);
262
+            SERIAL_CHAR(')');
263
+            SERIAL_EOL;
264
+
265
+            #if ENABLED(ULTRA_LCD)
266
+              strcpy(lcd_status_message, "get_z_correction() indexes out of range.");
267
+              lcd_quick_feedback();
268
+            #endif
269
+            return 0.0; // this used to return state.z_offset
270
+          }
271
+
272
+          const float z1 = calc_z0(RAW_X_POSITION(x0),
273
+                        mesh_index_to_xpos[cx], z_values[cx][cy],
274
+                        mesh_index_to_xpos[cx + 1], z_values[cx + 1][cy]),
275
+                      z2 = calc_z0(RAW_X_POSITION(x0),
276
+                        mesh_index_to_xpos[cx], z_values[cx][cy + 1],
277
+                        mesh_index_to_xpos[cx + 1], z_values[cx + 1][cy + 1]);
278
+                float z0 = calc_z0(RAW_Y_POSITION(y0),
279
+                    mesh_index_to_ypos[cy], z1,
280
+                    mesh_index_to_ypos[cy + 1], z2);
308 281
 
309 282
           #if ENABLED(DEBUG_LEVELING_FEATURE)
310 283
             if (DEBUGGING(MESH_ADJUST)) {
311
-              SERIAL_ECHOPAIR("??? Yikes!  NAN in get_z_correction(", x0);
312
-              SERIAL_CHAR(',');
284
+              SERIAL_ECHOPAIR(" raw get_z_correction(", x0);
285
+              SERIAL_CHAR(',')
313 286
               SERIAL_ECHO(y0);
314
-              SERIAL_CHAR(')');
287
+              SERIAL_ECHOPGM(") = ");
288
+              SERIAL_ECHO_F(z0, 6);
289
+            }
290
+          #endif
291
+
292
+          #if ENABLED(DEBUG_LEVELING_FEATURE)
293
+            if (DEBUGGING(MESH_ADJUST)) {
294
+              SERIAL_ECHOPGM(" >>>---> ");
295
+              SERIAL_ECHO_F(z0, 6);
315 296
               SERIAL_EOL;
316 297
             }
317 298
           #endif
318
-        }
319
-        return z0; // there used to be a +state.z_offset on this line
320
-      }
321
-
322
-      /**
323
-       * This routine is used to scale the Z correction depending upon the current nozzle height. It is
324
-       * optimized for speed. It avoids floating point operations by checking if the requested scaling
325
-       * factor is going to be the same as the last time the function calculated a value. If so, it just
326
-       * returns it.
327
-       *
328
-       * It returns a scaling factor of 1.0 if UBL is inactive.
329
-       * It returns a scaling factor of 0.0 if Z is past the specified 'Fade Height'
330
-       */
331
-      #if ENABLED(ENABLE_LEVELING_FADE_HEIGHT)
332 299
 
333
-        FORCE_INLINE float fade_scaling_factor_for_z(const float &lz) {
334
-          const float rz = RAW_Z_POSITION(lz);
335
-          if (last_specified_z != rz) {
336
-            last_specified_z = rz;
337
-            fade_scaling_factor_for_current_height =
338
-              state.active && rz < state.g29_correction_fade_height
339
-                ? 1.0 - (rz * state.g29_fade_height_multiplier)
340
-                : 0.0;
300
+          if (isnan(z0)) { // if part of the Mesh is undefined, it will show up as NAN
301
+            z0 = 0.0;      // in ubl.z_values[][] and propagate through the
302
+                           // calculations. If our correction is NAN, we throw it out
303
+                           // because part of the Mesh is undefined and we don't have the
304
+                           // information we need to complete the height correction.
305
+
306
+            #if ENABLED(DEBUG_LEVELING_FEATURE)
307
+              if (DEBUGGING(MESH_ADJUST)) {
308
+                SERIAL_ECHOPAIR("??? Yikes!  NAN in get_z_correction(", x0);
309
+                SERIAL_CHAR(',');
310
+                SERIAL_ECHO(y0);
311
+                SERIAL_CHAR(')');
312
+                SERIAL_EOL;
313
+              }
314
+            #endif
341 315
           }
342
-          return fade_scaling_factor_for_current_height;
316
+          return z0; // there used to be a +state.z_offset on this line
343 317
         }
344 318
 
345
-      #else
319
+        /**
320
+         * This routine is used to scale the Z correction depending upon the current nozzle height. It is
321
+         * optimized for speed. It avoids floating point operations by checking if the requested scaling
322
+         * factor is going to be the same as the last time the function calculated a value. If so, it just
323
+         * returns it.
324
+         *
325
+         * It returns a scaling factor of 1.0 if UBL is inactive.
326
+         * It returns a scaling factor of 0.0 if Z is past the specified 'Fade Height'
327
+         */
328
+        #if ENABLED(ENABLE_LEVELING_FADE_HEIGHT)
329
+
330
+          FORCE_INLINE float fade_scaling_factor_for_z(const float &lz) {
331
+            const float rz = RAW_Z_POSITION(lz);
332
+            if (last_specified_z != rz) {
333
+              last_specified_z = rz;
334
+              fade_scaling_factor_for_current_height =
335
+                state.active && rz < state.g29_correction_fade_height
336
+                  ? 1.0 - (rz * state.g29_fade_height_multiplier)
337
+                  : 0.0;
338
+            }
339
+            return fade_scaling_factor_for_current_height;
340
+          }
346 341
 
347
-        static constexpr float fade_scaling_factor_for_z(const float &lz) { UNUSED(lz); return 1.0; }
342
+        #else
348 343
 
349
-      #endif
344
+          static constexpr float fade_scaling_factor_for_z(const float &lz) { UNUSED(lz); return 1.0; }
345
+
346
+        #endif
350 347
 
351 348
     }; // class unified_bed_leveling
352 349
 
@@ -355,5 +352,4 @@
355 352
     #define UBL_LAST_EEPROM_INDEX (E2END - sizeof(unified_bed_leveling::state))
356 353
 
357 354
   #endif // AUTO_BED_LEVELING_UBL
358
-
359 355
 #endif // UNIFIED_BED_LEVELING_H

+ 17
- 17
Marlin/UBL_Bed_Leveling.cpp View File

@@ -57,23 +57,26 @@
57 57
     }
58 58
   }
59 59
 
60
-  /**
61
-   * These variables used to be declared inside the unified_bed_leveling class. We are going to
62
-   * still declare them within the .cpp file for bed leveling. But there is only one instance of
63
-   * the bed leveling object and we can get rid of a level of inderection by not making them
64
-   * 'member data'. So, in the interest of speed, we do it this way. On a 32-bit CPU they can be
65
-   * moved back inside the bed leveling class.
66
-   */
67
-  float mesh_index_to_x_location[UBL_MESH_NUM_X_POINTS + 1], // +1 just because of paranoia that we might end up on the
68
-        mesh_index_to_y_location[UBL_MESH_NUM_Y_POINTS + 1]; // the last Mesh Line and that is the start of a whole new cell
60
+  ubl_state unified_bed_leveling::state, unified_bed_leveling::pre_initialized;
69 61
 
70
-  unified_bed_leveling::unified_bed_leveling() {
71
-    for (uint8_t i = 0; i <= UBL_MESH_NUM_X_POINTS; i++)  // We go one past what we expect to ever need for safety
72
-      mesh_index_to_x_location[i] = double(UBL_MESH_MIN_X) + double(MESH_X_DIST) * double(i);
62
+  float unified_bed_leveling::z_values[UBL_MESH_NUM_X_POINTS][UBL_MESH_NUM_Y_POINTS],
63
+        unified_bed_leveling::last_specified_z,
64
+        unified_bed_leveling::fade_scaling_factor_for_current_height,
65
+        unified_bed_leveling::mesh_index_to_xpos[UBL_MESH_NUM_X_POINTS + 1], // +1 safety margin for now, until determinism prevails
66
+        unified_bed_leveling::mesh_index_to_ypos[UBL_MESH_NUM_Y_POINTS + 1];
67
+
68
+  bool unified_bed_leveling::g26_debug_flag = false,
69
+       unified_bed_leveling::has_control_of_lcd_panel = false;
73 70
 
74
-    for (uint8_t i = 0; i <= UBL_MESH_NUM_Y_POINTS; i++)  // We go one past what we expect to ever need for safety
75
-      mesh_index_to_y_location[i] = double(UBL_MESH_MIN_Y) + double(MESH_Y_DIST) * double(i);
71
+  int8_t unified_bed_leveling::eeprom_start = -1;
76 72
 
73
+  volatile int unified_bed_leveling::encoder_diff;
74
+
75
+  unified_bed_leveling::unified_bed_leveling() {
76
+    for (uint8_t i = 0; i < COUNT(mesh_index_to_xpos); i++)
77
+      mesh_index_to_xpos[i] = UBL_MESH_MIN_X + i * (MESH_X_DIST);
78
+    for (uint8_t i = 0; i < COUNT(mesh_index_to_ypos); i++)
79
+      mesh_index_to_ypos[i] = UBL_MESH_MIN_Y + i * (MESH_Y_DIST);
77 80
     reset();
78 81
   }
79 82
 
@@ -161,9 +164,6 @@
161 164
   }
162 165
 
163 166
   void unified_bed_leveling::invalidate() {
164
-    print_hex_word((uint16_t)this);
165
-    SERIAL_EOL;
166
-
167 167
     state.active = false;
168 168
     state.z_offset = 0;
169 169
     for (int x = 0; x < UBL_MESH_NUM_X_POINTS; x++)

+ 10
- 10
Marlin/UBL_G29.cpp View File

@@ -750,8 +750,8 @@
750 750
       location = find_closest_mesh_point_of_type(INVALID, lx, ly, 1, NULL, do_furthest );  // the '1' says we want the location to be relative to the probe
751 751
       if (location.x_index >= 0 && location.y_index >= 0) {
752 752
 
753
-        const float rawx = ubl.map_x_index_to_bed_location(location.x_index),
754
-                    rawy = ubl.map_y_index_to_bed_location(location.y_index);
753
+        const float rawx = ubl.mesh_index_to_xpos[location.x_index],
754
+                    rawy = ubl.mesh_index_to_ypos[location.y_index];
755 755
 
756 756
         // TODO: Change to use `position_is_reachable` (for SCARA-compatibility)
757 757
         if (rawx < (MIN_PROBE_X) || rawx > (MAX_PROBE_X) || rawy < (MIN_PROBE_Y) || rawy > (MAX_PROBE_Y)) {
@@ -900,8 +900,8 @@
900 900
       // It doesn't matter if the probe can't reach the NAN location. This is a manual probe.
901 901
       if (location.x_index < 0 && location.y_index < 0) continue;
902 902
 
903
-      const float rawx = ubl.map_x_index_to_bed_location(location.x_index),
904
-                  rawy = ubl.map_y_index_to_bed_location(location.y_index);
903
+      const float rawx = ubl.mesh_index_to_xpos[location.x_index],
904
+                  rawy = ubl.mesh_index_to_ypos[location.y_index];
905 905
 
906 906
       // TODO: Change to use `position_is_reachable` (for SCARA-compatibility)
907 907
       if (rawx < (X_MIN_POS) || rawx > (X_MAX_POS) || rawy < (Y_MIN_POS) || rawy > (Y_MAX_POS)) {
@@ -1137,7 +1137,7 @@
1137 1137
 
1138 1138
     SERIAL_PROTOCOLPGM("X-Axis Mesh Points at: ");
1139 1139
     for (uint8_t i = 0; i < UBL_MESH_NUM_X_POINTS; i++) {
1140
-      SERIAL_PROTOCOL_F(LOGICAL_X_POSITION(ubl.map_x_index_to_bed_location(i)), 1);
1140
+      SERIAL_PROTOCOL_F(LOGICAL_X_POSITION(ubl.mesh_index_to_xpos[i]), 1);
1141 1141
       SERIAL_PROTOCOLPGM("  ");
1142 1142
       safe_delay(50);
1143 1143
     }
@@ -1145,7 +1145,7 @@
1145 1145
 
1146 1146
     SERIAL_PROTOCOLPGM("Y-Axis Mesh Points at: ");
1147 1147
     for (uint8_t i = 0; i < UBL_MESH_NUM_Y_POINTS; i++) {
1148
-      SERIAL_PROTOCOL_F(LOGICAL_Y_POSITION(ubl.map_y_index_to_bed_location(i)), 1);
1148
+      SERIAL_PROTOCOL_F(LOGICAL_Y_POSITION(ubl.mesh_index_to_ypos[i]), 1);
1149 1149
       SERIAL_PROTOCOLPGM("  ");
1150 1150
       safe_delay(50);
1151 1151
     }
@@ -1283,8 +1283,8 @@
1283 1283
 
1284 1284
           // We only get here if we found a Mesh Point of the specified type
1285 1285
 
1286
-          const float rawx = ubl.map_x_index_to_bed_location(i), // Check if we can probe this mesh location
1287
-                      rawy = ubl.map_y_index_to_bed_location(j);
1286
+          const float rawx = ubl.mesh_index_to_xpos[i], // Check if we can probe this mesh location
1287
+                      rawy = ubl.mesh_index_to_ypos[j];
1288 1288
 
1289 1289
           // If using the probe as the reference there are some unreachable locations.
1290 1290
           // Prune them from the list and ignore them till the next Phase (manual nozzle probing).
@@ -1350,8 +1350,8 @@
1350 1350
       bit_clear(not_done, location.x_index, location.y_index);  // Mark this location as 'adjusted' so we will find a
1351 1351
                                                                 // different location the next time through the loop
1352 1352
 
1353
-      const float rawx = ubl.map_x_index_to_bed_location(location.x_index),
1354
-                  rawy = ubl.map_y_index_to_bed_location(location.y_index);
1353
+      const float rawx = ubl.mesh_index_to_xpos[location.x_index],
1354
+                  rawy = ubl.mesh_index_to_ypos[location.y_index];
1355 1355
 
1356 1356
       // TODO: Change to use `position_is_reachable` (for SCARA-compatibility)
1357 1357
       if (rawx < (X_MIN_POS) || rawx > (X_MAX_POS) || rawy < (Y_MIN_POS) || rawy > (Y_MAX_POS)) { // In theory, we don't need this check.

+ 12
- 12
Marlin/UBL_line_to_destination.cpp View File

@@ -167,16 +167,16 @@
167 167
        * to create a 1-over number for us. That will allow us to do a floating point multiply instead of a floating point divide.
168 168
        */
169 169
 
170
-      const float xratio = (RAW_X_POSITION(x_end) - mesh_index_to_x_location[cell_dest_xi]) * (1.0 / (MESH_X_DIST)),
171
-                  z1 = z_values[cell_dest_xi    ][cell_dest_yi    ] + xratio *
172
-                      (z_values[cell_dest_xi + 1][cell_dest_yi    ] - z_values[cell_dest_xi][cell_dest_yi    ]),
173
-                  z2 = z_values[cell_dest_xi    ][cell_dest_yi + 1] + xratio *
174
-                      (z_values[cell_dest_xi + 1][cell_dest_yi + 1] - z_values[cell_dest_xi][cell_dest_yi + 1]);
170
+      const float xratio = (RAW_X_POSITION(x_end) - ubl.mesh_index_to_xpos[cell_dest_xi]) * (1.0 / (MESH_X_DIST)),
171
+                  z1 = ubl.z_values[cell_dest_xi    ][cell_dest_yi    ] + xratio *
172
+                      (ubl.z_values[cell_dest_xi + 1][cell_dest_yi    ] - ubl.z_values[cell_dest_xi][cell_dest_yi    ]),
173
+                  z2 = ubl.z_values[cell_dest_xi    ][cell_dest_yi + 1] + xratio *
174
+                      (ubl.z_values[cell_dest_xi + 1][cell_dest_yi + 1] - ubl.z_values[cell_dest_xi][cell_dest_yi + 1]);
175 175
 
176 176
       // we are done with the fractional X distance into the cell. Now with the two Z-Heights we have calculated, we
177 177
       // are going to apply the Y-Distance into the cell to interpolate the final Z correction.
178 178
 
179
-      const float yratio = (RAW_Y_POSITION(y_end) - mesh_index_to_y_location[cell_dest_yi]) * (1.0 / (MESH_Y_DIST));
179
+      const float yratio = (RAW_Y_POSITION(y_end) - ubl.mesh_index_to_ypos[cell_dest_yi]) * (1.0 / (MESH_Y_DIST));
180 180
 
181 181
       float z0 = z1 + (z2 - z1) * yratio;
182 182
 
@@ -274,7 +274,7 @@
274 274
       current_yi += down_flag;  // Line is heading down, we just want to go to the bottom
275 275
       while (current_yi != cell_dest_yi + down_flag) {
276 276
         current_yi += dyi;
277
-        const float next_mesh_line_y = LOGICAL_Y_POSITION(mesh_index_to_y_location[current_yi]);
277
+        const float next_mesh_line_y = LOGICAL_Y_POSITION(ubl.mesh_index_to_ypos[current_yi]);
278 278
 
279 279
         /**
280 280
          * inf_m_flag? the slope of the line is infinite, we won't do the calculations
@@ -316,7 +316,7 @@
316 316
          */
317 317
         if (isnan(z0)) z0 = 0.0;
318 318
 
319
-        const float y = LOGICAL_Y_POSITION(mesh_index_to_y_location[current_yi]);
319
+        const float y = LOGICAL_Y_POSITION(ubl.mesh_index_to_ypos[current_yi]);
320 320
 
321 321
         /**
322 322
          * Without this check, it is possible for the algorithm to generate a zero length move in the case
@@ -365,7 +365,7 @@
365 365
                                 // edge of this cell for the first move.
366 366
       while (current_xi != cell_dest_xi + left_flag) {
367 367
         current_xi += dxi;
368
-        const float next_mesh_line_x = LOGICAL_X_POSITION(mesh_index_to_x_location[current_xi]),
368
+        const float next_mesh_line_x = LOGICAL_X_POSITION(ubl.mesh_index_to_xpos[current_xi]),
369 369
                     y = m * next_mesh_line_x + c;   // Calculate X at the next Y mesh line
370 370
 
371 371
         float z0 = ubl.get_z_correction_along_vertical_mesh_line_at_specific_Y(y, current_xi, current_yi);
@@ -401,7 +401,7 @@
401 401
          */
402 402
         if (isnan(z0)) z0 = 0.0;
403 403
 
404
-        const float x = LOGICAL_X_POSITION(mesh_index_to_x_location[current_xi]);
404
+        const float x = LOGICAL_X_POSITION(ubl.mesh_index_to_xpos[current_xi]);
405 405
 
406 406
         /**
407 407
          * Without this check, it is possible for the algorithm to generate a zero length move in the case
@@ -451,8 +451,8 @@
451 451
 
452 452
     while (xi_cnt > 0 || yi_cnt > 0) {
453 453
 
454
-      const float next_mesh_line_x = LOGICAL_X_POSITION(mesh_index_to_x_location[current_xi + dxi]),
455
-                  next_mesh_line_y = LOGICAL_Y_POSITION(mesh_index_to_y_location[current_yi + dyi]),
454
+      const float next_mesh_line_x = LOGICAL_X_POSITION(ubl.mesh_index_to_xpos[current_xi + dxi]),
455
+                  next_mesh_line_y = LOGICAL_Y_POSITION(ubl.mesh_index_to_ypos[current_yi + dyi]),
456 456
                   y = m * next_mesh_line_x + c,   // Calculate Y at the next X mesh line
457 457
                   x = (next_mesh_line_y - c) / m; // Calculate X at the next Y mesh line    (we don't have to worry
458 458
                                                   // about m being equal to 0.0  If this was the case, we would have

Loading…
Cancel
Save