🚸 ProUI APRIL2022 updates (#24084)

This commit is contained in:
Scott Lahteine 2022-05-17 15:05:25 -05:00
parent 8351b1431f
commit 268a16b1ef
24 changed files with 1644 additions and 990 deletions

View File

@ -883,7 +883,7 @@ void kill(FSTR_P const lcd_error/*=nullptr*/, FSTR_P const lcd_component/*=nullp
// Echo the LCD message to serial for extra context
if (lcd_error) { SERIAL_ECHO_START(); SERIAL_ECHOLNF(lcd_error); }
#if EITHER(HAS_DISPLAY, DWIN_LCD_PROUI)
#if HAS_DISPLAY
ui.kill_screen(lcd_error ?: GET_TEXT_F(MSG_KILLED), lcd_component ?: FPSTR(NUL_STR));
#else
UNUSED(lcd_error); UNUSED(lcd_component);

View File

@ -727,6 +727,7 @@ void unified_bed_leveling::shift_mesh_height() {
TERN_(HAS_MARLINUI_MENU, ui.capture());
TERN_(EXTENSIBLE_UI, ExtUI::onLevelingStart());
TERN_(DWIN_LCD_PROUI, DWIN_LevelingStart());
save_ubl_active_state_and_disable(); // No bed level correction so only raw data is obtained
uint8_t count = GRID_MAX_POINTS;
@ -790,6 +791,7 @@ void unified_bed_leveling::shift_mesh_height() {
);
TERN_(EXTENSIBLE_UI, ExtUI::onLevelingDone());
TERN_(DWIN_LCD_PROUI, DWIN_LevelingDone());
}
#endif // HAS_BED_PROBE

View File

@ -33,6 +33,10 @@
#include "../../feature/probe_temp_comp.h"
#endif
#if ENABLED(DWIN_LCD_PROUI)
#include "../../lcd/marlinui.h"
#endif
/**
* G30: Do a single Z probe at the current XY
*
@ -48,20 +52,38 @@ void GcodeSuite::G30() {
const xy_pos_t pos = { parser.linearval('X', current_position.x + probe.offset_xy.x),
parser.linearval('Y', current_position.y + probe.offset_xy.y) };
if (!probe.can_reach(pos)) return;
if (!probe.can_reach(pos)) {
#if ENABLED(DWIN_LCD_PROUI)
SERIAL_ECHOLNF(GET_EN_TEXT_F(MSG_ZPROBE_OUT));
LCD_MESSAGE(MSG_ZPROBE_OUT);
#endif
return;
}
// Disable leveling so the planner won't mess with us
TERN_(HAS_LEVELING, set_bed_leveling_enabled(false));
remember_feedrate_scaling_off();
TERN_(DWIN_LCD_PROUI, process_subcommands_now(F("G28O")));
const ProbePtRaise raise_after = parser.boolval('E', true) ? PROBE_PT_STOW : PROBE_PT_NONE;
TERN_(HAS_PTC, ptc.set_enabled(!parser.seen('C') || parser.value_bool()));
const float measured_z = probe.probe_at_point(pos, raise_after, 1);
TERN_(HAS_PTC, ptc.set_enabled(true));
if (!isnan(measured_z))
if (!isnan(measured_z)) {
SERIAL_ECHOLNPGM("Bed X: ", pos.x, " Y: ", pos.y, " Z: ", measured_z);
#if ENABLED(DWIN_LCD_PROUI)
char msg[31], str_1[6], str_2[6], str_3[6];
sprintf_P(msg, PSTR("X:%s, Y:%s, Z:%s"),
dtostrf(pos.x, 1, 1, str_1),
dtostrf(pos.y, 1, 1, str_2),
dtostrf(measured_z, 1, 2, str_3)
);
ui.set_status(msg);
#endif
}
restore_feedrate_and_scaling();

View File

@ -33,7 +33,7 @@ void GcodeSuite::M31() {
char buffer[22];
duration_t(print_job_timer.duration()).toString(buffer);
ui.set_status(buffer);
ui.set_status(buffer, ENABLED(DWIN_LCD_PROUI));
SERIAL_ECHO_MSG("Print time: ", buffer);
}

View File

@ -234,7 +234,9 @@ void DWIN_Frame_AreaMove(uint8_t mode, uint8_t dir, uint16_t dis,
// *string: The string
// rlimit: To limit the drawn string length
void DWIN_Draw_String(bool bShow, uint8_t size, uint16_t color, uint16_t bColor, uint16_t x, uint16_t y, const char * const string, uint16_t rlimit/*=0xFFFF*/) {
#if DISABLED(DWIN_LCD_PROUI)
DWIN_Draw_Rectangle(1, bColor, x, y, x + (fontWidth(size) * strlen_P(string)), y + fontHeight(size));
#endif
constexpr uint8_t widthAdjust = 0;
size_t i = 0;
DWIN_Byte(i, 0x11);

View File

@ -3556,9 +3556,9 @@ void HMI_AdvSet() {
case ADVSET_CASE_HOMEOFF:
checkkey = HomeOff;
select_item.reset();
HMI_ValueStruct.Home_OffX_scaled = home_offset[X_AXIS] * 10;
HMI_ValueStruct.Home_OffY_scaled = home_offset[Y_AXIS] * 10;
HMI_ValueStruct.Home_OffZ_scaled = home_offset[Z_AXIS] * 10;
HMI_ValueStruct.Home_OffX_scaled = home_offset.x * 10;
HMI_ValueStruct.Home_OffY_scaled = home_offset.y * 10;
HMI_ValueStruct.Home_OffZ_scaled = home_offset.z * 10;
Draw_HomeOff_Menu();
break;
#endif

File diff suppressed because it is too large Load Diff

View File

@ -24,8 +24,8 @@
/**
* DWIN Enhanced implementation for PRO UI
* Author: Miguel A. Risco-Castillo (MRISCOC)
* Version: 3.15.2
* Date: 2022/03/01
* Version: 3.17.2
* Date: 2022/04/08
*/
#include "dwin_defines.h"
@ -73,12 +73,13 @@ enum pidresult_t : uint8_t {
typedef struct {
int8_t Color[3]; // Color components
pidresult_t pidresult = PID_DONE;
int8_t Preheat = 0; // Material Select 0: PLA, 1: ABS, 2: Custom
uint8_t Select = 0; // Auxiliary selector variable
AxisEnum axis = X_AXIS; // Axis Select
} HMI_value_t;
typedef struct {
uint8_t language;
bool percent_flag:1; // percent was override by M73
bool remain_flag:1; // remain was override by M73
bool pause_flag:1; // printing is paused
bool pause_action:1; // flag a pause action
@ -103,9 +104,53 @@ extern millis_t dwin_heat_time;
void Popup_PowerLossRecovery();
#endif
// SD Card
void HMI_SDCardInit();
void HMI_SDCardUpdate();
// Tool Functions
#if ENABLED(EEPROM_SETTINGS)
void WriteEeprom();
void ReadEeprom();
void ResetEeprom();
#if HAS_MESH
void SaveMesh();
#endif
#endif
void RebootPrinter();
void DisableMotors();
void AutoLev();
void AutoHome();
#if HAS_PREHEAT
void DoPreheat0();
void DoPreheat1();
void DoPreheat2();
#endif
void DoCoolDown();
#if HAS_HOTEND
void HotendPID();
#endif
#if HAS_HEATED_BED
void BedPID();
#endif
#if ENABLED(BAUD_RATE_GCODE)
void HMI_SetBaudRate();
void SetBaud115K();
void SetBaud250K();
#endif
#if HAS_LCD_BRIGHTNESS
void TurnOffBacklight();
#endif
void ApplyExtMinT();
void ParkHead();
#if HAS_ONESTEP_LEVELING
void Trammingwizard();
#endif
#if BOTH(LED_CONTROL_MENU, HAS_COLOR_LEDS)
void ApplyLEDColor();
#endif
#if ENABLED(AUTO_BED_LEVELING_UBL)
void UBLTiltMesh();
bool UBLValidMesh();
void UBLSaveMesh();
void UBLLoadMesh();
#endif
// Other
void Goto_PrintProcess();
@ -114,29 +159,19 @@ void Goto_Info_Menu();
void Goto_PowerLossRecovery();
void Goto_ConfirmToPrint();
void DWIN_Draw_Dashboard(const bool with_update); // Status Area
void Draw_Main_Area(); // Redraw main area;
void Draw_Main_Area(); // Redraw main area
void DWIN_DrawStatusLine(const char *text); // Draw simple status text
void DWIN_DrawStatusLine(FSTR_P fstr);
void DWIN_RedrawDash(); // Redraw Dash and Status line
void DWIN_RedrawScreen(); // Redraw all screen elements
void HMI_MainMenu(); // Main process screen
void HMI_SelectFile(); // File page
void HMI_Printing(); // Print page
void HMI_ReturnScreen(); // Return to previous screen before popups
void ApplyExtMinT();
void HMI_SetLanguageCache(); // Set the languaje image cache
void RebootPrinter();
#if ENABLED(BAUD_RATE_GCODE)
void HMI_SetBaudRate();
void SetBaud115K();
void SetBaud250K();
#endif
#if ENABLED(EEPROM_SETTINGS)
void WriteEeprom();
void ReadEeprom();
void ResetEeprom();
#endif
void HMI_WaitForUser();
void HMI_SaveProcessID(const uint8_t id);
void HMI_AudioFeedback(const bool success=true);
void HMI_SDCardInit();
void HMI_SDCardUpdate();
void EachMomentUpdate();
void update_variable();
void DWIN_InitScreen();
@ -248,3 +283,12 @@ void Draw_Steps_Menu();
#if ENABLED(INDIVIDUAL_AXIS_HOMING_SUBMENU)
void Draw_Homing_Menu();
#endif
#if ENABLED(FWRETRACT)
void Draw_FWRetract_Menu();
#endif
#if HAS_MESH
void Draw_MeshSet_Menu();
#if ENABLED(MESH_EDIT_MENU)
void Draw_EditMesh_Menu();
#endif
#endif

View File

@ -34,6 +34,23 @@
#include "../../../inc/MarlinConfigPre.h"
#include <stddef.h>
#define HAS_ESDIAG 1
#if defined(__STM32F1__) || defined(STM32F1)
#define DASH_REDRAW 1
#endif
#if DISABLED(LIMITED_MAX_FR_EDITING)
#error "LIMITED_MAX_FR_EDITING is required with ProUI."
#endif
#if DISABLED(LIMITED_MAX_ACCEL_EDITING)
#error "LIMITED_MAX_ACCEL_EDITING is required with ProUI."
#endif
#if ENABLED(CLASSIC_JERK) && DISABLED(LIMITED_JERK_EDITING)
#error "LIMITED_JERK_EDITING is required with ProUI."
#endif
#if DISABLED(FILAMENT_RUNOUT_SENSOR)
#error "FILAMENT_RUNOUT_SENSOR is required with ProUI."
#endif
#if DISABLED(INDIVIDUAL_AXIS_HOMING_SUBMENU)
#error "INDIVIDUAL_AXIS_HOMING_SUBMENU is required with ProUI."
#endif
@ -81,7 +98,7 @@
#define HAS_ESDIAG 1
#if BOTH(LED_CONTROL_MENU, HAS_COLOR_LEDS)
#define Def_Leds_Color LEDColorWhite()
#define Def_Leds_Color 0xFFFFFFFF
#endif
#if ENABLED(CASELIGHT_USES_BRIGHTNESS)
#define Def_CaseLight_Brightness 255
@ -128,14 +145,13 @@ typedef struct {
#endif
bool FullManualTramming = false;
// Led
#if BOTH(LED_CONTROL_MENU, HAS_COLOR_LEDS)
LEDColor Led_Color = Def_Leds_Color;
#if ENABLED(MESH_BED_LEVELING)
float ManualZOffset = 0;
#endif
// Case Light
#if ENABLED(CASELIGHT_USES_BRIGHTNESS)
uint8_t CaseLight_Brightness = Def_CaseLight_Brightness;
#if BOTH(LED_CONTROL_MENU, HAS_COLOR_LEDS)
uint32_t LED_Color = Def_Leds_Color;
#endif
} HMI_data_t;
static constexpr size_t eeprom_data_size = 64;
static constexpr size_t eeprom_data_size = sizeof(HMI_data_t);
extern HMI_data_t HMI_data;

View File

@ -23,8 +23,8 @@
/**
* DWIN Enhanced implementation for PRO UI
* Author: Miguel A. Risco-Castillo (MRISCOC)
* Version: 3.9.1
* Date: 2022/02/08
* Version: 3.10.1
* Date: 2022/03/06
*/
#include "../../../inc/MarlinConfigPre.h"
@ -35,54 +35,6 @@
#include "dwin_lcd.h"
/*---------------------------------------- Numeric related functions ----------------------------------------*/
// Draw a numeric value
// bShow: true=display background color; false=don't display background color
// zeroFill: true=zero fill; false=no zero fill
// signedMode: 1=signed; 0=unsigned
// zeroMode: 1=leading 0 displayed as 0; 0=leading 0 displayed as a space
// size: Font size
// color: Character color
// bColor: Background color
// iNum: Number of digits
// fNum: Number of decimal digits
// x/y: Upper-left coordinate
// value: Integer value
void DWIN_Draw_Value(uint8_t bShow, bool signedMode, bool zeroFill, uint8_t zeroMode, uint8_t size, uint16_t color,
uint16_t bColor, uint8_t iNum, uint8_t fNum, uint16_t x, uint16_t y, int32_t value) {
size_t i = 0;
DWIN_Byte(i, 0x14);
// Bit 7: bshow
// Bit 6: 1 = signed; 0 = unsigned number;
// Bit 5: zeroFill
// Bit 4: zeroMode
// Bit 3-0: size
DWIN_Byte(i, (bShow * 0x80) | (signedMode * 0x40) | (zeroFill * 0x20) | (zeroMode * 0x10) | size);
DWIN_Word(i, color);
DWIN_Word(i, bColor);
DWIN_Byte(i, signedMode && (value >= 0) ? iNum + 1 : iNum);
DWIN_Byte(i, fNum);
DWIN_Word(i, x);
DWIN_Word(i, y);
// Write a big-endian 64 bit integer
const size_t p = i + 1;
for (size_t count = 8; count--;) { // 7..0
++i;
DWIN_SendBuf[p + count] = value;
value >>= 8;
}
DWIN_Send(i);
}
// Draw a numeric value
// value: positive unscaled float value
void DWIN_Draw_Value(uint8_t bShow, bool signedMode, bool zeroFill, uint8_t zeroMode, uint8_t size, uint16_t color,
uint16_t bColor, uint8_t iNum, uint8_t fNum, uint16_t x, uint16_t y, float value) {
const int32_t val = round(value * POW(10, fNum));
DWIN_Draw_Value(bShow, signedMode, zeroFill, zeroMode, size, color, bColor, iNum, fNum, x, y, val);
}
/*---------------------------------------- Picture related functions ----------------------------------------*/
// Display QR code

View File

@ -24,30 +24,12 @@
/**
* DWIN Enhanced implementation for PRO UI
* Author: Miguel A. Risco-Castillo (MRISCOC)
* Version: 3.9.1
* Date: 2022/02/08
* Version: 3.10.1
* Date: 2022/03/06
*/
#include "../common/dwin_api.h"
// Draw a numeric value
// bShow: true=display background color; false=don't display background color
// zeroFill: true=zero fill; false=no zero fill
// signedMode: 1=signed; 0=unsigned
// zeroMode: 1=leading 0 displayed as 0; 0=leading 0 displayed as a space
// size: Font size
// color: Character color
// bColor: Background color
// iNum: Number of digits
// fNum: Number of decimal digits
// x/y: Upper-left coordinate
// value: Integer value
void DWIN_Draw_Value(uint8_t bShow, bool signedMode, bool zeroFill, uint8_t zeroMode, uint8_t size, uint16_t color,
uint16_t bColor, uint8_t iNum, uint8_t fNum, uint16_t x, uint16_t y, int32_t value);
// value: positive unscaled float value
void DWIN_Draw_Value(uint8_t bShow, bool signedMode, bool zeroFill, uint8_t zeroMode, uint8_t size, uint16_t color,
uint16_t bColor, uint8_t iNum, uint8_t fNum, uint16_t x, uint16_t y, float value);
// Display QR code
// The size of the QR code is (46*QR_Pixel)*(46*QR_Pixel) dot matrix
// QR_Pixel: The pixel size occupied by each point of the QR code: 0x01-0x0F (1-16)

View File

@ -23,8 +23,8 @@
/**
* DWIN Enhanced implementation for PRO UI
* Author: Miguel A. Risco-Castillo (MRISCOC)
* Version: 3.15.1
* Date: 2022/02/25
* Version: 3.17.1
* Date: 2022/04/12
*/
#include "../../../inc/MarlinConfigPre.h"
@ -39,12 +39,6 @@
//#define DEBUG_OUT 1
#include "../../../core/debug_out.h"
int8_t MenuItemTotal = 0;
int8_t MenuItemCount = 0;
MenuItemClass** MenuItems = nullptr;
MenuClass *CurrentMenu = nullptr;
MenuClass *PreviousMenu = nullptr;
xy_int_t DWINUI::cursor = { 0 };
uint16_t DWINUI::pencolor = Color_White;
uint16_t DWINUI::textcolor = Def_Text_Color;
@ -53,16 +47,15 @@ uint16_t DWINUI::buttoncolor = Def_Button_Color;
uint8_t DWINUI::font = font8x16;
FSTR_P const DWINUI::Author = F(STRING_CONFIG_H_AUTHOR);
void (*DWINUI::onCursorErase)(const int8_t line)=nullptr;
void (*DWINUI::onCursorDraw)(const int8_t line)=nullptr;
void (*DWINUI::onTitleDraw)(TitleClass* title) = nullptr;
void (*DWINUI::onMenuDraw)(MenuClass* menu)=nullptr;
void DWINUI::init() {
TERN_(DEBUG_DWIN, SERIAL_ECHOPGM("\r\nDWIN handshake "));
delay(750); // Delay for wait to wakeup screen
const bool hs = DWIN_Handshake();
TERN(DEBUG_DWIN, SERIAL_ECHOLNF(hs ? F("ok.") : F("error.")), UNUSED(hs));
const bool hs = DWIN_Handshake(); UNUSED(hs);
#if ENABLED(DEBUG_DWIN)
SERIAL_ECHOPGM("DWIN_Handshake ");
SERIAL_ECHOLNF(hs ? F("ok.") : F("error."));
#endif
DWIN_Frame_SetDir(1);
cursor.reset();
pencolor = Color_White;
@ -164,16 +157,19 @@ void DWINUI::Draw_CenteredString(bool bShow, uint8_t size, uint16_t color, uint1
DWIN_Draw_String(bShow, size, color, bColor, x, y, string);
}
// // Draw a Centered string using DWIN_WIDTH
// void DWINUI::Draw_CenteredString(bool bShow, uint8_t size, uint16_t color, uint16_t bColor, uint16_t y, const char * const string) {
// const int8_t x = _MAX(0U, DWIN_WIDTH - strlen_P(string) * fontWidth(size)) / 2 - 1;
// DWIN_Draw_String(bShow, size, color, bColor, x, y, string);
// }
// Draw a char at cursor position
void DWINUI::Draw_Char(uint16_t color, const char c) {
// Draw a char
// color: Character color
// x: abscissa of the display
// y: ordinate of the display
// c: ASCII code of char
void DWINUI::Draw_Char(uint16_t color, uint16_t x, uint16_t y, const char c) {
const char string[2] = { c, 0};
DWIN_Draw_String(false, font, color, backcolor, cursor.x, cursor.y, string, 1);
DWIN_Draw_String(false, font, color, backcolor, x, y, string, 1);
}
// Draw a char at cursor position and increment cursor
void DWINUI::Draw_Char(uint16_t color, const char c) {
Draw_Char(color, cursor.x, cursor.y, c);
MoveBy(fontWidth(font), 0);
}
@ -190,6 +186,36 @@ void DWINUI::Draw_String(uint16_t color, const char * const string, uint16_t rli
MoveBy(strlen(string) * fontWidth(font), 0);
}
// Draw a numeric integer value
// bShow: true=display background color; false=don't display background color
// signedMode: 1=signed; 0=unsigned
// size: Font size
// color: Character color
// bColor: Background color
// iNum: Number of digits
// x/y: Upper-left coordinate
// value: Integer value
void DWINUI::Draw_Int(uint8_t bShow, bool signedMode, uint8_t size, uint16_t color, uint16_t bColor, uint8_t iNum, uint16_t x, uint16_t y, int32_t value) {
char nstr[10];
sprintf_P(nstr, PSTR("%*li"), (signedMode ? iNum + 1 : iNum), value);
DWIN_Draw_String(bShow, size, color, bColor, x, y, nstr);
}
// Draw a numeric float value
// bShow: true=display background color; false=don't display background color
// signedMode: 1=signed; 0=unsigned
// size: Font size
// color: Character color
// bColor: Background color
// iNum: Number of digits
// fNum: Number of decimal digits
// x/y: Upper-left coordinate
// value: float value
void DWINUI::Draw_Float(uint8_t bShow, bool signedMode, uint8_t size, uint16_t color, uint16_t bColor, uint8_t iNum, uint8_t fNum, uint16_t x, uint16_t y, float value) {
char nstr[10];
DWIN_Draw_String(bShow, size, color, bColor, x, y, dtostrf(value, iNum + (signedMode ? 2:1) + fNum, fNum, nstr));
}
// ------------------------- Buttons ------------------------------//
void DWINUI::Draw_Button(uint16_t color, uint16_t bcolor, uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2, const char * const caption) {
@ -204,6 +230,7 @@ void DWINUI::Draw_Button(uint8_t id, uint16_t x, uint16_t y) {
case BTN_Continue: Draw_Button(GET_TEXT_F(MSG_BUTTON_CONTINUE), x, y); break;
case BTN_Print : Draw_Button(GET_TEXT_F(MSG_BUTTON_PRINT), x, y); break;
case BTN_Save : Draw_Button(GET_TEXT_F(MSG_BUTTON_SAVE), x, y); break;
case BTN_Purge : Draw_Button(GET_TEXT_F(MSG_BUTTON_PURGE), x, y); break;
default: break;
}
}
@ -265,7 +292,7 @@ uint16_t DWINUI::ColorInt(int16_t val, int16_t minv, int16_t maxv, uint16_t colo
return RGB(R, G, B);
}
// Color Interpolator through Red->Yellow->Green->Blue
// Color Interpolator through Red->Yellow->Green->Blue (Pro UI)
// val : Interpolator minv..maxv
// minv : Minimum value
// maxv : Maximum value
@ -308,33 +335,6 @@ void DWINUI::ClearMainArea() {
DWIN_Draw_Rectangle(1, backcolor, 0, TITLE_HEIGHT, DWIN_WIDTH - 1, STATUS_Y - 1);
}
void DWINUI::MenuItemsClear() {
if (MenuItems == nullptr) return;
for (int8_t i = 0; i < MenuItemCount; i++) delete MenuItems[i];
delete[] MenuItems;
MenuItems = nullptr;
MenuItemCount = 0;
MenuItemTotal = 0;
}
void DWINUI::MenuItemsPrepare(int8_t totalitems) {
MenuItemsClear();
MenuItemTotal = totalitems;
MenuItems = new MenuItemClass*[totalitems];
}
MenuItemClass* DWINUI::MenuItemsAdd(MenuItemClass* menuitem) {
if (MenuItemCount < MenuItemTotal) {
MenuItems[MenuItemCount] = menuitem;
menuitem->pos = MenuItemCount++;
return menuitem;
}
else {
delete menuitem;
return nullptr;
}
}
/* Title Class ==============================================================*/
TitleClass Title;
@ -375,85 +375,4 @@ void TitleClass::FrameCopy(uint16_t x, uint16_t y, uint16_t w, uint16_t h) {
FrameCopy(1, x, y, x + w - 1, y + h - 1);
}
/* Menu Class ===============================================================*/
MenuClass::MenuClass() {
selected = 0;
topline = 0;
}
void MenuClass::draw() {
MenuTitle.draw();
if (DWINUI::onMenuDraw != nullptr) (*DWINUI::onMenuDraw)(this);
for (int8_t i = 0; i < MenuItemCount; i++)
MenuItems[i]->draw(i - topline);
if (DWINUI::onCursorDraw != nullptr) DWINUI::onCursorDraw(line());
DWIN_UpdateLCD();
}
void MenuClass::onScroll(bool dir) {
int8_t sel = selected;
if (dir) sel++; else sel--;
LIMIT(sel, 0, MenuItemCount - 1);
if (sel != selected) {
if (DWINUI::onCursorErase != nullptr) DWINUI::onCursorErase(line());
if ((sel - topline) == TROWS) {
DWIN_Frame_AreaMove(1, DWIN_SCROLL_UP, MLINE, DWINUI::backcolor, 0, TITLE_HEIGHT + 1, DWIN_WIDTH, STATUS_Y - 1);
topline++;
MenuItems[sel]->draw(TROWS - 1);
}
if ((sel < topline)) {
DWIN_Frame_AreaMove(1, DWIN_SCROLL_DOWN, MLINE, DWINUI::backcolor, 0, TITLE_HEIGHT + 1, DWIN_WIDTH, STATUS_Y - 1);
topline--;
MenuItems[sel]->draw(0);
}
selected = sel;
if (DWINUI::onCursorDraw != nullptr) DWINUI::onCursorDraw(line());
DWIN_UpdateLCD();
}
}
void MenuClass::onClick() {
if (MenuItems[selected]->onClick != nullptr) (*MenuItems[selected]->onClick)();
}
MenuItemClass *MenuClass::SelectedItem() {
return MenuItems[selected];
}
/* MenuItem Class ===========================================================*/
MenuItemClass::MenuItemClass(uint8_t cicon, const char * const text, void (*ondraw)(MenuItemClass* menuitem, int8_t line), void (*onclick)()) {
icon = cicon;
onClick = onclick;
onDraw = ondraw;
const uint8_t len = _MIN(sizeof(caption) - 1, strlen(text));
memcpy(&caption[0], text, len);
caption[len] = '\0';
}
MenuItemClass::MenuItemClass(uint8_t cicon, uint8_t id, uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2, void (*ondraw)(MenuItemClass* menuitem, int8_t line), void (*onclick)()) {
icon = cicon;
onClick = onclick;
onDraw = ondraw;
caption[0] = '\0';
frameid = id;
frame = { x1, y1, x2, y2 };
}
void MenuItemClass::SetFrame(uint8_t id, uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2) {
caption[0] = '\0';
frameid = id;
frame = { x1, y1, x2, y2 };
}
void MenuItemClass::draw(int8_t line) {
if (line < 0 || line >= TROWS) return;
if (onDraw != nullptr) (*onDraw)(this, line);
};
MenuItemPtrClass::MenuItemPtrClass(uint8_t cicon, const char * const text, void (*ondraw)(MenuItemClass* menuitem, int8_t line), void (*onclick)(), void* val) : MenuItemClass(cicon, text, ondraw, onclick) {
value = val;
};
#endif // DWIN_LCD_PROUI

View File

@ -24,8 +24,8 @@
/**
* DWIN Enhanced implementation for PRO UI
* Author: Miguel A. Risco-Castillo (MRISCOC)
* Version: 3.15.1
* Date: 2022/02/25
* Version: 3.17.1
* Date: 2022/04/12
*/
#include "dwin_lcd.h"
@ -37,6 +37,7 @@
#define ICON_AdvSet ICON_Language
#define ICON_BedSizeX ICON_PrintSize
#define ICON_BedSizeY ICON_PrintSize
#define ICON_BedTramming ICON_SetHome
#define ICON_Binary ICON_Contact
#define ICON_Brightness ICON_Motion
#define ICON_Cancel ICON_StockConfiguration
@ -50,10 +51,12 @@
#define ICON_FilUnload ICON_ReadEEPROM
#define ICON_Flow ICON_StepE
#define ICON_Folder ICON_More
#define ICON_FWRetract ICON_StepE
#define ICON_FWRetLength ICON_StepE
#define ICON_FWRetSpeed ICON_Setspeed
#define ICON_FWRetZRaise ICON_MoveZ
#define ICON_FWRecSpeed ICON_Setspeed
#define ICON_FWRecExtra ICON_StepE
#define ICON_HomeX ICON_MoveX
#define ICON_HomeY ICON_MoveY
#define ICON_HomeZ ICON_MoveZ
@ -102,6 +105,9 @@
#define ICON_SetBaudRate ICON_Setspeed
#define ICON_SetCustomPreheat ICON_SetEndTemp
#define ICON_Sound ICON_Cool
#define ICON_TBSetup ICON_Contact
#define ICON_UBLActive ICON_HotendTemp
#define ICON_CaseLight ICON_Motion
#define ICON_LedControl ICON_Motion
@ -111,12 +117,27 @@
#define BTN_Confirm 89
#define BTN_Print 90
#define BTN_Save 91
#define BTN_Purge 92
// Extended and default UI Colors
#define Color_Black 0
#define Color_Green RGB(0,63,0)
#define Color_Aqua RGB(0,63,31)
#define Color_Blue RGB(0,0,31)
#define Color_Light_White 0xBDD7
#define Color_Light_Green 0x3460
#define Color_Cyan 0x07FF
#define Color_Light_Cyan 0x04F3
#define Color_Light_Blue 0x3A6A
#define Color_Magenta 0xF81F
#define Color_Light_Magenta 0x9813
#define Color_Light_Red 0x8800
#define Color_Orange 0xFA20
#define Color_Light_Orange 0xFBC0
#define Color_Light_Yellow 0x8BE0
#define Color_Brown 0xCC27
#define Color_Light_Brown 0x6204
#define Color_Grey 0x18E3
// UI element defines and constants
#define DWIN_FONT_MENU font8x16
@ -130,7 +151,7 @@
#define UNITFDIGITS 1
#define MINUNITMULT POW(10, UNITFDIGITS)
constexpr uint16_t TITLE_HEIGHT = 30, // Title bar height
constexpr uint8_t TITLE_HEIGHT = 30, // Title bar height
MLINE = 53, // Menu line height
TROWS = (STATUS_Y - TITLE_HEIGHT) / MLINE, // Total rows
MROWS = TROWS - 1, // Other-than-Back
@ -149,10 +170,6 @@ constexpr uint16_t TITLE_HEIGHT = 30, // Title bar heig
// Menuitem caption Y position
#define MBASE(L) (MYPOS(L) + CAPOFF)
// Create and add a MenuItem object to the menu array
#define MENU_ITEM(V...) DWINUI::MenuItemsAdd(new MenuItemClass(V))
#define EDIT_ITEM(V...) DWINUI::MenuItemsAdd(new MenuItemPtrClass(V))
typedef struct { uint16_t left, top, right, bottom; } rect_t;
typedef struct { uint16_t x, y, w, h; } frame_rect_t;
@ -173,49 +190,6 @@ public:
};
extern TitleClass Title;
class MenuItemClass {
protected:
public:
int8_t pos = 0;
uint8_t icon = 0;
char caption[32] = "";
uint8_t frameid = 0;
rect_t frame = {0};
void (*onDraw)(MenuItemClass* menuitem, int8_t line) = nullptr;
void (*onClick)() = nullptr;
MenuItemClass() {};
MenuItemClass(uint8_t cicon, const char * const text=nullptr, void (*ondraw)(MenuItemClass* menuitem, int8_t line)=nullptr, void (*onclick)()=nullptr);
MenuItemClass(uint8_t cicon, FSTR_P text = nullptr, void (*ondraw)(MenuItemClass* menuitem, int8_t line)=nullptr, void (*onclick)()=nullptr) : MenuItemClass(cicon, FTOP(text), ondraw, onclick){}
MenuItemClass(uint8_t cicon, uint8_t id, uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2, void (*ondraw)(MenuItemClass* menuitem, int8_t line)=nullptr, void (*onclick)()=nullptr);
void SetFrame(uint8_t id, uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2);
virtual ~MenuItemClass(){};
virtual void draw(int8_t line);
};
class MenuItemPtrClass: public MenuItemClass {
public:
void *value = nullptr;
using MenuItemClass::MenuItemClass;
MenuItemPtrClass(uint8_t cicon, const char * const text, void (*ondraw)(MenuItemClass* menuitem, int8_t line), void (*onclick)(), void* val);
MenuItemPtrClass(uint8_t cicon, FSTR_P text, void (*ondraw)(MenuItemClass* menuitem, int8_t line), void (*onclick)(), void* val) : MenuItemPtrClass(cicon, FTOP(text), ondraw, onclick, val){}
};
class MenuClass {
public:
int8_t topline = 0;
int8_t selected = 0;
TitleClass MenuTitle;
MenuClass();
virtual ~MenuClass(){};
inline int8_t line() { return selected - topline; };
inline int8_t line(uint8_t pos) {return pos - topline; };
void draw();
void onScroll(bool dir);
void onClick();
MenuItemClass* SelectedItem();
};
extern MenuClass *CurrentMenu;
namespace DWINUI {
extern xy_int_t cursor;
extern uint16_t pencolor;
@ -225,10 +199,7 @@ namespace DWINUI {
extern uint8_t font;
extern FSTR_P const Author;
extern void (*onCursorErase)(const int8_t line);
extern void (*onCursorDraw)(const int8_t line);
extern void (*onTitleDraw)(TitleClass* title);
extern void (*onMenuDraw)(MenuClass* menu);
// DWIN LCD Initialization
void init();
@ -304,129 +275,121 @@ namespace DWINUI {
DWIN_ICON_Show(true, false, false, ICON, icon, x, y);
}
// Draw a positive integer
// Draw a numeric integer value
// bShow: true=display background color; false=don't display background color
// zeroFill: true=zero fill; false=no zero fill
// zeroMode: 1=leading 0 displayed as 0; 0=leading 0 displayed as a space
// signedMode: 1=signed; 0=unsigned
// size: Font size
// color: Character color
// bColor: Background color
// iNum: Number of digits
// x/y: Upper-left coordinate
// value: Integer value
inline void Draw_Int(uint8_t bShow, bool zeroFill, uint8_t zeroMode, uint8_t size, uint16_t color, uint16_t bColor, uint8_t iNum, uint16_t x, uint16_t y, long value) {
DWIN_Draw_Value(bShow, 0, zeroFill, zeroMode, size, color, bColor, iNum, 0, x, y, value);
void Draw_Int(uint8_t bShow, bool signedMode, uint8_t size, uint16_t color, uint16_t bColor, uint8_t iNum, uint16_t x, uint16_t y, int32_t value);
// Draw a positive integer
inline void Draw_Int(uint8_t bShow, uint8_t size, uint16_t color, uint16_t bColor, uint8_t iNum, uint16_t x, uint16_t y, long value) {
Draw_Int(bShow, 0, size, color, bColor, iNum, x, y, value);
}
inline void Draw_Int(uint8_t iNum, long value) {
DWIN_Draw_Value(false, 0, true, 0, font, textcolor, backcolor, iNum, 0, cursor.x, cursor.y, value);
Draw_Int(false, 0, font, textcolor, backcolor, iNum, cursor.x, cursor.y, value);
MoveBy(iNum * fontWidth(font), 0);
}
inline void Draw_Int(uint8_t iNum, uint16_t x, uint16_t y, long value) {
DWIN_Draw_Value(false, 0, true, 0, font, textcolor, backcolor, iNum, 0, x, y, value);
Draw_Int(false, 0, font, textcolor, backcolor, iNum, x, y, value);
}
inline void Draw_Int(uint16_t color, uint8_t iNum, uint16_t x, uint16_t y, long value) {
DWIN_Draw_Value(false, 0, true, 0, font, color, backcolor, iNum, 0, x, y, value);
Draw_Int(false, 0, font, color, backcolor, iNum, x, y, value);
}
inline void Draw_Int(uint16_t color, uint16_t bColor, uint8_t iNum, uint16_t x, uint16_t y, long value) {
DWIN_Draw_Value(true, 0, true, 0, font, color, bColor, iNum, 0, x, y, value);
Draw_Int(true, 0, font, color, bColor, iNum, x, y, value);
}
inline void Draw_Int(uint8_t size, uint16_t color, uint16_t bColor, uint8_t iNum, uint16_t x, uint16_t y, long value) {
DWIN_Draw_Value(true, 0, true, 0, size, color, bColor, iNum, 0, x, y, value);
Draw_Int(true, 0, size, color, bColor, iNum, x, y, value);
}
// Draw a signed integer
inline void Draw_Signed_Int(uint8_t bShow, uint8_t size, uint16_t color, uint16_t bColor, uint8_t iNum, uint16_t x, uint16_t y, long value) {
Draw_Int(bShow, 1, size, color, bColor, iNum, x, y, value);
}
inline void Draw_Signed_Int(uint8_t iNum, long value) {
Draw_Int(false, 1, font, textcolor, backcolor, iNum, cursor.x, cursor.y, value);
MoveBy(iNum * fontWidth(font), 0);
}
inline void Draw_Signed_Int(uint8_t iNum, uint16_t x, uint16_t y, long value) {
Draw_Int(false, 1, font, textcolor, backcolor, iNum, x, y, value);
}
inline void Draw_Signed_Int(uint16_t color, uint8_t iNum, uint16_t x, uint16_t y, long value) {
Draw_Int(false, 1, font, color, backcolor, iNum, x, y, value);
}
inline void Draw_Signed_Int(uint16_t color, uint16_t bColor, uint8_t iNum, uint16_t x, uint16_t y, long value) {
Draw_Int(true, 1, font, color, bColor, iNum, x, y, value);
}
inline void Draw_Signed_Int(uint8_t size, uint16_t color, uint16_t bColor, uint8_t iNum, uint16_t x, uint16_t y, long value) {
Draw_Int(true, 1, size, color, bColor, iNum, x, y, value);
}
// Draw a numeric float value
// bShow: true=display background color; false=don't display background color
// zeroFill: true=zero fill; false=no zero fill
// zeroMode: 1=leading 0 displayed as 0; 0=leading 0 displayed as a space
// signedMode: 1=signed; 0=unsigned
// size: Font size
// color: Character color
// bColor: Background color
// iNum: Number of digits
// fNum: Number of decimal digits
// x/y: Upper-left coordinate
// value: Integer value
inline void Draw_Signed_Int(uint8_t bShow, bool zeroFill, uint8_t zeroMode, uint8_t size, uint16_t color, uint16_t bColor, uint8_t iNum, uint16_t x, uint16_t y, long value) {
DWIN_Draw_Value(bShow, 1, zeroFill, zeroMode, size, color, bColor, iNum, 0, x, y, value);
}
inline void Draw_Signed_Int(uint8_t iNum, long value) {
DWIN_Draw_Value(false, 1, true, 0, font, textcolor, backcolor, iNum, 0, cursor.x, cursor.y, value);
MoveBy(iNum * fontWidth(font), 0);
}
inline void Draw_Signed_Int(uint8_t iNum, uint16_t x, uint16_t y, long value) {
DWIN_Draw_Value(false, 1, true, 0, font, textcolor, backcolor, iNum, 0, x, y, value);
}
inline void Draw_Signed_Int(uint16_t color, uint8_t iNum, uint16_t x, uint16_t y, long value) {
DWIN_Draw_Value(false, 1, true, 0, font, color, backcolor, iNum, 0, x, y, value);
}
inline void Draw_Signed_Int(uint16_t color, uint16_t bColor, uint8_t iNum, uint16_t x, uint16_t y, long value) {
DWIN_Draw_Value(true, 1, true, 0, font, color, bColor, iNum, 0, x, y, value);
}
inline void Draw_Signed_Int(uint8_t size, uint16_t color, uint16_t bColor, uint8_t iNum, uint16_t x, uint16_t y, long value) {
DWIN_Draw_Value(true, 1, true, 0, size, color, bColor, iNum, 0, x, y, value);
}
// value: float value
void Draw_Float(uint8_t bShow, bool signedMode, uint8_t size, uint16_t color, uint16_t bColor, uint8_t iNum, uint8_t fNum, uint16_t x, uint16_t y, float value);
// Draw a positive floating point number
// bShow: true=display background color; false=don't display background color
// zeroFill: true=zero fill; false=no zero fill
// zeroMode: 1=leading 0 displayed as 0; 0=leading 0 displayed as a space
// size: Font size
// color: Character color
// bColor: Background color
// iNum: Number of whole digits
// fNum: Number of decimal digits
// x/y: Upper-left point
// value: Float value
inline void Draw_Float(uint8_t bShow, bool zeroFill, uint8_t zeroMode, uint8_t size, uint16_t color, uint16_t bColor, uint8_t iNum, uint8_t fNum, uint16_t x, uint16_t y, float value) {
DWIN_Draw_Value(bShow, 0, zeroFill, zeroMode, size, color, bColor, iNum, fNum, x, y, value);
inline void Draw_Float(uint8_t bShow, uint8_t size, uint16_t color, uint16_t bColor, uint8_t iNum, uint8_t fNum, uint16_t x, uint16_t y, float value) {
Draw_Float(bShow, 0, size, color, bColor, iNum, fNum, x, y, value);
}
inline void Draw_Float(uint8_t iNum, uint8_t fNum, float value) {
DWIN_Draw_Value(false, 0, true, 0, font, textcolor, backcolor, iNum, fNum, cursor.x, cursor.y, value);
Draw_Float(false, 0, font, textcolor, backcolor, iNum, fNum, cursor.x, cursor.y, value);
MoveBy((iNum + fNum + 1) * fontWidth(font), 0);
}
inline void Draw_Float(uint8_t iNum, uint8_t fNum, uint16_t x, uint16_t y, float value) {
DWIN_Draw_Value(false, 0, true, 0, font, textcolor, backcolor, iNum, fNum, x, y, value);
Draw_Float(false, 0, font, textcolor, backcolor, iNum, fNum, x, y, value);
}
inline void Draw_Float(uint16_t color, uint8_t iNum, uint8_t fNum, uint16_t x, uint16_t y, float value) {
DWIN_Draw_Value(false, 0, true, 0, font, color, backcolor, iNum, fNum, x, y, value);
inline void Draw_Float(uint8_t size, uint8_t iNum, uint8_t fNum, uint16_t x, uint16_t y, float value) {
Draw_Float(false, 0, size, textcolor, backcolor, iNum, fNum, x, y, value);
}
inline void Draw_Float(uint16_t color, uint16_t bColor, uint8_t iNum, uint8_t fNum, uint16_t x, uint16_t y, float value) {
DWIN_Draw_Value(true, 0, true, 0, font, color, bColor, iNum, fNum, x, y, value);
Draw_Float(true, 0, font, color, bColor, iNum, fNum, x, y, value);
}
inline void Draw_Float(uint8_t size, uint16_t color, uint16_t bColor, uint8_t iNum, uint8_t fNum, uint16_t x, uint16_t y, float value) {
DWIN_Draw_Value(true, 0, true, 0, size, color, bColor, iNum, fNum, x, y, value);
Draw_Float(true, 0, size, color, bColor, iNum, fNum, x, y, value);
}
// Draw a signed floating point number
// bShow: true=display background color; false=don't display background color
// zeroFill: true=zero fill; false=no zero fill
// zeroMode: 1=leading 0 displayed as 0; 0=leading 0 displayed as a space
// size: Font size
// color: Character color
// bColor: Background color
// iNum: Number of whole digits
// fNum: Number of decimal digits
// x/y: Upper-left point
// value: Float value
inline void Draw_Signed_Float(uint8_t bShow, bool zeroFill, uint8_t zeroMode, uint8_t size, uint16_t color, uint16_t bColor, uint8_t iNum, uint8_t fNum, uint16_t x, uint16_t y, float value) {
DWIN_Draw_Value(bShow, 1, zeroFill, zeroMode, size, color, bColor, iNum, fNum, x, y, value);
inline void Draw_Signed_Float(uint8_t bShow, uint8_t size, uint16_t color, uint16_t bColor, uint8_t iNum, uint8_t fNum, uint16_t x, uint16_t y, float value) {
Draw_Float(bShow, 1, size, color, bColor, iNum, fNum, x, y, value);
}
inline void Draw_Signed_Float(uint8_t iNum, uint8_t fNum, float value) {
DWIN_Draw_Value(false, 1, true, 0, font, textcolor, backcolor, iNum, fNum, cursor.x, cursor.y, value);
Draw_Float(false, 1, font, textcolor, backcolor, iNum, fNum, cursor.x, cursor.y, value);
MoveBy((iNum + fNum + 1) * fontWidth(font), 0);
}
inline void Draw_Signed_Float(uint8_t iNum, uint8_t fNum, uint16_t x, uint16_t y, float value) {
DWIN_Draw_Value(false, 1, true, 0, font, textcolor, backcolor, iNum, fNum, x, y, value);
Draw_Float(false, 1, font, textcolor, backcolor, iNum, fNum, x, y, value);
}
inline void Draw_Signed_Float(uint8_t size, uint8_t iNum, uint8_t fNum, uint16_t x, uint16_t y, float value) {
DWIN_Draw_Value(false, 1, true, 0, size, textcolor, backcolor, iNum, fNum, x, y, value);
Draw_Float(false, 1, size, textcolor, backcolor, iNum, fNum, x, y, value);
}
inline void Draw_Signed_Float(uint16_t color, uint16_t bColor, uint8_t iNum, uint8_t fNum, uint16_t x, uint16_t y, float value) {
DWIN_Draw_Value(true, 1, true, 0, font, color, bColor, iNum, fNum, x, y, value);
Draw_Float(true, 1, font, color, bColor, iNum, fNum, x, y, value);
}
inline void Draw_Signed_Float(uint8_t size, uint16_t color, uint16_t bColor, uint8_t iNum, uint8_t fNum, uint16_t x, uint16_t y, float value) {
DWIN_Draw_Value(true, 1, true, 0, size, color, bColor, iNum, fNum, x, y, value);
Draw_Float(true, 1, size, color, bColor, iNum, fNum, x, y, value);
}
// Draw a char at cursor position
// Draw a char
// color: Character color
// x: abscissa of the display
// y: ordinate of the display
// c: ASCII code of char
void Draw_Char(uint16_t color, uint16_t x, uint16_t y, const char c);
inline void Draw_Char(uint16_t x, uint16_t y, const char c) { Draw_Char(textcolor, x, y, c); };
// Draw a char at cursor position and increment cursor
void Draw_Char(uint16_t color, const char c);
inline void Draw_Char(const char c) { Draw_Char(textcolor, c); }
@ -591,17 +554,8 @@ namespace DWINUI {
DWIN_WriteToMem(0xA5, addr, length, data);
}
// Clear Menu by filling the area with background color
// Clear by filling the area with background color
// Area (0, TITLE_HEIGHT, DWIN_WIDTH, STATUS_Y - 1)
void ClearMainArea();
// Clear MenuItems array and free MenuItems elements
void MenuItemsClear();
// Prepare MenuItems array
void MenuItemsPrepare(int8_t totalitems);
// Add elements to the MenuItems array
MenuItemClass* MenuItemsAdd(MenuItemClass* menuitem);
};

View File

@ -23,8 +23,8 @@
/**
* Lock screen implementation for PRO UI
* Author: Miguel A. Risco-Castillo (MRISCOC)
* Version: 2.1
* Date: 2021/11/09
* Version: 2.2.0
* Date: 2022/04/11
*/
#include "../../../inc/MarlinConfigPre.h"
@ -50,6 +50,7 @@ void LockScreenClass::init() {
}
void LockScreenClass::draw() {
Title.SetCaption(GET_TEXT_F(MSG_LOCKSCREEN));
DWINUI::ClearMainArea();
DWINUI::Draw_Icon(ICON_LOGO, 71, 120); // CREALITY logo
DWINUI::Draw_CenteredString(Color_White, 180, GET_TEXT_F(MSG_LOCKSCREEN_LOCKED));

View File

@ -24,8 +24,8 @@
/**
* Lock screen implementation for PRO UI
* Author: Miguel A. Risco-Castillo (MRISCOC)
* Version: 2.1
* Date: 2021/11/09
* Version: 2.2.0
* Date: 2022/04/11
*/
#include "../common/encoder.h"

View File

@ -23,8 +23,8 @@
/**
* Menu functions for ProUI
* Author: Miguel A. Risco-Castillo
* Version: 1.2.1
* Date: 2022/02/25
* Version: 1.4.1
* Date: 2022/04/14
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as
@ -51,6 +51,14 @@
#include "dwin.h"
#include "menus.h"
int8_t MenuItemTotal = 0;
int8_t MenuItemCount = 0;
MenuItemClass** MenuItems = nullptr;
MenuClass *CurrentMenu = nullptr;
MenuClass *PreviousMenu = nullptr;
void (*onMenuDraw)(MenuClass* menu) = nullptr;
void (*onCursorErase)(const int8_t line) = nullptr;
void (*onCursorDraw)(const int8_t line) = nullptr;
MenuData_t MenuData;
// Menuitem Drawing functions =================================================
@ -69,11 +77,13 @@ void Draw_Menu(MenuClass* menu) {
}
void Draw_Menu_Cursor(const int8_t line) {
DWIN_Draw_Rectangle(1, HMI_data.Cursor_color, 0, MBASE(line) - 18, 14, MBASE(line + 1) - 20);
const uint16_t ypos = MYPOS(line);
DWINUI::Draw_Box(1, HMI_data.Cursor_color, {0, ypos, 15, MLINE - 1});
}
void Erase_Menu_Cursor(const int8_t line) {
DWIN_Draw_Rectangle(1, HMI_data.Background_Color, 0, MBASE(line) - 18, 14, MBASE(line + 1) - 20);
const uint16_t ypos = MYPOS(line);
DWINUI::Draw_Box(1, HMI_data.Background_Color, {0, ypos, 15, MLINE - 1});
}
void Draw_Menu_Line(const uint8_t line, const uint8_t icon /*=0*/, const char * const label /*=nullptr*/, bool more /*=false*/) {
@ -84,7 +94,7 @@ void Draw_Menu_Line(const uint8_t line, const uint8_t icon /*=0*/, const char *
}
void Draw_Chkb_Line(const uint8_t line, const bool checked) {
DWINUI::Draw_Checkbox(HMI_data.Text_Color, HMI_data.Background_Color, VALX + 16, MBASE(line) - 1, checked);
DWINUI::Draw_Checkbox(HMI_data.Text_Color, HMI_data.Background_Color, VALX + 3 * DWINUI::fontWidth(), MBASE(line) - 1, checked);
}
void Draw_Menu_IntValue(uint16_t bcolor, const uint8_t line, uint8_t iNum, const int32_t value /*=0*/) {
@ -141,11 +151,21 @@ void onDrawPFloat2Menu(MenuItemClass* menuitem, int8_t line) {
onDrawFloatMenu(menuitem, line, 2, value);
}
void onDrawPFloat3Menu(MenuItemClass* menuitem, int8_t line) {
const float value = *(float*)static_cast<MenuItemPtrClass*>(menuitem)->value;
onDrawFloatMenu(menuitem, line, 3, value);
}
void onDrawChkbMenu(MenuItemClass* menuitem, int8_t line, bool checked) {
onDrawMenuItem(menuitem, line);
Draw_Chkb_Line(line, checked);
}
void onDrawChkbMenu(MenuItemClass* menuitem, int8_t line) {
const bool val = *(bool*)static_cast<MenuItemPtrClass*>(menuitem)->value;
onDrawChkbMenu(menuitem, line, val);
}
//-----------------------------------------------------------------------------
// On click functions
//-----------------------------------------------------------------------------
@ -165,7 +185,7 @@ void SetOnClick(uint8_t process, const int32_t lo, const int32_t hi, uint8_t dp,
MenuData.dp = dp;
MenuData.Apply = Apply;
MenuData.LiveUpdate = LiveUpdate;
MenuData.Value = val;
MenuData.Value = constrain(val, lo, hi);
EncoderRate.enabled = true;
}
@ -257,6 +277,7 @@ void HMI_Menu() {
// 1 : live change
// 2 : apply change
int8_t HMI_GetIntNoDraw(const int32_t lo, const int32_t hi) {
const int32_t cval = MenuData.Value;
EncoderState encoder_diffState = Encoder_ReceiveAnalyze();
if (encoder_diffState != ENCODER_DIFF_NO) {
if (Apply_Encoder(encoder_diffState, MenuData.Value)) {
@ -265,9 +286,8 @@ int8_t HMI_GetIntNoDraw(const int32_t lo, const int32_t hi) {
return 2;
}
LIMIT(MenuData.Value, lo, hi);
return 1;
}
return 0;
return int8_t(cval != MenuData.Value);
}
// Get an integer value using the encoder
@ -367,4 +387,166 @@ void HMI_SetPFloat() {
}
}
// Menu Classes ===============================================================
MenuClass::MenuClass() {
selected = 0;
topline = 0;
}
void MenuClass::draw() {
MenuTitle.draw();
if (onMenuDraw != nullptr) onMenuDraw(this);
for (int8_t i = 0; i < MenuItemCount; i++)
MenuItems[i]->draw(i - topline);
if (onCursorDraw != nullptr) onCursorDraw(line());
DWIN_UpdateLCD();
}
void MenuClass::onScroll(bool dir) {
int8_t sel = selected;
if (dir) sel++; else sel--;
LIMIT(sel, 0, MenuItemCount - 1);
if (sel != selected) {
if (onCursorErase != nullptr) onCursorErase(line());
DWIN_UpdateLCD();
if ((sel - topline) == TROWS) {
DWIN_Frame_AreaMove(1, DWIN_SCROLL_UP, MLINE, DWINUI::backcolor, 0, TITLE_HEIGHT + 1, DWIN_WIDTH, STATUS_Y - 1);
topline++;
MenuItems[sel]->draw(TROWS - 1);
}
if ((sel < topline)) {
DWIN_Frame_AreaMove(1, DWIN_SCROLL_DOWN, MLINE, DWINUI::backcolor, 0, TITLE_HEIGHT + 1, DWIN_WIDTH, STATUS_Y - 1);
topline--;
MenuItems[sel]->draw(0);
}
selected = sel;
if (onCursorDraw != nullptr) onCursorDraw(line());
DWIN_UpdateLCD();
}
}
void MenuClass::onClick() {
if (MenuItems[selected]->onClick != nullptr) (*MenuItems[selected]->onClick)();
}
MenuItemClass *MenuClass::SelectedItem() {
return MenuItems[selected];
}
MenuItemClass** MenuClass::Items() {
return MenuItems;
}
int8_t MenuClass::count() {
return MenuItemCount;
};
/* MenuItem Class ===========================================================*/
MenuItemClass::MenuItemClass(uint8_t cicon, const char * const text, void (*ondraw)(MenuItemClass* menuitem, int8_t line), void (*onclick)()) {
icon = cicon;
onClick = onclick;
onDraw = ondraw;
const uint8_t len = _MIN(sizeof(caption) - 1, strlen(text));
memcpy(&caption[0], text, len);
caption[len] = '\0';
}
MenuItemClass::MenuItemClass(uint8_t cicon, uint8_t id, uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2, void (*ondraw)(MenuItemClass* menuitem, int8_t line), void (*onclick)()) {
icon = cicon;
onClick = onclick;
onDraw = ondraw;
caption[0] = '\0';
frameid = id;
frame = { x1, y1, x2, y2 };
}
void MenuItemClass::SetFrame(uint8_t id, uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2) {
caption[0] = '\0';
frameid = id;
frame = { x1, y1, x2, y2 };
}
void MenuItemClass::draw(int8_t line) {
if (line < 0 || line >= TROWS) return;
if (onDraw != nullptr) (*onDraw)(this, line);
};
void MenuItemClass::redraw() {
draw(CurrentMenu->line(this->pos));
}
MenuItemPtrClass::MenuItemPtrClass(uint8_t cicon, const char * const text, void (*ondraw)(MenuItemClass* menuitem, int8_t line), void (*onclick)(), void* val) : MenuItemClass(cicon, text, ondraw, onclick) {
value = val;
};
// Menu auxiliary functions ===================================================
void MenuItemsClear() {
if (MenuItems == nullptr) return;
for (int8_t i = 0; i < MenuItemCount; i++) delete MenuItems[i];
delete[] MenuItems;
MenuItems = nullptr;
MenuItemCount = 0;
MenuItemTotal = 0;
}
void MenuItemsPrepare(int8_t totalitems) {
MenuItemsClear();
MenuItemTotal = totalitems;
MenuItems = new MenuItemClass*[totalitems];
}
MenuItemClass* MenuItemsAdd(MenuItemClass* menuitem) {
MenuItems[MenuItemCount] = menuitem;
menuitem->pos = MenuItemCount++;
return menuitem;
}
MenuItemClass* MenuItemsAdd(uint8_t cicon, const char * const text/*=nullptr*/, void (*ondraw)(MenuItemClass* menuitem, int8_t line)/*=nullptr*/, void (*onclick)()/*=nullptr*/) {
if (MenuItemCount < MenuItemTotal) {
MenuItemClass* menuitem = new MenuItemClass(cicon, text, ondraw, onclick);
return MenuItemsAdd(menuitem);
}
else return nullptr;
}
MenuItemClass* MenuItemsAdd(uint8_t cicon, uint8_t id, uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2, void (*ondraw)(MenuItemClass* menuitem, int8_t line)/*=nullptr*/, void (*onclick)()/*=nullptr*/) {
if (MenuItemCount < MenuItemTotal) {
MenuItemClass* menuitem = new MenuItemClass(cicon, id, x1, y1, x2, y2, ondraw, onclick);
return MenuItemsAdd(menuitem);
}
else return nullptr;
}
MenuItemClass* MenuItemsAdd(uint8_t cicon, const char * const text, void (*ondraw)(MenuItemClass* menuitem, int8_t line), void (*onclick)(), void* val) {
if (MenuItemCount < MenuItemTotal) {
MenuItemClass* menuitem = new MenuItemPtrClass(cicon, text, ondraw, onclick, val);
return MenuItemsAdd(menuitem);
}
else return nullptr;
}
bool SetMenu(MenuClass* &menu, FSTR_P title, int8_t totalitems) {
if (!menu) menu = new MenuClass();
const bool NotCurrent = (CurrentMenu != menu);
if (NotCurrent) {
menu->MenuTitle.SetCaption(title);
MenuItemsPrepare(totalitems);
}
return NotCurrent;
}
void UpdateMenu(MenuClass* &menu) {
if (!menu) return;
if (CurrentMenu != menu) {
PreviousMenu = CurrentMenu;
CurrentMenu = menu;
}
menu->draw();
}
void ReDrawMenu() { if (CurrentMenu && checkkey==Menu) CurrentMenu->draw(); }
#endif // DWIN_LCD_PROUI

View File

@ -23,8 +23,8 @@
/**
* Menu functions for ProUI
* Author: Miguel A. Risco-Castillo
* Version: 1.2.1
* Date: 2022/02/25
* Version: 1.4.1
* Date: 2022/04/14
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as
@ -56,8 +56,70 @@ typedef struct {
} MenuData_t;
extern MenuData_t MenuData;
extern void (*onCursorErase)(const int8_t line);
extern void (*onCursorDraw)(const int8_t line);
// Auxiliary Macros ===========================================================
// Create and add a MenuItem object to the menu array
#define BACK_ITEM(H) MenuItemsAdd(ICON_Back, GET_TEXT_F(MSG_BUTTON_BACK), onDrawMenuItem, H)
#define MENU_ITEM(V...) MenuItemsAdd(V)
#define EDIT_ITEM(V...) MenuItemsAdd(V)
#define MENU_ITEM_F(I,L,V...) MenuItemsAdd(I, GET_TEXT_F(L), V)
#define EDIT_ITEM_F(I,L,V...) MenuItemsAdd(I, GET_TEXT_F(L), V)
// Menu Classes ===============================================================
class MenuItemClass {
protected:
public:
int8_t pos = 0;
uint8_t icon = 0;
char caption[32] = "";
uint8_t frameid = 0;
rect_t frame = {0};
void (*onDraw)(MenuItemClass* menuitem, int8_t line) = nullptr;
void (*onClick)() = nullptr;
MenuItemClass() {};
MenuItemClass(uint8_t cicon, const char * const text=nullptr, void (*ondraw)(MenuItemClass* menuitem, int8_t line)=nullptr, void (*onclick)()=nullptr);
// MenuItemClass(uint8_t cicon, FSTR_P text = nullptr, void (*ondraw)(MenuItemClass* menuitem, int8_t line)=nullptr, void (*onclick)()=nullptr) : MenuItemClass(cicon, FTOP(text), ondraw, onclick){}
MenuItemClass(uint8_t cicon, uint8_t id, uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2, void (*ondraw)(MenuItemClass* menuitem, int8_t line)=nullptr, void (*onclick)()=nullptr);
void SetFrame(uint8_t id, uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2);
virtual ~MenuItemClass(){};
virtual void draw(int8_t line);
void redraw();
};
class MenuItemPtrClass: public MenuItemClass {
public:
void *value = nullptr;
using MenuItemClass::MenuItemClass;
MenuItemPtrClass(uint8_t cicon, const char * const text, void (*ondraw)(MenuItemClass* menuitem, int8_t line), void (*onclick)(), void* val);
MenuItemPtrClass(uint8_t cicon, FSTR_P text, void (*ondraw)(MenuItemClass* menuitem, int8_t line), void (*onclick)(), void* val) : MenuItemPtrClass(cicon, FTOP(text), ondraw, onclick, val){}
};
class MenuClass {
public:
int8_t topline = 0;
int8_t selected = 0;
TitleClass MenuTitle;
MenuClass();
virtual ~MenuClass(){};
inline int8_t line() { return selected - topline; };
inline int8_t line(uint8_t pos) {return pos - topline; };
int8_t count();
virtual void draw();
virtual void onScroll(bool dir);
void onClick();
MenuItemClass* SelectedItem();
static MenuItemClass** Items();
};
extern MenuClass *CurrentMenu;
extern MenuClass *PreviousMenu;
extern void (*onMenuDraw)(MenuClass* menu);
// Menuitem Drawing functions =================================================
void Draw_Title(TitleClass* title);
void Draw_Menu(MenuClass* menu);
void Draw_Menu_Cursor(const int8_t line);
@ -74,9 +136,12 @@ void onDrawPInt32Menu(MenuItemClass* menuitem, int8_t line);
void onDrawFloatMenu(MenuItemClass* menuitem, int8_t line, uint8_t dp, const float value);
void onDrawPFloatMenu(MenuItemClass* menuitem, int8_t line);
void onDrawPFloat2Menu(MenuItemClass* menuitem, int8_t line);
void onDrawPFloat3Menu(MenuItemClass* menuitem, int8_t line);
void onDrawChkbMenu(MenuItemClass* menuitem, int8_t line, bool checked);
void onDrawChkbMenu(MenuItemClass* menuitem, int8_t line);
// On click functions =========================================================
void SetOnClick(uint8_t process, const int32_t lo, const int32_t hi, uint8_t dp, const int32_t val, void (*Apply)() = nullptr, void (*LiveUpdate)() = nullptr);
void SetValueOnClick(uint8_t process, const int32_t lo, const int32_t hi, const int32_t val, void (*Apply)() = nullptr, void (*LiveUpdate)() = nullptr);
void SetValueOnClick(uint8_t process, const float lo, const float hi, uint8_t dp, const float val, void (*Apply)() = nullptr, void (*LiveUpdate)() = nullptr);
@ -86,9 +151,38 @@ void SetFloatOnClick(const float lo, const float hi, uint8_t dp, const float val
void SetPFloatOnClick(const float lo, const float hi, uint8_t dp, void (*Apply)() = nullptr, void (*LiveUpdate)() = nullptr);
// HMI user control functions =================================================
void HMI_Menu();
void HMI_SetInt();
void HMI_SetPInt();
void HMI_SetIntNoDraw();
void HMI_SetFloat();
void HMI_SetPFloat();
// Menu auxiliary functions ===================================================
// Create a new menu
bool SetMenu(MenuClass* &menu, FSTR_P title, int8_t totalitems);
//Update the Menu and Draw if it is valid
void UpdateMenu(MenuClass* &menu);
//Redraw the current Menu if it is valid
void ReDrawMenu();
// Clear MenuItems array and free MenuItems elements
void MenuItemsClear();
// Prepare MenuItems array
void MenuItemsPrepare(int8_t totalitems);
// Add elements to the MenuItems array
MenuItemClass* MenuItemsAdd(uint8_t cicon, const char * const text=nullptr, void (*ondraw)(MenuItemClass* menuitem, int8_t line)=nullptr, void (*onclick)()=nullptr);
inline MenuItemClass* MenuItemsAdd(uint8_t cicon, FSTR_P text = nullptr, void (*ondraw)(MenuItemClass* menuitem, int8_t line)=nullptr, void (*onclick)()=nullptr) {
return MenuItemsAdd(cicon, FTOP(text), ondraw, onclick);
}
MenuItemClass* MenuItemsAdd(uint8_t cicon, uint8_t id, uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2, void (*ondraw)(MenuItemClass* menuitem, int8_t line)=nullptr, void (*onclick)()=nullptr);
MenuItemClass* MenuItemsAdd(uint8_t cicon, const char * const text, void (*ondraw)(MenuItemClass* menuitem, int8_t line), void (*onclick)(), void* val);
inline MenuItemClass* MenuItemsAdd(uint8_t cicon, FSTR_P text, void (*ondraw)(MenuItemClass* menuitem, int8_t line), void (*onclick)(), void* val) {
return MenuItemsAdd(cicon, FTOP(text), ondraw, onclick, val);
}

View File

@ -23,8 +23,8 @@
/**
* Mesh Viewer for PRO UI
* Author: Miguel A. Risco-Castillo (MRISCOC)
* version: 3.12.1
* Date: 2022/02/24
* version: 3.14.1
* Date: 2022/04/11
*/
#include "../../../inc/MarlinConfigPre.h"
@ -41,6 +41,10 @@
#include "dwin_popup.h"
#include "../../../feature/bedlevel/bedlevel.h"
#if ENABLED(AUTO_BED_LEVELING_UBL)
#include "ubl_tools.h"
#endif
MeshViewerClass MeshViewer;
void MeshViewerClass::DrawMesh(bed_mesh_t zval, const uint8_t sizex, const uint8_t sizey) {
@ -56,17 +60,15 @@ void MeshViewerClass::DrawMesh(bed_mesh_t zval, const uint8_t sizex, const uint8
#define DrawMeshValue(xp, yp, zv) DWINUI::Draw_Signed_Float(font6x12, 1, 2, px(xp) - 18, py(yp) - 6, zv)
#define DrawMeshHLine(yp) DWIN_Draw_HLine(HMI_data.SplitLine_Color, px(0), py(yp), DWIN_WIDTH - 2 * mx)
#define DrawMeshVLine(xp) DWIN_Draw_VLine(HMI_data.SplitLine_Color, px(xp), py(sizey - 1), DWIN_WIDTH - 2 * my)
int16_t maxz =-32000; int16_t minz = 32000; avg = 0;
int16_t maxz =-32000; int16_t minz = 32000;
LOOP_L_N(y, sizey) LOOP_L_N(x, sizex) {
const float v = isnan(zval[x][y]) ? 0 : round(zval[x][y] * 100);
zmesh[x][y] = v;
avg += v;
NOLESS(maxz, v);
NOMORE(minz, v);
}
max = (float)maxz / 100;
min = (float)minz / 100;
avg = avg / (100 * sizex * sizey);
DWINUI::ClearMainArea();
DWIN_Draw_Rectangle(0, HMI_data.SplitLine_Color, px(0), py(0), px(sizex - 1), py(sizey - 1));
LOOP_S_L_N(x, 1, sizex - 1) DrawMeshVLine(x);
@ -77,8 +79,10 @@ void MeshViewerClass::DrawMesh(bed_mesh_t zval, const uint8_t sizex, const uint8
uint16_t color = DWINUI::RainbowInt(zmesh[x][y], _MIN(-5, minz), _MAX(5, maxz));
uint8_t radius = rm(zmesh[x][y]);
DWINUI::Draw_FillCircle(color, px(x), py(y), radius);
if (sizex < 9)
DWINUI::Draw_Signed_Float(font6x12, 1, 2, px(x) - 18, py(y) - 6, zval[x][y]);
if (sizex < 9) {
if (zmesh[x][y] == 0) DWINUI::Draw_Float(font6x12, 1, 2, px(x) - 12, py(y) - 6, 0);
else DWINUI::Draw_Signed_Float(font6x12, 1, 2, px(x) - 18, py(y) - 6, zval[x][y]);
}
else {
char str_1[9];
str_1[0] = 0;
@ -108,7 +112,13 @@ void MeshViewerClass::DrawMesh(bed_mesh_t zval, const uint8_t sizex, const uint8
void MeshViewerClass::Draw(bool withsave /*= false*/) {
Title.ShowCaption(GET_TEXT_F(MSG_MESH_VIEWER));
#if ENABLED(USE_UBL_VIEWER)
DWINUI::ClearMainArea();
ubl_tools.viewer_print_value = true;
ubl_tools.Draw_Bed_Mesh(-1, 1, 8, 10 + TITLE_HEIGHT);
#else
DrawMesh(Z_VALUES_ARR, GRID_MAX_POINTS_X, GRID_MAX_POINTS_Y);
#endif
if (withsave) {
DWINUI::Draw_Button(BTN_Save, 26, 305);
DWINUI::Draw_Button(BTN_Continue, 146, 305);
@ -117,15 +127,19 @@ void MeshViewerClass::Draw(bool withsave /*= false*/) {
else
DWINUI::Draw_Button(BTN_Continue, 86, 305);
#if ENABLED(USE_UBL_VIEWER)
ubl_tools.Set_Mesh_Viewer_Status();
#else
char str_1[6], str_2[6] = "";
ui.status_printf(0, F("Mesh minZ: %s, maxZ: %s"),
dtostrf(min, 1, 2, str_1),
dtostrf(max, 1, 2, str_2)
);
#endif
}
void Draw_MeshViewer() { MeshViewer.Draw(true); }
void onClick_MeshViewer() { if (HMI_flag.select_flag) WriteEeprom(); HMI_ReturnScreen(); }
void onClick_MeshViewer() { if (HMI_flag.select_flag) SaveMesh(); HMI_ReturnScreen(); }
void Goto_MeshViewer() { if (leveling_is_valid()) Goto_Popup(Draw_MeshViewer, onClick_MeshViewer); else HMI_ReturnScreen(); }
#endif // DWIN_LCD_PROUI && HAS_MESH

View File

@ -27,13 +27,13 @@
/**
* Mesh Viewer for PRO UI
* Author: Miguel A. Risco-Castillo (MRISCOC)
* version: 3.12.1
* Date: 2022/02/24
* version: 3.14.1
* Date: 2022/04/11
*/
class MeshViewerClass {
public:
float avg, max, min;
float max, min;
void Draw(bool withsave = false);
void DrawMesh(bed_mesh_t zval, const uint8_t sizex, const uint8_t sizey);
};

View File

@ -71,7 +71,7 @@ void PrintStatsClass::Draw() {
void PrintStatsClass::Reset() {
print_job_timer.initStats();
HMI_AudioFeedback();
DONE_BUZZ(true);
}
void Goto_PrintStats() {

View File

@ -0,0 +1,255 @@
/**
* UBL Tools and Mesh Viewer for Pro UI
* Version: 1.0.0
* Date: 2022/04/13
*
* Original Author: Henri-J-Norden
* Original Source: https://github.com/Jyers/Marlin/pull/126
*
* 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.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*
*/
#include "../../../inc/MarlinConfigPre.h"
#include "ubl_tools.h"
#if ENABLED(DWIN_LCD_PROUI)
#include "../../marlinui.h"
#include "../../../core/types.h"
#include "dwin.h"
#include "dwinui.h"
#include "dwin_popup.h"
#include "../../../feature/bedlevel/bedlevel.h"
#include "../../../module/probe.h"
#include "../../../gcode/gcode.h"
#include "../../../module/planner.h"
#include "../../../gcode/queue.h"
#include "../../../libs/least_squares_fit.h"
#include "../../../libs/vector_3.h"
UBLMeshToolsClass ubl_tools;
#if ENABLED(USE_UBL_VIEWER)
bool UBLMeshToolsClass::viewer_asymmetric_range = false;
bool UBLMeshToolsClass::viewer_print_value = false;
#endif
bool UBLMeshToolsClass::goto_mesh_value = false;
uint8_t UBLMeshToolsClass::tilt_grid = 1;
bool drawing_mesh = false;
char cmd[MAX_CMD_SIZE+16], str_1[16], str_2[16], str_3[16];
#if ENABLED(AUTO_BED_LEVELING_UBL)
void UBLMeshToolsClass::manual_value_update(const uint8_t mesh_x, const uint8_t mesh_y, bool undefined/*=false*/) {
sprintf_P(cmd, PSTR("M421 I%i J%i Z%s %s"), mesh_x, mesh_y, dtostrf(current_position.z, 1, 3, str_1), undefined ? "N" : "");
gcode.process_subcommands_now(cmd);
planner.synchronize();
}
bool UBLMeshToolsClass::create_plane_from_mesh() {
struct linear_fit_data lsf_results;
incremental_LSF_reset(&lsf_results);
GRID_LOOP(x, y) {
if (!isnan(Z_VALUES_ARR[x][y])) {
xy_pos_t rpos;
rpos.x = ubl.mesh_index_to_xpos(x);
rpos.y = ubl.mesh_index_to_ypos(y);
incremental_LSF(&lsf_results, rpos, Z_VALUES_ARR[x][y]);
}
}
if (finish_incremental_LSF(&lsf_results)) {
SERIAL_ECHOPGM("Could not complete LSF!");
return true;
}
ubl.set_all_mesh_points_to_value(0);
matrix_3x3 rotation = matrix_3x3::create_look_at(vector_3(lsf_results.A, lsf_results.B, 1));
GRID_LOOP(i, j) {
float mx = ubl.mesh_index_to_xpos(i),
my = ubl.mesh_index_to_ypos(j),
mz = Z_VALUES_ARR[i][j];
if (DEBUGGING(LEVELING)) {
DEBUG_ECHOPAIR_F("before rotation = [", mx, 7);
DEBUG_CHAR(',');
DEBUG_ECHO_F(my, 7);
DEBUG_CHAR(',');
DEBUG_ECHO_F(mz, 7);
DEBUG_ECHOPGM("] ---> ");
DEBUG_DELAY(20);
}
rotation.apply_rotation_xyz(mx, my, mz);
if (DEBUGGING(LEVELING)) {
DEBUG_ECHOPAIR_F("after rotation = [", mx, 7);
DEBUG_CHAR(',');
DEBUG_ECHO_F(my, 7);
DEBUG_CHAR(',');
DEBUG_ECHO_F(mz, 7);
DEBUG_ECHOLNPGM("]");
DEBUG_DELAY(20);
}
Z_VALUES_ARR[i][j] = mz - lsf_results.D;
}
return false;
}
#else
void UBLMeshToolsClass::manual_value_update(const uint8_t mesh_x, const uint8_t mesh_y) {
sprintf_P(cmd, PSTR("G29 I%i J%i Z%s"), mesh_x, mesh_y, dtostrf(current_position.z, 1, 3, str_1));
gcode.process_subcommands_now(cmd);
planner.synchronize();
}
#endif
void UBLMeshToolsClass::manual_move(const uint8_t mesh_x, const uint8_t mesh_y, bool zmove/*=false*/) {
if (zmove) {
planner.synchronize();
current_position.z = goto_mesh_value ? Z_VALUES_ARR[mesh_x][mesh_y] : Z_CLEARANCE_BETWEEN_PROBES;
planner.buffer_line(current_position, homing_feedrate(Z_AXIS), active_extruder);
planner.synchronize();
}
else {
DWIN_Show_Popup(ICON_BLTouch, F("Moving to Point"), F("Please wait until done."));
HMI_SaveProcessID(NothingToDo);
sprintf_P(cmd, PSTR("G0 F300 Z%s"), dtostrf(Z_CLEARANCE_BETWEEN_PROBES, 1, 3, str_1));
gcode.process_subcommands_now(cmd);
sprintf_P(cmd, PSTR("G42 F4000 I%i J%i"), mesh_x, mesh_y);
gcode.process_subcommands_now(cmd);
planner.synchronize();
current_position.z = goto_mesh_value ? Z_VALUES_ARR[mesh_x][mesh_y] : Z_CLEARANCE_BETWEEN_PROBES;
planner.buffer_line(current_position, homing_feedrate(Z_AXIS), active_extruder);
planner.synchronize();
HMI_ReturnScreen();
}
}
float UBLMeshToolsClass::get_max_value() {
float max = __FLT_MIN__;
GRID_LOOP(x, y) {
if (!isnan(Z_VALUES_ARR[x][y]) && Z_VALUES_ARR[x][y] > max)
max = Z_VALUES_ARR[x][y];
}
return max;
}
float UBLMeshToolsClass::get_min_value() {
float min = __FLT_MAX__;
GRID_LOOP(x, y) {
if (!isnan(Z_VALUES_ARR[x][y]) && Z_VALUES_ARR[x][y] < min)
min = Z_VALUES_ARR[x][y];
}
return min;
}
bool UBLMeshToolsClass::validate() {
float min = __FLT_MAX__;
float max = __FLT_MIN__;
GRID_LOOP(x, y) {
if (isnan(Z_VALUES_ARR[x][y])) return false;
if (Z_VALUES_ARR[x][y] < min) min = Z_VALUES_ARR[x][y];
if (Z_VALUES_ARR[x][y] > max) max = Z_VALUES_ARR[x][y];
}
return max <= UBL_Z_OFFSET_MAX && min >= UBL_Z_OFFSET_MIN;
}
#if ENABLED(USE_UBL_VIEWER)
void UBLMeshToolsClass::Draw_Bed_Mesh(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;
const uint16_t total_width_px = DWIN_WIDTH - padding_x - padding_x;
const uint16_t cell_width_px = total_width_px / GRID_MAX_POINTS_X;
const uint16_t cell_height_px = total_width_px / GRID_MAX_POINTS_Y;
const float v_max = abs(get_max_value()), v_min = abs(get_min_value()), range = _MAX(v_min, v_max);
// Clear background from previous selection and select new square
DWIN_Draw_Rectangle(1, Color_Bg_Black, _MAX(0, padding_x - gridline_width), _MAX(0, padding_y_top - gridline_width), padding_x + total_width_px, padding_y_top + total_width_px);
if (selected >= 0) {
const auto selected_y = selected / GRID_MAX_POINTS_X;
const auto selected_x = selected - (GRID_MAX_POINTS_X * selected_y);
const auto start_y_px = padding_y_top + selected_y * cell_height_px;
const auto start_x_px = padding_x + selected_x * cell_width_px;
DWIN_Draw_Rectangle(1, Color_White, _MAX(0, start_x_px - gridline_width), _MAX(0, start_y_px - gridline_width), start_x_px + cell_width_px, start_y_px + cell_height_px);
}
// Draw value square grid
char buf[8];
GRID_LOOP(x, y) {
const auto start_x_px = padding_x + x * cell_width_px;
const auto end_x_px = start_x_px + cell_width_px - 1 - gridline_width;
const auto start_y_px = padding_y_top + (GRID_MAX_POINTS_Y - y - 1) * cell_height_px;
const auto end_y_px = start_y_px + cell_height_px - 1 - gridline_width;
DWIN_Draw_Rectangle(1, // RGB565 colors: http://www.barth-dev.de/online/rgb565-color-picker/
isnan(Z_VALUES_ARR[x][y]) ? Color_Grey : ( // gray if undefined
(Z_VALUES_ARR[x][y] < 0 ?
(uint16_t)round(0x1F * -Z_VALUES_ARR[x][y] / (!viewer_asymmetric_range ? range : v_min)) << 11 : // red if mesh point value is negative
(uint16_t)round(0x3F * Z_VALUES_ARR[x][y] / (!viewer_asymmetric_range ? range : v_max)) << 5) | // green if mesh point value is positive
_MIN(0x1F, (((uint8_t)abs(Z_VALUES_ARR[x][y]) / 10) * 4))), // + blue stepping for every mm
start_x_px, start_y_px, end_x_px, end_y_px
);
safe_delay(10);
LCD_SERIAL.flushTX();
// Draw value text on
if (viewer_print_value) {
int8_t offset_x, offset_y = cell_height_px / 2 - 6;
if (isnan(Z_VALUES_ARR[x][y])) { // undefined
DWIN_Draw_String(false, font6x12, Color_White, Color_Bg_Blue, start_x_px + cell_width_px / 2 - 5, start_y_px + offset_y, F("X"));
}
else { // has value
if (GRID_MAX_POINTS_X < 10)
sprintf_P(buf, PSTR("%s"), dtostrf(abs(Z_VALUES_ARR[x][y]), 1, 2, str_1));
else
sprintf_P(buf, PSTR("%02i"), (uint16_t)(abs(Z_VALUES_ARR[x][y] - (int16_t)Z_VALUES_ARR[x][y]) * 100));
offset_x = cell_width_px / 2 - 3 * (strlen(buf)) - 2;
if (!(GRID_MAX_POINTS_X < 10))
DWIN_Draw_String(false, font6x12, Color_White, Color_Bg_Blue, start_x_px - 2 + offset_x, start_y_px + offset_y /*+ square / 2 - 6*/, F("."));
DWIN_Draw_String(false, font6x12, Color_White, Color_Bg_Blue, start_x_px + 1 + offset_x, start_y_px + offset_y /*+ square / 2 - 6*/, buf);
}
safe_delay(10);
LCD_SERIAL.flushTX();
}
}
}
void UBLMeshToolsClass::Set_Mesh_Viewer_Status() { // TODO: draw gradient with values as a legend instead
float v_max = abs(get_max_value()), v_min = abs(get_min_value()), range = _MAX(v_min, v_max);
if (v_min > 3e+10F) v_min = 0.0000001;
if (v_max > 3e+10F) v_max = 0.0000001;
if (range > 3e+10F) range = 0.0000001;
char msg[46];
if (viewer_asymmetric_range) {
dtostrf(-v_min, 1, 3, str_1);
dtostrf( v_max, 1, 3, str_2);
}
else {
dtostrf(-range, 1, 3, str_1);
dtostrf( range, 1, 3, str_2);
}
sprintf_P(msg, PSTR("Red %s..0..%s Green"), str_1, str_2);
ui.set_status(msg);
drawing_mesh = false;
}
#endif
#endif // DWIN_LCD_PROUI

View File

@ -0,0 +1,59 @@
/**
* UBL Tools and Mesh Viewer for Pro UI
* Version: 1.0.0
* Date: 2022/04/13
*
* Original Author: Henri-J-Norden (https://github.com/Henri-J-Norden)
* Original Source: https://github.com/Jyers/Marlin/pull/135
*
* 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.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*
*/
#pragma once
#include "../../../inc/MarlinConfigPre.h"
//#define USE_UBL_VIEWER 1
#define UBL_Z_OFFSET_MIN -3.0
#define UBL_Z_OFFSET_MAX 3.0
class UBLMeshToolsClass {
public:
#if ENABLED(USE_UBL_VIEWER)
static bool viewer_asymmetric_range;
static bool viewer_print_value;
#endif
static bool goto_mesh_value;
static uint8_t tilt_grid;
#if ENABLED(AUTO_BED_LEVELING_UBL)
static void manual_value_update(const uint8_t mesh_x, const uint8_t mesh_y, bool undefined=false);
static bool create_plane_from_mesh();
#else
static void manual_value_update(const uint8_t mesh_x, const uint8_t mesh_y);
#endif
static void manual_move(const uint8_t mesh_x, const uint8_t mesh_y, bool zmove=false);
static float get_max_value();
static float get_min_value();
static bool validate();
#if ENABLED(USE_UBL_VIEWER)
static void Draw_Bed_Mesh(int16_t selected = -1, uint8_t gridline_width = 1, uint16_t padding_x = 8, uint16_t padding_y_top = 40 + 53 - 7);
static void Set_Mesh_Viewer_Status();
#endif
};
extern UBLMeshToolsClass ubl_tools;
void Goto_MeshViewer();

View File

@ -53,6 +53,8 @@ namespace Language_en {
LSTR WELCOME_MSG = MACHINE_NAME _UxGT(" Ready.");
LSTR MSG_YES = _UxGT("YES");
LSTR MSG_NO = _UxGT("NO");
LSTR MSG_HIGH = _UxGT("HIGH");
LSTR MSG_LOW = _UxGT("LOW");
LSTR MSG_BACK = _UxGT("Back");
LSTR MSG_ERROR = _UxGT("Error");
LSTR MSG_MEDIA_ABORTING = _UxGT("Aborting...");
@ -68,6 +70,8 @@ namespace Language_en {
LSTR MSG_LCD_SOFT_ENDSTOPS = _UxGT("Soft Endstops");
LSTR MSG_MAIN = _UxGT("Main");
LSTR MSG_ADVANCED_SETTINGS = _UxGT("Advanced Settings");
LSTR MSG_TOOLBAR_SETUP = _UxGT("Toolbar Setup");
LSTR MSG_OPTION_DISABLED = _UxGT("Option Disabled");
LSTR MSG_CONFIGURATION = _UxGT("Configuration");
LSTR MSG_RUN_AUTO_FILES = _UxGT("Run Auto Files");
LSTR MSG_DISABLE_STEPPERS = _UxGT("Disable Steppers");
@ -81,6 +85,7 @@ namespace Language_en {
LSTR MSG_AUTO_HOME_Z = _UxGT("Home Z");
LSTR MSG_FILAMENT_SET = _UxGT("Filament Settings");
LSTR MSG_FILAMENT_MAN = _UxGT("Filament Management");
LSTR MSG_MANUAL_LEVELING = _UxGT("Manual Leveling");
LSTR MSG_LEVBED_FL = _UxGT("Front Left");
LSTR MSG_LEVBED_FR = _UxGT("Front Right");
LSTR MSG_LEVBED_C = _UxGT("Center");
@ -116,7 +121,14 @@ namespace Language_en {
LSTR MSG_PREHEAT_1_ALL = _UxGT("Preheat ") PREHEAT_1_LABEL _UxGT(" All");
LSTR MSG_PREHEAT_1_BEDONLY = _UxGT("Preheat ") PREHEAT_1_LABEL _UxGT(" Bed");
LSTR MSG_PREHEAT_1_SETTINGS = _UxGT("Preheat ") PREHEAT_1_LABEL _UxGT(" Conf");
#ifdef PREHEAT_2_LABEL
LSTR MSG_PREHEAT_2 = _UxGT("Preheat ") PREHEAT_2_LABEL;
LSTR MSG_PREHEAT_2_SETTINGS = _UxGT("Preheat ") PREHEAT_2_LABEL _UxGT(" Conf");
#endif
#ifdef PREHEAT_3_LABEL
LSTR MSG_PREHEAT_3 = _UxGT("Preheat ") PREHEAT_3_LABEL;
LSTR MSG_PREHEAT_3_SETTINGS = _UxGT("Preheat ") PREHEAT_3_LABEL _UxGT(" Conf");
#endif
LSTR MSG_PREHEAT_M = _UxGT("Preheat $");
LSTR MSG_PREHEAT_M_H = _UxGT("Preheat $ ~");
LSTR MSG_PREHEAT_M_END = _UxGT("Preheat $ End");
@ -163,10 +175,19 @@ namespace Language_en {
LSTR MSG_MESH_VIEW = _UxGT("View Mesh");
LSTR MSG_EDITING_STOPPED = _UxGT("Mesh Editing Stopped");
LSTR MSG_NO_VALID_MESH = _UxGT("No valid mesh");
LSTR MSG_ACTIVATE_MESH = _UxGT("Activate Leveling");
LSTR MSG_PROBING_POINT = _UxGT("Probing Point");
LSTR MSG_MESH_X = _UxGT("Index X");
LSTR MSG_MESH_Y = _UxGT("Index Y");
LSTR MSG_MESH_INSET = _UxGT("Mesh Inset");
LSTR MSG_MESH_MIN_X = _UxGT("Mesh X Minimum");
LSTR MSG_MESH_MAX_X = _UxGT("Mesh X Maximum");
LSTR MSG_MESH_MIN_Y = _UxGT("Mesh Y Minimum");
LSTR MSG_MESH_MAX_Y = _UxGT("Mesh Y Maximum");
LSTR MSG_MESH_AMAX = _UxGT("Maximize Area");
LSTR MSG_MESH_CENTER = _UxGT("Center Area");
LSTR MSG_MESH_EDIT_Z = _UxGT("Z Value");
LSTR MSG_MESH_CANCEL = _UxGT("Mesh cancelled");
LSTR MSG_CUSTOM_COMMANDS = _UxGT("Custom Commands");
LSTR MSG_M48_TEST = _UxGT("M48 Probe Test");
LSTR MSG_M48_POINT = _UxGT("M48 Point");
@ -185,6 +206,9 @@ namespace Language_en {
LSTR MSG_UBL_TOOLS = _UxGT("UBL Tools");
LSTR MSG_UBL_LEVEL_BED = _UxGT("Unified Bed Leveling");
LSTR MSG_LCD_TILTING_MESH = _UxGT("Tilting Point");
LSTR MSG_UBL_TILT_MESH = _UxGT("Tilt Mesh");
LSTR MSG_UBL_TILTING_GRID = _UxGT("Tilting Grid Size");
LSTR MSG_UBL_MESH_TILTED = _UxGT("Mesh Tilted");
LSTR MSG_UBL_MANUAL_MESH = _UxGT("Manually Build Mesh");
LSTR MSG_UBL_MESH_WIZARD = _UxGT("UBL Mesh Wizard");
LSTR MSG_UBL_BC_INSERT = _UxGT("Place Shim & Measure");
@ -233,6 +257,7 @@ namespace Language_en {
LSTR MSG_UBL_MANUAL_FILLIN = _UxGT("Manual Fill-in");
LSTR MSG_UBL_SMART_FILLIN = _UxGT("Smart Fill-in");
LSTR MSG_UBL_FILLIN_MESH = _UxGT("Fill-in Mesh");
LSTR MSG_UBL_MESH_FILLED = _UxGT("Missing Points Filled");
LSTR MSG_UBL_INVALIDATE_ALL = _UxGT("Invalidate All");
LSTR MSG_UBL_INVALIDATE_CLOSEST = _UxGT("Invalidate Closest");
LSTR MSG_UBL_FINE_TUNE_ALL = _UxGT("Fine Tune All");
@ -241,6 +266,7 @@ namespace Language_en {
LSTR MSG_UBL_STORAGE_SLOT = _UxGT("Memory Slot");
LSTR MSG_UBL_LOAD_MESH = _UxGT("Load Bed Mesh");
LSTR MSG_UBL_SAVE_MESH = _UxGT("Save Bed Mesh");
LSTR MSG_UBL_INVALID_SLOT = _UxGT("First Select a Mesh Slot");
LSTR MSG_MESH_LOADED = _UxGT("Mesh %i Loaded");
LSTR MSG_MESH_SAVED = _UxGT("Mesh %i Saved");
LSTR MSG_UBL_NO_STORAGE = _UxGT("No Storage");
@ -344,6 +370,7 @@ namespace Language_en {
LSTR MSG_PID_AUTOTUNE_FAILED = _UxGT("PID Autotune failed!");
LSTR MSG_BAD_EXTRUDER_NUM = _UxGT("Bad extruder.");
LSTR MSG_TEMP_TOO_HIGH = _UxGT("Temperature too high.");
LSTR MSG_TIMEOUT = _UxGT("Timeout.");
LSTR MSG_PID_BAD_EXTRUDER_NUM = _UxGT("Autotune failed! Bad extruder.");
LSTR MSG_PID_TEMP_TOO_HIGH = _UxGT("Autotune failed! Temperature too high.");
LSTR MSG_PID_TIMEOUT = _UxGT("Autotune failed! Timeout.");
@ -420,6 +447,10 @@ namespace Language_en {
LSTR MSG_RESET_PRINTER = _UxGT("Reset Printer");
LSTR MSG_REFRESH = LCD_STR_REFRESH _UxGT("Refresh");
LSTR MSG_INFO_SCREEN = _UxGT("Info Screen");
LSTR MSG_INFO_MACHINENAME = _UxGT("Machine Name");
LSTR MSG_INFO_SIZE = _UxGT("Size");
LSTR MSG_INFO_FWVERSION = _UxGT("Firmware Version");
LSTR MSG_INFO_BUILD = _UxGT("Build Datetime");
LSTR MSG_PREPARE = _UxGT("Prepare");
LSTR MSG_TUNE = _UxGT("Tune");
LSTR MSG_POWER_MONITOR = _UxGT("Power monitor");
@ -446,6 +477,7 @@ namespace Language_en {
LSTR MSG_BUTTON_RESUME = _UxGT("Resume");
LSTR MSG_BUTTON_ADVANCED = _UxGT("Advanced");
LSTR MSG_BUTTON_SAVE = _UxGT("Save");
LSTR MSG_BUTTON_PURGE = _UxGT("Purge");
LSTR MSG_PAUSING = _UxGT("Pausing...");
LSTR MSG_PAUSE_PRINT = _UxGT("Pause Print");
LSTR MSG_ADVANCED_PAUSE = _UxGT("Advanced Pause");
@ -468,9 +500,12 @@ namespace Language_en {
LSTR MSG_REMAINING_TIME = _UxGT("Remaining");
LSTR MSG_PRINT_ABORTED = _UxGT("Print Aborted");
LSTR MSG_PRINT_DONE = _UxGT("Print Done");
LSTR MSG_PRINTER_KILLED = _UxGT("Printer killed!");
LSTR MSG_TURN_OFF = _UxGT("Turn off the printer");
LSTR MSG_NO_MOVE = _UxGT("No Move.");
LSTR MSG_KILLED = _UxGT("KILLED. ");
LSTR MSG_STOPPED = _UxGT("STOPPED. ");
LSTR MSG_FWRETRACT = _UxGT("Firmware Retract");
LSTR MSG_CONTROL_RETRACT = _UxGT("Retract mm");
LSTR MSG_CONTROL_RETRACT_SWAP = _UxGT("Swap Re.mm");
LSTR MSG_CONTROL_RETRACTF = _UxGT("Retract V");
@ -536,6 +571,9 @@ namespace Language_en {
LSTR MSG_ZPROBE_XOFFSET = _UxGT("Probe X Offset");
LSTR MSG_ZPROBE_YOFFSET = _UxGT("Probe Y Offset");
LSTR MSG_ZPROBE_ZOFFSET = _UxGT("Probe Z Offset");
LSTR MSG_ZPROBE_MARGIN = _UxGT("Probe Margin");
LSTR MSG_Z_FEED_RATE = _UxGT("Z Feed Rate");
LSTR MSG_ENABLE_HS_MODE = _UxGT("Enable HS mode");
LSTR MSG_MOVE_NOZZLE_TO_BED = _UxGT("Move Nozzle to Bed");
LSTR MSG_BABYSTEP_X = _UxGT("Babystep X");
LSTR MSG_BABYSTEP_Y = _UxGT("Babystep Y");
@ -603,18 +641,6 @@ namespace Language_en {
LSTR MSG_CASE_LIGHT_BRIGHTNESS = _UxGT("Light Brightness");
LSTR MSG_KILL_EXPECTED_PRINTER = _UxGT("INCORRECT PRINTER");
LSTR MSG_LOCKSCREEN = _UxGT("Lock Screen");
LSTR MSG_LOCKSCREEN_LOCKED = _UxGT("Printer is Locked,");
LSTR MSG_LOCKSCREEN_UNLOCK = _UxGT("Scroll to unlock.");
#if LCD_WIDTH >= 20 || HAS_DWIN_E3V2
LSTR MSG_MEDIA_NOT_INSERTED = _UxGT("No media inserted.");
LSTR MSG_PLEASE_WAIT_REBOOT = _UxGT("Please wait until reboot. ");
LSTR MSG_PLEASE_PREHEAT = _UxGT("Please preheat the hot end.");
LSTR MSG_INFO_PRINT_COUNT_RESET = _UxGT("Reset Print Count");
LSTR MSG_INFO_PRINT_COUNT = _UxGT("Print Count");
LSTR MSG_INFO_PRINT_TIME = _UxGT("Print Time");
LSTR MSG_INFO_PRINT_LONGEST = _UxGT("Longest Job Time");
LSTR MSG_INFO_PRINT_FILAMENT = _UxGT("Extruded Total");
LSTR MSG_COLORS_GET = _UxGT("Get Color");
LSTR MSG_COLORS_SELECT = _UxGT("Select Colors");
LSTR MSG_COLORS_APPLIED = _UxGT("Colors applied");
@ -624,6 +650,19 @@ namespace Language_en {
LSTR MSG_COLORS_WHITE = _UxGT("White");
LSTR MSG_UI_LANGUAGE = _UxGT("UI Language");
LSTR MSG_SOUND_ENABLE = _UxGT("Enable sound");
LSTR MSG_LOCKSCREEN = _UxGT("Lock Screen");
LSTR MSG_LOCKSCREEN_LOCKED = _UxGT("Printer is Locked,");
LSTR MSG_LOCKSCREEN_UNLOCK = _UxGT("Scroll to unlock.");
LSTR MSG_PLEASE_WAIT_REBOOT = _UxGT("Please wait until reboot.");
#if LCD_WIDTH >= 20 || HAS_DWIN_E3V2
LSTR MSG_MEDIA_NOT_INSERTED = _UxGT("No media inserted.");
LSTR MSG_PLEASE_PREHEAT = _UxGT("Please preheat the hot end.");
LSTR MSG_INFO_PRINT_COUNT_RESET = _UxGT("Reset Print Count");
LSTR MSG_INFO_PRINT_COUNT = _UxGT("Print Count");
LSTR MSG_INFO_PRINT_TIME = _UxGT("Print Time");
LSTR MSG_INFO_PRINT_LONGEST = _UxGT("Longest Job Time");
LSTR MSG_INFO_PRINT_FILAMENT = _UxGT("Extruded Total");
#else
LSTR MSG_MEDIA_NOT_INSERTED = _UxGT("No Media");
LSTR MSG_PLEASE_PREHEAT = _UxGT("Please Preheat");
@ -654,10 +693,14 @@ namespace Language_en {
LSTR MSG_FILAMENT_CHANGE_OPTION_HEADER = _UxGT("RESUME OPTIONS:");
LSTR MSG_FILAMENT_CHANGE_OPTION_PURGE = _UxGT("Purge more");
LSTR MSG_FILAMENT_CHANGE_OPTION_RESUME = _UxGT("Continue");
LSTR MSG_FILAMENT_CHANGE_PURGE_CONTINUE = _UxGT("Purge or Continue?");
LSTR MSG_FILAMENT_CHANGE_NOZZLE = _UxGT(" Nozzle: ");
LSTR MSG_RUNOUT_SENSOR = _UxGT("Runout Sensor");
LSTR MSG_RUNOUT_DISTANCE_MM = _UxGT("Runout Dist mm");
LSTR MSG_RUNOUT_ENABLE = _UxGT("Enable Runout");
LSTR MSG_RUNOUT_ACTIVE = _UxGT("Runout Active");
LSTR MSG_INVERT_EXTRUDER = _UxGT("Invert Extruder");
LSTR MSG_EXTRUDER_MIN_TEMP = _UxGT("Extruder Min Temp.");
LSTR MSG_FANCHECK = _UxGT("Fan Tacho Check");
LSTR MSG_KILL_HOMING_FAILED = _UxGT("Homing Failed");
LSTR MSG_LCD_PROBING_FAILED = _UxGT("Probing Failed");