diff --git a/Marlin/src/feature/bedlevel/abl/bbl.cpp b/Marlin/src/feature/bedlevel/abl/bbl.cpp index 280700c1f1..0e8c4a273e 100644 --- a/Marlin/src/feature/bedlevel/abl/bbl.cpp +++ b/Marlin/src/feature/bedlevel/abl/bbl.cpp @@ -37,12 +37,12 @@ LevelingBilinear bedlevel; -xy_pos_t LevelingBilinear::grid_spacing, - LevelingBilinear::grid_start; xy_float_t LevelingBilinear::grid_factor; +xy_pos_t LevelingBilinear::grid_spacing, + LevelingBilinear::grid_start, + LevelingBilinear::cached_rel; +xy_int8_t LevelingBilinear::cached_g; bed_mesh_t LevelingBilinear::z_values; -xy_pos_t LevelingBilinear::cached_rel; -xy_int8_t LevelingBilinear::cached_g; /** * Extrapolate a single point from its neighbors @@ -106,9 +106,17 @@ void LevelingBilinear::reset() { } } +/** + * Set grid spacing and start position + */ void LevelingBilinear::set_grid(const xy_pos_t& _grid_spacing, const xy_pos_t& _grid_start) { - grid_spacing = _grid_spacing; - grid_start = _grid_start; + #if HAS_PROUI_MESH_EDIT + grid_spacing.set(MESH_X_DIST, MESH_Y_DIST); + grid_start = mesh_min; + #else + grid_spacing = _grid_spacing; + grid_start = _grid_start; + #endif grid_factor = grid_spacing.reciprocal(); } diff --git a/Marlin/src/feature/bedlevel/bedlevel.cpp b/Marlin/src/feature/bedlevel/bedlevel.cpp index c49afa30e2..f3e5791e86 100644 --- a/Marlin/src/feature/bedlevel/bedlevel.cpp +++ b/Marlin/src/feature/bedlevel/bedlevel.cpp @@ -46,8 +46,18 @@ #include "../../lcd/extui/ui_api.h" #endif +#if HAS_PROUI_MESH_EDIT + #include "../../lcd/dwin/proui/bedlevel_tools.h" +#endif + bool leveling_is_valid() { - return TERN1(HAS_MESH, bedlevel.mesh_is_valid()); + return ( + #if HAS_PROUI_MESH_EDIT + bedLevelTools.meshValidate() + #else + TERN1(HAS_MESH, bedlevel.mesh_is_valid()) + #endif + ); } /** diff --git a/Marlin/src/feature/bedlevel/hilbert_curve.cpp b/Marlin/src/feature/bedlevel/hilbert_curve.cpp index 57cbdfb34d..b57991297e 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(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)); + const uint8_t grid_x = LROUND(constrain((pos.x - mesh_min.x) / (MESH_X_DIST), 0, (GRID_MAX_POINTS_X) - 1)); + const uint8_t grid_y = LROUND(constrain((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 47e8e34fbd..93e50b6498 100644 --- a/Marlin/src/feature/bedlevel/mbl/mesh_bed_leveling.cpp +++ b/Marlin/src/feature/bedlevel/mbl/mesh_bed_leveling.cpp @@ -39,14 +39,21 @@ mesh_bed_leveling::index_to_xpos[GRID_MAX_POINTS_X], mesh_bed_leveling::index_to_ypos[GRID_MAX_POINTS_Y]; - mesh_bed_leveling::mesh_bed_leveling() { + mesh_bed_leveling::mesh_bed_leveling() { initialize(); } + + void mesh_bed_leveling::initialize() { for (uint8_t i = 0; i < GRID_MAX_POINTS_X; ++i) - index_to_xpos[i] = MESH_MIN_X + i * (MESH_X_DIST); + index_to_xpos[i] = mesh_min.x + i * (MESH_X_DIST); for (uint8_t i = 0; i < GRID_MAX_POINTS_Y; ++i) - index_to_ypos[i] = MESH_MIN_Y + i * (MESH_Y_DIST); + index_to_ypos[i] = mesh_min.y + i * (MESH_Y_DIST); reset(); } + void mesh_bed_leveling::report_mesh() { + SERIAL_ECHOLN(F(STRINGIFY(GRID_MAX_POINTS_X) "x" STRINGIFY(GRID_MAX_POINTS_Y) " mesh. Z offset: "), p_float_t(z_offset, 5), F("\nMeasured points:")); + print_2d_array(GRID_MAX_POINTS_X, GRID_MAX_POINTS_Y, 5, z_values[0]); + } + void mesh_bed_leveling::reset() { z_offset = 0; ZERO(z_values); @@ -122,9 +129,4 @@ #endif // IS_CARTESIAN && !SEGMENT_LEVELED_MOVES - void mesh_bed_leveling::report_mesh() { - SERIAL_ECHOLN(F(STRINGIFY(GRID_MAX_POINTS_X) "x" STRINGIFY(GRID_MAX_POINTS_Y) " mesh. Z offset: "), p_float_t(z_offset, 5), F("\nMeasured points:")); - print_2d_array(GRID_MAX_POINTS_X, GRID_MAX_POINTS_Y, 5, z_values[0]); - } - #endif // MESH_BED_LEVELING diff --git a/Marlin/src/feature/bedlevel/mbl/mesh_bed_leveling.h b/Marlin/src/feature/bedlevel/mbl/mesh_bed_leveling.h index 43dabd3adb..92791d3f38 100644 --- a/Marlin/src/feature/bedlevel/mbl/mesh_bed_leveling.h +++ b/Marlin/src/feature/bedlevel/mbl/mesh_bed_leveling.h @@ -32,8 +32,7 @@ enum MeshLevelingState : char { MeshReset // G29 S5 }; -#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)) +#include "../../../module/motion.h" class mesh_bed_leveling { public: @@ -44,10 +43,12 @@ public: mesh_bed_leveling(); - static void report_mesh(); - static void reset(); + static void initialize(); + + static void report_mesh(); + FORCE_INLINE static bool has_mesh() { GRID_LOOP(x, y) if (z_values[x][y]) return true; return false; @@ -73,11 +74,11 @@ public: static float get_mesh_y(const uint8_t i) { return index_to_ypos[i]; } static uint8_t cell_index_x(const float x) { - int8_t cx = (x - (MESH_MIN_X)) * RECIPROCAL(MESH_X_DIST); + const int8_t cx = (x - mesh_min.x) * RECIPROCAL(MESH_X_DIST); return constrain(cx, 0, GRID_MAX_CELLS_X - 1); } static uint8_t cell_index_y(const float y) { - int8_t cy = (y - (MESH_MIN_Y)) * RECIPROCAL(MESH_Y_DIST); + const int8_t cy = (y - mesh_min.y) * RECIPROCAL(MESH_Y_DIST); return constrain(cy, 0, GRID_MAX_CELLS_Y - 1); } static xy_uint8_t cell_indexes(const float x, const float y) { @@ -86,11 +87,11 @@ public: static xy_uint8_t cell_indexes(const xy_pos_t &xy) { return cell_indexes(xy.x, xy.y); } 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); + const 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; } 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); + const 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; } static xy_int8_t probe_indexes(const float x, const float y) { diff --git a/Marlin/src/feature/bedlevel/ubl/ubl.cpp b/Marlin/src/feature/bedlevel/ubl/ubl.cpp index cc887fd23b..28a85ae6d4 100644 --- a/Marlin/src/feature/bedlevel/ubl/ubl.cpp +++ b/Marlin/src/feature/bedlevel/ubl/ubl.cpp @@ -63,23 +63,25 @@ void unified_bed_leveling::report_state() { int8_t unified_bed_leveling::storage_slot; -float unified_bed_leveling::z_values[GRID_MAX_POINTS_X][GRID_MAX_POINTS_Y]; +bed_mesh_t unified_bed_leveling::z_values; -#define _GRIDPOS(A,N) (MESH_MIN_##A + N * (MESH_##A##_DIST)) +#if !HAS_PROUI_MESH_EDIT + #define _GRIDPOS(A,N) (MESH_MIN_##A + N * (MESH_##A##_DIST)) -const float -unified_bed_leveling::_mesh_index_to_xpos[GRID_MAX_POINTS_X] PROGMEM = ARRAY_N(GRID_MAX_POINTS_X, - _GRIDPOS(X, 0), _GRIDPOS(X, 1), _GRIDPOS(X, 2), _GRIDPOS(X, 3), - _GRIDPOS(X, 4), _GRIDPOS(X, 5), _GRIDPOS(X, 6), _GRIDPOS(X, 7), - _GRIDPOS(X, 8), _GRIDPOS(X, 9), _GRIDPOS(X, 10), _GRIDPOS(X, 11), - _GRIDPOS(X, 12), _GRIDPOS(X, 13), _GRIDPOS(X, 14), _GRIDPOS(X, 15) -), -unified_bed_leveling::_mesh_index_to_ypos[GRID_MAX_POINTS_Y] PROGMEM = ARRAY_N(GRID_MAX_POINTS_Y, - _GRIDPOS(Y, 0), _GRIDPOS(Y, 1), _GRIDPOS(Y, 2), _GRIDPOS(Y, 3), - _GRIDPOS(Y, 4), _GRIDPOS(Y, 5), _GRIDPOS(Y, 6), _GRIDPOS(Y, 7), - _GRIDPOS(Y, 8), _GRIDPOS(Y, 9), _GRIDPOS(Y, 10), _GRIDPOS(Y, 11), - _GRIDPOS(Y, 12), _GRIDPOS(Y, 13), _GRIDPOS(Y, 14), _GRIDPOS(Y, 15) -); + const float + unified_bed_leveling::_mesh_index_to_xpos[GRID_MAX_POINTS_X] PROGMEM = ARRAY_N(GRID_MAX_POINTS_X, + _GRIDPOS(X, 0), _GRIDPOS(X, 1), _GRIDPOS(X, 2), _GRIDPOS(X, 3), + _GRIDPOS(X, 4), _GRIDPOS(X, 5), _GRIDPOS(X, 6), _GRIDPOS(X, 7), + _GRIDPOS(X, 8), _GRIDPOS(X, 9), _GRIDPOS(X, 10), _GRIDPOS(X, 11), + _GRIDPOS(X, 12), _GRIDPOS(X, 13), _GRIDPOS(X, 14), _GRIDPOS(X, 15) + ), + unified_bed_leveling::_mesh_index_to_ypos[GRID_MAX_POINTS_Y] PROGMEM = ARRAY_N(GRID_MAX_POINTS_Y, + _GRIDPOS(Y, 0), _GRIDPOS(Y, 1), _GRIDPOS(Y, 2), _GRIDPOS(Y, 3), + _GRIDPOS(Y, 4), _GRIDPOS(Y, 5), _GRIDPOS(Y, 6), _GRIDPOS(Y, 7), + _GRIDPOS(Y, 8), _GRIDPOS(Y, 9), _GRIDPOS(Y, 10), _GRIDPOS(Y, 11), + _GRIDPOS(Y, 12), _GRIDPOS(Y, 13), _GRIDPOS(Y, 14), _GRIDPOS(Y, 15) + ); +#endif volatile int16_t unified_bed_leveling::encoder_diff; @@ -173,8 +175,8 @@ void unified_bed_leveling::display_map(const uint8_t map_type) { SERIAL_ECHOPGM("\nBed Topography Report"); if (human) { SERIAL_ECHOLNPGM(":\n"); - serial_echo_xy(4, MESH_MIN_X, MESH_MAX_Y); - serial_echo_xy(twixt, MESH_MAX_X, MESH_MAX_Y); + serial_echo_xy(4, mesh_min.x, mesh_max.y); + serial_echo_xy(twixt, mesh_max.x, mesh_max.y); SERIAL_EOL(); serial_echo_column_labels(eachsp - 2); } @@ -207,6 +209,7 @@ void unified_bed_leveling::display_map(const uint8_t map_type) { const float f = z_values[i][j]; if (lcd) { // TODO: Display on Graphical LCD + TERN_(DWIN_LCD_PROUI, dwinMeshViewer()); } else if (isnan(f)) SERIAL_ECHO(human ? F(" . ") : F("NAN")); @@ -231,8 +234,8 @@ void unified_bed_leveling::display_map(const uint8_t map_type) { if (human) { serial_echo_column_labels(eachsp - 2); SERIAL_EOL(); - serial_echo_xy(4, MESH_MIN_X, MESH_MIN_Y); - serial_echo_xy(twixt, MESH_MAX_X, MESH_MIN_Y); + serial_echo_xy(4, mesh_min.x, mesh_min.y); + serial_echo_xy(twixt, mesh_max.x, mesh_min.y); SERIAL_EOL(); SERIAL_EOL(); } diff --git a/Marlin/src/feature/bedlevel/ubl/ubl.h b/Marlin/src/feature/bedlevel/ubl/ubl.h index f6e9ba0cd9..9383b14e4d 100644 --- a/Marlin/src/feature/bedlevel/ubl/ubl.h +++ b/Marlin/src/feature/bedlevel/ubl/ubl.h @@ -38,9 +38,6 @@ enum MeshPointType : char { INVALID, REAL, SET_IN_BITMAP, CLOSEST }; struct mesh_index_pair; -#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]; #endif @@ -116,8 +113,11 @@ public: static void set_store_from_mesh(const bed_mesh_t &in_values, mesh_store_t &stored_values); static void set_mesh_from_store(const mesh_store_t &stored_values, bed_mesh_t &out_values); #endif - static const float _mesh_index_to_xpos[GRID_MAX_POINTS_X], - _mesh_index_to_ypos[GRID_MAX_POINTS_Y]; + + #if !HAS_PROUI_MESH_EDIT + static const float _mesh_index_to_xpos[GRID_MAX_POINTS_X], + _mesh_index_to_ypos[GRID_MAX_POINTS_Y]; + #endif #if HAS_MARLINUI_MENU static bool lcd_map_control; @@ -133,11 +133,11 @@ public: FORCE_INLINE static void set_z(const int8_t px, const int8_t py, const float z) { z_values[px][py] = z; } static int8_t cell_index_x_raw(const float x) { - return FLOOR((x - (MESH_MIN_X)) * RECIPROCAL(MESH_X_DIST)); + return FLOOR((x - mesh_min.x) * RECIPROCAL(MESH_X_DIST)); } static int8_t cell_index_y_raw(const float y) { - return FLOOR((y - (MESH_MIN_Y)) * RECIPROCAL(MESH_Y_DIST)); + return FLOOR((y - mesh_min.y) * RECIPROCAL(MESH_Y_DIST)); } static bool cell_index_x_valid(const float x) { @@ -162,11 +162,11 @@ public: static xy_uint8_t cell_indexes(const xy_pos_t &xy) { return cell_indexes(xy.x, xy.y); } 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); + 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; } 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); + 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; } static xy_int8_t closest_indexes(const xy_pos_t &xy) { @@ -259,7 +259,7 @@ public: * UBL_Z_RAISE_WHEN_OFF_MESH is specified, that value is returned. */ #ifdef UBL_Z_RAISE_WHEN_OFF_MESH - if (!WITHIN(rx0, MESH_MIN_X, MESH_MAX_X) || !WITHIN(ry0, MESH_MIN_Y, MESH_MAX_Y)) + if (!WITHIN(rx0, mesh_min.x, mesh_max.x) || !WITHIN(ry0, mesh_min.y, mesh_max.y)) return UBL_Z_RAISE_WHEN_OFF_MESH; #endif @@ -287,12 +287,20 @@ public: static constexpr float get_z_offset() { return 0.0f; } - static float get_mesh_x(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); - } - static float get_mesh_y(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); - } + static float _get_mesh_x(const uint8_t i) { return mesh_min.x + i * (MESH_X_DIST); } + static float _get_mesh_y(const uint8_t i) { return mesh_min.y + i * (MESH_Y_DIST); } + + #if HAS_PROUI_MESH_EDIT + static float get_mesh_x(const uint8_t i) { return _get_mesh_x(i); } + static float get_mesh_y(const uint8_t i) { return _get_mesh_y(i); } + #else + static float get_mesh_x(const uint8_t i) { + return i < (GRID_MAX_POINTS_X) ? pgm_read_float(&_mesh_index_to_xpos[i]) : _get_mesh_x(i); + } + static float get_mesh_y(const uint8_t i) { + return i < (GRID_MAX_POINTS_Y) ? pgm_read_float(&_mesh_index_to_ypos[i]) : _get_mesh_y(i); + } + #endif #if UBL_SEGMENTED static bool line_to_destination_segmented(const feedRate_t scaled_fr_mm_s); diff --git a/Marlin/src/feature/bedlevel/ubl/ubl_G29.cpp b/Marlin/src/feature/bedlevel/ubl/ubl_G29.cpp index 02b904adca..3586e29741 100644 --- a/Marlin/src/feature/bedlevel/ubl/ubl_G29.cpp +++ b/Marlin/src/feature/bedlevel/ubl/ubl_G29.cpp @@ -43,6 +43,10 @@ #include "../../../lcd/extui/ui_api.h" #endif +#if ENABLED(DWIN_LCD_PROUI) + #include "../../../lcd/dwin/proui/meshviewer.h" +#endif + #if ENABLED(UBL_HILBERT_CURVE) #include "../hilbert_curve.h" #endif @@ -318,7 +322,7 @@ void unified_bed_leveling::G29() { // Check for commands that require the printer to be homed if (may_move) { planner.synchronize(); - #if ALL(DWIN_LCD_PROUI, ZHOME_BEFORE_LEVELING) + #if ENABLED(DWIN_LCD_PROUI) save_ubl_active_state_and_disable(); gcode.process_subcommands_now(F("G28Z")); restore_ubl_active_state(false); // ...without telling ExtUI "done" @@ -444,7 +448,7 @@ void unified_bed_leveling::G29() { tilt_mesh_based_on_probed_grid(param.J_grid_size == 0); // Zero size does 3-Point restore_ubl_active_state(); #if ENABLED(UBL_G29_J_RECENTER) - motion.blocking_move_xy(0.5f * ((MESH_MIN_X) + (MESH_MAX_X)), 0.5f * ((MESH_MIN_Y) + (MESH_MAX_Y))); + motion.blocking_move_xy(0.5f * (mesh_min.x + mesh_max.x), 0.5f * (mesh_min.y + mesh_max.y)); #endif motion.report_position(); SET_PROBE_DEPLOYED(true); @@ -783,6 +787,10 @@ void unified_bed_leveling::shift_mesh_height(const float zoffs) { TERN_(HAS_STATUS_MESSAGE, ui.status_printf(0, F(S_FMT " %i/%i"), GET_TEXT(MSG_PROBING_POINT), point_num, int(GRID_MAX_POINTS))); TERN_(HAS_BACKLIGHT_TIMEOUT, ui.refresh_backlight_timeout()); + #if ENABLED(DWIN_LCD_PROUI) + if (!hmiFlag.cancel_lev) dwinRedrawScreen(); else break; + #endif + #if HAS_MARLINUI_MENU if (ui.button_pressed()) { ui.quick_feedback(false); // Preserve button state for click-and-hold @@ -811,11 +819,15 @@ void unified_bed_leveling::shift_mesh_height(const float zoffs) { ExtUI::onMeshUpdate(best.pos, ExtUI::G29_POINT_FINISH); ExtUI::onMeshUpdate(best.pos, measured_z); #endif + TERN_(DWIN_LCD_PROUI, meshViewer.drawMeshPoint(best.pos, measured_z)); } SERIAL_FLUSH(); // Prevent host M105 buffer overrun. } while (best.pos.x >= 0 && --count); + if (TERN0(DWIN_LCD_PROUI, hmiFlag.cancel_lev)) + goto EXIT_PROBE_MESH; + GRID_LOOP(x, y) if (z_values[x][y] == HUGE_VALF) z_values[x][y] = NAN; // Restore NAN for HUGE_VALF marks TERN_(EXTENSIBLE_UI, ExtUI::onMeshUpdate(best.pos, ExtUI::G29_FINISH)); @@ -827,10 +839,16 @@ void unified_bed_leveling::shift_mesh_height(const float zoffs) { probe.move_z_after_probing(); - motion.blocking_move_xy( - constrain(nearby.x - probe.offset_xy.x, MESH_MIN_X, MESH_MAX_X), - constrain(nearby.y - probe.offset_xy.y, MESH_MIN_Y, MESH_MAX_Y) - ); + #if ENABLED(DWIN_LCD_PROUI) + bedlevel.smart_fill_mesh(); + #else + motion.blocking_move_xy( + constrain(nearby.x - probe.offset_xy.x, mesh_min.x, mesh_max.x), + constrain(nearby.y - probe.offset_xy.y, mesh_min.y, mesh_max.y) + ); + #endif + + EXIT_PROBE_MESH: restore_ubl_active_state(); } @@ -895,8 +913,8 @@ void set_message_with_feedback(FSTR_P const fstr) { motion.blocking_move( xyz_pos_t({ - 0.5f * ((MESH_MIN_X) + (MESH_MAX_X)), - 0.5f * ((MESH_MIN_Y) + (MESH_MAX_Y)), + 0.5f * (mesh_min.x + mesh_max.x), + 0.5f * (mesh_min.y + mesh_max.y), MANUAL_PROBE_START_Z #ifdef SAFE_BED_LEVELING_START_I , SAFE_BED_LEVELING_START_I @@ -1191,9 +1209,9 @@ bool unified_bed_leveling::G29_parse_parameters() { } param.XY_seen.x = parser.seenval('X'); - float sx = param.XY_seen.x ? parser.value_float() : motion.position.x; + float sx = param.XY_seen.x ? parser.value_float() : DIFF_TERN(HAS_BED_PROBE, motion.position.x, probe.offset.x); param.XY_seen.y = parser.seenval('Y'); - float sy = param.XY_seen.y ? parser.value_float() : motion.position.y; + float sy = param.XY_seen.y ? parser.value_float() : DIFF_TERN(HAS_BED_PROBE, motion.position.y, probe.offset.y); if (param.XY_seen.x != param.XY_seen.y) { SERIAL_ECHOLNPGM("Both X & Y locations must be specified.\n"); @@ -1202,8 +1220,8 @@ bool unified_bed_leveling::G29_parse_parameters() { // If X or Y are not valid, use center of the bed values // (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 (!COORDINATE_OKAY(sx, X_MIN_BED, X_MAX_BED)) sx = TERN(UBL_HILBERT_CURVE, 0, DIFF_TERN(HAS_BED_PROBE, X_CENTER, probe.offset.x)); + if (!COORDINATE_OKAY(sy, Y_MIN_BED, Y_MAX_BED)) sy = TERN(UBL_HILBERT_CURVE, 0, DIFF_TERN(HAS_BED_PROBE, Y_CENTER, probe.offset.y)); if (err_flag) return UBL_ERR; @@ -1535,10 +1553,10 @@ void unified_bed_leveling::smart_fill_mesh() { #ifndef G29J_MESH_TILT_MARGIN #define G29J_MESH_TILT_MARGIN 0 #endif - const float x_min = _MAX((X_MIN_POS) + (G29J_MESH_TILT_MARGIN), MESH_MIN_X, probe.min_x()), - x_max = _MIN((X_MAX_POS) - (G29J_MESH_TILT_MARGIN), MESH_MAX_X, probe.max_x()), - y_min = _MAX((Y_MIN_POS) + (G29J_MESH_TILT_MARGIN), MESH_MIN_Y, probe.min_y()), - y_max = _MIN((Y_MAX_POS) - (G29J_MESH_TILT_MARGIN), MESH_MAX_Y, probe.max_y()), + const float x_min = _MAX((X_MIN_POS) + (G29J_MESH_TILT_MARGIN), mesh_min.x, probe.min_x()), + x_max = _MIN((X_MAX_POS) - (G29J_MESH_TILT_MARGIN), mesh_max.x, probe.max_x()), + y_min = _MAX((Y_MIN_POS) + (G29J_MESH_TILT_MARGIN), mesh_min.y, probe.min_y()), + y_max = _MIN((Y_MAX_POS) - (G29J_MESH_TILT_MARGIN), mesh_max.y, probe.max_y()), dx = (x_max - x_min) / (param.J_grid_size - 1), dy = (y_max - y_min) / (param.J_grid_size - 1); @@ -1760,14 +1778,12 @@ void unified_bed_leveling::smart_fill_mesh() { SERIAL_ECHOLNPGM("Probe Offset M851 Z", p_float_t(probe.offset.z, 7)); #endif - SERIAL_ECHOLNPGM("MESH_MIN_X " STRINGIFY(MESH_MIN_X) "=", MESH_MIN_X); serial_delay(50); - SERIAL_ECHOLNPGM("MESH_MIN_Y " STRINGIFY(MESH_MIN_Y) "=", MESH_MIN_Y); serial_delay(50); - SERIAL_ECHOLNPGM("MESH_MAX_X " STRINGIFY(MESH_MAX_X) "=", MESH_MAX_X); serial_delay(50); - SERIAL_ECHOLNPGM("MESH_MAX_Y " STRINGIFY(MESH_MAX_Y) "=", MESH_MAX_Y); serial_delay(50); - SERIAL_ECHOLNPGM("GRID_MAX_POINTS_X ", GRID_MAX_POINTS_X); serial_delay(50); - SERIAL_ECHOLNPGM("GRID_MAX_POINTS_Y ", GRID_MAX_POINTS_Y); serial_delay(50); + SERIAL_ECHOLNPGM("mesh_min ", mesh_min.x, ", ", mesh_min.y); serial_delay(50); + SERIAL_ECHOLNPGM("mesh_max ", mesh_max.x, ", ", mesh_max.y); serial_delay(50); + SERIAL_ECHOLNPGM("GRID_MAX_POINTS_X ", GRID_MAX_POINTS_X); serial_delay(50); + SERIAL_ECHOLNPGM("GRID_MAX_POINTS_Y ", GRID_MAX_POINTS_Y); serial_delay(50); SERIAL_ECHOLNPGM("MESH_X_DIST ", MESH_X_DIST); - SERIAL_ECHOLNPGM("MESH_Y_DIST ", MESH_Y_DIST); serial_delay(50); + SERIAL_ECHOLNPGM("MESH_Y_DIST ", MESH_Y_DIST); serial_delay(50); SERIAL_ECHOPGM("X-Axis Mesh Points at: "); for (uint8_t i = 0; i < GRID_MAX_POINTS_X; ++i) { diff --git a/Marlin/src/feature/bedlevel/ubl/ubl_motion.cpp b/Marlin/src/feature/bedlevel/ubl/ubl_motion.cpp index fa77bc1e18..40c308e39a 100644 --- a/Marlin/src/feature/bedlevel/ubl/ubl_motion.cpp +++ b/Marlin/src/feature/bedlevel/ubl/ubl_motion.cpp @@ -414,8 +414,8 @@ // for mesh inset area. xy_int8_t icell = { - int8_t((raw.x - (MESH_MIN_X)) * RECIPROCAL(MESH_X_DIST)), - int8_t((raw.y - (MESH_MIN_Y)) * RECIPROCAL(MESH_Y_DIST)) + 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_CELLS_X); LIMIT(icell.y, 0, GRID_MAX_CELLS_Y); diff --git a/Marlin/src/gcode/bedlevel/abl/G29.cpp b/Marlin/src/gcode/bedlevel/abl/G29.cpp index 0830725170..f9e0fa2bb0 100644 --- a/Marlin/src/gcode/bedlevel/abl/G29.cpp +++ b/Marlin/src/gcode/bedlevel/abl/G29.cpp @@ -56,6 +56,10 @@ #include "../../../lcd/sovol_rts/sovol_rts.h" #endif +#if ENABLED(DWIN_LCD_PROUI) + #include "../../../lcd/dwin/proui/meshviewer.h" +#endif + #define DEBUG_OUT ENABLED(DEBUG_LEVELING_FEATURE) #include "../../../core/debug_out.h" @@ -257,6 +261,8 @@ G29_TYPE GcodeSuite::G29() { // Send 'N' to force homing before G29 (internal only) if (parser.seen_test('N')) process_subcommands_now(TERN(CAN_SET_LEVELING_AFTER_G28, F("G28L0"), FPSTR(G28_STR))); + else if (ENABLED(DWIN_LCD_PROUI)) + process_subcommands_now(F("G28Z")); // Don't allow auto-leveling without homing first if (motion.homing_needed_error()) G29_RETURN(false, false); @@ -681,6 +687,8 @@ G29_TYPE GcodeSuite::G29() { // Outer loop is Y with PROBE_Y_FIRST disabled for (PR_OUTER_VAR = 0; PR_OUTER_VAR < PR_OUTER_SIZE && !isnan(abl.measured_z); PR_OUTER_VAR++) { + if (TERN0(DWIN_LCD_PROUI, hmiFlag.cancel_lev)) break; + int8_t inStart, inStop, inInc; if (zig) { // Zig away from origin @@ -795,6 +803,7 @@ G29_TYPE GcodeSuite::G29() { const float z = abl.measured_z + abl.Z_offset; abl.z_values[abl.meshCount.x][abl.meshCount.y] = z; TERN_(EXTENSIBLE_UI, ExtUI::onMeshUpdate(abl.meshCount, z)); + TERN_(DWIN_LCD_PROUI, meshViewer.drawMeshPoint(abl.meshCount, z)); #if ENABLED(SOVOL_SV06_RTS) if (pt_index <= GRID_MAX_POINTS) rts.sendData(pt_index, AUTO_BED_LEVEL_ICON_VP); @@ -807,6 +816,8 @@ G29_TYPE GcodeSuite::G29() { abl.reenable = false; // Don't re-enable after modifying the mesh marlin.idle_no_sleep(); + if (TERN0(DWIN_LCD_PROUI, hmiFlag.cancel_lev)) break; + } // inner } // outer @@ -1011,7 +1022,7 @@ G29_TYPE GcodeSuite::G29() { // Restore state after probing if (!faux) motion.restore_feedrate_and_scaling(); - TERN_(HAS_BED_PROBE, probe.move_z_after_probing()); + probe.move_z_after_probing(); #ifdef EVENT_GCODE_AFTER_G29 if (DEBUGGING(LEVELING)) DEBUG_ECHOLNPGM("After G29 G-code: ", EVENT_GCODE_AFTER_G29); diff --git a/Marlin/src/inc/Conditionals-2-LCD.h b/Marlin/src/inc/Conditionals-2-LCD.h index 72bad45c89..511950ce59 100644 --- a/Marlin/src/inc/Conditionals-2-LCD.h +++ b/Marlin/src/inc/Conditionals-2-LCD.h @@ -581,6 +581,9 @@ #define DO_LIST_BIN_FILES 1 #define LCD_BRIGHTNESS_DEFAULT 127 #define STATUS_DO_CLEAR_EMPTY + #if HAS_MESH + #define HAS_PROUI_MESH_EDIT 1 + #endif #endif // Serial Controllers require LCD_SERIAL_PORT diff --git a/Marlin/src/inc/Conditionals-4-adv.h b/Marlin/src/inc/Conditionals-4-adv.h index 664fd38e40..f4a574dac0 100644 --- a/Marlin/src/inc/Conditionals-4-adv.h +++ b/Marlin/src/inc/Conditionals-4-adv.h @@ -105,7 +105,14 @@ #endif #endif -#if !(ANY(HAS_BED_PROBE, BACKLASH_GCODE) || (ENABLED(EXTENSIBLE_UI) && ANY(MESH_BED_LEVELING, AUTO_BED_LEVELING_UBL))) +#if HAS_BED_PROBE + #ifndef Z_PROBE_FEEDRATE_SLOW + #define Z_PROBE_FEEDRATE_SLOW (4*60) + #endif + #ifndef Z_PROBE_FEEDRATE_FAST + #define Z_PROBE_FEEDRATE_FAST (Z_PROBE_FEEDRATE_SLOW / 2) + #endif +#elif !(ANY(HAS_BED_PROBE, BACKLASH_GCODE) || ALL(EXTENSIBLE_UI, HAS_MESH)) #undef Z_PROBE_FEEDRATE_FAST #undef Z_PROBE_FEEDRATE_SLOW #endif diff --git a/Marlin/src/inc/Conditionals-5-post.h b/Marlin/src/inc/Conditionals-5-post.h index 05e036c774..4f65916491 100644 --- a/Marlin/src/inc/Conditionals-5-post.h +++ b/Marlin/src/inc/Conditionals-5-post.h @@ -3415,7 +3415,7 @@ /** * Default mesh area is an area with an inset margin on the print area. */ -#if ANY(MESH_BED_LEVELING, AUTO_BED_LEVELING_UBL) +#if HAS_MESH #if IS_KINEMATIC // Probing points may be verified at compile time within the radius // using static_assert(HYPOT2(X2-X1,Y2-Y1)<=sq(PRINTABLE_RADIUS),"bad probe point!") diff --git a/Marlin/src/inc/SanityCheck.h b/Marlin/src/inc/SanityCheck.h index 6be3b167db..0e96c355f5 100644 --- a/Marlin/src/inc/SanityCheck.h +++ b/Marlin/src/inc/SanityCheck.h @@ -1593,7 +1593,7 @@ static_assert(NUM_SERVOS <= NUM_SERVO_PLUGS, "NUM_SERVOS (or some servo index) i static_assert(Z_AFTER_PROBING >= 0, "Probes require Z_AFTER_PROBING >= 0."); #endif - #if MULTIPLE_PROBING > 0 || EXTRA_PROBING > 0 + #if DISABLED(DWIN_LCD_PROUI) && (MULTIPLE_PROBING > 0 || EXTRA_PROBING > 0) #if MULTIPLE_PROBING == 0 #error "EXTRA_PROBING requires MULTIPLE_PROBING." #elif MULTIPLE_PROBING < 2 diff --git a/Marlin/src/lcd/dwin/proui/bedlevel_tools.cpp b/Marlin/src/lcd/dwin/proui/bedlevel_tools.cpp index 91a991d29f..283f46e909 100644 --- a/Marlin/src/lcd/dwin/proui/bedlevel_tools.cpp +++ b/Marlin/src/lcd/dwin/proui/bedlevel_tools.cpp @@ -45,6 +45,11 @@ #if ALL(DWIN_LCD_PROUI, HAS_LEVELING) +#include "dwin.h" +#include "dwinui.h" +#include "dwin_popup.h" +#include "bedlevel_tools.h" + #include "../../marlinui.h" #include "../../../core/types.h" #include "../../../feature/bedlevel/bedlevel.h" @@ -55,14 +60,12 @@ #include "../../../libs/least_squares_fit.h" #include "../../../libs/vector_3.h" -#include "dwin.h" -#include "dwinui.h" -#include "dwin_popup.h" -#include "bedlevel_tools.h" +#define DEBUG_OUT ENABLED(DEBUG_LEVELING_FEATURE) +#include "../../../core/debug_out.h" BedLevelTools bedLevelTools; -#if ENABLED(USE_GRID_MESHVIEWER) +#if USE_GRID_MESHVIEWER bool BedLevelTools::grid_meshview = false; bool BedLevelTools::viewer_print_value = false; #endif @@ -152,7 +155,7 @@ void BedLevelTools::moveToZ() { } void BedLevelTools::probeXY() { gcode.process_subcommands_now( - MString( + TS( F("G28O\nG0Z"), uint16_t(Z_CLEARANCE_DEPLOY_PROBE), F("\nG30X"), p_float_t(bedlevel.get_mesh_x(mesh_x), 2), F("Y"), p_float_t(bedlevel.get_mesh_y(mesh_y), 2) @@ -161,6 +164,7 @@ void BedLevelTools::probeXY() { } void BedLevelTools::meshReset() { + set_bed_leveling_enabled(false); ZERO(bedlevel.z_values); TERN_(AUTO_BED_LEVELING_BILINEAR, bedlevel.refresh_bed_level()); } @@ -180,16 +184,17 @@ float BedLevelTools::getMinValue() { // Return 'true' if mesh is good and within LCD limits bool BedLevelTools::meshValidate() { + if (mesh_max.x <= mesh_min.x || mesh_max.y <= mesh_min.y) + return false; GRID_LOOP(x, y) { const float z = bedlevel.z_values[x][y]; - if (isnan(z) || !WITHIN(z, Z_OFFSET_MIN, Z_OFFSET_MAX)) return false; + if (isnan(z) || TERN0(HAS_PROUI_MESH_EDIT, !WITHIN(z, Z_OFFSET_MIN, Z_OFFSET_MAX))) + return false; } return true; } -#if ENABLED(USE_GRID_MESHVIEWER) - - constexpr uint8_t meshfont = TERN(TJC_DISPLAY, font8x16, font6x12); +#if USE_GRID_MESHVIEWER void BedLevelTools::drawBedMesh(int16_t selected/*=-1*/, uint8_t gridline_width/*=1*/, uint16_t padding_x/*=8*/, uint16_t padding_y_top/*=(40 + 53 - 7)*/) { drawing_mesh = true; @@ -216,8 +221,8 @@ bool BedLevelTools::meshValidate() { const auto end_y_px = start_y_px + cell_height_px - 1 - gridline_width; const float z = bedlevel.z_values[x][y]; const uint16_t color = isnan(z) ? COLOR_GREY : ( // Gray if undefined - (z < 0 ? uint16_t(LROUND(0x1F * -z / rmax)) << 11 // Red for negative mesh point - : uint16_t(LROUND(0x3F * z / rmax)) << 5) // Green for positive mesh point + (z > 0 ? uint16_t(LROUND(0x1F * z / rmax)) << 11 // Red for positive mesh point + : uint16_t(LROUND(0x3F * -z / rmax)) << 5) // Green for negative mesh point | _MIN(0x1F, (uint8_t(abs(z) * 0.4))) // + Blue stepping for every mm ); @@ -229,10 +234,10 @@ bool BedLevelTools::meshValidate() { // Draw value text on if (!viewer_print_value) continue; - const uint8_t fs = DWINUI::fontWidth(meshfont); + const uint8_t fs = DWINUI::fontWidth(title.meshfont); const int8_t offset_y = cell_height_px / 2 - fs; if (isnan(z)) { // undefined - dwinDrawString(false, meshfont, COLOR_WHITE, COLOR_BG_BLUE, start_x_px + cell_width_px / 2 - 5, start_y_px + offset_y, F("X")); + dwinDrawString(false, title.meshfont, COLOR_WHITE, COLOR_BG_BLUE, start_x_px + cell_width_px / 2 - 5, start_y_px + offset_y, F("X")); } else { // has value MString<12> msg; @@ -243,8 +248,8 @@ bool BedLevelTools::meshValidate() { msg.set(p_float_t(abs(z), 2)); const int8_t offset_x = cell_width_px / 2 - (fs / 2) * msg.length() - 2; if (is_wide) - dwinDrawString(false, meshfont, COLOR_WHITE, COLOR_BG_BLUE, start_x_px - 2 + offset_x, start_y_px + offset_y, F(".")); - dwinDrawString(false, meshfont, COLOR_WHITE, COLOR_BG_BLUE, start_x_px + 1 + offset_x, start_y_px + offset_y, msg); + dwinDrawString(false, title.meshfont, COLOR_WHITE, COLOR_BG_BLUE, start_x_px - 2 + offset_x, start_y_px + offset_y, F(".")); + dwinDrawString(false, title.meshfont, COLOR_WHITE, COLOR_BG_BLUE, start_x_px + 1 + offset_x, start_y_px + offset_y, msg); } safe_delay(10); diff --git a/Marlin/src/lcd/dwin/proui/bedlevel_tools.h b/Marlin/src/lcd/dwin/proui/bedlevel_tools.h index 26f2ecc399..e59da88f28 100644 --- a/Marlin/src/lcd/dwin/proui/bedlevel_tools.h +++ b/Marlin/src/lcd/dwin/proui/bedlevel_tools.h @@ -42,8 +42,6 @@ */ #pragma once -#include "../../../inc/MarlinConfigPre.h" - class BedLevelTools { public: #if USE_GRID_MESHVIEWER diff --git a/Marlin/src/lcd/dwin/proui/dwin.cpp b/Marlin/src/lcd/dwin/proui/dwin.cpp index 5d4a102fd2..64d2091657 100644 --- a/Marlin/src/lcd/dwin/proui/dwin.cpp +++ b/Marlin/src/lcd/dwin/proui/dwin.cpp @@ -179,7 +179,7 @@ enum SelectItem : uint8_t { PAGE_PRINT = 0, PAGE_PREPARE, PAGE_CONTROL, - PAGE_ADVANCE, + PAGE_LEVEL, PAGE_COUNT, PRINT_SETUP = 0, @@ -215,6 +215,7 @@ Menu *prepareMenu = nullptr; Menu *moveMenu = nullptr; Menu *controlMenu = nullptr; Menu *advancedSettingsMenu = nullptr; +Menu *levelMenu = nullptr; #if HAS_HOME_OFFSET Menu *homeOffsetMenu = nullptr; #endif @@ -275,7 +276,8 @@ Menu *stepsMenu = nullptr; #endif #if HAS_MESH Menu *meshMenu = nullptr; - #if ENABLED(PROUI_MESH_EDIT) + #if HAS_PROUI_MESH_EDIT + Menu *meshInsetMenu = nullptr; Menu *editMeshMenu = nullptr; #endif #endif @@ -368,12 +370,12 @@ void ICON_Control() { } // -// Main Menu: "Advanced Settings" +// Main Menu: "Level" // -void ICON_AdvSettings() { +void ICON_Level() { constexpr frame_rect_t ico = { 145, 226, 110, 100 }; constexpr text_info_t txt = { 91, { 405, 447 }, 27, 15 }; - ICON_Button(select_page.now == PAGE_ADVANCE, ICON_Info_0, ico, txt, GET_TEXT_F(MSG_BUTTON_ADVANCED)); + ICON_Button(select_page.now == PAGE_LEVEL, ICON_Leveling_0, ico, txt, GET_TEXT_F(MSG_BUTTON_LEVEL)); } // @@ -685,7 +687,7 @@ void drawMainMenu() { ICON_Print(); ICON_Prepare(); ICON_Control(); - ICON_AdvSettings(); + ICON_Level(); } void gotoMainMenu() { @@ -1145,7 +1147,7 @@ void hmiMainMenu() { case PAGE_PRINT: ICON_Print(); break; case PAGE_PREPARE: ICON_Print(); ICON_Prepare(); break; case PAGE_CONTROL: ICON_Prepare(); ICON_Control(); break; - case PAGE_ADVANCE: ICON_Control(); ICON_AdvSettings(); break; + case PAGE_LEVEL: ICON_Control(); ICON_Level(); break; } } } @@ -1154,8 +1156,8 @@ void hmiMainMenu() { switch (select_page.now) { case PAGE_PRINT: ICON_Print(); ICON_Prepare(); break; case PAGE_PREPARE: ICON_Prepare(); ICON_Control(); break; - case PAGE_CONTROL: ICON_Control(); ICON_AdvSettings(); break; - case PAGE_ADVANCE: ICON_AdvSettings(); break; + case PAGE_CONTROL: ICON_Control(); ICON_Level(); break; + case PAGE_LEVEL: ICON_Level(); break; } } } @@ -1170,7 +1172,7 @@ void hmiMainMenu() { break; case PAGE_PREPARE: drawPrepareMenu(); break; case PAGE_CONTROL: drawControlMenu(); break; - case PAGE_ADVANCE: drawAdvancedSettingsMenu(); break; + case PAGE_LEVEL: drawLevelMenu(); break; } } dwinUpdateLCD(); @@ -1262,7 +1264,7 @@ void drawMainArea() { case ID_SetPInt: case ID_SetIntNoDraw: case ID_SetFloat: - case ID_SetPFloat: ReDrawMenu(true); break; + case ID_SetPFloat: redrawMenu(true); break; default: break; } } @@ -1277,6 +1279,12 @@ void hmiWaitForUser() { if (!marlin.wait_for_user) { switch (checkkey) { case ID_PrintDone: select_page.reset(); gotoMainMenu(); break; + case ID_Leveling: + hmiFlag.cancel_lev = 1; + dwinDrawStatusLine("Canceling auto leveling..."); + dwinUpdateLCD(); + case ID_NothingToDo: + break; default: ui.reset_status(true); hmiReturnScreen(); break; } } @@ -1288,7 +1296,7 @@ void hmiInit() { #define BOOTSCREEN_TIMEOUT 1100 #endif DWINUI::drawBox(1, COLOR_BLACK, { 5, 220, DWIN_WIDTH - 5, DWINUI::fontHeight() }); - DWINUI::drawCenteredString(COLOR_WHITE, 220, F("ProUI starting up ")); + DWINUI::drawCenteredString(COLOR_WHITE, 220, F("ProUI starting up")); for (uint16_t t = 15; t < 257; t += 11) { DWINUI::drawIcon(ICON_Bar, 15, 260); dwinDrawRectangle(1, hmiData.colorBackground, t, 260, 257, 280); @@ -1538,7 +1546,7 @@ void hmiReturnScreen() { void dwinHomingStart() { hmiFlag.home_flag = true; - hmiSaveProcessID(ID_Homing); + if (checkkey != ID_NothingToDo) { hmiSaveProcessID(ID_Homing); } title.showCaption(GET_TEXT_F(MSG_HOMING)); dwinShowPopup(HOME_AND_KILL_ICON, GET_TEXT_F(MSG_HOMING), GET_TEXT_F(MSG_PLEASE_WAIT)); } @@ -1547,26 +1555,44 @@ void dwinHomingDone() { hmiFlag.home_flag = false; if (last_checkkey == ID_PrintDone) gotoPrintDone(); - else - hmiReturnScreen(); + else if (checkkey != ID_NothingToDo) { hmiReturnScreen(); } } -void dwinLevelingStart() { - #if HAS_BED_PROBE - hmiSaveProcessID(ID_Leveling); - title.showCaption(GET_TEXT_F(MSG_BED_LEVELING)); - dwinShowPopup(ICON_AutoLeveling, GET_TEXT_F(MSG_BED_LEVELING), GET_TEXT_F(MSG_PLEASE_WAIT)); +#if HAS_LEVELING + void dwinLevelingStart() { + #if HAS_BED_PROBE + hmiFlag.cancel_lev = 0; + hmiSaveProcessID(ID_Leveling); + title.showCaption(GET_TEXT_F(MSG_BED_LEVELING)); + #if ENABLED(AUTO_BED_LEVELING_UBL) + meshViewer.drawMeshGrid(GRID_MAX_POINTS_X, GRID_MAX_POINTS_Y); + DWINUI::drawButton(BTN_Cancel, 86, 305); + #else + dwinShowPopup(ICON_AutoLeveling, GET_TEXT_F(MSG_BED_LEVELING), GET_TEXT_F(MSG_PLEASE_WAIT)); + #endif + #elif ENABLED(MESH_BED_LEVELING) + drawManualMeshMenu(); + #endif #if ALL(AUTO_BED_LEVELING_UBL, PREHEAT_BEFORE_LEVELING) if (!DEBUGGING(DRYRUN)) probe.preheat_for_probing(LEVELING_NOZZLE_TEMP, hmiData.bedLevT); #endif - #elif ENABLED(MESH_BED_LEVELING) - drawManualMeshMenu(); - #endif -} + } -void dwinLevelingDone() { - TERN_(HAS_MESH, gotoMeshViewer(true)); -} + #if ALL(HAS_MESH, HAS_BED_PROBE) + void dwinLevelingDone() { + if (hmiFlag.cancel_lev) { + probe.stow(); + reset_bed_level(); + hmiReturnScreen(); + dwinUpdateLCD(); + ui.set_status(F("Mesh was cancelled")); + } + else { + gotoMeshViewer(true); + } + } + #endif +#endif // HAS_LEVELING #if HAS_MESH void dwinMeshUpdate(const int8_t cpos, const int8_t tpos, const float zval) { @@ -1580,8 +1606,6 @@ void dwinLevelingDone() { #if PROUI_TUNING_GRAPH - #include "plot.h" - celsius_t _maxtemp, _target; void dwinDrawPIDMPCPopup() { constexpr frame_rect_t gfrm = { 30, 150, DWIN_WIDTH - 60, 160 }; @@ -1874,13 +1898,13 @@ void dwinSetColorDefaults() { hmiData.colorCoordinate = defColorCoordinate; } -static_assert(ExtUI::eeprom_data_size >= sizeof(hmi_data_t), "Insufficient space in EEPROM for UI parameters"); +static_assert(ExtUI::eeprom_data_size >= EXTUI_EEPROM_DATA_SIZE, "Insufficient space in EEPROM for UI parameters"); void dwinSetDataDefaults() { dwinSetColorDefaults(); DWINUI::setColors(hmiData.colorText, hmiData.colorBackground, hmiData.colorStatusBg); - TERN_(PIDTEMP, hmiData.hotendPIDT = DEF_HOTENDPIDT); - TERN_(PIDTEMPBED, hmiData.bedPIDT = DEF_BEDPIDT); + TERN_(PIDTEMP, hmiData.hotendPIDT = PREHEAT_1_TEMP_HOTEND); + TERN_(PIDTEMPBED, hmiData.bedPIDT = PREHEAT_1_TEMP_BED); TERN_(HAS_PID_HEATING, hmiData.pidCycles = DEF_PIDCYCLES); #if ENABLED(PREVENT_COLD_EXTRUSION) hmiData.extMinT = EXTRUDE_MINTEMP; @@ -1904,6 +1928,9 @@ void dwinSetDataDefaults() { applyLEDColor(); #endif TERN_(HAS_GCODE_PREVIEW, hmiData.enablePreview = true); + #if HAS_BED_PROBE && DISABLED(BD_SENSOR) + hmiData.multiple_probing = MULTIPLE_PROBING; + #endif } void dwinCopySettingsTo(char * const buff) { @@ -1929,15 +1956,6 @@ void dwinCopySettingsFrom(const char * const buff) { } // Initialize or re-initialize the LCD -void MarlinUI::init_lcd() { - delay(750); // Wait to wakeup screen - const bool hs = dwinHandshake(); UNUSED(hs); - dwinFrameSetDir(1); - dwinJPGCacheTo1(Language_English); -} - -void MarlinUI::clear_lcd() {} - void dwinInitScreen() { dwinSetColorDefaults(); hmiInit(); // Draws boot screen @@ -1952,6 +1970,37 @@ void dwinInitScreen() { gotoMainMenu(); } +void dwinRebootScreen() { + dwinFrameClear(COLOR_BG_BLACK); + dwinJPGShowAndCache(0); + DWINUI::drawCenteredString(COLOR_WHITE, 220, GET_TEXT_F(MSG_PLEASE_WAIT_REBOOT)); + dwinUpdateLCD(); + safe_delay(500); +} + +void dwinRedrawDash() { + hash_changed = true; + dwinDrawStatusMessage(); + dwinDrawDashboard(); +} + +void dwinRedrawScreen() { + drawMainArea(); + dwinRedrawDash(); +} + +// +// MarlinUI functions +// +void MarlinUI::init_lcd() { + delay(750); // Wait to wakeup screen + const bool hs = dwinHandshake(); UNUSED(hs); + dwinFrameSetDir(1); + dwinJPGCacheTo1(Language_English); +} + +void MarlinUI::clear_lcd() {} + void MarlinUI::update() { hmiSDCardUpdate(); // SD card update eachMomentUpdate(); // Status update @@ -1974,133 +2023,6 @@ void MarlinUI::kill_screen(FSTR_P const lcd_error, FSTR_P const) { dwinUpdateLCD(); } -void dwinRebootScreen() { - dwinFrameClear(COLOR_BG_BLACK); - dwinJPGShowAndCache(0); - DWINUI::drawCenteredString(COLOR_WHITE, 220, GET_TEXT_F(MSG_PLEASE_WAIT_REBOOT)); - dwinUpdateLCD(); - safe_delay(500); -} - -void dwinRedrawDash() { - hash_changed = true; - dwinDrawStatusMessage(); - dwinDrawDashboard(); -} - -void dwinRedrawScreen() { - drawMainArea(); - dwinRedrawDash(); -} - -#if ENABLED(ADVANCED_PAUSE_FEATURE) - - void dwinPopupPause(FSTR_P const fmsg, uint8_t button/*=0*/) { - hmiSaveProcessID(button ? ID_WaitResponse : ID_NothingToDo); - dwinShowPopup(ICON_Pause_1, GET_TEXT_F(MSG_ADVANCED_PAUSE), fmsg, button); - } - - void drawPopupFilamentPurge() { - dwinDrawPopup(ICON_AutoLeveling, GET_TEXT_F(MSG_ADVANCED_PAUSE), GET_TEXT_F(MSG_FILAMENT_CHANGE_PURGE_CONTINUE)); - DWINUI::drawButton(BTN_Purge, 26, 280); - DWINUI::drawButton(BTN_Continue, 146, 280); - drawSelectHighlight(true); - } - - void onClickFilamentPurge() { - if (hmiFlag.select_flag) - pause_menu_response = PAUSE_RESPONSE_EXTRUDE_MORE; // "Purge More" button - else { - hmiSaveProcessID(ID_NothingToDo); - pause_menu_response = PAUSE_RESPONSE_RESUME_PRINT; // "Continue" button - } - } - - void gotoFilamentPurge() { - pause_menu_response = PAUSE_RESPONSE_WAIT_FOR; - gotoPopup(drawPopupFilamentPurge, onClickFilamentPurge); - } - -#endif // ADVANCED_PAUSE_FEATURE - -#if HAS_MESH - void _dwinMeshViewer() { - if (!leveling_is_valid()) - dwinPopupContinue(ICON_Leveling_1, GET_TEXT_F(MSG_MESH_VIEWER), GET_TEXT_F(MSG_NO_VALID_MESH)); - else { - hmiSaveProcessID(ID_WaitResponse); - meshViewer.draw(); - } - } - void dwinMeshViewer() { - TERN_(USE_GRID_MESHVIEWER, bedLevelTools.grid_meshview = false); - _dwinMeshViewer(); - } - #if ENABLED(USE_GRID_MESHVIEWER) - void dwinMeshViewerGrid() { bedLevelTools.grid_meshview = true; _dwinMeshViewer(); } - #endif -#endif - -#if HAS_LOCKSCREEN - - void dwinLockScreen() { - if (checkkey != ID_Locked) { - lockScreen.rprocess = checkkey; - checkkey = ID_Locked; - lockScreen.init(); - } - } - - void dwinUnLockScreen() { - if (checkkey == ID_Locked) { - checkkey = lockScreen.rprocess; - drawMainArea(); - } - } - - void hmiLockScreen() { - EncoderState encoder_diffState = get_encoder_state(); - if (encoder_diffState == ENCODER_DIFF_NO) return; - lockScreen.onEncoder(encoder_diffState); - if (lockScreen.isUnlocked()) dwinUnLockScreen(); - } - -#endif // HAS_LOCKSCREEN - -#if HAS_GCODE_PREVIEW - - void setPreview() { toggleCheckboxLine(hmiData.enablePreview); } - - void onClickConfirmToPrint() { - dwinResetStatusLine(); - if (hmiFlag.select_flag) { // Confirm - gotoMainMenu(); - card.openAndPrintFile(card.filename); - return; - } - else - hmiReturnScreen(); - } - -#endif // HAS_GCODE_PREVIEW - -void gotoConfirmToPrint() { - #if HAS_GCODE_PREVIEW - if (hmiData.enablePreview) { - gotoPopup(preview.drawFromSD, onClickConfirmToPrint); - return; - } - #endif - card.openAndPrintFile(card.filename); // Direct print SD file -} - -#if HAS_ESDIAG - void drawEndStopDiag() { - hmiSaveProcessID(ID_ESDiagProcess); - esDiag.draw(); - } -#endif - //============================================================================= // MENU SUBSYSTEM //============================================================================= @@ -2150,10 +2072,6 @@ void gotoInfoMenu() { void disableMotors() { queue.inject(F("M84")); } -void autoLevel() { // Always reacquire the Z "home" position - queue.inject(F(TERN(AUTO_BED_LEVELING_UBL, "G29P1", "G29"))); -} - void autoHome() { queue.inject_P(G28_STR); } #if ENABLED(INDIVIDUAL_AXIS_HOMING_SUBMENU) @@ -2210,9 +2128,20 @@ void autoHome() { queue.inject_P(G28_STR); } #endif // HAS_ZOFFSET_ITEM #if HAS_PREHEAT - #define _doPreheat(N) void DoPreheat##N() { ui.preheat_all(N-1); }\ - void DoPreheatHotend##N() { ui.preheat_hotend(N-1); } + + #if HAS_HOTEND + #define _DRAW_PREHEAT(N) void onDrawPreheat##N(MenuItem* menuitem, int8_t line) \ + { if (N == 1) { \ + if (hmiIsChinese()) menuitem->setFrame(1, 100, 89, 151, 101); } \ + else if (N == 2) { \ + if (hmiIsChinese()) menuitem->setFrame(1, 180, 89, 233, 100); } \ + onDrawMenuItem(menuitem, line); } + REPEAT_1(PREHEAT_COUNT, _DRAW_PREHEAT) + #endif + + #define _doPreheat(N) void DoPreheat##N() { ui.preheat_all(N-1); } REPEAT_1(PREHEAT_COUNT, _doPreheat) + #endif void doCoolDown() { thermalManager.cooldown(); } @@ -2220,7 +2149,7 @@ void doCoolDown() { thermalManager.cooldown(); } void setLanguage() { hmiToggleLanguage(); currentMenu = nullptr; // Invalidate menu to full redraw - drawPrepareMenu(); + drawControlMenu(); } bool enableLiveMove = false; @@ -2362,6 +2291,17 @@ void setMoveZ() { hmiValue.axis = Z_AXIS; setPFloatOnClick(Z_MIN_POS, Z_MAX_POS, void setHSMode() { toggleCheckboxLine(bltouch.high_speed_mode); } #endif + #if DISABLED(BD_SENSOR) + void applyProbeMultiple() { hmiData.multiple_probing = menuData.value; } + void setProbeMultiple() { setIntOnClick(0, 4, hmiData.multiple_probing, applyProbeMultiple); } + #endif + + void setProbeZSpeed() { setPIntOnClick(60, 1000); } + + void autoLevel() { + queue.inject(F(TERN(AUTO_BED_LEVELING_UBL, "G29P1", "G29"))); + } + #endif #if ENABLED(EDITABLE_DISPLAY_TIMEOUT) @@ -2390,8 +2330,13 @@ void setMoveZ() { hmiValue.axis = Z_AXIS; setPFloatOnClick(Z_MIN_POS, Z_MAX_POS, void setExtMinT() { setPIntOnClick(MIN_ETEMP, MAX_ETEMP, applyExtMinT); } #endif -void setSpeed() { setPIntOnClick(SPEED_EDIT_MIN, SPEED_EDIT_MAX); } -void setFlow() { setPIntOnClick(FLOW_EDIT_MIN, FLOW_EDIT_MAX, []{ planner.refresh_e_factor(0); }); } +#if HAS_FEEDRATE_EDIT + void setSpeed() { setPIntOnClick(SPEED_EDIT_MIN, SPEED_EDIT_MAX); } +#endif + +#if HAS_FLOW_EDIT + void setFlow() { setPIntOnClick(FLOW_EDIT_MIN, FLOW_EDIT_MAX, []{ planner.refresh_e_factor(0); }); } +#endif #if HAS_HOTEND void applyHotendTemp() { thermalManager.setTargetHotend(menuData.value, 0); } @@ -2417,6 +2362,32 @@ void setFlow() { setPIntOnClick(FLOW_EDIT_MIN, FLOW_EDIT_MAX, []{ planner.refres #if ENABLED(ADVANCED_PAUSE_FEATURE) + void dwinPopupPause(FSTR_P const fmsg, uint8_t button/*=0*/) { + hmiSaveProcessID(button ? ID_WaitResponse : ID_NothingToDo); + dwinShowPopup(ICON_Pause_1, GET_TEXT_F(MSG_ADVANCED_PAUSE), fmsg, button); + } + + void drawPopupFilamentPurge() { + dwinDrawPopup(ICON_AutoLeveling, GET_TEXT_F(MSG_ADVANCED_PAUSE), GET_TEXT_F(MSG_FILAMENT_CHANGE_PURGE_CONTINUE)); + DWINUI::drawButton(BTN_Purge, 26, 280); + DWINUI::drawButton(BTN_Continue, 146, 280); + drawSelectHighlight(true); + } + + void onClickFilamentPurge() { + if (hmiFlag.select_flag) + pause_menu_response = PAUSE_RESPONSE_EXTRUDE_MORE; // "Purge More" button + else { + hmiSaveProcessID(ID_NothingToDo); + pause_menu_response = PAUSE_RESPONSE_RESUME_PRINT; // "Continue" button + } + } + + void gotoFilamentPurge() { + pause_menu_response = PAUSE_RESPONSE_WAIT_FOR; + gotoPopup(drawPopupFilamentPurge, onClickFilamentPurge); + } + void changeFilament() { hmiSaveProcessID(ID_NothingToDo); queue.inject(F("M600 B2")); @@ -2436,6 +2407,139 @@ void setFlow() { setPIntOnClick(FLOW_EDIT_MIN, FLOW_EDIT_MAX, []{ planner.refres #endif // ADVANCED_PAUSE_FEATURE +#if HAS_MESH + + void _dwinMeshViewer() { + if (!leveling_is_valid()) + dwinPopupContinue(ICON_Leveling_1, GET_TEXT_F(MSG_MESH_VIEWER), GET_TEXT_F(MSG_NO_VALID_MESH)); + else { + hmiSaveProcessID(ID_WaitResponse); + meshViewer.draw(); + } + } + void dwinMeshViewer() { + TERN_(USE_GRID_MESHVIEWER, bedLevelTools.grid_meshview = false); + _dwinMeshViewer(); + } + #if ENABLED(USE_GRID_MESHVIEWER) + void dwinMeshViewerGrid() { bedLevelTools.grid_meshview = true; _dwinMeshViewer(); } + #endif + + void applyMeshFadeHeight() { set_z_fade_height(planner.z_fade_height); } + void setMeshFadeHeight() { setPFloatOnClick(0, 100, 1, applyMeshFadeHeight); } + + void setMeshActive() { + set_bed_leveling_enabled(!planner.leveling_active); + drawCheckboxLine(currentMenu->line(), planner.leveling_active); + dwinUpdateLCD(); + } + + #if ENABLED(PREHEAT_BEFORE_LEVELING) + void setBedLevT() { setPIntOnClick(MIN_BEDTEMP, MAX_BEDTEMP); } + #endif + +#endif // HAS_MESH + +#if HAS_LOCKSCREEN + + void dwinLockScreen() { + if (checkkey != ID_Locked) { + lockScreen.rprocess = checkkey; + checkkey = ID_Locked; + lockScreen.init(); + } + } + + void dwinUnLockScreen() { + if (checkkey == ID_Locked) { + checkkey = lockScreen.rprocess; + drawMainArea(); + } + } + + void hmiLockScreen() { + EncoderState encoder_diffState = get_encoder_state(); + if (encoder_diffState == ENCODER_DIFF_NO) return; + lockScreen.onEncoder(encoder_diffState); + if (lockScreen.isUnlocked()) dwinUnLockScreen(); + } + +#endif // HAS_LOCKSCREEN + +#if HAS_GCODE_PREVIEW + + void setPreview() { toggleCheckboxLine(hmiData.enablePreview); } + + void onClickConfirmToPrint() { + dwinResetStatusLine(); + if (hmiFlag.select_flag) { // Confirm + gotoMainMenu(); + card.openAndPrintFile(card.filename); + return; + } + else + hmiReturnScreen(); + } + +#endif // HAS_GCODE_PREVIEW + +void gotoConfirmToPrint() { + #if HAS_GCODE_PREVIEW + if (hmiData.enablePreview) { + gotoPopup(preview.drawFromSD, onClickConfirmToPrint); + return; + } + #endif + card.openAndPrintFile(card.filename); // Direct print SD file +} + +#if HAS_ESDIAG + void drawEndStopDiag() { + hmiSaveProcessID(ID_ESDiagProcess); + esDiag.draw(); + } +#endif + +#if ENABLED(AUTO_BED_LEVELING_UBL) + + void applyUBLSlot() { bedlevel.storage_slot = menuData.value; } + void setUBLSlot() { setIntOnClick(0, settings.calc_num_meshes() - 1, bedlevel.storage_slot, applyUBLSlot); } + void onDrawUBLSlot(MenuItem* menuitem, int8_t line) { + NOLESS(bedlevel.storage_slot, 0); + onDrawIntMenu(menuitem, line, bedlevel.storage_slot); + } + + void applyUBLTiltGrid() { bedLevelTools.tilt_grid = menuData.value; } + void setUBLTiltGrid() { setIntOnClick(1, 3, bedLevelTools.tilt_grid, applyUBLTiltGrid); } + + void ublMeshTilt() { + NOLESS(bedlevel.storage_slot, 0); + if (bedLevelTools.tilt_grid > 1) + gcode.process_subcommands_now(TS(F("G29J"), bedLevelTools.tilt_grid)); + else + gcode.process_subcommands_now(F("G29J")); + LCD_MESSAGE(MSG_UBL_MESH_TILTED); + } + + void ublSmartFillMesh() { + for (uint8_t x = 0; x < GRID_MAX_POINTS_Y; ++x) bedlevel.smart_fill_mesh(); + LCD_MESSAGE(MSG_UBL_MESH_FILLED); + } + + void ublMeshSave() { + NOLESS(bedlevel.storage_slot, 0); + settings.store_mesh(bedlevel.storage_slot); + ui.status_printf(0, GET_TEXT_F(MSG_MESH_SAVED), bedlevel.storage_slot); + DONE_BUZZ(true); + } + + void ublMeshLoad() { + NOLESS(bedlevel.storage_slot, 0); + settings.load_mesh(bedlevel.storage_slot); + } + +#endif // AUTO_BED_LEVELING_UBL + // Bed Tramming #if ENABLED(LCD_BED_TRAMMING) @@ -2487,22 +2591,8 @@ void setFlow() { setPIntOnClick(FLOW_EDIT_MIN, FLOW_EDIT_MAX, []{ planner.refres )); } else { - // AUTO_BED_LEVELING_BILINEAR does not define MESH_INSET - #ifndef MESH_MIN_X - #define MESH_MIN_X (_MAX(X_MIN_BED + (PROBING_MARGIN_LEFT), X_MIN_POS)) - #endif - #ifndef MESH_MIN_Y - #define MESH_MIN_Y (_MAX(Y_MIN_BED + (PROBING_MARGIN_FRONT), Y_MIN_POS)) - #endif - #ifndef MESH_MAX_X - #define MESH_MAX_X (_MIN(X_MAX_BED - (PROBING_MARGIN_RIGHT), X_MAX_POS)) - #endif - #ifndef MESH_MAX_Y - #define MESH_MAX_Y (_MIN(Y_MAX_BED - (PROBING_MARGIN_BACK), Y_MAX_POS)) - #endif - - LIMIT(xpos, MESH_MIN_X, MESH_MAX_X); - LIMIT(ypos, MESH_MIN_Y, MESH_MAX_Y); + LIMIT(xpos, mesh_min.x, mesh_max.x); + LIMIT(ypos, mesh_min.y, mesh_max.y); probe.stow(); gcode.process_subcommands_now(F("M420S0\nG28O")); inLev = true; @@ -2740,7 +2830,7 @@ void applyMaxAccel() { planner.set_max_acceleration(hmiValue.axis, menuData.valu #endif #if ENABLED(FWRETRACT) - void returnFWRetractMenu() { (previousMenu == filSetMenu) ? drawFilSetMenu() : drawTuneMenu(); } + void returnFWRetractMenu() { (previousMenu == filamentMenu) ? drawFilamentManMenu() : drawTuneMenu(); } void setRetractLength() { setPFloatOnClick( 0, 10, UNITFDIGITS); } void setRetractSpeed() { setPFloatOnClick( 1, 90, UNITFDIGITS); } void setZRaise() { setPFloatOnClick( 0, 2, 2); } @@ -2833,19 +2923,6 @@ void onDrawAutoHome(MenuItem* menuitem, int8_t line) { #endif #endif -#if HAS_HOTEND - void onDrawPreheat1(MenuItem* menuitem, int8_t line) { - if (hmiIsChinese()) menuitem->setFrame(1, 100, 89, 151, 101); - onDrawMenuItem(menuitem, line); - } - #if PREHEAT_COUNT > 1 - void onDrawPreheat2(MenuItem* menuitem, int8_t line) { - if (hmiIsChinese()) menuitem->setFrame(1, 180, 89, 233, 100); - onDrawMenuItem(menuitem, line); - } - #endif -#endif - #if HAS_PREHEAT void onDrawCooldown(MenuItem* menuitem, int8_t line) { if (hmiIsChinese()) menuitem->setFrame(1, 1, 104, 56, 117); @@ -3151,35 +3228,24 @@ frame_rect_t selrect(frame_rect_t) { } void drawPrepareMenu() { - constexpr uint8_t items = (3 - + COUNT_ENABLED(LCD_BED_TRAMMING) - + 2 - + TERN(MESH_BED_LEVELING, 1, ENABLED(HAS_BED_PROBE)) + constexpr uint8_t items = (5 + TERN(HAS_ZOFFSET_ITEM, ENABLED(HAS_BED_PROBE), ENABLED(BABYSTEPPING)) - + PREHEAT_COUNT + + COUNT_ENABLED(LCD_BED_TRAMMING) + + ENABLED(HAS_PREHEAT) + 1 + 2 * ALL(PROUI_TUNING_GRAPH, PROUI_ITEM_PLOT) - + 1 ); checkkey = ID_Menu; if (SET_MENU_R(prepareMenu, selrect({133, 1, 28, 13}), MSG_PREPARE, items)) { BACK_ITEM(gotoMainMenu); - MENU_ITEM(ICON_FilMan, MSG_FILAMENT_MAN, onDrawSubMenu, drawFilamentManMenu); - MENU_ITEM(ICON_Axis, MSG_MOVE_AXIS, onDrawMoveSubMenu, drawMoveMenu); - #if ENABLED(LCD_BED_TRAMMING) - MENU_ITEM(ICON_Tram, MSG_BED_TRAMMING, onDrawSubMenu, drawTrammingMenu); - #endif - MENU_ITEM(ICON_CloseMotor, MSG_DISABLE_STEPPERS, onDrawDisableMotors, disableMotors); #if ENABLED(INDIVIDUAL_AXIS_HOMING_SUBMENU) MENU_ITEM(ICON_Homing, MSG_HOMING, onDrawSubMenu, drawHomingMenu); #else MENU_ITEM(ICON_Homing, MSG_AUTO_HOME, onDrawAutoHome, autoHome); #endif - #if ENABLED(MESH_BED_LEVELING) - MENU_ITEM(ICON_ManualMesh, MSG_MANUAL_MESH, onDrawSubMenu, drawManualMeshMenu); - #elif HAS_BED_PROBE - MENU_ITEM(ICON_Level, MSG_AUTO_MESH, onDrawMenuItem, autoLevel); - #endif + MENU_ITEM(ICON_Axis, MSG_MOVE_AXIS, onDrawMoveSubMenu, drawMoveMenu); + MENU_ITEM(ICON_CloseMotor, MSG_DISABLE_STEPPERS, onDrawDisableMotors, disableMotors); + MENU_ITEM(ICON_FilMan, MSG_FILAMENT_MAN, onDrawSubMenu, drawFilamentManMenu); #if HAS_ZOFFSET_ITEM #if HAS_BED_PROBE MENU_ITEM(ICON_SetZOffset, MSG_PROBE_WIZARD, onDrawSubMenu, drawZOffsetWizMenu); @@ -3187,16 +3253,21 @@ void drawPrepareMenu() { EDIT_ITEM(ICON_Zoffset, MSG_HOME_OFFSET_Z, onDrawPFloat2Menu, setZOffset, &BABY_Z_VAR); #endif #endif + #if ENABLED(LCD_BED_TRAMMING) + MENU_ITEM(ICON_Tram, MSG_BED_TRAMMING, onDrawSubMenu, drawTrammingMenu); + #endif #if HAS_PREHEAT - #define _ITEM_PREHEAT(N) MENU_ITEM(ICON_Preheat##N, MSG_PREHEAT_##N, onDrawMenuItem, DoPreheat##N); - REPEAT_1(PREHEAT_COUNT, _ITEM_PREHEAT) + #if PREHEAT_COUNT > 1 + MENU_ITEM(ICON_SetEndTemp, MSG_PREHEAT_HOTEND, onDrawSubMenu, drawPreheatHotendMenu); + #else + MENU_ITEM(ICON_Preheat1, MSG_PREHEAT_1, onDrawPreheat1, DoPreheat1); + #endif #endif MENU_ITEM(ICON_Cool, MSG_COOLDOWN, onDrawCooldown, doCoolDown); #if ALL(PROUI_TUNING_GRAPH, PROUI_ITEM_PLOT) MENU_ITEM(ICON_PIDNozzle, MSG_HOTEND_TEMP_GRAPH, onDrawMenuItem, drawHPlot); MENU_ITEM(ICON_PIDBed, MSG_BED_TEMP_GRAPH, onDrawMenuItem, drawBPlot); #endif - MENU_ITEM(ICON_Language, MSG_UI_LANGUAGE, onDrawLanguage, setLanguage); } ui.reset_status(true); updateMenu(prepareMenu); @@ -3235,26 +3306,25 @@ void drawPrepareMenu() { void drawControlMenu() { constexpr uint8_t items = (3 - + COUNT_ENABLED(CASE_LIGHT_MENU, LED_CONTROL_MENU) + + ENABLED(HAS_CUSTOM_COLORS) + + ENABLED(HAS_ESDIAG) + + ENABLED(HAS_LOCKSCREEN) + TERN0(EEPROM_SETTINGS, 3) - + 2 + + 4 ); checkkey = ID_Menu; if (SET_MENU_R(controlMenu, selrect({103, 1, 28, 14}), MSG_CONTROL, items)) { BACK_ITEM(gotoMainMenu); MENU_ITEM(ICON_Temperature, MSG_TEMPERATURE, onDrawTempSubMenu, drawTemperatureMenu); MENU_ITEM(ICON_Motion, MSG_MOTION, onDrawMotionSubMenu, drawMotionMenu); - #if ENABLED(CASE_LIGHT_MENU) - #if CASELIGHT_USES_BRIGHTNESS - enableLiveCaseLightBrightness = true; // Allow live update of brightness in control menu - MENU_ITEM(ICON_CaseLight, MSG_CASE_LIGHT, onDrawSubMenu, drawCaseLightMenu); - #else - EDIT_ITEM(ICON_CaseLight, MSG_CASE_LIGHT, onDrawChkbMenu, setCaseLight, &caselight.on); - #endif + #if HAS_CUSTOM_COLORS + MENU_ITEM(ICON_Scolor, MSG_COLORS_SELECT, onDrawSubMenu, drawSelectColorsMenu); #endif - #if ENABLED(LED_CONTROL_MENU) - enableLiveLedColor = true; // Allow live update of color in control menu - MENU_ITEM(ICON_LedControl, MSG_LED_CONTROL, onDrawSubMenu, drawLedControlMenu); + #if HAS_ESDIAG + MENU_ITEM_F(ICON_esDiag, "End-stops diag.", onDrawSubMenu, drawEndStopDiag); + #endif + #if HAS_LOCKSCREEN + MENU_ITEM(ICON_Lock, MSG_LOCKSCREEN, onDrawMenuItem, dwinLockScreen); #endif #if ENABLED(EEPROM_SETTINGS) MENU_ITEM(ICON_WriteEEPROM, MSG_STORE_EEPROM, onDrawWriteEeprom, writeEEPROM); @@ -3262,7 +3332,9 @@ void drawControlMenu() { MENU_ITEM(ICON_ResetEEPROM, MSG_RESTORE_DEFAULTS, onDrawResetEeprom, resetEEPROM); #endif MENU_ITEM(ICON_Reboot, MSG_RESET_PRINTER, onDrawMenuItem, rebootPrinter); + MENU_ITEM(ICON_AdvSet, MSG_ADVANCED_SETTINGS, onDrawSubMenu, drawAdvancedSettingsMenu); MENU_ITEM(ICON_Info, MSG_INFO_SCREEN, onDrawInfoSubMenu, gotoInfoMenu); + MENU_ITEM(ICON_Language, MSG_UI_LANGUAGE, onDrawLanguage, setLanguage); } ui.reset_status(true); updateMenu(controlMenu); @@ -3270,16 +3342,16 @@ void drawControlMenu() { void drawAdvancedSettingsMenu() { constexpr uint8_t items = (1 - + COUNT_ENABLED(EEPROM_SETTINGS, HAS_MESH, HAS_BED_PROBE, HAS_HOME_OFFSET, HAS_TRINAMIC_CONFIG, HAS_ESDIAG, \ - HAS_LOCKSCREEN, EDITABLE_DISPLAY_TIMEOUT, SOUND_MENU_ITEM, POWER_LOSS_RECOVERY, HAS_GCODE_PREVIEW, \ - PROUI_MEDIASORT, BAUD_RATE_GCODE, HAS_CUSTOM_COLORS) - + 1 + + COUNT_ENABLED(EEPROM_SETTINGS, HAS_BED_PROBE, HAS_HOME_OFFSET) + (ENABLED(PIDTEMP) && ANY(PID_AUTOTUNE_MENU, PID_EDIT_MENU)) + ANY(MPC_EDIT_MENU, MPC_AUTOTUNE_MENU) + (ENABLED(PIDTEMPBED) && ANY(PID_AUTOTUNE_MENU, PID_EDIT_MENU)) + TERN0(PRINTCOUNTER, 2) + + COUNT_ENABLED(EDITABLE_DISPLAY_TIMEOUT, SOUND_MENU_ITEM, POWER_LOSS_RECOVERY, HAS_GCODE_PREVIEW, PROUI_MEDIASORT) + 1 + TERN0(HAS_LCD_BRIGHTNESS, 2) + + ENABLED(CASE_LIGHT_MENU) + + ENABLED(LED_CONTROL_MENU) ); checkkey = ID_Menu; if (SET_MENU(advancedSettingsMenu, MSG_ADVANCED_SETTINGS, items)) { @@ -3287,16 +3359,12 @@ void drawAdvancedSettingsMenu() { #if ENABLED(EEPROM_SETTINGS) MENU_ITEM(ICON_WriteEEPROM, MSG_STORE_EEPROM, onDrawMenuItem, writeEEPROM); #endif - #if HAS_MESH - MENU_ITEM(ICON_Mesh, MSG_MESH_LEVELING, onDrawSubMenu, drawMeshSetMenu); - #endif #if HAS_BED_PROBE MENU_ITEM(ICON_Probe, MSG_ZPROBE_SETTINGS, onDrawSubMenu, drawProbeSetMenu); #endif #if HAS_HOME_OFFSET MENU_ITEM(ICON_HomeOffset, MSG_SET_HOME_OFFSETS, onDrawSubMenu, drawHomeOffsetMenu); #endif - MENU_ITEM(ICON_FilSet, MSG_FILAMENT_SET, onDrawSubMenu, drawFilSetMenu); #if ENABLED(PIDTEMP) && ANY(PID_AUTOTUNE_MENU, PID_EDIT_MENU) MENU_ITEM_F(ICON_PIDNozzle, STR_HOTEND_PID " Settings", onDrawSubMenu, drawHotendPIDMenu); #endif @@ -3306,19 +3374,10 @@ void drawAdvancedSettingsMenu() { #if ENABLED(PIDTEMPBED) && ANY(PID_AUTOTUNE_MENU, PID_EDIT_MENU) MENU_ITEM_F(ICON_PIDBed, STR_BED_PID " Settings", onDrawSubMenu, drawBedPIDMenu); #endif - #if HAS_TRINAMIC_CONFIG - MENU_ITEM(ICON_TMCSet, MSG_TMC_DRIVERS, onDrawSubMenu, drawTrinamicConfigMenu); - #endif - #if HAS_ESDIAG - MENU_ITEM_F(ICON_esDiag, "End-stops diag.", onDrawSubMenu, drawEndStopDiag); - #endif #if ENABLED(PRINTCOUNTER) MENU_ITEM(ICON_PrintStats, MSG_INFO_STATS_MENU, onDrawSubMenu, gotoPrintStats); MENU_ITEM(ICON_PrintStatsReset, MSG_INFO_PRINT_COUNT_RESET, onDrawSubMenu, printStatsReset); #endif - #if HAS_LOCKSCREEN - MENU_ITEM(ICON_Lock, MSG_LOCKSCREEN, onDrawMenuItem, dwinLockScreen); - #endif #if ENABLED(EDITABLE_DISPLAY_TIMEOUT) EDIT_ITEM(ICON_RemainTime, MSG_SCREEN_TIMEOUT, onDrawPIntMenu, setTimer, &ui.backlight_timeout_minutes); #endif @@ -3342,8 +3401,17 @@ void drawAdvancedSettingsMenu() { EDIT_ITEM(ICON_Brightness, MSG_BRIGHTNESS, onDrawPInt8Menu, setBrightness, &ui.brightness); MENU_ITEM(ICON_Box, MSG_BRIGHTNESS_OFF, onDrawMenuItem, turnOffBacklight); #endif - #if HAS_CUSTOM_COLORS - MENU_ITEM(ICON_Scolor, MSG_COLORS_SELECT, onDrawSubMenu, drawSelectColorsMenu); + #if ENABLED(CASE_LIGHT_MENU) + #if CASELIGHT_USES_BRIGHTNESS + enableLiveCaseLightBrightness = true; // Allow live update of brightness in control menu + MENU_ITEM(ICON_CaseLight, MSG_CASE_LIGHT, onDrawSubMenu, drawCaseLightMenu); + #else + EDIT_ITEM(ICON_CaseLight, MSG_CASE_LIGHT, onDrawChkbMenu, setCaseLight, &caselight.on); + #endif + #endif + #if ENABLED(LED_CONTROL_MENU) + enableLiveLedColor = true; // Allow live update of color in control menu + MENU_ITEM(ICON_LedControl, MSG_LED_CONTROL, onDrawSubMenu, drawLedControlMenu); #endif } ui.reset_status(true); @@ -3400,8 +3468,9 @@ void drawMoveMenu() { void drawProbeSetMenu() { constexpr uint8_t items = (1 - + COUNT_ENABLED(HAS_X_AXIS, HAS_Y_AXIS, HAS_Z_AXIS, Z_MIN_PROBE_REPEATABILITY_TEST) + + COUNT_ENABLED(HAS_X_AXIS, HAS_Y_AXIS, HAS_Z_AXIS, BD_SENSOR, PROUI_ITEM_ZFR, Z_MIN_PROBE_REPEATABILITY_TEST) + TERN0(BLTOUCH, 3 + ENABLED(HAS_BLTOUCH_HS_MODE)) + + ENABLED(Z_MIN_PROBE_REPEATABILITY_TEST) ); checkkey = ID_Menu; if (SET_MENU(probeSettingsMenu, MSG_ZPROBE_SETTINGS, items)) { @@ -3415,6 +3484,12 @@ void drawMoveMenu() { #if HAS_Z_AXIS EDIT_ITEM(ICON_ProbeOffsetZ, MSG_ZPROBE_ZOFFSET, onDrawPFloat2Menu, setProbeOffsetZ, &probe.offset.z); #endif + #if DISABLED(BD_SENSOR) + EDIT_ITEM(ICON_Cancel, MSG_ZPROBE_MULTIPLE, onDrawPInt8Menu, setProbeMultiple, &hmiData.multiple_probing); + #endif + #if ENABLED(PROUI_ITEM_ZFR) + EDIT_ITEM(ICON_ProbeZSpeed, MSG_Z_FEED_RATE, onDrawPIntMenu, setProbeZSpeed, &motion.z_probe_slow_mm_s); + #endif #if ENABLED(BLTOUCH) MENU_ITEM(ICON_ProbeStow, MSG_MANUAL_STOW, onDrawMenuItem, probeStow); MENU_ITEM(ICON_ProbeDeploy, MSG_MANUAL_DEPLOY, onDrawMenuItem, probeDeploy); @@ -3432,40 +3507,12 @@ void drawMoveMenu() { #endif // HAS_BED_PROBE -void drawFilSetMenu() { - constexpr uint8_t items = (1 - + COUNT_ENABLED(HAS_FILAMENT_SENSOR, HAS_FILAMENT_RUNOUT_DISTANCE, PREVENT_COLD_EXTRUSION, FWRETRACT) - + TERN0(CONFIGURE_FILAMENT_CHANGE, 2) - ); - checkkey = ID_Menu; - if (SET_MENU(filSetMenu, MSG_FILAMENT_SET, items)) { - BACK_ITEM(drawAdvancedSettingsMenu); - #if HAS_FILAMENT_SENSOR - EDIT_ITEM(ICON_Runout, MSG_RUNOUT_SENSOR, onDrawChkbMenu, setRunoutEnable, &runout.enabled); - #endif - #if HAS_FILAMENT_RUNOUT_DISTANCE - EDIT_ITEM(ICON_Runout, MSG_RUNOUT_DISTANCE_MM, onDrawPFloatMenu, setRunoutDistance, &runout.runout_distance()); - #endif - #if ENABLED(PREVENT_COLD_EXTRUSION) - EDIT_ITEM(ICON_ExtrudeMinT, MSG_EXTRUDER_MIN_TEMP, onDrawPIntMenu, setExtMinT, &hmiData.extMinT); - #endif - #if ENABLED(CONFIGURE_FILAMENT_CHANGE) - EDIT_ITEM(ICON_FilLoad, MSG_FILAMENT_LOAD, onDrawPFloatMenu, setFilLoad, &fc_settings[0].load_length); - EDIT_ITEM(ICON_FilUnload, MSG_FILAMENT_UNLOAD, onDrawPFloatMenu, setFilUnload, &fc_settings[0].unload_length); - #endif - #if ENABLED(FWRETRACT) - MENU_ITEM(ICON_FWRetract, MSG_FWRETRACT, onDrawSubMenu, drawFWRetractMenu); - #endif - } - updateMenu(filSetMenu); -} - #if ALL(CASE_LIGHT_MENU, CASELIGHT_USES_BRIGHTNESS) void drawCaseLightMenu() { checkkey = ID_Menu; if (SET_MENU(caseLightMenu, MSG_CASE_LIGHT, 3)) { - BACK_ITEM(drawControlMenu); + BACK_ITEM(drawAdvancedSettingsMenu); EDIT_ITEM(ICON_CaseLight, MSG_CASE_LIGHT, onDrawChkbMenu, setCaseLight, &caselight.on); EDIT_ITEM(ICON_Brightness, MSG_CASE_LIGHT_BRIGHTNESS, onDrawPInt8Menu, setCaseLightBrightness, &caselight.brightness); } @@ -3479,11 +3526,11 @@ void drawFilSetMenu() { void drawLedControlMenu() { constexpr uint8_t items = (1 + !ALL(CASE_LIGHT_MENU, CASE_LIGHT_USE_NEOPIXEL) - + ENABLED(HAS_COLOR_LEDS) * TERN(LED_COLOR_PRESETS, 8, 3 + ENABLED(HAS_WHITE_LED)), + + TERN0(HAS_COLOR_LEDS, TERN(LED_COLOR_PRESETS, 8, 3 + ENABLED(HAS_WHITE_LED))), ); checkkey = ID_Menu; if (SET_MENU(ledControlMenu, MSG_LED_CONTROL, items)) { - BACK_ITEM((currentMenu == tuneMenu) ? drawTuneMenu : drawControlMenu); + BACK_ITEM((currentMenu == tuneMenu) ? drawTuneMenu : drawAdvancedSettingsMenu); #if !ALL(CASE_LIGHT_MENU, CASE_LIGHT_USE_NEOPIXEL) EDIT_ITEM(ICON_LedControl, MSG_LIGHTS, onDrawChkbMenu, setLedStatus, &leds.lights_on); #endif @@ -3513,11 +3560,13 @@ void drawFilSetMenu() { #endif // LED_CONTROL_MENU void drawTuneMenu() { - constexpr uint8_t items = (2 - + COUNT_ENABLED(HAS_HOTEND, HAS_HEATED_BED, HAS_FAN) - + ALL(HAS_ZOFFSET_ITEM, BABYSTEPPING) + constexpr uint8_t items = (1 + + COUNT_ENABLED(HAS_FEEDRATE_EDIT, HAS_FLOW_EDIT, HAS_HOTEND, HAS_HEATED_BED, HAS_FAN) + + (ALL(HAS_ZOFFSET_ITEM, HAS_BED_PROBE, BABYSTEP_ZPROBE_OFFSET, BABYSTEPPING) || ALL(HAS_ZOFFSET_ITEM, MESH_BED_LEVELING, BABYSTEPPING)) + 1 - + COUNT_ENABLED(ADVANCED_PAUSE_FEATURE, HAS_FILAMENT_SENSOR, PROUI_ITEM_PLR, FWRETRACT, PROUI_ITEM_JD, PROUI_ITEM_ADVK, HAS_LOCKSCREEN) + + COUNT_ENABLED(ADVANCED_PAUSE_FEATURE, HAS_FILAMENT_SENSOR, PROUI_ITEM_PLR, FWRETRACT, PROUI_ITEM_JD) + + TERN0(PROUI_ITEM_ADVK, 1 + ENABLED(SMOOTH_LIN_ADVANCE)) + + ENABLED(HAS_LOCKSCREEN) + TERN0(HAS_LCD_BRIGHTNESS, 2) + ENABLED(EDITABLE_DISPLAY_TIMEOUT) + 2 * ALL(PROUI_TUNING_GRAPH, PROUI_ITEM_PLOT) @@ -3529,8 +3578,12 @@ void drawTuneMenu() { checkkey = ID_Menu; if (SET_MENU_R(tuneMenu, selrect({73, 2, 28, 12}), MSG_TUNE, items)) { BACK_ITEM(gotoPrintProcess); - EDIT_ITEM(ICON_Speed, MSG_SPEED, onDrawSpeedItem, setSpeed, &motion.feedrate_percentage); - EDIT_ITEM(ICON_Flow, MSG_FLOW, onDrawPIntMenu, setFlow, &planner.flow_percentage[0]); + #if HAS_FEEDRATE_EDIT + EDIT_ITEM(ICON_Speed, MSG_SPEED, onDrawSpeedItem, setSpeed, &motion.feedrate_percentage); + #endif + #if HAS_FLOW_EDIT + EDIT_ITEM(ICON_Flow, MSG_FLOW, onDrawPIntMenu, setFlow, &planner.flow_percentage[0]); + #endif #if HAS_HOTEND hotendTargetItem = EDIT_ITEM(ICON_HotendTemp, MSG_UBL_SET_TEMP_HOTEND, onDrawHotendTemp, setHotendTemp, &thermalManager.temp_hotend[0].target); #endif @@ -3675,9 +3728,9 @@ void drawTuneMenu() { checkkey = ID_Menu; if (SET_MENU(trinamicConfigMenu, MSG_TMC_DRIVERS, items)) { BACK_ITEM(drawAdvancedSettingsMenu); - TERN_(X_IS_TRINAMIC, EDIT_ITEM(ICON_TMCXSet, MSG_TMC_ACURRENT, onDrawPIntMenu, setXTMCCurrent, &stepperX.val_mA)); - TERN_(Y_IS_TRINAMIC, EDIT_ITEM(ICON_TMCYSet, MSG_TMC_BCURRENT, onDrawPIntMenu, setYTMCCurrent, &stepperY.val_mA)); - TERN_(Z_IS_TRINAMIC, EDIT_ITEM(ICON_TMCZSet, MSG_TMC_CCURRENT, onDrawPIntMenu, setZTMCCurrent, &stepperZ.val_mA)); + TERN_(X_IS_TRINAMIC, EDIT_ITEM(ICON_TMCXSet, MSG_TMC_ACURRENT, onDrawPIntMenu, setXTMCCurrent, &stepperX.val_mA)); + TERN_(Y_IS_TRINAMIC, EDIT_ITEM(ICON_TMCYSet, MSG_TMC_BCURRENT, onDrawPIntMenu, setYTMCCurrent, &stepperY.val_mA)); + TERN_(Z_IS_TRINAMIC, EDIT_ITEM(ICON_TMCZSet, MSG_TMC_CCURRENT, onDrawPIntMenu, setZTMCCurrent, &stepperZ.val_mA)); TERN_(E0_IS_TRINAMIC, EDIT_ITEM(ICON_TMCESet, MSG_TMC_ECURRENT, onDrawPIntMenu, setETMCCurrent, &stepperE0.val_mA)); } updateMenu(trinamicConfigMenu); @@ -3692,8 +3745,17 @@ void drawMotionMenu() { checkkey = ID_Menu; if (SET_MENU_R(motionMenu, selrect({1, 16, 28, 13}), MSG_MOTION, items)) { BACK_ITEM(drawControlMenu); + #if HAS_FEEDRATE_EDIT + EDIT_ITEM(ICON_Speed, MSG_SPEED, onDrawPIntMenu, setSpeed, &motion.feedrate_percentage); + #endif + #if HAS_FLOW_EDIT + EDIT_ITEM(ICON_Flow, MSG_FLOW, onDrawPIntMenu, setFlow, &planner.flow_percentage[0]); + #endif MENU_ITEM(ICON_MaxSpeed, MSG_SPEED, onDrawSpeed, drawMaxSpeedMenu); MENU_ITEM(ICON_MaxAccelerated, MSG_ACCELERATION, onDrawAcc, drawMaxAccelMenu); + #if ENABLED(EDITABLE_STEPS_PER_UNIT) + MENU_ITEM(ICON_Step, MSG_STEPS_PER_MM, onDrawSteps, drawStepsMenu); + #endif #if ENABLED(CLASSIC_JERK) MENU_ITEM(ICON_MaxJerk, MSG_JERK, onDrawJerk, drawMaxJerkMenu); #elif HAS_JUNCTION_DEVIATION @@ -3721,31 +3783,60 @@ void drawMotionMenu() { #if ENABLED(ADAPTIVE_STEP_SMOOTHING_TOGGLE) EDIT_ITEM(ICON_UBLActive, MSG_STEP_SMOOTHING, onDrawChkbMenu, toggleAdaptiveStepSmoothing, &stepper.adaptive_step_smoothing_enabled); #endif - EDIT_ITEM(ICON_Speed, MSG_SPEED, onDrawSpeedItem, setSpeed, &motion.feedrate_percentage); - EDIT_ITEM(ICON_Flow, MSG_FLOW, onDrawPIntMenu, setFlow, &planner.flow_percentage[0]); + #if HAS_TRINAMIC_CONFIG + MENU_ITEM(ICON_TMCSet, MSG_TMC_DRIVERS, onDrawSubMenu, drawTrinamicConfigMenu); + #endif } updateMenu(motionMenu); } -#if ALL(ADVANCED_PAUSE_FEATURE, HAS_PREHEAT) - +#if HAS_PREHEAT void drawPreheatHotendMenu() { checkkey = ID_Menu; if (SET_MENU(preheatHotendMenu, MSG_PREHEAT_HOTEND, 1 + PREHEAT_COUNT)) { - BACK_ITEM(drawFilamentManMenu); - #define _ITEM_PREHEAT_HE(N) MENU_ITEM(ICON_Preheat##N, MSG_PREHEAT_##N, onDrawMenuItem, DoPreheatHotend##N); - REPEAT_1(PREHEAT_COUNT, _ITEM_PREHEAT_HE) + BACK_ITEM(drawPrepareMenu); + #define _ITEM_PREHEAT(N) MENU_ITEM(ICON_Preheat##N, MSG_PREHEAT_##N, onDrawPreheat##N, DoPreheat##N); + REPEAT_1(PREHEAT_COUNT, _ITEM_PREHEAT) } updateMenu(preheatHotendMenu); } - #endif +void drawFilSetMenu() { + constexpr uint8_t items = (1 + + COUNT_ENABLED(HAS_FILAMENT_SENSOR, HAS_FILAMENT_RUNOUT_DISTANCE, PREVENT_COLD_EXTRUSION, FWRETRACT) + + TERN0(CONFIGURE_FILAMENT_CHANGE, 2) + ); + checkkey = ID_Menu; + if (SET_MENU(filSetMenu, MSG_FILAMENT_SET, items)) { + BACK_ITEM(drawAdvancedSettingsMenu); + #if HAS_FILAMENT_SENSOR + EDIT_ITEM(ICON_Runout, MSG_RUNOUT_SENSOR, onDrawChkbMenu, setRunoutEnable, &runout.enabled); + #endif + #if HAS_FILAMENT_RUNOUT_DISTANCE + EDIT_ITEM(ICON_Runout, MSG_RUNOUT_DISTANCE_MM, onDrawPFloatMenu, setRunoutDistance, &runout.runout_distance()); + #endif + #if ENABLED(PREVENT_COLD_EXTRUSION) + EDIT_ITEM(ICON_ExtrudeMinT, MSG_EXTRUDER_MIN_TEMP, onDrawPIntMenu, setExtMinT, &hmiData.extMinT); + #endif + #if ENABLED(CONFIGURE_FILAMENT_CHANGE) + EDIT_ITEM(ICON_FilLoad, MSG_FILAMENT_LOAD, onDrawPFloatMenu, setFilLoad, &fc_settings[0].load_length); + EDIT_ITEM(ICON_FilUnload, MSG_FILAMENT_UNLOAD, onDrawPFloatMenu, setFilUnload, &fc_settings[0].unload_length); + #endif + #if ENABLED(FWRETRACT) + MENU_ITEM(ICON_FWRetract, MSG_FWRETRACT, onDrawSubMenu, drawFWRetractMenu); + #endif + } + updateMenu(filSetMenu); +} + void drawFilamentManMenu() { constexpr uint8_t items = (1 + ENABLED(NOZZLE_PARK_FEATURE) + + 1 + TERN0(ADVANCED_PAUSE_FEATURE, 1 + ENABLED(HAS_PREHEAT)) + TERN0(FILAMENT_LOAD_UNLOAD_GCODES, 2) + + ENABLED(FWRETRACT) ); checkkey = ID_Menu; if (SET_MENU(filamentMenu, MSG_FILAMENT_MAN, items)) { @@ -3753,15 +3844,16 @@ void drawFilamentManMenu() { #if ENABLED(NOZZLE_PARK_FEATURE) MENU_ITEM(ICON_Park, MSG_FILAMENT_PARK_ENABLED, onDrawMenuItem, parkHead); #endif + MENU_ITEM(ICON_FilSet, MSG_FILAMENT_SET, onDrawSubMenu, drawFilSetMenu); #if ENABLED(ADVANCED_PAUSE_FEATURE) - #if HAS_PREHEAT - MENU_ITEM(ICON_SetEndTemp, MSG_PREHEAT_HOTEND, onDrawSubMenu, drawPreheatHotendMenu); - #endif MENU_ITEM(ICON_FilMan, MSG_FILAMENTCHANGE, onDrawMenuItem, changeFilament); #endif #if ENABLED(FILAMENT_LOAD_UNLOAD_GCODES) - MENU_ITEM(ICON_FilUnload, MSG_FILAMENTUNLOAD, onDrawMenuItem, unloadFilament); MENU_ITEM(ICON_FilLoad, MSG_FILAMENTLOAD, onDrawMenuItem, loadFilament); + MENU_ITEM(ICON_FilUnload, MSG_FILAMENTUNLOAD, onDrawMenuItem, unloadFilament); + #endif + #if ENABLED(FWRETRACT) + MENU_ITEM(ICON_FWRetract, MSG_FWRETRACT, onDrawSubMenu, drawFWRetractMenu); #endif } updateMenu(filamentMenu); @@ -3823,6 +3915,9 @@ void drawFilamentManMenu() { void drawTemperatureMenu() { constexpr uint8_t items = (1 + COUNT_ENABLED(HAS_HOTEND, HAS_HEATED_BED, HAS_FAN) + + ((ENABLED(PIDTEMP) && ANY(PID_AUTOTUNE_MENU, PID_EDIT_MENU)) || (ENABLED(MPCTEMP) && ANY(MPC_EDIT_MENU, MPC_AUTOTUNE_MENU))) + + (ENABLED(PIDTEMPBED) && ANY(PID_AUTOTUNE_MENU, PID_EDIT_MENU)) + + (ENABLED(PIDTEMPCHAMBER) && ANY(PID_AUTOTUNE_MENU, PID_EDIT_MENU)) + PREHEAT_COUNT ); checkkey = ID_Menu; @@ -3837,6 +3932,17 @@ void drawTemperatureMenu() { #if HAS_FAN fanSpeedItem = EDIT_ITEM(ICON_FanSpeed, MSG_FAN_SPEED, onDrawFanSpeed, setFanSpeed, &thermalManager.fan_speed[0]); #endif + #if ENABLED(PIDTEMP) && ANY(PID_AUTOTUNE_MENU, PID_EDIT_MENU) + MENU_ITEM_F(ICON_PIDNozzle, STR_HOTEND_PID " Settings", onDrawSubMenu, drawHotendPIDMenu); + #elif ENABLED(MPCTEMP) && ANY(MPC_EDIT_MENU, MPC_AUTOTUNE_MENU) + MENU_ITEM_F(ICON_MPCNozzle, "MPC Settings", onDrawSubMenu, drawHotendMPCMenu); + #endif + #if ENABLED(PIDTEMPBED) && ANY(PID_AUTOTUNE_MENU, PID_EDIT_MENU) + MENU_ITEM_F(ICON_PIDBed, STR_BED_PID " Settings", onDrawSubMenu, drawBedPIDMenu); + #endif + #if ENABLED(PIDTEMPCHAMBER) && ANY(PID_AUTOTUNE_MENU, PID_EDIT_MENU) + MENU_ITEM_F(ICON_PIDBed, STR_CHAMBER_PID " Settings", onDrawSubMenu, drawChamberPIDMenu); + #endif #if HAS_PREHEAT #define _ITEM_SETPREHEAT(N) MENU_ITEM(ICON_SetPreheat##N, MSG_PREHEAT_## N ##_SETTINGS, onDrawSubMenu, drawPreheat## N ##Menu); REPEAT_1(PREHEAT_COUNT, _ITEM_SETPREHEAT) @@ -4004,7 +4110,7 @@ void drawMaxAccelMenu() { void drawSelectColorsMenu() { checkkey = ID_Menu; if (SET_MENU(selectColorMenu, MSG_COLORS_SELECT, 20)) { - BACK_ITEM(drawAdvancedSettingsMenu); + BACK_ITEM(drawControlMenu); MENU_ITEM(ICON_StockConfiguration, MSG_RESTORE_DEFAULTS, onDrawMenuItem, restoreDefaultColors); EDIT_ITEM_F(0, "Screen Background", onDrawSelColorItem, selColor, &hmiData.colorBackground); EDIT_ITEM_F(0, "Cursor", onDrawSelColorItem, selColor, &hmiData.colorCursor); @@ -4047,7 +4153,7 @@ void drawMaxAccelMenu() { // Nozzle and Bed PID/MPC //============================================================================= -#if ANY(MPC_EDIT_MENU, MPC_AUTOTUNE_MENU) +#if ENABLED(MPCTEMP) && ANY(MPC_EDIT_MENU, MPC_AUTOTUNE_MENU) #if ENABLED(MPC_EDIT_MENU) void setHeaterPower() { setPFloatOnClick(1, 200, 1); } @@ -4070,7 +4176,7 @@ void drawMaxAccelMenu() { checkkey = ID_Menu; if (SET_MENU_F(hotendMPCMenu, "MPC Settings", items)) { MPC_t &mpc = thermalManager.temp_hotend[0].mpc; - BACK_ITEM(drawAdvancedSettingsMenu); + BACK_ITEM(drawTemperatureMenu); #if ENABLED(MPC_AUTOTUNE_MENU) MENU_ITEM(ICON_MPCNozzle, MSG_MPC_AUTOTUNE, onDrawMenuItem, []{ thermalManager.MPC_autotune(motion.extruder, Temperature::MPCTuningType::AUTO); }); #endif @@ -4305,128 +4411,104 @@ void drawMaxAccelMenu() { // Mesh Bed Leveling //============================================================================= -#if HAS_MESH - - void applyMeshFadeHeight() { set_z_fade_height(planner.z_fade_height); } - void setMeshFadeHeight() { setPFloatOnClick(0, 100, 1, applyMeshFadeHeight); } - - void setMeshActive() { - set_bed_leveling_enabled(!planner.leveling_active); - drawCheckboxLine(currentMenu->line(), planner.leveling_active); - dwinUpdateLCD(); - } - - #if ENABLED(PREHEAT_BEFORE_LEVELING) - void setBedLevT() { setPIntOnClick(MIN_BEDTEMP, MAX_BEDTEMP); } - #endif - - #if ENABLED(PROUI_MESH_EDIT) - void liveEditMesh() { ((MenuItemPtr*)editZValueItem)->value = &bedlevel.z_values[hmiValue.select ? bedLevelTools.mesh_x : menuData.value][hmiValue.select ? menuData.value : bedLevelTools.mesh_y]; editZValueItem->redraw(); } - void applyEditMeshX() { bedLevelTools.mesh_x = menuData.value; } - void applyEditMeshY() { bedLevelTools.mesh_y = menuData.value; } - void resetMesh() { bedLevelTools.meshReset(); LCD_MESSAGE(MSG_MESH_RESET); } - void zeroPoint() { bedLevelTools.manualValueUpdate(bedLevelTools.mesh_x, bedLevelTools.mesh_y, true); editZValueItem->redraw(); LCD_MESSAGE(MSG_ZERO_MESH_POINT); } - void setEditMeshX() { hmiValue.select = 0; setIntOnClick(0, GRID_MAX_POINTS_X - 1, bedLevelTools.mesh_x, applyEditMeshX, liveEditMesh); } - void setEditMeshY() { hmiValue.select = 1; setIntOnClick(0, GRID_MAX_POINTS_Y - 1, bedLevelTools.mesh_y, applyEditMeshY, liveEditMesh); } - void setEditZValue() { setPFloatOnClick(Z_OFFSET_MIN, Z_OFFSET_MAX, 3); } - #endif - -#endif // HAS_MESH - -#if ENABLED(AUTO_BED_LEVELING_UBL) - - void applyUBLSlot() { bedlevel.storage_slot = menuData.value; } - void setUBLSlot() { setIntOnClick(0, settings.calc_num_meshes() - 1, bedlevel.storage_slot, applyUBLSlot); } - void onDrawUBLSlot(MenuItem* menuitem, int8_t line) { - NOLESS(bedlevel.storage_slot, 0); - onDrawIntMenu(menuitem, line, bedlevel.storage_slot); - } - - void applyUBLTiltGrid() { bedLevelTools.tilt_grid = menuData.value; } - void setUBLTiltGrid() { setIntOnClick(1, 3, bedLevelTools.tilt_grid, applyUBLTiltGrid); } - - void ublMeshTilt() { - NOLESS(bedlevel.storage_slot, 0); - if (bedLevelTools.tilt_grid > 1) - gcode.process_subcommands_now(TS(F("G29J"), bedLevelTools.tilt_grid)); - else - gcode.process_subcommands_now(F("G29J")); - LCD_MESSAGE(MSG_UBL_MESH_TILTED); - } - - void ublSmartFillMesh() { - for (uint8_t x = 0; x < GRID_MAX_POINTS_Y; ++x) bedlevel.smart_fill_mesh(); - LCD_MESSAGE(MSG_UBL_MESH_FILLED); - } - - void ublMeshSave() { - NOLESS(bedlevel.storage_slot, 0); - settings.store_mesh(bedlevel.storage_slot); - ui.status_printf(0, GET_TEXT_F(MSG_MESH_SAVED), bedlevel.storage_slot); - DONE_BUZZ(true); - } - - void ublMeshLoad() { - NOLESS(bedlevel.storage_slot, 0); - settings.load_mesh(bedlevel.storage_slot); - } - -#endif // AUTO_BED_LEVELING_UBL - #if HAS_MESH void drawMeshSetMenu() { constexpr uint8_t items = (1 + + ENABLED(HAS_PROUI_MESH_EDIT) + ENABLED(PREHEAT_BEFORE_LEVELING) + 2 - + ENABLED(HAS_BED_PROBE) - + TERN0(AUTO_BED_LEVELING_UBL, 6) - + TERN0(PROUI_MESH_EDIT, 2) - + 1 - + ENABLED(USE_GRID_MESHVIEWER) + + ENABLED(AUTO_BED_LEVELING_UBL) ); checkkey = ID_Menu; if (SET_MENU(meshMenu, MSG_MESH_LEVELING, items)) { - BACK_ITEM(drawAdvancedSettingsMenu); + BACK_ITEM(drawLevelMenu); + #if HAS_PROUI_MESH_EDIT + MENU_ITEM(ICON_ProbeMargin, MSG_MESH_INSET, onDrawSubMenu, drawMeshInsetMenu); + #endif #if ENABLED(PREHEAT_BEFORE_LEVELING) EDIT_ITEM(ICON_Temperature, MSG_UBL_SET_TEMP_BED, onDrawPIntMenu, setBedLevT, &hmiData.bedLevT); #endif EDIT_ITEM(ICON_SetZOffset, MSG_Z_FADE_HEIGHT, onDrawPFloatMenu, setMeshFadeHeight, &planner.z_fade_height); EDIT_ITEM(ICON_UBLActive, MSG_ACTIVATE_MESH, onDrawChkbMenu, setMeshActive, &planner.leveling_active); - #if HAS_BED_PROBE - MENU_ITEM(ICON_Level, MSG_AUTO_MESH, onDrawMenuItem, autoLevel); - #endif #if ENABLED(AUTO_BED_LEVELING_UBL) - EDIT_ITEM(ICON_UBLSlot, MSG_UBL_STORAGE_SLOT, onDrawUBLSlot, setUBLSlot, &bedlevel.storage_slot); - MENU_ITEM(ICON_UBLMeshSave, MSG_UBL_SAVE_MESH, onDrawMenuItem, ublMeshSave); - MENU_ITEM(ICON_UBLMeshLoad, MSG_UBL_LOAD_MESH, onDrawMenuItem, ublMeshLoad); EDIT_ITEM(ICON_UBLTiltGrid, MSG_UBL_TILTING_GRID, onDrawPInt8Menu, setUBLTiltGrid, &bedLevelTools.tilt_grid); - MENU_ITEM(ICON_UBLTiltGrid, MSG_UBL_TILT_MESH, onDrawMenuItem, ublMeshTilt); - MENU_ITEM(ICON_UBLSmartFill, MSG_UBL_SMART_FILLIN, onDrawMenuItem, ublSmartFillMesh); - #endif - #if ENABLED(PROUI_MESH_EDIT) - MENU_ITEM(ICON_MeshReset, MSG_MESH_RESET, onDrawMenuItem, resetMesh); - MENU_ITEM(ICON_MeshEdit, MSG_EDIT_MESH, onDrawSubMenu, drawEditMeshMenu); - #endif - MENU_ITEM(ICON_MeshViewer, MSG_MESH_VIEW, onDrawSubMenu, dwinMeshViewer); - #if USE_GRID_MESHVIEWER - MENU_ITEM(ICON_MeshViewer, MSG_MESH_VIEW_GRID, onDrawSubMenu, dwinMeshViewerGrid); #endif } updateMenu(meshMenu); } - #if ENABLED(PROUI_MESH_EDIT) + #if HAS_PROUI_MESH_EDIT + bool autoMovToMesh = false; + void setAutoMovToMesh() { toggleCheckboxLine(autoMovToMesh); } + + // Mesh Points + void liveEditMesh() { ((MenuItemPtr*)editZValueItem)->value = &bedlevel.z_values[hmiValue.select ? bedLevelTools.mesh_x : menuData.value][hmiValue.select ? menuData.value : bedLevelTools.mesh_y]; editZValueItem->redraw(); } + void applyEditMeshX() { bedLevelTools.mesh_x = menuData.value; if (autoMovToMesh) { bedLevelTools.moveToXY(); } } + void applyEditMeshY() { bedLevelTools.mesh_y = menuData.value; if (autoMovToMesh) { bedLevelTools.moveToXY(); } } + void setEditMeshX() { hmiValue.select = 0; setIntOnClick(0, GRID_MAX_POINTS_X - 1, bedLevelTools.mesh_x, applyEditMeshX, liveEditMesh); } + void setEditMeshY() { hmiValue.select = 1; setIntOnClick(0, GRID_MAX_POINTS_Y - 1, bedLevelTools.mesh_y, applyEditMeshY, liveEditMesh); } + void setEditZValue() { setPFloatOnClick(Z_OFFSET_MIN, Z_OFFSET_MAX, 3); } + void zeroPoint() { bedLevelTools.manualValueUpdate(bedLevelTools.mesh_x, bedLevelTools.mesh_y, true); editZValueItem->redraw(); LCD_MESSAGE(MSG_ZERO_MESH); } + void resetMesh() { bedLevelTools.meshReset(); LCD_MESSAGE(MSG_MESH_RESET); } + + // Mesh Inset + void resetMeshInset() { set_bed_leveling_enabled(false); OPTCODE(MESH_BED_LEVELING, bedlevel.initialize()) reset_bed_level(); } + void applyMeshInset() { resetMeshInset(); redrawItem(); } + void setXMeshInset() { setPFloatOnClick(0, X_BED_SIZE, UNITFDIGITS, applyMeshInset); } + void setYMeshInset() { setPFloatOnClick(0, Y_BED_SIZE, UNITFDIGITS, applyMeshInset); } + void maxMeshArea() { + mesh_min.set(0, 0); + mesh_max.set(X_BED_SIZE, Y_BED_SIZE); + resetMeshInset(); + redrawMenu(); + } + + void centerMeshArea() { + float max = (mesh_min.x + mesh_min.y) * 0.5f; + NOLESS(max, (X_BED_SIZE) - mesh_max.x); + NOLESS(max, mesh_min.y); + NOLESS(max, (Y_BED_SIZE) - mesh_min.y); + mesh_min.set(max, max); + mesh_max.set((X_BED_SIZE) - max, (Y_BED_SIZE) - max); + resetMeshInset(); + redrawMenu(); + } + + void drawMeshInsetMenu() { + checkkey = ID_Menu; + if (SET_MENU(meshInsetMenu, MSG_MESH_INSET, 7)) { + BACK_ITEM(drawMeshSetMenu); + EDIT_ITEM(ICON_Box, MSG_MESH_MIN_X, onDrawPFloatMenu, setXMeshInset, &mesh_min.x); + EDIT_ITEM(ICON_ProbeMargin, MSG_MESH_MAX_X, onDrawPFloatMenu, setXMeshInset, &mesh_max.x); + EDIT_ITEM(ICON_Box, MSG_MESH_MIN_Y, onDrawPFloatMenu, setYMeshInset, &mesh_min.y); + EDIT_ITEM(ICON_ProbeMargin, MSG_MESH_MAX_Y, onDrawPFloatMenu, setYMeshInset, &mesh_max.y); + MENU_ITEM(ICON_AxisC, MSG_MESH_AMAX, onDrawMenuItem, maxMeshArea); + MENU_ITEM(ICON_SetHome, MSG_MESH_CENTER, onDrawMenuItem, centerMeshArea); + } + updateMenu(meshInsetMenu); + LCD_MESSAGE_F("..Center Area sets mesh equidistant by greatest inset from edge."); + } + void drawEditMeshMenu() { - if (!leveling_is_valid()) { LCD_MESSAGE(MSG_UBL_MESH_INVALID); return; } + constexpr uint8_t items = (6 + ENABLED(HAS_BED_PROBE)); + if (!leveling_is_valid()) { + LCD_MESSAGE(MSG_UBL_MESH_INVALID); + dwinPopupConfirm(ICON_Leveling_1, GET_TEXT_F(MSG_NO_VALID_MESH), GET_TEXT_F(MSG_UBL_LOAD_MESH)); + return; + } set_bed_leveling_enabled(false); checkkey = ID_Menu; - if (SET_MENU(editMeshMenu, MSG_EDIT_MESH, 4)) { + if (SET_MENU(editMeshMenu, MSG_MESH_EDITOR, items)) { bedLevelTools.mesh_x = bedLevelTools.mesh_y = 0; - BACK_ITEM(drawMeshSetMenu); + BACK_ITEM(drawLevelMenu); + EDIT_ITEM(ICON_SetHome, MSG_PROBE_WIZARD_MOVING, onDrawChkbMenu, setAutoMovToMesh, &autoMovToMesh); EDIT_ITEM(ICON_MeshEditX, MSG_MESH_X, onDrawPInt8Menu, setEditMeshX, &bedLevelTools.mesh_x); EDIT_ITEM(ICON_MeshEditY, MSG_MESH_Y, onDrawPInt8Menu, setEditMeshY, &bedLevelTools.mesh_y); editZValueItem = EDIT_ITEM(ICON_MeshEditZ, MSG_MESH_EDIT_Z, onDrawPFloat2Menu, setEditZValue, &bedlevel.z_values[bedLevelTools.mesh_x][bedLevelTools.mesh_y]); + #if HAS_BED_PROBE + MENU_ITEM(ICON_Probe, MSG_PROBE_WIZARD_PROBING, onDrawMenuItem, bedLevelTools.probeXY); + #endif MENU_ITEM(ICON_SetZOffset, MSG_ZERO_MESH_POINT, onDrawMenuItem, zeroPoint); } updateMenu(editMeshMenu); @@ -4435,4 +4517,51 @@ void drawMaxAccelMenu() { #endif // HAS_MESH +void drawLevelMenu() { + constexpr uint8_t items = (1 + + ENABLED(EEPROM_SETTINGS) + + ENABLED(MESH_BED_LEVELING) + + TERN0(HAS_BED_PROBE, 2) + + ENABLED(HAS_HOME_OFFSET) + + TERN0(HAS_MESH, 2 + ENABLED(USE_GRID_MESHVIEWER) + TERN0(HAS_PROUI_MESH_EDIT, 2)) + + TERN0(AUTO_BED_LEVELING_UBL, 5) + ); + checkkey = ID_Menu; + if (SET_MENU(levelMenu, MSG_BED_LEVELING, items)) { + BACK_ITEM(gotoMainMenu); + #if ENABLED(EEPROM_SETTINGS) + MENU_ITEM(ICON_WriteEEPROM, MSG_STORE_EEPROM, onDrawMenuItem, writeEEPROM); + #endif + #if ENABLED(MESH_BED_LEVELING) + MENU_ITEM(ICON_ManualMesh, MSG_MANUAL_MESH, onDrawSubMenu, drawManualMeshMenu); + #elif HAS_BED_PROBE + MENU_ITEM(ICON_Mesh, MSG_AUTO_MESH, onDrawMenuItem, autoLevel); + MENU_ITEM(ICON_Probe, MSG_ZPROBE_SETTINGS, onDrawSubMenu, drawProbeSetMenu); + #endif + #if HAS_HOME_OFFSET + MENU_ITEM(ICON_HomeOffset, MSG_SET_HOME_OFFSETS, onDrawSubMenu, drawHomeOffsetMenu); + #endif + #if HAS_MESH + MENU_ITEM(ICON_MeshViewer, MSG_MESH_VIEW, onDrawSubMenu, dwinMeshViewer); + #if USE_GRID_MESHVIEWER + MENU_ITEM(ICON_MeshViewer, MSG_MESH_VIEW_GRID, onDrawSubMenu, dwinMeshViewerGrid); + #endif + MENU_ITEM(ICON_Mesh, MSG_MESH_SETTINGS, onDrawSubMenu, drawMeshSetMenu); + #if HAS_PROUI_MESH_EDIT + MENU_ITEM(ICON_MeshEdit, MSG_EDIT_MESH, onDrawSubMenu, drawEditMeshMenu); + MENU_ITEM(ICON_MeshReset, MSG_MESH_RESET, onDrawMenuItem, resetMesh); + #endif + #endif + #if ENABLED(AUTO_BED_LEVELING_UBL) + EDIT_ITEM(ICON_UBLSlot, MSG_UBL_STORAGE_SLOT, onDrawUBLSlot, setUBLSlot, &bedlevel.storage_slot); + MENU_ITEM(ICON_UBLMeshSave, MSG_UBL_SAVE_MESH, onDrawMenuItem, ublMeshSave); + MENU_ITEM(ICON_UBLMeshLoad, MSG_UBL_LOAD_MESH, onDrawMenuItem, ublMeshLoad); + MENU_ITEM(ICON_UBLTiltGrid, MSG_UBL_TILT_MESH, onDrawMenuItem, ublMeshTilt); + MENU_ITEM(ICON_UBLSmartFill, MSG_UBL_SMART_FILLIN, onDrawMenuItem, ublSmartFillMesh); + #endif + } + ui.reset_status(true); + updateMenu(levelMenu); +} + #endif // DWIN_LCD_PROUI diff --git a/Marlin/src/lcd/dwin/proui/dwin.h b/Marlin/src/lcd/dwin/proui/dwin.h index 12910a2537..67d19534ed 100644 --- a/Marlin/src/lcd/dwin/proui/dwin.h +++ b/Marlin/src/lcd/dwin/proui/dwin.h @@ -127,17 +127,26 @@ typedef struct { uint16_t colorCoordinate; // Temperatures - #if HAS_PID_HEATING + #if ANY(PIDTEMP, PIDTEMPBED, PIDTEMPCHAMBER) int16_t pidCycles = DEF_PIDCYCLES; - #if ENABLED(PIDTEMP) - celsius_t hotendPIDT = DEF_HOTENDPIDT; + #endif + #if ENABLED(PIDTEMP) + #ifndef PREHEAT_1_TEMP_HOTEND + #define PREHEAT_1_TEMP_HOTEND 195 #endif - #if ENABLED(PIDTEMPBED) - celsius_t bedPIDT = DEF_BEDPIDT; + celsius_t hotendPIDT = PREHEAT_1_TEMP_HOTEND; + #endif + #if ENABLED(PIDTEMPBED) + #ifndef PREHEAT_1_TEMP_BED + #define PREHEAT_1_TEMP_BED 60 #endif - #if ENABLED(PIDTEMPCHAMBER) - celsius_t chamberPIDT = DEF_CHAMBERPIDT; + celsius_t bedPIDT = PREHEAT_1_TEMP_BED; + #endif + #if ENABLED(PIDTEMPCHAMBER) + #ifndef PREHEAT_1_TEMP_CHAMBER + #define PREHEAT_1_TEMP_CHAMBER 0 #endif + celsius_t chamberPIDT = PREHEAT_1_TEMP_CHAMBER; #endif #if ENABLED(PREVENT_COLD_EXTRUSION) celsius_t extMinT = EXTRUDE_MINTEMP; @@ -145,6 +154,8 @@ typedef struct { #if ENABLED(PREHEAT_BEFORE_LEVELING) celsius_t bedLevT = LEVELING_BED_TEMP; #endif + + // Various Options #if ENABLED(BAUD_RATE_GCODE) bool baud115K = false; #endif @@ -156,7 +167,7 @@ typedef struct { #endif bool mediaAutoMount = ENABLED(HAS_SD_EXTENDER); #if ALL(INDIVIDUAL_AXIS_HOMING_SUBMENU, MESH_BED_LEVELING) - uint8_t zAfterHoming = DEF_Z_AFTER_HOMING; + uint8_t zAfterHoming = Z_AFTER_HOMING; #define Z_POST_CLEARANCE hmiData.zAfterHoming #endif #if ALL(LED_CONTROL_MENU, HAS_COLOR_LEDS) @@ -165,6 +176,9 @@ typedef struct { #if HAS_GCODE_PREVIEW bool enablePreview = true; #endif + #if HAS_BED_PROBE && DISABLED(BD_SENSOR) + uint8_t multiple_probing = MULTIPLE_PROBING; + #endif } hmi_data_t; extern hmi_data_t hmiData; @@ -202,6 +216,7 @@ typedef struct { bool pause_flag:1; // printing is paused bool select_flag:1; // Popup button selected bool home_flag:1; // homing in course + bool cancel_lev:1; // cancel abl } hmi_flag_t; extern hmi_flag_t hmiFlag; @@ -225,11 +240,16 @@ uint32_t getHash(char * str); void saveMesh(); #endif #endif +#if HAS_BED_PROBE + void autoLevel(); +#else + void homeZAndDisable(); +#endif void rebootPrinter(); void disableMotors(); -void autoLevel(); void autoHome(); #if HAS_PREHEAT + void drawPreheatHotendMenu(); #define _DOPREHEAT(N) void DoPreheat##N(); REPEAT_1(PREHEAT_COUNT, _DOPREHEAT) #endif @@ -259,9 +279,6 @@ void doCoolDown(); void ublMeshSave(); void ublMeshLoad(); #endif -#if DISABLED(HAS_BED_PROBE) - void homeZAndDisable(); -#endif // Other void gotoPrintProcess(); @@ -290,8 +307,10 @@ void dwinHomingDone(); #if HAS_MESH void dwinMeshUpdate(const int8_t cpos, const int8_t tpos, const float zval); #endif -void dwinLevelingStart(); -void dwinLevelingDone(); +#if HAS_LEVELING + void dwinLevelingStart(); + void dwinLevelingDone(); +#endif void dwinPrintStarted(); void dwinPrintPause(); void dwinPrintResume(); @@ -336,6 +355,7 @@ void drawPrintFileMenu(); void drawControlMenu(); void drawAdvancedSettingsMenu(); void drawPrepareMenu(); +void drawLevelMenu(); void drawMoveMenu(); void drawTrammingMenu(); #if HAS_HOME_OFFSET @@ -380,7 +400,8 @@ void drawMaxAccelMenu(); #endif #if HAS_MESH void drawMeshSetMenu(); - #if ENABLED(PROUI_MESH_EDIT) + #if HAS_PROUI_MESH_EDIT + void drawMeshInsetMenu(); void drawEditMeshMenu(); #endif #endif diff --git a/Marlin/src/lcd/dwin/proui/dwin_defines.h b/Marlin/src/lcd/dwin/proui/dwin_defines.h index 42645be0f4..86d1153233 100644 --- a/Marlin/src/lcd/dwin/proui/dwin_defines.h +++ b/Marlin/src/lcd/dwin/proui/dwin_defines.h @@ -30,23 +30,13 @@ */ #include "../../../inc/MarlinConfigPre.h" +#include +#include "../../../core/types.h" //#define TJC_DISPLAY // Enable for TJC display //#define DACAI_DISPLAY // Enable for DACAI display //#define TITLE_CENTERED // Center Menu Title Text -#if HAS_MESH - #define USE_GRID_MESHVIEWER 1 -#endif - -#if HAS_MESH - #define PROUI_MESH_EDIT // Add a menu to edit mesh points - #if ENABLED(PROUI_MESH_EDIT) - #define Z_OFFSET_MIN -3.0 // (mm) - #define Z_OFFSET_MAX 3.0 // (mm) - #endif -#endif - #if defined(__STM32F1__) || defined(STM32F1) #define DASH_REDRAW 1 #endif @@ -89,32 +79,18 @@ #define defCaseLightBrightness 255 #endif -#ifdef Z_AFTER_HOMING - #define DEF_Z_AFTER_HOMING Z_AFTER_HOMING -#else - #define DEF_Z_AFTER_HOMING 0 +#ifndef Z_AFTER_HOMING + #define Z_AFTER_HOMING 0 #endif -#ifdef PREHEAT_1_TEMP_HOTEND - #define DEF_HOTENDPIDT PREHEAT_1_TEMP_HOTEND -#else - #define DEF_HOTENDPIDT 195 -#endif -#ifdef PREHEAT_1_TEMP_BED - #define DEF_BEDPIDT PREHEAT_1_TEMP_BED -#else - #define DEF_BEDPIDT 60 -#endif -#ifdef PREHEAT_1_TEMP_CHAMBER - #define DEF_CHAMBERPIDT PREHEAT_1_TEMP_CHAMBER -#else - #define DEF_CHAMBERPIDT 0 -#endif #define DEF_PIDCYCLES 5 /** * ProUI internal feature flags */ +#if HAS_BED_PROBE + #define PROUI_ITEM_ZFR // Add a menu item to change Z_PROBE_FEEDRATE_SLOW - probe speed +#endif #if ALL(SDCARD_SORT_ALPHA, SDSORT_GCODE) #define PROUI_MEDIASORT // Enable option to sort G-code files #endif @@ -127,7 +103,7 @@ #if HAS_LIN_ADVANCE_K #define PROUI_ITEM_ADVK 1 // Tune > Linear Advance #endif -#if ANY(HAS_PID_HEATING, MPC_AUTOTUNE) && DISABLED(DISABLE_TUNING_GRAPH) +#if DISABLED(DISABLE_TUNING_GRAPH) #define PROUI_TUNING_GRAPH 1 #endif #if PROUI_TUNING_GRAPH @@ -138,3 +114,18 @@ #define HAS_ESDIAG 1 // View End-stop/Runout switch continuity #define HAS_LOCKSCREEN 1 // Simple lockscreen #define HAS_SD_EXTENDER 1 // Enable to support SD card extender cables +#define USE_GRID_MESHVIEWER 1 // Enable for two mesh graph types + +#if HAS_PROUI_MESH_EDIT + #define Z_OFFSET_MIN -3.0 // (mm) + #define Z_OFFSET_MAX 3.0 // (mm) + #ifndef MESH_INSET + #define MESH_INSET 10 + #endif + #define MIN_MESH_INSET 0 + #define MAX_MESH_INSET X_BED_SIZE +#endif + +#ifndef MULTIPLE_PROBING + #define MULTIPLE_PROBING 0 +#endif diff --git a/Marlin/src/lcd/dwin/proui/dwin_popup.cpp b/Marlin/src/lcd/dwin/proui/dwin_popup.cpp index f0ed1a6c07..5521082a10 100644 --- a/Marlin/src/lcd/dwin/proui/dwin_popup.cpp +++ b/Marlin/src/lcd/dwin/proui/dwin_popup.cpp @@ -32,7 +32,6 @@ #if ENABLED(DWIN_LCD_PROUI) -#include "dwin.h" #include "dwinui.h" #include "dwin_popup.h" diff --git a/Marlin/src/lcd/dwin/proui/dwin_popup.h b/Marlin/src/lcd/dwin/proui/dwin_popup.h index 9443e88a36..fa26402f26 100644 --- a/Marlin/src/lcd/dwin/proui/dwin_popup.h +++ b/Marlin/src/lcd/dwin/proui/dwin_popup.h @@ -29,7 +29,6 @@ * Date: 2022/02/28 */ -#include "dwinui.h" #include "dwin.h" typedef void (*popupDrawFunc_t)(); diff --git a/Marlin/src/lcd/dwin/proui/dwinui.cpp b/Marlin/src/lcd/dwin/proui/dwinui.cpp index 2d6dc67197..138e75a6b9 100644 --- a/Marlin/src/lcd/dwin/proui/dwinui.cpp +++ b/Marlin/src/lcd/dwin/proui/dwinui.cpp @@ -32,8 +32,8 @@ #if ENABLED(DWIN_LCD_PROUI) -#include "dwin_defines.h" #include "dwinui.h" +#include "dwin_defines.h" xy_int_t DWINUI::cursor = { 0 }; uint16_t DWINUI::penColor = COLOR_WHITE; @@ -237,59 +237,23 @@ void DWINUI::drawButton(uint8_t id, uint16_t x, uint16_t y) { // -------------------------- Extra -------------------------------// -// Draw a circle -// color: circle color -// x: the abscissa of the center of the circle -// y: ordinate of the center of the circle -// r: circle radius -void DWINUI::drawCircle(uint16_t color, uint16_t x, uint16_t y, uint8_t r) { - int a = 0, b = 0; - while (a <= b) { - b = SQRT(sq(r) - sq(a)); - if (a == 0) b--; - dwinDrawPoint(color, 1, 1, x + a, y + b); // Draw some sector 1 - dwinDrawPoint(color, 1, 1, x + b, y + a); // Draw some sector 2 - dwinDrawPoint(color, 1, 1, x + b, y - a); // Draw some sector 3 - dwinDrawPoint(color, 1, 1, x + a, y - b); // Draw some sector 4 - dwinDrawPoint(color, 1, 1, x - a, y - b); // Draw some sector 5 - dwinDrawPoint(color, 1, 1, x - b, y - a); // Draw some sector 6 - dwinDrawPoint(color, 1, 1, x - b, y + a); // Draw some sector 7 - dwinDrawPoint(color, 1, 1, x - a, y + b); // Draw some sector 8 - a++; - } -} - // Draw a circle filled with color // bcolor: fill color // x: the abscissa of the center of the circle // y: ordinate of the center of the circle // r: circle radius -void DWINUI::drawFillCircle(uint16_t bcolor, uint16_t x, uint16_t y, uint8_t r) { +void DWINUI::drawFillCircle(const uint16_t bcolor, const uint16_t x, const uint16_t y, const uint8_t r) { + const uint16_t r2 = sq(r); dwinDrawLine(bcolor, x - r, y, x + r, y); - uint16_t b = 1; - while (b <= r) { - uint16_t a = SQRT(sq(r) - sq(b)); + + const uint8_t step = TERN(TJC_DISPLAY, 2, 1); + for (uint16_t b = step; b <= r; b += step) { + const uint16_t a = SQRT(r2 - sq(b)); dwinDrawLine(bcolor, x - a, y + b, x + a, y + b); dwinDrawLine(bcolor, x - a, y - b, x + a, y - b); - b += TERN(TJC_DISPLAY, 2, 1); } } -// Color Interpolator -// val : Interpolator minv..maxv -// minv : Minimum value -// maxv : Maximum value -// color1 : Start color -// color2 : End color -uint16_t DWINUI::colorInt(int16_t val, int16_t minv, int16_t maxv, uint16_t color1, uint16_t color2) { - uint8_t B, G, R; - const float n = float(val - minv) / (maxv - minv + 1); - R = (1.0f - n) * GetRColor(color1) + n * GetRColor(color2); - G = (1.0f - n) * GetGColor(color1) + n * GetGColor(color2); - B = (1.0f - n) * GetBColor(color1) + n * GetBColor(color2); - return RGB(R, G, B); -} - // Color Interpolator through Red->Yellow->Green->Blue (Pro UI) // val : Interpolator minv..maxv // minv : Minimum value diff --git a/Marlin/src/lcd/dwin/proui/dwinui.h b/Marlin/src/lcd/dwin/proui/dwinui.h index 1c98704433..f98e85c642 100644 --- a/Marlin/src/lcd/dwin/proui/dwinui.h +++ b/Marlin/src/lcd/dwin/proui/dwinui.h @@ -57,7 +57,6 @@ #define ICON_HSMode ICON_MaxAccZ #define ICON_InputShaping ICON_MaxAccelerated #define ICON_JDmm ICON_MaxJerk -#define ICON_Level ICON_Mesh #define ICON_Lock ICON_Checkbox #define ICON_ManualMesh ICON_Mesh #define ICON_MaxPosX ICON_MoveX @@ -210,6 +209,7 @@ typedef struct { uint16_t x, y, w, h; } frame_rect_t; class Title { public: + const uint8_t meshfont = TERN(TJC_DISPLAY, font8x16, font6x12); char caption[32] = ""; uint8_t frameid = 0; rect_t frame = {0}; @@ -526,16 +526,6 @@ namespace DWINUI { dwinDrawBox(mode, color, frame.x, frame.y, frame.w, frame.h); } - // Draw a circle - // Color: circle color - // x: abscissa of the center of the circle - // y: ordinate of the center of the circle - // r: circle radius - void drawCircle(uint16_t color, uint16_t x,uint16_t y,uint8_t r); - inline void drawCircle(uint16_t color, uint8_t r) { - drawCircle(color, cursor.x, cursor.y, r); - } - // Draw a checkbox // Color: frame color // bColor: Background color @@ -546,14 +536,6 @@ namespace DWINUI { drawCheckbox(textColor, backColor, x, y, checked); } - // Color Interpolator - // val : Interpolator minv..maxv - // minv : Minimum value - // maxv : Maximum value - // color1 : Start color - // color2 : End color - uint16_t colorInt(int16_t val, int16_t minv, int16_t maxv, uint16_t color1, uint16_t color2); - // ------------------------- Buttons ------------------------------// void drawButton(uint16_t color, uint16_t bcolor, uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2, const char * const caption); @@ -572,8 +554,8 @@ namespace DWINUI { // x: abscissa of the center of the circle // y: ordinate of the center of the circle // r: circle radius - void drawFillCircle(uint16_t bcolor, uint16_t x,uint16_t y,uint8_t r); - inline void drawFillCircle(uint16_t bcolor, uint8_t r) { + void drawFillCircle(const uint16_t bcolor, const uint16_t x, const uint16_t y, const uint8_t r); + inline void drawFillCircle(const uint16_t bcolor, const uint8_t r) { drawFillCircle(bcolor, cursor.x, cursor.y, r); } diff --git a/Marlin/src/lcd/dwin/proui/endstop_diag.cpp b/Marlin/src/lcd/dwin/proui/endstop_diag.cpp index 83b084ab0d..07b60031ab 100644 --- a/Marlin/src/lcd/dwin/proui/endstop_diag.cpp +++ b/Marlin/src/lcd/dwin/proui/endstop_diag.cpp @@ -32,13 +32,12 @@ #if ENABLED(DWIN_LCD_PROUI) -#include "dwin_defines.h" +#include "dwin.h" #if HAS_ESDIAG #include "endstop_diag.h" #include "../../marlinui.h" -#include "dwin.h" #include "dwin_popup.h" #if HAS_FILAMENT_SENSOR diff --git a/Marlin/src/lcd/dwin/proui/gcode_preview.cpp b/Marlin/src/lcd/dwin/proui/gcode_preview.cpp index ddd73d72b5..5172610bb1 100644 --- a/Marlin/src/lcd/dwin/proui/gcode_preview.cpp +++ b/Marlin/src/lcd/dwin/proui/gcode_preview.cpp @@ -31,7 +31,7 @@ #if ENABLED(DWIN_LCD_PROUI) -#include "dwin_defines.h" +#include "dwin.h" #if HAS_GCODE_PREVIEW @@ -39,47 +39,36 @@ #include "../../marlinui.h" #include "../../../sd/cardreader.h" -#include "../../../MarlinCore.h" // for wait_for_user -#include "dwin.h" #include "dwin_popup.h" #include "base64.h" -#define THUMBWIDTH 230 -#define THUMBHEIGHT 180 - -Preview preview; - -typedef struct { - char name[13] = ""; // 8.3 + null - uint32_t thumbstart = 0; - int thumbsize = 0; - int thumbheight = 0, thumbwidth = 0; - float time = 0; - float filament = 0; - float layer = 0; - float width = 0, height = 0, length = 0; - - void setname(const char * const fn) { - const uint8_t len = _MIN(sizeof(name) - 1, strlen(fn)); - memcpy(name, fn, len); - name[len] = '\0'; - } - - void clear() { - name[0] = '\0'; - thumbstart = 0; - thumbsize = 0; - thumbheight = thumbwidth = 0; - time = 0; - filament = 0; - layer = 0; - height = width = length = 0; - } - -} fileprop_t; +#if ENABLED(TJC_DISPLAY) + #define THUMBWIDTH 180 + #define THUMBHEIGHT 180 +#else + #define THUMBWIDTH 200 + #define THUMBHEIGHT 200 +#endif fileprop_t fileprop; +void fileprop_t::setname(const char * const fn) { + const uint8_t len = _MIN(sizeof(name) - 1, strlen(fn)); + memcpy(name, fn, len); + name[len] = '\0'; +} + +void fileprop_t::clear() { + name[0] = '\0'; + thumbstart = 0; + thumbsize = 0; + thumbheight = thumbwidth = 0; + time = 0; + filament = 0; + layer = 0; + height = width = length = 0; +} + void getValue(const char * const buf, PGM_P const key, float &value) { if (value != 0.0f) return; @@ -189,11 +178,7 @@ bool Preview::hasPreview() { } void Preview::drawFromSD() { - if (!hasPreview()) { - hmiFlag.select_flag = 1; - marlin.user_resume(); - return; - } + hasPreview(); TString buf; dwinDrawRectangle(1, hmiData.colorBackground, 0, 0, DWIN_WIDTH, STATUS_Y - 1); @@ -213,10 +198,17 @@ void Preview::drawFromSD() { buf.set(F("Volume: "), p_float_t(fileprop.width, 1), 'x', p_float_t(fileprop.length, 1), 'x', p_float_t(fileprop.height, 1), F(" mm")); DWINUI::drawString(20, 70, &buf); } + if (!fileprop.thumbsize) { + const uint8_t xpos = ((DWIN_WIDTH) / 2) - 55, // 55 = iconW/2 + ypos = ((DWIN_HEIGHT) / 2) - 125; + DWINUI::drawIcon(ICON_Info_0, xpos, ypos); + buf.set(PSTR("No " STRINGIFY(THUMBWIDTH) "x" STRINGIFY(THUMBHEIGHT) " Thumbnail")); + DWINUI::drawCenteredString(false, (DWINUI::fontID * 3), DWINUI::textColor, DWINUI::backColor, 0, DWIN_WIDTH, (DWIN_HEIGHT / 2), &buf); + } DWINUI::drawButton(BTN_Print, 26, 290); DWINUI::drawButton(BTN_Cancel, 146, 290); if (fileprop.thumbsize) show(); - drawSelectHighlight(true, 290); + drawSelectHighlight(false, 290); dwinUpdateLCD(); } diff --git a/Marlin/src/lcd/dwin/proui/gcode_preview.h b/Marlin/src/lcd/dwin/proui/gcode_preview.h index 9146642447..4d8325678e 100644 --- a/Marlin/src/lcd/dwin/proui/gcode_preview.h +++ b/Marlin/src/lcd/dwin/proui/gcode_preview.h @@ -39,3 +39,19 @@ private: }; extern Preview preview; + +typedef struct { + char name[13] = ""; // 8.3 + null + uint32_t thumbstart; + int thumbsize, thumbheight, thumbwidth; + float time, + filament, + layer, + width, height, length; + + void setname(const char * const fn); + void clear(); + +} fileprop_t; + +extern fileprop_t fileprop; diff --git a/Marlin/src/lcd/dwin/proui/lockscreen.cpp b/Marlin/src/lcd/dwin/proui/lockscreen.cpp index fbba326152..ecfee98487 100644 --- a/Marlin/src/lcd/dwin/proui/lockscreen.cpp +++ b/Marlin/src/lcd/dwin/proui/lockscreen.cpp @@ -32,11 +32,10 @@ #if ENABLED(DWIN_LCD_PROUI) -#include "dwin_defines.h" +#include "dwin.h" #if HAS_LOCKSCREEN -#include "dwin.h" #include "lockscreen.h" LockScreen lockScreen; diff --git a/Marlin/src/lcd/dwin/proui/menus.cpp b/Marlin/src/lcd/dwin/proui/menus.cpp index a3d159ff8a..859914f035 100644 --- a/Marlin/src/lcd/dwin/proui/menus.cpp +++ b/Marlin/src/lcd/dwin/proui/menus.cpp @@ -157,7 +157,7 @@ void onDrawChkbMenu(MenuItem* menuitem, int8_t line) { onDrawChkbMenu(menuitem, line, val); } -void DrawItemEdit(const bool selected) { +void drawItemEdit(const bool selected) { const uint16_t bcolor = selected ? hmiData.colorSelected : hmiData.colorBackground; const uint8_t iNum = 4 - ((menuData.dp > 0) ? (menuData.dp - 1) : 0); switch (checkkey) { @@ -202,7 +202,7 @@ void setOnClick(uint8_t process, const int32_t lo, const int32_t hi, uint8_t dp, // apply: update function when the encoder is pressed void setValueOnClick(uint8_t process, const int32_t lo, const int32_t hi, const int32_t val, void (*apply)()/*=nullptr*/, void (*liveUpdate)()/*=nullptr*/) { setOnClick(process, lo, hi, 0, val, apply, liveUpdate); - DrawItemEdit(true); + drawItemEdit(true); } // Generic onclick event for float values @@ -215,7 +215,7 @@ void setValueOnClick(uint8_t process, const int32_t lo, const int32_t hi, const void setValueOnClick(uint8_t process, const float lo, const float hi, uint8_t dp, const float val, void (*apply)()/*=nullptr*/, void (*liveUpdate)()/*=nullptr*/) { const int32_t value = LROUND(val * POW(10, dp)); setOnClick(process, lo * POW(10, dp), hi * POW(10, dp), dp, value, apply, liveUpdate); - DrawItemEdit(true); + drawItemEdit(true); } // Generic onclick event for integer values @@ -285,14 +285,14 @@ int8_t hmiGet(bool draw) { if (encoder_diffState != ENCODER_DIFF_NO) { if (applyEncoder(encoder_diffState, menuData.value)) { encoderRate.enabled = false; - if (draw) DrawItemEdit(false); + if (draw) drawItemEdit(false); checkkey = ID_Menu; return 2; } LIMIT(menuData.value, lo, hi); } const bool change = cval != menuData.value; - if (change) DrawItemEdit(true); + if (change) drawItemEdit(true); return int8_t(change); } @@ -547,13 +547,13 @@ void updateMenu(Menu* &menu) { menu->draw(); } -void ReDrawMenu(bool force/*=false*/) { +void redrawMenu(bool force/*=false*/) { if (currentMenu && (force || checkkey == ID_Menu)) currentMenu->draw(); - if (force) DrawItemEdit(true); + if (force) drawItemEdit(true); } -void ReDrawItem() { - static_cast(currentMenu->selectedItem())->redraw(false); +void redrawItem() { + static_cast(currentMenu->selectedItem())->value; } #endif // DWIN_LCD_PROUI diff --git a/Marlin/src/lcd/dwin/proui/menus.h b/Marlin/src/lcd/dwin/proui/menus.h index 1d3a394710..d206897984 100644 --- a/Marlin/src/lcd/dwin/proui/menus.h +++ b/Marlin/src/lcd/dwin/proui/menus.h @@ -187,10 +187,10 @@ void invalidateMenu(); void updateMenu(Menu* &menu); // Redraw the current Menu if it is valid -void ReDrawMenu(bool force=false); +void redrawMenu(bool force=false); // Redraw selected menu item -void ReDrawItem(); +void redrawItem(); // Clear menuItems array and free menuItems elements void menuItemsClear(); diff --git a/Marlin/src/lcd/dwin/proui/meshviewer.cpp b/Marlin/src/lcd/dwin/proui/meshviewer.cpp index 54904ad8b9..a4aa48ecec 100644 --- a/Marlin/src/lcd/dwin/proui/meshviewer.cpp +++ b/Marlin/src/lcd/dwin/proui/meshviewer.cpp @@ -32,11 +32,9 @@ #if ALL(DWIN_LCD_PROUI, HAS_MESH) -#include "../../../core/types.h" #include "../../marlinui.h" -#include "dwin.h" -#include "dwin_popup.h" #include "../../../feature/bedlevel/bedlevel.h" +#include "dwin_popup.h" #include "meshviewer.h" #if USE_GRID_MESHVIEWER @@ -55,8 +53,6 @@ uint8_t rmax; // Maximum radius #define px(xp) (margin + (xp) * (width) / (sizex - 1)) #define py(yp) (30 + DWIN_WIDTH - margin - (yp) * (width) / (sizey - 1)) -constexpr uint8_t meshfont = TERN(TJC_DISPLAY, font8x16, font6x12); - MeshViewer meshViewer; float MeshViewer::max, MeshViewer::min; @@ -74,31 +70,32 @@ void MeshViewer::drawMeshGrid(const uint8_t csizex, const uint8_t csizey) { } void MeshViewer::drawMeshPoint(const uint8_t x, const uint8_t y, const float z) { - const uint8_t fs = DWINUI::fontWidth(meshfont); + const uint8_t fs = DWINUI::fontWidth(title.meshfont); const int16_t v = isnan(z) ? int16_t(0) : int16_t(LROUND(z * 100)); NOLESS(max, z); NOMORE(min, z); const uint16_t color = DWINUI::rainbowInt(v, zmin, zmax); - DWINUI::drawFillCircle(color, px(x), py(y), r(_MAX(_MIN(v, zmax), zmin))); + const int16_t xp = px(x), yp = py(y); + DWINUI::drawFillCircle(color, xp, yp, r(_MAX(_MIN(v, zmax), zmin))); TERN_(TJC_DISPLAY, delay(100)); - const uint16_t fy = py(y) - fs; + const int16_t fy = yp - fs; if (sizex < TERN(TJC_DISPLAY, 8, 9)) { - if (v == 0) DWINUI::drawFloat(meshfont, 1, 2, px(x) - 2 * fs, fy, 0); - else DWINUI::drawSignedFloat(meshfont, 1, 2, px(x) - 3 * fs, fy, z); + if (v == 0) DWINUI::drawFloat(title.meshfont, 1, 2, xp - 2 * fs, fy, 0); + else DWINUI::drawSignedFloat(title.meshfont, 1, 2, xp - 3 * fs, fy, z); } else { char msg[9]; msg[0] = '\0'; switch (v) { case -999 ... -100: - case 100 ... 999: DWINUI::drawSignedFloat(meshfont, 1, 1, px(x) - 3 * fs, fy, z); break; + case 100 ... 999: DWINUI::drawSignedFloat(title.meshfont, 1, 1, xp - 3 * fs, fy, z); break; case -99 ... -1: sprintf_P(msg, PSTR("-.%2i"), -v); break; case 1 ... 99: sprintf_P(msg, PSTR( ".%2i"), v); break; default: - dwinDrawString(false, meshfont, DWINUI::textColor, DWINUI::backColor, px(x) - 4, fy, "0"); + dwinDrawString(false, title.meshfont, DWINUI::textColor, DWINUI::backColor, xp - 4, fy, "0"); return; } - dwinDrawString(false, meshfont, DWINUI::textColor, DWINUI::backColor, px(x) - 2 * fs, fy, msg); + dwinDrawString(false, title.meshfont, DWINUI::textColor, DWINUI::backColor, xp - 2 * fs, fy, msg); } } diff --git a/Marlin/src/lcd/dwin/proui/meshviewer.h b/Marlin/src/lcd/dwin/proui/meshviewer.h index 93be9ee7c2..d81efc04ae 100644 --- a/Marlin/src/lcd/dwin/proui/meshviewer.h +++ b/Marlin/src/lcd/dwin/proui/meshviewer.h @@ -34,6 +34,7 @@ public: static float max, min; static void drawMeshGrid(const uint8_t csizex, const uint8_t csizey); static void drawMeshPoint(const uint8_t x, const uint8_t y, const float z); + static void drawMeshPoint(const xy_int8_t xy, const float z) { drawMeshPoint(uint8_t(xy.x), uint8_t(xy.y), z); } static void draw(const bool withsave=false, const bool redraw=true); static void drawMesh(const bed_mesh_t zval, const uint8_t csizex, const uint8_t csizey); }; diff --git a/Marlin/src/lcd/dwin/proui/plot.cpp b/Marlin/src/lcd/dwin/proui/plot.cpp index bd5638a6bc..e81dfb66ed 100644 --- a/Marlin/src/lcd/dwin/proui/plot.cpp +++ b/Marlin/src/lcd/dwin/proui/plot.cpp @@ -27,15 +27,14 @@ * Date: 2023/01/29 */ -#include "../../../inc/MarlinConfig.h" +#include "../../../inc/MarlinConfigPre.h" #if ENABLED(DWIN_LCD_PROUI) -#include "dwin_defines.h" +#include "dwin.h" #if PROUI_TUNING_GRAPH -#include "dwin.h" #include "../../marlinui.h" #include "plot.h" diff --git a/Marlin/src/lcd/dwin/proui/printstats.cpp b/Marlin/src/lcd/dwin/proui/printstats.cpp index 90973dc9c5..e7eb3e658f 100644 --- a/Marlin/src/lcd/dwin/proui/printstats.cpp +++ b/Marlin/src/lcd/dwin/proui/printstats.cpp @@ -32,14 +32,13 @@ #if ALL(DWIN_LCD_PROUI, PRINTCOUNTER) +#include "dwin_popup.h" #include "printstats.h" -#include "../../../core/types.h" #include "../../../MarlinCore.h" -#include "../../marlinui.h" +#include "../../../core/types.h" #include "../../../module/printcounter.h" -#include "dwin.h" -#include "dwin_popup.h" +#include "../../marlinui.h" PrintStats printStats; diff --git a/Marlin/src/lcd/dwin/proui/proui_extui.cpp b/Marlin/src/lcd/dwin/proui/proui_extui.cpp index 4aec61f0fb..5d16e54aaf 100644 --- a/Marlin/src/lcd/dwin/proui/proui_extui.cpp +++ b/Marlin/src/lcd/dwin/proui/proui_extui.cpp @@ -156,7 +156,11 @@ namespace ExtUI { #if HAS_LEVELING void onLevelingStart() { dwinLevelingStart(); } - void onLevelingDone() { dwinLevelingDone(); } + void onLevelingDone() { + #if ALL(HAS_MESH, HAS_BED_PROBE) + dwinLevelingDone(); + #endif + } #if ENABLED(PREHEAT_BEFORE_LEVELING) celsius_t getLevelingBedTemp() { return hmiData.bedLevT; } #endif diff --git a/Marlin/src/lcd/extui/ftdi_eve_touch_ui/cocoa_press/leveling_menu.cpp b/Marlin/src/lcd/extui/ftdi_eve_touch_ui/cocoa_press/leveling_menu.cpp index 820594acab..6551c2c7b5 100644 --- a/Marlin/src/lcd/extui/ftdi_eve_touch_ui/cocoa_press/leveling_menu.cpp +++ b/Marlin/src/lcd/extui/ftdi_eve_touch_ui/cocoa_press/leveling_menu.cpp @@ -29,7 +29,7 @@ using namespace FTDI; using namespace ExtUI; using namespace Theme; -#if ANY(MESH_BED_LEVELING, AUTO_BED_LEVELING_UBL) +#if HAS_MESH #define GRID_COLS 3 #define GRID_ROWS 6 #define BED_MESH_TITLE_POS BTN_POS(1,1), BTN_SIZE(3,1) diff --git a/Marlin/src/lcd/extui/ftdi_eve_touch_ui/generic/bed_mesh_view_screen.cpp b/Marlin/src/lcd/extui/ftdi_eve_touch_ui/generic/bed_mesh_view_screen.cpp index 6030fd02a0..62c8656b7e 100644 --- a/Marlin/src/lcd/extui/ftdi_eve_touch_ui/generic/bed_mesh_view_screen.cpp +++ b/Marlin/src/lcd/extui/ftdi_eve_touch_ui/generic/bed_mesh_view_screen.cpp @@ -53,7 +53,7 @@ constexpr static float gaugeThickness = 0.25; #endif static float meshGetter(uint8_t x, uint8_t y, void*) { - return ExtUI::getMeshPoint(xy_uint8_t({ x, y })); + return ExtUI::getMeshPoint(xy_uint8_t({x, y})); } void BedMeshViewScreen::onEntry() { diff --git a/Marlin/src/lcd/extui/ui_api.cpp b/Marlin/src/lcd/extui/ui_api.cpp index 05eced9c18..31bbe800bc 100644 --- a/Marlin/src/lcd/extui/ui_api.cpp +++ b/Marlin/src/lcd/extui/ui_api.cpp @@ -883,8 +883,8 @@ namespace ExtUI { void moveToMeshPoint(const xy_uint8_t &pos, const float z) { #if ANY(MESH_BED_LEVELING, AUTO_BED_LEVELING_UBL) REMEMBER(fr, motion.feedrate_mm_s); - const float x_target = MESH_MIN_X + pos.x * (MESH_X_DIST), - y_target = MESH_MIN_Y + pos.y * (MESH_Y_DIST); + const float x_target = mesh_min.x + pos.x * (MESH_X_DIST), + y_target = mesh_min.y + pos.y * (MESH_Y_DIST); if (x_target != motion.position.x || y_target != motion.position.y) { // If moving across bed, raise nozzle to safe height over bed motion.feedrate_mm_s = motion.z_probe_fast_mm_s; diff --git a/Marlin/src/lcd/language/language_en.h b/Marlin/src/lcd/language/language_en.h index 0472c9e4ec..cbbf277334 100644 --- a/Marlin/src/lcd/language/language_en.h +++ b/Marlin/src/lcd/language/language_en.h @@ -479,6 +479,7 @@ namespace LanguageNarrow_en { LSTR MSG_BILINEAR_LEVELING = _UxGT("Bilinear Leveling"); LSTR MSG_UBL_LEVELING = _UxGT("Unified Bed Leveling"); LSTR MSG_MESH_LEVELING = _UxGT("Mesh Leveling"); + LSTR MSG_MESH_SETTINGS = _UxGT("Mesh Settings"); LSTR MSG_INFO_RUNAWAY_OFF = _UxGT("Runaway Watch: OFF"); LSTR MSG_INFO_RUNAWAY_ON = _UxGT("Runaway Watch: ON"); LSTR MSG_CASE_LIGHT_BRIGHTNESS = _UxGT("Light Brightness"); @@ -697,6 +698,7 @@ namespace LanguageNarrow_en { LSTR MSG_ZPROBE_SETTINGS = _UxGT("Probe Settings"); LSTR MSG_ZPROBE_OFFSETS = _UxGT("Probe Offsets"); LSTR MSG_ZPROBE_MARGIN = _UxGT("Probe Margin"); + LSTR MSG_ZPROBE_MULTIPLE = _UxGT("Multiple Probing"); LSTR MSG_Z_FEED_RATE = _UxGT("Z Feedrate"); LSTR MSG_ENABLE_HS_MODE = _UxGT("Enable HS mode"); LSTR MSG_MOVE_NOZZLE_TO_BED = _UxGT("Move Nozzle to Bed"); @@ -1093,6 +1095,7 @@ namespace LanguageWide_en { LSTR MSG_PLEASE_PREHEAT = _UxGT("Please preheat the hot end."); LSTR MSG_MEDIA_NOT_INSERTED = _UxGT("No media inserted."); LSTR MSG_INFO_PRINT_COUNT_RESET = _UxGT("Reset Print Count"); + LSTR MSG_ZERO_MESH = _UxGT("Zero Current Point"); LSTR MSG_HOMING_FEEDRATE_N = _UxGT("@ Homing Feedrate"); LSTR MSG_PREHEAT_1_CHAMBER = _UxGT("Preheat ") PREHEAT_1_LABEL _UxGT(" Chamber"); LSTR MSG_PREHEAT_M_CHAMBER = _UxGT("Preheat $ Chamber"); diff --git a/Marlin/src/module/motion.cpp b/Marlin/src/module/motion.cpp index 239f8ac627..b401090d87 100644 --- a/Marlin/src/module/motion.cpp +++ b/Marlin/src/module/motion.cpp @@ -218,13 +218,20 @@ int16_t Motion::feedrate_percentage = 100; feedRate_t Motion::xy_probe_feedrate_mm_s = MMM_TO_MMS(XY_PROBE_FEEDRATE); #endif -#ifdef Z_PROBE_FEEDRATE_SLOW +#if ENABLED(DWIN_LCD_PROUI) + uint16_t Motion::z_probe_slow_mm_s = MMM_TO_MMS(Z_PROBE_FEEDRATE_SLOW); +#elif Z_PROBE_FEEDRATE_SLOW constexpr feedRate_t Motion::z_probe_slow_mm_s; #endif #ifdef Z_PROBE_FEEDRATE_FAST constexpr feedRate_t Motion::z_probe_fast_mm_s; #endif +#if HAS_PROUI_MESH_EDIT + xy_pos_t mesh_min{ MESH_MIN_X, MESH_MIN_Y }, + mesh_max{ MESH_MAX_X, MESH_MAX_Y }; +#endif + /** * Output the current position to serial */ @@ -1090,6 +1097,11 @@ void Motion::blocking_move(const xy_pos_t &raw, const feedRate_t fr_mm_s/*=0.0f* if (DEBUGGING(LEVELING)) DEBUG_ECHOLNPGM("do_z_clearance_by(", zclear, ")"); do_z_clearance(position.z + zclear, false); } + + #if ENABLED(DWIN_LCD_PROUI) && (HAS_MESH || ALL(INDIVIDUAL_AXIS_HOMING_SUBMENU, MESH_BED_LEVELING)) + #include "../lcd/dwin/proui/dwin.h" // for Z_POST_CLEARANCE + #endif + /** * Move Z to Z_POST_CLEARANCE, * The axis is allowed to move down. @@ -1107,9 +1119,6 @@ void Motion::blocking_move(const xy_pos_t &raw, const feedRate_t fr_mm_s/*=0.0f* #endif } - #if ALL(DWIN_LCD_PROUI, INDIVIDUAL_AXIS_HOMING_SUBMENU, MESH_BED_LEVELING) - #include "../lcd/e3v2/proui/dwin.h" // for Z_POST_CLEARANCE - #endif #ifndef Z_POST_CLEARANCE // May be set by proui/dwin.h :-P #ifdef Z_AFTER_HOMING #define Z_POST_CLEARANCE Z_AFTER_HOMING diff --git a/Marlin/src/module/motion.h b/Marlin/src/module/motion.h index 242606b228..e6a8e23254 100644 --- a/Marlin/src/module/motion.h +++ b/Marlin/src/module/motion.h @@ -30,10 +30,6 @@ #include "../inc/MarlinConfig.h" -//#if ALL(DWIN_LCD_PROUI, INDIVIDUAL_AXIS_HOMING_SUBMENU, MESH_BED_LEVELING) -// #include "../lcd/dwin/proui/dwin.h" // for Z_POST_CLEARANCE -//#endif - #if IS_SCARA #include "scara.h" #elif ENABLED(POLAR) @@ -261,7 +257,9 @@ public: #if HAS_VARIABLE_XY_PROBE_FEEDRATE static feedRate_t xy_probe_feedrate_mm_s; // Set with 'G29 S' for ABL LINEAR/BILINEAR. TODO: Store to EEPROM. #endif - #ifdef Z_PROBE_FEEDRATE_SLOW + #if ENABLED(DWIN_LCD_PROUI) + static uint16_t z_probe_slow_mm_s; + #elif defined(Z_PROBE_FEEDRATE_SLOW) static constexpr feedRate_t z_probe_slow_mm_s = MMM_TO_MMS(Z_PROBE_FEEDRATE_SLOW); #endif #ifdef Z_PROBE_FEEDRATE_FAST @@ -681,6 +679,17 @@ private: extern Motion motion; +#if HAS_PROUI_MESH_EDIT + #define MESH_X_DIST ((mesh_max.x - mesh_min.x) / (GRID_MAX_CELLS_X)) + #define MESH_Y_DIST ((mesh_max.y - mesh_min.y) / (GRID_MAX_CELLS_Y)) + extern xy_pos_t mesh_min, mesh_max; +#elif HAS_MESH + #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)) + constexpr xy_pos_t mesh_min{ MESH_MIN_X, MESH_MIN_Y }, + mesh_max{ MESH_MAX_X, MESH_MAX_Y }; +#endif + // External conversion methods (motion.h) inline void toLogical(xy_pos_t &raw) { motion.toLogical(raw); } inline void toLogical(xyz_pos_t &raw) { motion.toLogical(raw); } diff --git a/Marlin/src/module/probe.cpp b/Marlin/src/module/probe.cpp index b3c7fa6f88..79020393e9 100644 --- a/Marlin/src/module/probe.cpp +++ b/Marlin/src/module/probe.cpp @@ -376,7 +376,7 @@ FORCE_INLINE void probe_specific_action(const bool deploy) { #if ENABLED(PAUSE_BEFORE_DEPLOY_STOW) // Start preheating before waiting for user confirmation that the probe is ready. - TERN_(PREHEAT_BEFORE_PROBING, if (deploy) probe.preheat_for_probing(0, PROBING_BED_TEMP, true)); + TERN_(PREHEAT_BEFORE_PROBING, if (deploy) probe.preheat_for_probing(PROBING_NOZZLE_TEMP, PROBING_BED_TEMP, true)); FSTR_P const ds_fstr = deploy ? GET_TEXT_F(MSG_MANUAL_DEPLOY) : GET_TEXT_F(MSG_MANUAL_STOW); ui.return_to_status(); // To display the new status message @@ -812,8 +812,125 @@ float Probe::run_z_probe(const bool sanity_check/*=true*/, const float z_min_poi const float z_probe_low_point = zoffs + z_min_point -float((!motion.axis_is_trusted(Z_AXIS)) * 10); if (DEBUGGING(LEVELING)) DEBUG_ECHOLNPGM("Probe Low Point: ", z_probe_low_point); - // Double-probing does a fast probe followed by a slow probe - #if TOTAL_PROBING == 2 + #if DISABLED(DWIN_LCD_PROUI) + + // Double-probing does a fast probe followed by a slow probe + #if TOTAL_PROBING == 2 + + // Attempt to tare the probe + if (TERN0(PROBE_TARE, tare())) return NAN; + + // Do a first probe at the fast speed + if (try_to_probe(PSTR("FAST"), z_probe_low_point, motion.z_probe_fast_mm_s, sanity_check)) return NAN; + + const float z1 = DIFF_TERN(HAS_DELTA_SENSORLESS_PROBING, motion.position.z, largest_sensorless_adj); + if (DEBUGGING(LEVELING)) DEBUG_ECHOLNPGM("1st Probe Z:", z1); + + // Raise to give the probe clearance + motion.do_z_clearance(z1 + (Z_CLEARANCE_MULTI_PROBE), false); + + #elif Z_PROBE_FEEDRATE_FAST != Z_PROBE_FEEDRATE_SLOW + + // If the nozzle is well over the travel height then + // move down quickly before doing the slow probe + const float z = (Z_CLEARANCE_DEPLOY_PROBE) + 5.0f + _MAX(zoffs, 0.0f); + if (motion.position.z > z) { + // Probe down fast. If the probe never triggered, raise for probe clearance + if (!probe_down_to_z(z, motion.z_probe_fast_mm_s)) + motion.do_z_clearance(z_clearance); + } + #endif + + #if EXTRA_PROBING > 0 + float probes[TOTAL_PROBING]; + #endif + + #if TOTAL_PROBING > 2 + float probes_z_sum = 0; + for ( + #if EXTRA_PROBING > 0 + uint8_t p = 0; p < TOTAL_PROBING; p++ + #else + uint8_t p = TOTAL_PROBING; p--; + #endif + ) + #endif + { + // If the probe won't tare, return + if (TERN0(PROBE_TARE, tare())) return true; + + // Probe downward slowly to find the bed + if (DEBUGGING(LEVELING)) DEBUG_ECHOLNPGM("Slow Probe:"); + if (try_to_probe(PSTR("SLOW"), z_probe_low_point, motion.z_probe_slow_mm_s, sanity_check)) return NAN; + + TERN_(MEASURE_BACKLASH_WHEN_PROBING, backlash.measure_with_probe()); + + const float z = DIFF_TERN(HAS_DELTA_SENSORLESS_PROBING, motion.position.z, largest_sensorless_adj); + + #if EXTRA_PROBING > 0 + // Insert Z measurement into probes[]. Keep it sorted ascending. + for (uint8_t i = 0; i <= p; ++i) { // Iterate the saved Zs to insert the new Z + if (i == p || probes[i] > z) { // Last index or new Z is smaller than this Z + for (int8_t m = p; --m >= i;) probes[m + 1] = probes[m]; // Shift items down after the insertion point + probes[i] = z; // Insert the new Z measurement + break; // Only one to insert. Done! + } + } + #elif TOTAL_PROBING > 2 + probes_z_sum += z; + #else + UNUSED(z); + #endif + + #if TOTAL_PROBING > 2 + // Small Z raise after all but the last probe + if (p + #if EXTRA_PROBING > 0 + < TOTAL_PROBING - 1 + #endif + ) motion.do_z_clearance(z + (Z_CLEARANCE_MULTI_PROBE), false); + #endif + } + + #if TOTAL_PROBING > 2 + + #if EXTRA_PROBING > 0 + // Take the center value (or average the two middle values) as the median + static constexpr int PHALF = (TOTAL_PROBING - 1) / 2; + const float middle = probes[PHALF], + median = ((TOTAL_PROBING) & 1) ? middle : (middle + probes[PHALF + 1]) * 0.5f; + + // Remove values farthest from the median + uint8_t min_avg_idx = 0, max_avg_idx = TOTAL_PROBING - 1; + for (uint8_t i = EXTRA_PROBING; i--;) + if (ABS(probes[max_avg_idx] - median) > ABS(probes[min_avg_idx] - median)) + max_avg_idx--; else min_avg_idx++; + + // Return the average value of all remaining probes. + for (uint8_t i = min_avg_idx; i <= max_avg_idx; ++i) + probes_z_sum += probes[i]; + + #endif + + const float measured_z = probes_z_sum * RECIPROCAL(MULTIPLE_PROBING); + + #elif TOTAL_PROBING == 2 + + const float z2 = DIFF_TERN(HAS_DELTA_SENSORLESS_PROBING, motion.position.z, largest_sensorless_adj); + + if (DEBUGGING(LEVELING)) DEBUG_ECHOLNPGM("2nd Probe Z:", z2, " Discrepancy:", z1 - z2); + + // Return a weighted average of the fast and slow probes + const float measured_z = (z2 * 3.0f + z1 * 2.0f) * 0.2f; + + #else + + // Return the single probe result + const float measured_z = motion.position.z; + + #endif + + #else // DWIN_LCD_PROUI // Attempt to tare the probe if (TERN0(PROBE_TARE, tare())) return NAN; @@ -827,33 +944,8 @@ float Probe::run_z_probe(const bool sanity_check/*=true*/, const float z_min_poi // Raise to give the probe clearance motion.do_z_clearance(z1 + (Z_CLEARANCE_MULTI_PROBE), false); - #elif Z_PROBE_FEEDRATE_FAST != Z_PROBE_FEEDRATE_SLOW - - // If the nozzle is well over the travel height then - // move down quickly before doing the slow probe - const float z = (Z_CLEARANCE_DEPLOY_PROBE) + 5.0f + _MAX(zoffs, 0.0f); - if (motion.position.z > z) { - // Probe down fast. If the probe never triggered, raise for probe clearance - if (!probe_down_to_z(z, motion.z_probe_fast_mm_s)) - motion.do_z_clearance(z_clearance); - } - #endif - - #if EXTRA_PROBING > 0 - float probes[TOTAL_PROBING]; - #endif - - #if TOTAL_PROBING > 2 float probes_z_sum = 0; - for ( - #if EXTRA_PROBING > 0 - uint8_t p = 0; p < TOTAL_PROBING; p++ - #else - uint8_t p = TOTAL_PROBING; p--; - #endif - ) - #endif - { + for (uint8_t p = 0; p < hmiData.multiple_probing - 1; p++) { // If the probe won't tare, return if (TERN0(PROBE_TARE, tare())) return true; @@ -864,69 +956,15 @@ float Probe::run_z_probe(const bool sanity_check/*=true*/, const float z_min_poi TERN_(MEASURE_BACKLASH_WHEN_PROBING, backlash.measure_with_probe()); const float z = DIFF_TERN(HAS_DELTA_SENSORLESS_PROBING, motion.position.z, largest_sensorless_adj); - - #if EXTRA_PROBING > 0 - // Insert Z measurement into probes[]. Keep it sorted ascending. - for (uint8_t i = 0; i <= p; ++i) { // Iterate the saved Zs to insert the new Z - if (i == p || probes[i] > z) { // Last index or new Z is smaller than this Z - for (int8_t m = p; --m >= i;) probes[m + 1] = probes[m]; // Shift items down after the insertion point - probes[i] = z; // Insert the new Z measurement - break; // Only one to insert. Done! - } - } - #elif TOTAL_PROBING > 2 - probes_z_sum += z; - #else - UNUSED(z); - #endif - - #if TOTAL_PROBING > 2 - // Small Z raise after all but the last probe - if (p - #if EXTRA_PROBING > 0 - < TOTAL_PROBING - 1 - #endif - ) motion.do_z_clearance(z + (Z_CLEARANCE_MULTI_PROBE), false); - #endif + probes_z_sum += z; + // Small Z raise after probe + motion.do_z_clearance(z + (Z_CLEARANCE_MULTI_PROBE), false); } - #if TOTAL_PROBING > 2 - - #if EXTRA_PROBING > 0 - // Take the center value (or average the two middle values) as the median - static constexpr int PHALF = (TOTAL_PROBING - 1) / 2; - const float middle = probes[PHALF], - median = ((TOTAL_PROBING) & 1) ? middle : (middle + probes[PHALF + 1]) * 0.5f; - - // Remove values farthest from the median - uint8_t min_avg_idx = 0, max_avg_idx = TOTAL_PROBING - 1; - for (uint8_t i = EXTRA_PROBING; i--;) - if (ABS(probes[max_avg_idx] - median) > ABS(probes[min_avg_idx] - median)) - max_avg_idx--; else min_avg_idx++; - - // Return the average value of all remaining probes. - for (uint8_t i = min_avg_idx; i <= max_avg_idx; ++i) - probes_z_sum += probes[i]; - - #endif - - const float measured_z = probes_z_sum * RECIPROCAL(MULTIPLE_PROBING); - - #elif TOTAL_PROBING == 2 - - const float z2 = DIFF_TERN(HAS_DELTA_SENSORLESS_PROBING, motion.position.z, largest_sensorless_adj); - - if (DEBUGGING(LEVELING)) DEBUG_ECHOLNPGM("2nd Probe Z:", z2, " Discrepancy:", z1 - z2); - // Return a weighted average of the fast and slow probes - const float measured_z = (z2 * 3.0f + z1 * 2.0f) * 0.2f; + const float measured_z = (hmiData.multiple_probing > 1) ? (probes_z_sum * 3.0f + z1 * 2.0f) * 0.2f : z1; - #else - - // Return the single probe result - const float measured_z = motion.position.z; - - #endif + #endif // DWIN_LCD_PROUI return DIFF_TERN(HAS_HOTEND_OFFSET, measured_z, motion.active_hotend_offset().z); } diff --git a/Marlin/src/module/probe.h b/Marlin/src/module/probe.h index 521b028592..4f2a10eb1a 100644 --- a/Marlin/src/module/probe.h +++ b/Marlin/src/module/probe.h @@ -335,10 +335,10 @@ public: points[0] = xy_float_t({ (X_CENTER) + probe_radius() * COS0, (Y_CENTER) + probe_radius() * SIN0 }); points[1] = xy_float_t({ (X_CENTER) + probe_radius() * COS120, (Y_CENTER) + probe_radius() * SIN120 }); points[2] = xy_float_t({ (X_CENTER) + probe_radius() * COS240, (Y_CENTER) + probe_radius() * SIN240 }); - #elif ENABLED(AUTO_BED_LEVELING_UBL) - points[0] = xy_float_t({ _MAX(float(MESH_MIN_X), min_x()), _MAX(float(MESH_MIN_Y), min_y()) }); - points[1] = xy_float_t({ _MIN(float(MESH_MAX_X), max_x()), _MAX(float(MESH_MIN_Y), min_y()) }); - points[2] = xy_float_t({ (_MAX(float(MESH_MIN_X), min_x()) + _MIN(float(MESH_MAX_X), max_x())) / 2, _MIN(float(MESH_MAX_Y), max_y()) }); + #elif ENABLED(AUTO_BED_LEVELING_UBL) && !HAS_PROUI_MESH_EDIT + points[0] = xy_float_t({ _MAX(mesh_min.x, min_x()), _MAX(mesh_min.y, min_y()) }); + points[1] = xy_float_t({ _MIN(mesh_max.x, max_x()), _MAX(mesh_min.y, min_y()) }); + points[2] = xy_float_t({ (_MAX(mesh_min.x, min_x()) + _MIN(mesh_max.x, max_x())) / 2, _MIN(mesh_max.y, max_y()) }); #else points[0] = xy_float_t({ min_x(), min_y() }); points[1] = xy_float_t({ max_x(), min_y() }); diff --git a/buildroot/tests/STM32F103RE_creality b/buildroot/tests/STM32F103RE_creality index 45821598e0..a33c20bf00 100755 --- a/buildroot/tests/STM32F103RE_creality +++ b/buildroot/tests/STM32F103RE_creality @@ -26,15 +26,13 @@ opt_enable DWIN_MARLINUI_LANDSCAPE LCD_ENDSTOP_TEST AUTO_BED_LEVELING_UBL BLTOUC exec_test $1 $2 "Ender-3 V2 - MarlinUI (Games, UBL+BLTOUCH, MPCTEMP, LCD_ENDSTOP_TEST)" "$3" use_example_configs "Creality/Ender-3 S1/STM32F1" -opt_disable DWIN_CREALITY_LCD Z_MIN_PROBE_USES_Z_MIN_ENDSTOP_PIN AUTO_BED_LEVELING_BILINEAR CANCEL_OBJECTS FWRETRACT EVENT_GCODE_SD_ABORT -opt_enable DWIN_LCD_PROUI INDIVIDUAL_AXIS_HOMING_SUBMENU PID_AUTOTUNE_MENU PID_EDIT_MENU \ - SET_PROGRESS_MANUALLY SET_PROGRESS_PERCENT STATUS_MESSAGE_SCROLLING \ - SOUND_MENU_ITEM PRINTCOUNTER NOZZLE_PARK_FEATURE ADVANCED_PAUSE_FEATURE FILAMENT_RUNOUT_SENSOR \ - BLTOUCH Z_SAFE_HOMING AUTO_BED_LEVELING_UBL MESH_EDIT_MENU LCD_BED_TRAMMING LIN_ADVANCE \ - LIMITED_MAX_FR_EDITING LIMITED_MAX_ACCEL_EDITING LIMITED_JERK_EDITING BAUD_RATE_GCODE \ - CASE_LIGHT_ENABLE CASE_LIGHT_MENU CASE_LIGHT_NO_BRIGHTNESS NONLINEAR_EXTRUSION -opt_set PREHEAT_3_LABEL '"CUSTOM"' PREHEAT_3_TEMP_HOTEND 240 PREHEAT_3_TEMP_BED 60 PREHEAT_3_FAN_SPEED 128 BOOTSCREEN_TIMEOUT 1100 CASE_LIGHT_PIN 4 -exec_test $1 $2 "Ender-3 S1 - ProUI (PIDTEMP)" "$3" +opt_disable DWIN_CREALITY_LCD AUTO_BED_LEVELING_BILINEAR CANCEL_OBJECTS FWRETRACT EVENT_GCODE_SD_ABORT REINIT_NOISY_LCD +opt_enable DWIN_LCD_PROUI PID_AUTOTUNE_MENU PID_EDIT_MENU STATUS_MESSAGE_SCROLLING PRINTCOUNTER \ + AUTO_BED_LEVELING_UBL LCD_BED_TRAMMING LIN_ADVANCE \ + LIMITED_MAX_FR_EDITING LIMITED_JERK_EDITING BAUD_RATE_GCODE \ + CASE_LIGHT_ENABLE CASE_LIGHT_NO_BRIGHTNESS CASE_LIGHT_MENU NONLINEAR_EXTRUSION +opt_set BOOTSCREEN_TIMEOUT 1100 CASE_LIGHT_PIN 4 SDSORT_GCODE true +exec_test $1 $2 "Ender-3 S1 - ProUI (UBL, PIDTEMP)" "$3" restore_configs opt_set MOTHERBOARD BOARD_CREALITY_V452 SERIAL_PORT 1