From de725a902d40a05f2376afd201c8cf6200a957a2 Mon Sep 17 00:00:00 2001 From: Marcio Teixeira Date: Mon, 29 Mar 2021 14:57:08 -0600 Subject: [PATCH 01/25] Fix for "G29 P1 X0 Y0" not starting in correct grid point - Fixed probe offset being applied twice --- Marlin/src/feature/bedlevel/ubl/ubl_G29.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/Marlin/src/feature/bedlevel/ubl/ubl_G29.cpp b/Marlin/src/feature/bedlevel/ubl/ubl_G29.cpp index 2003e9b6f560..ed98e5787494 100644 --- a/Marlin/src/feature/bedlevel/ubl/ubl_G29.cpp +++ b/Marlin/src/feature/bedlevel/ubl/ubl_G29.cpp @@ -433,8 +433,7 @@ void unified_bed_leveling::G29() { SERIAL_DECIMAL(param.XY_pos.y); SERIAL_ECHOLNPGM(").\n"); } - const xy_pos_t near_probe_xy = param.XY_pos + probe.offset_xy; - probe_entire_mesh(near_probe_xy, parser.seen('T'), parser.seen('E'), parser.seen('U')); + probe_entire_mesh(param.XY_pos, parser.seen('T'), parser.seen('E'), parser.seen('U')); report_current_position(); probe_deployed = true; From 45ec55dcd101527b0532d5a1c5e661b1024c90ac Mon Sep 17 00:00:00 2001 From: Marcio Teixeira Date: Mon, 29 Mar 2021 15:09:51 -0600 Subject: [PATCH 02/25] Start UBL_HILBERT_CURVE at lower-left --- Marlin/src/feature/bedlevel/ubl/ubl_G29.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/Marlin/src/feature/bedlevel/ubl/ubl_G29.cpp b/Marlin/src/feature/bedlevel/ubl/ubl_G29.cpp index ed98e5787494..c0396e00f58d 100644 --- a/Marlin/src/feature/bedlevel/ubl/ubl_G29.cpp +++ b/Marlin/src/feature/bedlevel/ubl/ubl_G29.cpp @@ -1139,8 +1139,9 @@ bool unified_bed_leveling::G29_parse_parameters() { } // If X or Y are not valid, use center of the bed values - if (!COORDINATE_OKAY(sx, X_MIN_BED, X_MAX_BED)) sx = X_CENTER; - if (!COORDINATE_OKAY(sy, Y_MIN_BED, Y_MAX_BED)) sy = Y_CENTER; + // (for UBL_HILBERT_CURVE default to lower-left corner instead) + if (!COORDINATE_OKAY(sx, X_MIN_BED, X_MAX_BED)) sx = TERN(UBL_HILBERT_CURVE, 0, X_CENTER); + if (!COORDINATE_OKAY(sy, Y_MIN_BED, Y_MAX_BED)) sy = TERN(UBL_HILBERT_CURVE, 0, Y_CENTER); if (err_flag) return UBL_ERR; From fa0ba034e39807e09479cdb76ae4305115c78857 Mon Sep 17 00:00:00 2001 From: Marcio Teixeira Date: Mon, 29 Mar 2021 15:21:37 -0600 Subject: [PATCH 03/25] Allow G26 to use UBL_HILBERT_CURVE --- Marlin/src/gcode/bedlevel/G26.cpp | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/Marlin/src/gcode/bedlevel/G26.cpp b/Marlin/src/gcode/bedlevel/G26.cpp index 0468b79363bb..0dfbee207356 100644 --- a/Marlin/src/gcode/bedlevel/G26.cpp +++ b/Marlin/src/gcode/bedlevel/G26.cpp @@ -113,6 +113,10 @@ #include "../../module/temperature.h" #include "../../lcd/marlinui.h" +#if ENABLED(UBL_HILBERT_CURVE) + #include "../../feature/bedlevel/hilbert_curve.h" +#endif + #define EXTRUSION_MULTIPLIER 1.0 #define PRIME_LENGTH 10.0 #define OOZE_AMOUNT 0.3 @@ -178,6 +182,24 @@ int8_t g26_prime_flag; #endif +#if ENABLED(UBL_HILBERT_CURVE) +static bool test_func(uint8_t i, uint8_t j, void *data) { + if (!circle_flags.marked(i, j)) { + mesh_index_pair *out_point = (mesh_index_pair *) data; + out_point->pos.set(i, j); // Save its data + return true; + } + return false; +} + +mesh_index_pair find_closest_circle_to_print(const xy_pos_t &pos) { + mesh_index_pair out_point; + out_point.pos = -1; + hilbert_curve::search_from_closest(pos, test_func, &out_point); + circle_flags.mark(out_point); // Mark this location as done. + return out_point; +} +#else mesh_index_pair find_closest_circle_to_print(const xy_pos_t &pos) { float closest = 99999.99; mesh_index_pair out_point; @@ -211,6 +233,7 @@ mesh_index_pair find_closest_circle_to_print(const xy_pos_t &pos) { circle_flags.mark(out_point); // Mark this location as done. return out_point; } +#endif void move_to(const float &rx, const float &ry, const float &z, const float &e_delta) { static float last_z = -999.99; @@ -878,3 +901,4 @@ void GcodeSuite::G26() { } #endif // G26_MESH_VALIDATION + From c1d6fb9254ddf2029791461e77f0b48c69b27e13 Mon Sep 17 00:00:00 2001 From: Scott Lahteine Date: Mon, 29 Mar 2021 22:01:00 -0500 Subject: [PATCH 04/25] reformat --- Marlin/src/gcode/bedlevel/G26.cpp | 85 +++++++++++++++---------------- 1 file changed, 42 insertions(+), 43 deletions(-) diff --git a/Marlin/src/gcode/bedlevel/G26.cpp b/Marlin/src/gcode/bedlevel/G26.cpp index 0dfbee207356..b66680ac6257 100644 --- a/Marlin/src/gcode/bedlevel/G26.cpp +++ b/Marlin/src/gcode/bedlevel/G26.cpp @@ -182,58 +182,58 @@ int8_t g26_prime_flag; #endif -#if ENABLED(UBL_HILBERT_CURVE) -static bool test_func(uint8_t i, uint8_t j, void *data) { - if (!circle_flags.marked(i, j)) { - mesh_index_pair *out_point = (mesh_index_pair *) data; - out_point->pos.set(i, j); // Save its data - return true; - } - return false; -} - mesh_index_pair find_closest_circle_to_print(const xy_pos_t &pos) { + mesh_index_pair out_point; out_point.pos = -1; - hilbert_curve::search_from_closest(pos, test_func, &out_point); - circle_flags.mark(out_point); // Mark this location as done. - return out_point; -} -#else -mesh_index_pair find_closest_circle_to_print(const xy_pos_t &pos) { - float closest = 99999.99; - mesh_index_pair out_point; - out_point.pos = -1; + #if ENABLED(UBL_HILBERT_CURVE) - GRID_LOOP(i, j) { - if (!circle_flags.marked(i, j)) { - // We found a circle that needs to be printed - const xy_pos_t m = { _GET_MESH_X(i), _GET_MESH_Y(j) }; - - // Get the distance to this intersection - float f = (pos - m).magnitude(); - - // It is possible that we are being called with the values - // to let us find the closest circle to the start position. - // But if this is not the case, add a small weighting to the - // distance calculation to help it choose a better place to continue. - f += (g26_xy_pos - m).magnitude() / 15.0f; - - // Add the specified amount of Random Noise to our search - if (g26_random_deviation > 1.0) f += random(0.0, g26_random_deviation); - - if (f < closest) { - closest = f; // Found a closer un-printed location - out_point.pos.set(i, j); // Save its data - out_point.distance = closest; + auto test_func = [](uint8_t i, uint8_t j, void *data) { + if (!circle_flags.marked(i, j)) { + mesh_index_pair *out_point = (mesh_index_pair*)data; + out_point->pos.set(i, j); // Save its data + return true; } + return false; } - } + + hilbert_curve::search_from_closest(pos, test_func, &out_point); + + #else + + float closest = 99999.99; + + GRID_LOOP(i, j) { + if (!circle_flags.marked(i, j)) { + // We found a circle that needs to be printed + const xy_pos_t m = { _GET_MESH_X(i), _GET_MESH_Y(j) }; + + // Get the distance to this intersection + float f = (pos - m).magnitude(); + + // It is possible that we are being called with the values + // to let us find the closest circle to the start position. + // But if this is not the case, add a small weighting to the + // distance calculation to help it choose a better place to continue. + f += (g26_xy_pos - m).magnitude() / 15.0f; + + // Add the specified amount of Random Noise to our search + if (g26_random_deviation > 1.0) f += random(0.0, g26_random_deviation); + + if (f < closest) { + closest = f; // Found a closer un-printed location + out_point.pos.set(i, j); // Save its data + out_point.distance = closest; + } + } + } + + #endif + circle_flags.mark(out_point); // Mark this location as done. return out_point; } -#endif void move_to(const float &rx, const float &ry, const float &z, const float &e_delta) { static float last_z = -999.99; @@ -901,4 +901,3 @@ void GcodeSuite::G26() { } #endif // G26_MESH_VALIDATION - From 52f3fd186a17257c78b1124a847986a412ef32f3 Mon Sep 17 00:00:00 2001 From: Scott Lahteine Date: Mon, 29 Mar 2021 22:31:19 -0500 Subject: [PATCH 05/25] Use less SRAM --- Marlin/src/gcode/bedlevel/G26.cpp | 112 ++++++++++++++---------------- 1 file changed, 54 insertions(+), 58 deletions(-) diff --git a/Marlin/src/gcode/bedlevel/G26.cpp b/Marlin/src/gcode/bedlevel/G26.cpp index b66680ac6257..aa3e00d21c18 100644 --- a/Marlin/src/gcode/bedlevel/G26.cpp +++ b/Marlin/src/gcode/bedlevel/G26.cpp @@ -155,18 +155,6 @@ float g26_random_deviation = 0.0; static bool g26_retracted = false; // Track the retracted state of the nozzle so mismatched // retracts/recovers won't result in a bad state. -float g26_extrusion_multiplier, - g26_retraction_multiplier, - g26_layer_height, - g26_prime_length; - -xy_pos_t g26_xy_pos; // = { 0, 0 } - -int16_t g26_bed_temp, - g26_hotend_temp; - -int8_t g26_prime_flag; - #if HAS_LCD_MENU /** @@ -182,7 +170,7 @@ int8_t g26_prime_flag; #endif -mesh_index_pair find_closest_circle_to_print(const xy_pos_t &pos) { +mesh_index_pair find_closest_circle_to_print(const xy_pos_t &pos, const xy_pos_t &command_pos) { mesh_index_pair out_point; out_point.pos = -1; @@ -216,7 +204,7 @@ mesh_index_pair find_closest_circle_to_print(const xy_pos_t &pos) { // to let us find the closest circle to the start position. // But if this is not the case, add a small weighting to the // distance calculation to help it choose a better place to continue. - f += (g26_xy_pos - m).magnitude() / 15.0f; + f += (command_pos - m).magnitude() / 15.0f; // Add the specified amount of Random Noise to our search if (g26_random_deviation > 1.0) f += random(0.0, g26_random_deviation); @@ -264,23 +252,23 @@ void move_to(const float &rx, const float &ry, const float &z, const float &e_de FORCE_INLINE void move_to(const xyz_pos_t &where, const float &de) { move_to(where.x, where.y, where.z, de); } -void retract_filament(const xyz_pos_t &where) { +void retract_filament(const xyz_pos_t &where, const float &retraction_multiplier) { if (!g26_retracted) { // Only retract if we are not already retracted! g26_retracted = true; - move_to(where, -1.0f * g26_retraction_multiplier); + move_to(where, -1.0f * retraction_multiplier); } } // TODO: Parameterize the Z lift with a define -void retract_lift_move(const xyz_pos_t &s) { - retract_filament(destination); - move_to(current_position.x, current_position.y, current_position.z + 0.5f, 0.0); // Z lift to minimize scraping - move_to(s.x, s.y, s.z + 0.5f, 0.0); // Get to the starting point with no extrusion while lifted +void retract_lift_move(const xyz_pos_t &s, const float &retraction_multiplier) { + retract_filament(destination, retraction_multiplier); + move_to(current_position.x, current_position.y, current_position.z + 0.5f, 0.0f); // Z lift to minimize scraping + move_to(s.x, s.y, s.z + 0.5f, 0.0f); // Get to the starting point with no extrusion while lifted } -void recover_filament(const xyz_pos_t &where) { +void recover_filament(const xyz_pos_t &where, const float &retraction_multiplier) { if (g26_retracted) { // Only un-retract if we are retracted. - move_to(where, 1.2f * g26_retraction_multiplier); + move_to(where, 1.2f * retraction_multiplier); g26_retracted = false; } } @@ -300,7 +288,7 @@ void recover_filament(const xyz_pos_t &where) { * segment of a 'circle'. The time this requires is very short and is easily saved by the other * cases where the optimization comes into play. */ -void print_line_from_here_to_there(const xyz_pos_t &s, const xyz_pos_t &e) { +void print_line_from_here_to_there(const xyz_pos_t &s, const xyz_pos_t &e, const float &extrusion_multiplier, const float &retraction_multiplier) { // Distances to the start / end of the line xy_float_t svec = current_position - s, evec = current_position - e; @@ -312,22 +300,22 @@ void print_line_from_here_to_there(const xyz_pos_t &s, const xyz_pos_t &e) { // If the end point of the line is closer to the nozzle, flip the direction, // moving from the end to the start. On very small lines the optimization isn't worth it. if (dist_end < dist_start && (INTERSECTION_CIRCLE_RADIUS) < ABS(line_length)) - return print_line_from_here_to_there(e, s); + return print_line_from_here_to_there(e, s, extrusion_multiplier, retraction_multiplier); // Decide whether to retract & lift - if (dist_start > 2.0) retract_lift_move(s); + if (dist_start > 2.0) retract_lift_move(s, retraction_multiplier); move_to(s, 0.0); // Get to the starting point with no extrusion / un-Z lift - const float e_pos_delta = line_length * g26_e_axis_feedrate * g26_extrusion_multiplier; + const float e_pos_delta = line_length * g26_e_axis_feedrate * extrusion_multiplier; - recover_filament(destination); + recover_filament(destination, retraction_multiplier); move_to(e, e_pos_delta); // Get to the ending point with an appropriate amount of extrusion } -inline bool look_for_lines_to_connect() { +inline bool look_for_lines_to_connect(const float &layer_height, const float &extrusion_multiplier, const float &retraction_multiplier) { xyz_pos_t s, e; - s.z = e.z = g26_layer_height; + s.z = e.z = layer_height; GRID_LOOP(i, j) { @@ -351,7 +339,7 @@ inline bool look_for_lines_to_connect() { #endif if (position_is_reachable(s.x, s.y) && position_is_reachable(e.x, e.y)) - print_line_from_here_to_there(s, e); + print_line_from_here_to_there(s, e, extrusion_multiplier, retraction_multiplier); horizontal_mesh_line_flags.mark(i, j); // Mark done, even if skipped } @@ -375,7 +363,7 @@ inline bool look_for_lines_to_connect() { #endif if (position_is_reachable(s.x, s.y) && position_is_reachable(e.x, e.y)) - print_line_from_here_to_there(s, e); + print_line_from_here_to_there(s, e, extrusion_multiplier, retraction_multiplier); vertical_mesh_line_flags.mark(i, j); // Mark done, even if skipped } @@ -390,19 +378,19 @@ inline bool look_for_lines_to_connect() { * Turn on the bed and nozzle heat and * wait for them to get up to temperature. */ -inline bool turn_on_heaters() { +inline bool turn_on_heaters(const celsius_t hotend_temp, const celsius_t bed_temp) { SERIAL_ECHOLNPGM("Waiting for heatup."); #if HAS_HEATED_BED - if (g26_bed_temp > 25) { + if (bed_temp > 25) { #if HAS_WIRED_LCD ui.set_status_P(GET_TEXT(MSG_G26_HEATING_BED), 99); ui.quick_feedback(); TERN_(HAS_LCD_MENU, ui.capture()); #endif - thermalManager.setTargetBed(g26_bed_temp); + thermalManager.setTargetBed(bed_temp); // Wait for the temperature to stabilize if (!thermalManager.wait_for_bed(true @@ -413,6 +401,10 @@ inline bool turn_on_heaters() { ) return G26_ERR; } + #else + + UNUSED(bed_temp); + #endif // HAS_HEATED_BED // Start heating the active nozzle @@ -420,7 +412,7 @@ inline bool turn_on_heaters() { ui.set_status_P(GET_TEXT(MSG_G26_HEATING_NOZZLE), 99); ui.quick_feedback(); #endif - thermalManager.setTargetHotend(g26_hotend_temp, active_extruder); + thermalManager.setTargetHotend(hotend_temp, active_extruder); // Wait for the temperature to stabilize if (!thermalManager.wait_for_hotend(active_extruder, true @@ -440,7 +432,7 @@ inline bool turn_on_heaters() { /** * Prime the nozzle if needed. Return true on error. */ -inline bool prime_nozzle() { +inline bool prime_nozzle(const int8_t prime_flag, const float &prime_length, const float &retraction_multiplier) { const feedRate_t fr_slow_e = planner.settings.max_feedrate_mm_s[E_AXIS] / 15.0f; #if HAS_LCD_MENU && !HAS_TOUCH_BUTTONS // ui.button_pressed issue with touchscreen @@ -448,14 +440,14 @@ inline bool prime_nozzle() { float Total_Prime = 0.0; #endif - if (g26_prime_flag == -1) { // The user wants to control how much filament gets purged + if (prime_flag == -1) { // The user wants to control how much filament gets purged ui.capture(); ui.set_status_P(GET_TEXT(MSG_G26_MANUAL_PRIME), 99); ui.chirp(); destination = current_position; - recover_filament(destination); // Make sure G26 doesn't think the filament is retracted(). + recover_filament(destination, retraction_multiplier); // Make sure G26 doesn't think the filament is retracted(). while (!ui.button_pressed()) { ui.chirp(); @@ -489,10 +481,10 @@ inline bool prime_nozzle() { ui.quick_feedback(); #endif destination = current_position; - destination.e += g26_prime_length; + destination.e += prime_length; prepare_internal_move_to_destination(fr_slow_e); - destination.e -= g26_prime_length; - retract_filament(destination); + destination.e -= prime_length; + retract_filament(destination, retraction_multiplier); } return G26_OK; @@ -533,13 +525,15 @@ void GcodeSuite::G26() { // Change the tool first, if specified if (parser.seenval('T')) tool_change(parser.value_int()); - g26_extrusion_multiplier = EXTRUSION_MULTIPLIER; - g26_retraction_multiplier = G26_RETRACT_MULTIPLIER; - g26_layer_height = MESH_TEST_LAYER_HEIGHT; - g26_prime_length = PRIME_LENGTH; - g26_bed_temp = MESH_TEST_BED_TEMP; - g26_hotend_temp = MESH_TEST_HOTEND_TEMP; - g26_prime_flag = 0; + float g26_extrusion_multiplier = EXTRUSION_MULTIPLIER, + g26_retraction_multiplier = G26_RETRACT_MULTIPLIER, + g26_layer_height = MESH_TEST_LAYER_HEIGHT, + g26_prime_length = PRIME_LENGTH; + + int16_t g26_hotend_temp = MESH_TEST_HOTEND_TEMP, + g26_bed_temp = MESH_TEST_BED_TEMP; + + int8_t g26_prime_flag = 0; float g26_nozzle = MESH_TEST_NOZZLE_SIZE, g26_filament_diameter = DEFAULT_NOMINAL_FILAMENT_DIA, @@ -683,8 +677,10 @@ void GcodeSuite::G26() { } // Set a position with 'X' and/or 'Y'. Default: current_position - g26_xy_pos.set(parser.seenval('X') ? RAW_X_POSITION(parser.value_linear_units()) : current_position.x, - parser.seenval('Y') ? RAW_Y_POSITION(parser.value_linear_units()) : current_position.y); + xy_pos_t g26_xy_pos = { + parser.seenval('X') ? RAW_X_POSITION(parser.value_linear_units()) : current_position.x, + parser.seenval('Y') ? RAW_Y_POSITION(parser.value_linear_units()) : current_position.y + }; if (!position_is_reachable(g26_xy_pos)) { SERIAL_ECHOLNPGM("?Specified X,Y coordinate out of bounds."); return; @@ -703,12 +699,12 @@ void GcodeSuite::G26() { planner.calculate_volumetric_multipliers(); #endif - if (turn_on_heaters() != G26_OK) goto LEAVE; + if (turn_on_heaters(g26_hotend_temp, g26_bed_temp) != G26_OK) goto LEAVE; current_position.e = 0.0; sync_plan_position_e(); - if (g26_prime_flag && prime_nozzle() != G26_OK) goto LEAVE; + if (g26_prime_flag && prime_nozzle(g26_prime_flag, g26_prime_length, g26_retraction_multiplier) != G26_OK) goto LEAVE; /** * Bed is preheated @@ -755,7 +751,7 @@ void GcodeSuite::G26() { mesh_index_pair location; do { // Find the nearest confluence - location = find_closest_circle_to_print(g26_continue_with_closest ? xy_pos_t(current_position) : g26_xy_pos); + location = find_closest_circle_to_print(g26_continue_with_closest ? xy_pos_t(current_position) : g26_xy_pos, g26_xy_pos); if (location.valid()) { const xy_pos_t circle = _GET_MESH_POS(location.pos); @@ -811,13 +807,13 @@ void GcodeSuite::G26() { if (dist_start > 2.0) { s.z = g26_layer_height + 0.5f; - retract_lift_move(s); + retract_lift_move(s, g26_retraction_multiplier); } s.z = g26_layer_height; move_to(s, 0.0); // Get to the starting point with no extrusion / un-Z lift - recover_filament(destination); + recover_filament(destination, g26_retraction_multiplier); const feedRate_t old_feedrate = feedrate_mm_s; feedrate_mm_s = PLANNER_XY_FEEDRATE() * 0.1f; @@ -864,13 +860,13 @@ void GcodeSuite::G26() { LIMIT(q.y, Y_MIN_POS + 1, Y_MAX_POS - 1); #endif - print_line_from_here_to_there(p, q); + print_line_from_here_to_there(p, q, g26_extrusion_multiplier, g26_retraction_multiplier); SERIAL_FLUSH(); // Prevent host M105 buffer overrun. } #endif // !ARC_SUPPORT - if (look_for_lines_to_connect()) goto LEAVE; + if (look_for_lines_to_connect(g26_layer_height, g26_extrusion_multiplier, g26_retraction_multiplier)) goto LEAVE; } SERIAL_FLUSH(); // Prevent host M105 buffer overrun. @@ -880,7 +876,7 @@ void GcodeSuite::G26() { LEAVE: ui.set_status_P(GET_TEXT(MSG_G26_LEAVING), -1); - retract_filament(destination); + retract_filament(destination, g26_retraction_multiplier); destination.z = Z_CLEARANCE_BETWEEN_PROBES; move_to(destination, 0); // Raise the nozzle From e2565cc379c8a5c059b3787beb8ebc9a437fbdbd Mon Sep 17 00:00:00 2001 From: Scott Lahteine Date: Mon, 29 Mar 2021 22:33:58 -0500 Subject: [PATCH 06/25] etc. --- Marlin/src/gcode/bedlevel/G26.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Marlin/src/gcode/bedlevel/G26.cpp b/Marlin/src/gcode/bedlevel/G26.cpp index aa3e00d21c18..757e5520c454 100644 --- a/Marlin/src/gcode/bedlevel/G26.cpp +++ b/Marlin/src/gcode/bedlevel/G26.cpp @@ -677,7 +677,7 @@ void GcodeSuite::G26() { } // Set a position with 'X' and/or 'Y'. Default: current_position - xy_pos_t g26_xy_pos = { + const xy_pos_t g26_xy_pos = { parser.seenval('X') ? RAW_X_POSITION(parser.value_linear_units()) : current_position.x, parser.seenval('Y') ? RAW_Y_POSITION(parser.value_linear_units()) : current_position.y }; From cb53cc1b6d02e820743e71c979edcb49aa512478 Mon Sep 17 00:00:00 2001 From: Scott Lahteine Date: Mon, 29 Mar 2021 23:51:00 -0500 Subject: [PATCH 07/25] Put G26 in a struct --- Marlin/src/gcode/bedlevel/G26.cpp | 453 +++++++++++++++--------------- 1 file changed, 230 insertions(+), 223 deletions(-) diff --git a/Marlin/src/gcode/bedlevel/G26.cpp b/Marlin/src/gcode/bedlevel/G26.cpp index 757e5520c454..9ca695ada0a9 100644 --- a/Marlin/src/gcode/bedlevel/G26.cpp +++ b/Marlin/src/gcode/bedlevel/G26.cpp @@ -152,9 +152,6 @@ constexpr float g26_e_axis_feedrate = 0.025; static MeshFlags circle_flags, horizontal_mesh_line_flags, vertical_mesh_line_flags; float g26_random_deviation = 0.0; -static bool g26_retracted = false; // Track the retracted state of the nozzle so mismatched - // retracts/recovers won't result in a bad state. - #if HAS_LCD_MENU /** @@ -252,243 +249,261 @@ void move_to(const float &rx, const float &ry, const float &z, const float &e_de FORCE_INLINE void move_to(const xyz_pos_t &where, const float &de) { move_to(where.x, where.y, where.z, de); } -void retract_filament(const xyz_pos_t &where, const float &retraction_multiplier) { - if (!g26_retracted) { // Only retract if we are not already retracted! - g26_retracted = true; - move_to(where, -1.0f * retraction_multiplier); - } -} +typedef struct { + float extrusion_multiplier = EXTRUSION_MULTIPLIER, + retraction_multiplier = G26_RETRACT_MULTIPLIER, + layer_height = MESH_TEST_LAYER_HEIGHT, + prime_length = PRIME_LENGTH; -// TODO: Parameterize the Z lift with a define -void retract_lift_move(const xyz_pos_t &s, const float &retraction_multiplier) { - retract_filament(destination, retraction_multiplier); - move_to(current_position.x, current_position.y, current_position.z + 0.5f, 0.0f); // Z lift to minimize scraping - move_to(s.x, s.y, s.z + 0.5f, 0.0f); // Get to the starting point with no extrusion while lifted -} + int16_t bed_temp = MESH_TEST_BED_TEMP, + hotend_temp = MESH_TEST_HOTEND_TEMP; -void recover_filament(const xyz_pos_t &where, const float &retraction_multiplier) { - if (g26_retracted) { // Only un-retract if we are retracted. - move_to(where, 1.2f * retraction_multiplier); - g26_retracted = false; - } -} + xy_pos_t xy_pos; // = { 0, 0 } -/** - * print_line_from_here_to_there() takes two cartesian coordinates and draws a line from one - * to the other. But there are really three sets of coordinates involved. The first coordinate - * is the present location of the nozzle. We don't necessarily want to print from this location. - * We first need to move the nozzle to the start of line segment where we want to print. Once - * there, we can use the two coordinates supplied to draw the line. - * - * Note: Although we assume the first set of coordinates is the start of the line and the second - * set of coordinates is the end of the line, it does not always work out that way. This function - * optimizes the movement to minimize the travel distance before it can start printing. This saves - * a lot of time and eliminates a lot of nonsensical movement of the nozzle. However, it does - * cause a lot of very little short retracement of th nozzle when it draws the very first line - * segment of a 'circle'. The time this requires is very short and is easily saved by the other - * cases where the optimization comes into play. - */ -void print_line_from_here_to_there(const xyz_pos_t &s, const xyz_pos_t &e, const float &extrusion_multiplier, const float &retraction_multiplier) { + int8_t prime_flag = 0; - // Distances to the start / end of the line - xy_float_t svec = current_position - s, evec = current_position - e; + bool g26_retracted = false; // Track the retracted state during G26 so mismatched + // retracts/recovers don't result in a bad state. - const float dist_start = HYPOT2(svec.x, svec.y), - dist_end = HYPOT2(evec.x, evec.y), - line_length = HYPOT(e.x - s.x, e.y - s.y); + void retract_filament(const xyz_pos_t &where) { + if (!g26_retracted) { // Only retract if we are not already retracted! + g26_retracted = true; + move_to(where, -1.0f * retraction_multiplier); + } + } - // If the end point of the line is closer to the nozzle, flip the direction, - // moving from the end to the start. On very small lines the optimization isn't worth it. - if (dist_end < dist_start && (INTERSECTION_CIRCLE_RADIUS) < ABS(line_length)) - return print_line_from_here_to_there(e, s, extrusion_multiplier, retraction_multiplier); + // TODO: Parameterize the Z lift with a define + void retract_lift_move(const xyz_pos_t &s) { + retract_filament(destination); + move_to(current_position.x, current_position.y, current_position.z + 0.5f, 0.0f); // Z lift to minimize scraping + move_to(s.x, s.y, s.z + 0.5f, 0.0f); // Get to the starting point with no extrusion while lifted + } - // Decide whether to retract & lift - if (dist_start > 2.0) retract_lift_move(s, retraction_multiplier); + void recover_filament(const xyz_pos_t &where) { + if (g26_retracted) { // Only un-retract if we are retracted. + move_to(where, 1.2f * retraction_multiplier); + g26_retracted = false; + } + } - move_to(s, 0.0); // Get to the starting point with no extrusion / un-Z lift + /** + * print_line_from_here_to_there() takes two cartesian coordinates and draws a line from one + * to the other. But there are really three sets of coordinates involved. The first coordinate + * is the present location of the nozzle. We don't necessarily want to print from this location. + * We first need to move the nozzle to the start of line segment where we want to print. Once + * there, we can use the two coordinates supplied to draw the line. + * + * Note: Although we assume the first set of coordinates is the start of the line and the second + * set of coordinates is the end of the line, it does not always work out that way. This function + * optimizes the movement to minimize the travel distance before it can start printing. This saves + * a lot of time and eliminates a lot of nonsensical movement of the nozzle. However, it does + * cause a lot of very little short retracement of th nozzle when it draws the very first line + * segment of a 'circle'. The time this requires is very short and is easily saved by the other + * cases where the optimization comes into play. + */ + void print_line_from_here_to_there(const xyz_pos_t &s, const xyz_pos_t &e) { - const float e_pos_delta = line_length * g26_e_axis_feedrate * extrusion_multiplier; + // Distances to the start / end of the line + xy_float_t svec = current_position - s, evec = current_position - e; - recover_filament(destination, retraction_multiplier); - move_to(e, e_pos_delta); // Get to the ending point with an appropriate amount of extrusion -} + const float dist_start = HYPOT2(svec.x, svec.y), + dist_end = HYPOT2(evec.x, evec.y), + line_length = HYPOT(e.x - s.x, e.y - s.y); -inline bool look_for_lines_to_connect(const float &layer_height, const float &extrusion_multiplier, const float &retraction_multiplier) { - xyz_pos_t s, e; - s.z = e.z = layer_height; + // If the end point of the line is closer to the nozzle, flip the direction, + // moving from the end to the start. On very small lines the optimization isn't worth it. + if (dist_end < dist_start && (INTERSECTION_CIRCLE_RADIUS) < ABS(line_length)) + return print_line_from_here_to_there(e, s); - GRID_LOOP(i, j) { + // Decide whether to retract & lift + if (dist_start > 2.0) retract_lift_move(s); - if (TERN0(HAS_LCD_MENU, user_canceled())) return true; + move_to(s, 0.0); // Get to the starting point with no extrusion / un-Z lift - if (i < (GRID_MAX_POINTS_X)) { // Can't connect to anything farther to the right than GRID_MAX_POINTS_X. - // Already a half circle at the edge of the bed. + const float e_pos_delta = line_length * g26_e_axis_feedrate * extrusion_multiplier; - if (circle_flags.marked(i, j) && circle_flags.marked(i + 1, j)) { // Test whether a leftward line can be done - if (!horizontal_mesh_line_flags.marked(i, j)) { - // Two circles need a horizontal line to connect them - s.x = _GET_MESH_X( i ) + (INTERSECTION_CIRCLE_RADIUS - (CROSSHAIRS_SIZE)); // right edge - e.x = _GET_MESH_X(i + 1) - (INTERSECTION_CIRCLE_RADIUS - (CROSSHAIRS_SIZE)); // left edge + recover_filament(destination); + move_to(e, e_pos_delta); // Get to the ending point with an appropriate amount of extrusion + } - #if HAS_ENDSTOPS - LIMIT(s.x, X_MIN_POS + 1, X_MAX_POS - 1); - s.y = e.y = constrain(_GET_MESH_Y(j), Y_MIN_POS + 1, Y_MAX_POS - 1); - LIMIT(e.x, X_MIN_POS + 1, X_MAX_POS - 1); - #else - s.y = e.y = _GET_MESH_Y(j); - #endif + inline bool look_for_lines_to_connect() { + xyz_pos_t s, e; + s.z = e.z = layer_height; - if (position_is_reachable(s.x, s.y) && position_is_reachable(e.x, e.y)) - print_line_from_here_to_there(s, e, extrusion_multiplier, retraction_multiplier); + GRID_LOOP(i, j) { - horizontal_mesh_line_flags.mark(i, j); // Mark done, even if skipped - } - } + if (TERN0(HAS_LCD_MENU, user_canceled())) return true; - if (j < (GRID_MAX_POINTS_Y)) { // Can't connect to anything further back than GRID_MAX_POINTS_Y. + if (i < (GRID_MAX_POINTS_X)) { // Can't connect to anything farther to the right than GRID_MAX_POINTS_X. // Already a half circle at the edge of the bed. - if (circle_flags.marked(i, j) && circle_flags.marked(i, j + 1)) { // Test whether a downward line can be done - if (!vertical_mesh_line_flags.marked(i, j)) { - // Two circles that need a vertical line to connect them - s.y = _GET_MESH_Y( j ) + (INTERSECTION_CIRCLE_RADIUS - (CROSSHAIRS_SIZE)); // top edge - e.y = _GET_MESH_Y(j + 1) - (INTERSECTION_CIRCLE_RADIUS - (CROSSHAIRS_SIZE)); // bottom edge + if (circle_flags.marked(i, j) && circle_flags.marked(i + 1, j)) { // Test whether a leftward line can be done + if (!horizontal_mesh_line_flags.marked(i, j)) { + // Two circles need a horizontal line to connect them + s.x = _GET_MESH_X( i ) + (INTERSECTION_CIRCLE_RADIUS - (CROSSHAIRS_SIZE)); // right edge + e.x = _GET_MESH_X(i + 1) - (INTERSECTION_CIRCLE_RADIUS - (CROSSHAIRS_SIZE)); // left edge #if HAS_ENDSTOPS - s.x = e.x = constrain(_GET_MESH_X(i), X_MIN_POS + 1, X_MAX_POS - 1); - LIMIT(s.y, Y_MIN_POS + 1, Y_MAX_POS - 1); - LIMIT(e.y, Y_MIN_POS + 1, Y_MAX_POS - 1); + LIMIT(s.x, X_MIN_POS + 1, X_MAX_POS - 1); + s.y = e.y = constrain(_GET_MESH_Y(j), Y_MIN_POS + 1, Y_MAX_POS - 1); + LIMIT(e.x, X_MIN_POS + 1, X_MAX_POS - 1); #else - s.x = e.x = _GET_MESH_X(i); + s.y = e.y = _GET_MESH_Y(j); #endif if (position_is_reachable(s.x, s.y) && position_is_reachable(e.x, e.y)) - print_line_from_here_to_there(s, e, extrusion_multiplier, retraction_multiplier); + print_line_from_here_to_there(s, e); - vertical_mesh_line_flags.mark(i, j); // Mark done, even if skipped + horizontal_mesh_line_flags.mark(i, j); // Mark done, even if skipped } } - } - } - } - return false; -} -/** - * Turn on the bed and nozzle heat and - * wait for them to get up to temperature. - */ -inline bool turn_on_heaters(const celsius_t hotend_temp, const celsius_t bed_temp) { + if (j < (GRID_MAX_POINTS_Y)) { // Can't connect to anything further back than GRID_MAX_POINTS_Y. + // Already a half circle at the edge of the bed. - SERIAL_ECHOLNPGM("Waiting for heatup."); + if (circle_flags.marked(i, j) && circle_flags.marked(i, j + 1)) { // Test whether a downward line can be done + if (!vertical_mesh_line_flags.marked(i, j)) { + // Two circles that need a vertical line to connect them + s.y = _GET_MESH_Y( j ) + (INTERSECTION_CIRCLE_RADIUS - (CROSSHAIRS_SIZE)); // top edge + e.y = _GET_MESH_Y(j + 1) - (INTERSECTION_CIRCLE_RADIUS - (CROSSHAIRS_SIZE)); // bottom edge - #if HAS_HEATED_BED + #if HAS_ENDSTOPS + s.x = e.x = constrain(_GET_MESH_X(i), X_MIN_POS + 1, X_MAX_POS - 1); + LIMIT(s.y, Y_MIN_POS + 1, Y_MAX_POS - 1); + LIMIT(e.y, Y_MIN_POS + 1, Y_MAX_POS - 1); + #else + s.x = e.x = _GET_MESH_X(i); + #endif - if (bed_temp > 25) { - #if HAS_WIRED_LCD - ui.set_status_P(GET_TEXT(MSG_G26_HEATING_BED), 99); - ui.quick_feedback(); - TERN_(HAS_LCD_MENU, ui.capture()); - #endif - thermalManager.setTargetBed(bed_temp); + if (position_is_reachable(s.x, s.y) && position_is_reachable(e.x, e.y)) + print_line_from_here_to_there(s, e); - // Wait for the temperature to stabilize - if (!thermalManager.wait_for_bed(true - #if G26_CLICK_CAN_CANCEL - , true - #endif - ) - ) return G26_ERR; + vertical_mesh_line_flags.mark(i, j); // Mark done, even if skipped + } + } + } + } } + return false; + } - #else + /** + * Turn on the bed and nozzle heat and + * wait for them to get up to temperature. + */ + bool turn_on_heaters() { - UNUSED(bed_temp); + SERIAL_ECHOLNPGM("Waiting for heatup."); - #endif // HAS_HEATED_BED + #if HAS_HEATED_BED - // Start heating the active nozzle - #if HAS_WIRED_LCD - ui.set_status_P(GET_TEXT(MSG_G26_HEATING_NOZZLE), 99); - ui.quick_feedback(); - #endif - thermalManager.setTargetHotend(hotend_temp, active_extruder); + if (bed_temp > 25) { + #if HAS_WIRED_LCD + ui.set_status_P(GET_TEXT(MSG_G26_HEATING_BED), 99); + ui.quick_feedback(); + TERN_(HAS_LCD_MENU, ui.capture()); + #endif + thermalManager.setTargetBed(bed_temp); - // Wait for the temperature to stabilize - if (!thermalManager.wait_for_hotend(active_extruder, true - #if G26_CLICK_CAN_CANCEL - , true - #endif - )) return G26_ERR; + // Wait for the temperature to stabilize + if (!thermalManager.wait_for_bed(true + #if G26_CLICK_CAN_CANCEL + , true + #endif + ) + ) return G26_ERR; + } - #if HAS_WIRED_LCD - ui.reset_status(); - ui.quick_feedback(); - #endif + #else - return G26_OK; -} + UNUSED(bed_temp); -/** - * Prime the nozzle if needed. Return true on error. - */ -inline bool prime_nozzle(const int8_t prime_flag, const float &prime_length, const float &retraction_multiplier) { + #endif // HAS_HEATED_BED - const feedRate_t fr_slow_e = planner.settings.max_feedrate_mm_s[E_AXIS] / 15.0f; - #if HAS_LCD_MENU && !HAS_TOUCH_BUTTONS // ui.button_pressed issue with touchscreen - #if ENABLED(PREVENT_LENGTHY_EXTRUDE) - float Total_Prime = 0.0; + // Start heating the active nozzle + #if HAS_WIRED_LCD + ui.set_status_P(GET_TEXT(MSG_G26_HEATING_NOZZLE), 99); + ui.quick_feedback(); #endif + thermalManager.setTargetHotend(hotend_temp, active_extruder); - if (prime_flag == -1) { // The user wants to control how much filament gets purged - ui.capture(); - ui.set_status_P(GET_TEXT(MSG_G26_MANUAL_PRIME), 99); - ui.chirp(); + // Wait for the temperature to stabilize + if (!thermalManager.wait_for_hotend(active_extruder, true + #if G26_CLICK_CAN_CANCEL + , true + #endif + )) return G26_ERR; - destination = current_position; + #if HAS_WIRED_LCD + ui.reset_status(); + ui.quick_feedback(); + #endif - recover_filament(destination, retraction_multiplier); // Make sure G26 doesn't think the filament is retracted(). + return G26_OK; + } - while (!ui.button_pressed()) { + /** + * Prime the nozzle if needed. Return true on error. + */ + bool prime_nozzle() { + + const feedRate_t fr_slow_e = planner.settings.max_feedrate_mm_s[E_AXIS] / 15.0f; + #if HAS_LCD_MENU && !HAS_TOUCH_BUTTONS // ui.button_pressed issue with touchscreen + #if ENABLED(PREVENT_LENGTHY_EXTRUDE) + float Total_Prime = 0.0; + #endif + + if (prime_flag == -1) { // The user wants to control how much filament gets purged + ui.capture(); + ui.set_status_P(GET_TEXT(MSG_G26_MANUAL_PRIME), 99); ui.chirp(); - destination.e += 0.25; - #if ENABLED(PREVENT_LENGTHY_EXTRUDE) - Total_Prime += 0.25; - if (Total_Prime >= EXTRUDE_MAXLENGTH) { - ui.release(); - return G26_ERR; - } - #endif - prepare_internal_move_to_destination(fr_slow_e); + destination = current_position; - planner.synchronize(); // Without this synchronize, the purge is more consistent, - // but because the planner has a buffer, we won't be able - // to stop as quickly. So we put up with the less smooth - // action to give the user a more responsive 'Stop'. - } - ui.wait_for_release(); + recover_filament(destination); // Make sure G26 doesn't think the filament is retracted(). + + while (!ui.button_pressed()) { + ui.chirp(); + destination.e += 0.25; + #if ENABLED(PREVENT_LENGTHY_EXTRUDE) + Total_Prime += 0.25; + if (Total_Prime >= EXTRUDE_MAXLENGTH) { + ui.release(); + return G26_ERR; + } + #endif + prepare_internal_move_to_destination(fr_slow_e); + destination = current_position; + planner.synchronize(); // Without this synchronize, the purge is more consistent, + // but because the planner has a buffer, we won't be able + // to stop as quickly. So we put up with the less smooth + // action to give the user a more responsive 'Stop'. + } - ui.set_status_P(GET_TEXT(MSG_G26_PRIME_DONE), 99); - ui.quick_feedback(); - ui.release(); - } - else - #endif - { - #if HAS_WIRED_LCD - ui.set_status_P(GET_TEXT(MSG_G26_FIXED_LENGTH), 99); - ui.quick_feedback(); + ui.wait_for_release(); + + ui.set_status_P(GET_TEXT(MSG_G26_PRIME_DONE), 99); + ui.quick_feedback(); + ui.release(); + } + else #endif - destination = current_position; - destination.e += prime_length; - prepare_internal_move_to_destination(fr_slow_e); - destination.e -= prime_length; - retract_filament(destination, retraction_multiplier); + { + #if HAS_WIRED_LCD + ui.set_status_P(GET_TEXT(MSG_G26_FIXED_LENGTH), 99); + ui.quick_feedback(); + #endif + destination = current_position; + destination.e += prime_length; + prepare_internal_move_to_destination(fr_slow_e); + destination.e -= prime_length; + retract_filament(destination); + } + + return G26_OK; } - return G26_OK; -} +} g26_state_t; /** * G26: Mesh Validation Pattern generation. @@ -525,15 +540,7 @@ void GcodeSuite::G26() { // Change the tool first, if specified if (parser.seenval('T')) tool_change(parser.value_int()); - float g26_extrusion_multiplier = EXTRUSION_MULTIPLIER, - g26_retraction_multiplier = G26_RETRACT_MULTIPLIER, - g26_layer_height = MESH_TEST_LAYER_HEIGHT, - g26_prime_length = PRIME_LENGTH; - - int16_t g26_hotend_temp = MESH_TEST_HOTEND_TEMP, - g26_bed_temp = MESH_TEST_BED_TEMP; - - int8_t g26_prime_flag = 0; + g26_state_t g26; float g26_nozzle = MESH_TEST_NOZZLE_SIZE, g26_filament_diameter = DEFAULT_NOMINAL_FILAMENT_DIA, @@ -565,14 +572,14 @@ void GcodeSuite::G26() { SERIAL_ECHOLNPAIR("?Specified bed temperature not plausible (40-", BED_MAX_TARGET, "C)."); return; } - g26_bed_temp = bedtemp; + g26.bed_temp = bedtemp; } #endif // HAS_HEATED_BED if (parser.seenval('L')) { - g26_layer_height = parser.value_linear_units(); - if (!WITHIN(g26_layer_height, 0.0, 2.0)) { + g26.layer_height = parser.value_linear_units(); + if (!WITHIN(g26.layer_height, 0.0, 2.0)) { SERIAL_ECHOLNPGM("?Specified layer height not plausible."); return; } @@ -580,8 +587,8 @@ void GcodeSuite::G26() { if (parser.seen('Q')) { if (parser.has_value()) { - g26_retraction_multiplier = parser.value_float(); - if (!WITHIN(g26_retraction_multiplier, 0.05, 15.0)) { + g26.retraction_multiplier = parser.value_float(); + if (!WITHIN(g26.retraction_multiplier, 0.05, 15.0)) { SERIAL_ECHOLNPGM("?Specified Retraction Multiplier not plausible."); return; } @@ -603,16 +610,16 @@ void GcodeSuite::G26() { if (parser.seen('P')) { if (!parser.has_value()) { #if HAS_LCD_MENU - g26_prime_flag = -1; + g26.prime_flag = -1; #else SERIAL_ECHOLNPGM("?Prime length must be specified when not using an LCD."); return; #endif } else { - g26_prime_flag++; - g26_prime_length = parser.value_linear_units(); - if (!WITHIN(g26_prime_length, 0.0, 25.0)) { + g26.prime_flag++; + g26.prime_length = parser.value_linear_units(); + if (!WITHIN(g26.prime_length, 0.0, 25.0)) { SERIAL_ECHOLNPGM("?Specified prime length not plausible."); return; } @@ -626,11 +633,11 @@ void GcodeSuite::G26() { return; } } - g26_extrusion_multiplier *= sq(1.75) / sq(g26_filament_diameter); // If we aren't using 1.75mm filament, we need to + g26.extrusion_multiplier *= sq(1.75) / sq(g26_filament_diameter); // If we aren't using 1.75mm filament, we need to // scale up or down the length needed to get the // same volume of filament - g26_extrusion_multiplier *= g26_filament_diameter * sq(g26_nozzle) / sq(0.3); // Scale up by nozzle size + g26.extrusion_multiplier *= g26_filament_diameter * sq(g26_nozzle) / sq(0.3); // Scale up by nozzle size // Get a temperature from 'I' or 'H' celsius_t noztemp = 0; @@ -649,7 +656,7 @@ void GcodeSuite::G26() { SERIAL_ECHOLNPGM("?Specified nozzle temperature not plausible."); return; } - g26_hotend_temp = noztemp; + g26.hotend_temp = noztemp; } // 'U' to Randomize and optionally set circle deviation @@ -677,11 +684,11 @@ void GcodeSuite::G26() { } // Set a position with 'X' and/or 'Y'. Default: current_position - const xy_pos_t g26_xy_pos = { + g26.xy_pos = xy_pos_t({ parser.seenval('X') ? RAW_X_POSITION(parser.value_linear_units()) : current_position.x, parser.seenval('Y') ? RAW_Y_POSITION(parser.value_linear_units()) : current_position.y - }; - if (!position_is_reachable(g26_xy_pos)) { + }); + if (!position_is_reachable(g26.xy_pos)) { SERIAL_ECHOLNPGM("?Specified X,Y coordinate out of bounds."); return; } @@ -699,12 +706,12 @@ void GcodeSuite::G26() { planner.calculate_volumetric_multipliers(); #endif - if (turn_on_heaters(g26_hotend_temp, g26_bed_temp) != G26_OK) goto LEAVE; + if (g26.turn_on_heaters() != G26_OK) goto LEAVE; current_position.e = 0.0; sync_plan_position_e(); - if (g26_prime_flag && prime_nozzle(g26_prime_flag, g26_prime_length, g26_retraction_multiplier) != G26_OK) goto LEAVE; + if (g26.prime_flag && g26.prime_nozzle() != G26_OK) goto LEAVE; /** * Bed is preheated @@ -722,7 +729,7 @@ void GcodeSuite::G26() { // Move nozzle to the specified height for the first layer destination = current_position; - destination.z = g26_layer_height; + destination.z = g26.layer_height; move_to(destination, 0.0); move_to(destination, g26_ooze_amount); @@ -751,7 +758,7 @@ void GcodeSuite::G26() { mesh_index_pair location; do { // Find the nearest confluence - location = find_closest_circle_to_print(g26_continue_with_closest ? xy_pos_t(current_position) : g26_xy_pos, g26_xy_pos); + location = find_closest_circle_to_print(g26_continue_with_closest ? xy_pos_t(current_position) : g26.xy_pos, g26.xy_pos); if (location.valid()) { const xy_pos_t circle = _GET_MESH_POS(location.pos); @@ -801,19 +808,19 @@ void GcodeSuite::G26() { const xy_float_t dist = current_position - s; // Distance from the start of the actual circle const float dist_start = HYPOT2(dist.x, dist.y); const xyze_pos_t endpoint = { - e.x, e.y, g26_layer_height, - current_position.e + (arc_length * g26_e_axis_feedrate * g26_extrusion_multiplier) + e.x, e.y, g26.layer_height, + current_position.e + (arc_length * g26_e_axis_feedrate * g26.extrusion_multiplier) }; if (dist_start > 2.0) { - s.z = g26_layer_height + 0.5f; - retract_lift_move(s, g26_retraction_multiplier); + s.z = g26.layer_height + 0.5f; + g26.retract_lift_move(s); } - s.z = g26_layer_height; + s.z = g26.layer_height; move_to(s, 0.0); // Get to the starting point with no extrusion / un-Z lift - recover_filament(destination, g26_retraction_multiplier); + g26.recover_filament(destination); const feedRate_t old_feedrate = feedrate_mm_s; feedrate_mm_s = PLANNER_XY_FEEDRATE() * 0.1f; @@ -847,8 +854,8 @@ void GcodeSuite::G26() { if (TERN0(HAS_LCD_MENU, user_canceled())) goto LEAVE; // Check if the user wants to stop the Mesh Validation - xyz_float_t p = { circle.x + _COS(ind ), circle.y + _SIN(ind ), g26_layer_height }, - q = { circle.x + _COS(ind + 1), circle.y + _SIN(ind + 1), g26_layer_height }; + xyz_float_t p = { circle.x + _COS(ind ), circle.y + _SIN(ind ), g26.layer_height }, + q = { circle.x + _COS(ind + 1), circle.y + _SIN(ind + 1), g26.layer_height }; #if IS_KINEMATIC // Check to make sure this segment is entirely on the bed, skip if not. @@ -860,13 +867,13 @@ void GcodeSuite::G26() { LIMIT(q.y, Y_MIN_POS + 1, Y_MAX_POS - 1); #endif - print_line_from_here_to_there(p, q, g26_extrusion_multiplier, g26_retraction_multiplier); + g26.print_line_from_here_to_there(p, q); SERIAL_FLUSH(); // Prevent host M105 buffer overrun. } #endif // !ARC_SUPPORT - if (look_for_lines_to_connect(g26_layer_height, g26_extrusion_multiplier, g26_retraction_multiplier)) goto LEAVE; + if (g26.look_for_lines_to_connect()) goto LEAVE; } SERIAL_FLUSH(); // Prevent host M105 buffer overrun. @@ -876,11 +883,11 @@ void GcodeSuite::G26() { LEAVE: ui.set_status_P(GET_TEXT(MSG_G26_LEAVING), -1); - retract_filament(destination, g26_retraction_multiplier); + g26.retract_filament(destination); destination.z = Z_CLEARANCE_BETWEEN_PROBES; move_to(destination, 0); // Raise the nozzle - destination = g26_xy_pos; // Move back to the starting XY position + destination = g26.xy_pos; // Move back to the starting XY position move_to(destination, 0); // Move back to the starting position #if DISABLED(NO_VOLUMETRICS) From 4afa315f2b96b773334b986cb6b67954b7311c73 Mon Sep 17 00:00:00 2001 From: Scott Lahteine Date: Mon, 29 Mar 2021 23:52:58 -0500 Subject: [PATCH 08/25] prettier --- Marlin/src/gcode/bedlevel/G26.cpp | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/Marlin/src/gcode/bedlevel/G26.cpp b/Marlin/src/gcode/bedlevel/G26.cpp index 9ca695ada0a9..106c91305cb6 100644 --- a/Marlin/src/gcode/bedlevel/G26.cpp +++ b/Marlin/src/gcode/bedlevel/G26.cpp @@ -684,10 +684,8 @@ void GcodeSuite::G26() { } // Set a position with 'X' and/or 'Y'. Default: current_position - g26.xy_pos = xy_pos_t({ - parser.seenval('X') ? RAW_X_POSITION(parser.value_linear_units()) : current_position.x, - parser.seenval('Y') ? RAW_Y_POSITION(parser.value_linear_units()) : current_position.y - }); + g26_xy_pos.set(parser.seenval('X') ? RAW_X_POSITION(parser.value_linear_units()) : current_position.x, + parser.seenval('Y') ? RAW_Y_POSITION(parser.value_linear_units()) : current_position.y); if (!position_is_reachable(g26.xy_pos)) { SERIAL_ECHOLNPGM("?Specified X,Y coordinate out of bounds."); return; From 9e70fa01b52b87169be344a412df0d4620aa237c Mon Sep 17 00:00:00 2001 From: Marcio T Date: Tue, 30 Mar 2021 10:43:34 -0600 Subject: [PATCH 09/25] Fix compilation error. --- Marlin/src/gcode/bedlevel/G26.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Marlin/src/gcode/bedlevel/G26.cpp b/Marlin/src/gcode/bedlevel/G26.cpp index 106c91305cb6..f48bdca043ac 100644 --- a/Marlin/src/gcode/bedlevel/G26.cpp +++ b/Marlin/src/gcode/bedlevel/G26.cpp @@ -684,7 +684,7 @@ void GcodeSuite::G26() { } // Set a position with 'X' and/or 'Y'. Default: current_position - g26_xy_pos.set(parser.seenval('X') ? RAW_X_POSITION(parser.value_linear_units()) : current_position.x, + g26.xy_pos.set(parser.seenval('X') ? RAW_X_POSITION(parser.value_linear_units()) : current_position.x, parser.seenval('Y') ? RAW_Y_POSITION(parser.value_linear_units()) : current_position.y); if (!position_is_reachable(g26.xy_pos)) { SERIAL_ECHOLNPGM("?Specified X,Y coordinate out of bounds."); From c659df52c0a58d4155b7c5834344d644a7b477fb Mon Sep 17 00:00:00 2001 From: Scott Lahteine Date: Tue, 30 Mar 2021 15:07:00 -0500 Subject: [PATCH 10/25] move some things --- Marlin/src/gcode/bedlevel/G26.cpp | 117 +++++++++++++++--------------- 1 file changed, 59 insertions(+), 58 deletions(-) diff --git a/Marlin/src/gcode/bedlevel/G26.cpp b/Marlin/src/gcode/bedlevel/G26.cpp index f48bdca043ac..5749d04efd01 100644 --- a/Marlin/src/gcode/bedlevel/G26.cpp +++ b/Marlin/src/gcode/bedlevel/G26.cpp @@ -167,59 +167,6 @@ float g26_random_deviation = 0.0; #endif -mesh_index_pair find_closest_circle_to_print(const xy_pos_t &pos, const xy_pos_t &command_pos) { - - mesh_index_pair out_point; - out_point.pos = -1; - - #if ENABLED(UBL_HILBERT_CURVE) - - auto test_func = [](uint8_t i, uint8_t j, void *data) { - if (!circle_flags.marked(i, j)) { - mesh_index_pair *out_point = (mesh_index_pair*)data; - out_point->pos.set(i, j); // Save its data - return true; - } - return false; - } - - hilbert_curve::search_from_closest(pos, test_func, &out_point); - - #else - - float closest = 99999.99; - - GRID_LOOP(i, j) { - if (!circle_flags.marked(i, j)) { - // We found a circle that needs to be printed - const xy_pos_t m = { _GET_MESH_X(i), _GET_MESH_Y(j) }; - - // Get the distance to this intersection - float f = (pos - m).magnitude(); - - // It is possible that we are being called with the values - // to let us find the closest circle to the start position. - // But if this is not the case, add a small weighting to the - // distance calculation to help it choose a better place to continue. - f += (command_pos - m).magnitude() / 15.0f; - - // Add the specified amount of Random Noise to our search - if (g26_random_deviation > 1.0) f += random(0.0, g26_random_deviation); - - if (f < closest) { - closest = f; // Found a closer un-printed location - out_point.pos.set(i, j); // Save its data - out_point.distance = closest; - } - } - } - - #endif - - circle_flags.mark(out_point); // Mark this location as done. - return out_point; -} - void move_to(const float &rx, const float &ry, const float &z, const float &e_delta) { static float last_z = -999.99; @@ -503,6 +450,62 @@ typedef struct { return G26_OK; } + /** + * Find the nearest point at which to print a circle + */ + mesh_index_pair find_closest_circle_to_print(const xy_pos_t &pos) { + + mesh_index_pair out_point; + out_point.pos = -1; + + #if ENABLED(UBL_HILBERT_CURVE) + + auto test_func = [](uint8_t i, uint8_t j, void *data) { + if (!circle_flags.marked(i, j)) { + mesh_index_pair *out_point = (mesh_index_pair*)data; + out_point->pos.set(i, j); // Save its data + return true; + } + return false; + } + + hilbert_curve::search_from_closest(pos, test_func, &out_point); + + #else + + float closest = 99999.99; + + GRID_LOOP(i, j) { + if (!circle_flags.marked(i, j)) { + // We found a circle that needs to be printed + const xy_pos_t m = { _GET_MESH_X(i), _GET_MESH_Y(j) }; + + // Get the distance to this intersection + float f = (pos - m).magnitude(); + + // It is possible that we are being called with the values + // to let us find the closest circle to the start position. + // But if this is not the case, add a small weighting to the + // distance calculation to help it choose a better place to continue. + f += (xy_pos - m).magnitude() / 15.0f; + + // Add the specified amount of Random Noise to our search + if (g26_random_deviation > 1.0) f += random(0.0, g26_random_deviation); + + if (f < closest) { + closest = f; // Found a closer un-printed location + out_point.pos.set(i, j); // Save its data + out_point.distance = closest; + } + } + } + + #endif + + circle_flags.mark(out_point); // Mark this location as done. + return out_point; + } + } g26_state_t; /** @@ -756,7 +759,7 @@ void GcodeSuite::G26() { mesh_index_pair location; do { // Find the nearest confluence - location = find_closest_circle_to_print(g26_continue_with_closest ? xy_pos_t(current_position) : g26.xy_pos, g26.xy_pos); + location = find_closest_circle_to_print(g26_continue_with_closest ? xy_pos_t(current_position) : g26.xy_pos); if (location.valid()) { const xy_pos_t circle = _GET_MESH_POS(location.pos); @@ -883,10 +886,8 @@ void GcodeSuite::G26() { g26.retract_filament(destination); destination.z = Z_CLEARANCE_BETWEEN_PROBES; - move_to(destination, 0); // Raise the nozzle - - destination = g26.xy_pos; // Move back to the starting XY position - move_to(destination, 0); // Move back to the starting position + move_to(destination, 0); // Raise the nozzle + move_to(g26.xy_pos, 0); // Move back to the starting position #if DISABLED(NO_VOLUMETRICS) parser.volumetric_enabled = volumetric_was_enabled; From e315d76b1bb52b444cf33613edcdb4b7ddc6a3b6 Mon Sep 17 00:00:00 2001 From: Scott Lahteine Date: Tue, 30 Mar 2021 16:24:08 -0500 Subject: [PATCH 11/25] missing prefix --- Marlin/src/gcode/bedlevel/G26.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Marlin/src/gcode/bedlevel/G26.cpp b/Marlin/src/gcode/bedlevel/G26.cpp index 5749d04efd01..9e901c011d63 100644 --- a/Marlin/src/gcode/bedlevel/G26.cpp +++ b/Marlin/src/gcode/bedlevel/G26.cpp @@ -759,7 +759,7 @@ void GcodeSuite::G26() { mesh_index_pair location; do { // Find the nearest confluence - location = find_closest_circle_to_print(g26_continue_with_closest ? xy_pos_t(current_position) : g26.xy_pos); + location = g26.find_closest_circle_to_print(g26_continue_with_closest ? xy_pos_t(current_position) : g26.xy_pos); if (location.valid()) { const xy_pos_t circle = _GET_MESH_POS(location.pos); From 5ef35b16bdffb1897632fc60948ce8549f9ff38c Mon Sep 17 00:00:00 2001 From: Scott Lahteine Date: Tue, 30 Mar 2021 18:10:05 -0500 Subject: [PATCH 12/25] add ; --- Marlin/src/gcode/bedlevel/G26.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Marlin/src/gcode/bedlevel/G26.cpp b/Marlin/src/gcode/bedlevel/G26.cpp index 9e901c011d63..4195203d1602 100644 --- a/Marlin/src/gcode/bedlevel/G26.cpp +++ b/Marlin/src/gcode/bedlevel/G26.cpp @@ -467,7 +467,7 @@ typedef struct { return true; } return false; - } + }; hilbert_curve::search_from_closest(pos, test_func, &out_point); From ac35e5d20bc79d80348ae1bf87607b3ba30a073d Mon Sep 17 00:00:00 2001 From: Scott Lahteine Date: Tue, 30 Mar 2021 18:24:40 -0500 Subject: [PATCH 13/25] finish up --- Marlin/src/gcode/bedlevel/G26.cpp | 40 +++++++++++++++++-------------- 1 file changed, 22 insertions(+), 18 deletions(-) diff --git a/Marlin/src/gcode/bedlevel/G26.cpp b/Marlin/src/gcode/bedlevel/G26.cpp index 4195203d1602..7ce1842e86d7 100644 --- a/Marlin/src/gcode/bedlevel/G26.cpp +++ b/Marlin/src/gcode/bedlevel/G26.cpp @@ -205,7 +205,14 @@ typedef struct { int16_t bed_temp = MESH_TEST_BED_TEMP, hotend_temp = MESH_TEST_HOTEND_TEMP; - xy_pos_t xy_pos; // = { 0, 0 } + float nozzle = MESH_TEST_NOZZLE_SIZE, + filament_diameter = DEFAULT_NOMINAL_FILAMENT_DIA, + ooze_amount; // 'O' ... OOZE_AMOUNT + + bool continue_with_closest, // 'C' + keep_heaters_on; // 'K' + + xy_pos_t xy_pos; // = { 0, 0 } int8_t prime_flag = 0; @@ -506,7 +513,7 @@ typedef struct { return out_point; } -} g26_state_t; +} g26_helper_t; /** * G26: Mesh Validation Pattern generation. @@ -543,14 +550,11 @@ void GcodeSuite::G26() { // Change the tool first, if specified if (parser.seenval('T')) tool_change(parser.value_int()); - g26_state_t g26; - - float g26_nozzle = MESH_TEST_NOZZLE_SIZE, - g26_filament_diameter = DEFAULT_NOMINAL_FILAMENT_DIA, - g26_ooze_amount = parser.linearval('O', OOZE_AMOUNT); + g26_helper_t g26; - bool g26_continue_with_closest = parser.boolval('C'), - g26_keep_heaters_on = parser.boolval('K'); + g26.ooze_amount = parser.linearval('O', OOZE_AMOUNT); + g26.continue_with_closest = parser.boolval('C'); + g26.keep_heaters_on = parser.boolval('K'); // Accept 'I' if temperature presets are defined #if PREHEAT_COUNT @@ -603,8 +607,8 @@ void GcodeSuite::G26() { } if (parser.seenval('S')) { - g26_nozzle = parser.value_float(); - if (!WITHIN(g26_nozzle, 0.1, 2.0)) { + g26.nozzle = parser.value_float(); + if (!WITHIN(g26.nozzle, 0.1, 2.0)) { SERIAL_ECHOLNPGM("?Specified nozzle size not plausible."); return; } @@ -630,17 +634,17 @@ void GcodeSuite::G26() { } if (parser.seenval('F')) { - g26_filament_diameter = parser.value_linear_units(); - if (!WITHIN(g26_filament_diameter, 1.0, 4.0)) { + g26.filament_diameter = parser.value_linear_units(); + if (!WITHIN(g26.filament_diameter, 1.0, 4.0)) { SERIAL_ECHOLNPGM("?Specified filament size not plausible."); return; } } - g26.extrusion_multiplier *= sq(1.75) / sq(g26_filament_diameter); // If we aren't using 1.75mm filament, we need to + g26.extrusion_multiplier *= sq(1.75) / sq(g26.filament_diameter); // If we aren't using 1.75mm filament, we need to // scale up or down the length needed to get the // same volume of filament - g26.extrusion_multiplier *= g26_filament_diameter * sq(g26_nozzle) / sq(0.3); // Scale up by nozzle size + g26.extrusion_multiplier *= g26.filament_diameter * sq(g26.nozzle) / sq(0.3); // Scale up by nozzle size // Get a temperature from 'I' or 'H' celsius_t noztemp = 0; @@ -732,7 +736,7 @@ void GcodeSuite::G26() { destination = current_position; destination.z = g26.layer_height; move_to(destination, 0.0); - move_to(destination, g26_ooze_amount); + move_to(destination, g26.ooze_amount); TERN_(HAS_LCD_MENU, ui.capture()); @@ -759,7 +763,7 @@ void GcodeSuite::G26() { mesh_index_pair location; do { // Find the nearest confluence - location = g26.find_closest_circle_to_print(g26_continue_with_closest ? xy_pos_t(current_position) : g26.xy_pos); + location = g26.find_closest_circle_to_print(g26.continue_with_closest ? xy_pos_t(current_position) : g26.xy_pos); if (location.valid()) { const xy_pos_t circle = _GET_MESH_POS(location.pos); @@ -896,7 +900,7 @@ void GcodeSuite::G26() { TERN_(HAS_LCD_MENU, ui.release()); // Give back control of the LCD - if (!g26_keep_heaters_on) { + if (!g26.keep_heaters_on) { TERN_(HAS_HEATED_BED, thermalManager.setTargetBed(0)); thermalManager.setTargetHotend(active_extruder, 0); } From cc0a14d4d911507e26dd273b56d630b3ac91d455 Mon Sep 17 00:00:00 2001 From: Scott Lahteine Date: Tue, 30 Mar 2021 18:45:02 -0500 Subject: [PATCH 14/25] use REMEMBER --- Marlin/src/gcode/bedlevel/G26.cpp | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/Marlin/src/gcode/bedlevel/G26.cpp b/Marlin/src/gcode/bedlevel/G26.cpp index 7ce1842e86d7..9d8c6e25e876 100644 --- a/Marlin/src/gcode/bedlevel/G26.cpp +++ b/Marlin/src/gcode/bedlevel/G26.cpp @@ -172,8 +172,8 @@ void move_to(const float &rx, const float &ry, const float &z, const float &e_de const xy_pos_t dest = { rx, ry }; - const bool has_xy_component = dest != current_position; // Check if X or Y is involved in the movement. - const bool has_e_component = e_delta != 0.0; + const bool has_xy_component = dest != current_position, // Check if X or Y is involved in the movement. + has_e_component = e_delta != 0.0; destination = current_position; @@ -793,7 +793,7 @@ void GcodeSuite::G26() { if (!b) { e.x = circle.x; e.y += INTERSECTION_CIRCLE_RADIUS; } arc_length = (f || b) ? ARC_LENGTH(1) : ARC_LENGTH(2); } - else if (r) { // right edge + else if (r) { // right edge if (b) s.set(circle.x - (INTERSECTION_CIRCLE_RADIUS), circle.y); else s.set(circle.x, circle.y + INTERSECTION_CIRCLE_RADIUS); if (f) e.set(circle.x - (INTERSECTION_CIRCLE_RADIUS), circle.y); @@ -827,11 +827,10 @@ void GcodeSuite::G26() { g26.recover_filament(destination); - const feedRate_t old_feedrate = feedrate_mm_s; - feedrate_mm_s = PLANNER_XY_FEEDRATE() * 0.1f; - plan_arc(endpoint, arc_offset, false, 0); // Draw a counter-clockwise arc - feedrate_mm_s = old_feedrate; - destination = current_position; + { REMEMBER(fr, feedrate_mm_s, PLANNER_XY_FEEDRATE() * 0.1f); + plan_arc(endpoint, arc_offset, false, 0); // Draw a counter-clockwise arc + destination = current_position; + } if (TERN0(HAS_LCD_MENU, user_canceled())) goto LEAVE; // Check if the user wants to stop the Mesh Validation From e55ea91814062598ec20d8a4292b7bda4969fb2d Mon Sep 17 00:00:00 2001 From: Scott Lahteine Date: Tue, 30 Mar 2021 18:45:33 -0500 Subject: [PATCH 15/25] Limit to 0...N-1 --- Marlin/src/feature/bedlevel/hilbert_curve.cpp | 4 ++-- Marlin/src/lcd/extui/ui_api.cpp | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Marlin/src/feature/bedlevel/hilbert_curve.cpp b/Marlin/src/feature/bedlevel/hilbert_curve.cpp index 6150226e0b7e..36bc5273c449 100644 --- a/Marlin/src/feature/bedlevel/hilbert_curve.cpp +++ b/Marlin/src/feature/bedlevel/hilbert_curve.cpp @@ -104,8 +104,8 @@ bool hilbert_curve::search_from_closest(const xy_pos_t &pos, hilbert_curve::call // Find closest grid intersection uint8_t grid_x = LROUND(float(pos.x - MESH_MIN_X) / MESH_X_DIST); uint8_t grid_y = LROUND(float(pos.y - MESH_MIN_Y) / MESH_Y_DIST); - LIMIT(grid_x, 0, GRID_MAX_POINTS_X); - LIMIT(grid_y, 0, GRID_MAX_POINTS_Y); + LIMIT(grid_x, 0, GRID_MAX_POINTS_X - 1); + LIMIT(grid_y, 0, GRID_MAX_POINTS_Y - 1); return search_from(grid_x, grid_y, func, data); } diff --git a/Marlin/src/lcd/extui/ui_api.cpp b/Marlin/src/lcd/extui/ui_api.cpp index 23930c04f33a..8ae96cf86935 100644 --- a/Marlin/src/lcd/extui/ui_api.cpp +++ b/Marlin/src/lcd/extui/ui_api.cpp @@ -859,7 +859,7 @@ namespace ExtUI { bed_mesh_t& getMeshArray() { return Z_VALUES_ARR; } float getMeshPoint(const xy_uint8_t &pos) { return Z_VALUES(pos.x, pos.y); } void setMeshPoint(const xy_uint8_t &pos, const float &zoff) { - if (WITHIN(pos.x, 0, GRID_MAX_POINTS_X) && WITHIN(pos.y, 0, GRID_MAX_POINTS_Y)) { + if (WITHIN(pos.x, 0, GRID_MAX_POINTS_X - 1) && WITHIN(pos.y, 0, GRID_MAX_POINTS_Y - 1)) { Z_VALUES(pos.x, pos.y) = zoff; TERN_(ABL_BILINEAR_SUBDIVISION, bed_level_virt_interpolate()); } From 9299e62138205fb30ac3dc62e95f099eafc12c9c Mon Sep 17 00:00:00 2001 From: Marcio Teixeira Date: Wed, 31 Mar 2021 13:58:02 -0600 Subject: [PATCH 16/25] Fix incorrect behavior on negative starting coordinates. --- Marlin/src/feature/bedlevel/hilbert_curve.cpp | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/Marlin/src/feature/bedlevel/hilbert_curve.cpp b/Marlin/src/feature/bedlevel/hilbert_curve.cpp index 36bc5273c449..af270735d12d 100644 --- a/Marlin/src/feature/bedlevel/hilbert_curve.cpp +++ b/Marlin/src/feature/bedlevel/hilbert_curve.cpp @@ -102,10 +102,9 @@ bool hilbert_curve::search_from(uint8_t x, uint8_t y, hilbert_curve::callback_pt */ bool hilbert_curve::search_from_closest(const xy_pos_t &pos, hilbert_curve::callback_ptr func, void *data) { // Find closest grid intersection - uint8_t grid_x = LROUND(float(pos.x - MESH_MIN_X) / MESH_X_DIST); - uint8_t grid_y = LROUND(float(pos.y - MESH_MIN_Y) / MESH_Y_DIST); - LIMIT(grid_x, 0, GRID_MAX_POINTS_X - 1); - LIMIT(grid_y, 0, GRID_MAX_POINTS_Y - 1); + #define CLAMP(VALUE,MIN,MAX) _MIN(_MAX(VALUE, MIN), MAX) + const uint8_t grid_x = LROUND(CLAMP(float(pos.x - MESH_MIN_X) / MESH_X_DIST, 0, GRID_MAX_POINTS_X - 1)); + const uint8_t grid_y = LROUND(CLAMP(float(pos.y - MESH_MIN_Y) / MESH_Y_DIST, 0, GRID_MAX_POINTS_Y - 1)); return search_from(grid_x, grid_y, func, data); } From d07e9585d868232d315c1cd00f31dec726f3d523 Mon Sep 17 00:00:00 2001 From: Marcio Teixeira Date: Wed, 31 Mar 2021 13:59:17 -0600 Subject: [PATCH 17/25] Fix out-of-bounds error in code --- Marlin/src/gcode/bedlevel/G26.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Marlin/src/gcode/bedlevel/G26.cpp b/Marlin/src/gcode/bedlevel/G26.cpp index 9d8c6e25e876..2609326394a6 100644 --- a/Marlin/src/gcode/bedlevel/G26.cpp +++ b/Marlin/src/gcode/bedlevel/G26.cpp @@ -288,7 +288,7 @@ typedef struct { if (TERN0(HAS_LCD_MENU, user_canceled())) return true; - if (i < (GRID_MAX_POINTS_X)) { // Can't connect to anything farther to the right than GRID_MAX_POINTS_X. + if (i < (GRID_MAX_POINTS_X - 1)) { // Can't connect to anything farther to the right than GRID_MAX_POINTS_X. // Already a half circle at the edge of the bed. if (circle_flags.marked(i, j) && circle_flags.marked(i + 1, j)) { // Test whether a leftward line can be done @@ -312,7 +312,7 @@ typedef struct { } } - if (j < (GRID_MAX_POINTS_Y)) { // Can't connect to anything further back than GRID_MAX_POINTS_Y. + if (j < (GRID_MAX_POINTS_Y - 1)) { // Can't connect to anything further back than GRID_MAX_POINTS_Y. // Already a half circle at the edge of the bed. if (circle_flags.marked(i, j) && circle_flags.marked(i, j + 1)) { // Test whether a downward line can be done From b53d4c684aaeda34aee2c8ddb32e805f654fb09f Mon Sep 17 00:00:00 2001 From: Marcio Teixeira Date: Wed, 31 Mar 2021 14:00:13 -0600 Subject: [PATCH 18/25] Fix compilation error due to function mismatch. --- Marlin/src/gcode/bedlevel/G26.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Marlin/src/gcode/bedlevel/G26.cpp b/Marlin/src/gcode/bedlevel/G26.cpp index 2609326394a6..fa5bacc89b12 100644 --- a/Marlin/src/gcode/bedlevel/G26.cpp +++ b/Marlin/src/gcode/bedlevel/G26.cpp @@ -467,7 +467,7 @@ typedef struct { #if ENABLED(UBL_HILBERT_CURVE) - auto test_func = [](uint8_t i, uint8_t j, void *data) { + auto test_func = [](uint8_t i, uint8_t j, void *data) -> bool { if (!circle_flags.marked(i, j)) { mesh_index_pair *out_point = (mesh_index_pair*)data; out_point->pos.set(i, j); // Save its data From 75a6bb54c39296a039aaa06ce8f77e4902c1a9d6 Mon Sep 17 00:00:00 2001 From: Marcio Teixeira Date: Wed, 31 Mar 2021 16:42:24 -0600 Subject: [PATCH 19/25] Fix right hand side of mesh. --- Marlin/src/gcode/bedlevel/G26.cpp | 92 ++++++++++++++++--------------- 1 file changed, 49 insertions(+), 43 deletions(-) diff --git a/Marlin/src/gcode/bedlevel/G26.cpp b/Marlin/src/gcode/bedlevel/G26.cpp index fa5bacc89b12..97931d22808f 100644 --- a/Marlin/src/gcode/bedlevel/G26.cpp +++ b/Marlin/src/gcode/bedlevel/G26.cpp @@ -288,54 +288,60 @@ typedef struct { if (TERN0(HAS_LCD_MENU, user_canceled())) return true; - if (i < (GRID_MAX_POINTS_X - 1)) { // Can't connect to anything farther to the right than GRID_MAX_POINTS_X. - // Already a half circle at the edge of the bed. - - if (circle_flags.marked(i, j) && circle_flags.marked(i + 1, j)) { // Test whether a leftward line can be done - if (!horizontal_mesh_line_flags.marked(i, j)) { - // Two circles need a horizontal line to connect them - s.x = _GET_MESH_X( i ) + (INTERSECTION_CIRCLE_RADIUS - (CROSSHAIRS_SIZE)); // right edge - e.x = _GET_MESH_X(i + 1) - (INTERSECTION_CIRCLE_RADIUS - (CROSSHAIRS_SIZE)); // left edge - - #if HAS_ENDSTOPS - LIMIT(s.x, X_MIN_POS + 1, X_MAX_POS - 1); - s.y = e.y = constrain(_GET_MESH_Y(j), Y_MIN_POS + 1, Y_MAX_POS - 1); - LIMIT(e.x, X_MIN_POS + 1, X_MAX_POS - 1); - #else - s.y = e.y = _GET_MESH_Y(j); - #endif - - if (position_is_reachable(s.x, s.y) && position_is_reachable(e.x, e.y)) - print_line_from_here_to_there(s, e); - - horizontal_mesh_line_flags.mark(i, j); // Mark done, even if skipped - } - } + if ( + // Can't connect to anything farther to the right than GRID_MAX_POINTS_X + // Already a half circle at the edge of the bed. + i < (GRID_MAX_POINTS_X - 1) && + + // Test whether a leftward line can be done + circle_flags.marked(i, j) && circle_flags.marked(i + 1, j) && + + // Two circles need a horizontal line to connect them + !horizontal_mesh_line_flags.marked(i, j) + ) { + s.x = _GET_MESH_X( i ) + (INTERSECTION_CIRCLE_RADIUS - (CROSSHAIRS_SIZE)); // right edge + e.x = _GET_MESH_X(i + 1) - (INTERSECTION_CIRCLE_RADIUS - (CROSSHAIRS_SIZE)); // left edge + + #if HAS_ENDSTOPS + LIMIT(s.x, X_MIN_POS + 1, X_MAX_POS - 1); + s.y = e.y = constrain(_GET_MESH_Y(j), Y_MIN_POS + 1, Y_MAX_POS - 1); + LIMIT(e.x, X_MIN_POS + 1, X_MAX_POS - 1); + #else + s.y = e.y = _GET_MESH_Y(j); + #endif - if (j < (GRID_MAX_POINTS_Y - 1)) { // Can't connect to anything further back than GRID_MAX_POINTS_Y. - // Already a half circle at the edge of the bed. + if (position_is_reachable(s.x, s.y) && position_is_reachable(e.x, e.y)) + print_line_from_here_to_there(s, e); - if (circle_flags.marked(i, j) && circle_flags.marked(i, j + 1)) { // Test whether a downward line can be done - if (!vertical_mesh_line_flags.marked(i, j)) { - // Two circles that need a vertical line to connect them - s.y = _GET_MESH_Y( j ) + (INTERSECTION_CIRCLE_RADIUS - (CROSSHAIRS_SIZE)); // top edge - e.y = _GET_MESH_Y(j + 1) - (INTERSECTION_CIRCLE_RADIUS - (CROSSHAIRS_SIZE)); // bottom edge + horizontal_mesh_line_flags.mark(i, j); // Mark done, even if skipped + } - #if HAS_ENDSTOPS - s.x = e.x = constrain(_GET_MESH_X(i), X_MIN_POS + 1, X_MAX_POS - 1); - LIMIT(s.y, Y_MIN_POS + 1, Y_MAX_POS - 1); - LIMIT(e.y, Y_MIN_POS + 1, Y_MAX_POS - 1); - #else - s.x = e.x = _GET_MESH_X(i); - #endif + if ( + // Can't connect to anything further back than GRID_MAX_POINTS_Y + // Already a half circle at the edge of the bed. + j < (GRID_MAX_POINTS_Y - 1) && + + // Test whether a downward line can be done + circle_flags.marked(i, j) && circle_flags.marked(i, j + 1) && + + // Two circles that need a vertical line to connect them + !vertical_mesh_line_flags.marked(i, j) + ) { + s.y = _GET_MESH_Y( j ) + (INTERSECTION_CIRCLE_RADIUS - (CROSSHAIRS_SIZE)); // top edge + e.y = _GET_MESH_Y(j + 1) - (INTERSECTION_CIRCLE_RADIUS - (CROSSHAIRS_SIZE)); // bottom edge + + #if HAS_ENDSTOPS + s.x = e.x = constrain(_GET_MESH_X(i), X_MIN_POS + 1, X_MAX_POS - 1); + LIMIT(s.y, Y_MIN_POS + 1, Y_MAX_POS - 1); + LIMIT(e.y, Y_MIN_POS + 1, Y_MAX_POS - 1); + #else + s.x = e.x = _GET_MESH_X(i); + #endif - if (position_is_reachable(s.x, s.y) && position_is_reachable(e.x, e.y)) - print_line_from_here_to_there(s, e); + if (position_is_reachable(s.x, s.y) && position_is_reachable(e.x, e.y)) + print_line_from_here_to_there(s, e); - vertical_mesh_line_flags.mark(i, j); // Mark done, even if skipped - } - } - } + vertical_mesh_line_flags.mark(i, j); // Mark done, even if skipped } } return false; From c61d258f869a05d2883567ae72abecfcfe305bb0 Mon Sep 17 00:00:00 2001 From: Marcio Teixeira Date: Wed, 31 Mar 2021 17:35:03 -0600 Subject: [PATCH 20/25] Simplify mesh connection algorithm - Rather than checking entire mesh after each point, only check neighbors - Eliminate looping through entire mesh - Eliminate flags for horizontal and vertical lines --- Marlin/src/gcode/bedlevel/G26.cpp | 97 ++++++++++--------------------- 1 file changed, 30 insertions(+), 67 deletions(-) diff --git a/Marlin/src/gcode/bedlevel/G26.cpp b/Marlin/src/gcode/bedlevel/G26.cpp index 97931d22808f..5bfbff33054f 100644 --- a/Marlin/src/gcode/bedlevel/G26.cpp +++ b/Marlin/src/gcode/bedlevel/G26.cpp @@ -149,7 +149,7 @@ constexpr float g26_e_axis_feedrate = 0.025; -static MeshFlags circle_flags, horizontal_mesh_line_flags, vertical_mesh_line_flags; +static MeshFlags circle_flags; float g26_random_deviation = 0.0; #if HAS_LCD_MENU @@ -280,71 +280,32 @@ typedef struct { move_to(e, e_pos_delta); // Get to the ending point with an appropriate amount of extrusion } - inline bool look_for_lines_to_connect() { - xyz_pos_t s, e; - s.z = e.z = layer_height; - - GRID_LOOP(i, j) { - - if (TERN0(HAS_LCD_MENU, user_canceled())) return true; - - if ( - // Can't connect to anything farther to the right than GRID_MAX_POINTS_X - // Already a half circle at the edge of the bed. - i < (GRID_MAX_POINTS_X - 1) && - - // Test whether a leftward line can be done - circle_flags.marked(i, j) && circle_flags.marked(i + 1, j) && - - // Two circles need a horizontal line to connect them - !horizontal_mesh_line_flags.marked(i, j) - ) { - s.x = _GET_MESH_X( i ) + (INTERSECTION_CIRCLE_RADIUS - (CROSSHAIRS_SIZE)); // right edge - e.x = _GET_MESH_X(i + 1) - (INTERSECTION_CIRCLE_RADIUS - (CROSSHAIRS_SIZE)); // left edge - - #if HAS_ENDSTOPS - LIMIT(s.x, X_MIN_POS + 1, X_MAX_POS - 1); - s.y = e.y = constrain(_GET_MESH_Y(j), Y_MIN_POS + 1, Y_MAX_POS - 1); - LIMIT(e.x, X_MIN_POS + 1, X_MAX_POS - 1); - #else - s.y = e.y = _GET_MESH_Y(j); - #endif - - if (position_is_reachable(s.x, s.y) && position_is_reachable(e.x, e.y)) - print_line_from_here_to_there(s, e); - - horizontal_mesh_line_flags.mark(i, j); // Mark done, even if skipped - } - - if ( - // Can't connect to anything further back than GRID_MAX_POINTS_Y - // Already a half circle at the edge of the bed. - j < (GRID_MAX_POINTS_Y - 1) && - - // Test whether a downward line can be done - circle_flags.marked(i, j) && circle_flags.marked(i, j + 1) && - - // Two circles that need a vertical line to connect them - !vertical_mesh_line_flags.marked(i, j) - ) { - s.y = _GET_MESH_Y( j ) + (INTERSECTION_CIRCLE_RADIUS - (CROSSHAIRS_SIZE)); // top edge - e.y = _GET_MESH_Y(j + 1) - (INTERSECTION_CIRCLE_RADIUS - (CROSSHAIRS_SIZE)); // bottom edge - - #if HAS_ENDSTOPS - s.x = e.x = constrain(_GET_MESH_X(i), X_MIN_POS + 1, X_MAX_POS - 1); - LIMIT(s.y, Y_MIN_POS + 1, Y_MAX_POS - 1); - LIMIT(e.y, Y_MIN_POS + 1, Y_MAX_POS - 1); - #else - s.x = e.x = _GET_MESH_X(i); - #endif - - if (position_is_reachable(s.x, s.y) && position_is_reachable(e.x, e.y)) - print_line_from_here_to_there(s, e); + void connect_neighbor_with_line(const xy_int8_t &p1, int8_t dx, int8_t dy) { + xy_int8_t p2; + p2.x = p1.x + dx; + p2.y = p1.y + dy; + + if (p2.x < 0 || p2.x >= GRID_MAX_POINTS_X) return; + if (p2.y < 0 || p2.y >= GRID_MAX_POINTS_Y) return; + + if(circle_flags.marked(p1.x, p1.y) && circle_flags.marked(p2.x, p2.y)) { + xyz_pos_t s, e; + s.x = _GET_MESH_X(p1.x) + (INTERSECTION_CIRCLE_RADIUS - (CROSSHAIRS_SIZE)) * dx; + e.x = _GET_MESH_X(p2.x) - (INTERSECTION_CIRCLE_RADIUS - (CROSSHAIRS_SIZE)) * dx; + s.y = _GET_MESH_Y(p1.y) + (INTERSECTION_CIRCLE_RADIUS - (CROSSHAIRS_SIZE)) * dy; + e.y = _GET_MESH_Y(p2.y) - (INTERSECTION_CIRCLE_RADIUS - (CROSSHAIRS_SIZE)) * dy; + s.z = e.z = layer_height; + + #if HAS_ENDSTOPS + LIMIT(s.y, Y_MIN_POS + 1, Y_MAX_POS - 1); + LIMIT(e.y, Y_MIN_POS + 1, Y_MAX_POS - 1); + LIMIT(s.x, X_MIN_POS + 1, X_MAX_POS - 1); + LIMIT(e.x, X_MIN_POS + 1, X_MAX_POS - 1); + #endif - vertical_mesh_line_flags.mark(i, j); // Mark done, even if skipped - } + if (position_is_reachable(s.x, s.y) && position_is_reachable(e.x, e.y)) + print_line_from_here_to_there(s, e); } - return false; } /** @@ -735,8 +696,6 @@ void GcodeSuite::G26() { */ circle_flags.reset(); - horizontal_mesh_line_flags.reset(); - vertical_mesh_line_flags.reset(); // Move nozzle to the specified height for the first layer destination = current_position; @@ -883,7 +842,11 @@ void GcodeSuite::G26() { #endif // !ARC_SUPPORT - if (g26.look_for_lines_to_connect()) goto LEAVE; + g26.connect_neighbor_with_line(location.pos, -1, 0); + g26.connect_neighbor_with_line(location.pos, 1, 0); + g26.connect_neighbor_with_line(location.pos, 0, -1); + g26.connect_neighbor_with_line(location.pos, 0, 1); + if (TERN0(HAS_LCD_MENU, user_canceled())) goto LEAVE; } SERIAL_FLUSH(); // Prevent host M105 buffer overrun. From 32691785eede7dadf185dce9d0d95a9d986004f7 Mon Sep 17 00:00:00 2001 From: Scott Lahteine Date: Wed, 31 Mar 2021 22:01:50 -0500 Subject: [PATCH 21/25] Add parentheses and cell-oriented max --- Marlin/src/core/utility.h | 2 +- Marlin/src/feature/bedlevel/abl/abl.cpp | 38 +++++++-------- Marlin/src/feature/bedlevel/hilbert_curve.cpp | 7 ++- .../bedlevel/mbl/mesh_bed_leveling.cpp | 8 ++-- .../feature/bedlevel/mbl/mesh_bed_leveling.h | 14 +++--- Marlin/src/feature/bedlevel/ubl/ubl.cpp | 4 +- Marlin/src/feature/bedlevel/ubl/ubl.h | 46 +++++++++---------- .../src/feature/bedlevel/ubl/ubl_motion.cpp | 4 +- Marlin/src/gcode/bedlevel/G26.cpp | 4 +- Marlin/src/gcode/bedlevel/M420.cpp | 4 +- Marlin/src/gcode/bedlevel/abl/G29.cpp | 6 +-- Marlin/src/gcode/bedlevel/mbl/G29.cpp | 10 ++-- Marlin/src/inc/Conditionals_post.h | 5 ++ Marlin/src/inc/SanityCheck.h | 6 +-- Marlin/src/lcd/HD44780/marlinui_HD44780.cpp | 2 +- Marlin/src/lcd/dogm/marlinui_DOGM.cpp | 2 +- .../screens/bed_mesh_screen.cpp | 10 ++-- Marlin/src/lcd/extui/ui_api.cpp | 2 +- Marlin/src/lcd/menu/menu_bed_leveling.cpp | 4 +- Marlin/src/lcd/menu/menu_ubl.cpp | 4 +- Marlin/src/lcd/tft/ui_320x240.cpp | 14 +++--- Marlin/src/lcd/tft/ui_480x320.cpp | 14 +++--- Marlin/src/module/settings.cpp | 4 +- 23 files changed, 109 insertions(+), 105 deletions(-) diff --git a/Marlin/src/core/utility.h b/Marlin/src/core/utility.h index 645a4be80735..aaa241d4600d 100644 --- a/Marlin/src/core/utility.h +++ b/Marlin/src/core/utility.h @@ -34,7 +34,7 @@ void safe_delay(millis_t ms); inline void serial_delay(const millis_t) {} #endif -#if GRID_MAX_POINTS_X && GRID_MAX_POINTS_Y +#if (GRID_MAX_POINTS_X) && (GRID_MAX_POINTS_Y) // 16x16 bit arrays template diff --git a/Marlin/src/feature/bedlevel/abl/abl.cpp b/Marlin/src/feature/bedlevel/abl/abl.cpp index a663ee571df5..b5abb19146f3 100644 --- a/Marlin/src/feature/bedlevel/abl/abl.cpp +++ b/Marlin/src/feature/bedlevel/abl/abl.cpp @@ -85,9 +85,9 @@ static void extrapolate_one_point(const uint8_t x, const uint8_t y, const int8_t //#define EXTRAPOLATE_FROM_EDGE #if ENABLED(EXTRAPOLATE_FROM_EDGE) - #if GRID_MAX_POINTS_X < GRID_MAX_POINTS_Y + #if (GRID_MAX_POINTS_X) < (GRID_MAX_POINTS_Y) #define HALF_IN_X - #elif GRID_MAX_POINTS_Y < GRID_MAX_POINTS_X + #elif (GRID_MAX_POINTS_Y) < (GRID_MAX_POINTS_X) #define HALF_IN_Y #endif #endif @@ -98,23 +98,23 @@ static void extrapolate_one_point(const uint8_t x, const uint8_t y, const int8_t */ void extrapolate_unprobed_bed_level() { #ifdef HALF_IN_X - constexpr uint8_t ctrx2 = 0, xlen = GRID_MAX_POINTS_X - 1; + constexpr uint8_t ctrx2 = 0, xend = GRID_MAX_POINTS_X - 1; #else - constexpr uint8_t ctrx1 = (GRID_MAX_POINTS_X - 1) / 2, // left-of-center - ctrx2 = (GRID_MAX_POINTS_X) / 2, // right-of-center - xlen = ctrx1; + constexpr uint8_t ctrx1 = (GRID_MAX_CELLS_X) / 2, // left-of-center + ctrx2 = (GRID_MAX_POINTS_X) / 2, // right-of-center + xend = ctrx1; #endif #ifdef HALF_IN_Y - constexpr uint8_t ctry2 = 0, ylen = GRID_MAX_POINTS_Y - 1; + constexpr uint8_t ctry2 = 0, yend = GRID_MAX_POINTS_Y - 1; #else - constexpr uint8_t ctry1 = (GRID_MAX_POINTS_Y - 1) / 2, // top-of-center - ctry2 = (GRID_MAX_POINTS_Y) / 2, // bottom-of-center - ylen = ctry1; + constexpr uint8_t ctry1 = (GRID_MAX_CELLS_Y) / 2, // top-of-center + ctry2 = (GRID_MAX_POINTS_Y) / 2, // bottom-of-center + yend = ctry1; #endif - LOOP_LE_N(xo, xlen) - LOOP_LE_N(yo, ylen) { + LOOP_LE_N(xo, xend) + LOOP_LE_N(yo, yend) { uint8_t x2 = ctrx2 + xo, y2 = ctry2 + yo; #ifndef HALF_IN_X const uint8_t x1 = ctrx1 - xo; @@ -143,8 +143,8 @@ void print_bilinear_leveling_grid() { #if ENABLED(ABL_BILINEAR_SUBDIVISION) - #define ABL_GRID_POINTS_VIRT_X (GRID_MAX_POINTS_X - 1) * (BILINEAR_SUBDIVISIONS) + 1 - #define ABL_GRID_POINTS_VIRT_Y (GRID_MAX_POINTS_Y - 1) * (BILINEAR_SUBDIVISIONS) + 1 + #define ABL_GRID_POINTS_VIRT_X GRID_MAX_CELLS_X * (BILINEAR_SUBDIVISIONS) + 1 + #define ABL_GRID_POINTS_VIRT_Y GRID_MAX_CELLS_Y * (BILINEAR_SUBDIVISIONS) + 1 #define ABL_TEMP_POINTS_X (GRID_MAX_POINTS_X + 2) #define ABL_TEMP_POINTS_Y (GRID_MAX_POINTS_Y + 2) float z_values_virt[ABL_GRID_POINTS_VIRT_X][ABL_GRID_POINTS_VIRT_Y]; @@ -161,7 +161,7 @@ void print_bilinear_leveling_grid() { #define LINEAR_EXTRAPOLATION(E, I) ((E) * 2 - (I)) float bed_level_virt_coord(const uint8_t x, const uint8_t y) { uint8_t ep = 0, ip = 1; - if (x > GRID_MAX_POINTS_X + 1 || y > GRID_MAX_POINTS_Y + 1) { + if (x > (GRID_MAX_POINTS_X) + 1 || y > (GRID_MAX_POINTS_Y) + 1) { // The requested point requires extrapolating two points beyond the mesh. // These values are only requested for the edges of the mesh, which are always an actual mesh point, // and do not require interpolation. When interpolation is not needed, this "Mesh + 2" point is @@ -171,8 +171,8 @@ void print_bilinear_leveling_grid() { } if (!x || x == ABL_TEMP_POINTS_X - 1) { if (x) { - ep = GRID_MAX_POINTS_X - 1; - ip = GRID_MAX_POINTS_X - 2; + ep = (GRID_MAX_POINTS_X) - 1; + ip = GRID_MAX_CELLS_X - 1; } if (WITHIN(y, 1, ABL_TEMP_POINTS_Y - 2)) return LINEAR_EXTRAPOLATION( @@ -187,8 +187,8 @@ void print_bilinear_leveling_grid() { } if (!y || y == ABL_TEMP_POINTS_Y - 1) { if (y) { - ep = GRID_MAX_POINTS_Y - 1; - ip = GRID_MAX_POINTS_Y - 2; + ep = (GRID_MAX_POINTS_Y) - 1; + ip = GRID_MAX_CELLS_Y - 1; } if (WITHIN(x, 1, ABL_TEMP_POINTS_X - 2)) return LINEAR_EXTRAPOLATION( diff --git a/Marlin/src/feature/bedlevel/hilbert_curve.cpp b/Marlin/src/feature/bedlevel/hilbert_curve.cpp index af270735d12d..48eeac9dee7f 100644 --- a/Marlin/src/feature/bedlevel/hilbert_curve.cpp +++ b/Marlin/src/feature/bedlevel/hilbert_curve.cpp @@ -36,7 +36,7 @@ constexpr uint8_t dim = _BV(ord); static inline bool eval_candidate(int8_t x, int8_t y, hilbert_curve::callback_ptr func, void *data) { // The print bed likely has fewer points than the full Hilbert // curve, so cull unecessary points - return x < GRID_MAX_POINTS_X && y < GRID_MAX_POINTS_Y ? func(x, y, data) : false; + return x < (GRID_MAX_POINTS_X) && y < (GRID_MAX_POINTS_Y) ? func(x, y, data) : false; } 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,9 +102,8 @@ bool hilbert_curve::search_from(uint8_t x, uint8_t y, hilbert_curve::callback_pt */ bool hilbert_curve::search_from_closest(const xy_pos_t &pos, hilbert_curve::callback_ptr func, void *data) { // Find closest grid intersection - #define CLAMP(VALUE,MIN,MAX) _MIN(_MAX(VALUE, MIN), MAX) - const uint8_t grid_x = LROUND(CLAMP(float(pos.x - MESH_MIN_X) / MESH_X_DIST, 0, GRID_MAX_POINTS_X - 1)); - const uint8_t grid_y = LROUND(CLAMP(float(pos.y - MESH_MIN_Y) / MESH_Y_DIST, 0, GRID_MAX_POINTS_Y - 1)); + const uint8_t grid_x = LROUND(LIMIT(float(pos.x - (MESH_MIN_X)) / (MESH_X_DIST), 0, (GRID_MAX_POINTS_X) - 1)); + const uint8_t grid_y = LROUND(LIMIT(float(pos.y - (MESH_MIN_Y)) / (MESH_Y_DIST), 0, (GRID_MAX_POINTS_Y) - 1)); return search_from(grid_x, grid_y, func, data); } diff --git a/Marlin/src/feature/bedlevel/mbl/mesh_bed_leveling.cpp b/Marlin/src/feature/bedlevel/mbl/mesh_bed_leveling.cpp index ec5b95c108b8..f78860045cf6 100644 --- a/Marlin/src/feature/bedlevel/mbl/mesh_bed_leveling.cpp +++ b/Marlin/src/feature/bedlevel/mbl/mesh_bed_leveling.cpp @@ -64,10 +64,10 @@ void mesh_bed_leveling::line_to_destination(const feedRate_t &scaled_fr_mm_s, uint8_t x_splits, uint8_t y_splits) { // Get current and destination cells for this line xy_int8_t scel = cell_indexes(current_position), ecel = cell_indexes(destination); - NOMORE(scel.x, GRID_MAX_POINTS_X - 2); - NOMORE(scel.y, GRID_MAX_POINTS_Y - 2); - NOMORE(ecel.x, GRID_MAX_POINTS_X - 2); - NOMORE(ecel.y, GRID_MAX_POINTS_Y - 2); + NOMORE(scel.x, GRID_MAX_CELLS_X - 1); + NOMORE(scel.y, GRID_MAX_CELLS_Y - 1); + NOMORE(ecel.x, GRID_MAX_CELLS_X - 1); + NOMORE(ecel.y, GRID_MAX_CELLS_Y - 1); // Start and end in the same cell? No split needed. if (scel == ecel) { diff --git a/Marlin/src/feature/bedlevel/mbl/mesh_bed_leveling.h b/Marlin/src/feature/bedlevel/mbl/mesh_bed_leveling.h index ade7a931401a..96d5589ca09f 100644 --- a/Marlin/src/feature/bedlevel/mbl/mesh_bed_leveling.h +++ b/Marlin/src/feature/bedlevel/mbl/mesh_bed_leveling.h @@ -32,8 +32,8 @@ enum MeshLevelingState : char { MeshReset // G29 S5 }; -#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)) +#define MESH_X_DIST (float(MESH_MAX_X - (MESH_MIN_X)) / (GRID_MAX_CELLS_X)) +#define MESH_Y_DIST (float(MESH_MAX_Y - (MESH_MIN_Y)) / (GRID_MAX_CELLS_Y)) #define _GET_MESH_X(I) mbl.index_to_xpos[I] #define _GET_MESH_Y(J) mbl.index_to_ypos[J] #define Z_VALUES_ARR mbl.z_values @@ -61,7 +61,7 @@ class mesh_bed_leveling { static inline void zigzag(const int8_t index, int8_t &px, int8_t &py) { px = index % (GRID_MAX_POINTS_X); py = index / (GRID_MAX_POINTS_X); - if (py & 1) px = (GRID_MAX_POINTS_X - 1) - px; // Zig zag + if (py & 1) px = (GRID_MAX_POINTS_X) - 1 - px; // Zig zag } static void set_zigzag_z(const int8_t index, const float &z) { @@ -72,11 +72,11 @@ class mesh_bed_leveling { static int8_t cell_index_x(const float &x) { int8_t cx = (x - (MESH_MIN_X)) * RECIPROCAL(MESH_X_DIST); - return constrain(cx, 0, (GRID_MAX_POINTS_X) - 2); + return constrain(cx, 0, GRID_MAX_CELLS_X - 1); } static int8_t cell_index_y(const float &y) { int8_t cy = (y - (MESH_MIN_Y)) * RECIPROCAL(MESH_Y_DIST); - return constrain(cy, 0, (GRID_MAX_POINTS_Y) - 2); + return constrain(cy, 0, GRID_MAX_CELLS_Y - 1); } static inline xy_int8_t cell_indexes(const float &x, const float &y) { return { cell_index_x(x), cell_index_y(y) }; @@ -85,11 +85,11 @@ class mesh_bed_leveling { static int8_t probe_index_x(const float &x) { int8_t px = (x - (MESH_MIN_X) + 0.5f * (MESH_X_DIST)) * RECIPROCAL(MESH_X_DIST); - return WITHIN(px, 0, GRID_MAX_POINTS_X - 1) ? px : -1; + return WITHIN(px, 0, (GRID_MAX_POINTS_X) - 1) ? px : -1; } static int8_t probe_index_y(const float &y) { int8_t py = (y - (MESH_MIN_Y) + 0.5f * (MESH_Y_DIST)) * RECIPROCAL(MESH_Y_DIST); - return WITHIN(py, 0, GRID_MAX_POINTS_Y - 1) ? py : -1; + return WITHIN(py, 0, (GRID_MAX_POINTS_Y) - 1) ? py : -1; } static inline xy_int8_t probe_indexes(const float &x, const float &y) { return { probe_index_x(x), probe_index_y(y) }; diff --git a/Marlin/src/feature/bedlevel/ubl/ubl.cpp b/Marlin/src/feature/bedlevel/ubl/ubl.cpp index 05b96daefa83..9c71a0c5a4c5 100644 --- a/Marlin/src/feature/bedlevel/ubl/ubl.cpp +++ b/Marlin/src/feature/bedlevel/ubl/ubl.cpp @@ -190,7 +190,7 @@ void unified_bed_leveling::display_map(const int map_type) { const xy_int8_t curr = closest_indexes(xy_pos_t(current_position) + probe.offset_xy); if (!lcd) SERIAL_EOL(); - for (int8_t j = GRID_MAX_POINTS_Y - 1; j >= 0; j--) { + for (int8_t j = (GRID_MAX_POINTS_Y) - 1; j >= 0; j--) { // Row Label (J index) if (human) { @@ -217,7 +217,7 @@ void unified_bed_leveling::display_map(const int map_type) { if (human && f >= 0.0) SERIAL_CHAR(f > 0 ? '+' : ' '); // Display sign also for positive numbers (' ' for 0) SERIAL_ECHO_F(f, 3); // Positive: 5 digits, Negative: 6 digits } - if (csv && i < GRID_MAX_POINTS_X - 1) SERIAL_CHAR('\t'); + if (csv && i < (GRID_MAX_POINTS_X) - 1) SERIAL_CHAR('\t'); // Closing Brace or Space if (human) SERIAL_CHAR(is_current ? ']' : ' '); diff --git a/Marlin/src/feature/bedlevel/ubl/ubl.h b/Marlin/src/feature/bedlevel/ubl/ubl.h index 56de4e45ba3a..d56e2e4f5056 100644 --- a/Marlin/src/feature/bedlevel/ubl/ubl.h +++ b/Marlin/src/feature/bedlevel/ubl/ubl.h @@ -38,8 +38,8 @@ enum MeshPointType : char { INVALID, REAL, SET_IN_BITMAP }; 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)) +#define MESH_X_DIST (float(MESH_MAX_X - (MESH_MIN_X)) / (GRID_MAX_CELLS_X)) +#define MESH_Y_DIST (float(MESH_MAX_Y - (MESH_MIN_Y)) / (GRID_MAX_CELLS_Y)) #if ENABLED(OPTIMIZED_MESH_STORAGE) typedef int16_t mesh_store_t[GRID_MAX_POINTS_X][GRID_MAX_POINTS_Y]; @@ -142,19 +142,19 @@ class unified_bed_leveling { } static int8_t cell_index_x_valid(const float &x) { - return WITHIN(cell_index_x_raw(x), 0, (GRID_MAX_POINTS_X - 2)); + return WITHIN(cell_index_x_raw(x), 0, GRID_MAX_CELLS_X - 1); } static int8_t cell_index_y_valid(const float &y) { - return WITHIN(cell_index_y_raw(y), 0, (GRID_MAX_POINTS_Y - 2)); + return WITHIN(cell_index_y_raw(y), 0, GRID_MAX_CELLS_Y - 1); } static int8_t cell_index_x(const float &x) { - return constrain(cell_index_x_raw(x), 0, (GRID_MAX_POINTS_X) - 2); + return constrain(cell_index_x_raw(x), 0, GRID_MAX_CELLS_X - 1); } static int8_t cell_index_y(const float &y) { - return constrain(cell_index_y_raw(y), 0, (GRID_MAX_POINTS_Y) - 2); + return constrain(cell_index_y_raw(y), 0, GRID_MAX_CELLS_Y - 1); } static inline xy_int8_t cell_indexes(const float &x, const float &y) { @@ -164,11 +164,11 @@ class unified_bed_leveling { static int8_t closest_x_index(const float &x) { const int8_t px = (x - (MESH_MIN_X) + (MESH_X_DIST) * 0.5) * RECIPROCAL(MESH_X_DIST); - return WITHIN(px, 0, GRID_MAX_POINTS_X - 1) ? px : -1; + return WITHIN(px, 0, (GRID_MAX_POINTS_X) - 1) ? px : -1; } static int8_t closest_y_index(const float &y) { const int8_t py = (y - (MESH_MIN_Y) + (MESH_Y_DIST) * 0.5) * RECIPROCAL(MESH_Y_DIST); - return WITHIN(py, 0, GRID_MAX_POINTS_Y - 1) ? py : -1; + return WITHIN(py, 0, (GRID_MAX_POINTS_Y) - 1) ? py : -1; } static inline xy_int8_t closest_indexes(const xy_pos_t &xy) { return { closest_x_index(xy.x), closest_y_index(xy.y) }; @@ -204,10 +204,10 @@ class unified_bed_leveling { * the case where the printer is making a vertical line that only crosses horizontal mesh lines. */ static inline float z_correction_for_x_on_horizontal_mesh_line(const float &rx0, const int x1_i, const int yi) { - if (!WITHIN(x1_i, 0, GRID_MAX_POINTS_X - 1) || !WITHIN(yi, 0, GRID_MAX_POINTS_Y - 1)) { + if (!WITHIN(x1_i, 0, (GRID_MAX_POINTS_X) - 1) || !WITHIN(yi, 0, (GRID_MAX_POINTS_Y) - 1)) { if (DEBUGGING(LEVELING)) { - if (WITHIN(x1_i, 0, GRID_MAX_POINTS_X - 1)) DEBUG_ECHOPGM("yi"); else DEBUG_ECHOPGM("x1_i"); + if (WITHIN(x1_i, 0, (GRID_MAX_POINTS_X) - 1)) DEBUG_ECHOPGM("yi"); else DEBUG_ECHOPGM("x1_i"); DEBUG_ECHOLNPAIR(" out of bounds in z_correction_for_x_on_horizontal_mesh_line(rx0=", rx0, ",x1_i=", x1_i, ",yi=", yi, ")"); } @@ -218,19 +218,19 @@ class unified_bed_leveling { const float xratio = (rx0 - mesh_index_to_xpos(x1_i)) * RECIPROCAL(MESH_X_DIST), z1 = z_values[x1_i][yi]; - 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 - // If it is, it is clamped to the last element of the - // z_values[][] array and no correction is applied. + 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 + // If it is, it is clamped to the last element of the + // z_values[][] array and no correction is applied. } // // See comments above for z_correction_for_x_on_horizontal_mesh_line // static inline float z_correction_for_y_on_vertical_mesh_line(const float &ry0, const int xi, const int y1_i) { - if (!WITHIN(xi, 0, GRID_MAX_POINTS_X - 1) || !WITHIN(y1_i, 0, GRID_MAX_POINTS_Y - 1)) { + if (!WITHIN(xi, 0, (GRID_MAX_POINTS_X) - 1) || !WITHIN(y1_i, 0, (GRID_MAX_POINTS_Y) - 1)) { if (DEBUGGING(LEVELING)) { - if (WITHIN(xi, 0, GRID_MAX_POINTS_X - 1)) DEBUG_ECHOPGM("y1_i"); else DEBUG_ECHOPGM("xi"); + if (WITHIN(xi, 0, (GRID_MAX_POINTS_X) - 1)) DEBUG_ECHOPGM("y1_i"); else DEBUG_ECHOPGM("xi"); DEBUG_ECHOLNPAIR(" out of bounds in z_correction_for_y_on_vertical_mesh_line(ry0=", ry0, ", xi=", xi, ", y1_i=", y1_i, ")"); } @@ -241,9 +241,9 @@ class unified_bed_leveling { const float yratio = (ry0 - mesh_index_to_ypos(y1_i)) * RECIPROCAL(MESH_Y_DIST), z1 = z_values[xi][y1_i]; - 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 - // If it is, it is clamped to the last element of the - // z_values[][] array and no correction is applied. + 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 + // If it is, it is clamped to the last element of the + // z_values[][] array and no correction is applied. } /** @@ -266,11 +266,11 @@ class unified_bed_leveling { const float z1 = calc_z0(rx0, mesh_index_to_xpos(cx), z_values[cx][cy], - mesh_index_to_xpos(cx + 1), z_values[_MIN(cx, GRID_MAX_POINTS_X - 2) + 1][cy]); + mesh_index_to_xpos(cx + 1), z_values[_MIN(cx, (GRID_MAX_POINTS_X) - 2) + 1][cy]); const float z2 = calc_z0(rx0, - mesh_index_to_xpos(cx), z_values[cx][_MIN(cy, GRID_MAX_POINTS_Y - 2) + 1], - mesh_index_to_xpos(cx + 1), z_values[_MIN(cx, GRID_MAX_POINTS_X - 2) + 1][_MIN(cy, GRID_MAX_POINTS_Y - 2) + 1]); + mesh_index_to_xpos(cx), z_values[cx][_MIN(cy, (GRID_MAX_POINTS_Y) - 2) + 1], + mesh_index_to_xpos(cx + 1), z_values[_MIN(cx, (GRID_MAX_POINTS_X) - 2) + 1][_MIN(cy, (GRID_MAX_POINTS_Y) - 2) + 1]); float z0 = calc_z0(ry0, mesh_index_to_ypos(cy), z1, @@ -302,10 +302,10 @@ class unified_bed_leveling { static inline float get_z_correction(const xy_pos_t &pos) { return get_z_correction(pos.x, pos.y); } static inline float mesh_index_to_xpos(const uint8_t i) { - return i < GRID_MAX_POINTS_X ? pgm_read_float(&_mesh_index_to_xpos[i]) : MESH_MIN_X + i * (MESH_X_DIST); + return i < (GRID_MAX_POINTS_X) ? pgm_read_float(&_mesh_index_to_xpos[i]) : MESH_MIN_X + i * (MESH_X_DIST); } static inline float mesh_index_to_ypos(const uint8_t i) { - return i < GRID_MAX_POINTS_Y ? pgm_read_float(&_mesh_index_to_ypos[i]) : MESH_MIN_Y + i * (MESH_Y_DIST); + return i < (GRID_MAX_POINTS_Y) ? pgm_read_float(&_mesh_index_to_ypos[i]) : MESH_MIN_Y + i * (MESH_Y_DIST); } #if UBL_SEGMENTED diff --git a/Marlin/src/feature/bedlevel/ubl/ubl_motion.cpp b/Marlin/src/feature/bedlevel/ubl/ubl_motion.cpp index 33b4f03ac290..d8d3ce132763 100644 --- a/Marlin/src/feature/bedlevel/ubl/ubl_motion.cpp +++ b/Marlin/src/feature/bedlevel/ubl/ubl_motion.cpp @@ -397,8 +397,8 @@ int8_t((raw.x - (MESH_MIN_X)) * RECIPROCAL(MESH_X_DIST)), int8_t((raw.y - (MESH_MIN_Y)) * RECIPROCAL(MESH_Y_DIST)) }; - LIMIT(icell.x, 0, (GRID_MAX_POINTS_X) - 1); - LIMIT(icell.y, 0, (GRID_MAX_POINTS_Y) - 1); + LIMIT(icell.x, 0, GRID_MAX_CELLS_X); + LIMIT(icell.y, 0, GRID_MAX_CELLS_Y); float z_x0y0 = z_values[icell.x ][icell.y ], // z at lower left corner z_x1y0 = z_values[icell.x+1][icell.y ], // z at upper left corner diff --git a/Marlin/src/gcode/bedlevel/G26.cpp b/Marlin/src/gcode/bedlevel/G26.cpp index 5bfbff33054f..fa8dc07a8d52 100644 --- a/Marlin/src/gcode/bedlevel/G26.cpp +++ b/Marlin/src/gcode/bedlevel/G26.cpp @@ -285,8 +285,8 @@ typedef struct { p2.x = p1.x + dx; p2.y = p1.y + dy; - if (p2.x < 0 || p2.x >= GRID_MAX_POINTS_X) return; - if (p2.y < 0 || p2.y >= GRID_MAX_POINTS_Y) return; + if (p2.x < 0 || p2.x >= (GRID_MAX_POINTS_X)) return; + if (p2.y < 0 || p2.y >= (GRID_MAX_POINTS_Y)) return; if(circle_flags.marked(p1.x, p1.y) && circle_flags.marked(p2.x, p2.y)) { xyz_pos_t s, e; diff --git a/Marlin/src/gcode/bedlevel/M420.cpp b/Marlin/src/gcode/bedlevel/M420.cpp index 55b14c19dc06..e42a5902653c 100644 --- a/Marlin/src/gcode/bedlevel/M420.cpp +++ b/Marlin/src/gcode/bedlevel/M420.cpp @@ -68,8 +68,8 @@ void GcodeSuite::M420() { y_min = probe.min_y(), y_max = probe.max_y(); #if ENABLED(AUTO_BED_LEVELING_BILINEAR) bilinear_start.set(x_min, y_min); - bilinear_grid_spacing.set((x_max - x_min) / (GRID_MAX_POINTS_X - 1), - (y_max - y_min) / (GRID_MAX_POINTS_Y - 1)); + bilinear_grid_spacing.set((x_max - x_min) / (GRID_MAX_CELLS_X), + (y_max - y_min) / (GRID_MAX_CELLS_Y)); #endif GRID_LOOP(x, y) { Z_VALUES(x, y) = 0.001 * random(-200, 200); diff --git a/Marlin/src/gcode/bedlevel/abl/G29.cpp b/Marlin/src/gcode/bedlevel/abl/G29.cpp index a746b86108eb..cd92f1d1741f 100644 --- a/Marlin/src/gcode/bedlevel/abl/G29.cpp +++ b/Marlin/src/gcode/bedlevel/abl/G29.cpp @@ -291,10 +291,10 @@ G29_TYPE GcodeSuite::G29() { // Get nearest i / j from rx / ry i = (rx - bilinear_start.x + 0.5 * gridSpacing.x) / gridSpacing.x; j = (ry - bilinear_start.y + 0.5 * gridSpacing.y) / gridSpacing.y; - LIMIT(i, 0, GRID_MAX_POINTS_X - 1); - LIMIT(j, 0, GRID_MAX_POINTS_Y - 1); + LIMIT(i, 0, (GRID_MAX_POINTS_X) - 1); + LIMIT(j, 0, (GRID_MAX_POINTS_Y) - 1); } - if (WITHIN(i, 0, GRID_MAX_POINTS_X - 1) && WITHIN(j, 0, GRID_MAX_POINTS_Y)) { + if (WITHIN(i, 0, (GRID_MAX_POINTS_X) - 1) && WITHIN(j, 0, (GRID_MAX_POINTS_Y) - 1)) { set_bed_leveling_enabled(false); z_values[i][j] = rz; TERN_(ABL_BILINEAR_SUBDIVISION, bed_level_virt_interpolate()); diff --git a/Marlin/src/gcode/bedlevel/mbl/G29.cpp b/Marlin/src/gcode/bedlevel/mbl/G29.cpp index 278a39b4f8db..1ec514c3ec3b 100644 --- a/Marlin/src/gcode/bedlevel/mbl/G29.cpp +++ b/Marlin/src/gcode/bedlevel/mbl/G29.cpp @@ -106,7 +106,7 @@ void GcodeSuite::G29() { SET_SOFT_ENDSTOP_LOOSE(false); } // If there's another point to sample, move there with optional lift. - if (mbl_probe_index < GRID_MAX_POINTS) { + if (mbl_probe_index < (GRID_MAX_POINTS)) { // Disable software endstops to allow manual adjustment // If G29 is left hanging without completion they won't be re-enabled! SET_SOFT_ENDSTOP_LOOSE(true); @@ -142,8 +142,8 @@ void GcodeSuite::G29() { case MeshSet: if (parser.seenval('I')) { ix = parser.value_int(); - if (!WITHIN(ix, 0, GRID_MAX_POINTS_X - 1)) { - SERIAL_ECHOLNPAIR("I out of range (0-", GRID_MAX_POINTS_X - 1, ")"); + if (!WITHIN(ix, 0, (GRID_MAX_POINTS_X) - 1)) { + SERIAL_ECHOLNPAIR("I out of range (0-", (GRID_MAX_POINTS_X) - 1, ")"); return; } } @@ -152,8 +152,8 @@ void GcodeSuite::G29() { if (parser.seenval('J')) { iy = parser.value_int(); - if (!WITHIN(iy, 0, GRID_MAX_POINTS_Y - 1)) { - SERIAL_ECHOLNPAIR("J out of range (0-", GRID_MAX_POINTS_Y - 1, ")"); + if (!WITHIN(iy, 0, (GRID_MAX_POINTS_Y) - 1)) { + SERIAL_ECHOLNPAIR("J out of range (0-", (GRID_MAX_POINTS_Y) - 1, ")"); return; } } diff --git a/Marlin/src/inc/Conditionals_post.h b/Marlin/src/inc/Conditionals_post.h index 2433050528fa..337cf2a950e4 100644 --- a/Marlin/src/inc/Conditionals_post.h +++ b/Marlin/src/inc/Conditionals_post.h @@ -224,6 +224,11 @@ #endif #endif +#ifdef GRID_MAX_POINTS_X + #define GRID_MAX_CELLS_X (GRID_MAX_POINTS_X - 1) + #define GRID_MAX_CELLS_Y (GRID_MAX_POINTS_Y - 1) +#endif + /** * Host keep alive */ diff --git a/Marlin/src/inc/SanityCheck.h b/Marlin/src/inc/SanityCheck.h index 287f0c5600f2..39c16f03315d 100644 --- a/Marlin/src/inc/SanityCheck.h +++ b/Marlin/src/inc/SanityCheck.h @@ -1263,9 +1263,9 @@ static_assert(Y_MAX_LENGTH >= Y_BED_SIZE, "Movement bounds (Y_MIN_POS, Y_MAX_POS #elif ENABLED(DELTA_CALIBRATION_MENU) && !HAS_LCD_MENU #error "DELTA_CALIBRATION_MENU requires an LCD Controller." #elif ABL_GRID - #if (GRID_MAX_POINTS_X & 1) == 0 || (GRID_MAX_POINTS_Y & 1) == 0 + #if ((GRID_MAX_POINTS_X) & 1) == 0 || ((GRID_MAX_POINTS_Y) & 1) == 0 #error "DELTA requires GRID_MAX_POINTS_X and GRID_MAX_POINTS_Y to be odd numbers." - #elif GRID_MAX_POINTS_X < 3 + #elif (GRID_MAX_POINTS_X) < 3 #error "DELTA requires GRID_MAX_POINTS_X and GRID_MAX_POINTS_Y to be 3 or higher." #endif #endif @@ -1518,7 +1518,7 @@ static_assert(Y_MAX_LENGTH >= Y_BED_SIZE, "Movement bounds (Y_MIN_POS, Y_MAX_POS // Mesh Bed Leveling #if ENABLED(DELTA) #error "MESH_BED_LEVELING is not compatible with DELTA printers." - #elif GRID_MAX_POINTS_X > 9 || GRID_MAX_POINTS_Y > 9 + #elif (GRID_MAX_POINTS_X) > 9 || (GRID_MAX_POINTS_Y) > 9 #error "GRID_MAX_POINTS_X and GRID_MAX_POINTS_Y must be less than 10 for MBL." #endif diff --git a/Marlin/src/lcd/HD44780/marlinui_HD44780.cpp b/Marlin/src/lcd/HD44780/marlinui_HD44780.cpp index e18ed7273cd1..61c7ce18d6df 100644 --- a/Marlin/src/lcd/HD44780/marlinui_HD44780.cpp +++ b/Marlin/src/lcd/HD44780/marlinui_HD44780.cpp @@ -1279,7 +1279,7 @@ void MarlinUI::draw_status_screen() { pixels_per_x_mesh_pnt, pixels_per_y_mesh_pnt, suppress_x_offset = 0, suppress_y_offset = 0; - const uint8_t y_plot_inv = (GRID_MAX_POINTS_Y - 1) - y_plot; + const uint8_t y_plot_inv = (GRID_MAX_POINTS_Y) - 1 - y_plot; upper_left.column = 0; upper_left.row = 0; diff --git a/Marlin/src/lcd/dogm/marlinui_DOGM.cpp b/Marlin/src/lcd/dogm/marlinui_DOGM.cpp index c2d2cf43af48..72d9df009145 100644 --- a/Marlin/src/lcd/dogm/marlinui_DOGM.cpp +++ b/Marlin/src/lcd/dogm/marlinui_DOGM.cpp @@ -529,7 +529,7 @@ void MarlinUI::clear_lcd() { } // Automatically cleared by Picture Loop // Fill in the Specified Mesh Point - 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 + 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 // invert the Y to get it to plot in the right location. const u8g_uint_t by = y_offset + y_plot_inv * pixels_per_y_mesh_pnt; diff --git a/Marlin/src/lcd/extui/lib/ftdi_eve_touch_ui/screens/bed_mesh_screen.cpp b/Marlin/src/lcd/extui/lib/ftdi_eve_touch_ui/screens/bed_mesh_screen.cpp index 053f4ebd72f4..4128183b3733 100644 --- a/Marlin/src/lcd/extui/lib/ftdi_eve_touch_ui/screens/bed_mesh_screen.cpp +++ b/Marlin/src/lcd/extui/lib/ftdi_eve_touch_ui/screens/bed_mesh_screen.cpp @@ -55,12 +55,12 @@ constexpr static float gaugeThickness = 0.25; #endif 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) { - constexpr uint8_t rows = GRID_MAX_POINTS_Y; - constexpr uint8_t cols = GRID_MAX_POINTS_X; + constexpr uint8_t rows = GRID_MAX_POINTS_Y; + constexpr uint8_t cols = GRID_MAX_POINTS_X; - #define VALUE(X,Y) (data ? data[X][Y] : 0) - #define ISVAL(X,Y) (data ? !isnan(VALUE(X,Y)) : true) - #define HEIGHT(X,Y) (ISVAL(X,Y) ? (VALUE(X,Y) - val_min) * scale_z : 0) + #define VALUE(X,Y) (data ? data[X][Y] : 0) + #define ISVAL(X,Y) (data ? !isnan(VALUE(X,Y)) : true) + #define HEIGHT(X,Y) (ISVAL(X,Y) ? (VALUE(X,Y) - val_min) * scale_z : 0) // Compute the mean, min and max for the points diff --git a/Marlin/src/lcd/extui/ui_api.cpp b/Marlin/src/lcd/extui/ui_api.cpp index 8ae96cf86935..08e4c2849a57 100644 --- a/Marlin/src/lcd/extui/ui_api.cpp +++ b/Marlin/src/lcd/extui/ui_api.cpp @@ -859,7 +859,7 @@ namespace ExtUI { bed_mesh_t& getMeshArray() { return Z_VALUES_ARR; } float getMeshPoint(const xy_uint8_t &pos) { return Z_VALUES(pos.x, pos.y); } void setMeshPoint(const xy_uint8_t &pos, const float &zoff) { - if (WITHIN(pos.x, 0, GRID_MAX_POINTS_X - 1) && WITHIN(pos.y, 0, GRID_MAX_POINTS_Y - 1)) { + if (WITHIN(pos.x, 0, (GRID_MAX_POINTS_X) - 1) && WITHIN(pos.y, 0, (GRID_MAX_POINTS_Y) - 1)) { Z_VALUES(pos.x, pos.y) = zoff; TERN_(ABL_BILINEAR_SUBDIVISION, bed_level_virt_interpolate()); } diff --git a/Marlin/src/lcd/menu/menu_bed_leveling.cpp b/Marlin/src/lcd/menu/menu_bed_leveling.cpp index 6a9f89f118ba..5fc9fbccbd9c 100644 --- a/Marlin/src/lcd/menu/menu_bed_leveling.cpp +++ b/Marlin/src/lcd/menu/menu_bed_leveling.cpp @@ -214,8 +214,8 @@ static uint8_t xind, yind; // =0 START_MENU(); BACK_ITEM(MSG_BED_LEVELING); - EDIT_ITEM(uint8, MSG_MESH_X, &xind, 0, GRID_MAX_POINTS_X - 1); - EDIT_ITEM(uint8, MSG_MESH_Y, &yind, 0, GRID_MAX_POINTS_Y - 1); + EDIT_ITEM(uint8, MSG_MESH_X, &xind, 0, (GRID_MAX_POINTS_X) - 1); + EDIT_ITEM(uint8, MSG_MESH_Y, &yind, 0, (GRID_MAX_POINTS_Y) - 1); 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); END_MENU(); } diff --git a/Marlin/src/lcd/menu/menu_ubl.cpp b/Marlin/src/lcd/menu/menu_ubl.cpp index 565e6725a71a..baa91892fa99 100644 --- a/Marlin/src/lcd/menu/menu_ubl.cpp +++ b/Marlin/src/lcd/menu/menu_ubl.cpp @@ -484,8 +484,8 @@ void ubl_map_screen() { #if IS_KINEMATIC n_edit_pts = 9; // TODO: Delta accessible edit points #else - const bool xc = WITHIN(x, 1, GRID_MAX_POINTS_X - 2), - yc = WITHIN(y, 1, GRID_MAX_POINTS_Y - 2); + const bool xc = WITHIN(x, 1, (GRID_MAX_POINTS_X) - 2), + yc = WITHIN(y, 1, (GRID_MAX_POINTS_Y) - 2); n_edit_pts = yc ? (xc ? 9 : 6) : (xc ? 6 : 4); // Corners #endif diff --git a/Marlin/src/lcd/tft/ui_320x240.cpp b/Marlin/src/lcd/tft/ui_320x240.cpp index 793ee60847ce..5563d3069b61 100644 --- a/Marlin/src/lcd/tft/ui_320x240.cpp +++ b/Marlin/src/lcd/tft/ui_320x240.cpp @@ -462,12 +462,12 @@ void MenuItem_confirm::draw_select_screen(PGM_P const yes, PGM_P const no, const tft.set_background(COLOR_BACKGROUND); tft.add_rectangle(0, 0, GRID_WIDTH, GRID_HEIGHT, COLOR_WHITE); - for (uint16_t x = 0; x < GRID_MAX_POINTS_X ; x++) - for (uint16_t y = 0; y < GRID_MAX_POINTS_Y ; y++) + for (uint16_t x = 0; x < (GRID_MAX_POINTS_X); x++) + for (uint16_t y = 0; y < (GRID_MAX_POINTS_Y); y++) if (position_is_reachable({ ubl.mesh_index_to_xpos(x), ubl.mesh_index_to_ypos(y) })) - 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); + 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); - 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); + 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); const xy_pos_t pos = { ubl.mesh_index_to_xpos(x_plot), ubl.mesh_index_to_ypos(y_plot) }, lpos = pos.asLogical(); @@ -512,9 +512,9 @@ void MenuItem_confirm::draw_select_screen(PGM_P const yes, PGM_P const no, const #if ENABLED(TOUCH_SCREEN) touch.clear(); draw_menu_navigation = false; - 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); - 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); - add_control(GRID_OFFSET_X + CONTROL_OFFSET, GRID_OFFSET_Y + GRID_HEIGHT + CONTROL_OFFSET, UBL, - ENCODER_STEPS_PER_MENU_ITEM, imgLeft); + 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); + 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); + add_control(GRID_OFFSET_X + CONTROL_OFFSET, GRID_OFFSET_Y + GRID_HEIGHT + CONTROL_OFFSET, UBL, -(ENCODER_STEPS_PER_MENU_ITEM), imgLeft); add_control(GRID_OFFSET_X + GRID_WIDTH - CONTROL_OFFSET - 32, GRID_OFFSET_Y + GRID_HEIGHT + CONTROL_OFFSET, UBL, ENCODER_STEPS_PER_MENU_ITEM, imgRight); add_control(224, GRID_OFFSET_Y + GRID_HEIGHT + CONTROL_OFFSET, CLICK, imgLeveling); add_control(144, 206, BACK, imgBack); diff --git a/Marlin/src/lcd/tft/ui_480x320.cpp b/Marlin/src/lcd/tft/ui_480x320.cpp index a8979d0ca6e9..21b280ac757c 100644 --- a/Marlin/src/lcd/tft/ui_480x320.cpp +++ b/Marlin/src/lcd/tft/ui_480x320.cpp @@ -462,12 +462,12 @@ void MenuItem_confirm::draw_select_screen(PGM_P const yes, PGM_P const no, const tft.set_background(COLOR_BACKGROUND); tft.add_rectangle(0, 0, GRID_WIDTH, GRID_HEIGHT, COLOR_WHITE); - for (uint16_t x = 0; x < GRID_MAX_POINTS_X ; x++) - for (uint16_t y = 0; y < GRID_MAX_POINTS_Y ; y++) + for (uint16_t x = 0; x < (GRID_MAX_POINTS_X); x++) + for (uint16_t y = 0; y < (GRID_MAX_POINTS_Y); y++) if (position_is_reachable({ ubl.mesh_index_to_xpos(x), ubl.mesh_index_to_ypos(y) })) - 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); + 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); - 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); + 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); const xy_pos_t pos = { ubl.mesh_index_to_xpos(x_plot), ubl.mesh_index_to_ypos(y_plot) }, lpos = pos.asLogical(); @@ -512,9 +512,9 @@ void MenuItem_confirm::draw_select_screen(PGM_P const yes, PGM_P const no, const #if ENABLED(TOUCH_SCREEN) touch.clear(); draw_menu_navigation = false; - 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); - 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); - add_control(GRID_OFFSET_X + CONTROL_OFFSET, GRID_OFFSET_Y + GRID_HEIGHT + CONTROL_OFFSET, UBL, - ENCODER_STEPS_PER_MENU_ITEM, imgLeft); + 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); + 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); + add_control(GRID_OFFSET_X + CONTROL_OFFSET, GRID_OFFSET_Y + GRID_HEIGHT + CONTROL_OFFSET, UBL, -(ENCODER_STEPS_PER_MENU_ITEM), imgLeft); add_control(GRID_OFFSET_X + GRID_WIDTH - CONTROL_OFFSET - 32, GRID_OFFSET_Y + GRID_HEIGHT + CONTROL_OFFSET, UBL, ENCODER_STEPS_PER_MENU_ITEM, imgRight); add_control(320, GRID_OFFSET_Y + GRID_HEIGHT + CONTROL_OFFSET, CLICK, imgLeveling); add_control(224, TFT_HEIGHT - 34, BACK, imgBack); diff --git a/Marlin/src/module/settings.cpp b/Marlin/src/module/settings.cpp index d98ee3c218ee..c264f5ad9476 100644 --- a/Marlin/src/module/settings.cpp +++ b/Marlin/src/module/settings.cpp @@ -1580,7 +1580,7 @@ void MarlinSettings::postprocess() { #if ENABLED(MESH_BED_LEVELING) if (!validating) mbl.z_offset = dummyf; - if (mesh_num_x == GRID_MAX_POINTS_X && mesh_num_y == GRID_MAX_POINTS_Y) { + if (mesh_num_x == (GRID_MAX_POINTS_X) && mesh_num_y == (GRID_MAX_POINTS_Y)) { // EEPROM data fits the current mesh EEPROM_READ(mbl.z_values); } @@ -1627,7 +1627,7 @@ void MarlinSettings::postprocess() { EEPROM_READ_ALWAYS(grid_max_x); // 1 byte EEPROM_READ_ALWAYS(grid_max_y); // 1 byte #if ENABLED(AUTO_BED_LEVELING_BILINEAR) - if (grid_max_x == GRID_MAX_POINTS_X && grid_max_y == GRID_MAX_POINTS_Y) { + if (grid_max_x == (GRID_MAX_POINTS_X) && grid_max_y == (GRID_MAX_POINTS_Y)) { if (!validating) set_bed_leveling_enabled(false); EEPROM_READ(bilinear_grid_spacing); // 2 ints EEPROM_READ(bilinear_start); // 2 ints From ebd596547393a84ab3780137d604fdd38d5b8e76 Mon Sep 17 00:00:00 2001 From: Marcio Teixeira Date: Thu, 1 Apr 2021 09:58:17 -0600 Subject: [PATCH 22/25] Fix Z-raise; do not return to start position --- Marlin/src/gcode/bedlevel/G26.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/Marlin/src/gcode/bedlevel/G26.cpp b/Marlin/src/gcode/bedlevel/G26.cpp index 5bfbff33054f..09d68739e5a8 100644 --- a/Marlin/src/gcode/bedlevel/G26.cpp +++ b/Marlin/src/gcode/bedlevel/G26.cpp @@ -167,7 +167,7 @@ float g26_random_deviation = 0.0; #endif -void move_to(const float &rx, const float &ry, const float &z, const float &e_delta) { +void move_to(float rx, float ry, float z, float e_delta) { static float last_z = -999.99; const xy_pos_t dest = { rx, ry }; @@ -859,7 +859,6 @@ void GcodeSuite::G26() { g26.retract_filament(destination); destination.z = Z_CLEARANCE_BETWEEN_PROBES; move_to(destination, 0); // Raise the nozzle - move_to(g26.xy_pos, 0); // Move back to the starting position #if DISABLED(NO_VOLUMETRICS) parser.volumetric_enabled = volumetric_was_enabled; From 9505adb747423d5524693d835d8d01c0a40168d4 Mon Sep 17 00:00:00 2001 From: Scott Lahteine Date: Thu, 1 Apr 2021 14:27:28 -0500 Subject: [PATCH 23/25] constrain --- Marlin/src/feature/bedlevel/hilbert_curve.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Marlin/src/feature/bedlevel/hilbert_curve.cpp b/Marlin/src/feature/bedlevel/hilbert_curve.cpp index 48eeac9dee7f..e4bc3aa61819 100644 --- a/Marlin/src/feature/bedlevel/hilbert_curve.cpp +++ b/Marlin/src/feature/bedlevel/hilbert_curve.cpp @@ -102,8 +102,8 @@ bool hilbert_curve::search_from(uint8_t x, uint8_t y, hilbert_curve::callback_pt */ bool hilbert_curve::search_from_closest(const xy_pos_t &pos, hilbert_curve::callback_ptr func, void *data) { // Find closest grid intersection - const uint8_t grid_x = LROUND(LIMIT(float(pos.x - (MESH_MIN_X)) / (MESH_X_DIST), 0, (GRID_MAX_POINTS_X) - 1)); - const uint8_t grid_y = LROUND(LIMIT(float(pos.y - (MESH_MIN_Y)) / (MESH_Y_DIST), 0, (GRID_MAX_POINTS_Y) - 1)); + const uint8_t grid_x = LROUND(constrain(float(pos.x - (MESH_MIN_X)) / (MESH_X_DIST), 0, (GRID_MAX_POINTS_X) - 1)); + const uint8_t grid_y = LROUND(constrain(float(pos.y - (MESH_MIN_Y)) / (MESH_Y_DIST), 0, (GRID_MAX_POINTS_Y) - 1)); return search_from(grid_x, grid_y, func, data); } From e14f951b38947d3ec6c0d59c32d39e787f9d463c Mon Sep 17 00:00:00 2001 From: Scott Lahteine Date: Thu, 1 Apr 2021 15:25:14 -0500 Subject: [PATCH 24/25] Revert move_to slightly Regression from #15204 --- Marlin/src/gcode/bedlevel/G26.cpp | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/Marlin/src/gcode/bedlevel/G26.cpp b/Marlin/src/gcode/bedlevel/G26.cpp index 5f2e7ebc24f6..74f9c0604496 100644 --- a/Marlin/src/gcode/bedlevel/G26.cpp +++ b/Marlin/src/gcode/bedlevel/G26.cpp @@ -167,7 +167,7 @@ float g26_random_deviation = 0.0; #endif -void move_to(float rx, float ry, float z, float e_delta) { +void move_to(const float &rx, const float &ry, const float &z, const float &e_delta) { static float last_z = -999.99; const xy_pos_t dest = { rx, ry }; @@ -175,10 +175,9 @@ void move_to(float rx, float ry, float z, float e_delta) { const bool has_xy_component = dest != current_position, // Check if X or Y is involved in the movement. has_e_component = e_delta != 0.0; - destination = current_position; - if (z != last_z) { - last_z = destination.z = z; + last_z = z; + destination.set(current_position.x, current_position.y, z, current_position.e); 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 prepare_internal_move_to_destination(fr_mm_s); } From 527311463969994cd277c44a9126a67dabc0e17a Mon Sep 17 00:00:00 2001 From: Scott Lahteine Date: Thu, 1 Apr 2021 16:01:24 -0500 Subject: [PATCH 25/25] optimize for size --- Marlin/src/gcode/bedlevel/G26.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Marlin/src/gcode/bedlevel/G26.cpp b/Marlin/src/gcode/bedlevel/G26.cpp index 74f9c0604496..b32fffb6627a 100644 --- a/Marlin/src/gcode/bedlevel/G26.cpp +++ b/Marlin/src/gcode/bedlevel/G26.cpp @@ -193,7 +193,7 @@ void move_to(const float &rx, const float &ry, const float &z, const float &e_de prepare_internal_move_to_destination(fr_mm_s); } -FORCE_INLINE void move_to(const xyz_pos_t &where, const float &de) { move_to(where.x, where.y, where.z, de); } +void move_to(const xyz_pos_t &where, const float &de) { move_to(where.x, where.y, where.z, de); } typedef struct { float extrusion_multiplier = EXTRUSION_MULTIPLIER,