diff --git a/Marlin/G26_Mesh_Validation_Tool.cpp b/Marlin/G26_Mesh_Validation_Tool.cpp old mode 100644 new mode 100755 index 0bf62432a1..da6a17b39b --- a/Marlin/G26_Mesh_Validation_Tool.cpp +++ b/Marlin/G26_Mesh_Validation_Tool.cpp @@ -256,8 +256,8 @@ : find_closest_circle_to_print(x_pos, y_pos); // Find the closest Mesh Intersection to where we are now. if (location.x_index >= 0 && location.y_index >= 0) { - const float circle_x = ubl.mesh_index_to_xpos[location.x_index], - circle_y = ubl.mesh_index_to_ypos[location.y_index]; + const float circle_x = pgm_read_float(&(ubl.mesh_index_to_xpos[location.x_index])), + circle_y = pgm_read_float(&(ubl.mesh_index_to_ypos[location.y_index])); // Let's do a couple of quick sanity checks. We can pull this code out later if we never see it catch a problem #ifdef DELTA @@ -399,8 +399,8 @@ for (uint8_t i = 0; i < GRID_MAX_POINTS_X; i++) { for (uint8_t j = 0; j < GRID_MAX_POINTS_Y; j++) { if (!is_bit_set(circle_flags, i, j)) { - const float mx = ubl.mesh_index_to_xpos[i], // We found a circle that needs to be printed - my = ubl.mesh_index_to_ypos[j]; + const float mx = pgm_read_float(&(ubl.mesh_index_to_xpos[i])), // We found a circle that needs to be printed + my = pgm_read_float(&(ubl.mesh_index_to_ypos[j])); // Get the distance to this intersection float f = HYPOT(X - mx, Y - my); @@ -444,11 +444,11 @@ // We found two circles that need a horizontal line to connect them // Print it! // - sx = ubl.mesh_index_to_xpos[ i ] + (SIZE_OF_INTERSECTION_CIRCLES - (SIZE_OF_CROSSHAIRS)); // right edge - ex = ubl.mesh_index_to_xpos[i + 1] - (SIZE_OF_INTERSECTION_CIRCLES - (SIZE_OF_CROSSHAIRS)); // left edge + sx = pgm_read_float(&(ubl.mesh_index_to_xpos[ i ])) + (SIZE_OF_INTERSECTION_CIRCLES - (SIZE_OF_CROSSHAIRS)); // right edge + ex = pgm_read_float(&(ubl.mesh_index_to_xpos[i + 1])) - (SIZE_OF_INTERSECTION_CIRCLES - (SIZE_OF_CROSSHAIRS)); // left edge sx = constrain(sx, X_MIN_POS + 1, X_MAX_POS - 1); - sy = ey = constrain(ubl.mesh_index_to_ypos[j], Y_MIN_POS + 1, Y_MAX_POS - 1); + sy = ey = constrain(pgm_read_float(&(ubl.mesh_index_to_ypos[j])), Y_MIN_POS + 1, Y_MAX_POS - 1); ex = constrain(ex, X_MIN_POS + 1, X_MAX_POS - 1); if (ubl.g26_debug_flag) { @@ -475,10 +475,10 @@ // We found two circles that need a vertical line to connect them // Print it! // - sy = ubl.mesh_index_to_ypos[ j ] + (SIZE_OF_INTERSECTION_CIRCLES - (SIZE_OF_CROSSHAIRS)); // top edge - ey = ubl.mesh_index_to_ypos[j + 1] - (SIZE_OF_INTERSECTION_CIRCLES - (SIZE_OF_CROSSHAIRS)); // bottom edge + sy = pgm_read_float(&(ubl.mesh_index_to_ypos[ j ])) + (SIZE_OF_INTERSECTION_CIRCLES - (SIZE_OF_CROSSHAIRS)); // top edge + ey = pgm_read_float(&(ubl.mesh_index_to_ypos[j + 1])) - (SIZE_OF_INTERSECTION_CIRCLES - (SIZE_OF_CROSSHAIRS)); // bottom edge - sx = ex = constrain(ubl.mesh_index_to_xpos[i], X_MIN_POS + 1, X_MAX_POS - 1); + sx = ex = constrain(pgm_read_float(&(ubl.mesh_index_to_xpos[i])), X_MIN_POS + 1, X_MAX_POS - 1); sy = constrain(sy, Y_MIN_POS + 1, Y_MAX_POS - 1); ey = constrain(ey, Y_MIN_POS + 1, Y_MAX_POS - 1); diff --git a/Marlin/ubl.cpp b/Marlin/ubl.cpp index 06ef9c6838..1d6e06fdab 100755 --- a/Marlin/ubl.cpp +++ b/Marlin/ubl.cpp @@ -60,9 +60,12 @@ ubl_state unified_bed_leveling::state, unified_bed_leveling::pre_initialized; float unified_bed_leveling::z_values[GRID_MAX_POINTS_X][GRID_MAX_POINTS_Y], - unified_bed_leveling::last_specified_z, - unified_bed_leveling::mesh_index_to_xpos[GRID_MAX_POINTS_X + 1], // +1 safety margin for now, until determinism prevails - unified_bed_leveling::mesh_index_to_ypos[GRID_MAX_POINTS_Y + 1]; + unified_bed_leveling::last_specified_z; + + // 15 is the maximum nubmer of grid points supported + 1 safety margin for now, + // until determinism prevails + constexpr float unified_bed_leveling::mesh_index_to_xpos[16], + unified_bed_leveling::mesh_index_to_ypos[16]; bool unified_bed_leveling::g26_debug_flag = false, unified_bed_leveling::has_control_of_lcd_panel = false; @@ -72,10 +75,6 @@ volatile int unified_bed_leveling::encoder_diff; unified_bed_leveling::unified_bed_leveling() { - for (uint8_t i = 0; i < COUNT(mesh_index_to_xpos); i++) - mesh_index_to_xpos[i] = UBL_MESH_MIN_X + i * (MESH_X_DIST); - for (uint8_t i = 0; i < COUNT(mesh_index_to_ypos); i++) - mesh_index_to_ypos[i] = UBL_MESH_MIN_Y + i * (MESH_Y_DIST); reset(); } diff --git a/Marlin/ubl.h b/Marlin/ubl.h index b168b896c6..6cc45b4871 100755 --- a/Marlin/ubl.h +++ b/Marlin/ubl.h @@ -119,12 +119,31 @@ static ubl_state state, pre_initialized; - static float z_values[GRID_MAX_POINTS_X][GRID_MAX_POINTS_Y], - mesh_index_to_xpos[GRID_MAX_POINTS_X + 1], // +1 safety margin for now, until determinism prevails - mesh_index_to_ypos[GRID_MAX_POINTS_Y + 1]; + static float z_values[GRID_MAX_POINTS_X][GRID_MAX_POINTS_Y]; - static bool g26_debug_flag, - has_control_of_lcd_panel; + // 15 is the maximum nubmer of grid points supported + 1 safety margin for now, + // until determinism prevails + constexpr static float mesh_index_to_xpos[16] PROGMEM = { UBL_MESH_MIN_X+0*(MESH_X_DIST), + UBL_MESH_MIN_X+1*(MESH_X_DIST), UBL_MESH_MIN_X+2*(MESH_X_DIST), + UBL_MESH_MIN_X+3*(MESH_X_DIST), UBL_MESH_MIN_X+4*(MESH_X_DIST), + UBL_MESH_MIN_X+5*(MESH_X_DIST), UBL_MESH_MIN_X+6*(MESH_X_DIST), + UBL_MESH_MIN_X+7*(MESH_X_DIST), UBL_MESH_MIN_X+8*(MESH_X_DIST), + UBL_MESH_MIN_X+9*(MESH_X_DIST), UBL_MESH_MIN_X+10*(MESH_X_DIST), + UBL_MESH_MIN_X+11*(MESH_X_DIST), UBL_MESH_MIN_X+12*(MESH_X_DIST), + UBL_MESH_MIN_X+13*(MESH_X_DIST), UBL_MESH_MIN_X+14*(MESH_X_DIST), + UBL_MESH_MIN_X+15*(MESH_X_DIST) }; + + constexpr static float mesh_index_to_ypos[16] PROGMEM = { UBL_MESH_MIN_Y+0*(MESH_Y_DIST), + UBL_MESH_MIN_Y+1*(MESH_Y_DIST), UBL_MESH_MIN_Y+2*(MESH_Y_DIST), + UBL_MESH_MIN_Y+3*(MESH_Y_DIST), UBL_MESH_MIN_Y+4*(MESH_Y_DIST), + UBL_MESH_MIN_Y+5*(MESH_Y_DIST), UBL_MESH_MIN_Y+6*(MESH_Y_DIST), + UBL_MESH_MIN_Y+7*(MESH_Y_DIST), UBL_MESH_MIN_Y+8*(MESH_Y_DIST), + UBL_MESH_MIN_Y+9*(MESH_Y_DIST), UBL_MESH_MIN_Y+10*(MESH_Y_DIST), + UBL_MESH_MIN_Y+11*(MESH_Y_DIST), UBL_MESH_MIN_Y+12*(MESH_Y_DIST), + UBL_MESH_MIN_Y+13*(MESH_Y_DIST), UBL_MESH_MIN_Y+14*(MESH_Y_DIST), + UBL_MESH_MIN_Y+15*(MESH_Y_DIST) }; + + static bool g26_debug_flag, has_control_of_lcd_panel; static int8_t eeprom_start; @@ -204,7 +223,7 @@ return NAN; } - const float xratio = (RAW_X_POSITION(lx0) - mesh_index_to_xpos[x1_i]) * (1.0 / (MESH_X_DIST)), + const float xratio = (RAW_X_POSITION(lx0) - pgm_read_float(&mesh_index_to_xpos[x1_i])) * (1.0 / (MESH_X_DIST)), z1 = z_values[x1_i][yi]; return z1 + xratio * (z_values[x1_i + 1][yi] - z1); @@ -223,7 +242,7 @@ return NAN; } - const float yratio = (RAW_Y_POSITION(ly0) - mesh_index_to_ypos[y1_i]) * (1.0 / (MESH_Y_DIST)), + const float yratio = (RAW_Y_POSITION(ly0) - pgm_read_float(&mesh_index_to_ypos[y1_i])) * (1.0 / (MESH_Y_DIST)), z1 = z_values[xi][y1_i]; return z1 + yratio * (z_values[xi][y1_i + 1] - z1); @@ -254,14 +273,16 @@ } const float z1 = calc_z0(RAW_X_POSITION(lx0), - mesh_index_to_xpos[cx], z_values[cx][cy], - mesh_index_to_xpos[cx + 1], z_values[cx + 1][cy]), - z2 = calc_z0(RAW_X_POSITION(lx0), - mesh_index_to_xpos[cx], z_values[cx][cy + 1], - mesh_index_to_xpos[cx + 1], z_values[cx + 1][cy + 1]); - float z0 = calc_z0(RAW_Y_POSITION(ly0), - mesh_index_to_ypos[cy], z1, - mesh_index_to_ypos[cy + 1], z2); + pgm_read_float(&mesh_index_to_xpos[cx]), z_values[cx][cy], + pgm_read_float(&mesh_index_to_xpos[cx + 1]), z_values[cx + 1][cy]); + + const float z2 = calc_z0(RAW_X_POSITION(lx0), + pgm_read_float(&mesh_index_to_xpos[cx]), z_values[cx][cy + 1], + pgm_read_float(&mesh_index_to_xpos[cx + 1]), z_values[cx + 1][cy + 1]); + + float z0 = calc_z0(RAW_Y_POSITION(ly0), + pgm_read_float(&mesh_index_to_ypos[cy]), z1, + pgm_read_float(&mesh_index_to_ypos[cy + 1]), z2); #if ENABLED(DEBUG_LEVELING_FEATURE) if (DEBUGGING(MESH_ADJUST)) { diff --git a/Marlin/ubl_G29.cpp b/Marlin/ubl_G29.cpp index 1fd0334b8d..ccd5035f15 100755 --- a/Marlin/ubl_G29.cpp +++ b/Marlin/ubl_G29.cpp @@ -757,8 +757,8 @@ 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 if (location.x_index >= 0 && location.y_index >= 0) { - const float rawx = ubl.mesh_index_to_xpos[location.x_index], - rawy = ubl.mesh_index_to_ypos[location.y_index]; + const float rawx = pgm_read_float(&(ubl.mesh_index_to_xpos[location.x_index])), + rawy = pgm_read_float(&(ubl.mesh_index_to_ypos[location.y_index])); // TODO: Change to use `position_is_reachable` (for SCARA-compatibility) if (!WITHIN(rawx, MIN_PROBE_X, MAX_PROBE_X) || !WITHIN(rawy, MIN_PROBE_Y, MAX_PROBE_Y)) { @@ -905,8 +905,8 @@ // It doesn't matter if the probe can't reach the NAN location. This is a manual probe. if (location.x_index < 0 && location.y_index < 0) continue; - const float rawx = ubl.mesh_index_to_xpos[location.x_index], - rawy = ubl.mesh_index_to_ypos[location.y_index]; + const float rawx = pgm_read_float(&(ubl.mesh_index_to_xpos[location.x_index])), + rawy = pgm_read_float(&(ubl.mesh_index_to_ypos[location.y_index])); // TODO: Change to use `position_is_reachable` (for SCARA-compatibility) if (!WITHIN(rawx, X_MIN_POS, X_MAX_POS) || !WITHIN(rawy, Y_MIN_POS, Y_MAX_POS)) { @@ -1174,7 +1174,7 @@ SERIAL_PROTOCOLPGM("X-Axis Mesh Points at: "); for (uint8_t i = 0; i < GRID_MAX_POINTS_X; i++) { - SERIAL_PROTOCOL_F(LOGICAL_X_POSITION(ubl.mesh_index_to_xpos[i]), 1); + SERIAL_PROTOCOL_F(LOGICAL_X_POSITION(pgm_read_float(&(ubl.mesh_index_to_xpos[i]))), 1); SERIAL_PROTOCOLPGM(" "); safe_delay(50); } @@ -1182,7 +1182,7 @@ SERIAL_PROTOCOLPGM("Y-Axis Mesh Points at: "); for (uint8_t i = 0; i < GRID_MAX_POINTS_Y; i++) { - SERIAL_PROTOCOL_F(LOGICAL_Y_POSITION(ubl.mesh_index_to_ypos[i]), 1); + SERIAL_PROTOCOL_F(LOGICAL_Y_POSITION(pgm_read_float(&(ubl.mesh_index_to_ypos[i]))), 1); SERIAL_PROTOCOLPGM(" "); safe_delay(50); } @@ -1320,8 +1320,8 @@ // We only get here if we found a Mesh Point of the specified type - const float rawx = ubl.mesh_index_to_xpos[i], // Check if we can probe this mesh location - rawy = ubl.mesh_index_to_ypos[j]; + const float rawx = pgm_read_float(&(ubl.mesh_index_to_xpos[i])), // Check if we can probe this mesh location + rawy = pgm_read_float(&(ubl.mesh_index_to_ypos[j])); // If using the probe as the reference there are some unreachable locations. // Prune them from the list and ignore them till the next Phase (manual nozzle probing). @@ -1386,8 +1386,8 @@ bit_clear(not_done, location.x_index, location.y_index); // Mark this location as 'adjusted' so we will find a // different location the next time through the loop - const float rawx = ubl.mesh_index_to_xpos[location.x_index], - rawy = ubl.mesh_index_to_ypos[location.y_index]; + const float rawx = pgm_read_float(&(ubl.mesh_index_to_xpos[location.x_index])), + rawy = pgm_read_float(&(ubl.mesh_index_to_ypos[location.y_index])); // TODO: Change to use `position_is_reachable` (for SCARA-compatibility) if (!WITHIN(rawx, X_MIN_POS, X_MAX_POS) || !WITHIN(rawy, Y_MIN_POS, Y_MAX_POS)) { // In theory, we don't need this check. @@ -1482,7 +1482,8 @@ //find min & max probeable points in the mesh for (xCount = 0; xCount < GRID_MAX_POINTS_X; xCount++) { for (yCount = 0; yCount < GRID_MAX_POINTS_Y; yCount++) { - if (WITHIN(ubl.mesh_index_to_xpos[xCount], MIN_PROBE_X, MAX_PROBE_X) && WITHIN(ubl.mesh_index_to_ypos[yCount], MIN_PROBE_Y, MAX_PROBE_Y)) { + if (WITHIN(pgm_read_float(&(ubl.mesh_index_to_xpos[xCount])), MIN_PROBE_X, MAX_PROBE_X) && + WITHIN(pgm_read_float(&(ubl.mesh_index_to_ypos[yCount])), MIN_PROBE_Y, MAX_PROBE_Y)) { NOMORE(x_min, xCount); NOLESS(x_max, xCount); NOMORE(y_min, yCount); @@ -1577,11 +1578,12 @@ } //SERIAL_ECHOPAIR("\nCheckpoint: ", 5); - const float probeX = ubl.mesh_index_to_xpos[grid_G_index_to_xpos[xCount]], //where we want the probe to be - probeY = ubl.mesh_index_to_ypos[grid_G_index_to_ypos[yCount]]; + const float probeX = pgm_read_float(&(ubl.mesh_index_to_xpos[grid_G_index_to_xpos[xCount]])), //where we want the probe to be + probeY = pgm_read_float(&(ubl.mesh_index_to_ypos[grid_G_index_to_ypos[yCount]])); //SERIAL_ECHOPAIR("\nCheckpoint: ", 6); - const float measured_z = probe_pt(LOGICAL_X_POSITION(probeX), LOGICAL_Y_POSITION(probeY), code_seen('E'), (code_seen('V') && code_has_value()) ? code_value_int() : 0); // takes into account the offsets + const float measured_z = probe_pt(LOGICAL_X_POSITION(probeX), LOGICAL_Y_POSITION(probeY), code_seen('E'), + (code_seen('V') && code_has_value()) ? code_value_int() : 0); // takes into account the offsets //SERIAL_ECHOPAIR("\nmeasured_z: ", measured_z); @@ -1595,7 +1597,7 @@ restore_ubl_active_state_and_leave(); // ?? ubl.has_control_of_lcd_panel = true; - //do_blocking_move_to_xy(ubl.mesh_index_to_xpos[grid_G_index_to_xpos[0]], ubl.mesh_index_to_ypos[grid_G_index_to_ypos[0]]); + //do_blocking_move_to_xy(pgm_read_float(&(ubl.mesh_index_to_xpos[grid_G_index_to_xpos[0]])),pgm_read_float(&(ubl.mesh_index_to_ypos[grid_G_index_to_ypos[0]]))); // least squares code double xxx5[] = { 0,50,100,150,200, 20,70,120,165,195, 0,50,100,150,200, 0,55,100,150,200, 0,65,100,150,205 }, diff --git a/Marlin/ubl_motion.cpp b/Marlin/ubl_motion.cpp old mode 100644 new mode 100755 index 9847dfea87..7325a5cf2c --- a/Marlin/ubl_motion.cpp +++ b/Marlin/ubl_motion.cpp @@ -154,7 +154,7 @@ * to create a 1-over number for us. That will allow us to do a floating point multiply instead of a floating point divide. */ - const float xratio = (RAW_X_POSITION(end[X_AXIS]) - ubl.mesh_index_to_xpos[cell_dest_xi]) * (1.0 / (MESH_X_DIST)), + const float xratio = (RAW_X_POSITION(end[X_AXIS]) - pgm_read_float(&(ubl.mesh_index_to_xpos[cell_dest_xi]))) * (1.0 / (MESH_X_DIST)), z1 = ubl.z_values[cell_dest_xi ][cell_dest_yi ] + xratio * (ubl.z_values[cell_dest_xi + 1][cell_dest_yi ] - ubl.z_values[cell_dest_xi][cell_dest_yi ]), z2 = ubl.z_values[cell_dest_xi ][cell_dest_yi + 1] + xratio * @@ -163,7 +163,7 @@ // we are done with the fractional X distance into the cell. Now with the two Z-Heights we have calculated, we // are going to apply the Y-Distance into the cell to interpolate the final Z correction. - const float yratio = (RAW_Y_POSITION(end[Y_AXIS]) - ubl.mesh_index_to_ypos[cell_dest_yi]) * (1.0 / (MESH_Y_DIST)); + const float yratio = (RAW_Y_POSITION(end[Y_AXIS]) - pgm_read_float(&(ubl.mesh_index_to_ypos[cell_dest_yi]))) * (1.0 / (MESH_Y_DIST)); float z0 = z1 + (z2 - z1) * yratio; @@ -262,7 +262,7 @@ current_yi += down_flag; // Line is heading down, we just want to go to the bottom while (current_yi != cell_dest_yi + down_flag) { current_yi += dyi; - const float next_mesh_line_y = LOGICAL_Y_POSITION(ubl.mesh_index_to_ypos[current_yi]); + const float next_mesh_line_y = LOGICAL_Y_POSITION(pgm_read_float(&(ubl.mesh_index_to_ypos[current_yi]))); /** * inf_m_flag? the slope of the line is infinite, we won't do the calculations @@ -304,7 +304,7 @@ */ if (isnan(z0)) z0 = 0.0; - const float y = LOGICAL_Y_POSITION(ubl.mesh_index_to_ypos[current_yi]); + const float y = LOGICAL_Y_POSITION(pgm_read_float(&(ubl.mesh_index_to_ypos[current_yi]))); /** * Without this check, it is possible for the algorithm to generate a zero length move in the case @@ -353,7 +353,7 @@ // edge of this cell for the first move. while (current_xi != cell_dest_xi + left_flag) { current_xi += dxi; - const float next_mesh_line_x = LOGICAL_X_POSITION(ubl.mesh_index_to_xpos[current_xi]), + const float next_mesh_line_x = LOGICAL_X_POSITION(pgm_read_float(&(ubl.mesh_index_to_xpos[current_xi]))), y = m * next_mesh_line_x + c; // Calculate X at the next Y mesh line float z0 = ubl.z_correction_for_y_on_vertical_mesh_line(y, current_xi, current_yi); @@ -389,7 +389,7 @@ */ if (isnan(z0)) z0 = 0.0; - const float x = LOGICAL_X_POSITION(ubl.mesh_index_to_xpos[current_xi]); + const float x = LOGICAL_X_POSITION(pgm_read_float(&(ubl.mesh_index_to_xpos[current_xi]))); /** * Without this check, it is possible for the algorithm to generate a zero length move in the case @@ -439,8 +439,8 @@ while (xi_cnt > 0 || yi_cnt > 0) { - const float next_mesh_line_x = LOGICAL_X_POSITION(ubl.mesh_index_to_xpos[current_xi + dxi]), - next_mesh_line_y = LOGICAL_Y_POSITION(ubl.mesh_index_to_ypos[current_yi + dyi]), + const float next_mesh_line_x = LOGICAL_X_POSITION(pgm_read_float(&(ubl.mesh_index_to_xpos[current_xi + dxi]))), + next_mesh_line_y = LOGICAL_Y_POSITION(pgm_read_float(&(ubl.mesh_index_to_ypos[current_yi + dyi]))), y = m * next_mesh_line_x + c, // Calculate Y at the next X mesh line x = (next_mesh_line_y - c) / m; // Calculate X at the next Y mesh line // (No need to worry about m being zero.