Browse Source

Add OPTIMIZED_MESH_STORAGE option (for UBL) (#20371)

Co-authored-by: Scott Lahteine <thinkyhead@users.noreply.github.com>
ubik2 3 years ago
parent
commit
844a8c7074
No account linked to committer's email address

+ 4
- 0
Marlin/Configuration_adv.h View File

@@ -1739,6 +1739,10 @@
1739 1739
   //#define MESH_MAX_Y Y_BED_SIZE - (MESH_INSET)
1740 1740
 #endif
1741 1741
 
1742
+#if BOTH(AUTO_BED_LEVELING_UBL, EEPROM_SETTINGS)
1743
+  //#define OPTIMIZED_MESH_STORAGE  // Store mesh with less precision to save EEPROM space
1744
+#endif
1745
+
1742 1746
 /**
1743 1747
  * Repeatedly attempt G29 leveling until it succeeds.
1744 1748
  * Stop after G29_MAX_RETRIES attempts.

+ 1
- 0
Marlin/src/core/macros.h View File

@@ -286,6 +286,7 @@
286 286
 #define RSQRT(x)    (1.0f / sqrtf(x))
287 287
 #define CEIL(x)     ceilf(x)
288 288
 #define FLOOR(x)    floorf(x)
289
+#define TRUNC(x)    truncf(x)
289 290
 #define LROUND(x)   lroundf(x)
290 291
 #define FMOD(x, y)  fmodf(x, y)
291 292
 #define HYPOT(x,y)  SQRT(HYPOT2(x,y))

+ 28
- 7
Marlin/src/feature/bedlevel/ubl/ubl.cpp View File

@@ -42,9 +42,7 @@
42 42
 
43 43
   #include "math.h"
44 44
 
45
-  void unified_bed_leveling::echo_name() {
46
-    SERIAL_ECHOPGM("Unified Bed Leveling");
47
-  }
45
+  void unified_bed_leveling::echo_name() { SERIAL_ECHOPGM("Unified Bed Leveling"); }
48 46
 
49 47
   void unified_bed_leveling::report_current_mesh() {
50 48
     if (!leveling_is_valid()) return;
@@ -86,9 +84,7 @@
86 84
 
87 85
   volatile int16_t unified_bed_leveling::encoder_diff;
88 86
 
89
-  unified_bed_leveling::unified_bed_leveling() {
90
-    reset();
91
-  }
87
+  unified_bed_leveling::unified_bed_leveling() { reset(); }
92 88
 
93 89
   void unified_bed_leveling::reset() {
94 90
     const bool was_enabled = planner.leveling_active;
@@ -113,6 +109,31 @@
113 109
     }
114 110
   }
115 111
 
112
+  #if ENABLED(OPTIMIZED_MESH_STORAGE)
113
+
114
+    constexpr float mesh_store_scaling = 1000;
115
+    constexpr int16_t Z_STEPS_NAN = INT16_MAX;
116
+
117
+    void unified_bed_leveling::set_store_from_mesh(const bed_mesh_t &in_values, mesh_store_t &stored_values) {
118
+      auto z_to_store = [](const float &z) {
119
+        if (isnan(z)) return Z_STEPS_NAN;
120
+        const int32_t z_scaled = TRUNC(z * mesh_store_scaling);
121
+        if (z_scaled == Z_STEPS_NAN || !WITHIN(z_scaled, INT16_MIN, INT16_MAX))
122
+          return Z_STEPS_NAN; // If Z is out of range, return our custom 'NaN'
123
+        return int16_t(z_scaled);
124
+      };
125
+      GRID_LOOP(x, y) stored_values[x][y] = z_to_store(in_values[x][y]);
126
+    }
127
+
128
+    void unified_bed_leveling::set_mesh_from_store(const mesh_store_t &stored_values, bed_mesh_t &out_values) {
129
+      auto store_to_z = [](const int16_t z_scaled) {
130
+        return z_scaled == Z_STEPS_NAN ? NAN : z_scaled / mesh_store_scaling;
131
+      };
132
+      GRID_LOOP(x, y) out_values[x][y] = store_to_z(stored_values[x][y]);
133
+    }
134
+
135
+  #endif // OPTIMIZED_MESH_STORAGE
136
+
116 137
   static void serial_echo_xy(const uint8_t sp, const int16_t x, const int16_t y) {
117 138
     SERIAL_ECHO_SP(sp);
118 139
     SERIAL_CHAR('(');
@@ -127,7 +148,7 @@
127 148
 
128 149
   static void serial_echo_column_labels(const uint8_t sp) {
129 150
     SERIAL_ECHO_SP(7);
130
-    for (int8_t i = 0; i < GRID_MAX_POINTS_X; i++) {
151
+    LOOP_L_N(i, GRID_MAX_POINTS_X) {
131 152
       if (i < 10) SERIAL_CHAR(' ');
132 153
       SERIAL_ECHO(i);
133 154
       SERIAL_ECHO_SP(sp);

+ 16
- 14
Marlin/src/feature/bedlevel/ubl/ubl.h View File

@@ -41,6 +41,10 @@ struct mesh_index_pair;
41 41
 #define MESH_X_DIST (float(MESH_MAX_X - (MESH_MIN_X)) / float(GRID_MAX_POINTS_X - 1))
42 42
 #define MESH_Y_DIST (float(MESH_MAX_Y - (MESH_MIN_Y)) / float(GRID_MAX_POINTS_Y - 1))
43 43
 
44
+#if ENABLED(OPTIMIZED_MESH_STORAGE)
45
+  typedef int16_t mesh_store_t[GRID_MAX_POINTS_X][GRID_MAX_POINTS_Y];
46
+#endif
47
+
44 48
 class unified_bed_leveling {
45 49
   private:
46 50
 
@@ -106,6 +110,10 @@ class unified_bed_leveling {
106 110
     static int8_t storage_slot;
107 111
 
108 112
     static bed_mesh_t z_values;
113
+    #if ENABLED(OPTIMIZED_MESH_STORAGE)
114
+      static void set_store_from_mesh(const bed_mesh_t &in_values, mesh_store_t &stored_values);
115
+      static void set_mesh_from_store(const mesh_store_t &stored_values, bed_mesh_t &out_values);
116
+    #endif
109 117
     static const float _mesh_index_to_xpos[GRID_MAX_POINTS_X],
110 118
                        _mesh_index_to_ypos[GRID_MAX_POINTS_Y];
111 119
 
@@ -182,6 +190,12 @@ class unified_bed_leveling {
182 190
       return z1 + (z2 - z1) * (a0 - a1) / (a2 - a1);
183 191
     }
184 192
 
193
+    #ifdef UBL_Z_RAISE_WHEN_OFF_MESH
194
+      #define _UBL_OUTER_Z_RAISE UBL_Z_RAISE_WHEN_OFF_MESH
195
+    #else
196
+      #define _UBL_OUTER_Z_RAISE NAN
197
+    #endif
198
+
185 199
     /**
186 200
      * z_correction_for_x_on_horizontal_mesh_line is an optimization for
187 201
      * the case where the printer is making a vertical line that only crosses horizontal mesh lines.
@@ -195,13 +209,7 @@ class unified_bed_leveling {
195 209
         }
196 210
 
197 211
         // The requested location is off the mesh. Return UBL_Z_RAISE_WHEN_OFF_MESH or NAN.
198
-        return (
199
-          #ifdef UBL_Z_RAISE_WHEN_OFF_MESH
200
-            UBL_Z_RAISE_WHEN_OFF_MESH
201
-          #else
202
-            NAN
203
-          #endif
204
-        );
212
+        return _UBL_OUTER_Z_RAISE;
205 213
       }
206 214
 
207 215
       const float xratio = (rx0 - mesh_index_to_xpos(x1_i)) * RECIPROCAL(MESH_X_DIST),
@@ -224,13 +232,7 @@ class unified_bed_leveling {
224 232
         }
225 233
 
226 234
         // The requested location is off the mesh. Return UBL_Z_RAISE_WHEN_OFF_MESH or NAN.
227
-        return (
228
-          #ifdef UBL_Z_RAISE_WHEN_OFF_MESH
229
-            UBL_Z_RAISE_WHEN_OFF_MESH
230
-          #else
231
-            NAN
232
-          #endif
233
-        );
235
+        return _UBL_OUTER_Z_RAISE;
234 236
       }
235 237
 
236 238
       const float yratio = (ry0 - mesh_index_to_ypos(y1_i)) * RECIPROCAL(MESH_Y_DIST),

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

@@ -543,7 +543,7 @@
543 543
           }
544 544
           else {
545 545
             const float cvf = parser.value_float();
546
-            switch ((int)truncf(cvf * 10.0f) - 30) {   // 3.1 -> 1
546
+            switch ((int)TRUNC(cvf * 10.0f) - 30) {   // 3.1 -> 1
547 547
               #if ENABLED(UBL_G29_P31)
548 548
                 case 1: {
549 549
 

+ 30
- 5
Marlin/src/module/settings.cpp View File

@@ -2385,12 +2385,14 @@ void MarlinSettings::postprocess() {
2385 2385
                                                           // or down a little bit without disrupting the mesh data
2386 2386
     }
2387 2387
 
2388
+    #define MESH_STORE_SIZE sizeof(TERN(OPTIMIZED_MESH_STORAGE, mesh_store_t, ubl.z_values))
2389
+
2388 2390
     uint16_t MarlinSettings::calc_num_meshes() {
2389
-      return (meshes_end - meshes_start_index()) / sizeof(ubl.z_values);
2391
+      return (meshes_end - meshes_start_index()) / MESH_STORE_SIZE;
2390 2392
     }
2391 2393
 
2392 2394
     int MarlinSettings::mesh_slot_offset(const int8_t slot) {
2393
-      return meshes_end - (slot + 1) * sizeof(ubl.z_values);
2395
+      return meshes_end - (slot + 1) * MESH_STORE_SIZE;
2394 2396
     }
2395 2397
 
2396 2398
     void MarlinSettings::store_mesh(const int8_t slot) {
@@ -2407,9 +2409,17 @@ void MarlinSettings::postprocess() {
2407 2409
         int pos = mesh_slot_offset(slot);
2408 2410
         uint16_t crc = 0;
2409 2411
 
2412
+        #if ENABLED(OPTIMIZED_MESH_STORAGE)
2413
+          int16_t z_mesh_store[GRID_MAX_POINTS_X][GRID_MAX_POINTS_Y];
2414
+          ubl.set_store_from_mesh(ubl.z_values, z_mesh_store);
2415
+          uint8_t * const src = (uint8_t*)&z_mesh_store;
2416
+        #else
2417
+          uint8_t * const src = (uint8_t*)&ubl.z_values;
2418
+        #endif
2419
+
2410 2420
         // Write crc to MAT along with other data, or just tack on to the beginning or end
2411 2421
         persistentStore.access_start();
2412
-        const bool status = persistentStore.write_data(pos, (uint8_t *)&ubl.z_values, sizeof(ubl.z_values), &crc);
2422
+        const bool status = persistentStore.write_data(pos, src, MESH_STORE_SIZE, &crc);
2413 2423
         persistentStore.access_finish();
2414 2424
 
2415 2425
         if (status) SERIAL_ECHOLNPGM("?Unable to save mesh data.");
@@ -2435,12 +2445,27 @@ void MarlinSettings::postprocess() {
2435 2445
 
2436 2446
         int pos = mesh_slot_offset(slot);
2437 2447
         uint16_t crc = 0;
2438
-        uint8_t * const dest = into ? (uint8_t*)into : (uint8_t*)&ubl.z_values;
2448
+        #if ENABLED(OPTIMIZED_MESH_STORAGE)
2449
+          int16_t z_mesh_store[GRID_MAX_POINTS_X][GRID_MAX_POINTS_Y];
2450
+          uint8_t * const dest = (uint8_t*)&z_mesh_store;
2451
+        #else
2452
+          uint8_t * const dest = into ? (uint8_t*)into : (uint8_t*)&ubl.z_values;
2453
+        #endif
2439 2454
 
2440 2455
         persistentStore.access_start();
2441
-        const uint16_t status = persistentStore.read_data(pos, dest, sizeof(ubl.z_values), &crc);
2456
+        const uint16_t status = persistentStore.read_data(pos, dest, MESH_STORE_SIZE, &crc);
2442 2457
         persistentStore.access_finish();
2443 2458
 
2459
+        #if ENABLED(OPTIMIZED_MESH_STORAGE)
2460
+          if (into) {
2461
+            float z_values[GRID_MAX_POINTS_X][GRID_MAX_POINTS_Y];
2462
+            ubl.set_mesh_from_store(z_mesh_store, z_values);
2463
+            memcpy(into, z_values, sizeof(z_values));
2464
+          }
2465
+          else
2466
+            ubl.set_mesh_from_store(z_mesh_store, ubl.z_values);
2467
+        #endif
2468
+
2444 2469
         if (status) SERIAL_ECHOLNPGM("?Unable to load mesh data.");
2445 2470
         else        DEBUG_ECHOLNPAIR("Mesh loaded from slot ", slot);
2446 2471
 

Loading…
Cancel
Save