diff --git a/Marlin/src/feature/bedlevel/ubl/ubl_G29.cpp b/Marlin/src/feature/bedlevel/ubl/ubl_G29.cpp
index 217d894543..940b4eaeb4 100644
--- a/Marlin/src/feature/bedlevel/ubl/ubl_G29.cpp
+++ b/Marlin/src/feature/bedlevel/ubl/ubl_G29.cpp
@@ -776,12 +776,16 @@
: find_closest_mesh_point_of_type(INVALID, near, true);
if (best.pos.x >= 0) { // mesh point found and is reachable by probe
+ #if ENABLED(EXTENSIBLE_UI)
+ ExtUI::onMeshUpdate(best.pos, ExtUI::PROBE_START);
+ #endif
const float measured_z = probe.probe_at_point(
best.meshpos(),
stow_probe ? PROBE_PT_STOW : PROBE_PT_RAISE, g29_verbose_level
);
z_values[best.pos.x][best.pos.y] = measured_z;
#if ENABLED(EXTENSIBLE_UI)
+ ExtUI::onMeshUpdate(best.pos, ExtUI::PROBE_FINISH);
ExtUI::onMeshUpdate(best.pos, measured_z);
#endif
}
diff --git a/Marlin/src/feature/pause.cpp b/Marlin/src/feature/pause.cpp
index 9c615b6ff8..23fa2fee01 100644
--- a/Marlin/src/feature/pause.cpp
+++ b/Marlin/src/feature/pause.cpp
@@ -499,10 +499,10 @@ void wait_for_confirmation(const bool is_reload/*=false*/, const int8_t max_beep
// Wait for filament insert by user and press button
KEEPALIVE_STATE(PAUSED_FOR_USER);
#if ENABLED(HOST_PROMPT_SUPPORT)
- host_prompt_do(PROMPT_USER_CONTINUE, PSTR("Nozzle Parked"), CONTINUE_STR);
+ host_prompt_do(PROMPT_USER_CONTINUE, GET_TEXT(MSG_NOZZLE_PARKED), CONTINUE_STR);
#endif
#if ENABLED(EXTENSIBLE_UI)
- ExtUI::onUserConfirmRequired_P(PSTR("Nozzle Parked"));
+ ExtUI::onUserConfirmRequired_P(GET_TEXT(MSG_NOZZLE_PARKED));
#endif
wait_for_user = true; // LCD click or M108 will clear this
while (wait_for_user) {
@@ -523,20 +523,20 @@ void wait_for_confirmation(const bool is_reload/*=false*/, const int8_t max_beep
SERIAL_ECHO_MSG(_PMSG(STR_FILAMENT_CHANGE_HEAT));
#if ENABLED(HOST_PROMPT_SUPPORT)
- host_prompt_do(PROMPT_USER_CONTINUE, PSTR("HeaterTimeout"), PSTR("Reheat"));
+ host_prompt_do(PROMPT_USER_CONTINUE, GET_TEXT(MSG_HEATER_TIMEOUT), GET_TEXT(MSG_REHEAT));
#endif
#if ENABLED(EXTENSIBLE_UI)
- ExtUI::onUserConfirmRequired_P(PSTR("HeaterTimeout"));
+ ExtUI::onUserConfirmRequired_P(GET_TEXT(MSG_HEATER_TIMEOUT));
#endif
wait_for_user_response(0, true); // Wait for LCD click or M108
#if ENABLED(HOST_PROMPT_SUPPORT)
- host_prompt_do(PROMPT_INFO, PSTR("Reheating"));
+ host_prompt_do(PROMPT_INFO, GET_TEXT(MSG_REHEATING));
#endif
#if ENABLED(EXTENSIBLE_UI)
- ExtUI::onStatusChanged(PSTR("Reheating..."));
+ ExtUI::onStatusChanged(GET_TEXT(MSG_REHEATING));
#endif
// Re-enable the heaters if they timed out
diff --git a/Marlin/src/lcd/extui/lib/ftdi_eve_touch_ui/marlin_events.cpp b/Marlin/src/lcd/extui/lib/ftdi_eve_touch_ui/marlin_events.cpp
index bed32cc606..9271f2a0cd 100644
--- a/Marlin/src/lcd/extui/lib/ftdi_eve_touch_ui/marlin_events.cpp
+++ b/Marlin/src/lcd/extui/lib/ftdi_eve_touch_ui/marlin_events.cpp
@@ -127,7 +127,12 @@ namespace ExtUI {
}
#if HAS_LEVELING && HAS_MESH
- void onMeshUpdate(const int8_t, const int8_t, const float) {
+ void onMeshUpdate(const int8_t x, const int8_t y, const float val) {
+ BedMeshScreen::onMeshUpdate(x, y, val);
+ }
+
+ void onMeshUpdate(const int8_t x, const int8_t y, const ExtUI::probe_state_t state) {
+ BedMeshScreen::onMeshUpdate(x, y, state);
}
#endif
diff --git a/Marlin/src/lcd/extui/lib/ftdi_eve_touch_ui/screens/bed_mesh_screen.cpp b/Marlin/src/lcd/extui/lib/ftdi_eve_touch_ui/screens/bed_mesh_screen.cpp
new file mode 100644
index 0000000000..bce39a6ec0
--- /dev/null
+++ b/Marlin/src/lcd/extui/lib/ftdi_eve_touch_ui/screens/bed_mesh_screen.cpp
@@ -0,0 +1,268 @@
+/***********************
+ * bed_mesh_screen.cpp *
+ ***********************/
+
+/****************************************************************************
+ * Written By Marcio Teixeira 2020 *
+ * *
+ * This program is free software: you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation, either version 3 of the License, or *
+ * (at your option) any later version. *
+ * *
+ * This program is distributed in the hope that it will be useful, *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+ * GNU General Public License for more details. *
+ * *
+ * To view a copy of the GNU General Public License, go to the following *
+ * location: . *
+ ****************************************************************************/
+
+#include "../config.h"
+
+#if ENABLED(TOUCH_UI_FTDI_EVE) && HAS_MESH
+
+#include "screens.h"
+#include "screen_data.h"
+
+using namespace FTDI;
+using namespace Theme;
+using namespace ExtUI;
+
+#ifdef TOUCH_UI_PORTRAIT
+ #define GRID_COLS 2
+ #define GRID_ROWS 10
+
+ #define MESH_POS BTN_POS(1, 2), BTN_SIZE(2,5)
+ #define Z_LABEL_POS BTN_POS(1, 8), BTN_SIZE(1,1)
+ #define Z_VALUE_POS BTN_POS(2, 8), BTN_SIZE(1,1)
+ #define WAIT_POS BTN_POS(1, 8), BTN_SIZE(2,1)
+ #define BACK_POS BTN_POS(1,10), BTN_SIZE(2,1)
+#else
+ #define GRID_COLS 5
+ #define GRID_ROWS 5
+
+ #define MESH_POS BTN_POS(2,1), BTN_SIZE(4,5)
+ #define Z_LABEL_POS BTN_POS(1,3), BTN_SIZE(1,1)
+ #define Z_VALUE_POS BTN_POS(1,4), BTN_SIZE(2,1)
+ #define WAIT_POS BTN_POS(1,3), BTN_SIZE(2,2)
+ #define BACK_POS BTN_POS(1,5), BTN_SIZE(2,1)
+#endif
+
+void BedMeshScreen::drawMesh(int16_t x, int16_t y, int16_t w, int16_t h, ExtUI::bed_mesh_t data, uint8_t opts) {
+ CommandProcessor cmd;
+
+ #define TRANSFORM_2(X,Y,Z) (X), (Y) // No transform
+ #define TRANSFORM_1(X,Y,Z) TRANSFORM_2((X) + (Y) * slant, (Y) - (Z), 0) // Perspective
+ #define TRANSFORM(X,Y,Z) TRANSFORM_1(float(X)/(cols-1) - 0.5, float(Y)/(rows-1) - 0.5, (Z)) // Normalize
+
+ constexpr uint8_t rows = GRID_MAX_POINTS_Y;
+ constexpr uint8_t cols = GRID_MAX_POINTS_X;
+ const float slant = 0.5;
+ const float bounds_min[] = {TRANSFORM(0 ,0 ,0)};
+ const float bounds_max[] = {TRANSFORM(cols,rows,0)};
+ const float scale_x = float(w)/(bounds_max[0] - bounds_min[0]);
+ const float scale_y = float(h)/(bounds_max[1] - bounds_min[1]);
+ const float center_x = x + w/2;
+ const float center_y = y + h/2;
+
+ float val_mean = 0;
+ float val_max = -INFINITY;
+ float val_min = INFINITY;
+ uint8_t val_cnt = 0;
+
+ if (opts & USE_AUTOSCALE) {
+ // Compute the mean
+ for (uint8_t y = 0; y < rows; y++) {
+ for (uint8_t x = 0; x < cols; x++) {
+ const float val = data[x][y];
+ if (!isnan(val)) {
+ val_mean += val;
+ val_max = max(val_max, val);
+ val_min = min(val_min, val);
+ val_cnt++;
+ }
+ }
+ }
+ if (val_cnt) {
+ val_mean /= val_cnt;
+ val_min -= val_mean;
+ val_max -= val_mean;
+ } else {
+ val_mean = 0;
+ val_min = 0;
+ val_max = 0;
+ }
+ }
+
+ const float scale_z = ((val_max == val_min) ? 1 : 1/(val_max - val_min)) * 0.1;
+
+ #undef TRANSFORM_2
+ #define TRANSFORM_2(X,Y,Z) center_x + (X) * scale_x, center_y + (Y) * scale_y // Scale and position
+ #define VALUE(X,Y) ((data && ISVAL(X,Y)) ? data[X][Y] : 0)
+ #define ISVAL(X,Y) (data ? !isnan(data[X][Y]) : true)
+ #define HEIGHT(X,Y) (VALUE(X,Y) * scale_z)
+
+ uint16_t basePointSize = min(scale_x,scale_y) / max(cols,rows);
+
+ cmd.cmd(SAVE_CONTEXT())
+ .cmd(VERTEX_FORMAT(0))
+ .cmd(TAG_MASK(false))
+ .cmd(SAVE_CONTEXT());
+
+ for (uint8_t y = 0; y < rows; y++) {
+ for (uint8_t x = 0; x < cols; x++) {
+ if (ISVAL(x,y)) {
+ const bool hasLeftSegment = x < cols - 1 && ISVAL(x+1,y);
+ const bool hasRightSegment = y < rows - 1 && ISVAL(x,y+1);
+ if (hasLeftSegment || hasRightSegment) {
+ cmd.cmd(BEGIN(LINE_STRIP));
+ if (hasLeftSegment) cmd.cmd(VERTEX2F(TRANSFORM(x + 1, y , HEIGHT(x + 1, y ))));
+ cmd.cmd( VERTEX2F(TRANSFORM(x , y , HEIGHT(x , y ))));
+ if (hasRightSegment) cmd.cmd(VERTEX2F(TRANSFORM(x , y + 1, HEIGHT(x , y + 1))));
+ }
+ }
+ }
+
+ if (opts & USE_POINTS) {
+ cmd.cmd(POINT_SIZE(basePointSize * 2));
+ cmd.cmd(BEGIN(POINTS));
+ for (uint8_t x = 0; x < cols; x++) {
+ if (ISVAL(x,y)) {
+ if (opts & USE_COLORS) {
+ const float val_dev = VALUE(x, y) - val_mean;
+ const uint8_t neg_byte = sq(val_dev) / sq(val_dev < 0 ? val_min : val_max) * 0xFF;
+ const uint8_t pos_byte = 255 - neg_byte;
+ cmd.cmd(COLOR_RGB(pos_byte, pos_byte, 0xFF));
+ }
+ cmd.cmd(VERTEX2F(TRANSFORM(x, y, HEIGHT(x, y))));
+ }
+ }
+ if (opts & USE_COLORS) {
+ cmd.cmd(RESTORE_CONTEXT())
+ .cmd(SAVE_CONTEXT());
+ }
+ }
+ }
+ cmd.cmd(RESTORE_CONTEXT())
+ .cmd(TAG_MASK(true));
+
+ if (opts & USE_TAGS) {
+ cmd.cmd(COLOR_MASK(false, false, false, false))
+ .cmd(POINT_SIZE(basePointSize * 10))
+ .cmd(BEGIN(POINTS));
+ for (uint8_t y = 0; y < rows; y++) {
+ for (uint8_t x = 0; x < cols; x++) {
+ const uint8_t tag = pointToTag(x, y);
+ cmd.tag(tag).cmd(VERTEX2F(TRANSFORM(x, y, HEIGHT(x, y))));
+ }
+ }
+ cmd.cmd(COLOR_MASK(true, true, true, true));
+ }
+
+ if (opts & USE_HIGHLIGHT) {
+ const uint8_t tag = screen_data.BedMeshScreen.highlightedTag;
+ uint8_t x, y;
+ tagToPoint(tag, x, y);
+ cmd.cmd(COLOR_A(128))
+ .cmd(POINT_SIZE(basePointSize * 6))
+ .cmd(BEGIN(POINTS))
+ .tag(tag).cmd(VERTEX2F(TRANSFORM(x, y, HEIGHT(x, y))));
+ }
+ cmd.cmd(END());
+ cmd.cmd(RESTORE_CONTEXT());
+}
+
+uint8_t BedMeshScreen::pointToTag(uint8_t x, uint8_t y) {
+ return y * (GRID_MAX_POINTS_X) + x + 10;
+}
+
+void BedMeshScreen::tagToPoint(uint8_t tag, uint8_t &x, uint8_t &y) {
+ x = (tag - 10) % (GRID_MAX_POINTS_X);
+ y = (tag - 10) / (GRID_MAX_POINTS_X);
+}
+
+void BedMeshScreen::onEntry() {
+ screen_data.BedMeshScreen.highlightedTag = 0;
+ screen_data.BedMeshScreen.count = 0;
+ BaseScreen::onEntry();
+}
+
+float BedMeshScreen::getHightlightedValue() {
+ if (screen_data.BedMeshScreen.highlightedTag) {
+ xy_uint8_t pt;
+ tagToPoint(screen_data.BedMeshScreen.highlightedTag, pt.x, pt.y);
+ return ExtUI::getMeshPoint(pt);
+ }
+ return NAN;
+}
+
+void BedMeshScreen::drawHighlightedPointValue() {
+ char str[16];
+ const float val = getHightlightedValue();
+ const bool isGood = !isnan(val);
+ if (isGood)
+ dtostrf(val, 5, 3, str);
+ else
+ strcpy_P(str, PSTR("-"));
+
+ CommandProcessor cmd;
+ cmd.font(Theme::font_medium)
+ .text(Z_LABEL_POS, GET_TEXT_F(MSG_MESH_EDIT_Z))
+ .text(Z_VALUE_POS, str)
+ .colors(action_btn)
+ .tag(1).button( BACK_POS, GET_TEXT_F(MSG_BACK))
+ .tag(0);
+}
+
+void BedMeshScreen::onRedraw(draw_mode_t what) {
+ if (what & BACKGROUND) {
+ CommandProcessor cmd;
+ cmd.cmd(CLEAR_COLOR_RGB(bg_color))
+ .cmd(CLEAR(true,true,true));
+
+ // Draw the shadow and tags
+ cmd.cmd(COLOR_RGB(0x444444));
+ BedMeshScreen::drawMesh(MESH_POS, nullptr, USE_POINTS | USE_TAGS);
+ cmd.cmd(COLOR_RGB(bg_text_enabled));
+ }
+
+ if (what & FOREGROUND) {
+ const bool levelingFinished = screen_data.BedMeshScreen.count >= GRID_MAX_POINTS;
+ if (levelingFinished) drawHighlightedPointValue();
+
+ BedMeshScreen::drawMesh(MESH_POS, ExtUI::getMeshArray(),
+ USE_POINTS | USE_HIGHLIGHT | USE_AUTOSCALE | (levelingFinished ? USE_COLORS : 0));
+ }
+}
+
+bool BedMeshScreen::onTouchStart(uint8_t tag) {
+ screen_data.BedMeshScreen.highlightedTag = tag;
+ return true;
+}
+
+bool BedMeshScreen::onTouchEnd(uint8_t tag) {
+ switch(tag) {
+ case 1:
+ GOTO_PREVIOUS();
+ return true;
+ default:
+ return false;
+ }
+}
+
+void BedMeshScreen::onMeshUpdate(const int8_t, const int8_t, const float) {
+ if (AT_SCREEN(BedMeshScreen))
+ onRefresh();
+}
+
+void BedMeshScreen::onMeshUpdate(const int8_t x, const int8_t y, const ExtUI::probe_state_t state) {
+ if (state == ExtUI::PROBE_FINISH) {
+ screen_data.BedMeshScreen.highlightedTag = pointToTag(x, y);
+ screen_data.BedMeshScreen.count++;
+ }
+ BedMeshScreen::onMeshUpdate(x, y, 0);
+}
+
+#endif // TOUCH_UI_FTDI_EVE
diff --git a/Marlin/src/lcd/extui/lib/ftdi_eve_touch_ui/screens/main_menu.cpp b/Marlin/src/lcd/extui/lib/ftdi_eve_touch_ui/screens/main_menu.cpp
index 5d165edef0..5a81a48257 100644
--- a/Marlin/src/lcd/extui/lib/ftdi_eve_touch_ui/screens/main_menu.cpp
+++ b/Marlin/src/lcd/extui/lib/ftdi_eve_touch_ui/screens/main_menu.cpp
@@ -146,14 +146,18 @@ bool MainMenu::onTouchEnd(uint8_t tag) {
#ifdef AXIS_LEVELING_COMMANDS
case 9: SpinnerDialogBox::enqueueAndWait_P(F(AXIS_LEVELING_COMMANDS)); break;
#endif
- #ifdef HAS_LEVELING
- case 10: SpinnerDialogBox::enqueueAndWait_P(F(
- #ifdef BED_LEVELING_COMMANDS
- BED_LEVELING_COMMANDS
- #else
- "G29"
- #endif
- )); break;
+ #if HAS_LEVELING
+ case 10:
+ #ifndef BED_LEVELING_COMMANDS
+ #define BED_LEVELING_COMMANDS "G29"
+ #endif
+ #if HAS_MESH
+ GOTO_SCREEN(BedMeshScreen);
+ injectCommands_P(PSTR(BED_LEVELING_COMMANDS));
+ #else
+ SpinnerDialogBox::enqueueAndWait_P(F(BED_LEVELING_COMMANDS));
+ #endif
+ break;
#endif
case 11: GOTO_SCREEN(AboutScreen); break;
default:
diff --git a/Marlin/src/lcd/extui/lib/ftdi_eve_touch_ui/screens/screen_data.h b/Marlin/src/lcd/extui/lib/ftdi_eve_touch_ui/screens/screen_data.h
index 6e2cb97a98..a0bc60d488 100644
--- a/Marlin/src/lcd/extui/lib/ftdi_eve_touch_ui/screens/screen_data.h
+++ b/Marlin/src/lcd/extui/lib/ftdi_eve_touch_ui/screens/screen_data.h
@@ -60,6 +60,12 @@ union screen_data_t {
struct base_numeric_adjustment_t placeholder;
float e_rel[ExtUI::extruderCount];
} MoveAxisScreen;
+#if HAS_MESH
+ struct {
+ uint8_t count;
+ uint8_t highlightedTag;
+ } BedMeshScreen;
+#endif
#if ENABLED(TOUCH_UI_DEVELOPER_MENU)
struct {
uint32_t next_watchdog_trigger;
diff --git a/Marlin/src/lcd/extui/lib/ftdi_eve_touch_ui/screens/screens.cpp b/Marlin/src/lcd/extui/lib/ftdi_eve_touch_ui/screens/screens.cpp
index ce75462040..5f59843bbe 100644
--- a/Marlin/src/lcd/extui/lib/ftdi_eve_touch_ui/screens/screens.cpp
+++ b/Marlin/src/lcd/extui/lib/ftdi_eve_touch_ui/screens/screens.cpp
@@ -55,6 +55,9 @@ SCREEN_TABLE {
#endif
#if ENABLED(BABYSTEPPING)
DECL_SCREEN(NudgeNozzleScreen),
+#endif
+#if HAS_MESH
+ DECL_SCREEN(BedMeshScreen),
#endif
DECL_SCREEN(MoveAxisScreen),
DECL_SCREEN(StepsScreen),
diff --git a/Marlin/src/lcd/extui/lib/ftdi_eve_touch_ui/screens/screens.h b/Marlin/src/lcd/extui/lib/ftdi_eve_touch_ui/screens/screens.h
index 346d122a0f..8fa4800d6a 100644
--- a/Marlin/src/lcd/extui/lib/ftdi_eve_touch_ui/screens/screens.h
+++ b/Marlin/src/lcd/extui/lib/ftdi_eve_touch_ui/screens/screens.h
@@ -55,6 +55,9 @@ enum {
MAX_VELOCITY_SCREEN_CACHE,
MAX_ACCELERATION_SCREEN_CACHE,
DEFAULT_ACCELERATION_SCREEN_CACHE,
+#if HAS_MESH
+ BED_MESH_SCREEN_CACHE,
+#endif
#if DISABLED(CLASSIC_JERK)
JUNC_DEV_SCREEN_CACHE,
#else
@@ -130,6 +133,33 @@ class AboutScreen : public BaseScreen, public UncachedScreen {
static bool onTouchEnd(uint8_t tag);
};
+#if HAS_MESH
+class BedMeshScreen : public BaseScreen, public CachedScreen {
+ private:
+ enum MeshOpts {
+ USE_POINTS = 0x01,
+ USE_COLORS = 0x02,
+ USE_TAGS = 0x04,
+ USE_HIGHLIGHT = 0x08,
+ USE_AUTOSCALE = 0x10
+ };
+
+ static uint8_t pointToTag(uint8_t x, uint8_t y);
+ static void tagToPoint(uint8_t tag, uint8_t &x, uint8_t &y);
+ static float getHightlightedValue();
+ static void drawHighlightedPointValue();
+ static void drawMesh(int16_t x, int16_t y, int16_t w, int16_t h, ExtUI::bed_mesh_t data, uint8_t opts);
+
+ public:
+ static void onMeshUpdate(const int8_t x, const int8_t y, const float val);
+ static void onMeshUpdate(const int8_t x, const int8_t y, const ExtUI::probe_state_t);
+ static void onEntry();
+ static void onRedraw(draw_mode_t);
+ static bool onTouchStart(uint8_t tag);
+ static bool onTouchEnd(uint8_t tag);
+};
+#endif
+
#if ENABLED(PRINTCOUNTER)
class StatisticsScreen : public BaseScreen, public UncachedScreen {
public:
diff --git a/Marlin/src/lcd/extui/ui_api.cpp b/Marlin/src/lcd/extui/ui_api.cpp
index 79e12f36d1..a5b1460c90 100644
--- a/Marlin/src/lcd/extui/ui_api.cpp
+++ b/Marlin/src/lcd/extui/ui_api.cpp
@@ -112,6 +112,9 @@ namespace ExtUI {
#if ENABLED(JOYSTICK)
uint8_t jogging : 1;
#endif
+ #if ENABLED(SDSUPPORT)
+ uint8_t was_sd_printing : 1;
+ #endif
} flags;
#ifdef __SAM3X8E__
@@ -1032,11 +1035,18 @@ namespace ExtUI {
}
bool isPrintingFromMedia() {
- return IFSD(card.isFileOpen(), false);
+ #if ENABLED(SDSUPPORT)
+ // Account for when IS_SD_PRINTING() reports the end of the
+ // print when there is still SD card data in the planner.
+ flags.was_sd_printing = card.isFileOpen() || (flags.was_sd_printing && commandsInQueue());
+ return flags.was_sd_printing;
+ #else
+ return false;
+ #endif
}
bool isPrinting() {
- return (planner.movesplanned() || isPrintingFromMedia() || IFSD(IS_SD_PRINTING(), false));
+ return (commandsInQueue() || isPrintingFromMedia() || IFSD(IS_SD_PRINTING(), false));
}
bool isMediaInserted() {
diff --git a/Marlin/src/lcd/extui/ui_api.h b/Marlin/src/lcd/extui/ui_api.h
index 01e0d1b7a3..43e337e877 100644
--- a/Marlin/src/lcd/extui/ui_api.h
+++ b/Marlin/src/lcd/extui/ui_api.h
@@ -141,6 +141,10 @@ namespace ExtUI {
void setMeshPoint(const xy_uint8_t &pos, const float zval);
void onMeshUpdate(const int8_t xpos, const int8_t ypos, const float zval);
inline void onMeshUpdate(const xy_int8_t &pos, const float zval) { onMeshUpdate(pos.x, pos.y, zval); }
+
+ typedef enum : unsigned char { PROBE_START, PROBE_FINISH } probe_state_t;
+ void onMeshUpdate(const int8_t xpos, const int8_t ypos, probe_state_t state);
+ inline void onMeshUpdate(const xy_int8_t &pos, probe_state_t state) { onMeshUpdate(pos.x, pos.y, state); }
#endif
#endif
diff --git a/Marlin/src/lcd/extui_dgus_lcd.cpp b/Marlin/src/lcd/extui_dgus_lcd.cpp
index 855d09033e..8880be7ef3 100644
--- a/Marlin/src/lcd/extui_dgus_lcd.cpp
+++ b/Marlin/src/lcd/extui_dgus_lcd.cpp
@@ -122,6 +122,10 @@ namespace ExtUI {
// Called when any mesh points are updated
}
+ void onMeshUpdate(const int8_t xpos, const int8_t ypos, const ExtUI::probe_state_t state) {
+ // Called to indicate a special condition
+ }
+
#if ENABLED(POWER_LOSS_RECOVERY)
void onPowerLossResume() {
// Called on resume from power-loss
diff --git a/Marlin/src/lcd/extui_example.cpp b/Marlin/src/lcd/extui_example.cpp
index 5c9a193ded..900afdea04 100644
--- a/Marlin/src/lcd/extui_example.cpp
+++ b/Marlin/src/lcd/extui_example.cpp
@@ -93,6 +93,10 @@ namespace ExtUI {
// Called when any mesh points are updated
}
+ void onMeshUpdate(const int8_t xpos, const int8_t ypos, const ExtUI::probe_state_t state) {
+ // Called to indicate a special condition
+ }
+
#if ENABLED(POWER_LOSS_RECOVERY)
void onPowerLossResume() {
// Called on resume from power-loss
diff --git a/Marlin/src/lcd/language/language_en.h b/Marlin/src/lcd/language/language_en.h
index a52d9652ac..79a6f814b2 100644
--- a/Marlin/src/lcd/language/language_en.h
+++ b/Marlin/src/lcd/language/language_en.h
@@ -240,6 +240,8 @@ namespace Language_en {
PROGMEM Language_Str MSG_BED_Z = _UxGT("Bed Z");
PROGMEM Language_Str MSG_NOZZLE = _UxGT("Nozzle");
PROGMEM Language_Str MSG_NOZZLE_N = _UxGT("Nozzle ~");
+ PROGMEM Language_Str MSG_NOZZLE_PARKED = _UxGT("Nozzle Parked");
+ PROGMEM Language_Str MSG_NOZZLE_STANDBY = _UxGT("Nozzle Standby");
PROGMEM Language_Str MSG_BED = _UxGT("Bed");
PROGMEM Language_Str MSG_CHAMBER = _UxGT("Enclosure");
PROGMEM Language_Str MSG_FAN_SPEED = _UxGT("Fan Speed");
@@ -371,7 +373,6 @@ namespace Language_en {
PROGMEM Language_Str MSG_TOOL_CHANGE_ZLIFT = _UxGT("Z Raise");
PROGMEM Language_Str MSG_SINGLENOZZLE_PRIME_SPD = _UxGT("Prime Speed");
PROGMEM Language_Str MSG_SINGLENOZZLE_RETRACT_SPD = _UxGT("Retract Speed");
- PROGMEM Language_Str MSG_NOZZLE_STANDBY = _UxGT("Nozzle Standby");
PROGMEM Language_Str MSG_FILAMENTCHANGE = _UxGT("Change Filament");
PROGMEM Language_Str MSG_FILAMENTCHANGE_E = _UxGT("Change Filament *");
PROGMEM Language_Str MSG_FILAMENTLOAD = _UxGT("Load Filament");
@@ -605,6 +606,9 @@ namespace Language_en {
PROGMEM Language_Str MSG_LEVEL_X_AXIS = _UxGT("Level X Axis");
PROGMEM Language_Str MSG_AUTO_CALIBRATE = _UxGT("Auto Calibrate");
+ PROGMEM Language_Str MSG_HEATER_TIMEOUT = _UxGT("Heater Timeout");
+ PROGMEM Language_Str MSG_REHEAT = _UxGT("Reheat");
+ PROGMEM Language_Str MSG_REHEATING = _UxGT("Reheating...");
}
#if FAN_COUNT == 1