Add OPTIMIZED_MESH_STORAGE option (for UBL) (#20371)
Co-authored-by: Scott Lahteine <thinkyhead@users.noreply.github.com>
This commit is contained in:
		
							parent
							
								
									2d88a2cfb7
								
							
						
					
					
						commit
						844a8c7074
					
				| @ -1739,6 +1739,10 @@ | ||||
|   //#define MESH_MAX_Y Y_BED_SIZE - (MESH_INSET)
 | ||||
| #endif | ||||
| 
 | ||||
| #if BOTH(AUTO_BED_LEVELING_UBL, EEPROM_SETTINGS) | ||||
|   //#define OPTIMIZED_MESH_STORAGE  // Store mesh with less precision to save EEPROM space
 | ||||
| #endif | ||||
| 
 | ||||
| /**
 | ||||
|  * Repeatedly attempt G29 leveling until it succeeds. | ||||
|  * Stop after G29_MAX_RETRIES attempts. | ||||
|  | ||||
| @ -286,6 +286,7 @@ | ||||
| #define RSQRT(x)    (1.0f / sqrtf(x)) | ||||
| #define CEIL(x)     ceilf(x) | ||||
| #define FLOOR(x)    floorf(x) | ||||
| #define TRUNC(x)    truncf(x) | ||||
| #define LROUND(x)   lroundf(x) | ||||
| #define FMOD(x, y)  fmodf(x, y) | ||||
| #define HYPOT(x,y)  SQRT(HYPOT2(x,y)) | ||||
|  | ||||
| @ -42,9 +42,7 @@ | ||||
| 
 | ||||
|   #include "math.h" | ||||
| 
 | ||||
|   void unified_bed_leveling::echo_name() { | ||||
|     SERIAL_ECHOPGM("Unified Bed Leveling"); | ||||
|   } | ||||
|   void unified_bed_leveling::echo_name() { SERIAL_ECHOPGM("Unified Bed Leveling"); } | ||||
| 
 | ||||
|   void unified_bed_leveling::report_current_mesh() { | ||||
|     if (!leveling_is_valid()) return; | ||||
| @ -86,9 +84,7 @@ | ||||
| 
 | ||||
|   volatile int16_t unified_bed_leveling::encoder_diff; | ||||
| 
 | ||||
|   unified_bed_leveling::unified_bed_leveling() { | ||||
|     reset(); | ||||
|   } | ||||
|   unified_bed_leveling::unified_bed_leveling() { reset(); } | ||||
| 
 | ||||
|   void unified_bed_leveling::reset() { | ||||
|     const bool was_enabled = planner.leveling_active; | ||||
| @ -113,6 +109,31 @@ | ||||
|     } | ||||
|   } | ||||
| 
 | ||||
|   #if ENABLED(OPTIMIZED_MESH_STORAGE) | ||||
| 
 | ||||
|     constexpr float mesh_store_scaling = 1000; | ||||
|     constexpr int16_t Z_STEPS_NAN = INT16_MAX; | ||||
| 
 | ||||
|     void unified_bed_leveling::set_store_from_mesh(const bed_mesh_t &in_values, mesh_store_t &stored_values) { | ||||
|       auto z_to_store = [](const float &z) { | ||||
|         if (isnan(z)) return Z_STEPS_NAN; | ||||
|         const int32_t z_scaled = TRUNC(z * mesh_store_scaling); | ||||
|         if (z_scaled == Z_STEPS_NAN || !WITHIN(z_scaled, INT16_MIN, INT16_MAX)) | ||||
|           return Z_STEPS_NAN; // If Z is out of range, return our custom 'NaN'
 | ||||
|         return int16_t(z_scaled); | ||||
|       }; | ||||
|       GRID_LOOP(x, y) stored_values[x][y] = z_to_store(in_values[x][y]); | ||||
|     } | ||||
| 
 | ||||
|     void unified_bed_leveling::set_mesh_from_store(const mesh_store_t &stored_values, bed_mesh_t &out_values) { | ||||
|       auto store_to_z = [](const int16_t z_scaled) { | ||||
|         return z_scaled == Z_STEPS_NAN ? NAN : z_scaled / mesh_store_scaling; | ||||
|       }; | ||||
|       GRID_LOOP(x, y) out_values[x][y] = store_to_z(stored_values[x][y]); | ||||
|     } | ||||
| 
 | ||||
|   #endif // OPTIMIZED_MESH_STORAGE
 | ||||
| 
 | ||||
|   static void serial_echo_xy(const uint8_t sp, const int16_t x, const int16_t y) { | ||||
|     SERIAL_ECHO_SP(sp); | ||||
|     SERIAL_CHAR('('); | ||||
| @ -127,7 +148,7 @@ | ||||
| 
 | ||||
|   static void serial_echo_column_labels(const uint8_t sp) { | ||||
|     SERIAL_ECHO_SP(7); | ||||
|     for (int8_t i = 0; i < GRID_MAX_POINTS_X; i++) { | ||||
|     LOOP_L_N(i, GRID_MAX_POINTS_X) { | ||||
|       if (i < 10) SERIAL_CHAR(' '); | ||||
|       SERIAL_ECHO(i); | ||||
|       SERIAL_ECHO_SP(sp); | ||||
|  | ||||
| @ -41,6 +41,10 @@ struct mesh_index_pair; | ||||
| #define MESH_X_DIST (float(MESH_MAX_X - (MESH_MIN_X)) / float(GRID_MAX_POINTS_X - 1)) | ||||
| #define MESH_Y_DIST (float(MESH_MAX_Y - (MESH_MIN_Y)) / float(GRID_MAX_POINTS_Y - 1)) | ||||
| 
 | ||||
| #if ENABLED(OPTIMIZED_MESH_STORAGE) | ||||
|   typedef int16_t mesh_store_t[GRID_MAX_POINTS_X][GRID_MAX_POINTS_Y]; | ||||
| #endif | ||||
| 
 | ||||
| class unified_bed_leveling { | ||||
|   private: | ||||
| 
 | ||||
| @ -106,6 +110,10 @@ class unified_bed_leveling { | ||||
|     static int8_t storage_slot; | ||||
| 
 | ||||
|     static bed_mesh_t z_values; | ||||
|     #if ENABLED(OPTIMIZED_MESH_STORAGE) | ||||
|       static void set_store_from_mesh(const bed_mesh_t &in_values, mesh_store_t &stored_values); | ||||
|       static void set_mesh_from_store(const mesh_store_t &stored_values, bed_mesh_t &out_values); | ||||
|     #endif | ||||
|     static const float _mesh_index_to_xpos[GRID_MAX_POINTS_X], | ||||
|                        _mesh_index_to_ypos[GRID_MAX_POINTS_Y]; | ||||
| 
 | ||||
| @ -182,6 +190,12 @@ class unified_bed_leveling { | ||||
|       return z1 + (z2 - z1) * (a0 - a1) / (a2 - a1); | ||||
|     } | ||||
| 
 | ||||
|     #ifdef UBL_Z_RAISE_WHEN_OFF_MESH | ||||
|       #define _UBL_OUTER_Z_RAISE UBL_Z_RAISE_WHEN_OFF_MESH | ||||
|     #else | ||||
|       #define _UBL_OUTER_Z_RAISE NAN | ||||
|     #endif | ||||
| 
 | ||||
|     /**
 | ||||
|      * z_correction_for_x_on_horizontal_mesh_line is an optimization for | ||||
|      * the case where the printer is making a vertical line that only crosses horizontal mesh lines. | ||||
| @ -195,13 +209,7 @@ class unified_bed_leveling { | ||||
|         } | ||||
| 
 | ||||
|         // The requested location is off the mesh. Return UBL_Z_RAISE_WHEN_OFF_MESH or NAN.
 | ||||
|         return ( | ||||
|           #ifdef UBL_Z_RAISE_WHEN_OFF_MESH | ||||
|             UBL_Z_RAISE_WHEN_OFF_MESH | ||||
|           #else | ||||
|             NAN | ||||
|           #endif | ||||
|         ); | ||||
|         return _UBL_OUTER_Z_RAISE; | ||||
|       } | ||||
| 
 | ||||
|       const float xratio = (rx0 - mesh_index_to_xpos(x1_i)) * RECIPROCAL(MESH_X_DIST), | ||||
| @ -224,13 +232,7 @@ class unified_bed_leveling { | ||||
|         } | ||||
| 
 | ||||
|         // The requested location is off the mesh. Return UBL_Z_RAISE_WHEN_OFF_MESH or NAN.
 | ||||
|         return ( | ||||
|           #ifdef UBL_Z_RAISE_WHEN_OFF_MESH | ||||
|             UBL_Z_RAISE_WHEN_OFF_MESH | ||||
|           #else | ||||
|             NAN | ||||
|           #endif | ||||
|         ); | ||||
|         return _UBL_OUTER_Z_RAISE; | ||||
|       } | ||||
| 
 | ||||
|       const float yratio = (ry0 - mesh_index_to_ypos(y1_i)) * RECIPROCAL(MESH_Y_DIST), | ||||
|  | ||||
| @ -543,7 +543,7 @@ | ||||
|           } | ||||
|           else { | ||||
|             const float cvf = parser.value_float(); | ||||
|             switch ((int)truncf(cvf * 10.0f) - 30) {   // 3.1 -> 1
 | ||||
|             switch ((int)TRUNC(cvf * 10.0f) - 30) {   // 3.1 -> 1
 | ||||
|               #if ENABLED(UBL_G29_P31) | ||||
|                 case 1: { | ||||
| 
 | ||||
|  | ||||
| @ -2385,12 +2385,14 @@ void MarlinSettings::postprocess() { | ||||
|                                                           // or down a little bit without disrupting the mesh data
 | ||||
|     } | ||||
| 
 | ||||
|     #define MESH_STORE_SIZE sizeof(TERN(OPTIMIZED_MESH_STORAGE, mesh_store_t, ubl.z_values)) | ||||
| 
 | ||||
|     uint16_t MarlinSettings::calc_num_meshes() { | ||||
|       return (meshes_end - meshes_start_index()) / sizeof(ubl.z_values); | ||||
|       return (meshes_end - meshes_start_index()) / MESH_STORE_SIZE; | ||||
|     } | ||||
| 
 | ||||
|     int MarlinSettings::mesh_slot_offset(const int8_t slot) { | ||||
|       return meshes_end - (slot + 1) * sizeof(ubl.z_values); | ||||
|       return meshes_end - (slot + 1) * MESH_STORE_SIZE; | ||||
|     } | ||||
| 
 | ||||
|     void MarlinSettings::store_mesh(const int8_t slot) { | ||||
| @ -2407,9 +2409,17 @@ void MarlinSettings::postprocess() { | ||||
|         int pos = mesh_slot_offset(slot); | ||||
|         uint16_t crc = 0; | ||||
| 
 | ||||
|         #if ENABLED(OPTIMIZED_MESH_STORAGE) | ||||
|           int16_t z_mesh_store[GRID_MAX_POINTS_X][GRID_MAX_POINTS_Y]; | ||||
|           ubl.set_store_from_mesh(ubl.z_values, z_mesh_store); | ||||
|           uint8_t * const src = (uint8_t*)&z_mesh_store; | ||||
|         #else | ||||
|           uint8_t * const src = (uint8_t*)&ubl.z_values; | ||||
|         #endif | ||||
| 
 | ||||
|         // Write crc to MAT along with other data, or just tack on to the beginning or end
 | ||||
|         persistentStore.access_start(); | ||||
|         const bool status = persistentStore.write_data(pos, (uint8_t *)&ubl.z_values, sizeof(ubl.z_values), &crc); | ||||
|         const bool status = persistentStore.write_data(pos, src, MESH_STORE_SIZE, &crc); | ||||
|         persistentStore.access_finish(); | ||||
| 
 | ||||
|         if (status) SERIAL_ECHOLNPGM("?Unable to save mesh data."); | ||||
| @ -2435,12 +2445,27 @@ void MarlinSettings::postprocess() { | ||||
| 
 | ||||
|         int pos = mesh_slot_offset(slot); | ||||
|         uint16_t crc = 0; | ||||
|         uint8_t * const dest = into ? (uint8_t*)into : (uint8_t*)&ubl.z_values; | ||||
|         #if ENABLED(OPTIMIZED_MESH_STORAGE) | ||||
|           int16_t z_mesh_store[GRID_MAX_POINTS_X][GRID_MAX_POINTS_Y]; | ||||
|           uint8_t * const dest = (uint8_t*)&z_mesh_store; | ||||
|         #else | ||||
|           uint8_t * const dest = into ? (uint8_t*)into : (uint8_t*)&ubl.z_values; | ||||
|         #endif | ||||
| 
 | ||||
|         persistentStore.access_start(); | ||||
|         const uint16_t status = persistentStore.read_data(pos, dest, sizeof(ubl.z_values), &crc); | ||||
|         const uint16_t status = persistentStore.read_data(pos, dest, MESH_STORE_SIZE, &crc); | ||||
|         persistentStore.access_finish(); | ||||
| 
 | ||||
|         #if ENABLED(OPTIMIZED_MESH_STORAGE) | ||||
|           if (into) { | ||||
|             float z_values[GRID_MAX_POINTS_X][GRID_MAX_POINTS_Y]; | ||||
|             ubl.set_mesh_from_store(z_mesh_store, z_values); | ||||
|             memcpy(into, z_values, sizeof(z_values)); | ||||
|           } | ||||
|           else | ||||
|             ubl.set_mesh_from_store(z_mesh_store, ubl.z_values); | ||||
|         #endif | ||||
| 
 | ||||
|         if (status) SERIAL_ECHOLNPGM("?Unable to load mesh data."); | ||||
|         else        DEBUG_ECHOLNPAIR("Mesh loaded from slot ", slot); | ||||
| 
 | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user