diff --git a/Marlin/G26_Mesh_Validation_Tool.cpp b/Marlin/G26_Mesh_Validation_Tool.cpp index 56a2e4950d..896eb4b8b5 100644 --- a/Marlin/G26_Mesh_Validation_Tool.cpp +++ b/Marlin/G26_Mesh_Validation_Tool.cpp @@ -740,12 +740,14 @@ } if (code_seen('R')) { - g26_repeats = code_has_value() ? code_value_int() - 1 : 999; + g26_repeats = code_has_value() ? code_value_int() : 999; if (g26_repeats <= 0) { SERIAL_PROTOCOLLNPGM("?(R)epeat value not plausible; must be greater than 0."); return UBL_ERR; } + + g26_repeats--; } diff --git a/Marlin/Marlin_main.cpp b/Marlin/Marlin_main.cpp index 63ae0a083a..7eb417db76 100644 --- a/Marlin/Marlin_main.cpp +++ b/Marlin/Marlin_main.cpp @@ -8477,7 +8477,7 @@ void quickstop_stepper() { } } -#elif ENABLED(AUTO_BED_LEVELING_BILINEAR) || ENABLED(AUTO_BED_LEVELING_UBL) +#elif ENABLED(AUTO_BED_LEVELING_BILINEAR) /** * M421: Set a single Mesh Bed Leveling Z coordinate @@ -8490,8 +8490,8 @@ void quickstop_stepper() { int8_t px = 0, py = 0; float z = 0; bool hasI, hasJ, hasZ, hasQ; - if ((hasI = code_seen('I'))) px = code_value_linear_units(); - if ((hasJ = code_seen('J'))) py = code_value_linear_units(); + if ((hasI = code_seen('I'))) px = code_value_int(); + if ((hasJ = code_seen('J'))) py = code_value_int(); if ((hasZ = code_seen('Z'))) z = code_value_linear_units(); if ((hasQ = code_seen('Q'))) z = code_value_linear_units(); @@ -8503,23 +8503,15 @@ void quickstop_stepper() { if (WITHIN(px, 0, GRID_MAX_POINTS_X - 1) && WITHIN(py, 0, GRID_MAX_POINTS_Y - 1)) { if (hasZ) { // doing an absolute mesh value - #if ENABLED(AUTO_BED_LEVELING_UBL) - ubl.z_values[px][py] = z; - #else - z_values[px][py] = z; - #if ENABLED(ABL_BILINEAR_SUBDIVISION) - bed_level_virt_interpolate(); - #endif + z_values[px][py] = z; + #if ENABLED(ABL_BILINEAR_SUBDIVISION) + bed_level_virt_interpolate(); #endif } else { // doing an offset of a mesh value - #if ENABLED(AUTO_BED_LEVELING_UBL) - ubl.z_values[px][py] += z; - #else - z_values[px][py] += z; - #if ENABLED(ABL_BILINEAR_SUBDIVISION) - bed_level_virt_interpolate(); - #endif + z_values[px][py] += z; + #if ENABLED(ABL_BILINEAR_SUBDIVISION) + bed_level_virt_interpolate(); #endif } } @@ -8528,6 +8520,52 @@ void quickstop_stepper() { SERIAL_ERRORLNPGM(MSG_ERR_MESH_XY); } } + +#elif ENABLED(AUTO_BED_LEVELING_UBL) + + /** + * M421: Set a single Mesh Bed Leveling Z coordinate + * + * M421 I J Z + * or + * M421 I J Q + */ + + //todo: change multiple points simultaneously? + + inline void gcode_M421() { + int8_t px = 0, py = 0; + float z = 0; + bool hasI, hasJ, hasZ, hasQ, hasC; + if ((hasI = code_seen('I'))) px = code_value_int(); + if ((hasJ = code_seen('J'))) py = code_value_int(); + if ((hasZ = code_seen('Z'))) z = code_value_linear_units(); + if ((hasQ = code_seen('Q'))) z = code_value_linear_units(); + hasC = code_seen('C'); + + if ( (!(hasI && hasJ) && !hasC) || (hasQ && hasZ) || (!hasQ && !hasZ)) { + SERIAL_ERROR_START; + SERIAL_ERRORLNPGM(MSG_ERR_M421_PARAMETERS); + return; + } + + if (hasC) { // get closest position + const mesh_index_pair location = find_closest_mesh_point_of_type(REAL, current_position[X_AXIS], current_position[Y_AXIS], USE_NOZZLE_AS_REFERENCE, NULL, false); + px = location.x_index; + py = location.y_index; + } + + if (WITHIN(px, 0, GRID_MAX_POINTS_X - 1) && WITHIN(py, 0, GRID_MAX_POINTS_Y - 1)) { + if (hasZ) // doing an absolute mesh value + ubl.z_values[px][py] = z; + else // doing an offset of a mesh value + ubl.z_values[px][py] += z; + } + else { // bad indexes were specified for the mesh point + SERIAL_ERROR_START; + SERIAL_ERRORLNPGM(MSG_ERR_MESH_XY); + } + } #endif #if HAS_M206_COMMAND diff --git a/Marlin/ubl.h b/Marlin/ubl.h index b33b5d21fe..4ae4c0504b 100644 --- a/Marlin/ubl.h +++ b/Marlin/ubl.h @@ -35,6 +35,9 @@ #define UBL_OK false #define UBL_ERR true + #define USE_NOZZLE_AS_REFERENCE 0 + #define USE_PROBE_AS_REFERENCE 1 + typedef struct { int8_t x_index, y_index; float distance; // When populated, the distance from the search location diff --git a/Marlin/ubl_G29.cpp b/Marlin/ubl_G29.cpp index cee20f1747..82efb2fa05 100644 --- a/Marlin/ubl_G29.cpp +++ b/Marlin/ubl_G29.cpp @@ -311,9 +311,6 @@ * we now have the functionality and features of all three systems combined. */ - #define USE_NOZZLE_AS_REFERENCE 0 - #define USE_PROBE_AS_REFERENCE 1 - // The simple parameter flags and values are 'static' so parameter parsing can be in a support routine. static int g29_verbose_level, phase_value, repetition_cnt, storage_slot = 0, map_type, grid_size;