From 5f34637233b5e7b9356ca23c60fe3a9bbb2d9b80 Mon Sep 17 00:00:00 2001 From: Scott Lahteine Date: Thu, 5 Feb 2026 14:11:15 -0600 Subject: [PATCH] Squash and rebase --- Marlin/src/feature/bedlevel/abl/bbl.cpp | 35 +- Marlin/src/feature/bedlevel/bedlevel.cpp | 10 +- .../bedlevel/mbl/mesh_bed_leveling.cpp | 32 +- .../feature/bedlevel/mbl/mesh_bed_leveling.h | 14 +- Marlin/src/feature/bedlevel/ubl/ubl.cpp | 35 +- Marlin/src/feature/bedlevel/ubl/ubl.h | 30 +- Marlin/src/feature/bedlevel/ubl/ubl_G29.cpp | 41 +- Marlin/src/gcode/bedlevel/abl/G29.cpp | 14 +- Marlin/src/inc/Conditionals-5-post.h | 4 +- Marlin/src/inc/MarlinConfigPre.h | 5 + Marlin/src/inc/SanityCheck.h | 16 +- Marlin/src/lcd/dwin/proui/bedlevel_tools.cpp | 59 +- Marlin/src/lcd/dwin/proui/bedlevel_tools.h | 1 - Marlin/src/lcd/dwin/proui/dwin.cpp | 905 ++++++++++-------- Marlin/src/lcd/dwin/proui/dwin.h | 85 +- Marlin/src/lcd/dwin/proui/dwin_defines.h | 170 +++- Marlin/src/lcd/dwin/proui/dwin_popup.cpp | 1 - Marlin/src/lcd/dwin/proui/dwin_popup.h | 1 - Marlin/src/lcd/dwin/proui/dwinui.h | 2 +- Marlin/src/lcd/dwin/proui/gcode_preview.cpp | 83 +- Marlin/src/lcd/dwin/proui/gcode_preview.h | 16 + Marlin/src/lcd/dwin/proui/menus.cpp | 18 +- Marlin/src/lcd/dwin/proui/menus.h | 4 +- Marlin/src/lcd/dwin/proui/meshviewer.cpp | 15 +- Marlin/src/lcd/dwin/proui/proui_extui.cpp | 6 +- Marlin/src/lcd/language/language_en.h | 3 + Marlin/src/module/motion.cpp | 2 +- Marlin/src/module/motion.h | 2 +- Marlin/src/module/probe.cpp | 315 +++--- buildroot/tests/STM32F103RE_creality | 16 +- 30 files changed, 1163 insertions(+), 777 deletions(-) diff --git a/Marlin/src/feature/bedlevel/abl/bbl.cpp b/Marlin/src/feature/bedlevel/abl/bbl.cpp index 918b06d2b4..4366f2412f 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,24 @@ void LevelingBilinear::reset() { } } +/** + * Set grid spacing and start position + */ +#if ENABLED(PROUI_MESH_EDIT) + #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)) +#endif + 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 ENABLED(PROUI_MESH_EDIT) + grid_start.x = MESH_MIN_X; + grid_start.y = MESH_MIN_Y; + grid_spacing.x = MESH_X_DIST; + grid_spacing.y = MESH_Y_DIST; + #else + grid_spacing = _grid_spacing; + grid_start = _grid_start; + #endif grid_factor = grid_spacing.reciprocal(); } @@ -120,16 +135,16 @@ void LevelingBilinear::extrapolate_unprobed_bed_level() { #ifdef HALF_IN_X constexpr uint8_t ctrx2 = 0, xend = GRID_MAX_POINTS_X - 1; #else - constexpr uint8_t ctrx1 = (GRID_MAX_CELLS_X) / 2, // left-of-center - ctrx2 = (GRID_MAX_POINTS_X) / 2, // right-of-center + constexpr uint8_t ctrx1 = (GRID_MAX_CELLS_X) / 2, // left-of-center + ctrx2 = (GRID_MAX_POINTS_X) / 2, // right-of-center xend = ctrx1; #endif #ifdef HALF_IN_Y constexpr uint8_t ctry2 = 0, yend = GRID_MAX_POINTS_Y - 1; #else - constexpr uint8_t ctry1 = (GRID_MAX_CELLS_Y) / 2, // top-of-center - ctry2 = (GRID_MAX_POINTS_Y) / 2, // bottom-of-center + constexpr uint8_t ctry1 = (GRID_MAX_CELLS_Y) / 2, // top-of-center + ctry2 = (GRID_MAX_POINTS_Y) / 2, // bottom-of-center yend = ctry1; #endif diff --git a/Marlin/src/feature/bedlevel/bedlevel.cpp b/Marlin/src/feature/bedlevel/bedlevel.cpp index e479e4c70a..ca1e3c296a 100644 --- a/Marlin/src/feature/bedlevel/bedlevel.cpp +++ b/Marlin/src/feature/bedlevel/bedlevel.cpp @@ -46,8 +46,16 @@ #include "../../lcd/extui/ui_api.h" #endif +#if ALL(HAS_MESH, DWIN_LCD_PROUI) + #include "../../lcd/dwin/proui/bedlevel_tools.h" +#endif + bool leveling_is_valid() { - return TERN1(HAS_MESH, bedlevel.mesh_is_valid()); + #if ALL(HAS_MESH, DWIN_LCD_PROUI) + return bedLevelTools.meshValidate(); + #else + return TERN1(HAS_MESH, bedlevel.mesh_is_valid()); + #endif } /** diff --git a/Marlin/src/feature/bedlevel/mbl/mesh_bed_leveling.cpp b/Marlin/src/feature/bedlevel/mbl/mesh_bed_leveling.cpp index 155d34c4df..755b6bb028 100644 --- a/Marlin/src/feature/bedlevel/mbl/mesh_bed_leveling.cpp +++ b/Marlin/src/feature/bedlevel/mbl/mesh_bed_leveling.cpp @@ -34,18 +34,12 @@ mesh_bed_leveling bedlevel; - float mesh_bed_leveling::z_offset, - mesh_bed_leveling::z_values[GRID_MAX_POINTS_X][GRID_MAX_POINTS_Y], - mesh_bed_leveling::index_to_xpos[GRID_MAX_POINTS_X], + float mesh_bed_leveling::z_offset; + float mesh_bed_leveling::index_to_xpos[GRID_MAX_POINTS_X], mesh_bed_leveling::index_to_ypos[GRID_MAX_POINTS_Y]; + float mesh_bed_leveling::z_values[GRID_MAX_POINTS_X][GRID_MAX_POINTS_Y]; - mesh_bed_leveling::mesh_bed_leveling() { - for (uint8_t i = 0; i < GRID_MAX_POINTS_X; ++i) - 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); - reset(); - } + mesh_bed_leveling::mesh_bed_leveling() { initialize(); } void mesh_bed_leveling::reset() { z_offset = 0; @@ -55,6 +49,19 @@ #endif } + 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); + for (uint8_t j = 0; j < GRID_MAX_POINTS_Y; ++j) + index_to_ypos[j] = MESH_MIN_Y + j * (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]); + } + #if IS_CARTESIAN && DISABLED(SEGMENT_LEVELED_MOVES) /** @@ -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..525f94582b 100644 --- a/Marlin/src/feature/bedlevel/mbl/mesh_bed_leveling.h +++ b/Marlin/src/feature/bedlevel/mbl/mesh_bed_leveling.h @@ -37,17 +37,19 @@ enum MeshLevelingState : char { class mesh_bed_leveling { public: - static float z_offset, - z_values[GRID_MAX_POINTS_X][GRID_MAX_POINTS_Y], - index_to_xpos[GRID_MAX_POINTS_X], + static float z_offset; + static float z_values[GRID_MAX_POINTS_X][GRID_MAX_POINTS_Y]; + static float index_to_xpos[GRID_MAX_POINTS_X], index_to_ypos[GRID_MAX_POINTS_Y]; 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; @@ -70,7 +72,7 @@ public: } static float get_mesh_x(const uint8_t i) { return index_to_xpos[i]; } - static float get_mesh_y(const uint8_t i) { return index_to_ypos[i]; } + static float get_mesh_y(const uint8_t j) { return index_to_ypos[j]; } static uint8_t cell_index_x(const float x) { int8_t cx = (x - (MESH_MIN_X)) * RECIPROCAL(MESH_X_DIST); diff --git a/Marlin/src/feature/bedlevel/ubl/ubl.cpp b/Marlin/src/feature/bedlevel/ubl/ubl.cpp index 2357437633..31b35c6a8d 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 DISABLED(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; @@ -165,7 +167,7 @@ static void serial_echo_column_labels(const uint8_t sp) { void unified_bed_leveling::display_map(const uint8_t map_type) { const bool was = gcode.set_autoreport_paused(true); - constexpr uint8_t eachsp = 1 + 6 + 1, // [-3.567] + constexpr uint8_t eachsp = 1 + 6 + 1, // [-3.567] twixt = eachsp * (GRID_MAX_POINTS_X) - 9 * 2; // Leading 4sp, Coordinates 9sp each const bool human = !(map_type & 0x3), csv = map_type == 1, lcd = map_type == 2, comp = map_type & 0x4; @@ -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")); diff --git a/Marlin/src/feature/bedlevel/ubl/ubl.h b/Marlin/src/feature/bedlevel/ubl/ubl.h index f6e9ba0cd9..720db06ea7 100644 --- a/Marlin/src/feature/bedlevel/ubl/ubl.h +++ b/Marlin/src/feature/bedlevel/ubl/ubl.h @@ -110,14 +110,17 @@ public: static void smart_fill_wlsf(const float ) __O2; // O2 gives smaller code than Os on A2560 static int8_t storage_slot; - static bed_mesh_t z_values; + #if ENABLED(OPTIMIZED_MESH_STORAGE) static void set_store_from_mesh(const bed_mesh_t &in_values, mesh_store_t &stored_values); static void set_mesh_from_store(const mesh_store_t &stored_values, bed_mesh_t &out_values); #endif - static const float _mesh_index_to_xpos[GRID_MAX_POINTS_X], - _mesh_index_to_ypos[GRID_MAX_POINTS_Y]; + + #if DISABLED(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; @@ -287,12 +290,21 @@ 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); - } + #if ENABLED(PROUI_MESH_EDIT) + 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 j) { + return MESH_MIN_Y + j * (MESH_Y_DIST); + } + #else + 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 j) { + return j < (GRID_MAX_POINTS_Y) ? pgm_read_float(&_mesh_index_to_ypos[j]) : MESH_MIN_Y + j * (MESH_Y_DIST); + } + #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 42b0d0d5f6..641a6ce6f4 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" @@ -782,6 +786,7 @@ void unified_bed_leveling::shift_mesh_height(const float zoffs) { SERIAL_ECHOLNPGM("Probing mesh point ", point_num, "/", GRID_MAX_POINTS, "."); 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()); + TERN_(DWIN_LCD_PROUI, if (!hmiFlag.cancel_lev) { dwinRedrawScreen(); } else { break; }) #if HAS_MARLINUI_MENU if (ui.button_pressed()) { @@ -811,11 +816,14 @@ 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.x, best.pos.y, measured_z)); } SERIAL_FLUSH(); // Prevent host M105 buffer overrun. } while (best.pos.x >= 0 && --count); + TERN_(DWIN_LCD_PROUI, if (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)); @@ -825,13 +833,18 @@ void unified_bed_leveling::shift_mesh_height(const float zoffs) { probe.stow(); TERN_(HAS_MARLINUI_MENU, ui.capture()); - probe.move_z_after_probing(); + TERN_(Z_AFTER_PROBING, probe.move_z_after_probing()); - do_blocking_move_to_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 + do_blocking_move_to_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 + TERN_(DWIN_LCD_PROUI, EXIT_PROBE_MESH:); restore_ubl_active_state(); } @@ -1191,9 +1204,9 @@ bool unified_bed_leveling::G29_parse_parameters() { } param.XY_seen.x = parser.seenval('X'); - float sx = param.XY_seen.x ? parser.value_float() : current_position.x; + float sx = param.XY_seen.x ? parser.value_float() : current_position.x - TERN0(HAS_BED_PROBE, probe.offset.x); param.XY_seen.y = parser.seenval('Y'); - float sy = param.XY_seen.y ? parser.value_float() : current_position.y; + float sy = param.XY_seen.y ? parser.value_float() : current_position.y - TERN0(HAS_BED_PROBE, probe.offset.y); if (param.XY_seen.x != param.XY_seen.y) { SERIAL_ECHOLNPGM("Both X & Y locations must be specified.\n"); @@ -1202,8 +1215,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, X_CENTER - TERN0(HAS_BED_PROBE, probe.offset.x)); + if (!COORDINATE_OKAY(sy, Y_MIN_BED, Y_MAX_BED)) sy = TERN(UBL_HILBERT_CURVE, 0, Y_CENTER - TERN0(HAS_BED_PROBE, probe.offset.y)); if (err_flag) return UBL_ERR; @@ -1523,7 +1536,7 @@ void unified_bed_leveling::smart_fill_mesh() { } probe.stow(); - probe.move_z_after_probing(); + TERN_(Z_AFTER_PROBING, probe.move_z_after_probing()); if (abort_flag) { SERIAL_ECHOLNPGM("?Error probing point. Aborting operation."); @@ -1609,7 +1622,7 @@ void unified_bed_leveling::smart_fill_mesh() { } } probe.stow(); - probe.move_z_after_probing(); + TERN_(Z_AFTER_PROBING, probe.move_z_after_probing()); if (abort_flag || finish_incremental_LSF(&lsf_results)) { SERIAL_ECHOLNPGM("Could not complete LSF!"); @@ -1777,8 +1790,8 @@ void unified_bed_leveling::smart_fill_mesh() { SERIAL_EOL(); SERIAL_ECHOPGM("Y-Axis Mesh Points at: "); - for (uint8_t i = 0; i < GRID_MAX_POINTS_Y; ++i) { - SERIAL_ECHO(p_float_t(LOGICAL_Y_POSITION(get_mesh_y(i)), 3), F(" ")); + for (uint8_t j = 0; j < GRID_MAX_POINTS_Y; ++j) { + SERIAL_ECHO(p_float_t(LOGICAL_Y_POSITION(get_mesh_y(j)), 3), F(" ")); serial_delay(25); } SERIAL_EOL(); diff --git a/Marlin/src/gcode/bedlevel/abl/G29.cpp b/Marlin/src/gcode/bedlevel/abl/G29.cpp index 800d51dac6..9240bc0ffd 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,10 @@ 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))); + #if ENABLED(DWIN_LCD_PROUI) + else + process_subcommands_now(F("G28Z")); + #endif // Don't allow auto-leveling without homing first if (homing_needed_error()) G29_RETURN(false, false); @@ -681,6 +689,8 @@ G29_TYPE GcodeSuite::G29() { int8_t inStart, inStop, inInc; + TERN_(DWIN_LCD_PROUI, if (hmiFlag.cancel_lev) break); + if (zig) { // Zig away from origin inStart = 0; // Left or front inStop = PR_INNER_SIZE; // Right or back @@ -793,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.x, abl.meshCount.y, z)); #if ENABLED(SOVOL_SV06_RTS) if (pt_index <= GRID_MAX_POINTS) rts.sendData(pt_index, AUTO_BED_LEVEL_ICON_VP); @@ -804,6 +815,7 @@ G29_TYPE GcodeSuite::G29() { abl.reenable = false; // Don't re-enable after modifying the mesh marlin.idle_no_sleep(); + TERN_(DWIN_LCD_PROUI, if (hmiFlag.cancel_lev) break); } // inner } // outer @@ -1009,7 +1021,7 @@ G29_TYPE GcodeSuite::G29() { // Restore state after probing if (!faux) restore_feedrate_and_scaling(); - TERN_(HAS_BED_PROBE, probe.move_z_after_probing()); + TERN_(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-5-post.h b/Marlin/src/inc/Conditionals-5-post.h index 55cd16c8d7..c069dcf732 100644 --- a/Marlin/src/inc/Conditionals-5-post.h +++ b/Marlin/src/inc/Conditionals-5-post.h @@ -574,7 +574,7 @@ #endif // Extender cable doesn't support SD_DETECT_PIN - #if ENABLED(NO_SD_DETECT) + #if ENABLED(NO_SD_DETECT) && DISABLED(DWIN_LCD_PROUI) #undef SD_DETECT_PIN #endif @@ -3445,7 +3445,7 @@ #ifndef MESH_MAX_Y #define MESH_MAX_Y _MESH_MAX_Y #endif -#else +#elif DISABLED(DWIN_LCD_PROUI) #undef MESH_MIN_X #undef MESH_MIN_Y #undef MESH_MAX_X diff --git a/Marlin/src/inc/MarlinConfigPre.h b/Marlin/src/inc/MarlinConfigPre.h index e89471f578..453d1aeb24 100644 --- a/Marlin/src/inc/MarlinConfigPre.h +++ b/Marlin/src/inc/MarlinConfigPre.h @@ -51,3 +51,8 @@ #ifndef __MARLIN_DEPS__ #include HAL_PATH(.., inc/Conditionals_adv.h) #endif + +// ProUI extra features +#if ENABLED(DWIN_LCD_PROUI) + #include "../lcd/dwin/proui/dwin_defines.h" +#endif diff --git a/Marlin/src/inc/SanityCheck.h b/Marlin/src/inc/SanityCheck.h index 761125d790..373f210157 100644 --- a/Marlin/src/inc/SanityCheck.h +++ b/Marlin/src/inc/SanityCheck.h @@ -1593,13 +1593,15 @@ 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 MULTIPLE_PROBING == 0 - #error "EXTRA_PROBING requires MULTIPLE_PROBING." - #elif MULTIPLE_PROBING < 2 - #error "MULTIPLE_PROBING must be 2 or more." - #elif MULTIPLE_PROBING <= EXTRA_PROBING - #error "EXTRA_PROBING must be less than MULTIPLE_PROBING." + #if DISABLED(DWIN_LCD_PROUI) + #if MULTIPLE_PROBING > 0 || EXTRA_PROBING > 0 + #if MULTIPLE_PROBING == 0 + #error "EXTRA_PROBING requires MULTIPLE_PROBING." + #elif MULTIPLE_PROBING < 2 + #error "MULTIPLE_PROBING must be 2 or more." + #elif MULTIPLE_PROBING <= EXTRA_PROBING + #error "EXTRA_PROBING must be less than MULTIPLE_PROBING." + #endif #endif #endif diff --git a/Marlin/src/lcd/dwin/proui/bedlevel_tools.cpp b/Marlin/src/lcd/dwin/proui/bedlevel_tools.cpp index 4621ce6653..81c01d21b9 100644 --- a/Marlin/src/lcd/dwin/proui/bedlevel_tools.cpp +++ b/Marlin/src/lcd/dwin/proui/bedlevel_tools.cpp @@ -60,13 +60,16 @@ #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) bool BedLevelTools::grid_meshview = false; bool BedLevelTools::viewer_print_value = false; #endif -bool BedLevelTools::goto_mesh_value = false; +bool BedLevelTools::goto_mesh_value = false; uint8_t BedLevelTools::mesh_x = 0; uint8_t BedLevelTools::mesh_y = 0; uint8_t BedLevelTools::tilt_grid = 1; @@ -97,17 +100,21 @@ bool drawing_mesh = false; GRID_LOOP(i, j) { float mx = bedlevel.get_mesh_x(i), my = bedlevel.get_mesh_y(j), mz = bedlevel.z_values[i][j]; - if (DEBUGGING(LEVELING)) { - DEBUG_ECHOLN(F("before rotation = ["), p_float_t(mx, 7), C(','), p_float_t(my, 7), C(','), p_float_t(mz, 7), F("] ---> ")); - DEBUG_DELAY(20); - } + #if DEBUG_OUT + if (DEBUGGING(LEVELING)) { + DEBUG_ECHOLN(F("before rotation = ["), p_float_t(mx, 7), C(','), p_float_t(my, 7), C(','), p_float_t(mz, 7), F("] ---> ")); + DEBUG_DELAY(20); + } + #endif rotation.apply_rotation_xyz(mx, my, mz); - if (DEBUGGING(LEVELING)) { - DEBUG_ECHOLN(F("after rotation = ["), p_float_t(mx, 7), C(','), p_float_t(my, 7), C(','), p_float_t(mz, 7), F("] ---> ")); - DEBUG_DELAY(20); - } + #if DEBUG_OUT + if (DEBUGGING(LEVELING)) { + DEBUG_ECHOLN(F("after rotation = ["), p_float_t(mx, 7), C(','), p_float_t(my, 7), C(','), p_float_t(mz, 7), F("] ---> ")); + DEBUG_DELAY(20); + } + #endif bedlevel.z_values[i][j] = mz - lsf_results.D; } @@ -127,7 +134,7 @@ void BedLevelTools::manualMove(const uint8_t mesh_x, const uint8_t mesh_y, bool if (!zmove) { dwinShowPopup(ICON_BLTouch, F("Moving to Point"), F("Please wait until done.")); hmiSaveProcessID(ID_NothingToDo); - gcode.process_subcommands_now(TS(F("G0 F300 Z"), p_float_t(Z_CLEARANCE_BETWEEN_PROBES, 3))); + gcode.process_subcommands_now(F("G0F600Z" STRINGIFY(Z_CLEARANCE_BETWEEN_PROBES))); gcode.process_subcommands_now(TS(F("G42 F4000 I"), mesh_x, F(" J"), mesh_y)); } planner.synchronize(); @@ -152,7 +159,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 +168,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()); } @@ -168,18 +176,25 @@ void BedLevelTools::meshReset() { // Accessors float BedLevelTools::getMaxValue() { float max = -(__FLT_MAX__); - GRID_LOOP(x, y) { const float z = bedlevel.z_values[x][y]; if (!isnan(z)) NOLESS(max, z); } + GRID_LOOP(x, y) { + const float z = bedlevel.z_values[x][y]; + if (!isnan(z)) NOLESS(max, z); + } return max; } float BedLevelTools::getMinValue() { float min = __FLT_MAX__; - GRID_LOOP(x, y) { const float z = bedlevel.z_values[x][y]; if (!isnan(z)) NOMORE(min, z); } + GRID_LOOP(x, y) { + const float z = bedlevel.z_values[x][y]; + if (!isnan(z)) NOMORE(min, z); + } return min; } // Return 'true' if mesh is good and within LCD limits bool BedLevelTools::meshValidate() { + TERN_(PROUI_MESH_EDIT, 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; @@ -187,9 +202,7 @@ bool BedLevelTools::meshValidate() { 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 +229,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,22 +242,22 @@ 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; - constexpr bool is_wide = (GRID_MAX_POINTS_X) >= TERN(TJC_DISPLAY, 8, 10); + const bool is_wide = (GRID_MAX_POINTS_X) >= TERN(TJC_DISPLAY, 8, 10); if (is_wide) msg.setf(F("%02i"), uint16_t(z * 100) % 100); else 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..d2bc433c52 100644 --- a/Marlin/src/lcd/dwin/proui/bedlevel_tools.h +++ b/Marlin/src/lcd/dwin/proui/bedlevel_tools.h @@ -53,7 +53,6 @@ public: static bool goto_mesh_value; static uint8_t mesh_x, mesh_y; static uint8_t tilt_grid; - #if ENABLED(AUTO_BED_LEVELING_UBL) static bool createPlaneFromMesh(); #endif diff --git a/Marlin/src/lcd/dwin/proui/dwin.cpp b/Marlin/src/lcd/dwin/proui/dwin.cpp index 9d404b3690..e5463dd07e 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 @@ -276,6 +277,7 @@ Menu *stepsMenu = nullptr; #if HAS_MESH Menu *meshMenu = nullptr; #if ENABLED(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)); } // @@ -474,9 +476,7 @@ void popupPauseOrStop() { } #endif -// // Draw status line -// void dwinDrawStatusLine(const char *text) { dwinDrawRectangle(1, hmiData.colorStatusBg, 0, STATUS_Y, DWIN_WIDTH, STATUS_Y + 20); if (text) DWINUI::drawCenteredString(hmiData.colorStatusTxt, STATUS_Y + 2, text); @@ -685,7 +685,7 @@ void drawMainMenu() { ICON_Print(); ICON_Prepare(); ICON_Control(); - ICON_AdvSettings(); + ICON_Level(); } void gotoMainMenu() { @@ -1145,7 +1145,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 +1154,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 +1170,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 +1262,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 +1277,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 +1294,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 +1544,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 +1553,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 +1604,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,7 +1896,7 @@ 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(); @@ -1904,6 +1926,10 @@ void dwinSetDataDefaults() { applyLEDColor(); #endif TERN_(HAS_GCODE_PREVIEW, hmiData.enablePreview = true); + #if HAS_BED_PROBE + IF_DISABLED(BD_SENSOR, hmiData.multiple_probing = MULTIPLE_PROBING); + hmiData.zprobeFeed = DEF_Z_PROBE_FEEDRATE_SLOW; + #endif } void dwinCopySettingsTo(char * const buff) { @@ -1929,15 +1955,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 +1969,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 +2022,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 +2071,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 +2127,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 +2148,7 @@ void doCoolDown() { thermalManager.cooldown(); } void setLanguage() { hmiToggleLanguage(); currentMenu = nullptr; // Invalidate menu to full redraw - drawPrepareMenu(); + drawControlMenu(); } bool enableLiveMove = false; @@ -2362,6 +2290,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 +2329,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 +2361,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 +2406,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,18 +2590,20 @@ 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)) + #if DISABLED(PROUI_MESH_EDIT) + // 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 #endif LIMIT(xpos, MESH_MIN_X, MESH_MAX_X); @@ -2740,7 +2845,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 +2938,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); @@ -3164,22 +3256,14 @@ void drawPrepareMenu() { 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 +3271,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); @@ -3244,17 +3333,14 @@ void drawControlMenu() { 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 +3348,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); @@ -3287,16 +3375,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 +3390,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 +3417,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); @@ -3415,6 +3499,10 @@ 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)); + #if ENABLED(PROUI_ITEM_ZFR) + EDIT_ITEM(ICON_ProbeZSpeed, MSG_Z_FEED_RATE, onDrawPIntMenu, setProbeZSpeed, &hmiData.zprobeFeed); + #endif #if ENABLED(BLTOUCH) MENU_ITEM(ICON_ProbeStow, MSG_MANUAL_STOW, onDrawMenuItem, probeStow); MENU_ITEM(ICON_ProbeDeploy, MSG_MANUAL_DEPLOY, onDrawMenuItem, probeDeploy); @@ -3432,40 +3520,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); } @@ -3483,7 +3543,7 @@ void drawFilSetMenu() { ); 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 @@ -3529,8 +3589,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, &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, &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 +3739,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 +3756,17 @@ void drawMotionMenu() { checkkey = ID_Menu; if (SET_MENU_R(motionMenu, selrect({1, 16, 28, 13}), MSG_MOTION, items)) { BACK_ITEM(drawControlMenu); + #if HAS_FLOW_EDIT + EDIT_ITEM(ICON_Flow, MSG_FLOW, onDrawPIntMenu, setFlow, &planner.flow_percentage[0]); + #endif + #if HAS_FEEDRATE_EDIT + EDIT_ITEM(ICON_Speed, MSG_SPEED, onDrawPIntMenu, setSpeed, &feedrate_percentage); + #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,26 +3794,53 @@ 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, &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) @@ -3753,15 +3853,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); @@ -3837,6 +3938,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 +4116,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 +4159,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 +4182,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(active_extruder, Temperature::MPCTuningType::AUTO); }); #endif @@ -4305,128 +4417,106 @@ 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(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 ENABLED(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) + 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() { + hmiData.mesh_min_x = 0; + hmiData.mesh_max_x = X_BED_SIZE; + hmiData.mesh_min_y = 0; + hmiData.mesh_max_y = Y_BED_SIZE; + resetMeshInset(); + redrawMenu(); + } + + void centerMeshArea() { + float max = (MESH_MIN_X + MESH_MIN_Y) * 0.5; + if (max < X_BED_SIZE - MESH_MAX_X) { max = X_BED_SIZE - MESH_MAX_X; } + if (max < MESH_MIN_Y) { max = MESH_MIN_Y; } + if (max < Y_BED_SIZE - MESH_MAX_Y) { max = Y_BED_SIZE - MESH_MAX_Y; } + hmiData.mesh_min_x = max; + hmiData.mesh_max_x = X_BED_SIZE - max; + hmiData.mesh_min_y = max; + hmiData.mesh_max_y = 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, &hmiData.mesh_min_x); + EDIT_ITEM(ICON_ProbeMargin, MSG_MESH_MAX_X, onDrawPFloatMenu, setXMeshInset, &hmiData.mesh_max_x); + EDIT_ITEM(ICON_Box, MSG_MESH_MIN_Y, onDrawPFloatMenu, setYMeshInset, &hmiData.mesh_min_y); + EDIT_ITEM(ICON_ProbeMargin, MSG_MESH_MAX_Y, onDrawPFloatMenu, setYMeshInset, &hmiData.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; } + 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, 7)) { 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]); + TERN_(HAS_BED_PROBE, MENU_ITEM(ICON_Probe, MSG_PROBE_WIZARD_PROBING, onDrawMenuItem, bedLevelTools.probeXY);) MENU_ITEM(ICON_SetZOffset, MSG_ZERO_MESH_POINT, onDrawMenuItem, zeroPoint); } updateMenu(editMeshMenu); @@ -4435,4 +4525,53 @@ 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(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 ENABLED(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..beeb5878c4 100644 --- a/Marlin/src/lcd/dwin/proui/dwin.h +++ b/Marlin/src/lcd/dwin/proui/dwin.h @@ -105,72 +105,6 @@ enum processID : uint8_t { #define DWIN_CHINESE 123 #define DWIN_ENGLISH 0 -typedef struct { - // Color settings - uint16_t colorBackground; - uint16_t colorCursor; - uint16_t colorTitleBg; - uint16_t colorTitleTxt; - uint16_t colorText; - uint16_t colorSelected; - uint16_t colorSplitLine; - uint16_t colorHighlight; - uint16_t colorStatusBg; - uint16_t colorStatusTxt; - uint16_t colorPopupBg; - uint16_t colorPopupTxt; - uint16_t colorAlertBg; - uint16_t colorAlertTxt; - uint16_t colorPercentTxt; - uint16_t colorBarfill; - uint16_t colorIndicator; - uint16_t colorCoordinate; - - // Temperatures - #if HAS_PID_HEATING - int16_t pidCycles = DEF_PIDCYCLES; - #if ENABLED(PIDTEMP) - celsius_t hotendPIDT = DEF_HOTENDPIDT; - #endif - #if ENABLED(PIDTEMPBED) - celsius_t bedPIDT = DEF_BEDPIDT; - #endif - #if ENABLED(PIDTEMPCHAMBER) - celsius_t chamberPIDT = DEF_CHAMBERPIDT; - #endif - #endif - #if ENABLED(PREVENT_COLD_EXTRUSION) - celsius_t extMinT = EXTRUDE_MINTEMP; - #endif - #if ENABLED(PREHEAT_BEFORE_LEVELING) - celsius_t bedLevT = LEVELING_BED_TEMP; - #endif - #if ENABLED(BAUD_RATE_GCODE) - bool baud115K = false; - #endif - #if ALL(LCD_BED_TRAMMING, HAS_BED_PROBE) - bool fullManualTramming = false; - #endif - #if ENABLED(PROUI_MEDIASORT) - bool mediaSort = true; - #endif - bool mediaAutoMount = ENABLED(HAS_SD_EXTENDER); - #if ALL(INDIVIDUAL_AXIS_HOMING_SUBMENU, MESH_BED_LEVELING) - uint8_t zAfterHoming = DEF_Z_AFTER_HOMING; - #define Z_POST_CLEARANCE hmiData.zAfterHoming - #endif - #if ALL(LED_CONTROL_MENU, HAS_COLOR_LEDS) - LED1Color_t ledColor = defColorLeds; - #endif - #if HAS_GCODE_PREVIEW - bool enablePreview = true; - #endif -} hmi_data_t; - -extern hmi_data_t hmiData; - -#define EXTUI_EEPROM_DATA_SIZE sizeof(hmi_data_t) - typedef struct { int8_t r, g, b; void set(int8_t _r, int8_t _g, int8_t _b) { r = _r; g = _g; b = _b; } @@ -202,6 +136,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 +160,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 +199,6 @@ void doCoolDown(); void ublMeshSave(); void ublMeshLoad(); #endif -#if DISABLED(HAS_BED_PROBE) - void homeZAndDisable(); -#endif // Other void gotoPrintProcess(); @@ -290,8 +227,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 +275,7 @@ void drawPrintFileMenu(); void drawControlMenu(); void drawAdvancedSettingsMenu(); void drawPrepareMenu(); +void drawLevelMenu(); void drawMoveMenu(); void drawTrammingMenu(); #if HAS_HOME_OFFSET @@ -381,6 +321,7 @@ void drawMaxAccelMenu(); #if HAS_MESH void drawMeshSetMenu(); #if ENABLED(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..154e51a065 100644 --- a/Marlin/src/lcd/dwin/proui/dwin_defines.h +++ b/Marlin/src/lcd/dwin/proui/dwin_defines.h @@ -30,22 +30,12 @@ */ #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 +//#define TJC_DISPLAY // Enable for TJC display +//#define DACAI_DISPLAY // Enable for DACAI display +//#define TITLE_CENTERED // Center Menu Title Text #if defined(__STM32F1__) || defined(STM32F1) #define DASH_REDRAW 1 @@ -115,6 +105,14 @@ /** * ProUI internal feature flags */ +#if HAS_MESH + #define PROUI_MESH_EDIT // Add a menu to edit mesh inset + points + #define Z_OFFSET_MIN -3.0 // (mm) + #define Z_OFFSET_MAX 3.0 // (mm) +#endif +#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 +125,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 +136,143 @@ #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 ENABLED(PROUI_MESH_EDIT) + #ifndef MESH_INSET + #define MESH_INSET 10 + #endif + #ifndef MESH_MIN_X + #define MESH_MIN_X MESH_INSET + #endif + #ifndef MESH_MIN_Y + #define MESH_MIN_Y MESH_INSET + #endif + #ifndef MESH_MAX_X + #define MESH_MAX_X X_BED_SIZE - (MESH_INSET) + #endif + #ifndef MESH_MAX_Y + #define MESH_MAX_Y Y_BED_SIZE - (MESH_INSET) + #endif + constexpr uint16_t DEF_MESH_MIN_X = MESH_MIN_X; + constexpr uint16_t DEF_MESH_MAX_X = MESH_MAX_X; + constexpr uint16_t DEF_MESH_MIN_Y = MESH_MIN_Y; + constexpr uint16_t DEF_MESH_MAX_Y = MESH_MAX_Y; + #define MIN_MESH_INSET 0 + #define MAX_MESH_INSET X_BED_SIZE +#endif + +#ifndef MULTIPLE_PROBING + #define MULTIPLE_PROBING 0 +#endif + +#if HAS_BED_PROBE + constexpr uint16_t DEF_Z_PROBE_FEEDRATE_SLOW = Z_PROBE_FEEDRATE_SLOW; +#endif + +#if HAS_EXTRUDERS + constexpr bool DEF_INVERT_E0_DIR = INVERT_E0_DIR; +#endif + +typedef struct { + // Color settings + uint16_t colorBackground; + uint16_t colorCursor; + uint16_t colorTitleBg; + uint16_t colorTitleTxt; + uint16_t colorText; + uint16_t colorSelected; + uint16_t colorSplitLine; + uint16_t colorHighlight; + uint16_t colorStatusBg; + uint16_t colorStatusTxt; + uint16_t colorPopupBg; + uint16_t colorPopupTxt; + uint16_t colorAlertBg; + uint16_t colorAlertTxt; + uint16_t colorPercentTxt; + uint16_t colorBarfill; + uint16_t colorIndicator; + uint16_t colorCoordinate; + + // Temperatures + #if ANY(PIDTEMP, PIDTEMPBED, PIDTEMPCHAMBER) + int16_t pidCycles = DEF_PIDCYCLES; + #endif + #if ENABLED(PIDTEMP) + celsius_t hotendPIDT = DEF_HOTENDPIDT; + #endif + #if ENABLED(PIDTEMPBED) + celsius_t bedPIDT = DEF_BEDPIDT; + #endif + #if ENABLED(PIDTEMPCHAMBER) + celsius_t chamberPIDT = DEF_CHAMBERPIDT; + #endif + #if ENABLED(PREVENT_COLD_EXTRUSION) + celsius_t extMinT = EXTRUDE_MINTEMP; + #endif + #if ENABLED(PREHEAT_BEFORE_LEVELING) + celsius_t bedLevT = LEVELING_BED_TEMP; + #endif + + // Various Options + #if ENABLED(BAUD_RATE_GCODE) + bool baud115K = false; + #endif + #if ALL(LCD_BED_TRAMMING, HAS_BED_PROBE) + bool fullManualTramming = false; + #endif + #if ENABLED(PROUI_MEDIASORT) + bool mediaSort = true; + #endif + bool mediaAutoMount = ENABLED(HAS_SD_EXTENDER); + #if ALL(INDIVIDUAL_AXIS_HOMING_SUBMENU, MESH_BED_LEVELING) + uint8_t zAfterHoming = DEF_Z_AFTER_HOMING; + #define Z_POST_CLEARANCE hmiData.zAfterHoming + #endif + #if ALL(LED_CONTROL_MENU, HAS_COLOR_LEDS) + LED1Color_t ledColor = defColorLeds; + #endif + #if HAS_GCODE_PREVIEW + bool enablePreview = true; + #endif + #if ENABLED(PROUI_MESH_EDIT) + float mesh_min_x = DEF_MESH_MIN_X; + float mesh_max_x = DEF_MESH_MAX_X; + float mesh_min_y = DEF_MESH_MIN_Y; + float mesh_max_y = DEF_MESH_MAX_Y; + #endif + #if HAS_BED_PROBE + IF_DISABLED(BD_SENSOR, uint8_t multiple_probing = MULTIPLE_PROBING); + uint16_t zprobeFeed = DEF_Z_PROBE_FEEDRATE_SLOW; + #endif + #if HAS_EXTRUDERS + bool Invert_E0 = DEF_INVERT_E0_DIR; + #endif +} hmi_data_t; + +extern hmi_data_t hmiData; + +#define EXTUI_EEPROM_DATA_SIZE sizeof(hmi_data_t) + +// ProUI extra feature redefines +#if ENABLED(PROUI_MESH_EDIT) + #undef MESH_MIN_X + #undef MESH_MAX_X + #undef MESH_MIN_Y + #undef MESH_MAX_Y + #define MESH_MIN_X hmiData.mesh_min_x + #define MESH_MAX_X hmiData.mesh_max_x + #define MESH_MIN_Y hmiData.mesh_min_y + #define MESH_MAX_Y hmiData.mesh_max_y +#endif + +#if HAS_BED_PROBE + #undef Z_PROBE_FEEDRATE_SLOW + #define Z_PROBE_FEEDRATE_SLOW hmiData.zprobeFeed +#endif + +#if HAS_EXTRUDERS + #undef INVERT_E0_DIR + #define INVERT_E0_DIR hmiData.Invert_E0 +#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.h b/Marlin/src/lcd/dwin/proui/dwinui.h index 0c98fc0d92..36a0909418 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 @@ -209,6 +208,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}; diff --git a/Marlin/src/lcd/dwin/proui/gcode_preview.cpp b/Marlin/src/lcd/dwin/proui/gcode_preview.cpp index ddd73d72b5..0265a89d22 100644 --- a/Marlin/src/lcd/dwin/proui/gcode_preview.cpp +++ b/Marlin/src/lcd/dwin/proui/gcode_preview.cpp @@ -29,57 +29,42 @@ #include "../../../inc/MarlinConfigPre.h" -#if ENABLED(DWIN_LCD_PROUI) - -#include "dwin_defines.h" - -#if HAS_GCODE_PREVIEW +#if ALL(DWIN_LCD_PROUI, HAS_GCODE_PREVIEW) #include "gcode_preview.h" #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 +174,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 +194,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(); } @@ -234,5 +222,4 @@ void Preview::show() { dwinIconShow(xpos, ypos, 0x00); } -#endif // HAS_GCODE_PREVIEW -#endif // DWIN_LCD_PROUI +#endif // DWIN_LCD_PROUI && HAS_GCODE_PREVIEW 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/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..f80ee4c986 100644 --- a/Marlin/src/lcd/dwin/proui/meshviewer.cpp +++ b/Marlin/src/lcd/dwin/proui/meshviewer.cpp @@ -34,7 +34,6 @@ #include "../../../core/types.h" #include "../../marlinui.h" -#include "dwin.h" #include "dwin_popup.h" #include "../../../feature/bedlevel/bedlevel.h" #include "meshviewer.h" @@ -55,8 +54,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,7 +71,7 @@ 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); @@ -84,21 +81,21 @@ void MeshViewer::drawMeshPoint(const uint8_t x, const uint8_t y, const float z) const uint16_t fy = py(y) - 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, px(x) - 2 * fs, fy, 0); + else DWINUI::drawSignedFloat(title.meshfont, 1, 2, px(x) - 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, px(x) - 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, px(x) - 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, px(x) - 2 * fs, fy, msg); } } diff --git a/Marlin/src/lcd/dwin/proui/proui_extui.cpp b/Marlin/src/lcd/dwin/proui/proui_extui.cpp index 9f19d354ad..bf97645651 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/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 8a92482d82..dae4ae6e0e 100644 --- a/Marlin/src/module/motion.cpp +++ b/Marlin/src/module/motion.cpp @@ -1061,7 +1061,7 @@ void do_blocking_move_to(const xyze_pos_t &raw, const feedRate_t fr_mm_s/*=0.0f* * - Execute the move at the probing (or homing) feedrate */ void do_z_clearance(const float zclear, const bool with_probe/*=true*/, const bool lower_allowed/*=false*/) { - UNUSED(with_probe); + IF_DISABLED(HAS_BED_PROBE, UNUSED(with_probe)); float zdest = zclear; TERN_(HAS_BED_PROBE, if (with_probe && probe.offset.z < 0) zdest -= probe.offset.z); NOMORE(zdest, Z_MAX_POS); diff --git a/Marlin/src/module/motion.h b/Marlin/src/module/motion.h index 8050e66448..3079b2fead 100644 --- a/Marlin/src/module/motion.h +++ b/Marlin/src/module/motion.h @@ -68,7 +68,7 @@ extern xyz_pos_t cartes; #endif #ifdef Z_PROBE_FEEDRATE_SLOW - constexpr feedRate_t z_probe_slow_mm_s = MMM_TO_MMS(Z_PROBE_FEEDRATE_SLOW); + TERN(DWIN_LCD_PROUI, const, constexpr) feedRate_t z_probe_slow_mm_s = MMM_TO_MMS(Z_PROBE_FEEDRATE_SLOW); #endif #ifdef Z_PROBE_FEEDRATE_FAST constexpr feedRate_t z_probe_fast_mm_s = MMM_TO_MMS(Z_PROBE_FEEDRATE_FAST); diff --git a/Marlin/src/module/probe.cpp b/Marlin/src/module/probe.cpp index 3a8bb2b6c6..d0aedbe260 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 @@ -777,43 +777,200 @@ bool Probe::probe_down_to_z(const float z, const feedRate_t fr_mm_s) { * * @return The Z position of the bed at the current XY or NAN on error. */ -float Probe::run_z_probe(const bool sanity_check/*=true*/, const float z_min_point/*=Z_PROBE_LOW_POINT*/, const float z_clearance/*=Z_TWEEN_SAFE_CLEARANCE*/) { - DEBUG_SECTION(log_probe, "Probe::run_z_probe", DEBUGGING(LEVELING)); +#if DISABLED(DWIN_LCD_PROUI) - const float zoffs = SUM_TERN(HAS_HOTEND_OFFSET, -offset.z, hotend_offset[active_extruder].z); + float Probe::run_z_probe(const bool sanity_check/*=true*/, const float z_min_point/*=Z_PROBE_LOW_POINT*/, const float z_clearance/*=Z_TWEEN_SAFE_CLEARANCE*/) { + DEBUG_SECTION(log_probe, "Probe::run_z_probe", DEBUGGING(LEVELING)); - auto try_to_probe = [&](PGM_P const plbl, const float z_probe_low_point, const feedRate_t fr_mm_s, const bool scheck) -> bool { - constexpr float error_tolerance = Z_PROBE_ERROR_TOLERANCE; - if (DEBUGGING(LEVELING)) { - DEBUG_ECHOPGM_P(plbl); - DEBUG_ECHOLNPGM("> try_to_probe(..., ", z_probe_low_point, ", ", fr_mm_s, ", ...)"); - } + const float zoffs = SUM_TERN(HAS_HOTEND_OFFSET, -offset.z, hotend_offset[active_extruder].z); - // Tare the probe, if supported - if (TERN0(PROBE_TARE, tare())) return true; - - // Do a first probe at the fast speed - const bool probe_fail = probe_down_to_z(z_probe_low_point, fr_mm_s), // No probe trigger? - early_fail = (scheck && current_position.z > zoffs + error_tolerance); // Probe triggered too high? - #if ENABLED(DEBUG_LEVELING_FEATURE) - if (DEBUGGING(LEVELING) && (probe_fail || early_fail)) { - DEBUG_ECHOPGM(" Probe fail! - "); - if (probe_fail) DEBUG_ECHOLNPGM("No trigger."); - if (early_fail) DEBUG_ECHOLNPGM("Triggered early (above ", zoffs + error_tolerance, "mm)"); + auto try_to_probe = [&](PGM_P const plbl, const float z_probe_low_point, const feedRate_t fr_mm_s, const bool scheck) -> bool { + constexpr float error_tolerance = Z_PROBE_ERROR_TOLERANCE; + if (DEBUGGING(LEVELING)) { + DEBUG_ECHOPGM_P(plbl); + DEBUG_ECHOLNPGM("> try_to_probe(..., ", z_probe_low_point, ", ", fr_mm_s, ", ...)"); + } + + // Tare the probe, if supported + if (TERN0(PROBE_TARE, tare())) return true; + + // Do a first probe at the fast speed + const bool probe_fail = probe_down_to_z(z_probe_low_point, fr_mm_s), // No probe trigger? + early_fail = (scheck && current_position.z > zoffs + error_tolerance); // Probe triggered too high? + #if ENABLED(DEBUG_LEVELING_FEATURE) + if (DEBUGGING(LEVELING) && (probe_fail || early_fail)) { + DEBUG_ECHOPGM(" Probe fail! - "); + if (probe_fail) DEBUG_ECHOLNPGM("No trigger."); + if (early_fail) DEBUG_ECHOLNPGM("Triggered early (above ", zoffs + error_tolerance, "mm)"); + } + #else + UNUSED(plbl); + #endif + return probe_fail || early_fail; + }; + + // Stop the probe before it goes too low to prevent damage. + // For known Z probe below the expected trigger point, otherwise -10mm lower. + const float z_probe_low_point = zoffs + z_min_point -float((!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 + + // 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, z_probe_fast_mm_s, sanity_check)) return NAN; + + const float z1 = DIFF_TERN(HAS_DELTA_SENSORLESS_PROBING, current_position.z, largest_sensorless_adj); + if (DEBUGGING(LEVELING)) DEBUG_ECHOLNPGM("1st Probe Z:", z1); + + // Raise to give the probe clearance + 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 (current_position.z > z) { + // Probe down fast. If the probe never triggered, raise for probe clearance + if (!probe_down_to_z(z, z_probe_fast_mm_s)) + do_z_clearance(z_clearance); } - #else - UNUSED(plbl); #endif - return probe_fail || early_fail; - }; - // Stop the probe before it goes too low to prevent damage. - // For known Z probe below the expected trigger point, otherwise -10mm lower. - const float z_probe_low_point = zoffs + z_min_point -float((!axis_is_trusted(Z_AXIS)) * 10); - if (DEBUGGING(LEVELING)) DEBUG_ECHOLNPGM("Probe Low Point: ", z_probe_low_point); + #if EXTRA_PROBING > 0 + float probes[TOTAL_PROBING]; + #endif - // Double-probing does a fast probe followed by a slow probe - #if TOTAL_PROBING == 2 + #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, MMM_TO_MMS(Z_PROBE_FEEDRATE_SLOW), sanity_check)) return NAN; + + TERN_(MEASURE_BACKLASH_WHEN_PROBING, backlash.measure_with_probe()); + + const float z = DIFF_TERN(HAS_DELTA_SENSORLESS_PROBING, current_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 + ) 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, current_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 = current_position.z; + + #endif + + return DIFF_TERN(HAS_HOTEND_OFFSET, measured_z, hotend_offset[active_extruder].z); + } + +#else // if DWIN_LCD_PROUI + + float Probe::run_z_probe(const bool sanity_check/*=true*/, const float z_min_point/*=Z_PROBE_LOW_POINT*/, const float z_clearance/*=Z_TWEEN_SAFE_CLEARANCE*/) { + DEBUG_SECTION(log_probe, "Probe::run_z_probe", DEBUGGING(LEVELING)); + + const float zoffs = SUM_TERN(HAS_HOTEND_OFFSET, -offset.z, hotend_offset[active_extruder].z); + + auto try_to_probe = [&](PGM_P const plbl, const float z_probe_low_point, const feedRate_t fr_mm_s, const bool scheck) -> bool { + constexpr float error_tolerance = Z_PROBE_ERROR_TOLERANCE; + if (DEBUGGING(LEVELING)) { + DEBUG_ECHOPGM_P(plbl); + DEBUG_ECHOLNPGM("> try_to_probe(..., ", z_probe_low_point, ", ", fr_mm_s, ", ...)"); + } + + // Tare the probe, if supported + if (TERN0(PROBE_TARE, tare())) return true; + + // Do a first probe at the fast speed + const bool probe_fail = probe_down_to_z(z_probe_low_point, fr_mm_s), // No probe trigger? + early_fail = (scheck && current_position.z > zoffs + error_tolerance); // Probe triggered too high? + #if ENABLED(DEBUG_LEVELING_FEATURE) + if (DEBUGGING(LEVELING) && (probe_fail || early_fail)) { + DEBUG_ECHOPGM(" Probe fail! - "); + if (probe_fail) DEBUG_ECHOLNPGM("No trigger."); + if (early_fail) DEBUG_ECHOLNPGM("Triggered early (above ", zoffs + error_tolerance, "mm)"); + } + #else + UNUSED(plbl); + #endif + return probe_fail || early_fail; + }; + + // Stop the probe before it goes too low to prevent damage. + // For known Z probe below the expected trigger point, otherwise -10mm lower. + const float z_probe_low_point = zoffs + z_min_point - float((!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 // Attempt to tare the probe if (TERN0(PROBE_TARE, tare())) return NAN; @@ -827,33 +984,8 @@ float Probe::run_z_probe(const bool sanity_check/*=true*/, const float z_min_poi // Raise to give the probe clearance 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 (current_position.z > z) { - // Probe down fast. If the probe never triggered, raise for probe clearance - if (!probe_down_to_z(z, z_probe_fast_mm_s)) - 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,72 +996,19 @@ 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, current_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 - ) do_z_clearance(z + (Z_CLEARANCE_MULTI_PROBE), false); - #endif + probes_z_sum += z; + // Small Z raise after probe + 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, current_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 DIFF_TERN(HAS_HOTEND_OFFSET, measured_z, hotend_offset[active_extruder].z); + } - // Return the single probe result - const float measured_z = current_position.z; - - #endif - - return DIFF_TERN(HAS_HOTEND_OFFSET, measured_z, hotend_offset[active_extruder].z); -} +#endif // !DWIN_LCD_PROUI #if DO_TOOLCHANGE_FOR_PROBING diff --git a/buildroot/tests/STM32F103RE_creality b/buildroot/tests/STM32F103RE_creality index 45821598e0..fe6a1f8399 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 +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