Merge upstream changes from Marlin 2.1.1

This commit is contained in:
Stefan Kalscheuer
2022-09-03 09:23:32 +02:00
parent 626283aadb
commit 986e416c7f
1610 changed files with 73839 additions and 40857 deletions

View File

@@ -1,6 +1,6 @@
# DWIN for Creality Ender 3 v2
Marlin's Ender 3 v2 support requires the `DWIN_SET` included with the Ender 3 V2 [example configuration](https://github.com/MarlinFirmware/Configurations/tree/bugfix-2.0.x/config/examples/Creality/Ender-3%20V2).
Marlin's Ender 3 v2 support requires the `DWIN_SET` included with the Ender 3 V2 [example configuration](https://github.com/MarlinFirmware/Configurations/tree/bugfix-2.1.x/config/examples/Creality/Ender-3%20V2).
## Easy Install

View File

@@ -21,10 +21,11 @@
*/
#include "../../../inc/MarlinConfigPre.h"
#if EITHER(HAS_DWIN_E3V2, IS_DWIN_MARLINUI)
#if HAS_DWIN_E3V2 || IS_DWIN_MARLINUI
#include "dwin_api.h"
#include "dwin_set.h"
#include "dwin_font.h"
#include "../../../inc/MarlinConfig.h"
@@ -89,6 +90,40 @@ bool DWIN_Handshake() {
}
#endif
// Get font character width
uint8_t fontWidth(uint8_t cfont) {
switch (cfont) {
case font6x12 : return 6;
case font8x16 : return 8;
case font10x20: return 10;
case font12x24: return 12;
case font14x28: return 14;
case font16x32: return 16;
case font20x40: return 20;
case font24x48: return 24;
case font28x56: return 28;
case font32x64: return 32;
default: return 0;
}
}
// Get font character height
uint8_t fontHeight(uint8_t cfont) {
switch (cfont) {
case font6x12 : return 12;
case font8x16 : return 16;
case font10x20: return 20;
case font12x24: return 24;
case font14x28: return 28;
case font16x32: return 32;
case font20x40: return 40;
case font24x48: return 48;
case font28x56: return 56;
case font32x64: return 64;
default: return 0;
}
}
// Set screen display direction
// dir: 0=0°, 1=90°, 2=180°, 3=270°
void DWIN_Frame_SetDir(uint8_t dir) {
@@ -199,6 +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);
@@ -228,6 +266,7 @@ void DWIN_Draw_String(bool bShow, uint8_t size, uint16_t color, uint16_t bColor,
void DWIN_Draw_IntValue(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, uint32_t value) {
size_t i = 0;
DWIN_Draw_Rectangle(1, bColor, x, y, x + fontWidth(size) * iNum + 1, y + fontHeight(size));
DWIN_Byte(i, 0x14);
// Bit 7: bshow
// Bit 6: 1 = signed; 0 = unsigned number;
@@ -275,6 +314,7 @@ void DWIN_Draw_FloatValue(uint8_t bShow, bool zeroFill, uint8_t zeroMode, uint8_
uint16_t bColor, uint8_t iNum, uint8_t fNum, uint16_t x, uint16_t y, int32_t value) {
//uint8_t *fvalue = (uint8_t*)&value;
size_t i = 0;
DWIN_Draw_Rectangle(1, bColor, x, y, x + fontWidth(size) * (iNum+fNum+1), y + fontHeight(size));
DWIN_Byte(i, 0x14);
DWIN_Byte(i, (bShow * 0x80) | (zeroFill * 0x20) | (zeroMode * 0x10) | size);
DWIN_Word(i, color);

View File

@@ -23,10 +23,11 @@
#include "../../../inc/MarlinConfig.h"
#ifndef DWIN_WIDTH
#if ENABLED(DWIN_MARLINUI_LANDSCAPE)
#define DWIN_WIDTH 480
#define DWIN_HEIGHT 272
#else
#define DWIN_WIDTH 272
#endif
#ifndef DWIN_HEIGHT
#define DWIN_HEIGHT 480
#endif
@@ -73,7 +74,7 @@ inline void DWIN_Text(size_t &i, const char * const string, uint16_t rlimit=0xFF
inline void DWIN_Text(size_t &i, FSTR_P string, uint16_t rlimit=0xFFFF) {
if (!string) return;
const size_t len = _MIN(sizeof(DWIN_SendBuf) - i, _MIN(rlimit, strlen_P((PGM_P)string))); // cast to PGM_P (const char*) measure with strlen_P.
const size_t len = _MIN(sizeof(DWIN_SendBuf) - i, _MIN(rlimit, strlen_P(FTOP(string))));
if (len == 0) return;
memcpy_P(&DWIN_SendBuf[i+1], string, len);
i += len;
@@ -174,9 +175,14 @@ void DWIN_Frame_AreaMove(uint8_t mode, uint8_t dir, uint16_t dis,
// rlimit: For draw less chars than string length use rlimit
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);
inline void DWIN_Draw_String(bool bShow, uint8_t size, uint16_t color, uint16_t bColor, uint16_t x, uint16_t y, FSTR_P title) {
// Note that this won't work on AVR, only 32-bit systems!
DWIN_Draw_String(bShow, size, color, bColor, x, y, FTOP(title));
inline void DWIN_Draw_String(bool bShow, uint8_t size, uint16_t color, uint16_t bColor, uint16_t x, uint16_t y, FSTR_P const ftitle) {
#ifdef __AVR__
char ctitle[strlen_P(FTOP(ftitle)) + 1];
strcpy_P(ctitle, FTOP(ftitle));
DWIN_Draw_String(bShow, size, color, bColor, x, y, ctitle);
#else
DWIN_Draw_String(bShow, size, color, bColor, x, y, FTOP(ftitle));
#endif
}
// Draw a positive integer

View File

@@ -21,6 +21,8 @@
*/
#pragma once
typedef uint8_t fontid_t;
/**
* 3-.0The font size, 0x00-0x09, corresponds to the font size below:
* 0x00=6*12 0x01=8*16 0x02=10*20 0x03=12*24 0x04=14*28

View File

@@ -25,7 +25,16 @@
#define Language_English 1
#define Language_Chinese 2
#define ICON 7 // Icon set file 7.ICO
//#define USE_STOCK_DWIN_SET // Use the Creality stock DWIN_SET instead of Marlin's unified DWIN_SET by The-EG & thinkyhead
#ifdef USE_STOCK_DWIN_SET
#define ICON 9 // 9.ICO
#else
#define ICON 7 // 7.ICO
#endif
#ifndef CORP_WEBSITE
#define CORP_WEBSITE WEBSITE_URL
#endif
#define ICON_LOGO 0
#define ICON_Print_0 1

View File

@@ -36,7 +36,7 @@
#include "../../marlinui.h"
#include "../../../HAL/shared/Delay.h"
#if HAS_BUZZER
#if HAS_SOUND
#include "../../../libs/buzzer.h"
#endif
@@ -50,13 +50,7 @@ ENCODER_Rate EncoderRate;
// TODO: Replace with ui.quick_feedback
void Encoder_tick() {
#if PIN_EXISTS(BEEPER)
if (ui.buzzer_enabled) {
WRITE(BEEPER_PIN, HIGH);
delay(10);
WRITE(BEEPER_PIN, LOW);
}
#endif
TERN_(HAS_BEEPER, if (ui.sound_on) buzzer.click(10));
}
// Encoder initialization
@@ -70,7 +64,7 @@ void Encoder_Configuration() {
#if BUTTON_EXISTS(ENC)
SET_INPUT_PULLUP(BTN_ENC);
#endif
#if PIN_EXISTS(BEEPER)
#if HAS_BEEPER
SET_OUTPUT(BEEPER_PIN); // TODO: Use buzzer.h which already inits this
#endif
}

View File

@@ -45,12 +45,32 @@ typedef enum {
ENCODER_DIFF_ENTER = 3 // click
} EncoderState;
#define ENCODER_WAIT_MS 20
// Encoder initialization
void Encoder_Configuration();
// Analyze encoder value and return state
EncoderState Encoder_ReceiveAnalyze();
inline EncoderState get_encoder_state() {
static millis_t Encoder_ms = 0;
const millis_t ms = millis();
if (PENDING(ms, Encoder_ms)) return ENCODER_DIFF_NO;
const EncoderState state = Encoder_ReceiveAnalyze();
if (state != ENCODER_DIFF_NO) Encoder_ms = ms + ENCODER_WAIT_MS;
return state;
}
template<typename T>
inline bool Apply_Encoder(const EncoderState &encoder_diffState, T &valref) {
if (encoder_diffState == ENCODER_DIFF_CW)
valref += EncoderRate.encoderMoveValue;
else if (encoder_diffState == ENCODER_DIFF_CCW)
valref -= EncoderRate.encoderMoveValue;
return encoder_diffState == ENCODER_DIFF_ENTER;
}
/*********************** Encoder LED ***********************/
#if PIN_EXISTS(LCD_LED)

View File

@@ -33,7 +33,7 @@
//#define USE_STRING_HEADINGS
//#define USE_STRING_TITLES
#if ENABLED(LCD_BED_LEVELING) && DISABLED(PROBE_MANUALLY) && ANY(AUTO_BED_LEVELING_BILINEAR, AUTO_BED_LEVELING_LINEAR, AUTO_BED_LEVELING_3POINT)
#if DISABLED(PROBE_MANUALLY) && ANY(AUTO_BED_LEVELING_BILINEAR, AUTO_BED_LEVELING_LINEAR, AUTO_BED_LEVELING_3POINT)
#define HAS_ONESTEP_LEVELING 1
#endif
@@ -91,9 +91,6 @@
#ifndef MACHINE_SIZE
#define MACHINE_SIZE STRINGIFY(X_BED_SIZE) "x" STRINGIFY(Y_BED_SIZE) "x" STRINGIFY(Z_MAX_POS)
#endif
#ifndef CORP_WEBSITE
#define CORP_WEBSITE WEBSITE_URL
#endif
#define PAUSE_HEAT
@@ -165,14 +162,15 @@ typedef struct {
} select_t;
select_t select_page{0}, select_file{0}, select_print{0}, select_prepare{0}
, select_control{0}, select_axis{0}, select_temp{0}, select_motion{0}, select_tune{0}
, select_advset{0}, select_PLA{0}, select_ABS{0}
, select_speed{0}
, select_acc{0}
, select_jerk{0}
, select_step{0}
, select_item{0}
;
, select_control{0}, select_axis{0}, select_temp{0}, select_motion{0}, select_tune{0}
, select_advset{0}, select_speed{0}, select_acc{0}, select_jerk{0}, select_step{0}, select_item{0};
#if HAS_PREHEAT
select_t select_PLA{0};
#if PREHEAT_COUNT > 1
select_t select_ABS{0};
#endif
#endif
uint8_t index_file = MROWS,
index_prepare = MROWS,
@@ -359,12 +357,8 @@ inline void Clear_Title_Bar() {
DWIN_Draw_Box(1, Color_Bg_Blue, 0, 0, DWIN_WIDTH, TITLE_HEIGHT);
}
void Draw_Title(const char * const title) {
DWIN_Draw_String(false, DWIN_FONT_HEAD, Color_White, Color_Bg_Blue, 14, 4, (char*)title);
}
void Draw_Title(FSTR_P title) {
DWIN_Draw_String(false, DWIN_FONT_HEAD, Color_White, Color_Bg_Blue, 14, 4, (char*)title);
void Draw_Title(FSTR_P ftitle) {
DWIN_Draw_String(false, DWIN_FONT_HEAD, Color_White, Color_Bg_Blue, 14, 4, ftitle);
}
inline void Clear_Menu_Area() {
@@ -420,32 +414,40 @@ inline uint16_t nr_sd_menu_items() {
return card.get_num_Files() + !card.flag.workDirIsRoot;
}
void Draw_Menu_Icon(const uint8_t line, const uint8_t icon) {
DWIN_ICON_Show(ICON, icon, 26, MBASE(line) - 3);
}
void Erase_Menu_Text(const uint8_t line) {
DWIN_Draw_Rectangle(1, Color_Bg_Black, LBLX, MBASE(line) - 14, 271, MBASE(line) + 28);
}
void Draw_Menu_Item(const uint8_t line, const uint8_t icon=0, const char * const label=nullptr, bool more=false) {
if (label) DWIN_Draw_String(false, font8x16, Color_White, Color_Bg_Black, LBLX, MBASE(line) - 1, (char*)label);
void Draw_Menu_Icon(const uint8_t line, const uint8_t icon) {
DWIN_ICON_Show(ICON, icon, 26, MBASE(line) - 3);
}
void _Decorate_Menu_Item(const uint8_t line, const uint8_t icon, bool more) {
if (icon) Draw_Menu_Icon(line, icon);
if (more) Draw_More_Icon(line);
}
void Draw_Menu_Item(const uint8_t line, const uint8_t icon=0, const char * const label=nullptr, bool more=false) {
if (label) DWIN_Draw_String(false, font8x16, Color_White, Color_Bg_Black, LBLX, MBASE(line) - 1, (char*)label);
_Decorate_Menu_Item(line, icon, more);
}
void Draw_Menu_Item(const uint8_t line, const uint8_t icon=0, FSTR_P const flabel=nullptr, bool more=false) {
if (flabel) DWIN_Draw_String(false, font8x16, Color_White, Color_Bg_Black, LBLX, MBASE(line) - 1, flabel);
_Decorate_Menu_Item(line, icon, more);
}
void Draw_Menu_Line(const uint8_t line, const uint8_t icon=0, const char * const label=nullptr, bool more=false) {
Draw_Menu_Item(line, icon, label, more);
DWIN_Draw_Line(Line_Color, 16, MBASE(line) + 33, 256, MBASE(line) + 34);
}
void Draw_Menu_LineF(const uint8_t line, const uint8_t icon=0, FSTR_P label=nullptr, bool more=false) {
Draw_Menu_Line(line, icon, (char*)label, more);
void Draw_Menu_Line(const uint8_t line, const uint8_t icon, FSTR_P const flabel, bool more=false) {
Draw_Menu_Item(line, icon, flabel, more);
DWIN_Draw_Line(Line_Color, 16, MBASE(line) + 33, 256, MBASE(line) + 34);
}
void Draw_Checkbox_Line(const uint8_t line, const bool ison) {
const uint16_t x = 225, y = EBASE(line) - 2;
DWIN_Draw_String(true, font8x16, Color_White, Color_Bg_Black, x + 5, y, F(ison ? "X" : " "));
DWIN_Draw_String(true, font8x16, Color_White, Color_Bg_Black, x + 5, y, ison ? F("X") : F(" "));
DWIN_Draw_Rectangle(0, Color_White, x + 2, y + 2, x + 16, y + 16);
}
@@ -469,15 +471,6 @@ void Draw_Back_First(const bool is_sel=true) {
if (is_sel) Draw_Menu_Cursor(0);
}
template <typename T>
inline bool Apply_Encoder(const EncoderState &encoder_diffState, T &valref) {
if (encoder_diffState == ENCODER_DIFF_CW)
valref += EncoderRate.encoderMoveValue;
else if (encoder_diffState == ENCODER_DIFF_CCW)
valref -= EncoderRate.encoderMoveValue;
return encoder_diffState == ENCODER_DIFF_ENTER;
}
//
// Draw Menus
//
@@ -493,8 +486,8 @@ inline bool Apply_Encoder(const EncoderState &encoder_diffState, T &valref) {
#define PREPARE_CASE_DISA 2
#define PREPARE_CASE_HOME 3
#define PREPARE_CASE_ZOFF (PREPARE_CASE_HOME + ENABLED(HAS_ZOFFSET_ITEM))
#define PREPARE_CASE_PLA (PREPARE_CASE_ZOFF + ENABLED(HAS_HOTEND))
#define PREPARE_CASE_ABS (PREPARE_CASE_PLA + ENABLED(HAS_HOTEND))
#define PREPARE_CASE_PLA (PREPARE_CASE_ZOFF + ENABLED(HAS_PREHEAT))
#define PREPARE_CASE_ABS (PREPARE_CASE_PLA + (TERN0(HAS_PREHEAT, PREHEAT_COUNT > 1)))
#define PREPARE_CASE_COOL (PREPARE_CASE_ABS + EITHER(HAS_HOTEND, HAS_HEATED_BED))
#define PREPARE_CASE_LANG (PREPARE_CASE_COOL + 1)
#define PREPARE_CASE_TOTAL PREPARE_CASE_LANG
@@ -518,8 +511,8 @@ inline bool Apply_Encoder(const EncoderState &encoder_diffState, T &valref) {
#define TEMP_CASE_TEMP (0 + ENABLED(HAS_HOTEND))
#define TEMP_CASE_BED (TEMP_CASE_TEMP + ENABLED(HAS_HEATED_BED))
#define TEMP_CASE_FAN (TEMP_CASE_BED + ENABLED(HAS_FAN))
#define TEMP_CASE_PLA (TEMP_CASE_FAN + ENABLED(HAS_HOTEND))
#define TEMP_CASE_ABS (TEMP_CASE_PLA + ENABLED(HAS_HOTEND))
#define TEMP_CASE_PLA (TEMP_CASE_FAN + ENABLED(HAS_PREHEAT))
#define TEMP_CASE_ABS (TEMP_CASE_PLA + (TERN0(HAS_PREHEAT, PREHEAT_COUNT > 1)))
#define TEMP_CASE_TOTAL TEMP_CASE_ABS
#define PREHEAT_CASE_TEMP (0 + ENABLED(HAS_HOTEND))
@@ -611,7 +604,7 @@ void Draw_Edit_Float3(const uint8_t row, const uint16_t value, const bool active
}
void Draw_Edit_Signed_Float2(const uint8_t row, const float value, const bool active=false) {
DWIN_Draw_Signed_Float(font8x16, active ? Select_Color : Color_Bg_Black, 2, UNITFDIGITS, 220 + 8 - UNITFDIGITS * 8, EBASE(row), value);
DWIN_Draw_Signed_Float(font8x16, active ? Select_Color : Color_Bg_Black, 2, UNITFDIGITS + 1, 220 + 8 - UNITFDIGITS * 8, EBASE(row), value);
}
void Draw_Edit_Signed_Float3(const uint8_t row, const float value, const bool active=false) {
@@ -696,7 +689,7 @@ void Item_Prepare_Home(const uint8_t row) {
#endif
#if HAS_HOTEND
#if HAS_PREHEAT
void Item_Prepare_PLA(const uint8_t row) {
if (HMI_IsChinese())
Item_AreaCopy(100, 89, 151, 101, row);
@@ -711,22 +704,22 @@ void Item_Prepare_Home(const uint8_t row) {
Draw_Menu_Line(row, ICON_PLAPreheat);
}
void Item_Prepare_ABS(const uint8_t row) {
if (HMI_IsChinese())
Item_AreaCopy(180, 89, 233, 100, row);
else {
#ifdef USE_STRING_TITLES
DWIN_Draw_Label(row, F("Preheat " PREHEAT_2_LABEL));
#else
Item_AreaCopy(108, 76, 155, 87, row); // "Preheat"
say_abs_en(52, row); // "ABS"
#endif
#if PREHEAT_COUNT > 1
void Item_Prepare_ABS(const uint8_t row) {
if (HMI_IsChinese())
Item_AreaCopy(180, 89, 233, 100, row);
else {
#ifdef USE_STRING_TITLES
DWIN_Draw_Label(row, F("Preheat " PREHEAT_2_LABEL));
#else
Item_AreaCopy(108, 76, 155, 87, row); // "Preheat"
say_abs_en(52, row); // "ABS"
#endif
}
Draw_Menu_Line(row, ICON_ABSPreheat);
}
Draw_Menu_Line(row, ICON_ABSPreheat);
}
#endif
#endif
#if HAS_PREHEAT
void Item_Prepare_Cool(const uint8_t row) {
if (HMI_IsChinese())
Item_AreaCopy(1, 104, 56, 117, row);
@@ -781,11 +774,13 @@ void Draw_Prepare_Menu() {
#if HAS_ZOFFSET_ITEM
if (PVISI(PREPARE_CASE_ZOFF)) Item_Prepare_Offset(PSCROL(PREPARE_CASE_ZOFF)); // Edit Z-Offset / Babystep / Set Home Offset
#endif
#if HAS_HOTEND
if (PVISI(PREPARE_CASE_PLA)) Item_Prepare_PLA(PSCROL(PREPARE_CASE_PLA)); // Preheat PLA
if (PVISI(PREPARE_CASE_ABS)) Item_Prepare_ABS(PSCROL(PREPARE_CASE_ABS)); // Preheat ABS
#endif
#if HAS_PREHEAT
if (PVISI(PREPARE_CASE_PLA)) Item_Prepare_PLA(PSCROL(PREPARE_CASE_PLA)); // Preheat PLA
#if PREHEAT_COUNT > 1
if (PVISI(PREPARE_CASE_ABS)) Item_Prepare_ABS(PSCROL(PREPARE_CASE_ABS)); // Preheat ABS
#endif
#endif
#if HAS_HOTEND || HAS_HEATED_BED
if (PVISI(PREPARE_CASE_COOL)) Item_Prepare_Cool(PSCROL(PREPARE_CASE_COOL)); // Cooldown
#endif
if (PVISI(PREPARE_CASE_LANG)) Item_Prepare_Lang(PSCROL(PREPARE_CASE_LANG)); // Language CN/EN
@@ -1292,15 +1287,6 @@ void Goto_MainMenu() {
TERN(HAS_ONESTEP_LEVELING, ICON_Leveling, ICON_StartInfo)();
}
inline EncoderState get_encoder_state() {
static millis_t Encoder_ms = 0;
const millis_t ms = millis();
if (PENDING(ms, Encoder_ms)) return ENCODER_DIFF_NO;
const EncoderState state = Encoder_ReceiveAnalyze();
if (state != ENCODER_DIFF_NO) Encoder_ms = ms + ENCODER_WAIT_MS;
return state;
}
void HMI_Plan_Move(const feedRate_t fr_mm_s) {
if (!planner.is_full()) {
planner.synchronize();
@@ -1380,8 +1366,6 @@ void HMI_Move_Z() {
#if HAS_ZOFFSET_ITEM
bool printer_busy() { return planner.movesplanned() || printingIsActive(); }
void HMI_Zoffset() {
EncoderState encoder_diffState = Encoder_ReceiveAnalyze();
if (encoder_diffState == ENCODER_DIFF_NO) return;
@@ -1421,25 +1405,34 @@ void HMI_Move_Z() {
uint8_t temp_line;
switch (HMI_ValueStruct.show_mode) {
case -1: temp_line = TEMP_CASE_TEMP; break;
case -2: temp_line = PREHEAT_CASE_TEMP; break;
case -3: temp_line = PREHEAT_CASE_TEMP; break;
#if HAS_PREHEAT
case -2: temp_line = PREHEAT_CASE_TEMP; break;
#if PREHEAT_COUNT > 1
case -3: temp_line = PREHEAT_CASE_TEMP; break;
#endif
#endif
default: temp_line = TUNE_CASE_TEMP + MROWS - index_tune;
}
if (Apply_Encoder(encoder_diffState, HMI_ValueStruct.E_Temp)) {
EncoderRate.enabled = false;
if (HMI_ValueStruct.show_mode == -2) {
checkkey = PLAPreheat;
ui.material_preset[0].hotend_temp = HMI_ValueStruct.E_Temp;
Draw_Edit_Integer3(temp_line, ui.material_preset[0].hotend_temp);
return;
}
else if (HMI_ValueStruct.show_mode == -3) {
checkkey = ABSPreheat;
ui.material_preset[1].hotend_temp = HMI_ValueStruct.E_Temp;
Draw_Edit_Integer3(temp_line, ui.material_preset[1].hotend_temp);
return;
}
else if (HMI_ValueStruct.show_mode == -1) // Temperature
#if HAS_PREHEAT
if (HMI_ValueStruct.show_mode == -2) {
checkkey = PLAPreheat;
ui.material_preset[0].hotend_temp = HMI_ValueStruct.E_Temp;
Draw_Edit_Integer3(temp_line, ui.material_preset[0].hotend_temp);
return;
}
#if PREHEAT_COUNT > 1
if (HMI_ValueStruct.show_mode == -3) {
checkkey = ABSPreheat;
ui.material_preset[1].hotend_temp = HMI_ValueStruct.E_Temp;
Draw_Edit_Integer3(temp_line, ui.material_preset[1].hotend_temp);
return;
}
#endif
#endif
if (HMI_ValueStruct.show_mode == -1) // Temperature
checkkey = TemperatureID;
else
checkkey = Tune;
@@ -1463,28 +1456,33 @@ void HMI_Move_Z() {
uint8_t bed_line;
switch (HMI_ValueStruct.show_mode) {
case -1: bed_line = TEMP_CASE_BED; break;
case -2: bed_line = PREHEAT_CASE_BED; break;
case -3: bed_line = PREHEAT_CASE_BED; break;
#if HAS_PREHEAT
case -2: bed_line = PREHEAT_CASE_BED; break;
#if PREHEAT_COUNT > 1
case -3: bed_line = PREHEAT_CASE_BED; break;
#endif
#endif
default: bed_line = TUNE_CASE_BED + MROWS - index_tune;
}
if (Apply_Encoder(encoder_diffState, HMI_ValueStruct.Bed_Temp)) {
EncoderRate.enabled = false;
if (HMI_ValueStruct.show_mode == -2) {
checkkey = PLAPreheat;
ui.material_preset[0].bed_temp = HMI_ValueStruct.Bed_Temp;
Draw_Edit_Integer3(bed_line, ui.material_preset[0].bed_temp);
return;
}
else if (HMI_ValueStruct.show_mode == -3) {
checkkey = ABSPreheat;
ui.material_preset[1].bed_temp = HMI_ValueStruct.Bed_Temp;
Draw_Edit_Integer3(bed_line, ui.material_preset[1].bed_temp);
return;
}
else if (HMI_ValueStruct.show_mode == -1)
checkkey = TemperatureID;
else
checkkey = Tune;
#if HAS_PREHEAT
if (HMI_ValueStruct.show_mode == -2) {
checkkey = PLAPreheat;
ui.material_preset[0].bed_temp = HMI_ValueStruct.Bed_Temp;
Draw_Edit_Integer3(bed_line, ui.material_preset[0].bed_temp);
return;
}
#if PREHEAT_COUNT > 1
if (HMI_ValueStruct.show_mode == -3) {
checkkey = ABSPreheat;
ui.material_preset[1].bed_temp = HMI_ValueStruct.Bed_Temp;
Draw_Edit_Integer3(bed_line, ui.material_preset[1].bed_temp);
return;
}
#endif
#endif
checkkey = HMI_ValueStruct.show_mode == -1 ? TemperatureID : Tune;
Draw_Edit_Integer3(bed_line, HMI_ValueStruct.Bed_Temp);
thermalManager.setTargetBed(HMI_ValueStruct.Bed_Temp);
return;
@@ -1518,16 +1516,15 @@ void HMI_Move_Z() {
Draw_Edit_Integer3(fan_line, ui.material_preset[0].fan_speed);
return;
}
else if (HMI_ValueStruct.show_mode == -3) {
checkkey = ABSPreheat;
ui.material_preset[1].fan_speed = HMI_ValueStruct.Fan_speed;
Draw_Edit_Integer3(fan_line, ui.material_preset[1].fan_speed);
return;
}
else if (HMI_ValueStruct.show_mode == -1)
checkkey = TemperatureID;
else
checkkey = Tune;
#if PREHEAT_COUNT > 1
if (HMI_ValueStruct.show_mode == -3) {
checkkey = ABSPreheat;
ui.material_preset[1].fan_speed = HMI_ValueStruct.Fan_speed;
Draw_Edit_Integer3(fan_line, ui.material_preset[1].fan_speed);
return;
}
#endif
checkkey = HMI_ValueStruct.show_mode == -1 ? TemperatureID : Tune;
Draw_Edit_Integer3(fan_line, HMI_ValueStruct.Fan_speed);
thermalManager.set_fan_speed(0, HMI_ValueStruct.Fan_speed);
return;
@@ -1655,7 +1652,7 @@ void _update_axis_value(const AxisEnum axis, const uint16_t x, const uint16_t y,
else if (blink && draw_empty)
DWIN_Draw_String(true, font8x16, Color_White, Color_Bg_Black, x, y, F(" "));
else
DWIN_Draw_FloatValue(true, true, 0, font8x16, Color_White, Color_Bg_Black, 3, 1, x, y, p * 10);
DWIN_Draw_FloatValue(true, true, 0, font8x16, Color_White, Color_Bg_Black, 3, 1, x, y, p);
}
}
@@ -1734,7 +1731,7 @@ void update_variable() {
if (_new_hotend_target)
Draw_Stat_Int(25 + 4 * STAT_CHR_W + 6, 384, _hotendtarget);
static int16_t _flow = planner.flow_percentage[0];
static int16_t _flow = 0;
if (_flow != planner.flow_percentage[0]) {
_flow = planner.flow_percentage[0];
Draw_Stat_Int(116 + 2 * STAT_CHR_W, 417, _flow);
@@ -1748,7 +1745,7 @@ void update_variable() {
Draw_Stat_Int(25 + 4 * STAT_CHR_W + 6, 417, _bedtarget);
#endif
static int16_t _feedrate = 100;
static int16_t _feedrate = 0;
if (_feedrate != feedrate_percentage) {
_feedrate = feedrate_percentage;
Draw_Stat_Int(116 + 2 * STAT_CHR_W, 384, _feedrate);
@@ -1765,11 +1762,11 @@ void update_variable() {
if (BABY_Z_VAR != _offset) {
_offset = BABY_Z_VAR;
if (BABY_Z_VAR < 0) {
Draw_Stat_Float(207, 417, -_offset * 100);
Draw_Stat_Float(207, 417, -_offset);
DWIN_Draw_String(true, font8x16, Color_White, Color_Bg_Black, 205, 419, F("-"));
}
else {
Draw_Stat_Float(207, 417, _offset * 100);
Draw_Stat_Float(207, 417, _offset);
DWIN_Draw_String(true, font8x16, Color_White, Color_Bg_Black, 205, 419, F(" "));
}
}
@@ -1814,6 +1811,9 @@ void make_name_without_ext(char *dst, char *src, size_t maxlen=MENU_CHAR_LIMIT)
void HMI_SDCardInit() { card.cdroot(); }
// Initialize or re-initialize the LCD
void MarlinUI::init_lcd() { DWIN_Startup(); }
void MarlinUI::refresh() { /* Nothing to see here */ }
#if HAS_LCD_BRIGHTNESS
@@ -1853,7 +1853,7 @@ void Draw_SDItem(const uint16_t item, int16_t row=-1) {
if (row < 0) row = item + 1 + MROWS - index_file;
const bool is_subdir = !card.flag.workDirIsRoot;
if (is_subdir && item == 0) {
Draw_Menu_Line(row, ICON_Folder, "..");
Draw_Menu_Line(row, ICON_Folder, F(".."));
return;
}
@@ -2249,6 +2249,8 @@ void HMI_SelectFile() {
// thermalManager.fan_speed[i] = 255;
#endif
_card_percent = 0;
_remain_time = 0;
Goto_PrintProcess();
}
}
@@ -2348,7 +2350,7 @@ void HMI_PauseOrStop() {
if (select_print.now == PRINT_PAUSE_RESUME) {
if (HMI_flag.select_flag) {
HMI_flag.pause_action = true;
queue.inject_P(PSTR("M25"));
queue.inject(F("M25"));
}
Goto_PrintProcess();
}
@@ -2359,7 +2361,7 @@ void HMI_PauseOrStop() {
card.abortFilePrintSoon(); // Let the main loop handle SD abort
dwin_abort_flag = true; // Reset feedrate, return to Home
#ifdef ACTION_ON_CANCEL
host_action_cancel();
hostui.cancel();
#endif
Popup_Window_Home(true);
if (HMI_flag.home_flag) planner.synchronize(); // Wait for planner moves to finish!
@@ -2531,7 +2533,7 @@ void Item_HomeOffs_X(const uint8_t row) {
}
else {
#ifdef USE_STRING_TITLES
Draw_Menu_LineF(row, ICON_HomeOffsetX, GET_TEXT_F(MSG_HOME_OFFSET_X));
Draw_Menu_Line(row, ICON_HomeOffsetX, GET_TEXT_F(MSG_HOME_OFFSET_X));
#else
say_home_offs_en(row); say_x_en(75, row); // "Home Offset X"
#endif
@@ -2546,7 +2548,7 @@ void Item_HomeOffs_Y(const uint8_t row) {
}
else {
#ifdef USE_STRING_TITLES
Draw_Menu_LineF(row, ICON_HomeOffsetY, GET_TEXT_F(MSG_HOME_OFFSET_Y));
Draw_Menu_Line(row, ICON_HomeOffsetY, GET_TEXT_F(MSG_HOME_OFFSET_Y));
#else
say_home_offs_en(row); say_y_en(75, row); // "Home Offset X"
#endif
@@ -2561,7 +2563,7 @@ void Item_HomeOffs_Z(const uint8_t row) {
}
else {
#ifdef USE_STRING_TITLES
Draw_Menu_LineF(row, ICON_HomeOffsetZ, GET_TEXT_F(MSG_HOME_OFFSET_Z));
Draw_Menu_Line(row, ICON_HomeOffsetZ, GET_TEXT_F(MSG_HOME_OFFSET_Z));
#else
say_home_offs_en(row); say_z_en(75, row); // "Home Offset Z"
#endif
@@ -2604,8 +2606,8 @@ void Draw_HomeOff_Menu() {
DWIN_Frame_TitleCopy(124, 431, 91, 12); // "Probe Offsets"
#endif
#ifdef USE_STRING_TITLES
Draw_Menu_LineF(1, ICON_ProbeOffsetX, GET_TEXT_F(MSG_ZPROBE_XOFFSET)); // Probe X Offset
Draw_Menu_LineF(2, ICON_ProbeOffsetY, GET_TEXT_F(MSG_ZPROBE_YOFFSET)); // Probe Y Offset
Draw_Menu_Line(1, ICON_ProbeOffsetX, GET_TEXT_F(MSG_ZPROBE_XOFFSET)); // Probe X Offset
Draw_Menu_Line(2, ICON_ProbeOffsetY, GET_TEXT_F(MSG_ZPROBE_YOFFSET)); // Probe Y Offset
#else
say_probe_offs_en(1); say_x_en(75, 1); // "Probe Offset X"
say_probe_offs_en(2); say_y_en(75, 2); // "Probe Offset Y"
@@ -2623,15 +2625,13 @@ void Draw_HomeOff_Menu() {
#include "../../../libs/buzzer.h"
void HMI_AudioFeedback(const bool success=true) {
#if HAS_BUZZER
if (success) {
buzzer.tone(100, 659);
buzzer.tone(10, 0);
buzzer.tone(100, 698);
}
else
buzzer.tone(40, 440);
#endif
if (success) {
BUZZ(100, 659);
BUZZ(10, 0);
BUZZ(100, 698);
}
else
BUZZ(40, 440);
}
// Prepare
@@ -2652,10 +2652,10 @@ void HMI_Prepare() {
// Draw "More" icon for sub-menus
if (index_prepare < 7) Draw_More_Icon(MROWS - index_prepare + 1);
#if HAS_HOTEND
#if PREHEAT_COUNT > 1
if (index_prepare == PREPARE_CASE_ABS) Item_Prepare_ABS(MROWS);
#endif
#if HAS_PREHEAT
#if HAS_HOTEND || HAS_HEATED_BED
if (index_prepare == PREPARE_CASE_COOL) Item_Prepare_Cool(MROWS);
#endif
if (index_prepare == PREPARE_CASE_LANG) Item_Prepare_Lang(MROWS);
@@ -2707,7 +2707,7 @@ void HMI_Prepare() {
#endif
break;
case PREPARE_CASE_DISA: queue.inject_P(PSTR("M84")); break;
case PREPARE_CASE_DISA: queue.inject(F("M84")); break;
case PREPARE_CASE_HOME: // Homing
checkkey = Last_Prepare;
@@ -2715,6 +2715,7 @@ void HMI_Prepare() {
queue.inject_P(G28_STR); // G28 will set home_flag
Popup_Window_Home();
break;
#if HAS_ZOFFSET_ITEM
case PREPARE_CASE_ZOFF:
#if EITHER(HAS_BED_PROBE, BABYSTEPPING)
@@ -2725,33 +2726,31 @@ void HMI_Prepare() {
EncoderRate.enabled = true;
#else
// Apply workspace offset, making the current position 0,0,0
queue.inject_P(PSTR("G92 X0 Y0 Z0"));
queue.inject(F("G92X0Y0Z0"));
HMI_AudioFeedback();
#endif
break;
#endif
#if HAS_PREHEAT
case PREPARE_CASE_PLA:
TERN_(HAS_HOTEND, thermalManager.setTargetHotend(ui.material_preset[0].hotend_temp, 0));
TERN_(HAS_HEATED_BED, thermalManager.setTargetBed(ui.material_preset[0].bed_temp));
TERN_(HAS_FAN, thermalManager.set_fan_speed(0, ui.material_preset[0].fan_speed));
break;
case PREPARE_CASE_ABS:
TERN_(HAS_HOTEND, thermalManager.setTargetHotend(ui.material_preset[1].hotend_temp, 0));
TERN_(HAS_HEATED_BED, thermalManager.setTargetBed(ui.material_preset[1].bed_temp));
TERN_(HAS_FAN, thermalManager.set_fan_speed(0, ui.material_preset[1].fan_speed));
break;
case PREPARE_CASE_PLA: ui.preheat_all(0); break;
#if PREHEAT_COUNT > 1
case PREPARE_CASE_ABS: ui.preheat_all(1); break;
#endif
#endif
#if HAS_HOTEND || HAS_HEATED_BED
case PREPARE_CASE_COOL:
TERN_(HAS_FAN, thermalManager.zero_fan_speeds());
#if HAS_HOTEND || HAS_HEATED_BED
thermalManager.disable_all_heaters();
#endif
thermalManager.cooldown();
ui.reset_status();
break;
#endif
case PREPARE_CASE_LANG:
HMI_ToggleLanguage();
Draw_Prepare_Menu();
break;
default: break;
}
}
@@ -2772,9 +2771,11 @@ void Draw_Temperature_Menu() {
#if HAS_FAN
Item_AreaCopy(115, 134, 170, 146, TEMP_CASE_FAN);
#endif
#if HAS_HOTEND
#if HAS_PREHEAT
Item_AreaCopy(100, 89, 178, 101, TEMP_CASE_PLA);
Item_AreaCopy(180, 89, 260, 100, TEMP_CASE_ABS);
#if PREHEAT_COUNT > 1
Item_AreaCopy(180, 89, 260, 100, TEMP_CASE_ABS);
#endif
#endif
}
else {
@@ -2793,30 +2794,33 @@ void Draw_Temperature_Menu() {
#if HAS_FAN
DWIN_Draw_Label(TEMP_CASE_FAN, GET_TEXT_F(MSG_FAN_SPEED));
#endif
#if HAS_HOTEND
#if HAS_PREHEAT
DWIN_Draw_Label(TEMP_CASE_PLA, F(PREHEAT_1_LABEL " Preheat Settings"));
DWIN_Draw_Label(TEMP_CASE_ABS, F(PREHEAT_2_LABEL " Preheat Settings"));
#if PREHEAT_COUNT > 1
DWIN_Draw_Label(TEMP_CASE_ABS, F(PREHEAT_2_LABEL " Preheat Settings"));
#endif
#endif
#else
#if HAS_HOTEND
Item_AreaCopy(197, 104, 238, 114, TEMP_CASE_TEMP); // "Nozzle"
Item_AreaCopy(1, 89, 83, 101, TEMP_CASE_TEMP, 44); // "Temperature"
Item_AreaCopy(197, 104, 238, 114, TEMP_CASE_TEMP); // "Nozzle"
Item_AreaCopy(1, 89, 83, 101, TEMP_CASE_TEMP, 44); // "Temperature"
#endif
#if HAS_HEATED_BED
Item_AreaCopy(240, 104, 264, 114, TEMP_CASE_BED); // "Bed"
Item_AreaCopy(1, 89, 83, 101, TEMP_CASE_BED, 27); // "Temperature"
Item_AreaCopy(240, 104, 264, 114, TEMP_CASE_BED); // "Bed"
Item_AreaCopy(1, 89, 83, 101, TEMP_CASE_BED, 27); // "Temperature"
#endif
#if HAS_FAN
Item_AreaCopy( 1, 119, 61, 132, TEMP_CASE_FAN); // "Fan speed"
Item_AreaCopy( 1, 119, 61, 132, TEMP_CASE_FAN); // "Fan speed"
#endif
#if HAS_HOTEND
Item_AreaCopy(107, 76, 156, 86, TEMP_CASE_PLA); // "Preheat"
say_pla_en(52, TEMP_CASE_PLA); // "PLA"
Item_AreaCopy(150, 135, 202, 148, TEMP_CASE_PLA, 79); // "Settings"
Item_AreaCopy(107, 76, 156, 86, TEMP_CASE_ABS); // "Preheat"
say_abs_en(52, TEMP_CASE_ABS); // "ABS"
Item_AreaCopy(150, 135, 202, 148, TEMP_CASE_ABS, 81); // "Settings"
#if HAS_PREHEAT
Item_AreaCopy(107, 76, 156, 86, TEMP_CASE_PLA); // "Preheat"
say_pla_en(52, TEMP_CASE_PLA); // "PLA"
Item_AreaCopy(150, 135, 202, 148, TEMP_CASE_PLA, 79); // "Settings"
#if PREHEAT_COUNT > 1
Item_AreaCopy(107, 76, 156, 86, TEMP_CASE_ABS); // "Preheat"
say_abs_en(52, TEMP_CASE_ABS); // "ABS"
Item_AreaCopy(150, 135, 202, 148, TEMP_CASE_ABS, 81); // "Settings"
#endif
#endif
#endif
}
@@ -2839,12 +2843,12 @@ void Draw_Temperature_Menu() {
_TMENU_ICON(TEMP_CASE_FAN);
Draw_Edit_Integer3(i, thermalManager.fan_speed[0]);
#endif
#if HAS_HOTEND
#if HAS_PREHEAT
// PLA/ABS items have submenus
_TMENU_ICON(TEMP_CASE_PLA);
Draw_More_Icon(i);
_TMENU_ICON(TEMP_CASE_ABS);
Draw_More_Icon(i);
_TMENU_ICON(TEMP_CASE_PLA); Draw_More_Icon(i);
#if PREHEAT_COUNT > 1
_TMENU_ICON(TEMP_CASE_ABS); Draw_More_Icon(i);
#endif
#endif
}
@@ -2940,7 +2944,7 @@ void HMI_Control() {
void HMI_Leveling() {
Popup_Window_Leveling();
DWIN_UpdateLCD();
queue.inject_P(PSTR("G28O\nG29"));
queue.inject(F("G28O\nG29"));
}
#endif
@@ -3064,7 +3068,8 @@ void HMI_Temperature() {
EncoderRate.enabled = true;
break;
#endif
#if HAS_HOTEND
#if HAS_PREHEAT
case TEMP_CASE_PLA: {
checkkey = PLAPreheat;
select_PLA.reset();
@@ -3090,7 +3095,7 @@ void HMI_Temperature() {
}
else {
#ifdef USE_STRING_HEADINGS
Draw_Title(PREHEAT_1_LABEL " Settings"); // TODO: GET_TEXT_F
Draw_Title(F(PREHEAT_1_LABEL " Settings")); // TODO: GET_TEXT_F
#else
DWIN_Frame_TitleCopy(56, 15, 85, 14); // "Temperature" TODO: "PLA Settings"
#endif
@@ -3141,7 +3146,9 @@ void HMI_Temperature() {
Draw_Menu_Line(++i, ICON_WriteEEPROM);
#endif
} break;
#endif // HAS_PREHEAT
#if PREHEAT_COUNT > 1
case TEMP_CASE_ABS: { // ABS preheat setting
checkkey = ABSPreheat;
select_ABS.reset();
@@ -3169,7 +3176,7 @@ void HMI_Temperature() {
}
else {
#ifdef USE_STRING_HEADINGS
Draw_Title("ABS Settings"); // TODO: GET_TEXT_F
Draw_Title(F("ABS Settings")); // TODO: GET_TEXT_F
#else
DWIN_Frame_TitleCopy(56, 15, 85, 14); // "Temperature" TODO: "ABS Settings"
#endif
@@ -3223,7 +3230,7 @@ void HMI_Temperature() {
} break;
#endif // HAS_HOTEND
#endif // PREHEAT_COUNT > 1
}
}
DWIN_UpdateLCD();
@@ -3252,7 +3259,7 @@ void Draw_Max_Speed_Menu() {
}
else {
#ifdef USE_STRING_HEADINGS
Draw_Title("Max Speed (mm/s)"); // TODO: GET_TEXT_F
Draw_Title(F("Max Speed (mm/s)")); // TODO: GET_TEXT_F
#else
DWIN_Frame_TitleCopy(144, 16, 46, 11); // "Max Speed (mm/s)"
#endif
@@ -3547,9 +3554,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
@@ -3566,14 +3573,12 @@ void HMI_AdvSet() {
#if HAS_HOTEND
case ADVSET_CASE_HEPID:
thermalManager.setTargetHotend(ui.material_preset[0].hotend_temp, 0);
thermalManager.PID_autotune(ui.material_preset[0].hotend_temp, H_E0, 10, true);
break;
#endif
#if HAS_HEATED_BED
case ADVSET_CASE_BEDPID:
thermalManager.setTargetBed(ui.material_preset[0].bed_temp);
thermalManager.PID_autotune(ui.material_preset[0].bed_temp, H_BED, 10, true);
break;
#endif
@@ -3799,7 +3804,7 @@ void HMI_Tune() {
EncoderRate.enabled = true;
#else
// Apply workspace offset, making the current position 0,0,0
queue.inject_P(PSTR("G92 X0 Y0 Z0"));
queue.inject(F("G92X0Y0Z0"));
HMI_AudioFeedback();
#endif
break;
@@ -3868,63 +3873,65 @@ void HMI_Tune() {
DWIN_UpdateLCD();
}
// ABS Preheat
void HMI_ABSPreheatSetting() {
EncoderState encoder_diffState = get_encoder_state();
if (encoder_diffState == ENCODER_DIFF_NO) return;
#if PREHEAT_COUNT > 1
// ABS Preheat
void HMI_ABSPreheatSetting() {
EncoderState encoder_diffState = get_encoder_state();
if (encoder_diffState == ENCODER_DIFF_NO) return;
// Avoid flicker by updating only the previous menu
if (encoder_diffState == ENCODER_DIFF_CW) {
if (select_ABS.inc(1 + PREHEAT_CASE_TOTAL)) Move_Highlight(1, select_ABS.now);
}
else if (encoder_diffState == ENCODER_DIFF_CCW) {
if (select_ABS.dec()) Move_Highlight(-1, select_ABS.now);
}
else if (encoder_diffState == ENCODER_DIFF_ENTER) {
switch (select_ABS.now) {
case CASE_BACK:
checkkey = TemperatureID;
select_temp.now = TEMP_CASE_ABS;
HMI_ValueStruct.show_mode = -1;
Draw_Temperature_Menu();
break;
#if HAS_HOTEND
case PREHEAT_CASE_TEMP:
checkkey = ETemp;
HMI_ValueStruct.E_Temp = ui.material_preset[1].hotend_temp;
Draw_Edit_Integer3(PREHEAT_CASE_TEMP, ui.material_preset[1].hotend_temp, true);
EncoderRate.enabled = true;
break;
#endif
#if HAS_HEATED_BED
case PREHEAT_CASE_BED:
checkkey = BedTemp;
HMI_ValueStruct.Bed_Temp = ui.material_preset[1].bed_temp;
Draw_Edit_Integer3(PREHEAT_CASE_BED, ui.material_preset[1].bed_temp, true);
EncoderRate.enabled = true;
break;
#endif
#if HAS_FAN
case PREHEAT_CASE_FAN:
checkkey = FanSpeed;
HMI_ValueStruct.Fan_speed = ui.material_preset[1].fan_speed;
Draw_Edit_Integer3(PREHEAT_CASE_FAN, ui.material_preset[1].fan_speed, true);
EncoderRate.enabled = true;
break;
#endif
#if ENABLED(EEPROM_SETTINGS)
case PREHEAT_CASE_SAVE: {
const bool success = settings.save();
HMI_AudioFeedback(success);
} break;
#endif
default: break;
// Avoid flicker by updating only the previous menu
if (encoder_diffState == ENCODER_DIFF_CW) {
if (select_ABS.inc(1 + PREHEAT_CASE_TOTAL)) Move_Highlight(1, select_ABS.now);
}
else if (encoder_diffState == ENCODER_DIFF_CCW) {
if (select_ABS.dec()) Move_Highlight(-1, select_ABS.now);
}
else if (encoder_diffState == ENCODER_DIFF_ENTER) {
switch (select_ABS.now) {
case CASE_BACK:
checkkey = TemperatureID;
select_temp.now = TEMP_CASE_ABS;
HMI_ValueStruct.show_mode = -1;
Draw_Temperature_Menu();
break;
#if HAS_HOTEND
case PREHEAT_CASE_TEMP:
checkkey = ETemp;
HMI_ValueStruct.E_Temp = ui.material_preset[1].hotend_temp;
Draw_Edit_Integer3(PREHEAT_CASE_TEMP, ui.material_preset[1].hotend_temp, true);
EncoderRate.enabled = true;
break;
#endif
#if HAS_HEATED_BED
case PREHEAT_CASE_BED:
checkkey = BedTemp;
HMI_ValueStruct.Bed_Temp = ui.material_preset[1].bed_temp;
Draw_Edit_Integer3(PREHEAT_CASE_BED, ui.material_preset[1].bed_temp, true);
EncoderRate.enabled = true;
break;
#endif
#if HAS_FAN
case PREHEAT_CASE_FAN:
checkkey = FanSpeed;
HMI_ValueStruct.Fan_speed = ui.material_preset[1].fan_speed;
Draw_Edit_Integer3(PREHEAT_CASE_FAN, ui.material_preset[1].fan_speed, true);
EncoderRate.enabled = true;
break;
#endif
#if ENABLED(EEPROM_SETTINGS)
case PREHEAT_CASE_SAVE: {
const bool success = settings.save();
HMI_AudioFeedback(success);
} break;
#endif
default: break;
}
}
DWIN_UpdateLCD();
}
DWIN_UpdateLCD();
}
#endif // PREHEAT_COUNT > 1
#endif
#endif // HAS_PREHEAT
// Max Speed
void HMI_MaxSpeed() {
@@ -4057,6 +4064,13 @@ void HMI_Init() {
HMI_SetLanguage();
}
void DWIN_InitScreen() {
Encoder_Configuration();
HMI_Init();
HMI_SetLanguageCache();
HMI_StartFrame(true);
}
void DWIN_Update() {
EachMomentUpdate(); // Status update
HMI_SDCardUpdate(); // SD card update
@@ -4108,7 +4122,7 @@ void EachMomentUpdate() {
TERN_(HAS_HEATED_BED, resume_bed_temp = thermalManager.degTargetBed());
thermalManager.disable_all_heaters();
#endif
queue.inject_P(PSTR("G1 F1200 X0 Y0"));
queue.inject(F("G1 F1200 X0 Y0"));
}
if (card.isPrinting() && checkkey == PrintProcess) { // print process
@@ -4149,10 +4163,7 @@ void EachMomentUpdate() {
}
#if ENABLED(POWER_LOSS_RECOVERY)
else if (DWIN_lcd_sd_status && recovery.dwin_flag) { // resume print before power off
static bool recovery_flag = false;
recovery.dwin_flag = false;
recovery_flag = true;
auto update_selection = [&](const bool sel) {
HMI_flag.select_flag = sel;
@@ -4172,13 +4183,14 @@ void EachMomentUpdate() {
DWIN_Draw_String(true, font8x16, Popup_Text_Color, Color_Bg_Window, npos, 252, name);
DWIN_UpdateLCD();
bool recovery_flag = true;
while (recovery_flag) {
EncoderState encoder_diffState = Encoder_ReceiveAnalyze();
if (encoder_diffState != ENCODER_DIFF_NO) {
if (encoder_diffState == ENCODER_DIFF_ENTER) {
recovery_flag = false;
if (HMI_flag.select_flag) break;
TERN_(POWER_LOSS_RECOVERY, queue.inject_P(PSTR("M1000C")));
TERN_(POWER_LOSS_RECOVERY, queue.inject(F("M1000C")));
HMI_StartFrame(true);
return;
}
@@ -4191,7 +4203,7 @@ void EachMomentUpdate() {
select_print.set(0);
HMI_ValueStruct.show_mode = 0;
queue.inject_P(PSTR("M1000"));
queue.inject(F("M1000"));
Goto_PrintProcess();
Draw_Status_Area(true);
}
@@ -4228,7 +4240,9 @@ void DWIN_HandleScreen() {
case Tune: HMI_Tune(); break;
#if HAS_PREHEAT
case PLAPreheat: HMI_PLAPreheatSetting(); break;
case ABSPreheat: HMI_ABSPreheatSetting(); break;
#if PREHEAT_COUNT > 1
case ABSPreheat: HMI_ABSPreheatSetting(); break;
#endif
#endif
case MaxSpeed: HMI_MaxSpeed(); break;
case MaxAcceleration: HMI_MaxAcceleration(); break;
@@ -4263,7 +4277,7 @@ void DWIN_HandleScreen() {
}
}
void DWIN_CompletedHoming() {
void DWIN_HomingDone() {
HMI_flag.home_flag = false;
dwin_zoffset = TERN0(HAS_BED_PROBE, probe.offset.z);
if (checkkey == Last_Prepare) {
@@ -4279,21 +4293,25 @@ void DWIN_CompletedHoming() {
}
}
void DWIN_CompletedLeveling() {
void DWIN_LevelingDone() {
if (checkkey == Leveling) Goto_MainMenu();
}
void DWIN_StatusChanged(const char *text) {
void DWIN_StatusChanged(const char * const cstr/*=nullptr*/) {
DWIN_Draw_Rectangle(1, Color_Bg_Blue, 0, STATUS_Y, DWIN_WIDTH, STATUS_Y + 24);
const int8_t x = _MAX(0U, DWIN_WIDTH - strlen_P(text) * MENU_CHR_W) / 2;
DWIN_Draw_String(false, font8x16, Color_White, Color_Bg_Blue, x, STATUS_Y + 3, F(text));
const int8_t x = _MAX(0U, DWIN_WIDTH - strlen(cstr) * MENU_CHR_W) / 2;
DWIN_Draw_String(false, font8x16, Color_White, Color_Bg_Blue, x, STATUS_Y + 3, cstr);
DWIN_UpdateLCD();
}
void DWIN_StatusChanged_P(PGM_P const pstr) {
char str[strlen_P((const char*)pstr) + 1];
strcpy_P(str, (const char*)pstr);
DWIN_StatusChanged(str);
void DWIN_StatusChanged(FSTR_P const fstr) {
#ifdef __AVR__
char str[strlen_P(FTOP(fstr)) + 1];
strcpy_P(str, FTOP(fstr));
DWIN_StatusChanged(str);
#else
DWIN_StatusChanged(FTOP(fstr));
#endif
}
#endif // DWIN_CREALITY_LCD

View File

@@ -31,13 +31,6 @@
#include "../../../inc/MarlinConfigPre.h"
#if ANY(HAS_HOTEND, HAS_HEATED_BED, HAS_FAN) && PREHEAT_COUNT
#define HAS_PREHEAT 1
#if PREHEAT_COUNT < 2
#error "Creality DWIN requires two material preheat presets."
#endif
#endif
enum processID : uint8_t {
// Process ID
MainMenu,
@@ -53,7 +46,9 @@ enum processID : uint8_t {
Tune,
#if HAS_PREHEAT
PLAPreheat,
ABSPreheat,
#if PREHEAT_COUNT > 1
ABSPreheat,
#endif
#endif
MaxSpeed,
MaxSpeed_value,
@@ -241,13 +236,14 @@ void HMI_MaxJerk(); // Maximum jerk speed submenu
void HMI_Step(); // Transmission ratio
void HMI_Init();
void DWIN_InitScreen();
void DWIN_Update();
void EachMomentUpdate();
void DWIN_HandleScreen();
void DWIN_StatusChanged(const char *text);
void DWIN_StatusChanged_P(PGM_P const pstr);
void DWIN_StatusChanged(const char * const cstr=nullptr);
void DWIN_StatusChanged(FSTR_P const fstr);
inline void DWIN_StartHoming() { HMI_flag.home_flag = true; }
inline void DWIN_HomingStart() { HMI_flag.home_flag = true; }
void DWIN_CompletedHoming();
void DWIN_CompletedLeveling();
void DWIN_HomingDone();
void DWIN_LevelingDone();

View File

@@ -49,6 +49,7 @@ void DWIN_Startup() {
#if DISABLED(SHOW_BOOTSCREEN)
DWIN_Frame_Clear(Color_Bg_Black); // MarlinUI handles the bootscreen so just clear here
#endif
DWIN_JPG_ShowAndCache(3);
DWIN_UpdateLCD();
}

View File

@@ -29,9 +29,6 @@
* @brief 迪文屏控制操作函数
********************************************************************************/
#define DWIN_WIDTH 272
#define DWIN_HEIGHT 480
#include "../common/dwin_api.h"
#include "../common/dwin_set.h"
#include "../common/dwin_font.h"

File diff suppressed because it is too large Load Diff

View File

@@ -1,280 +0,0 @@
/**
* Marlin 3D Printer Firmware
* Copyright (c) 2021 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
*
* Based on Sprinter and grbl.
* Copyright (c) 2011 Camiel Gubbels / Erik van der Zalm
*
* 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
/**
* DWIN UI Enhanced implementation
* Author: Miguel A. Risco-Castillo
* Version: 3.6.3
* Date: 2021/09/08
*/
#include "../../../inc/MarlinConfigPre.h"
#include "dwinui.h"
#include "../common/encoder.h"
#include "../../../libs/BL24CXX.h"
#if ANY(HAS_HOTEND, HAS_HEATED_BED, HAS_FAN) && PREHEAT_COUNT
#define HAS_PREHEAT 1
#if PREHEAT_COUNT < 2
#error "Creality DWIN requires two material preheat presets."
#endif
#endif
#if ANY(AUTO_BED_LEVELING_BILINEAR, AUTO_BED_LEVELING_LINEAR, AUTO_BED_LEVELING_3POINT) && DISABLED(PROBE_MANUALLY)
#define HAS_ONESTEP_LEVELING 1
#endif
#if !HAS_BED_PROBE && ENABLED(BABYSTEPPING)
#define JUST_BABYSTEP 1
#endif
#if ANY(BABYSTEPPING, HAS_BED_PROBE, HAS_WORKSPACE_OFFSET)
#define HAS_ZOFFSET_ITEM 1
#endif
static constexpr size_t eeprom_data_size = 64;
enum processID : uint8_t {
// Process ID
MainMenu,
Menu,
SetInt,
SetPInt,
SetIntNoDraw,
SetFloat,
SetPFloat,
SelectFile,
PrintProcess,
PrintDone,
Info,
// Popup Windows
Homing,
Leveling,
PauseOrStop,
FilamentPurge,
WaitResponse,
Locked,
NothingToDo,
};
enum pidresult_t : uint8_t {
PID_BAD_EXTRUDER_NUM,
PID_TEMP_TOO_HIGH,
PID_TUNING_TIMEOUT,
PID_EXTR_START,
PID_BED_START,
PID_DONE
};
#define DWIN_CHINESE 123
#define DWIN_ENGLISH 0
typedef struct {
int8_t Color[3]; // Color components
int8_t Preheat = 0; // Material Select 0: PLA, 1: ABS, 2: Custom
AxisEnum axis = X_AXIS; // Axis Select
int32_t MaxValue = 0; // Auxiliar max integer/scaled float value
int32_t MinValue = 0; // Auxiliar min integer/scaled float value
int8_t dp = 0; // Auxiliar decimal places
int32_t Value = 0; // Auxiliar integer / scaled float value
int16_t *P_Int = nullptr; // Auxiliar pointer to 16 bit integer variable
float *P_Float = nullptr; // Auxiliar pointer to float variable
void (*Apply)() = nullptr; // Auxiliar apply function
void (*LiveUpdate)() = nullptr; // Auxiliar live update function
} HMI_value_t;
typedef struct {
uint16_t Background_Color = Def_Background_Color;
uint16_t Cursor_color = Def_Cursor_color;
uint16_t TitleBg_color = Def_TitleBg_color;
uint16_t TitleTxt_color = Def_TitleTxt_color;
uint16_t Text_Color = Def_Text_Color;
uint16_t Selected_Color = Def_Selected_Color;
uint16_t SplitLine_Color = Def_SplitLine_Color;
uint16_t Highlight_Color = Def_Highlight_Color;
uint16_t StatusBg_Color = Def_StatusBg_Color;
uint16_t StatusTxt_Color = Def_StatusTxt_Color;
uint16_t PopupBg_color = Def_PopupBg_color;
uint16_t PopupTxt_Color = Def_PopupTxt_Color;
uint16_t AlertBg_Color = Def_AlertBg_Color;
uint16_t AlertTxt_Color = Def_AlertTxt_Color;
uint16_t PercentTxt_Color = Def_PercentTxt_Color;
uint16_t Barfill_Color = Def_Barfill_Color;
uint16_t Indicator_Color = Def_Indicator_Color;
uint16_t Coordinate_Color = Def_Coordinate_Color;
#if HAS_HOTEND
int16_t HotendPidT = PREHEAT_1_TEMP_HOTEND;
int16_t PidCycles = 10;
#endif
#ifdef PREHEAT_1_TEMP_BED
int16_t BedPidT = PREHEAT_1_TEMP_BED;
#endif
#if ENABLED(PREVENT_COLD_EXTRUSION)
int16_t ExtMinT = EXTRUDE_MINTEMP;
#endif
} HMI_data_t;
typedef struct {
uint8_t language;
bool pause_flag:1; // printing is paused
bool pause_action:1; // flag a pause action
bool print_finish:1; // print was finished
bool select_flag:1; // Popup button selected
bool home_flag:1; // homing in course
bool heat_flag:1; // 0: heating done 1: during heating
bool lock_flag:1; // 0: lock called from AdvSet 1: lock called from Tune
} HMI_flag_t;
extern HMI_value_t HMI_value;
extern HMI_flag_t HMI_flag;
extern HMI_data_t HMI_data;
extern uint8_t checkkey;
extern millis_t dwin_heat_time;
// Popup windows
void DWIN_Popup_Confirm(uint8_t icon, const char * const msg1, const char * const msg2);
#if HAS_HOTEND || HAS_HEATED_BED
void DWIN_Popup_Temperature(const bool toohigh);
#endif
#if HAS_HOTEND
void Popup_Window_ETempTooLow();
#endif
void Popup_Window_Resume();
// SD Card
void HMI_SDCardInit();
void HMI_SDCardUpdate();
// Other
void Goto_PrintProcess();
void Goto_Main_Menu();
void Draw_Select_Highlight(const bool sel);
void Draw_Status_Area(const bool with_update); // Status Area
void Draw_Main_Area(); // Redraw main area;
void DWIN_Redraw_screen(); // Redraw all screen elements
void HMI_StartFrame(const bool with_update); // Prepare the menu view
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 HMI_Init();
void HMI_Popup();
void HMI_SaveProcessID(const uint8_t id);
void HMI_AudioFeedback(const bool success=true);
void EachMomentUpdate();
void update_variable();
void DWIN_HandleScreen();
void DWIN_Update();
void DWIN_DrawStatusLine(const uint16_t color, const uint16_t bgcolor, const char *text);
void DWIN_StatusChanged(const char * const text);
void DWIN_StatusChanged_P(PGM_P const text);
void DWIN_StartHoming();
void DWIN_CompletedHoming();
#if HAS_MESH
void DWIN_MeshUpdate(const int8_t xpos, const int8_t ypos, const float zval);
#endif
void DWIN_MeshLevelingStart();
void DWIN_CompletedLeveling();
void DWIN_PidTuning(pidresult_t result);
void DWIN_Print_Started(const bool sd = false);
void DWIN_Print_Finished();
#if HAS_FILAMENT_SENSOR
void DWIN_FilamentRunout(const uint8_t extruder);
#endif
void DWIN_Progress_Update();
void DWIN_Print_Header(const char *text);
void DWIN_SetColorDefaults();
void DWIN_StoreSettings(char *buff);
void DWIN_LoadSettings(const char *buff);
void DWIN_SetDataDefaults();
void DWIN_RebootScreen();
#if ENABLED(ADVANCED_PAUSE_FEATURE)
void Draw_Popup_FilamentPurge();
void DWIN_Popup_FilamentPurge();
void HMI_FilamentPurge();
#endif
// Utility and extensions
void HMI_LockScreen();
void DWIN_LockScreen(const bool flag = true);
#if HAS_MESH
void DWIN_MeshViewer();
#endif
// HMI user control functions
void HMI_Menu();
void HMI_SetInt();
void HMI_SetPInt();
void HMI_SetIntNoDraw();
void HMI_SetFloat();
void HMI_SetPFloat();
// Menu drawing functions
void Draw_Control_Menu();
void Draw_AdvancedSettings_Menu();
void Draw_Prepare_Menu();
void Draw_Move_Menu();
void Draw_LevBedCorners_Menu();
#if HAS_HOME_OFFSET
void Draw_HomeOffset_Menu();
#endif
#if HAS_BED_PROBE
void Draw_ProbeSet_Menu();
#endif
#if HAS_FILAMENT_SENSOR
void Draw_FilSet_Menu();
#endif
void Draw_SelectColors_Menu();
void Draw_GetColor_Menu();
void Draw_Tune_Menu();
void Draw_Motion_Menu();
#if ENABLED(ADVANCED_PAUSE_FEATURE)
void Draw_FilamentMan_Menu();
#endif
#if ENABLED(MESH_BED_LEVELING)
void Draw_ManualMesh_Menu();
#endif
#if HAS_HOTEND
void Draw_Preheat1_Menu();
void Draw_Preheat2_Menu();
void Draw_Preheat3_Menu();
void Draw_HotendPID_Menu();
#endif
void Draw_Temperature_Menu();
void Draw_MaxSpeed_Menu();
void Draw_MaxAccel_Menu();
#if HAS_CLASSIC_JERK
void Draw_MaxJerk_Menu();
#endif
void Draw_Steps_Menu();
#if HAS_HEATED_BED
void Draw_BedPID_Menu();
#endif
#if EITHER(HAS_BED_PROBE, BABYSTEPPING)
void Draw_ZOffsetWiz_Menu();
#endif

View File

@@ -1,485 +0,0 @@
/**
* Marlin 3D Printer Firmware
* Copyright (c) 2021 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
*
* Based on Sprinter and grbl.
* Copyright (c) 2011 Camiel Gubbels / Erik van der Zalm
*
* 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
/**
* DWIN UI Enhanced implementation
* Author: Miguel A. Risco-Castillo
* Version: 3.6.3
* Date: 2021/09/08
*/
#include "../../../core/types.h"
#include "dwin_lcd.h"
#include "../common/dwin_set.h"
#include "../common/dwin_font.h"
#include "../common/dwin_color.h"
// Extra Icons
#define ICON_Brightness ICON_Motion
#define ICON_Cancel ICON_StockConfiguration
#define ICON_CustomPreheat ICON_SetEndTemp
#define ICON_Error ICON_TempTooHigh
#define ICON_ExtrudeMinT ICON_HotendTemp
#define ICON_FilLoad ICON_WriteEEPROM
#define ICON_FilMan ICON_ResumeEEPROM
#define ICON_FilSet ICON_ResumeEEPROM
#define ICON_FilUnload ICON_ReadEEPROM
#define ICON_Flow ICON_StepE
#define ICON_LevBed ICON_SetEndTemp
#define ICON_Lock ICON_Cool
#define ICON_ManualMesh ICON_HotendTemp
#define ICON_MeshNext ICON_Axis
#define ICON_MeshSave ICON_WriteEEPROM
#define ICON_MeshViewer ICON_HotendTemp
#define ICON_MoveZ0 ICON_HotendTemp
#define ICON_Park ICON_Motion
#define ICON_PIDcycles ICON_ResumeEEPROM
#define ICON_PIDValue ICON_Contact
#define ICON_ProbeSet ICON_SetEndTemp
#define ICON_ProbeTest ICON_SetEndTemp
#define ICON_Pwrlossr ICON_Motion
#define ICON_Reboot ICON_ResumeEEPROM
#define ICON_Runout ICON_MaxAccE
#define ICON_Scolor ICON_MaxSpeed
#define ICON_SetCustomPreheat ICON_SetEndTemp
#define ICON_Sound ICON_Cool
// Default UI Colors
#define Def_Background_Color Color_Bg_Black
#define Def_Cursor_color Rectangle_Color
#define Def_TitleBg_color Color_Bg_Blue
#define Def_TitleTxt_color Color_White
#define Def_Text_Color Color_White
#define Def_Selected_Color Select_Color
#define Def_SplitLine_Color Line_Color
#define Def_Highlight_Color Color_White
#define Def_StatusBg_Color RGB(0,20,20)
#define Def_StatusTxt_Color Color_Yellow
#define Def_PopupBg_color Color_Bg_Window
#define Def_PopupTxt_Color Popup_Text_Color
#define Def_AlertBg_Color Color_Bg_Red
#define Def_AlertTxt_Color Color_Yellow
#define Def_PercentTxt_Color Percent_Color
#define Def_Barfill_Color BarFill_Color
#define Def_Indicator_Color Color_White
#define Def_Coordinate_Color Color_White
// UI element defines and constants
#define DWIN_FONT_MENU font8x16
#define DWIN_FONT_STAT font10x20
#define DWIN_FONT_HEAD font10x20
#define DWIN_FONT_ALERT font10x20
#define STATUS_Y 354
#define LCD_WIDTH (DWIN_WIDTH / 8)
constexpr uint16_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
ICOX = 26, // Menu item icon X position
LBLX = 60, // Menu item label X position
VALX = 210, // Menu item value X position
MENU_CHR_W = 8, MENU_CHR_H = 16, // Menu font 8x16
STAT_CHR_W = 10;
// Menuitem Y position
#define MYPOS(L) (TITLE_HEIGHT + MLINE * (L))
// Menuitem caption Offset
#define CAPOFF ((MLINE - MENU_CHR_H) / 2)
// Menuitem caption Y position
#define MBASE(L) (MYPOS(L) + CAPOFF)
// Create and add a MenuItem object to the menu array
#define ADDMENUITEM(V...) DWINUI::MenuItemsAdd(new MenuItemClass(V))
#define ADDMENUITEM_P(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;
class TitleClass {
public:
char caption[32] = "";
uint8_t frameid = 0;
rect_t frame = {0};
void draw();
void SetCaption(const char * const title);
inline void SetCaption(FSTR_P title) { SetCaption((char *)title); }
void ShowCaption(const char * const title);
inline void ShowCaption(FSTR_P title) { ShowCaption((char *)title); }
void SetFrame(uint8_t id, uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2);
void SetFrame(uint16_t x, uint16_t y, uint16_t w, uint16_t h);
void FrameCopy(uint8_t id, uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2);
void FrameCopy(uint16_t x, uint16_t y, uint16_t h, uint16_t v);
};
extern TitleClass Title;
class MenuItemClass {
protected:
public:
uint8_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;
extern uint16_t textcolor;
extern uint16_t backcolor;
extern uint8_t font;
extern void (*onCursorErase)(uint8_t line);
extern void (*onCursorDraw)(uint8_t line);
extern void (*onTitleDraw)(TitleClass* title);
extern void (*onMenuDraw)(MenuClass* menu);
// DWIN LCD Initialization
void init();
// Set text/number font
void setFont(uint8_t cfont);
// Get font character width
uint8_t fontWidth(uint8_t cfont);
// Get font character heigh
uint8_t fontHeight(uint8_t cfont);
// Get screen x coodinates from text column
uint16_t ColToX(uint8_t col);
// Get screen y coodinates from text row
uint16_t RowToY(uint8_t row);
// Set text/number color
void SetColors(uint16_t fgcolor, uint16_t bgcolor);
void SetTextColor(uint16_t fgcolor);
void SetBackgroundColor(uint16_t bgcolor);
// Moves cursor to point
// x: abscissa of the display
// y: ordinate of the display
// point: xy coordinate
void MoveTo(int16_t x, int16_t y);
void MoveTo(xy_int_t point);
// Moves cursor relative to the actual position
// x: abscissa of the display
// y: ordinate of the display
// point: xy coordinate
void MoveBy(int16_t x, int16_t y);
void MoveBy(xy_int_t point);
// Draw a line from the cursor to xy position
// color: Line segment color
// x/y: End point
inline void LineTo(uint16_t color, uint16_t x, uint16_t y) {
DWIN_Draw_Line(color, cursor.x, cursor.y, x, y);
}
inline void LineTo(uint16_t x, uint16_t y) {
DWIN_Draw_Line(pencolor, cursor.x, cursor.y, x, y);
}
// Draw an Icon with transparent background from the library ICON
// icon: Icon ID
// x/y: Upper-left point
inline void Draw_Icon(uint8_t icon, uint16_t x, uint16_t y) {
DWIN_ICON_Show(ICON, icon, x, y);
}
// Draw a positive integer
// 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 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_IntValue(bShow, zeroFill, zeroMode, size, color, bColor, iNum, x, y, value);
}
inline void Draw_Int(uint8_t iNum, long value) {
DWIN_Draw_IntValue(false, true, 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_IntValue(false, true, 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_IntValue(false, true, 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_IntValue(true, 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_IntValue(true, true, 0, size, color, bColor, iNum, x, y, value);
}
// Draw a 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_FloatValue(bShow, zeroFill, zeroMode, size, color, bColor, iNum, fNum, x, y, value);
}
inline void Draw_Float(uint8_t iNum, uint8_t fNum, float value) {
DWIN_Draw_FloatValue(false, true, 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_FloatValue(false, true, 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_FloatValue(false, true, 0, font, color, 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_FloatValue(true, 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_FloatValue(true, 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
// bColor: Background color
// iNum: Number of whole digits
// fNum: Number of decimal digits
// x/y: Upper-left point
// value: Float value
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);
inline void Draw_Signed_Float(uint8_t iNum, uint8_t fNum, float value) {
Draw_Signed_Float(false, true, 0, 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) {
Draw_Signed_Float(false, true, 0, 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) {
Draw_Signed_Float(false, true, 0, 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) {
Draw_Signed_Float(true, true, 0, 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) {
Draw_Signed_Float(true, true, 0, size, color, bColor, iNum, fNum, x, y, value);
}
// Draw a char at cursor position
void Draw_Char(const char c);
// Draw a string at cursor position
// color: Character color
// *string: The string
// rlimit: For draw less chars than string length use rlimit
void Draw_String(const char * const string, uint16_t rlimit = 0xFFFF);
void Draw_String(uint16_t color, const char * const string, uint16_t rlimit = 0xFFFF);
// Draw a string
// size: Font size
// color: Character color
// bColor: Background color
// x/y: Upper-left coordinate of the string
// *string: The string
inline void Draw_String(uint16_t x, uint16_t y, const char * const string) {
DWIN_Draw_String(false, font, textcolor, backcolor, x, y, string);
}
inline void Draw_String(uint16_t x, uint16_t y, FSTR_P title) {
DWIN_Draw_String(false, font, textcolor, backcolor, x, y, (char *)title);
}
inline void Draw_String(uint16_t color, uint16_t x, uint16_t y, const char * const string) {
DWIN_Draw_String(false, font, color, backcolor, x, y, string);
}
inline void Draw_String(uint16_t color, uint16_t x, uint16_t y, FSTR_P title) {
DWIN_Draw_String(false, font, color, backcolor, x, y, (char *)title);
}
inline void Draw_String(uint16_t color, uint16_t bgcolor, uint16_t x, uint16_t y, const char * const string) {
DWIN_Draw_String(true, font, color, bgcolor, x, y, string);
}
inline void Draw_String(uint16_t color, uint16_t bgcolor, uint16_t x, uint16_t y, FSTR_P title) {
DWIN_Draw_String(true, font, color, bgcolor, x, y, (char *)title);
}
inline void Draw_String(uint8_t size, uint16_t color, uint16_t bgcolor, uint16_t x, uint16_t y, const char * const string) {
DWIN_Draw_String(true, size, color, bgcolor, x, y, string);
}
inline void Draw_String(uint8_t size, uint16_t color, uint16_t bgcolor, uint16_t x, uint16_t y, FSTR_P title) {
DWIN_Draw_String(true, size, color, bgcolor, x, y, (char *)title);
}
// Draw a centered string using DWIN_WIDTH
// bShow: true=display background color; false=don't display background color
// size: Font size
// color: Character color
// bColor: Background color
// y: Upper coordinate of the string
// *string: The string
void Draw_CenteredString(bool bShow, uint8_t size, uint16_t color, uint16_t bColor, uint16_t y, const char * const string);
inline void Draw_CenteredString(bool bShow, uint8_t size, uint16_t color, uint16_t bColor, uint16_t y, FSTR_P title) {
Draw_CenteredString(bShow, size, color, bColor, y, (char *)title);
}
inline void Draw_CenteredString(uint16_t color, uint16_t bcolor, uint16_t y, const char * const string) {
Draw_CenteredString(true, font, color, bcolor, y, string);
}
inline void Draw_CenteredString(uint8_t size, uint16_t color, uint16_t y, const char * const string) {
Draw_CenteredString(false, size, color, backcolor, y, string);
}
inline void Draw_CenteredString(uint8_t size, uint16_t color, uint16_t y, FSTR_P title) {
Draw_CenteredString(false, size, color, backcolor, y, (char *)title);
}
inline void Draw_CenteredString(uint16_t color, uint16_t y, const char * const string) {
Draw_CenteredString(false, font, color, backcolor, y, string);
}
inline void Draw_CenteredString(uint16_t color, uint16_t y, FSTR_P title) {
Draw_CenteredString(false, font, color, backcolor, y, (char *)title);
}
inline void Draw_CenteredString(uint16_t y, const char * const string) {
Draw_CenteredString(false, font, textcolor, backcolor, y, string);
}
inline void Draw_CenteredString(uint16_t y, FSTR_P title) {
Draw_CenteredString(false, font, textcolor, backcolor, y, (char *)title);
}
// Draw a circle
// Color: circle color
// x: abscissa of the center of the circle
// y: ordinate of the center of the circle
// r: circle radius
void Draw_Circle(uint16_t color, uint16_t x,uint16_t y,uint8_t r);
inline void Draw_Circle(uint16_t color, uint8_t r) {
Draw_Circle(color, cursor.x, cursor.y, r);
}
// Draw a checkbox
// Color: frame color
// bColor: Background color
// x/y: Upper-left point
// checked : 0 : unchecked, 1 : checked
void Draw_Checkbox(uint16_t color, uint16_t bcolor, uint16_t x, uint16_t y, bool checked);
inline void Draw_Checkbox(uint16_t x, uint16_t y, bool checked=false) {
Draw_Checkbox(textcolor, backcolor, x, y, checked);
}
// Color Interpolator
// val : Interpolator minv..maxv
// minv : Minimum value
// maxv : Maximum value
// color1 : Start color
// color2 : End color
uint16_t ColorInt(int16_t val, int16_t minv, int16_t maxv, uint16_t color1, uint16_t color2);
// -------------------------- Extra -------------------------------//
// Draw a circle filled with color
// bcolor: fill color
// x: abscissa of the center of the circle
// y: ordinate of the center of the circle
// r: circle radius
void Draw_FillCircle(uint16_t bcolor, uint16_t x,uint16_t y,uint8_t r);
inline void Draw_FillCircle(uint16_t bcolor, uint8_t r) {
Draw_FillCircle(bcolor, cursor.x, cursor.y, r);
}
// Color Interpolator through Red->Yellow->Green->Blue
// val : Interpolator minv..maxv
// minv : Minimum value
// maxv : Maximum value
uint16_t RainbowInt(int16_t val, int16_t minv, int16_t maxv);
// Write buffer data to the SRAM
// addr: SRAM start address 0x0000-0x7FFF
// length: Bytes to write
// data: address of the buffer with data
inline void WriteToSRAM(uint16_t addr, uint16_t length, uint8_t *data) {
DWIN_WriteToMem(0x5A, addr, length, data);
}
// Write buffer data to the Flash
// addr: Flash start address 0x0000-0x3FFF
// length: Bytes to write
// data: address of the buffer with data
inline void WriteToFlash(uint16_t addr, uint16_t length, uint8_t *data) {
DWIN_WriteToMem(0xA5, addr, length, data);
}
// Clear Menu by filling the area with background color
// Area (0, TITLE_HEIGHT, DWIN_WIDTH, STATUS_Y - 1)
void ClearMenuArea();
// Clear MenuItems array and free MenuItems elements
void MenuItemsClear();
// Prepare MenuItems array
void MenuItemsPrepare(uint8_t totalitems);
// Add elements to the MenuItems array
MenuItemClass* MenuItemsAdd(MenuItemClass* menuitem);
};

View File

@@ -1,75 +0,0 @@
/**
* DWIN Mesh Viewer
* Author: Miguel A. Risco-Castillo
* version: 2.5
* Date: 2021/09/27
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser 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 Lesser General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*
*/
#include "../../../inc/MarlinConfigPre.h"
#if BOTH(DWIN_CREALITY_LCD_ENHANCED, HAS_MESH)
#include "meshviewer.h"
#include "../../../core/types.h"
#include "../../marlinui.h"
#include "dwin_lcd.h"
#include "dwinui.h"
#include "dwin.h"
#include "../../../feature/bedlevel/bedlevel.h"
MeshViewerClass MeshViewer;
void MeshViewerClass::Draw() {
const int8_t mx = 30, my = 30; // Margins
const int16_t stx = (DWIN_WIDTH - 2 * mx) / (GRID_MAX_POINTS_X - 1), // Steps
sty = (DWIN_WIDTH - 2 * my) / (GRID_MAX_POINTS_Y - 1);
int8_t zmesh[GRID_MAX_POINTS_X][GRID_MAX_POINTS_Y], maxz =-127, minz = 127;
#define px(xp) (mx + (xp) * stx)
#define py(yp) (30 + DWIN_WIDTH - my - (yp) * sty)
#define rm(z) ((((z) - minz) * 10 / _MAX(1, (maxz - minz))) + 10)
#define DrawMeshValue(xp, yp, zv) DWINUI::Draw_Signed_Float(font6x12, 1, 2, px(xp) - 12, 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(GRID_MAX_POINTS_Y - 1), DWIN_WIDTH - 2 * my)
GRID_LOOP(x, y) {
const float v = Z_VALUES(x,y) * 100;
zmesh[x][y] = v;
NOLESS(maxz, v);
NOMORE(minz, v);
}
Title.ShowCaption(F("Mesh viewer"));
DWINUI::ClearMenuArea();
DWINUI::Draw_Icon(ICON_Continue_E, 86, 305);
DWIN_Draw_Rectangle(0, HMI_data.SplitLine_Color, px(0), py(0), px(GRID_MAX_POINTS_X - 1), py(GRID_MAX_POINTS_Y - 1));
LOOP_S_L_N(x, 1, GRID_MAX_POINTS_X - 1) DrawMeshVLine(x);
LOOP_S_L_N(y, 1, GRID_MAX_POINTS_Y - 1) DrawMeshHLine(y);
LOOP_L_N(y, GRID_MAX_POINTS_Y) {
watchdog_refresh();
LOOP_L_N(x, GRID_MAX_POINTS_X) {
uint16_t color = DWINUI::RainbowInt(zmesh[x][y], _MIN(-5, minz), _MAX(5, maxz));
DWINUI::Draw_FillCircle(color, px(x), py(y), rm(zmesh[x][y]));
DrawMeshValue(x, y, Z_VALUES(x,y));
}
}
char str_1[6], str_2[6] = "";
ui.status_printf_P(0, PSTR("Mesh minZ: %s, maxZ: %s"),
dtostrf((float)minz / 100, 1, 2, str_1),
dtostrf((float)maxz / 100, 1, 2, str_2)
);
}
#endif // DWIN_CREALITY_LCD_ENHANCED && HAS_MESH

View File

@@ -1,6 +1,6 @@
# DWIN for Creality Ender 3 v2
Marlin's Ender 3 v2 support requires the `DWIN_SET` included with the Ender 3 V2 [example configuration](https://github.com/MarlinFirmware/Configurations/tree/bugfix-2.0.x/config/examples/Creality/Ender-3%20V2).
Marlin's Ender 3 v2 support requires the `DWIN_SET` included with the Ender 3 V2 [example configuration](https://github.com/MarlinFirmware/Configurations/tree/bugfix-2.1.x/config/examples/Creality/Ender-3%20V2).
## Easy Install

File diff suppressed because it is too large Load Diff

View File

@@ -43,7 +43,7 @@ enum processID : uint8_t {
enum PopupID : uint8_t {
Pause, Stop, Resume, SaveLevel, ETemp, ConfFilChange, PurgeMore, MeshSlot,
Level, Home, MoveWait, Heating, FilLoad, FilChange, TempWarn, Runout, PIDWait, Resuming, ManualProbing,
FilInsert, HeaterTime, UserInput, LevelError, InvalidMesh, UI, Complete
FilInsert, HeaterTime, UserInput, LevelError, InvalidMesh, UI, Complete, Custom
};
enum menuID : uint8_t {
@@ -55,16 +55,16 @@ enum menuID : uint8_t {
ZOffset,
Preheat,
ChangeFilament,
MenuCustom,
Control,
TempMenu,
PID,
HotendPID,
BedPID,
Preheat1,
Preheat2,
Preheat3,
Preheat4,
Preheat5,
#if HAS_PREHEAT
#define _PREHEAT_ID(N) Preheat##N,
REPEAT_1(PREHEAT_COUNT, _PREHEAT_ID)
#endif
Motion,
HomeOffsets,
MaxSpeed,
@@ -175,7 +175,9 @@ public:
static uint16_t GetColor(uint8_t color, uint16_t original, bool light=false);
static void Draw_Checkbox(uint8_t row, bool value);
static void Draw_Title(const char * title);
static void Draw_Title(FSTR_P const title);
static void Draw_Menu_Item(uint8_t row, uint8_t icon=0, const char * const label1=nullptr, const char * const label2=nullptr, bool more=false, bool centered=false);
static void Draw_Menu_Item(uint8_t row, uint8_t icon=0, FSTR_P const flabel1=nullptr, FSTR_P const flabel2=nullptr, bool more=false, bool centered=false);
static void Draw_Menu(uint8_t menu, uint8_t select=0, uint8_t scroll=0);
static void Redraw_Menu(bool lastprocess=true, bool lastselection=false, bool lastmenu=false);
static void Redraw_Screen();
@@ -194,7 +196,7 @@ public:
static void Draw_SD_Item(uint8_t item, uint8_t row);
static void Draw_SD_List(bool removed=false);
static void Draw_Status_Area(bool icons=false);
static void Draw_Popup(PGM_P const line1, PGM_P const line2, PGM_P const line3, uint8_t mode, uint8_t icon=0);
static void Draw_Popup(FSTR_P const line1, FSTR_P const line2, FSTR_P const line3, uint8_t mode, uint8_t icon=0);
static void Popup_Select();
static void Update_Status_Bar(bool refresh=false);
@@ -203,7 +205,7 @@ public:
static void Set_Mesh_Viewer_Status();
#endif
static const char * Get_Menu_Title(uint8_t menu);
static FSTR_P Get_Menu_Title(uint8_t menu);
static uint8_t Get_Menu_Size(uint8_t menu);
static void Menu_Item_Handler(uint8_t menu, uint8_t item, bool draw=true);

View File

@@ -46,6 +46,7 @@ void DWIN_Startup() {
if (success) DEBUG_ECHOLNPGM("ok."); else DEBUG_ECHOLNPGM("error.");
DWIN_Frame_SetDir(TERN(DWIN_MARLINUI_LANDSCAPE, 0, 1));
DWIN_Frame_Clear(Color_Bg_Black); // MarlinUI handles the bootscreen so just clear here
DWIN_JPG_ShowAndCache(3);
DWIN_UpdateLCD();
}

View File

@@ -28,11 +28,6 @@
#include "../../../inc/MarlinConfigPre.h"
#if ENABLED(DWIN_MARLINUI_LANDSCAPE)
#define DWIN_WIDTH 480
#define DWIN_HEIGHT 272
#endif
#include "../common/dwin_api.h"
// Picture ID
@@ -69,6 +64,8 @@
#define ICON_UpArrow 14
#define ICON_DownArrow 15
#define ICON_BedLine 16
#define ICON_BedLevelOff 17
#define ICON_BedLevelOn 18
#include "../common/dwin_font.h"

View File

@@ -27,33 +27,35 @@
#include "dwin_string.h"
//#include "../../fontutils.h"
uint8_t DWIN_String::data[];
char DWIN_String::data[];
uint16_t DWIN_String::span;
uint8_t DWIN_String::len;
uint8_t DWIN_String::length;
void DWIN_String::set() {
//*data = 0x00;
memset(data, 0x00, sizeof(data));
span = 0;
len = 0;
length = 0;
}
uint8_t read_byte(uint8_t *byte) { return *byte; }
uint8_t read_byte(const uint8_t *byte) { return *byte; }
/**
* Add a string, applying substitutions for the following characters:
*
* $ displays the clipped string given by fstr or cstr
* = displays '0'....'10' for indexes 0 - 10
* ~ displays '1'....'11' for indexes 0 - 10
* * displays 'E1'...'E11' for indexes 0 - 10 (By default. Uses LCD_FIRST_TOOL)
* @ displays an axis name such as XYZUVW, or E for an extruder
*/
void DWIN_String::add(uint8_t *string, const int8_t index, uint8_t *itemString/*=nullptr*/) {
wchar_t wchar;
void DWIN_String::add(const char *tpl, const int8_t index, const char *cstr/*=nullptr*/, FSTR_P const fstr/*=nullptr*/) {
lchar_t wc;
while (*string) {
string = get_utf8_value_cb(string, read_byte, &wchar);
if (wchar > 255) wchar |= 0x0080;
uint8_t ch = uint8_t(wchar & 0x00FF);
while (*tpl) {
tpl = get_utf8_value_cb(tpl, read_byte, wc);
if (wc > 255) wc |= 0x0080;
const uint8_t ch = uint8_t(wc & 0x00FF);
if (ch == '=' || ch == '~' || ch == '*') {
if (index >= 0) {
@@ -62,48 +64,48 @@ void DWIN_String::add(uint8_t *string, const int8_t index, uint8_t *itemString/*
if (inum >= 10) { add_character('0' + (inum / 10)); inum %= 10; }
add_character('0' + inum);
}
else {
add(index == -2 ? GET_TEXT(MSG_CHAMBER) : GET_TEXT(MSG_BED));
}
continue;
else
add(index == -2 ? GET_TEXT_F(MSG_CHAMBER) : GET_TEXT_F(MSG_BED));
}
else if (ch == '$' && itemString) {
add(itemString);
continue;
}
add_character(ch);
else if (ch == '$' && fstr)
add(fstr);
else if (ch == '$' && cstr)
add(cstr);
else if (ch == '@')
add_character(AXIS_CHAR(index));
else
add_character(ch);
}
eol();
}
void DWIN_String::add(uint8_t *string, uint8_t max_len) {
wchar_t wchar;
while (*string && max_len) {
string = get_utf8_value_cb(string, read_byte, &wchar);
void DWIN_String::add(const char *cstr, uint8_t max_len/*=MAX_STRING_LENGTH*/) {
lchar_t wc;
while (*cstr && max_len) {
cstr = get_utf8_value_cb(cstr, read_byte, wc);
/*
if (wchar > 255) wchar |= 0x0080;
uint8_t ch = uint8_t(wchar & 0x00FF);
if (wc > 255) wc |= 0x0080;
const uint8_t ch = uint8_t(wc & 0x00FF);
add_character(ch);
*/
add(wchar);
add(wc);
max_len--;
}
eol();
}
void DWIN_String::add(wchar_t character) {
void DWIN_String::add(const lchar_t &wc) {
int ret;
size_t idx = 0;
dwin_charmap_t pinval;
dwin_charmap_t *copy_address = nullptr;
pinval.uchar = character;
pinval.uchar = wc;
pinval.idx = -1;
// For 8-bit ASCII just print the single character
char str[] = { '?', 0 };
if (character < 255) {
str[0] = (char)character;
if (wc < 255) {
str[0] = (char)wc;
}
else {
copy_address = nullptr;
@@ -127,18 +129,18 @@ void DWIN_String::add(wchar_t character) {
if (str[1]) add_character(str[1]);
}
void DWIN_String::add_character(const uint8_t character) {
if (len < MAX_STRING_LENGTH) {
data[len] = character;
len++;
void DWIN_String::add_character(const char character) {
if (length < MAX_STRING_LENGTH) {
data[length] = character;
length++;
//span += glyph(character)->DWidth;
}
}
void DWIN_String::rtrim(const uint8_t character) {
while (len) {
if (data[len - 1] == 0x20 || data[len - 1] == character) {
len--;
void DWIN_String::rtrim(const char character) {
while (length) {
if (data[length - 1] == 0x20 || data[length - 1] == character) {
length--;
//span -= glyph(data[length])->DWidth;
eol();
}
@@ -147,18 +149,18 @@ void DWIN_String::rtrim(const uint8_t character) {
}
}
void DWIN_String::ltrim(const uint8_t character) {
void DWIN_String::ltrim(const char character) {
uint16_t i, j;
for (i = 0; (i < len) && (data[i] == 0x20 || data[i] == character); i++) {
for (i = 0; (i < length) && (data[i] == 0x20 || data[i] == character); i++) {
//span -= glyph(data[i])->DWidth;
}
if (i == 0) return;
for (j = 0; i < len; data[j++] = data[i++]);
len = j;
for (j = 0; i < length; data[j++] = data[i++]);
length = j;
eol();
}
void DWIN_String::trim(const uint8_t character) {
void DWIN_String::trim(const char character) {
rtrim(character);
ltrim(character);
}

View File

@@ -21,13 +21,15 @@
*/
#pragma once
// TODO: Make AVR-compatible with separate ROM / RAM string methods
#include "../../fontutils.h"
#include "../../marlinui.h"
#include <stdint.h>
typedef struct _dwin_charmap_t {
wchar_t uchar; // the unicode char
lchar_t uchar; // the unicode char
uint8_t idx; // the glyph of the char in the ROM
uint8_t idx2; // the char used to be combined with the idx to simulate a single char
} dwin_charmap_t;
@@ -41,45 +43,87 @@ class DWIN_String {
//static glyph_t *glyphs[256];
//static font_t *font_header;
static uint8_t data[MAX_STRING_LENGTH + 1];
static char data[MAX_STRING_LENGTH + 1];
static uint16_t span; // in pixels
static uint8_t len; // in characters
static void add_character(const uint8_t character);
static void eol() { data[len] = 0x00; }
static void add_character(const char character);
static void eol() { data[length] = 0x00; }
public:
static uint8_t length; // in characters
//static void set_font(const uint8_t *font);
//static void add_glyphs(const uint8_t *font);
//static font_t *font() { return font_header; };
//static uint16_t font_height() { return font_header->FontAscent - font_header->FontDescent; }
//static glyph_t *glyph(uint8_t character) { return glyphs[character] ?: glyphs[0x3F]; } /* Use '?' for unknown glyphs */
//static inline glyph_t *glyph(uint8_t *character) { return glyph(*character); }
//static glyph_t *glyph(uint8_t *character) { return glyph(*character); }
/**
* @brief Set the string empty
*/
static void set();
//static void add(uint8_t character) { add_character(character); eol(); }
static void add(wchar_t character);
static void add(uint8_t *string, uint8_t max_len=MAX_STRING_LENGTH);
static void add(uint8_t *string, const int8_t index, uint8_t *itemString=nullptr);
static void set(uint8_t *string) { set(); add(string); }
static void set(wchar_t character) { set(); add(character); }
static void set(uint8_t *string, int8_t index, const char *itemString=nullptr) { set(); add(string, index, (uint8_t *)itemString); }
static inline void set(FSTR_P fstring) { set((uint8_t *)fstring); }
static inline void set(const char *string) { set((uint8_t *)string); }
static inline void set(const char *string, int8_t index, const char *itemString=nullptr) { set((uint8_t *)string, index, itemString); }
static inline void add(const char *string) { add((uint8_t *)string); }
static void trim(const uint8_t character=0x20);
static void rtrim(const uint8_t character=0x20);
static void ltrim(const uint8_t character=0x20);
//static void add(const char character) { add_character(character); eol(); }
static void truncate(uint8_t maxlen) { if (len > maxlen) { len = maxlen; eol(); } }
/**
* @brief Append a UTF-8 character
*
* @param wc The UTF-8 character
*/
static void add(const lchar_t &wc);
static void set(const lchar_t &wc) { set(); add(wc); }
static inline uint8_t length() { return len; }
static inline uint16_t width() { return span; }
static inline uint8_t *string() { return data; }
static uint16_t center(uint16_t width) { return span > width ? 0 : (width - span) / 2; }
/**
* @brief Append / Set C-string
*
* @param cstr The string
* @param max_len Character limit
*/
static void add(const char *cstr, uint8_t max_len=MAX_STRING_LENGTH);
static void set(const char *cstr) { set(); add(cstr); }
/**
* @brief Append / Set F-string
*
* @param fstr The string
* @param max_len Character limit
*/
static void add(FSTR_P const fstr, uint8_t max_len=MAX_STRING_LENGTH) { add(FTOP(fstr), max_len); }
static void set(FSTR_P const fstr) { set(FTOP(fstr)); }
/**
* @brief Append / Set C-string with optional substitution
*
* @param tpl A string with optional substitution
* @param index An index
* @param cstr An SRAM C-string to use for $ substitution
* @param fstr A ROM F-string to use for $ substitution
*/
static void add(const char *tpl, const int8_t index, const char *cstr=nullptr, FSTR_P const fstr=nullptr);
static void set(const char *tpl, const int8_t index, const char *cstr=nullptr, FSTR_P const fstr=nullptr) { set(); add(tpl, index, cstr, fstr); }
/**
* @brief Append / Set F-string with optional substitution
*
* @param ftpl A ROM F-string with optional substitution
* @param index An index
* @param cstr An SRAM C-string to use for $ substitution
* @param fstr A ROM F-string to use for $ substitution
*/
static void add(FSTR_P const ftpl, const int8_t index, const char *cstr=nullptr, FSTR_P const fstr=nullptr) { add(FTOP(ftpl), index, cstr, fstr); }
static void set(FSTR_P const ftpl, const int8_t index, const char *cstr=nullptr, FSTR_P const fstr=nullptr) { set(); add(ftpl, index, cstr, fstr); }
// Common string ops
static void trim(const char character=' ');
static void rtrim(const char character=' ');
static void ltrim(const char character=' ');
static void truncate(const uint8_t maxlen) { if (length > maxlen) { length = maxlen; eol(); } }
// Accessors
static char *string() { return data; }
static uint16_t width() { return span; }
static uint16_t center(const uint16_t width) { return span > width ? 0 : (width - span) / 2; }
};
int dwin_charmap_compare(dwin_charmap_t *v1, dwin_charmap_t *v2);

View File

@@ -16,7 +16,7 @@
* 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 <http://www.gnu.org/licenses/>.
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*
*/
@@ -56,20 +56,20 @@ void lcd_put_int(const int i) {
}
int lcd_put_dwin_string() {
DWIN_Draw_String(dwin_font.solid, dwin_font.index, dwin_font.fg, dwin_font.bg, cursor.x, cursor.y, (char*)dwin_string.string());
lcd_advance_cursor(dwin_string.length());
return dwin_string.length();
DWIN_Draw_String(dwin_font.solid, dwin_font.index, dwin_font.fg, dwin_font.bg, cursor.x, cursor.y, dwin_string.string());
lcd_advance_cursor(dwin_string.length);
return dwin_string.length;
}
// return < 0 on error
// return the advanced cols
int lcd_put_wchar_max(wchar_t c, pixel_len_t max_length) {
int lcd_put_lchar_max(const lchar_t &c, const pixel_len_t max_length) {
dwin_string.set(c);
dwin_string.truncate(max_length);
// Draw the char(s) at the cursor and advance the cursor
DWIN_Draw_String(dwin_font.solid, dwin_font.index, dwin_font.fg, dwin_font.bg, cursor.x, cursor.y, (char*)dwin_string.string());
lcd_advance_cursor(dwin_string.length());
return dwin_string.length();
DWIN_Draw_String(dwin_font.solid, dwin_font.index, dwin_font.fg, dwin_font.bg, cursor.x, cursor.y, dwin_string.string());
lcd_advance_cursor(dwin_string.length);
return dwin_string.length;
}
/**
@@ -83,35 +83,34 @@ int lcd_put_wchar_max(wchar_t c, pixel_len_t max_length) {
*
* Draw a UTF-8 string
*/
static int lcd_put_u8str_max_cb(const char * utf8_str, uint8_t (*cb_read_byte)(uint8_t * str), pixel_len_t max_length) {
uint8_t *p = (uint8_t *)utf8_str;
static int lcd_put_u8str_max_cb(const char * utf8_str, read_byte_cb_t cb_read_byte, const pixel_len_t max_length) {
const uint8_t *p = (uint8_t *)utf8_str;
dwin_string.set();
while (dwin_string.length() < max_length) {
wchar_t ch = 0;
p = get_utf8_value_cb(p, cb_read_byte, &ch);
if (!ch) break;
dwin_string.add(ch);
while (dwin_string.length < max_length) {
lchar_t wc;
p = get_utf8_value_cb(p, cb_read_byte, wc);
if (!wc) break;
dwin_string.add(wc);
}
DWIN_Draw_String(dwin_font.solid, dwin_font.index, dwin_font.fg, dwin_font.bg, cursor.x, cursor.y, (char*)dwin_string.string());
lcd_advance_cursor(dwin_string.length());
return dwin_string.length();
DWIN_Draw_String(dwin_font.solid, dwin_font.index, dwin_font.fg, dwin_font.bg, cursor.x, cursor.y, dwin_string.string());
lcd_advance_cursor(dwin_string.length);
return dwin_string.length;
}
int lcd_put_u8str_max(const char * utf8_str, pixel_len_t max_length) {
int lcd_put_u8str_max(const char * utf8_str, const pixel_len_t max_length) {
return lcd_put_u8str_max_cb(utf8_str, read_byte_ram, max_length);
}
int lcd_put_u8str_max_P(PGM_P utf8_str_P, pixel_len_t max_length) {
return lcd_put_u8str_max_cb(utf8_str_P, read_byte_rom, max_length);
int lcd_put_u8str_max_P(PGM_P utf8_pstr, const pixel_len_t max_length) {
return lcd_put_u8str_max_cb(utf8_pstr, read_byte_rom, max_length);
}
lcd_uint_t lcd_put_u8str_ind_P(PGM_P const pstr, const int8_t ind, PGM_P const inStr/*=nullptr*/, const lcd_uint_t maxlen/*=LCD_WIDTH*/) {
dwin_string.set();
dwin_string.add((uint8_t*)pstr, ind, (uint8_t*)inStr);
lcd_uint_t lcd_put_u8str_P(PGM_P const ptpl, const int8_t ind, const char * const cstr/*=nullptr*/, FSTR_P const fstr/*=nullptr*/, const lcd_uint_t maxlen/*=LCD_WIDTH*/) {
dwin_string.set(ptpl, ind, cstr, fstr);
dwin_string.truncate(maxlen);
DWIN_Draw_String(dwin_font.solid, dwin_font.index, dwin_font.fg, dwin_font.bg, cursor.x, cursor.y, (char*)dwin_string.string());
lcd_advance_cursor(dwin_string.length());
return dwin_string.length();
DWIN_Draw_String(dwin_font.solid, dwin_font.index, dwin_font.fg, dwin_font.bg, cursor.x, cursor.y, dwin_string.string());
lcd_advance_cursor(dwin_string.length);
return dwin_string.length;
}
#if ENABLED(DEBUG_LCDPRINT)

View File

@@ -16,7 +16,7 @@
* 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 <http://www.gnu.org/licenses/>.
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*
*/
#pragma once

View File

@@ -16,7 +16,7 @@
* 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 <http://www.gnu.org/licenses/>.
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*
*/
@@ -79,16 +79,12 @@ void MarlinUI::set_font(const uint8_t font_nr) {
bool MarlinUI::detected() { return true; }
// Initialize or re-initialize the LCD
void MarlinUI::init_lcd() {
DWIN_Startup();
// Load the assets JPG (currently just the status screen 'icon')
DWIN_JPG_CacheTo1(DWIN_MarlinUI_Assets);
}
void MarlinUI::init_lcd() { DWIN_Startup(); }
// This LCD should clear where it will draw anew
void MarlinUI::clear_lcd() {
DWIN_ICON_AnimationControl(0x0000); // disable all icon animations
DWIN_JPG_ShowAndCache(3);
DWIN_Frame_Clear(Color_Bg_Black);
DWIN_UpdateLCD();
@@ -98,30 +94,40 @@ void MarlinUI::clear_lcd() {
#if ENABLED(SHOW_BOOTSCREEN)
void MarlinUI::show_bootscreen() {
clear_lcd();
dwin_string.set(F(SHORT_BUILD_VERSION));
#if ENABLED(SHOW_CUSTOM_BOOTSCREEN) && !defined(CUSTOM_BOOTSCREEN_TIMEOUT)
#define CUSTOM_BOOTSCREEN_TIMEOUT 3000
#endif
#if ENABLED(DWIN_MARLINUI_PORTRAIT)
#define LOGO_CENTER ((LCD_PIXEL_WIDTH) / 2)
#define INFO_CENTER LOGO_CENTER
#define VERSION_Y 330
DWIN_ICON_Show(BOOT_ICON, ICON_MarlinBoot, LOGO_CENTER - 266 / 2, 15);
#else
#define LOGO_CENTER (280 / 2)
#define INFO_CENTER ((LCD_PIXEL_WIDTH) - 200 / 2)
#define VERSION_Y 84
#endif
DWIN_Draw_String(false, font10x20, Color_Yellow, Color_Bg_Black, INFO_CENTER - (dwin_string.length * 10) / 2, VERSION_Y, S(dwin_string.string()));
TERN_(SHOW_CUSTOM_BOOTSCREEN, safe_delay(CUSTOM_BOOTSCREEN_TIMEOUT));
clear_lcd();
DWIN_ICON_Show(BOOT_ICON, ICON_MarlinBoot, LOGO_CENTER - 266 / 2, 15);
#if ENABLED(DWIN_MARLINUI_PORTRAIT)
DWIN_ICON_Show(BOOT_ICON, ICON_OpenSource, LOGO_CENTER - 174 / 2, 280);
DWIN_ICON_Show(BOOT_ICON, ICON_GitHubURL, LOGO_CENTER - 180 / 2, 420);
DWIN_ICON_Show(BOOT_ICON, ICON_MarlinURL, LOGO_CENTER - 100 / 2, 440);
DWIN_ICON_Show(BOOT_ICON, ICON_Copyright, LOGO_CENTER - 126 / 2, 460);
#else
#define LOGO_CENTER (280 / 2)
#define INFO_CENTER ((LCD_PIXEL_WIDTH) - 200 / 2)
#define VERSION_Y 84
DWIN_ICON_Show(BOOT_ICON, ICON_MarlinBoot, LOGO_CENTER - 266 / 2, 15);
DWIN_ICON_Show(BOOT_ICON, ICON_OpenSource, INFO_CENTER - 174 / 2, 60);
DWIN_ICON_Show(BOOT_ICON, ICON_GitHubURL, INFO_CENTER - 180 / 2, 130);
DWIN_ICON_Show(BOOT_ICON, ICON_MarlinURL, INFO_CENTER - 100 / 2, 152);
DWIN_ICON_Show(BOOT_ICON, ICON_Copyright, INFO_CENTER - 126 / 2, 200);
#endif
DWIN_Draw_String(false, font10x20, Color_Yellow, Color_Bg_Black, INFO_CENTER - (dwin_string.length() * 10) / 2, VERSION_Y, S(dwin_string.string()));
DWIN_Draw_String(false, font10x20, Color_Yellow, Color_Bg_Black, INFO_CENTER - (dwin_string.length * 10) / 2, VERSION_Y, S(dwin_string.string()));
DWIN_UpdateLCD();
}
@@ -160,11 +166,11 @@ void MarlinUI::draw_kill_screen() {
slen = utf8_strlen(S(GET_TEXT_F(MSG_HALTED)));
lcd_moveto(cx - (slen / 2), cy);
lcd_put_u8str_P((const char*)GET_TEXT_F(MSG_HALTED));
lcd_put_u8str(GET_TEXT_F(MSG_HALTED));
slen = utf8_strlen(S(GET_TEXT_F(MSG_HALTED)));
lcd_moveto(cx - (slen / 2), cy + 1);
lcd_put_u8str_P((const char*)GET_TEXT_F(MSG_HALTED));
lcd_put_u8str(GET_TEXT_F(MSG_HALTED));
}
//
@@ -207,7 +213,7 @@ void MarlinUI::draw_status_message(const bool blink) {
lcd_put_u8str(status_message);
// Fill the rest with spaces
while (slen < max_status_chars) { lcd_put_wchar(' '); ++slen; }
while (slen < max_status_chars) { lcd_put_lchar(' '); ++slen; }
}
}
else {
@@ -221,10 +227,10 @@ void MarlinUI::draw_status_message(const bool blink) {
// If the string doesn't completely fill the line...
if (rlen < max_status_chars) {
lcd_put_wchar('.'); // Always at 1+ spaces left, draw a dot
lcd_put_lchar('.'); // Always at 1+ spaces left, draw a dot
uint8_t chars = max_status_chars - rlen; // Amount of space left in characters
if (--chars) { // Draw a second dot if there's space
lcd_put_wchar('.');
lcd_put_lchar('.');
if (--chars)
lcd_put_u8str_max(status_message, chars); // Print a second copy of the message
}
@@ -248,7 +254,7 @@ void MarlinUI::draw_status_message(const bool blink) {
lcd_put_u8str_max(status_message, max_status_chars);
// Fill the rest with spaces if there are missing spaces
while (slen < max_status_chars) { lcd_put_wchar(' '); ++slen; }
while (slen < max_status_chars) { lcd_put_lchar(' '); ++slen; }
}
#endif
@@ -258,7 +264,7 @@ void MarlinUI::draw_status_message(const bool blink) {
void MarlinUI::_set_brightness() { DWIN_LCD_Brightness(backlight ? brightness : 0); }
#endif
#if HAS_LCD_MENU
#if HAS_MARLINUI_MENU
#include "../../menu/menu.h"
@@ -268,7 +274,7 @@ void MarlinUI::draw_status_message(const bool blink) {
dwin_font.solid = false;
dwin_font.fg = Color_White;
dwin_string.set("E");
dwin_string.set('E');
dwin_string.add('1' + extruder);
dwin_string.add(' ');
dwin_string.add(i16tostr3rj(thermalManager.degHotend(extruder)));
@@ -276,9 +282,9 @@ void MarlinUI::draw_status_message(const bool blink) {
if (get_blink() || !thermalManager.heater_idle[thermalManager.idle_index_for_id(extruder)].timed_out)
dwin_string.add(i16tostr3rj(thermalManager.degTargetHotend(extruder)));
else
dwin_string.add(PSTR(" "));
dwin_string.add(F(" "));
lcd_moveto(LCD_WIDTH - dwin_string.length(), row);
lcd_moveto(LCD_WIDTH - dwin_string.length, row);
lcd_put_dwin_string();
}
@@ -305,7 +311,7 @@ void MarlinUI::draw_status_message(const bool blink) {
// Draw a static line of text in the same idiom as a menu item
void MenuItem_static::draw(const uint8_t row, PGM_P const pstr, const uint8_t style/*=SS_DEFAULT*/, const char * const vstr/*=nullptr*/) {
void MenuItem_static::draw(const uint8_t row, FSTR_P const ftpl, const uint8_t style/*=SS_DEFAULT*/, const char * const vstr/*=nullptr*/) {
// Call mark_as_selected to draw a bigger selection box
// and draw the text without a background
if (mark_as_selected(row, (bool)(style & SS_INVERT), true)) {
@@ -314,15 +320,15 @@ void MarlinUI::draw_status_message(const bool blink) {
dwin_font.fg = Color_White;
dwin_string.set();
const int8_t plen = pstr ? utf8_strlen_P(pstr) : 0,
const int8_t plen = ftpl ? utf8_strlen(ftpl) : 0,
vlen = vstr ? utf8_strlen(vstr) : 0;
if (style & SS_CENTER) {
int8_t pad = (LCD_WIDTH - 1 - plen - vlen) / 2;
while (--pad) dwin_string.add(' ');
}
if (plen) dwin_string.add((uint8_t*)pstr, itemIndex, (uint8_t*)itemString);
if (vlen) dwin_string.add((uint8_t*)vstr);
if (plen) dwin_string.add(ftpl, itemIndex, itemStringC, itemStringF);
if (vlen) dwin_string.add(vstr);
if (style & SS_CENTER) {
int8_t pad = (LCD_WIDTH - 1 - plen - vlen) / 2;
while (--pad) dwin_string.add(' ');
@@ -334,15 +340,15 @@ void MarlinUI::draw_status_message(const bool blink) {
}
// Draw a generic menu item
void MenuItemBase::_draw(const bool sel, const uint8_t row, PGM_P const pstr, const char, const char post_char) {
void MenuItemBase::_draw(const bool sel, const uint8_t row, FSTR_P const ftpl, const char, const char post_char) {
if (mark_as_selected(row, sel)) {
ui.set_font(DWIN_FONT_MENU);
dwin_font.solid = false;
dwin_font.fg = Color_White;
dwin_string.set(pstr, itemIndex, itemString);
dwin_string.set(ftpl, itemIndex, itemStringC, itemStringF);
pixel_len_t n = LCD_WIDTH - 1 - dwin_string.length();
pixel_len_t n = LCD_WIDTH - 1 - dwin_string.length;
while (--n > 1) dwin_string.add(' ');
dwin_string.add(post_char);
@@ -355,15 +361,15 @@ void MarlinUI::draw_status_message(const bool blink) {
//
// Draw a menu item with an editable value
//
void MenuEditItemBase::draw(const bool sel, const uint8_t row, PGM_P const pstr, const char* const data, const bool pgm) {
void MenuEditItemBase::draw(const bool sel, const uint8_t row, FSTR_P const ftpl, const char * const inStr, const bool pgm) {
if (mark_as_selected(row, sel)) {
ui.set_font(DWIN_FONT_MENU);
dwin_font.solid = false;
dwin_font.fg = Color_White;
const uint8_t vallen = (pgm ? utf8_strlen_P(data) : utf8_strlen(S(data)));
const uint8_t vallen = (pgm ? utf8_strlen_P(inStr) : utf8_strlen(S(inStr)));
dwin_string.set(pstr, itemIndex, itemString);
dwin_string.set(ftpl, itemIndex, itemStringC, itemStringF);
if (vallen) dwin_string.add(':');
lcd_moveto(1, row);
@@ -371,7 +377,7 @@ void MarlinUI::draw_status_message(const bool blink) {
if (vallen) {
dwin_font.fg = Color_Yellow;
dwin_string.set(data);
dwin_string.set(inStr);
lcd_moveto(LCD_WIDTH - vallen - 1, row);
lcd_put_dwin_string();
}
@@ -381,13 +387,12 @@ void MarlinUI::draw_status_message(const bool blink) {
//
// Draw an edit screen with label and current value
//
void MenuEditItemBase::draw_edit_screen(PGM_P const pstr, const char* const value/*=nullptr*/) {
void MenuEditItemBase::draw_edit_screen(FSTR_P const fstr, const char* const value/*=nullptr*/) {
ui.encoder_direction_normal();
const dwin_coord_t labellen = utf8_strlen_P(pstr), vallen = utf8_strlen(value);
const dwin_coord_t labellen = utf8_strlen(fstr), vallen = utf8_strlen(value);
dwin_string.set();
dwin_string.add((uint8_t*)pstr, itemIndex);
dwin_string.set(FTOP(fstr), itemIndex);
if (vallen) dwin_string.add(':'); // If a value is included, add a colon
// Assume the label is alpha-numeric (with a descender)
@@ -400,14 +405,12 @@ void MarlinUI::draw_status_message(const bool blink) {
// If a value is included, print the value in larger text below the label
if (vallen) {
dwin_string.set();
dwin_string.add(value);
dwin_string.set(value);
const dwin_coord_t by = (row * MENU_LINE_HEIGHT) + MENU_FONT_HEIGHT + EXTRA_ROW_HEIGHT / 2;
DWIN_Draw_String(true, font16x32, Color_Yellow, Color_Bg_Black, (LCD_PIXEL_WIDTH - vallen * 16) / 2, by, S(dwin_string.string()));
extern screenFunc_t _manual_move_func_ptr;
if (ui.currentScreen != _manual_move_func_ptr && !ui.external_control) {
if (ui.can_show_slider()) {
const dwin_coord_t slider_length = LCD_PIXEL_WIDTH - TERN(DWIN_MARLINUI_LANDSCAPE, 120, 20),
slider_height = 16,
@@ -424,31 +427,31 @@ void MarlinUI::draw_status_message(const bool blink) {
}
}
inline void draw_boxed_string(const bool yesopt, PGM_P const pstr, const bool inv) {
const uint8_t len = utf8_strlen_P(pstr),
inline void draw_boxed_string(const bool yesopt, FSTR_P const fstr, const bool inv) {
const uint8_t len = utf8_strlen(fstr),
mar = TERN(DWIN_MARLINUI_PORTRAIT, 1, 4),
col = yesopt ? LCD_WIDTH - mar - len : mar,
row = (LCD_HEIGHT >= 8 ? LCD_HEIGHT / 2 + 3 : LCD_HEIGHT - 1);
lcd_moveto(col, row);
DWIN_Draw_Box(1, inv ? Select_Color : Color_Bg_Black, cursor.x - dwin_font.width, cursor.y + 1, dwin_font.width * (len + 2), dwin_font.height + 2);
lcd_put_u8str_P(col, row, pstr);
lcd_put_u8str(col, row, fstr);
}
void MenuItem_confirm::draw_select_screen(
PGM_P const yes, PGM_P const no, const bool yesno,
PGM_P const pref, const char * const string/*=nullptr*/, PGM_P const suff/*=nullptr*/
FSTR_P const yes, FSTR_P const no, const bool yesno,
FSTR_P const pref, const char * const string/*=nullptr*/, FSTR_P const suff/*=nullptr*/
) {
ui.set_font(DWIN_FONT_MENU);
dwin_font.solid = false;
dwin_font.fg = Color_White;
ui.draw_select_screen_prompt(pref, string, suff);
draw_boxed_string(false, no, !yesno);
draw_boxed_string(true, yes, yesno);
if (no) draw_boxed_string(false, no, !yesno);
if (yes) draw_boxed_string(true, yes, yesno);
}
#if ENABLED(SDSUPPORT)
void MenuItem_sdbase::draw(const bool sel, const uint8_t row, PGM_P const, CardReader &theCard, const bool isDir) {
void MenuItem_sdbase::draw(const bool sel, const uint8_t row, FSTR_P const, CardReader &theCard, const bool isDir) {
if (mark_as_selected(row, sel)) {
dwin_string.set();
@@ -458,8 +461,8 @@ void MarlinUI::draw_status_message(const bool blink) {
maxlen -= 2;
}
dwin_string.add((uint8_t*)ui.scrolled_filename(theCard, maxlen, row, sel), maxlen);
uint8_t n = maxlen - dwin_string.length();
dwin_string.add(ui.scrolled_filename(theCard, maxlen, row, sel), maxlen);
uint8_t n = maxlen - dwin_string.length;
while (n > 0) { dwin_string.add(' '); --n; }
lcd_moveto(1, row);
lcd_put_dwin_string();
@@ -510,8 +513,8 @@ void MarlinUI::draw_status_message(const bool blink) {
// Display Mesh Point Locations
const dwin_coord_t sx = x_offset + pixels_per_x_mesh_pnt / 2;
dwin_coord_t y = y_offset + pixels_per_y_mesh_pnt / 2;
for (uint8_t j = 0; j < GRID_MAX_POINTS_Y; j++, y += pixels_per_y_mesh_pnt)
for (uint8_t i = 0, x = sx; i < GRID_MAX_POINTS_X; i++, x += pixels_per_x_mesh_pnt)
for (uint8_t j = 0; j < (GRID_MAX_POINTS_Y); j++, y += pixels_per_y_mesh_pnt)
for (uint8_t i = 0, x = sx; i < (GRID_MAX_POINTS_X); i++, x += pixels_per_x_mesh_pnt)
DWIN_Draw_Point(Color_White, 1, 1, x, y);
// Put Relevant Text on Display
@@ -519,7 +522,7 @@ void MarlinUI::draw_status_message(const bool blink) {
// Show X and Y positions at top of screen
dwin_font.fg = Color_White;
dwin_font.solid = true;
const xy_pos_t pos = { ubl.mesh_index_to_xpos(x_plot), ubl.mesh_index_to_ypos(y_plot) },
const xy_pos_t pos = { bedlevel.get_mesh_x(x_plot), bedlevel.get_mesh_y(y_plot) },
lpos = pos.asLogical();
lcd_moveto(
@@ -536,25 +539,25 @@ void MarlinUI::draw_status_message(const bool blink) {
lcd_put_u8str(ftostr52(lpos.y));
// Print plot position
dwin_string.set("(");
dwin_string.set('(');
dwin_string.add(i8tostr3rj(x_plot));
dwin_string.add(",");
dwin_string.add(',');
dwin_string.add(i8tostr3rj(y_plot));
dwin_string.add(")");
dwin_string.add(')');
lcd_moveto(
TERN(DWIN_MARLINUI_LANDSCAPE, ((x_offset + x_map_pixels) / MENU_FONT_WIDTH) + 2, LCD_WIDTH - dwin_string.length()),
TERN(DWIN_MARLINUI_LANDSCAPE, ((x_offset + x_map_pixels) / MENU_FONT_WIDTH) + 2, LCD_WIDTH - dwin_string.length),
TERN(DWIN_MARLINUI_LANDSCAPE, LCD_HEIGHT - 2, ((y_offset + y_map_pixels) / MENU_LINE_HEIGHT) + 1)
);
lcd_put_dwin_string();
// Show the location value
dwin_string.set(Z_LBL);
if (!isnan(Z_VALUES_ARR[x_plot][y_plot]))
dwin_string.add(ftostr43sign(Z_VALUES_ARR[x_plot][y_plot]));
if (!isnan(bedlevel.z_values[x_plot][y_plot]))
dwin_string.add(ftostr43sign(bedlevel.z_values[x_plot][y_plot]));
else
dwin_string.add(PSTR(" -----"));
dwin_string.add(F(" -----"));
lcd_moveto(
TERN(DWIN_MARLINUI_LANDSCAPE, ((x_offset + x_map_pixels) / MENU_FONT_WIDTH) + 2, LCD_WIDTH - dwin_string.length()),
TERN(DWIN_MARLINUI_LANDSCAPE, ((x_offset + x_map_pixels) / MENU_FONT_WIDTH) + 2, LCD_WIDTH - dwin_string.length),
TERN(DWIN_MARLINUI_LANDSCAPE, LCD_HEIGHT - 1, ((y_offset + y_map_pixels) / MENU_LINE_HEIGHT) + 2)
);
lcd_put_dwin_string();
@@ -562,19 +565,11 @@ void MarlinUI::draw_status_message(const bool blink) {
#endif // AUTO_BED_LEVELING_UBL
#if ANY(BABYSTEP_ZPROBE_GFX_OVERLAY, MESH_EDIT_GFX_OVERLAY, BABYSTEP_GFX_OVERLAY)
void _lcd_zoffset_overlay_gfx(const float zvalue) {
// Determine whether the user is raising or lowering the nozzle.
static int8_t dir;
static float old_zvalue;
if (zvalue != old_zvalue) {
dir = zvalue ? zvalue < old_zvalue ? -1 : 1 : 0;
old_zvalue = zvalue;
}
#if EITHER(BABYSTEP_ZPROBE_GFX_OVERLAY, MESH_EDIT_GFX_OVERLAY)
void MarlinUI::zoffset_overlay(const int8_t dir) {
const int rot_up = TERN(OVERLAY_GFX_REVERSE, ICON_RotateCCW, ICON_RotateCW),
rot_down = TERN(OVERLAY_GFX_REVERSE, ICON_RotateCW, ICON_RotateCCW);
rot_down = TERN(OVERLAY_GFX_REVERSE, ICON_RotateCW, ICON_RotateCCW);
const int nozzle = (LCD_PIXEL_WIDTH / 2) - 20;
@@ -594,6 +589,6 @@ void MarlinUI::draw_status_message(const bool blink) {
#endif // BABYSTEP_ZPROBE_GFX_OVERLAY || MESH_EDIT_GFX_OVERLAY
#endif // HAS_LCD_MENU
#endif // HAS_MARLINUI_MENU
#endif // IS_DWIN_MARLINUI

View File

@@ -16,7 +16,7 @@
* 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 <http://www.gnu.org/licenses/>.
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*
*/
@@ -37,6 +37,7 @@
#include "../../../module/motion.h"
#include "../../../module/temperature.h"
#include "../../../module/printcounter.h"
#include "../../../module/planner.h"
#if ENABLED(SDSUPPORT)
#include "../../../libs/duration_t.h"
@@ -46,8 +47,13 @@
#include "../../../MarlinCore.h" // for printingIsActive
#endif
#define STATUS_HEATERS_X 15
#define STATUS_HEATERS_Y 56
#if ENABLED(DWIN_MARLINUI_PORTRAIT)
#define STATUS_HEATERS_X 15
#define STATUS_HEATERS_Y 56
#else
#define STATUS_HEATERS_X 154
#define STATUS_HEATERS_Y 10
#endif
#define STATUS_HEATERS_XSPACE 64
#define STATUS_FAN_WIDTH 48
#define STATUS_FAN_HEIGHT 48
@@ -61,35 +67,61 @@
// Homed and known, display constantly.
//
FORCE_INLINE void _draw_axis_value(const AxisEnum axis, const char *value, const bool blink, const uint16_t x, const uint16_t y) {
uint8_t vallen = utf8_strlen(value);
if (!ui.did_first_redraw) {
dwin_string.set();
dwin_string.add('X' + axis);
DWIN_Draw_String(true, font16x32, Color_IconBlue, Color_Bg_Black, x + (vallen * 14 - 14) / 2, y + 2, S(dwin_string.string()));
}
#if ENABLED(DWIN_MARLINUI_PORTRAIT)
dwin_string.set();
if (blink)
dwin_string.add(value);
else {
if (!TEST(axis_homed, axis))
while (const char c = *value++) dwin_string.add(c <= '.' ? c : '?');
else {
#if NONE(HOME_AFTER_DEACTIVATE, DISABLE_REDUCED_ACCURACY_WARNING)
if (!TEST(axis_trusted, axis))
dwin_string.add(TERN1(DWIN_MARLINUI_PORTRAIT, axis == Z_AXIS) ? PSTR(" ") : PSTR(" "));
else
#endif
dwin_string.add(value);
uint8_t vallen = utf8_strlen(value);
if (!ui.did_first_redraw) {
dwin_string.set('X' + axis);
DWIN_Draw_String(true, font16x32, Color_IconBlue, Color_Bg_Black, x + (vallen * 14 - 14) / 2, y + 2, S(dwin_string.string()));
}
}
// For E_TOTAL there may be some characters to cover up
if (BOTH(DWIN_MARLINUI_PORTRAIT, LCD_SHOW_E_TOTAL) && axis == X_AXIS)
dwin_string.add(" ");
dwin_string.set();
if (blink)
dwin_string.add(value);
else if (!TEST(axes_homed, axis))
while (const char c = *value++) dwin_string.add(c <= '.' ? c : '?');
else if (NONE(HOME_AFTER_DEACTIVATE, DISABLE_REDUCED_ACCURACY_WARNING) && !TEST(axes_trusted, axis))
dwin_string.add(TERN1(DWIN_MARLINUI_PORTRAIT, axis == Z_AXIS) ? PSTR(" ") : PSTR(" "));
else
dwin_string.add(value);
DWIN_Draw_String(true, font14x28, Color_White, Color_Bg_Black, x, y + 32, S(dwin_string.string()));
// For E_TOTAL there may be some characters to cover up
if (BOTH(DWIN_MARLINUI_PORTRAIT, LCD_SHOW_E_TOTAL) && axis == X_AXIS)
dwin_string.add(F(" "));
DWIN_Draw_String(true, font14x28, Color_White, Color_Bg_Black, x, y + 32, S(dwin_string.string()));
#else // !DWIN_MARLINUI_PORTRAIT
if (!ui.did_first_redraw || ui.old_is_printing != print_job_timer.isRunning()) {
dwin_string.set('X' + axis);
DWIN_Draw_String(true, font16x32, Color_IconBlue, Color_Bg_Black, x, y, S(dwin_string.string()));
}
dwin_string.set();
if (blink)
dwin_string.add(value);
else {
if (!TEST(axes_homed, axis))
while (const char c = *value++) dwin_string.add(c <= '.' ? c : '?');
else {
#if NONE(HOME_AFTER_DEACTIVATE, DISABLE_REDUCED_ACCURACY_WARNING)
if (!TEST(axes_trusted, axis))
dwin_string.add(TERN1(DWIN_MARLINUI_PORTRAIT, axis == Z_AXIS) ? PSTR(" ") : PSTR(" "));
else
#endif
dwin_string.add(value);
}
}
// For E_TOTAL there may be some characters to cover up
if (ENABLED(LCD_SHOW_E_TOTAL) && (!ui.did_first_redraw || ui.old_is_printing != print_job_timer.isRunning()) && axis == X_AXIS)
dwin_string.add(F(" "));
DWIN_Draw_String(true, font14x28, Color_White, Color_Bg_Black, x + 32, y + 4, S(dwin_string.string()));
#endif // !DWIN_MARLINUI_PORTRAIT
}
#if ENABLED(LCD_SHOW_E_TOTAL)
@@ -97,20 +129,36 @@ FORCE_INLINE void _draw_axis_value(const AxisEnum axis, const char *value, const
FORCE_INLINE void _draw_e_value(const_float_t value, const uint16_t x, const uint16_t y) {
const uint8_t scale = value >= 100000.0f ? 10 : 1; // show cm after 99,999mm
if (!ui.did_first_redraw) {
// Extra spaces so we don't have to clear the 'Y' label separately
dwin_string.set("E ");
DWIN_Draw_String(true, font16x32, Color_IconBlue, Color_Bg_Black, x + (4 * 14 / 2) - 7, y + 2, S(dwin_string.string()));
}
#if ENABLED(DWIN_MARLINUI_PORTRAIT)
dwin_string.set(ui16tostr5rj(value / scale));
DWIN_Draw_String(true, font14x28, Color_White, Color_Bg_Black, x, y + 32, S(dwin_string.string()));
if (!ui.did_first_redraw) {
// Extra spaces to erase previous value
dwin_string.set(F("E "));
DWIN_Draw_String(true, font16x32, Color_IconBlue, Color_Bg_Black, x + (4 * 14 / 2) - 7, y + 2, S(dwin_string.string()));
}
// Extra spaces so we don't have to clear out the Y value separately
DWIN_Draw_String(true, font14x28, Color_IconBlue, Color_Bg_Black, x + (5 * 14), y + 32, S(scale == 1 ? "mm " : "cm "));
dwin_string.set(ui16tostr5rj(value / scale));
DWIN_Draw_String(true, font14x28, Color_White, Color_Bg_Black, x, y + 32, S(dwin_string.string()));
// Extra spaces to erase previous value
DWIN_Draw_String(true, font14x28, Color_IconBlue, Color_Bg_Black, x + (5 * 14), y + 32, S(scale == 1 ? "mm " : "cm "));
#else // !DWIN_MARLINUI_PORTRAIT
if (!ui.did_first_redraw || ui.old_is_printing != print_job_timer.isRunning()) {
dwin_string.set(F("E "));
DWIN_Draw_String(true, font16x32, Color_IconBlue, Color_Bg_Black, x, y, S(dwin_string.string()));
}
dwin_string.set(ui16tostr5rj(value / scale));
DWIN_Draw_String(true, font14x28, Color_White, Color_Bg_Black, x + 32, y + 4, S(dwin_string.string()));
DWIN_Draw_String(true, font14x28, Color_IconBlue, Color_Bg_Black, x + (32 + 70), y + 4, S(scale == 1 ? "mm " : "cm "));
#endif // !DWIN_MARLINUI_PORTRAIT
}
#endif
#endif // LCD_SHOW_E_TOTAL
//
// Fan Icon and Percentage
@@ -126,69 +174,104 @@ FORCE_INLINE void _draw_fan_status(const uint16_t x, const uint16_t y) {
DWIN_Draw_String(true, font14x28, Color_White, Color_Bg_Black, x, y + STATUS_FAN_HEIGHT, S(dwin_string.string()));
}
else {
DWIN_ICON_AnimationControl(0x0000); // disable all icon animations (this is the only one)
DWIN_ICON_Show(ICON, ICON_Fan0, x + fanx, y);
dwin_string.set(PSTR(" "));
dwin_string.set(F(" "));
DWIN_Draw_String(true, font14x28, Color_White, Color_Bg_Black, x, y + STATUS_FAN_HEIGHT, S(dwin_string.string()));
}
}
#if HOTENDS > 2
#define HOTEND_STATS 3
#elif HOTENDS > 1
#define HOTEND_STATS 2
#elif HAS_HOTEND
#define HOTEND_STATS 1
#endif
/**
* Draw a single heater icon with current and target temperature, at the given XY
*/
FORCE_INLINE void _draw_heater_status(const heater_id_t heater, const uint16_t x, const uint16_t y) {
#if HAS_HOTEND
static celsius_t old_temp[HOTEND_STATS] = ARRAY_N_1(HOTEND_STATS, 500),
old_target[HOTEND_STATS] = ARRAY_N_1(HOTEND_STATS, 500);
static bool old_on[HOTEND_STATS] = ARRAY_N_1(HOTEND_STATS, false);
#if HOTENDS > 2
#define HOTEND_STATS 3
#elif HOTENDS > 1
#define HOTEND_STATS 2
#else
#define HOTEND_STATS 1
#endif
static celsius_t old_temp[HOTEND_STATS] = { 0 },
old_target[HOTEND_STATS] = { 0 };
static bool old_on[HOTEND_STATS] = { false };
#endif
#if HAS_HEATED_BED
static celsius_t old_bed_temp = 500, old_bed_target = 500;
static celsius_t old_bed_temp = 0, old_bed_target = 0;
static bool old_bed_on = false;
#if HAS_LEVELING
static bool old_leveling_on = false;
#endif
#endif
#if HAS_HOTEND && HAS_HEATED_BED
float tc, tt;
bool c_draw, t_draw, i_draw, ta;
const bool isBed = heater < 0;
const float tc = (isBed ? thermalManager.degBed() : thermalManager.degHotend(heater)),
tt = (isBed ? thermalManager.degTargetBed() : thermalManager.degTargetHotend(heater));
const uint8_t ta = isBed ? thermalManager.isHeatingBed() : thermalManager.isHeatingHotend(heater);
const bool c_draw = tc != (isBed ? old_bed_temp : old_temp[heater]),
t_draw = tt != (isBed ? old_bed_target : old_target[heater]),
i_draw = ta != (isBed ? old_bed_on : old_on[heater]);
if (isBed) { old_bed_temp = tc; old_bed_target = tt; old_bed_on = ta; }
else { old_temp[heater] = tc; old_target[heater] = tt; old_on[heater] = ta; }
if (isBed) {
tc = thermalManager.degBed();
tt = thermalManager.degTargetBed();
ta = thermalManager.isHeatingBed();
c_draw = tc != old_bed_temp;
t_draw = tt != old_bed_target;
i_draw = ta != old_bed_on;
old_bed_temp = tc;
old_bed_target = tt;
old_bed_on = ta;
}
else {
tc = thermalManager.degHotend(heater);
tt = thermalManager.degTargetHotend(heater);
ta = thermalManager.isHeatingHotend(heater);
c_draw = tc != old_temp[heater];
t_draw = tt != old_target[heater];
i_draw = ta != old_on[heater];
old_temp[heater] = tc;
old_target[heater] = tt;
old_on[heater] = ta;
}
#elif HAS_HOTEND
constexpr bool isBed = false;
const float tc = thermalManager.degHotend(heater), tt = thermalManager.degTargetHotend(heater);
const uint8_t ta = thermalManager.isHeatingHotend(heater);
const bool c_draw = tc != old_bed_temp, t_draw = tt != old_bed_target, i_draw = ta != old_bed_on;
bool c_draw = tc != old_temp[heater], t_draw = tt != old_target[heater], i_draw = ta != old_on[heater];
old_temp[heater] = tc; old_target[heater] = tt; old_on[heater] = ta;
#elif HAS_HEATED_BED
constexpr bool isBed = true;
const float tc = thermalManager.degBed(), tt = thermalManager.degTargetBed();
const uint8_t ta = thermalManager.isHeatingBed();
const bool c_draw = tc != old_temp[heater], t_draw = tt != old_target[heater], i_draw = ta != old_on[heater];
bool c_draw = tc != old_bed_temp, t_draw = tt != old_bed_target, i_draw = ta != old_bed_on;
old_bed_temp = tc; old_bed_target = tt; old_bed_on = ta;
#else
bool c_draw = false, t_draw = false, i_draw = false;
constexpr float tc = 0, tt = 0;
constexpr uint8_t ta = 0;
#endif
#if HAS_HEATED_BED && HAS_LEVELING
if (isBed) {
i_draw |= (planner.leveling_active != old_leveling_on);
old_leveling_on = planner.leveling_active;
}
#endif
// Draw target temperature, if needed
if (!ui.did_first_redraw || t_draw) {
dwin_string.set(i16tostr3rj(tt + 0.5));
dwin_string.add(LCD_STR_DEGREE);
DWIN_Draw_String(true, font14x28, Color_White, Color_Bg_Black, x, y, S(dwin_string.string()));
}
if (!ui.did_first_redraw || i_draw)
DWIN_ICON_Show(ICON, (isBed ? ICON_BedOff : ICON_HotendOff) + ta, x, y + STATUS_CHR_HEIGHT + 2);
// Draw heater icon with on / off / leveled states
if (!ui.did_first_redraw || i_draw) {
const uint8_t ico = isBed ? (TERN0(HAS_LEVELING, planner.leveling_active) ? ICON_BedLevelOff : ICON_BedOff) : ICON_HotendOff;
DWIN_ICON_Show(ICON, ico + ta, x, y + STATUS_CHR_HEIGHT + 2);
}
// Draw current temperature, if needed
if (!ui.did_first_redraw || c_draw) {
dwin_string.set(i16tostr3rj(tc + 0.5));
dwin_string.add(LCD_STR_DEGREE);
@@ -206,7 +289,7 @@ FORCE_INLINE void _draw_feedrate_status(const char *value, uint16_t x, uint16_t
}
dwin_string.set(value);
dwin_string.add(PSTR("%"));
dwin_string.add('%');
DWIN_Draw_String(true, font14x28, Color_White, Color_Bg_Black, x + 14, y, S(dwin_string.string()));
}
@@ -221,14 +304,22 @@ void MarlinUI::draw_status_screen() {
// Logo/Status Icon
#define STATUS_LOGO_WIDTH 128
#define STATUS_LOGO_HEIGHT 40
DWIN_ICON_Show(ICON, ICON_LOGO_Marlin, (LCD_PIXEL_WIDTH - (STATUS_LOGO_WIDTH)) / 2, ((STATUS_HEATERS_Y - 4) - (STATUS_LOGO_HEIGHT)) / 2);
DWIN_ICON_Show(ICON, ICON_LOGO_Marlin,
#if ENABLED(DWIN_MARLINUI_PORTRAIT)
(LCD_PIXEL_WIDTH - (STATUS_LOGO_WIDTH)) / 2, ((STATUS_HEATERS_Y - 4) - (STATUS_LOGO_HEIGHT)) / 2
#else
5, 42
#endif
);
// Draw a frame around the x/y/z values
#if ENABLED(DWIN_MARLINUI_PORTRAIT)
DWIN_Draw_Rectangle(0, Select_Color, 0, 193, LCD_PIXEL_WIDTH, 260);
#else
//DWIN_Draw_Rectangle(0, Select_Color, LCD_PIXEL_WIDTH - 106, 50, LCD_PIXEL_WIDTH - 1, 230);
#endif
DWIN_Draw_Rectangle(0, Select_Color,
#if ENABLED(DWIN_MARLINUI_PORTRAIT)
0, 193, LCD_PIXEL_WIDTH, 260
#else
0, 115, LCD_PIXEL_WIDTH - 1, 152
#endif
);
}
uint16_t hx = STATUS_HEATERS_X;
@@ -245,33 +336,22 @@ void MarlinUI::draw_status_screen() {
#endif
#if HAS_FAN
// Fan display, pinned to the right side
#if ENABLED(DWIN_MARLINUI_PORTRAIT)
_draw_fan_status(LCD_PIXEL_WIDTH - STATUS_CHR_WIDTH * 4, STATUS_FAN_Y);
#else
_draw_fan_status(212, STATUS_FAN_Y);
#endif
_draw_fan_status(LCD_PIXEL_WIDTH - STATUS_CHR_WIDTH * 5, STATUS_FAN_Y);
#endif
// Axis values
const xyz_pos_t lpos = current_position.asLogical();
const bool show_e_total = TERN0(LCD_SHOW_E_TOTAL, printingIsActive()); UNUSED(show_e_total);
#if ENABLED(DWIN_MARLINUI_PORTRAIT)
constexpr int16_t cpy = 195;
if (show_e_total) {
TERN_(LCD_SHOW_E_TOTAL, _draw_e_value(e_move_accumulator, 6, cpy));
}
else {
_draw_axis_value(X_AXIS, ftostr4sign(lpos.x), blink, 6, cpy);
TERN_(HAS_Y_AXIS, _draw_axis_value(Y_AXIS, ftostr4sign(lpos.y), blink, 95, cpy));
}
TERN_(HAS_Z_AXIS, _draw_axis_value(Z_AXIS, ftostr52sp(lpos.z), blink, 165, cpy));
#else
constexpr int16_t cpx = LCD_PIXEL_WIDTH - 104;
_draw_axis_value(X_AXIS, ftostr52sp(lpos.x), blink, cpx, STATUS_HEATERS_Y);
TERN_(HAS_Y_AXIS, _draw_axis_value(Y_AXIS, ftostr52sp(lpos.y), blink, cpx, STATUS_HEATERS_Y + 59));
TERN_(HAS_Z_AXIS, _draw_axis_value(Z_AXIS, ftostr52sp(lpos.z), blink, cpx, STATUS_HEATERS_Y + 118));
#endif
constexpr int16_t cpy = TERN(DWIN_MARLINUI_PORTRAIT, 195, 117);
if (show_e_total) {
TERN_(LCD_SHOW_E_TOTAL, _draw_e_value(e_move_accumulator, TERN(DWIN_MARLINUI_PORTRAIT, 6, 75), cpy));
}
else {
_draw_axis_value(X_AXIS, ftostr4sign(lpos.x), blink, TERN(DWIN_MARLINUI_PORTRAIT, 6, 75), cpy);
TERN_(HAS_Y_AXIS, _draw_axis_value(Y_AXIS, ftostr4sign(lpos.y), blink, TERN(DWIN_MARLINUI_PORTRAIT, 95, 184), cpy));
}
TERN_(HAS_Z_AXIS, _draw_axis_value(Z_AXIS, ftostr52sp(lpos.z), blink, TERN(DWIN_MARLINUI_PORTRAIT, 165, 300), cpy));
// Feedrate
static uint16_t old_fp = 0;
@@ -279,9 +359,9 @@ void MarlinUI::draw_status_screen() {
old_fp = feedrate_percentage;
_draw_feedrate_status(i16tostr3rj(feedrate_percentage),
#if ENABLED(DWIN_MARLINUI_PORTRAIT)
5, 290
5, 290
#else
294, STATUS_HEATERS_Y
14, 195
#endif
);
}
@@ -309,34 +389,32 @@ void MarlinUI::draw_status_screen() {
time.toDigital(buffer);
dwin_string.add(prefix);
dwin_string.add(buffer);
DWIN_Draw_String(true, font14x28, Color_White, Color_Bg_Black, (LCD_PIXEL_WIDTH - ((dwin_string.length() + 1) * 14)), 290, S(dwin_string.string()));
DWIN_Draw_String(true, font14x28, Color_White, Color_Bg_Black, (LCD_PIXEL_WIDTH - ((dwin_string.length + 1) * 14)), 290, S(dwin_string.string()));
#else
// landscape mode shows both elapsed and remaining (if SHOW_REMAINING_TIME)
time = print_job_timer.duration();
time.toDigital(buffer);
dwin_string.set(" ");
dwin_string.set(' ');
dwin_string.add(buffer);
DWIN_Draw_String(true, font14x28, Color_White, Color_Bg_Black, 280, 100, S(dwin_string.string()));
DWIN_Draw_String(true, font14x28, Color_White, Color_Bg_Black, 230, 170, S(dwin_string.string()));
#if ENABLED(LCD_SHOW_E_TOTAL)
if (show_e_total && TERN1(SHOW_REMAINING_TIME, !blink)) { // if SHOW_REMAINING_TIME is also
const uint8_t escale = e_move_accumulator >= 100000.0f ? 10 : 1; // show cm after 99,000mm
DWIN_Draw_String(true, font14x28, Color_IconBlue, Color_Bg_Black, 249, 135, S("E"));
dwin_string.set(ui16tostr5rj(e_move_accumulator * escale));
DWIN_Draw_String(true, font14x28, Color_White, Color_Bg_Black, 263, 135, S(dwin_string.string()));
DWIN_Draw_String(true, font14x28, Color_IconBlue, Color_Bg_Black, 333, 135, S(escale==1 ? "mm" : "cm"));
}
#endif
#if ENABLED(SHOW_REMAINING_TIME)
if (!show_e_total || blink) {
DWIN_Draw_String(true, font14x28, Color_IconBlue, Color_Bg_Black, 249, 135, S(" R "));
if (print_job_timer.isRunning()) {
time = get_remaining_time();
time.toDigital(buffer);
dwin_string.set(buffer);
DWIN_Draw_String(true, font14x28, Color_White, Color_Bg_Black, 291, 135, S(dwin_string.string()));
DWIN_Draw_String(true, font14x28, Color_IconBlue, Color_Bg_Black, 336, 170, S(" R "));
if (print_job_timer.isPaused() && blink)
dwin_string.set(F(" "));
else {
time.toDigital(buffer);
dwin_string.set(buffer);
}
DWIN_Draw_String(true, font14x28, Color_White, Color_Bg_Black, 378, 170, S(dwin_string.string()));
}
else if (!ui.did_first_redraw || ui.old_is_printing != print_job_timer.isRunning()) {
dwin_string.set(F(" "));
DWIN_Draw_String(true, font14x28, Color_IconBlue, Color_Bg_Black, 336, 170, S(dwin_string.string()));
}
#endif
#endif
@@ -344,41 +422,45 @@ void MarlinUI::draw_status_screen() {
//
// Progress Bar
//
constexpr int16_t pb_margin = 5, pb_left = pb_margin, pb_height = 60,
pb_right = LCD_PIXEL_WIDTH - TERN(DWIN_MARLINUI_PORTRAIT, 0, 107) - pb_margin,
pb_bottom = TERN(DWIN_MARLINUI_PORTRAIT, 410, 230),
pb_top = pb_bottom - pb_height,
pb_width = pb_right - pb_left;
#if HAS_PRINT_PROGRESS
constexpr int16_t pb_margin = 5,
pb_left = pb_margin + TERN(DWIN_MARLINUI_PORTRAIT, 0, 90),
pb_height = TERN(DWIN_MARLINUI_PORTRAIT, 60, 20),
pb_right = LCD_PIXEL_WIDTH - pb_margin,
pb_bottom = TERN(DWIN_MARLINUI_PORTRAIT, 410, 220),
pb_top = pb_bottom - pb_height,
pb_width = pb_right - pb_left;
const progress_t progress = TERN(HAS_PRINT_PROGRESS_PERMYRIAD, get_progress_permyriad, get_progress_percent)();
const progress_t progress = TERN(HAS_PRINT_PROGRESS_PERMYRIAD, get_progress_permyriad, get_progress_percent)();
if (!ui.did_first_redraw)
DWIN_Draw_Rectangle(0, Select_Color, pb_left, pb_top, pb_right, pb_bottom); // Outline
if (!ui.did_first_redraw)
DWIN_Draw_Rectangle(0, Select_Color, pb_left, pb_top, pb_right, pb_bottom); // Outline
static uint16_t old_solid = 50;
const uint16_t pb_solid = (pb_width - 2) * (progress / (PROGRESS_SCALE)) * 0.01f;
const bool p_draw = !ui.did_first_redraw || old_solid != pb_solid;
static uint16_t old_solid = 50;
const uint16_t pb_solid = (pb_width - 2) * (progress / (PROGRESS_SCALE)) * 0.01f;
const bool p_draw = !ui.did_first_redraw || old_solid != pb_solid;
if (p_draw) {
//if (pb_solid)
DWIN_Draw_Rectangle(1, Select_Color, pb_left + 1, pb_top + 1, pb_left + pb_solid, pb_bottom - 1); // Fill the solid part
if (p_draw) {
//if (pb_solid)
DWIN_Draw_Rectangle(1, Select_Color, pb_left + 1, pb_top + 1, pb_left + pb_solid, pb_bottom - 1); // Fill the solid part
//if (pb_solid < old_solid)
DWIN_Draw_Rectangle(1, Color_Bg_Black, pb_left + 1 + pb_solid, pb_top + 1, pb_right - 1, pb_bottom - 1); // Erase the rest
//if (pb_solid < old_solid)
DWIN_Draw_Rectangle(1, Color_Bg_Black, pb_left + 1 + pb_solid, pb_top + 1, pb_right - 1, pb_bottom - 1); // Erase the rest
#if ENABLED(SHOW_SD_PERCENT)
dwin_string.set(TERN(PRINT_PROGRESS_SHOW_DECIMALS, permyriadtostr4(progress), ui8tostr3rj(progress / (PROGRESS_SCALE))));
dwin_string.add(PSTR("%"));
DWIN_Draw_String(
false, font16x32, Percent_Color, Color_Bg_Black,
pb_left + (pb_width - dwin_string.length() * 16) / 2,
pb_top + (pb_height - 32) / 2,
S(dwin_string.string())
);
#endif
#if ENABLED(SHOW_SD_PERCENT)
dwin_string.set(TERN(PRINT_PROGRESS_SHOW_DECIMALS, permyriadtostr4(progress), ui8tostr3rj(progress / (PROGRESS_SCALE))));
dwin_string.add('%');
DWIN_Draw_String(
false, font16x32, Percent_Color, Color_Bg_Black,
pb_left + (pb_width - dwin_string.length * 16) / 2,
pb_top + (pb_height - 32) / 2,
S(dwin_string.string())
);
#endif
old_solid = pb_solid;
}
old_solid = pb_solid;
}
#endif // HAS_PRINT_PROGRESS
//
// Status Message
@@ -386,6 +468,7 @@ void MarlinUI::draw_status_screen() {
draw_status_message(blink);
ui.did_first_redraw = true;
ui.old_is_printing = print_job_timer.isRunning();
}
#endif // IS_DWIN_MARLINUI

View File

@@ -0,0 +1,208 @@
/**
* Base64 encoder/decoder for arduino repo
* Uses common web conventions - '+' for 62, '/' for 63, '=' for padding.
* Note that invalid base64 characters are interpreted as padding.
* Author: Densaugeo
* Maintainer: Densaugeo
* Version: 1.2.1.1
* Changed unsigned int to uint16_t for use in the professional Ender 3V2/S1 firmware
* Url: https://www.arduino.cc/reference/en/libraries/base64/
*/
#ifndef BASE64_H_INCLUDED
#define BASE64_H_INCLUDED
/* binary_to_base64:
* Description:
* Converts a single byte from a binary value to the corresponding base64 character
* Parameters:
* v - Byte to convert
* Returns:
* ascii code of base64 character. If byte is >= 64, then there is not corresponding base64 character
* and 255 is returned
*/
unsigned char binary_to_base64(unsigned char v);
/* base64_to_binary:
* Description:
* Converts a single byte from a base64 character to the corresponding binary value
* Parameters:
* c - Base64 character (as ascii code)
* Returns:
* 6-bit binary value
*/
unsigned char base64_to_binary(unsigned char c);
/* encode_base64_length:
* Description:
* Calculates length of base64 string needed for a given number of binary bytes
* Parameters:
* input_length - Amount of binary data in bytes
* Returns:
* Number of base64 characters needed to encode input_length bytes of binary data
*/
uint16_t encode_base64_length(uint16_t input_length);
/* decode_base64_length:
* Description:
* Calculates number of bytes of binary data in a base64 string
* Variant that does not use input_length no longer used within library, retained for API compatibility
* Parameters:
* input - Base64-encoded null-terminated string
* input_length (optional) - Number of bytes to read from input pointer
* Returns:
* Number of bytes of binary data in input
*/
uint16_t decode_base64_length(unsigned char input[]);
uint16_t decode_base64_length(unsigned char input[], uint16_t input_length);
/* encode_base64:
* Description:
* Converts an array of bytes to a base64 null-terminated string
* Parameters:
* input - Pointer to input data
* input_length - Number of bytes to read from input pointer
* output - Pointer to output string. Null terminator will be added automatically
* Returns:
* Length of encoded string in bytes (not including null terminator)
*/
uint16_t encode_base64(unsigned char input[], uint16_t input_length, unsigned char output[]);
/* decode_base64:
* Description:
* Converts a base64 null-terminated string to an array of bytes
* Parameters:
* input - Pointer to input string
* input_length (optional) - Number of bytes to read from input pointer
* output - Pointer to output array
* Returns:
* Number of bytes in the decoded binary
*/
uint16_t decode_base64(unsigned char input[], unsigned char output[]);
uint16_t decode_base64(unsigned char input[], uint16_t input_length, unsigned char output[]);
unsigned char binary_to_base64(unsigned char v) {
// Capital letters - 'A' is ascii 65 and base64 0
if (v < 26) return v + 'A';
// Lowercase letters - 'a' is ascii 97 and base64 26
if (v < 52) return v + 71;
// Digits - '0' is ascii 48 and base64 52
if (v < 62) return v - 4;
// '+' is ascii 43 and base64 62
if (v == 62) return '+';
// '/' is ascii 47 and base64 63
if (v == 63) return '/';
return 64;
}
unsigned char base64_to_binary(unsigned char c) {
// Capital letters - 'A' is ascii 65 and base64 0
if ('A' <= c && c <= 'Z') return c - 'A';
// Lowercase letters - 'a' is ascii 97 and base64 26
if ('a' <= c && c <= 'z') return c - 71;
// Digits - '0' is ascii 48 and base64 52
if ('0' <= c && c <= '9') return c + 4;
// '+' is ascii 43 and base64 62
if (c == '+') return 62;
// '/' is ascii 47 and base64 63
if (c == '/') return 63;
return 255;
}
uint16_t encode_base64_length(uint16_t input_length) {
return (input_length + 2)/3*4;
}
uint16_t decode_base64_length(unsigned char input[]) {
return decode_base64_length(input, -1);
}
uint16_t decode_base64_length(unsigned char input[], uint16_t input_length) {
unsigned char *start = input;
while (base64_to_binary(input[0]) < 64 && (unsigned char)(input - start) < input_length) {
++input;
}
input_length = input - start;
return input_length/4*3 + (input_length % 4 ? input_length % 4 - 1 : 0);
}
uint16_t encode_base64(unsigned char input[], uint16_t input_length, unsigned char output[]) {
uint16_t full_sets = input_length/3;
// While there are still full sets of 24 bits...
for (uint16_t i = 0; i < full_sets; ++i) {
output[0] = binary_to_base64( input[0] >> 2);
output[1] = binary_to_base64((input[0] & 0x03) << 4 | input[1] >> 4);
output[2] = binary_to_base64((input[1] & 0x0F) << 2 | input[2] >> 6);
output[3] = binary_to_base64( input[2] & 0x3F);
input += 3;
output += 4;
}
switch(input_length % 3) {
case 0:
output[0] = '\0';
break;
case 1:
output[0] = binary_to_base64( input[0] >> 2);
output[1] = binary_to_base64((input[0] & 0x03) << 4);
output[2] = '=';
output[3] = '=';
output[4] = '\0';
break;
case 2:
output[0] = binary_to_base64( input[0] >> 2);
output[1] = binary_to_base64((input[0] & 0x03) << 4 | input[1] >> 4);
output[2] = binary_to_base64((input[1] & 0x0F) << 2);
output[3] = '=';
output[4] = '\0';
break;
}
return encode_base64_length(input_length);
}
uint16_t decode_base64(unsigned char input[], unsigned char output[]) {
return decode_base64(input, -1, output);
}
uint16_t decode_base64(unsigned char input[], uint16_t input_length, unsigned char output[]) {
uint16_t output_length = decode_base64_length(input, input_length);
// While there are still full sets of 24 bits...
for (uint16_t i = 2; i < output_length; i += 3) {
output[0] = base64_to_binary(input[0]) << 2 | base64_to_binary(input[1]) >> 4;
output[1] = base64_to_binary(input[1]) << 4 | base64_to_binary(input[2]) >> 2;
output[2] = base64_to_binary(input[2]) << 6 | base64_to_binary(input[3]);
input += 4;
output += 3;
}
switch(output_length % 3) {
case 1:
output[0] = base64_to_binary(input[0]) << 2 | base64_to_binary(input[1]) >> 4;
break;
case 2:
output[0] = base64_to_binary(input[0]) << 2 | base64_to_binary(input[1]) >> 4;
output[1] = base64_to_binary(input[1]) << 4 | base64_to_binary(input[2]) >> 2;
break;
}
return output_length;
}
#endif // ifndef

View File

@@ -0,0 +1,286 @@
/**
* Marlin 3D Printer Firmware
* Copyright (c) 2022 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
*
* Based on Sprinter and grbl.
* Copyright (c) 2011 Camiel Gubbels / Erik van der Zalm
*
* 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/>.
*
*/
/**
* Bed Level Tools for Pro UI
* Extended by: Miguel A. Risco-Castillo (MRISCOC)
* Version: 2.0.0
* Date: 2022/05/23
*
* Based on the original work of: Henri-J-Norden
* https://github.com/Jyers/Marlin/pull/126
*/
#include "../../../inc/MarlinConfigPre.h"
#include "bedlevel_tools.h"
#if BOTH(DWIN_LCD_PROUI, HAS_LEVELING)
#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"
BedLevelToolsClass BedLevelTools;
#if USE_UBL_VIEWER
bool BedLevelToolsClass::viewer_asymmetric_range = false;
bool BedLevelToolsClass::viewer_print_value = false;
#endif
bool BedLevelToolsClass::goto_mesh_value = false;
uint8_t BedLevelToolsClass::mesh_x = 0;
uint8_t BedLevelToolsClass::mesh_y = 0;
uint8_t BedLevelToolsClass::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 BedLevelToolsClass::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 BedLevelToolsClass::create_plane_from_mesh() {
struct linear_fit_data lsf_results;
incremental_LSF_reset(&lsf_results);
GRID_LOOP(x, y) {
if (!isnan(bedlevel.z_values[x][y])) {
xy_pos_t rpos = { bedlevel.get_mesh_x(x), bedlevel.get_mesh_y(y) };
incremental_LSF(&lsf_results, rpos, bedlevel.z_values[x][y]);
}
}
if (finish_incremental_LSF(&lsf_results)) {
SERIAL_ECHOPGM("Could not complete LSF!");
return true;
}
bedlevel.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 = bedlevel.get_mesh_x(i),
my = bedlevel.get_mesh_y(j),
mz = bedlevel.z_values[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);
}
bedlevel.z_values[i][j] = mz - lsf_results.D;
}
return false;
}
#else
void BedLevelToolsClass::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 BedLevelToolsClass::manual_move(const uint8_t mesh_x, const uint8_t mesh_y, bool zmove/*=false*/) {
gcode.process_subcommands_now(F("G28O"));
if (zmove) {
planner.synchronize();
current_position.z = goto_mesh_value ? bedlevel.z_values[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 ? bedlevel.z_values[mesh_x][mesh_y] : Z_CLEARANCE_BETWEEN_PROBES;
planner.buffer_line(current_position, homing_feedrate(Z_AXIS), active_extruder);
planner.synchronize();
HMI_ReturnScreen();
}
}
void BedLevelToolsClass::MoveToXYZ() {
BedLevelTools.goto_mesh_value = true;
BedLevelTools.manual_move(BedLevelTools.mesh_x, BedLevelTools.mesh_y, false);
}
void BedLevelToolsClass::MoveToXY() {
BedLevelTools.goto_mesh_value = false;
BedLevelTools.manual_move(BedLevelTools.mesh_x, BedLevelTools.mesh_y, false);
}
void BedLevelToolsClass::MoveToZ() {
BedLevelTools.goto_mesh_value = true;
BedLevelTools.manual_move(BedLevelTools.mesh_x, BedLevelTools.mesh_y, true);
}
void BedLevelToolsClass::ProbeXY() {
sprintf_P(cmd, PSTR("G30X%sY%s"),
dtostrf(bedlevel.get_mesh_x(BedLevelTools.mesh_x), 1, 2, str_1),
dtostrf(bedlevel.get_mesh_y(BedLevelTools.mesh_y), 1, 2, str_2)
);
gcode.process_subcommands_now(cmd);
}
float BedLevelToolsClass::get_max_value() {
float max = __FLT_MAX__ * -1;
GRID_LOOP(x, y) {
if (!isnan(bedlevel.z_values[x][y]) && bedlevel.z_values[x][y] > max)
max = bedlevel.z_values[x][y];
}
return max;
}
float BedLevelToolsClass::get_min_value() {
float min = __FLT_MAX__;
GRID_LOOP(x, y) {
if (!isnan(bedlevel.z_values[x][y]) && bedlevel.z_values[x][y] < min)
min = bedlevel.z_values[x][y];
}
return min;
}
bool BedLevelToolsClass::meshvalidate() {
float min = __FLT_MAX__, max = __FLT_MAX__ * -1;
GRID_LOOP(x, y) {
if (isnan(bedlevel.z_values[x][y])) return false;
if (bedlevel.z_values[x][y] < min) min = bedlevel.z_values[x][y];
if (bedlevel.z_values[x][y] > max) max = bedlevel.z_values[x][y];
}
return WITHIN(max, MESH_Z_OFFSET_MIN, MESH_Z_OFFSET_MAX);
}
#if USE_UBL_VIEWER
void BedLevelToolsClass::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(bedlevel.z_values[x][y]) ? Color_Grey : ( // gray if undefined
(bedlevel.z_values[x][y] < 0 ?
(uint16_t)round(0x1F * -bedlevel.z_values[x][y] / (!viewer_asymmetric_range ? range : v_min)) << 11 : // red if mesh point value is negative
(uint16_t)round(0x3F * bedlevel.z_values[x][y] / (!viewer_asymmetric_range ? range : v_max)) << 5) | // green if mesh point value is positive
_MIN(0x1F, (((uint8_t)abs(bedlevel.z_values[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(bedlevel.z_values[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(bedlevel.z_values[x][y]), 1, 2, str_1));
else
sprintf_P(buf, PSTR("%02i"), (uint16_t)(abs(bedlevel.z_values[x][y] - (int16_t)bedlevel.z_values[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 BedLevelToolsClass::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 // USE_UBL_VIEWER
#endif // DWIN_LCD_PROUI && HAS_LEVELING

View File

@@ -0,0 +1,77 @@
/*
* Marlin 3D Printer Firmware
* Copyright (c) 2022 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
*
* Based on Sprinter and grbl.
* Copyright (c) 2011 Camiel Gubbels / Erik van der Zalm
*
* 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/>.
*
*/
/**
* Bed Level Tools for Pro UI
* Extended by: Miguel A. Risco-Castillo (MRISCOC)
* Version: 2.0.0
* Date: 2022/05/23
*
* Based on the original work of: Henri-J-Norden
* https://github.com/Jyers/Marlin/pull/126
*/
#pragma once
#include "../../../inc/MarlinConfigPre.h"
#if ENABLED(AUTO_BED_LEVELING_UBL)
//#define USE_UBL_VIEWER 1
#endif
#define MESH_Z_OFFSET_MIN -3.0
#define MESH_Z_OFFSET_MAX 3.0
class BedLevelToolsClass {
public:
#if USE_UBL_VIEWER
static bool viewer_asymmetric_range;
static bool viewer_print_value;
#endif
static bool goto_mesh_value;
static uint8_t mesh_x;
static uint8_t mesh_y;
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 void MoveToXYZ();
static void MoveToXY();
static void MoveToZ();
static void ProbeXY();
static float get_max_value();
static float get_min_value();
static bool meshvalidate();
#if 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 BedLevelToolsClass BedLevelTools;
void Goto_MeshViewer();

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,293 @@
/**
* Marlin 3D Printer Firmware
* Copyright (c) 2021 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
*
* Based on Sprinter and grbl.
* Copyright (c) 2011 Camiel Gubbels / Erik van der Zalm
*
* 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
/**
* DWIN Enhanced implementation for PRO UI
* Author: Miguel A. Risco-Castillo (MRISCOC)
* Version: 3.17.2
* Date: 2022/04/08
*/
#include "dwin_defines.h"
#include "dwinui.h"
#include "../common/encoder.h"
#include "../../../libs/BL24CXX.h"
#include "../../../inc/MarlinConfig.h"
enum processID : uint8_t {
// Process ID
MainMenu,
Menu,
SetInt,
SetPInt,
SetIntNoDraw,
SetFloat,
SetPFloat,
SelectFile,
PrintProcess,
Popup,
Leveling,
Locked,
Reboot,
PrintDone,
ESDiagProcess,
WaitResponse,
Homing,
PidProcess,
NothingToDo
};
enum pidresult_t : uint8_t {
PID_BAD_EXTRUDER_NUM,
PID_TEMP_TOO_HIGH,
PID_TUNING_TIMEOUT,
PID_EXTR_START,
PID_BED_START,
PID_DONE
};
#define DWIN_CHINESE 123
#define DWIN_ENGLISH 0
typedef struct {
int8_t Color[3]; // Color components
pidresult_t pidresult = PID_DONE;
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
bool abort_flag:1; // printing is aborting
bool abort_action:1; // flag a aborting action
bool print_finish:1; // print was finished
bool select_flag:1; // Popup button selected
bool home_flag:1; // homing in course
bool heat_flag:1; // 0: heating done 1: during heating
} HMI_flag_t;
extern HMI_value_t HMI_value;
extern HMI_flag_t HMI_flag;
extern uint8_t checkkey;
extern millis_t dwin_heat_time;
// Popups
#if HAS_HOTEND || HAS_HEATED_BED
void DWIN_Popup_Temperature(const bool toohigh);
#endif
#if ENABLED(POWER_LOSS_RECOVERY)
void Popup_PowerLossRecovery();
#endif
// 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();
void Goto_Main_Menu();
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 DWIN_DrawStatusLine(); // Draw simple status text
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 HMI_WaitForUser();
void HMI_SaveProcessID(const uint8_t id);
void HMI_SDCardInit();
void HMI_SDCardUpdate();
void EachMomentUpdate();
void update_variable();
void DWIN_InitScreen();
void DWIN_HandleScreen();
void DWIN_CheckStatusMessage();
void DWIN_HomingStart();
void DWIN_HomingDone();
#if HAS_MESH
void DWIN_MeshUpdate(const int8_t xpos, const int8_t ypos, const_float_t zval);
#endif
void DWIN_LevelingStart();
void DWIN_LevelingDone();
void DWIN_PidTuning(pidresult_t result);
void DWIN_Print_Started(const bool sd=false);
void DWIN_Print_Pause();
void DWIN_Print_Resume();
void DWIN_Print_Finished();
void DWIN_Print_Aborted();
#if HAS_FILAMENT_SENSOR
void DWIN_FilamentRunout(const uint8_t extruder);
#endif
void DWIN_M73();
void DWIN_Print_Header(const char *text);
void DWIN_SetColorDefaults();
void DWIN_ApplyColor();
void DWIN_CopySettingsTo(char * const buff);
void DWIN_CopySettingsFrom(const char * const buff);
void DWIN_SetDataDefaults();
void DWIN_RebootScreen();
#if ENABLED(ADVANCED_PAUSE_FEATURE)
void DWIN_Popup_Pause(FSTR_P const fmsg, uint8_t button=0);
void Draw_Popup_FilamentPurge();
void Goto_FilamentPurge();
void HMI_FilamentPurge();
#endif
// Utility and extensions
#if HAS_LOCKSCREEN
void DWIN_LockScreen();
void DWIN_UnLockScreen();
void HMI_LockScreen();
#endif
#if HAS_MESH
void DWIN_MeshViewer();
#endif
#if HAS_GCODE_PREVIEW
void HMI_ConfirmToPrint();
#endif
#if HAS_ESDIAG
void Draw_EndStopDiag();
#endif
#if ENABLED(PRINTCOUNTER)
void Draw_PrintStats();
#endif
// Menu drawing functions
void Draw_Control_Menu();
void Draw_AdvancedSettings_Menu();
void Draw_Prepare_Menu();
void Draw_Move_Menu();
void Draw_Tramming_Menu();
#if HAS_HOME_OFFSET
void Draw_HomeOffset_Menu();
#endif
#if HAS_BED_PROBE
void Draw_ProbeSet_Menu();
#endif
void Draw_FilSet_Menu();
#if ENABLED(NOZZLE_PARK_FEATURE)
void Draw_ParkPos_Menu();
#endif
void Draw_PhySet_Menu();
void Draw_SelectColors_Menu();
void Draw_GetColor_Menu();
#if BOTH(CASE_LIGHT_MENU, CASELIGHT_USES_BRIGHTNESS)
void Draw_CaseLight_Menu();
#endif
#if ENABLED(LED_CONTROL_MENU)
void Draw_LedControl_Menu();
#endif
void Draw_Tune_Menu();
void Draw_Motion_Menu();
#if ENABLED(ADVANCED_PAUSE_FEATURE)
void Draw_FilamentMan_Menu();
#endif
#if ENABLED(MESH_BED_LEVELING)
void Draw_ManualMesh_Menu();
#endif
#if HAS_HOTEND
void Draw_Preheat1_Menu();
void Draw_Preheat2_Menu();
void Draw_Preheat3_Menu();
void Draw_HotendPID_Menu();
#endif
void Draw_Temperature_Menu();
void Draw_MaxSpeed_Menu();
void Draw_MaxAccel_Menu();
#if HAS_CLASSIC_JERK
void Draw_MaxJerk_Menu();
#endif
void Draw_Steps_Menu();
#if HAS_HEATED_BED
void Draw_BedPID_Menu();
#endif
#if EITHER(HAS_BED_PROBE, BABYSTEPPING)
void Draw_ZOffsetWiz_Menu();
#endif
#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

@@ -0,0 +1,122 @@
/**
* Marlin 3D Printer Firmware
* Copyright (c) 2021 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
*
* Based on Sprinter and grbl.
* Copyright (c) 2011 Camiel Gubbels / Erik van der Zalm
*
* 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
/**
* DWIN general defines and data structs for PRO UI
* Author: Miguel A. Risco-Castillo (MRISCOC)
* Version: 3.11.2
* Date: 2022/02/28
*/
#define HAS_GCODE_PREVIEW 1
#define HAS_PIDPLOT 1
#define HAS_ESDIAG 1
#define HAS_LOCKSCREEN 1
//#define DEBUG_DWIN 1
//#define NEED_HEX_PRINT 1
#include "../../../inc/MarlinConfigPre.h"
#include "../common/dwin_color.h"
#if ENABLED(LED_CONTROL_MENU)
#include "../../../feature/leds/leds.h"
#endif
#include <stddef.h>
#if defined(__STM32F1__) || defined(STM32F1)
#define DASH_REDRAW 1
#endif
#define Def_Background_Color RGB( 1, 12, 8)
#define Def_Cursor_color RGB(20, 49, 31)
#define Def_TitleBg_color RGB( 0, 23, 16)
#define Def_TitleTxt_color Color_White
#define Def_Text_Color Color_White
#define Def_Selected_Color Select_Color
#define Def_SplitLine_Color RGB( 0, 23, 16)
#define Def_Highlight_Color Color_White
#define Def_StatusBg_Color RGB( 0, 23, 16)
#define Def_StatusTxt_Color Color_Yellow
#define Def_PopupBg_color Color_Bg_Window
#define Def_PopupTxt_Color Popup_Text_Color
#define Def_AlertBg_Color Color_Bg_Red
#define Def_AlertTxt_Color Color_Yellow
#define Def_PercentTxt_Color Percent_Color
#define Def_Barfill_Color BarFill_Color
#define Def_Indicator_Color Color_White
#define Def_Coordinate_Color Color_White
#define Def_Button_Color RGB( 0, 23, 16)
#if BOTH(LED_CONTROL_MENU, HAS_COLOR_LEDS)
#define Def_Leds_Color LEDColorWhite()
#endif
typedef struct {
// Color settings
uint16_t Background_Color = Def_Background_Color;
uint16_t Cursor_color = Def_Cursor_color;
uint16_t TitleBg_color = Def_TitleBg_color;
uint16_t TitleTxt_color = Def_TitleTxt_color;
uint16_t Text_Color = Def_Text_Color;
uint16_t Selected_Color = Def_Selected_Color;
uint16_t SplitLine_Color = Def_SplitLine_Color;
uint16_t Highlight_Color = Def_Highlight_Color;
uint16_t StatusBg_Color = Def_StatusBg_Color;
uint16_t StatusTxt_Color = Def_StatusTxt_Color;
uint16_t PopupBg_color = Def_PopupBg_color;
uint16_t PopupTxt_Color = Def_PopupTxt_Color;
uint16_t AlertBg_Color = Def_AlertBg_Color;
uint16_t AlertTxt_Color = Def_AlertTxt_Color;
uint16_t PercentTxt_Color = Def_PercentTxt_Color;
uint16_t Barfill_Color = Def_Barfill_Color;
uint16_t Indicator_Color = Def_Indicator_Color;
uint16_t Coordinate_Color = Def_Coordinate_Color;
// Temperatures
#if HAS_HOTEND && defined(PREHEAT_1_TEMP_HOTEND)
int16_t HotendPidT = PREHEAT_1_TEMP_HOTEND;
#endif
#if HAS_HEATED_BED && defined(PREHEAT_1_TEMP_BED)
int16_t BedPidT = PREHEAT_1_TEMP_BED;
#endif
#if HAS_HOTEND || HAS_HEATED_BED
int16_t PidCycles = 10;
#endif
#if ENABLED(PREVENT_COLD_EXTRUSION)
int16_t ExtMinT = EXTRUDE_MINTEMP;
#endif
#if BOTH(HAS_HEATED_BED, PREHEAT_BEFORE_LEVELING)
int16_t BedLevT = LEVELING_BED_TEMP;
#endif
#if ENABLED(BAUD_RATE_GCODE)
bool Baud115K = false;
#endif
bool FullManualTramming = false;
#if ENABLED(MESH_BED_LEVELING)
float ManualZOffset = 0;
#endif
// Led
#if BOTH(LED_CONTROL_MENU, HAS_COLOR_LEDS)
LEDColor Led_Color = Def_Leds_Color;
#endif
} HMI_data_t;
static constexpr size_t eeprom_data_size = sizeof(HMI_data_t);
extern HMI_data_t HMI_data;

View File

@@ -21,15 +21,15 @@
*/
/**
* DWIN UI Enhanced implementation
* Author: Miguel A. Risco-Castillo
* Version: 3.6.3
* Date: 2021/09/08
* DWIN Enhanced implementation for PRO UI
* Author: Miguel A. Risco-Castillo (MRISCOC)
* Version: 3.10.1
* Date: 2022/03/06
*/
#include "../../../inc/MarlinConfigPre.h"
#if ENABLED(DWIN_CREALITY_LCD_ENHANCED)
#if ENABLED(DWIN_LCD_PROUI)
#include "../../../inc/MarlinConfig.h"
@@ -147,7 +147,7 @@ void DWIN_SRAMToPic(uint8_t picID) {
//--------------------------Test area -------------------------
//void DWIN_ReadSRAM(uint16_t addr, uint8_t length, const char * const data) {
//void DWIN_ReadSRAM(uint16_t addr, const uint8_t length, const char * const data) {
// size_t i = 0;
// DWIN_Byte(i, 0x32);
// DWIN_Byte(i, 0x5A); // 0x5A Read from SRAM - 0xA5 Read from Flash
@@ -157,4 +157,4 @@ void DWIN_SRAMToPic(uint8_t picID) {
// DWIN_Send(i);
//}
#endif // DWIN_CREALITY_LCD_ENHANCED
#endif // DWIN_LCD_PROUI

View File

@@ -22,10 +22,10 @@
#pragma once
/**
* DWIN UI Enhanced implementation
* Author: Miguel A. Risco-Castillo
* Version: 3.6.3
* Date: 2021/09/08
* DWIN Enhanced implementation for PRO UI
* Author: Miguel A. Risco-Castillo (MRISCOC)
* Version: 3.10.1
* Date: 2022/03/06
*/
#include "../common/dwin_api.h"
@@ -48,13 +48,6 @@ inline void DWIN_Draw_QR(uint8_t QR_Pixel, uint16_t x, uint16_t y, FSTR_P title)
// x/y: Screen paste point
void DWIN_Frame_AreaCopy(uint8_t cacheID, uint16_t xStart, uint16_t yStart, uint16_t xEnd, uint16_t yEnd, uint16_t x, uint16_t y);
// Copy area from virtual display area to current screen
// cacheID: virtual area number
// xStart/yStart: Upper-left of virtual area
// xEnd/yEnd: Lower-right of virtual area
// x/y: Screen paste point
void DWIN_Frame_AreaCopy(uint8_t cacheID, uint16_t xStart, uint16_t yStart, uint16_t xEnd, uint16_t yEnd, uint16_t x, uint16_t y);
// Copy area from current virtual display area to current screen
// xStart/yStart: Upper-left of virtual area
// xEnd/yEnd: Lower-right of virtual area

View File

@@ -0,0 +1,95 @@
/**
* Marlin 3D Printer Firmware
* Copyright (c) 2021 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
*
* Based on Sprinter and grbl.
* Copyright (c) 2011 Camiel Gubbels / Erik van der Zalm
*
* 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/>.
*
*/
/**
* DWIN Enhanced implementation for PRO UI
* Author: Miguel A. Risco-Castillo (MRISCOC)
* Version: 3.11.1
* Date: 2022/02/28
*/
#include "../../../inc/MarlinConfigPre.h"
#if ENABLED(DWIN_LCD_PROUI)
#include "dwin.h"
#include "dwinui.h"
#include "dwin_popup.h"
#include "../../../MarlinCore.h" // for wait_for_user
popupDrawFunc_t popupDraw = nullptr;
popupClickFunc_t popupClick = nullptr;
popupChangeFunc_t popupChange = nullptr;
uint16_t HighlightYPos = 280;
void Draw_Select_Highlight(const bool sel, const uint16_t ypos) {
HighlightYPos = ypos;
HMI_flag.select_flag = sel;
const uint16_t c1 = sel ? HMI_data.Highlight_Color : HMI_data.PopupBg_color,
c2 = sel ? HMI_data.PopupBg_color : HMI_data.Highlight_Color;
DWIN_Draw_Rectangle(0, c1, 25, ypos - 1, 126, ypos + 38);
DWIN_Draw_Rectangle(0, c1, 24, ypos - 2, 127, ypos + 39);
DWIN_Draw_Rectangle(0, c2, 145, ypos - 1, 246, ypos + 38);
DWIN_Draw_Rectangle(0, c2, 144, ypos - 2, 247, ypos + 39);
}
void DWIN_Popup_Continue(const uint8_t icon, FSTR_P const fmsg1, FSTR_P const fmsg2) {
HMI_SaveProcessID(WaitResponse);
DWIN_Draw_Popup(icon, fmsg1, fmsg2, BTN_Continue); // Button Continue
DWIN_UpdateLCD();
}
void DWIN_Popup_ConfirmCancel(const uint8_t icon, FSTR_P const fmsg2) {
DWIN_Draw_Popup(ICON_BLTouch, F("Please confirm"), fmsg2);
DWINUI::Draw_Button(BTN_Confirm, 26, 280);
DWINUI::Draw_Button(BTN_Cancel, 146, 280);
Draw_Select_Highlight(HMI_flag.select_flag);
DWIN_UpdateLCD();
}
void Goto_Popup(const popupDrawFunc_t fnDraw, const popupClickFunc_t fnClick/*=nullptr*/, const popupChangeFunc_t fnChange/*=nullptr*/) {
popupDraw = fnDraw;
popupClick = fnClick;
popupChange = fnChange;
HMI_SaveProcessID(Popup);
HMI_flag.select_flag = false;
popupDraw();
}
void HMI_Popup() {
if (!wait_for_user) {
if (popupClick) popupClick();
return;
}
else {
EncoderState encoder_diffState = get_encoder_state();
if (encoder_diffState == ENCODER_DIFF_CW || encoder_diffState == ENCODER_DIFF_CCW) {
const bool change = encoder_diffState != ENCODER_DIFF_CW;
if (popupChange) popupChange(change); else Draw_Select_Highlight(change, HighlightYPos);
DWIN_UpdateLCD();
}
}
}
#endif // DWIN_LCD_PROUI

View File

@@ -0,0 +1,73 @@
/**
* Marlin 3D Printer Firmware
* Copyright (c) 2021 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
*
* Based on Sprinter and grbl.
* Copyright (c) 2011 Camiel Gubbels / Erik van der Zalm
*
* 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
/**
* DWIN Enhanced implementation for PRO UI
* Author: Miguel A. Risco-Castillo (MRISCOC)
* Version: 3.11.1
* Date: 2022/02/28
*/
#include "dwinui.h"
#include "dwin.h"
typedef void (*popupDrawFunc_t)();
typedef void (*popupClickFunc_t)();
typedef void (*popupChangeFunc_t)(const bool state);
extern popupDrawFunc_t popupDraw;
void Draw_Select_Highlight(const bool sel, const uint16_t ypos);
inline void Draw_Select_Highlight(const bool sel) { Draw_Select_Highlight(sel, 280); };
void DWIN_Popup_Continue(const uint8_t icon, FSTR_P const fmsg1, FSTR_P const fmsg2);
void DWIN_Popup_ConfirmCancel(const uint8_t icon, FSTR_P const fmsg2);
void Goto_Popup(const popupDrawFunc_t fnDraw, const popupClickFunc_t fnClick=nullptr, const popupChangeFunc_t fnChange=nullptr);
void HMI_Popup();
inline void Draw_Popup_Bkgd() {
DWIN_Draw_Rectangle(1, HMI_data.PopupBg_color, 14, 60, 258, 330);
DWIN_Draw_Rectangle(0, HMI_data.Highlight_Color, 14, 60, 258, 330);
}
template<typename T, typename U>
void DWIN_Draw_Popup(const uint8_t icon, T amsg1=nullptr, U amsg2=nullptr, uint8_t button=0) {
DWINUI::ClearMainArea();
Draw_Popup_Bkgd();
if (icon) DWINUI::Draw_Icon(icon, 101, 105);
if (amsg1) DWINUI::Draw_CenteredString(HMI_data.PopupTxt_Color, 210, amsg1);
if (amsg2) DWINUI::Draw_CenteredString(HMI_data.PopupTxt_Color, 240, amsg2);
if (button) DWINUI::Draw_Button(button, 86, 280);
}
template<typename T, typename U>
void DWIN_Show_Popup(const uint8_t icon, T amsg1=nullptr, U amsg2=nullptr, uint8_t button=0) {
DWIN_Draw_Popup(icon, amsg1, amsg2, button);
DWIN_UpdateLCD();
}
template<typename T, typename U>
void DWIN_Popup_Confirm(const uint8_t icon, T amsg1, U amsg2) {
HMI_SaveProcessID(WaitResponse);
DWIN_Draw_Popup(icon, amsg1, amsg2, BTN_Confirm); // Button Confirm
DWIN_UpdateLCD();
}

View File

@@ -21,64 +21,56 @@
*/
/**
* DWIN UI Enhanced implementation
* Author: Miguel A. Risco-Castillo
* Version: 3.6.3
* Date: 2021/09/08
* DWIN Enhanced implementation for PRO UI
* Author: Miguel A. Risco-Castillo (MRISCOC)
* Version: 3.18.1
* Date: 2022/07/05
*/
#include "../../../inc/MarlinConfigPre.h"
#if ENABLED(DWIN_CREALITY_LCD_ENHANCED)
#if ENABLED(DWIN_LCD_PROUI)
#include "../../../inc/MarlinConfig.h"
#include "dwin_lcd.h"
#include "dwinui.h"
#include "dwin_defines.h"
//#define DEBUG_OUT 1
#include "../../../core/debug_out.h"
uint8_t MenuItemTotal = 0;
uint8_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;
uint16_t DWINUI::backcolor = Def_Background_Color;
uint8_t DWINUI::font = font8x16;
uint16_t DWINUI::buttoncolor = Def_Button_Color;
uint8_t DWINUI::fontid = font8x16;
FSTR_P const DWINUI::Author = F(STRING_CONFIG_H_AUTHOR);
void (*DWINUI::onCursorErase)(uint8_t line)=nullptr;
void (*DWINUI::onCursorDraw)(uint8_t line)=nullptr;
void (*DWINUI::onTitleDraw)(TitleClass* title)=nullptr;
void (*DWINUI::onMenuDraw)(MenuClass* menu)=nullptr;
void (*DWINUI::onTitleDraw)(TitleClass* title) = nullptr;
void DWINUI::init() {
DEBUG_ECHOPGM("\r\nDWIN handshake ");
delay(750); // Delay here or init later in the boot process
const bool success = DWIN_Handshake();
if (success) DEBUG_ECHOLNPGM("ok."); else DEBUG_ECHOLNPGM("error.");
delay(750); // Delay for wait to wakeup screen
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);
TERN(SHOW_BOOTSCREEN,,DWIN_Frame_Clear(Color_Bg_Black));
DWIN_UpdateLCD();
cursor.x = 0;
cursor.y = 0;
cursor.reset();
pencolor = Color_White;
textcolor = Def_Text_Color;
backcolor = Def_Background_Color;
font = font8x16;
buttoncolor = Def_Button_Color;
fontid = font8x16;
}
// Set text/number font
void DWINUI::setFont(uint8_t cfont) {
font = cfont;
}
void DWINUI::setFont(fontid_t fid) { fontid = fid; }
// Get font character width
uint8_t DWINUI::fontWidth(uint8_t cfont) {
switch (cfont) {
uint8_t DWINUI::fontWidth(fontid_t fid) {
switch (fid) {
case font6x12 : return 6;
case font8x16 : return 8;
case font10x20: return 10;
@@ -93,9 +85,9 @@ uint8_t DWINUI::fontWidth(uint8_t cfont) {
}
}
// Get font character heigh
uint8_t DWINUI::fontHeight(uint8_t cfont) {
switch (cfont) {
// Get font character height
uint8_t DWINUI::fontHeight(fontid_t fid) {
switch (fid) {
case font6x12 : return 12;
case font8x16 : return 16;
case font10x20: return 20;
@@ -110,20 +102,17 @@ uint8_t DWINUI::fontHeight(uint8_t cfont) {
}
}
// Get screen x coodinates from text column
uint16_t DWINUI::ColToX(uint8_t col) {
return col * fontWidth(font);
}
// Get screen x coordinates from text column
uint16_t DWINUI::ColToX(uint8_t col) { return col * fontWidth(fontid); }
// Get screen y coodinates from text row
uint16_t DWINUI::RowToY(uint8_t row) {
return row * fontHeight(font);
}
// Get screen y coordinates from text row
uint16_t DWINUI::RowToY(uint8_t row) { return row * fontHeight(fontid); }
// Set text/number color
void DWINUI::SetColors(uint16_t fgcolor, uint16_t bgcolor) {
void DWINUI::SetColors(uint16_t fgcolor, uint16_t bgcolor, uint16_t alcolor) {
textcolor = fgcolor;
backcolor = bgcolor;
buttoncolor = alcolor;
}
void DWINUI::SetTextColor(uint16_t fgcolor) {
textcolor = fgcolor;
@@ -156,17 +145,26 @@ void DWINUI::MoveBy(xy_int_t point) {
cursor += point;
}
// 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 Centered string using arbitrary x1 and x2 margins
void DWINUI::Draw_CenteredString(bool bShow, fontid_t fid, uint16_t color, uint16_t bColor, uint16_t x1, uint16_t x2, uint16_t y, const char * const string) {
const uint16_t x = _MAX(0U, x2 + x1 - strlen_P(string) * fontWidth(fid)) / 2 - 1;
DWIN_Draw_String(bShow, fid, color, bColor, x, y, string);
}
// Draw a char at cursor position
void DWINUI::Draw_Char(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, textcolor, backcolor, cursor.x, cursor.y, string, 1);
MoveBy(fontWidth(font), 0);
DWIN_Draw_String(false, fontid, 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(fontid), 0);
}
// Draw a string at cursor position
@@ -174,29 +172,65 @@ void DWINUI::Draw_Char(const char c) {
// *string: The string
// rlimit: For draw less chars than string length use rlimit
void DWINUI::Draw_String(const char * const string, uint16_t rlimit) {
DWIN_Draw_String(false, font, textcolor, backcolor, cursor.x, cursor.y, string, rlimit);
MoveBy(strlen(string) * fontWidth(font), 0);
DWIN_Draw_String(false, fontid, textcolor, backcolor, cursor.x, cursor.y, string, rlimit);
MoveBy(strlen(string) * fontWidth(fontid), 0);
}
void DWINUI::Draw_String(uint16_t color, const char * const string, uint16_t rlimit) {
DWIN_Draw_String(false, font, color, backcolor, cursor.x, cursor.y, string, rlimit);
MoveBy(strlen(string) * fontWidth(font), 0);
DWIN_Draw_String(false, fontid, color, backcolor, cursor.x, cursor.y, string, rlimit);
MoveBy(strlen(string) * fontWidth(fontid), 0);
}
// Draw a signed floating point number
// 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
// size: Font size
// signedMode: 1=signed; 0=unsigned
// fid: Font ID
// color: Character color
// bColor: Background color
// iNum: Number of whole digits
// fNum: Number of decimal digits
// x/y: Upper-left point
// value: Float value
void DWINUI::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_FloatValue(bShow, zeroFill, zeroMode, size, color, bColor, iNum, fNum, x, y, value < 0 ? -value : value);
DWIN_Draw_String(bShow, size, color, bColor, x - 6, y, value < 0 ? F("-") : F(" "));
// iNum: Number of digits
// x/y: Upper-left coordinate
// value: Integer value
void DWINUI::Draw_Int(uint8_t bShow, bool signedMode, fontid_t fid, 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, fid, 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
// fid: Font ID
// 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, fontid_t fid, 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, fid, 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) {
DWIN_Draw_Rectangle(1, bcolor, x1, y1, x2, y2);
Draw_CenteredString(0, fontid, color, bcolor, x1, x2, (y2 + y1 - fontHeight())/2, caption);
}
void DWINUI::Draw_Button(uint8_t id, uint16_t x, uint16_t y) {
switch (id) {
case BTN_Cancel : Draw_Button(GET_TEXT_F(MSG_BUTTON_CANCEL), x, y); break;
case BTN_Confirm : Draw_Button(GET_TEXT_F(MSG_BUTTON_CONFIRM), x, y); break;
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;
}
}
// -------------------------- Extra -------------------------------//
// Draw a circle
// color: circle color
// x: the abscissa of the center of the circle
@@ -244,47 +278,40 @@ void DWINUI::Draw_FillCircle(uint16_t bcolor, uint16_t x,uint16_t y,uint8_t r) {
// color1 : Start color
// color2 : End color
uint16_t DWINUI::ColorInt(int16_t val, int16_t minv, int16_t maxv, uint16_t color1, uint16_t color2) {
uint8_t B,G,R;
float n;
n = (float)(val-minv)/(maxv-minv);
R = (1-n)*GetRColor(color1) + n*GetRColor(color2);
G = (1-n)*GetGColor(color1) + n*GetGColor(color2);
B = (1-n)*GetBColor(color1) + n*GetBColor(color2);
return RGB(R,G,B);
uint8_t B, G, R;
const float n = (float)(val - minv) / (maxv - minv);
R = (1 - n) * GetRColor(color1) + n * GetRColor(color2);
G = (1 - n) * GetGColor(color1) + n * GetGColor(color2);
B = (1 - n) * GetBColor(color1) + n * GetBColor(color2);
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
uint16_t DWINUI::RainbowInt(int16_t val, int16_t minv, int16_t maxv) {
uint8_t B,G,R;
const uint8_t maxB = 28;
const uint8_t maxR = 28;
const uint8_t maxG = 38;
uint8_t B, G, R;
const uint8_t maxB = 28, maxR = 28, maxG = 38;
const int16_t limv = _MAX(abs(minv), abs(maxv));
float n;
if (minv>=0) {
n = (float)(val-minv)/(maxv-minv);
} else {
n = (float)val/limv;
}
n = _MIN(1, n);
n = _MAX(-1, n);
float n = minv >= 0 ? (float)(val - minv) / (maxv - minv) : (float)val / limv;
LIMIT(n, -1, 1);
if (n < 0) {
R = 0;
G = (1+n)*maxG;
B = (-n)*maxB;
} else if (n < 0.5) {
R = maxR*n*2;
G = (1 + n) * maxG;
B = (-n) * maxB;
}
else if (n < 0.5) {
R = maxR * n * 2;
G = maxG;
B = 0;
} else {
}
else {
R = maxR;
G = maxG*(1-n);
G = maxG * (1 - n);
B = 0;
}
return RGB(R,G,B);
return RGB(R, G, B);
}
// Draw a checkbox
@@ -298,37 +325,10 @@ void DWINUI::Draw_Checkbox(uint16_t color, uint16_t bcolor, uint16_t x, uint16_t
}
// Clear Menu by filling the menu area with background color
void DWINUI::ClearMenuArea() {
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 (uint8_t i = 0; i < MenuItemCount; i++) delete MenuItems[i];
delete[] MenuItems;
MenuItems = nullptr;
MenuItemCount = 0;
MenuItemTotal = 0;
}
void DWINUI::MenuItemsPrepare(uint8_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;
@@ -369,85 +369,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 (uint8_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_CREALITY_LCD_ENHANCED
#endif // DWIN_LCD_PROUI

View File

@@ -0,0 +1,562 @@
/**
* Marlin 3D Printer Firmware
* Copyright (c) 2021 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
*
* Based on Sprinter and grbl.
* Copyright (c) 2011 Camiel Gubbels / Erik van der Zalm
*
* 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
/**
* DWIN Enhanced implementation for PRO UI
* Author: Miguel A. Risco-Castillo (MRISCOC)
* Version: 3.18.1
* Date: 2022/07/05
*/
#include "dwin_lcd.h"
#include "../common/dwin_set.h"
#include "../common/dwin_font.h"
#include "../common/dwin_color.h"
// Extra Icons
#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_BltouchReset ICON_StockConfiguration
#define ICON_Brightness ICON_Motion
#define ICON_Cancel ICON_StockConfiguration
#define ICON_CustomPreheat ICON_SetEndTemp
#define ICON_Error ICON_TempTooHigh
#define ICON_ESDiag ICON_Info
#define ICON_ExtrudeMinT ICON_HotendTemp
#define ICON_FilLoad ICON_WriteEEPROM
#define ICON_FilMan ICON_ResumeEEPROM
#define ICON_FilSet ICON_ResumeEEPROM
#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
#define ICON_HomeOffset ICON_AdvSet
#define ICON_HomeOffsetX ICON_StepX
#define ICON_HomeOffsetY ICON_StepY
#define ICON_HomeOffsetZ ICON_StepZ
#define ICON_HSMode ICON_StockConfiguration
#define ICON_InvertE0 ICON_StepE
#define ICON_Tram ICON_SetEndTemp
#define ICON_Level ICON_HotendTemp
#define ICON_Lock ICON_Cool
#define ICON_ManualMesh ICON_HotendTemp
#define ICON_MaxPosX ICON_MoveX
#define ICON_MaxPosY ICON_MoveY
#define ICON_MaxPosZ ICON_MoveZ
#define ICON_MeshNext ICON_Axis
#define ICON_MeshPoints ICON_SetEndTemp
#define ICON_MeshSave ICON_WriteEEPROM
#define ICON_MeshViewer ICON_HotendTemp
#define ICON_MoveZ0 ICON_HotendTemp
#define ICON_Park ICON_Motion
#define ICON_ParkPos ICON_AdvSet
#define ICON_ParkPosX ICON_StepX
#define ICON_ParkPosY ICON_StepY
#define ICON_ParkPosZ ICON_StepZ
#define ICON_PhySet ICON_PrintSize
#define ICON_PIDbed ICON_SetBedTemp
#define ICON_PIDcycles ICON_ResumeEEPROM
#define ICON_PIDValue ICON_Contact
#define ICON_PrintStats ICON_PrintTime
#define ICON_PrintStatsReset ICON_RemainTime
#define ICON_ProbeDeploy ICON_SetEndTemp
#define ICON_ProbeMargin ICON_PrintSize
#define ICON_ProbeOffsetX ICON_StepX
#define ICON_ProbeOffsetY ICON_StepY
#define ICON_ProbeOffsetZ ICON_StepZ
#define ICON_ProbeSet ICON_SetEndTemp
#define ICON_ProbeStow ICON_SetEndTemp
#define ICON_ProbeTest ICON_SetEndTemp
#define ICON_ProbeZSpeed ICON_MaxSpeedZ
#define ICON_Pwrlossr ICON_Motion
#define ICON_Reboot ICON_ResumeEEPROM
#define ICON_Runout ICON_MaxAccE
#define ICON_Scolor ICON_MaxSpeed
#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
// Buttons
#define BTN_Continue 85
#define BTN_Cancel 87
#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
#define DWIN_FONT_STAT font10x20
#define DWIN_FONT_HEAD font10x20
#define DWIN_FONT_ALERT font10x20
#define STATUS_Y 354
#define LCD_WIDTH (DWIN_WIDTH / 8) // only if the default fontid is font8x16
// Minimum unit (0.1) : multiple (10)
#define UNITFDIGITS 1
#define MINUNITMULT POW(10, UNITFDIGITS)
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
ICOX = 26, // Menu item icon X position
LBLX = 55, // Menu item label X position
VALX = 210, // Menu item value X position
MENU_CHR_W = 8, MENU_CHR_H = 16, // Menu font 8x16
STAT_CHR_W = 10;
// Menuitem Y position
#define MYPOS(L) (TITLE_HEIGHT + MLINE * (L))
// Menuitem caption Offset
#define CAPOFF ((MLINE - MENU_CHR_H) / 2)
// Menuitem caption Y position
#define MBASE(L) (MYPOS(L) + CAPOFF)
typedef struct { uint16_t left, top, right, bottom; } rect_t;
typedef struct { uint16_t x, y, w, h; } frame_rect_t;
class TitleClass {
public:
char caption[32] = "";
uint8_t frameid = 0;
rect_t frame = {0};
void draw();
void SetCaption(const char * const title);
inline void SetCaption(FSTR_P title) { SetCaption((char *)title); }
void ShowCaption(const char * const title);
inline void ShowCaption(FSTR_P title) { ShowCaption((char *)title); }
void SetFrame(uint8_t id, uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2);
void SetFrame(uint16_t x, uint16_t y, uint16_t w, uint16_t h);
void FrameCopy(uint8_t id, uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2);
void FrameCopy(uint16_t x, uint16_t y, uint16_t h, uint16_t v);
};
extern TitleClass Title;
namespace DWINUI {
extern xy_int_t cursor;
extern uint16_t pencolor;
extern uint16_t textcolor;
extern uint16_t backcolor;
extern uint16_t buttoncolor;
extern fontid_t fontid;
extern FSTR_P const Author;
extern void (*onTitleDraw)(TitleClass* title);
// DWIN LCD Initialization
void init();
// Set text/number font
void setFont(fontid_t cfont);
// Get font character width
uint8_t fontWidth(fontid_t cfont);
inline uint8_t fontWidth() { return fontWidth(fontid); };
// Get font character height
uint8_t fontHeight(fontid_t cfont);
inline uint8_t fontHeight() { return fontHeight(fontid); };
// Get screen x coordinates from text column
uint16_t ColToX(uint8_t col);
// Get screen y coordinates from text row
uint16_t RowToY(uint8_t row);
// Set text/number color
void SetColors(uint16_t fgcolor, uint16_t bgcolor, uint16_t alcolor);
void SetTextColor(uint16_t fgcolor);
void SetBackgroundColor(uint16_t bgcolor);
// Moves cursor to point
// x: abscissa of the display
// y: ordinate of the display
// point: xy coordinate
void MoveTo(int16_t x, int16_t y);
void MoveTo(xy_int_t point);
// Moves cursor relative to the actual position
// x: abscissa of the display
// y: ordinate of the display
// point: xy coordinate
void MoveBy(int16_t x, int16_t y);
void MoveBy(xy_int_t point);
// Draw a line from the cursor to xy position
// color: Line segment color
// x/y: End point
inline void LineTo(uint16_t color, uint16_t x, uint16_t y) {
DWIN_Draw_Line(color, cursor.x, cursor.y, x, y);
}
inline void LineTo(uint16_t x, uint16_t y) {
DWIN_Draw_Line(pencolor, cursor.x, cursor.y, x, y);
}
// Extend a frame box
// v: value to extend
inline frame_rect_t ExtendFrame(frame_rect_t frame, uint8_t v) {
frame_rect_t t;
t.x = frame.x - v;
t.y = frame.y - v;
t.w = frame.w + 2 * v;
t.h = frame.h + 2 * v;
return t;
}
// Draw an Icon with transparent background from the library ICON
// icon: Icon ID
// x/y: Upper-left point
inline void Draw_Icon(uint8_t icon, uint16_t x, uint16_t y) {
DWIN_ICON_Show(ICON, icon, x, y);
}
// Draw an Icon from the library ICON with its background
// icon: Icon ID
// x/y: Upper-left point
inline void Draw_IconWB(uint8_t icon, uint16_t x, uint16_t y) {
DWIN_ICON_Show(true, false, false, ICON, icon, x, y);
}
// Draw a numeric integer value
// bShow: true=display background color; false=don't display background color
// signedMode: 1=signed; 0=unsigned
// fid: Font ID
// color: Character color
// bColor: Background color
// iNum: Number of digits
// x/y: Upper-left coordinate
// value: Integer value
void Draw_Int(uint8_t bShow, bool signedMode, fontid_t fid, 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, fontid_t fid, uint16_t color, uint16_t bColor, uint8_t iNum, uint16_t x, uint16_t y, long value) {
Draw_Int(bShow, 0, fid, color, bColor, iNum, x, y, value);
}
inline void Draw_Int(uint8_t iNum, long value) {
Draw_Int(false, 0, fontid, textcolor, backcolor, iNum, cursor.x, cursor.y, value);
MoveBy(iNum * fontWidth(fontid), 0);
}
inline void Draw_Int(uint8_t iNum, uint16_t x, uint16_t y, long value) {
Draw_Int(false, 0, fontid, textcolor, backcolor, iNum, x, y, value);
}
inline void Draw_Int(uint16_t color, uint8_t iNum, uint16_t x, uint16_t y, long value) {
Draw_Int(false, 0, fontid, 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) {
Draw_Int(true, 0, fontid, color, bColor, iNum, x, y, value);
}
inline void Draw_Int(fontid_t fid, uint16_t color, uint16_t bColor, uint8_t iNum, uint16_t x, uint16_t y, long value) {
Draw_Int(true, 0, fid, color, bColor, iNum, x, y, value);
}
// Draw a signed integer
inline void Draw_Signed_Int(uint8_t bShow, fontid_t fid, uint16_t color, uint16_t bColor, uint8_t iNum, uint16_t x, uint16_t y, long value) {
Draw_Int(bShow, 1, fid, color, bColor, iNum, x, y, value);
}
inline void Draw_Signed_Int(uint8_t iNum, long value) {
Draw_Int(false, 1, fontid, textcolor, backcolor, iNum, cursor.x, cursor.y, value);
MoveBy(iNum * fontWidth(fontid), 0);
}
inline void Draw_Signed_Int(uint8_t iNum, uint16_t x, uint16_t y, long value) {
Draw_Int(false, 1, fontid, 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, fontid, 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, fontid, color, bColor, iNum, x, y, value);
}
inline void Draw_Signed_Int(fontid_t fid, uint16_t color, uint16_t bColor, uint8_t iNum, uint16_t x, uint16_t y, long value) {
Draw_Int(true, 1, fid, color, bColor, iNum, x, y, value);
}
// Draw a numeric float value
// bShow: true=display background color; false=don't display background color
// signedMode: 1=signed; 0=unsigned
// fid: Font ID
// color: Character color
// bColor: Background color
// iNum: Number of digits
// fNum: Number of decimal digits
// x/y: Upper-left coordinate
// value: float value
void Draw_Float(uint8_t bShow, bool signedMode, fontid_t fid, 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
inline void Draw_Float(uint8_t bShow, fontid_t fid, uint16_t color, uint16_t bColor, uint8_t iNum, uint8_t fNum, uint16_t x, uint16_t y, float value) {
Draw_Float(bShow, 0, fid, color, bColor, iNum, fNum, x, y, value);
}
inline void Draw_Float(uint8_t iNum, uint8_t fNum, float value) {
Draw_Float(false, 0, fontid, textcolor, backcolor, iNum, fNum, cursor.x, cursor.y, value);
MoveBy((iNum + fNum + 1) * fontWidth(fontid), 0);
}
inline void Draw_Float(uint8_t iNum, uint8_t fNum, uint16_t x, uint16_t y, float value) {
Draw_Float(false, 0, fontid, textcolor, backcolor, iNum, fNum, x, y, value);
}
inline void Draw_Float(fontid_t fid, uint8_t iNum, uint8_t fNum, uint16_t x, uint16_t y, float value) {
Draw_Float(false, 0, fid, 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) {
Draw_Float(true, 0, fontid, color, bColor, iNum, fNum, x, y, value);
}
inline void Draw_Float(fontid_t fid, uint16_t color, uint16_t bColor, uint8_t iNum, uint8_t fNum, uint16_t x, uint16_t y, float value) {
Draw_Float(true, 0, fid, color, bColor, iNum, fNum, x, y, value);
}
// Draw a signed floating point number
inline void Draw_Signed_Float(uint8_t bShow, fontid_t fid, uint16_t color, uint16_t bColor, uint8_t iNum, uint8_t fNum, uint16_t x, uint16_t y, float value) {
Draw_Float(bShow, 1, fid, color, bColor, iNum, fNum, x, y, value);
}
inline void Draw_Signed_Float(uint8_t iNum, uint8_t fNum, float value) {
Draw_Float(false, 1, fontid, textcolor, backcolor, iNum, fNum, cursor.x, cursor.y, value);
MoveBy((iNum + fNum + 1) * fontWidth(fontid), 0);
}
inline void Draw_Signed_Float(uint8_t iNum, uint8_t fNum, uint16_t x, uint16_t y, float value) {
Draw_Float(false, 1, fontid, textcolor, backcolor, iNum, fNum, x, y, value);
}
inline void Draw_Signed_Float(fontid_t fid, uint8_t iNum, uint8_t fNum, uint16_t x, uint16_t y, float value) {
Draw_Float(false, 1, fid, 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) {
Draw_Float(true, 1, fontid, color, bColor, iNum, fNum, x, y, value);
}
inline void Draw_Signed_Float(fontid_t fid, uint16_t color, uint16_t bColor, uint8_t iNum, uint8_t fNum, uint16_t x, uint16_t y, float value) {
Draw_Float(true, 1, fid, color, bColor, iNum, fNum, x, y, value);
}
// 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); }
// Draw a string at cursor position
// color: Character color
// *string: The string
// rlimit: For draw less chars than string length use rlimit
void Draw_String(const char * const string, uint16_t rlimit = 0xFFFF);
void Draw_String(uint16_t color, const char * const string, uint16_t rlimit = 0xFFFF);
inline void Draw_String(FSTR_P string, uint16_t rlimit = 0xFFFF) {
Draw_String(FTOP(string), rlimit);
}
inline void Draw_String(uint16_t color, FSTR_P string, uint16_t rlimit = 0xFFFF) {
Draw_String(color, FTOP(string), rlimit);
}
// Draw a string
// fid: Font ID
// color: Character color
// bColor: Background color
// x/y: Upper-left coordinate of the string
// *string: The string
inline void Draw_String(uint16_t x, uint16_t y, const char * const string) {
DWIN_Draw_String(false, fontid, textcolor, backcolor, x, y, string);
}
inline void Draw_String(uint16_t x, uint16_t y, FSTR_P title) {
DWIN_Draw_String(false, fontid, textcolor, backcolor, x, y, FTOP(title));
}
inline void Draw_String(uint16_t color, uint16_t x, uint16_t y, const char * const string) {
DWIN_Draw_String(false, fontid, color, backcolor, x, y, string);
}
inline void Draw_String(uint16_t color, uint16_t x, uint16_t y, FSTR_P title) {
DWIN_Draw_String(false, fontid, color, backcolor, x, y, title);
}
inline void Draw_String(uint16_t color, uint16_t bgcolor, uint16_t x, uint16_t y, const char * const string) {
DWIN_Draw_String(true, fontid, color, bgcolor, x, y, string);
}
inline void Draw_String(uint16_t color, uint16_t bgcolor, uint16_t x, uint16_t y, FSTR_P title) {
DWIN_Draw_String(true, fontid, color, bgcolor, x, y, title);
}
inline void Draw_String(fontid_t fid, uint16_t color, uint16_t bgcolor, uint16_t x, uint16_t y, const char * const string) {
DWIN_Draw_String(true, fid, color, bgcolor, x, y, string);
}
inline void Draw_String(fontid_t fid, uint16_t color, uint16_t bgcolor, uint16_t x, uint16_t y, FSTR_P title) {
DWIN_Draw_String(true, fid, color, bgcolor, x, y, title);
}
// Draw a centered string using DWIN_WIDTH
// bShow: true=display background color; false=don't display background color
// fid: Font ID
// color: Character color
// bColor: Background color
// y: Upper coordinate of the string
// *string: The string
void Draw_CenteredString(bool bShow, fontid_t fid, uint16_t color, uint16_t bColor, uint16_t x1, uint16_t x2, uint16_t y, const char * const string);
inline void Draw_CenteredString(bool bShow, fontid_t fid, uint16_t color, uint16_t bColor, uint16_t y, const char * const string) {
Draw_CenteredString(bShow, fid, color, bColor, 0, DWIN_WIDTH, y, string);
}
inline void Draw_CenteredString(bool bShow, fontid_t fid, uint16_t color, uint16_t bColor, uint16_t y, FSTR_P string) {
Draw_CenteredString(bShow, fid, color, bColor, y, FTOP(string));
}
inline void Draw_CenteredString(uint16_t color, uint16_t bcolor, uint16_t y, const char * const string) {
Draw_CenteredString(true, fontid, color, bcolor, y, string);
}
inline void Draw_CenteredString(fontid_t fid, uint16_t color, uint16_t y, const char * const string) {
Draw_CenteredString(false, fid, color, backcolor, y, string);
}
inline void Draw_CenteredString(fontid_t fid, uint16_t color, uint16_t y, FSTR_P title) {
Draw_CenteredString(false, fid, color, backcolor, y, title);
}
inline void Draw_CenteredString(uint16_t color, uint16_t y, const char * const string) {
Draw_CenteredString(false, fontid, color, backcolor, y, string);
}
inline void Draw_CenteredString(uint16_t color, uint16_t y, FSTR_P title) {
Draw_CenteredString(false, fontid, color, backcolor, y, title);
}
inline void Draw_CenteredString(uint16_t y, const char * const string) {
Draw_CenteredString(false, fontid, textcolor, backcolor, y, string);
}
inline void Draw_CenteredString(uint16_t y, FSTR_P title) {
Draw_CenteredString(false, fontid, textcolor, backcolor, y, title);
}
// Draw a box
// mode: 0=frame, 1=fill, 2=XOR fill
// color: Rectangle color
// frame: Box coordinates and size
inline void Draw_Box(uint8_t mode, uint16_t color, frame_rect_t frame) {
DWIN_Draw_Box(mode, color, frame.x, frame.y, frame.w, frame.h);
}
// Draw a circle
// Color: circle color
// x: abscissa of the center of the circle
// y: ordinate of the center of the circle
// r: circle radius
void Draw_Circle(uint16_t color, uint16_t x,uint16_t y,uint8_t r);
inline void Draw_Circle(uint16_t color, uint8_t r) {
Draw_Circle(color, cursor.x, cursor.y, r);
}
// Draw a checkbox
// Color: frame color
// bColor: Background color
// x/y: Upper-left point
// checked : 0 : unchecked, 1 : checked
void Draw_Checkbox(uint16_t color, uint16_t bcolor, uint16_t x, uint16_t y, bool checked);
inline void Draw_Checkbox(uint16_t x, uint16_t y, bool checked=false) {
Draw_Checkbox(textcolor, backcolor, x, y, checked);
}
// Color Interpolator
// val : Interpolator minv..maxv
// minv : Minimum value
// maxv : Maximum value
// color1 : Start color
// color2 : End color
uint16_t ColorInt(int16_t val, int16_t minv, int16_t maxv, uint16_t color1, uint16_t color2);
// ------------------------- Buttons ------------------------------//
void Draw_Button(uint16_t color, uint16_t bcolor, uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2, const char * const caption);
inline void Draw_Button(uint16_t color, uint16_t bcolor, uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2, FSTR_P caption) {
Draw_Button(color, bcolor, x1, y1, x2, y2, FTOP(caption));
}
inline void Draw_Button(FSTR_P caption, uint16_t x, uint16_t y) {
Draw_Button(textcolor, buttoncolor, x, y, x + 99, y + 37, caption);
}
void Draw_Button(uint8_t id, uint16_t x, uint16_t y);
// -------------------------- Extra -------------------------------//
// Draw a circle filled with color
// bcolor: fill color
// x: abscissa of the center of the circle
// y: ordinate of the center of the circle
// r: circle radius
void Draw_FillCircle(uint16_t bcolor, uint16_t x,uint16_t y,uint8_t r);
inline void Draw_FillCircle(uint16_t bcolor, uint8_t r) {
Draw_FillCircle(bcolor, cursor.x, cursor.y, r);
}
// Color Interpolator through Red->Yellow->Green->Blue
// val : Interpolator minv..maxv
// minv : Minimum value
// maxv : Maximum value
uint16_t RainbowInt(int16_t val, int16_t minv, int16_t maxv);
// Write buffer data to the SRAM
// addr: SRAM start address 0x0000-0x7FFF
// length: Bytes to write
// data: address of the buffer with data
inline void WriteToSRAM(uint16_t addr, uint16_t length, uint8_t *data) {
DWIN_WriteToMem(0x5A, addr, length, data);
}
// Write buffer data to the Flash
// addr: Flash start address 0x0000-0x3FFF
// length: Bytes to write
// data: address of the buffer with data
inline void WriteToFlash(uint16_t addr, uint16_t length, uint8_t *data) {
DWIN_WriteToMem(0xA5, addr, length, data);
}
// Clear by filling the area with background color
// Area (0, TITLE_HEIGHT, DWIN_WIDTH, STATUS_Y - 1)
void ClearMainArea();
};

View File

@@ -0,0 +1,113 @@
/**
* Marlin 3D Printer Firmware
* Copyright (c) 2021 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
*
* Based on Sprinter and grbl.
* Copyright (c) 2011 Camiel Gubbels / Erik van der Zalm
*
* 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/>.
*
*/
/**
* DWIN Endstops diagnostic page for PRO UI
* Author: Miguel A. Risco-Castillo (MRISCOC)
* Version: 1.2.2
* Date: 2022/02/24
*/
#include "../../../inc/MarlinConfigPre.h"
#if ENABLED(DWIN_LCD_PROUI)
#include "dwin_defines.h"
#if HAS_ESDIAG
#include "endstop_diag.h"
#include "../../../core/types.h"
#include "../../marlinui.h"
#include "dwin_lcd.h"
#include "dwinui.h"
#include "dwin_popup.h"
#include "dwin.h"
#if HAS_FILAMENT_SENSOR
#include "../../../feature/runout.h"
#endif
#if HAS_BED_PROBE
#include "../../../module/probe.h"
#endif
ESDiagClass ESDiag;
void draw_es_label(FSTR_P const flabel=nullptr) {
DWINUI::cursor.x = 40;
if (flabel) DWINUI::Draw_String(F(flabel));
DWINUI::Draw_String(F(": "));
DWINUI::MoveBy(0, 25);
}
void draw_es_state(const bool is_hit) {
const uint8_t LM = 130;
DWINUI::cursor.x = LM;
DWIN_Draw_Rectangle(1, HMI_data.PopupBg_color, LM, DWINUI::cursor.y, LM + 100, DWINUI::cursor.y + 20);
is_hit ? DWINUI::Draw_String(RGB(31,31,16), F(STR_ENDSTOP_HIT)) : DWINUI::Draw_String(RGB(16,63,16), F(STR_ENDSTOP_OPEN));
DWINUI::MoveBy(0, 25);
}
void ESDiagClass::Draw() {
Title.ShowCaption(F("End-stops Diagnostic"));
DWINUI::ClearMainArea();
Draw_Popup_Bkgd();
DWINUI::Draw_Button(BTN_Continue, 86, 250);
DWINUI::cursor.y = 80;
#define ES_LABEL(S) draw_es_label(F(STR_##S))
#if HAS_X_MIN
ES_LABEL(X_MIN);
#endif
#if HAS_Y_MIN
ES_LABEL(Y_MIN);
#endif
#if HAS_Z_MIN
ES_LABEL(Z_MIN);
#endif
#if HAS_FILAMENT_SENSOR
draw_es_label(F(STR_FILAMENT));
#endif
Update();
}
void ESDiagClass::Update() {
DWINUI::cursor.y = 80;
#define ES_REPORT(S) draw_es_state(READ(S##_PIN) != S##_ENDSTOP_INVERTING)
#if HAS_X_MIN
ES_REPORT(X_MIN);
#endif
#if HAS_Y_MIN
ES_REPORT(Y_MIN);
#endif
#if HAS_Z_MIN
ES_REPORT(Z_MIN);
#endif
#if HAS_FILAMENT_SENSOR
draw_es_state(READ(FIL_RUNOUT1_PIN) != FIL_RUNOUT1_STATE);
#endif
DWIN_UpdateLCD();
}
#endif // HAS_ESDIAG
#endif // DWIN_LCD_PROUI

View File

@@ -0,0 +1,37 @@
/**
* Marlin 3D Printer Firmware
* Copyright (c) 2021 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
*
* Based on Sprinter and grbl.
* Copyright (c) 2011 Camiel Gubbels / Erik van der Zalm
*
* 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
/**
* DWIN End Stops diagnostic page for PRO UI
* Author: Miguel A. Risco-Castillo (MRISCOC)
* Version: 1.2.3
* Date: 2022/02/24
*/
class ESDiagClass {
public:
void Draw();
void Update();
};
extern ESDiagClass ESDiag;

View File

@@ -0,0 +1,258 @@
/**
* Marlin 3D Printer Firmware
* Copyright (c) 2022 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
*
* Based on Sprinter and grbl.
* Copyright (c) 2011 Camiel Gubbels / Erik van der Zalm
*
* 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/>.
*
*/
/**
* DWIN g-code thumbnail preview
* Author: Miguel A. Risco-Castillo
* version: 2.1
* Date: 2021/06/19
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser 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 Lesser General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*
* For commercial applications additional licenses can be requested
*/
#include "../../../inc/MarlinConfigPre.h"
#if ENABLED(DWIN_LCD_PROUI)
#include "dwin_defines.h"
#if HAS_GCODE_PREVIEW
#include "../../../core/types.h"
#include "../../marlinui.h"
#include "../../../sd/cardreader.h"
#include "../../../MarlinCore.h" // for wait_for_user
#include "dwin_lcd.h"
#include "dwinui.h"
#include "dwin.h"
#include "dwin_popup.h"
#include "base64.hpp"
#include "gcode_preview.h"
typedef struct {
char name[13] = ""; //8.3 + null
uint32_t thumbstart = 0;
int thumbsize = 0;
int thumbheight = 0;
int thumbwidth = 0;
uint8_t *thumbdata = nullptr;
float time = 0;
float filament = 0;
float layer = 0;
float width = 0;
float height = 0;
float length = 0;
void setname(const char * const fn);
void clear();
} fileprop_t;
fileprop_t fileprop;
void fileprop_t::setname(const char * const fn) {
const uint8_t len = _MIN(sizeof(name) - 1, strlen(fn));
memcpy(&name[0], fn, len);
name[len] = '\0';
}
void fileprop_t::clear() {
fileprop.name[0] = '\0';
fileprop.thumbstart = 0;
fileprop.thumbsize = 0;
fileprop.thumbheight = 0;
fileprop.thumbwidth = 0;
fileprop.thumbdata = nullptr;
fileprop.time = 0;
fileprop.filament = 0;
fileprop.layer = 0;
fileprop.height = 0;
fileprop.width = 0;
fileprop.length = 0;
}
void Get_Value(char *buf, const char * const key, float &value) {
char num[10] = "";
char * posptr = 0;
uint8_t i = 0;
if (!!value) return;
posptr = strstr(buf, key);
if (posptr != nullptr) {
while (i < sizeof(num)) {
char c = posptr[0];
if (!ISEOL(c) && (c != 0)) {
if ((c > 47 && c < 58) || (c == '.')) num[i++] = c;
posptr++;
}
else {
num[i] = '\0';
value = atof(num);
return;
}
}
}
}
bool Has_Preview() {
const char * tbstart = "; thumbnail begin 230x180";
char * posptr = 0;
uint8_t nbyte = 1;
uint32_t indx = 0;
char buf[256];
float tmp = 0;
fileprop.clear();
fileprop.setname(card.filename);
card.openFileRead(fileprop.name);
while ((nbyte > 0) && (indx < 4 * sizeof(buf)) && !fileprop.thumbstart) {
nbyte = card.read(buf, sizeof(buf) - 1);
if (nbyte > 0) {
buf[nbyte] = '\0';
Get_Value(buf, ";TIME:", fileprop.time);
Get_Value(buf, ";Filament used:", fileprop.filament);
Get_Value(buf, ";Layer height:", fileprop.layer);
Get_Value(buf, ";MINX:", tmp);
Get_Value(buf, ";MAXX:", fileprop.width);
fileprop.width -= tmp;
tmp = 0;
Get_Value(buf, ";MINY:", tmp);
Get_Value(buf, ";MAXY:", fileprop.length);
fileprop.length -= tmp;
tmp = 0;
Get_Value(buf, ";MINZ:", tmp);
Get_Value(buf, ";MAXZ:", fileprop.height);
fileprop.height -= tmp;
posptr = strstr(buf, tbstart);
if (posptr != NULL) {
fileprop.thumbstart = indx + (posptr - &buf[0]);
}
else {
indx += _MAX(10, nbyte - (signed)strlen(tbstart));
card.setIndex(indx);
}
}
}
if (!fileprop.thumbstart) {
card.closefile();
LCD_MESSAGE_F("Thumbnail not found");
return 0;
}
// Get the size of the thumbnail
card.setIndex(fileprop.thumbstart + strlen(tbstart));
for (uint8_t i = 0; i < 16; i++) {
char c = card.get();
if (!ISEOL(c)) {
buf[i] = c;
}
else {
buf[i] = 0;
break;
}
}
fileprop.thumbsize = atoi(buf);
// Exit if there isn't a thumbnail
if (!fileprop.thumbsize) {
card.closefile();
LCD_MESSAGE_F("Invalid Thumbnail Size");
return 0;
}
uint16_t readed = 0;
uint8_t buf64[fileprop.thumbsize];
fileprop.thumbdata = new uint8_t[3 + 3 * (fileprop.thumbsize / 4)]; // Reserve space for the JPEG thumbnail
while (readed < fileprop.thumbsize) {
uint8_t c = card.get();
if (!ISEOL(c) && (c != ';') && (c != ' ')) {
buf64[readed] = c;
readed++;
}
}
card.closefile();
buf64[readed] = 0;
fileprop.thumbsize = decode_base64(buf64, fileprop.thumbdata); card.closefile();
DWINUI::WriteToSRAM(0x00, fileprop.thumbsize, fileprop.thumbdata);
delete[] fileprop.thumbdata;
return true;
}
void Preview_DrawFromSD() {
if (Has_Preview()) {
char buf[46];
char str_1[6] = "";
char str_2[6] = "";
char str_3[6] = "";
DWIN_Draw_Rectangle(1, HMI_data.Background_Color, 0, 0, DWIN_WIDTH, STATUS_Y - 1);
if (fileprop.time) {
sprintf_P(buf, PSTR("Estimated time: %i:%02i"), (uint16_t)fileprop.time / 3600, ((uint16_t)fileprop.time % 3600) / 60);
DWINUI::Draw_String(20, 10, buf);
}
if (fileprop.filament) {
sprintf_P(buf, PSTR("Filament used: %s m"), dtostrf(fileprop.filament, 1, 2, str_1));
DWINUI::Draw_String(20, 30, buf);
}
if (fileprop.layer) {
sprintf_P(buf, PSTR("Layer height: %s mm"), dtostrf(fileprop.layer, 1, 2, str_1));
DWINUI::Draw_String(20, 50, buf);
}
if (fileprop.width) {
sprintf_P(buf, PSTR("Volume: %sx%sx%s mm"), dtostrf(fileprop.width, 1, 1, str_1), dtostrf(fileprop.length, 1, 1, str_2), dtostrf(fileprop.height, 1, 1, str_3));
DWINUI::Draw_String(20, 70, buf);
}
DWINUI::Draw_Button(BTN_Print, 26, 290);
DWINUI::Draw_Button(BTN_Cancel, 146, 290);
DWIN_ICON_Show(0, 0, 1, 21, 90, 0x00);
Draw_Select_Highlight(true, 290);
DWIN_UpdateLCD();
}
else {
HMI_flag.select_flag = 1;
wait_for_user = false;
}
}
bool Preview_Valid() {
return !!fileprop.thumbstart;
}
void Preview_Reset() {
fileprop.thumbsize = 0;
}
#endif // HAS_GCODE_PREVIEW
#endif // DWIN_LCD_PROUI

View File

@@ -1,8 +1,8 @@
/**
* DWIN Mesh Viewer
* DWIN g-code thumbnail preview
* Author: Miguel A. Risco-Castillo
* version: 2.5
* Date: 2021/09/27
* version: 2.1
* Date: 2021/06/19
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as
@@ -17,12 +17,11 @@
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*
* For commercial applications additional licenses can be requested
*/
#pragma once
class MeshViewerClass {
public:
void Draw();
};
extern MeshViewerClass MeshViewer;
void Preview_DrawFromSD();
bool Preview_Valid();
void Preview_Reset();

View File

@@ -21,18 +21,20 @@
*/
/**
* DWIN UI Enhanced implementation
* Author: Miguel A. Risco-Castillo
* Version: 3.6.3
* Date: 2021/09/08
* Lock screen implementation for PRO UI
* Author: Miguel A. Risco-Castillo (MRISCOC)
* Version: 2.2.0
* Date: 2022/04/11
*/
#include "../../../inc/MarlinConfigPre.h"
#if ENABLED(DWIN_CREALITY_LCD_ENHANCED)
#if ENABLED(DWIN_LCD_PROUI)
#include "dwin_defines.h"
#if HAS_LOCKSCREEN
#include "../../../core/types.h"
#include "dwin_lcd.h"
#include "dwinui.h"
#include "dwin.h"
#include "lockscreen.h"
@@ -41,6 +43,7 @@ LockScreenClass lockScreen;
uint8_t LockScreenClass::lock_pos = 0;
bool LockScreenClass::unlocked = false;
uint8_t LockScreenClass::rprocess = 0;
void LockScreenClass::init() {
lock_pos = 0;
@@ -49,11 +52,11 @@ void LockScreenClass::init() {
}
void LockScreenClass::draw() {
Title.SetCaption(PSTR("Lock Screen"));
DWINUI::ClearMenuArea();
Title.SetCaption(GET_TEXT_F(MSG_LOCKSCREEN));
DWINUI::ClearMainArea();
DWINUI::Draw_Icon(ICON_LOGO, 71, 120); // CREALITY logo
DWINUI::Draw_CenteredString(Color_White, 180, F("Printer is Locked,"));
DWINUI::Draw_CenteredString(Color_White, 200, F("Scroll to unlock."));
DWINUI::Draw_CenteredString(Color_White, 180, GET_TEXT_F(MSG_LOCKSCREEN_LOCKED));
DWINUI::Draw_CenteredString(Color_White, 200, GET_TEXT_F(MSG_LOCKSCREEN_UNLOCK));
DWINUI::Draw_CenteredString(Color_White, 240, F("-> | <-"));
DWIN_Draw_Box(1, HMI_data.Barfill_Color, 0, 260, DWIN_WIDTH, 20);
DWIN_Draw_VLine(Color_Yellow, lock_pos * DWIN_WIDTH / 255, 260, 20);
@@ -72,4 +75,6 @@ void LockScreenClass::onEncoder(EncoderState encoder_diffState) {
DWIN_UpdateLCD();
}
#endif // DWIN_CREALITY_LCD_ENHANCED
#endif // HAS_LOCKSCREEN
#endif // DWIN_LCD_PROUI

View File

@@ -22,10 +22,10 @@
#pragma once
/**
* DWIN UI Enhanced implementation
* Author: Miguel A. Risco-Castillo
* Version: 3.6.3
* Date: 2021/09/08
* Lock screen implementation for PRO UI
* Author: Miguel A. Risco-Castillo (MRISCOC)
* Version: 2.2.0
* Date: 2022/04/11
*/
#include "../common/encoder.h"
@@ -36,10 +36,11 @@ private:
static bool unlocked;
static uint8_t lock_pos;
public:
static uint8_t rprocess;
static void init();
static void onEncoder(EncoderState encoder_diffState);
static void draw();
static inline bool isUnlocked() { return unlocked; }
static bool isUnlocked() { return unlocked; }
};
extern LockScreenClass lockScreen;

View File

@@ -0,0 +1,566 @@
/**
* Marlin 3D Printer Firmware
* Copyright (c) 2022 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
*
* Based on Sprinter and grbl.
* Copyright (c) 2011 Camiel Gubbels / Erik van der Zalm
*
* 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/>.
*
*/
/**
* Menu functions for ProUI
* Author: Miguel A. Risco-Castillo
* Version: 1.5.1
* Date: 2022/05/23
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser 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 Lesser General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*
*/
#include "../../../inc/MarlinConfigPre.h"
#if ENABLED(DWIN_LCD_PROUI)
#include "../common/encoder.h"
#include "dwin_lcd.h"
#include "dwinui.h"
#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 =================================================
void Draw_Title(TitleClass* title) {
DWIN_Draw_Rectangle(1, HMI_data.TitleBg_color, 0, 0, DWIN_WIDTH - 1, TITLE_HEIGHT - 1);
if (title->frameid)
DWIN_Frame_AreaCopy(title->frameid, title->frame.left, title->frame.top, title->frame.right, title->frame.bottom, 14, (TITLE_HEIGHT - (title->frame.bottom - title->frame.top)) / 2 - 1);
else
DWIN_Draw_String(false, DWIN_FONT_HEAD, HMI_data.TitleTxt_color, HMI_data.TitleBg_color, 14, (TITLE_HEIGHT - DWINUI::fontHeight(DWIN_FONT_HEAD)) / 2 - 1, title->caption);
}
void Draw_Menu(MenuClass* menu) {
DWINUI::SetColors(HMI_data.Text_Color, HMI_data.Background_Color, HMI_data.StatusBg_Color);
DWIN_Draw_Rectangle(1, DWINUI::backcolor, 0, TITLE_HEIGHT, DWIN_WIDTH - 1, STATUS_Y - 1);
}
void Draw_Menu_Cursor(const int8_t line) {
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) {
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*/) {
if (icon) DWINUI::Draw_Icon(icon, ICOX, MBASE(line) - 3);
if (label) DWINUI::Draw_String(LBLX, MBASE(line) - 1, (char*)label);
if (more) DWINUI::Draw_Icon(ICON_More, VALX + 16, MBASE(line) - 3);
DWIN_Draw_HLine(HMI_data.SplitLine_Color, 16, MYPOS(line + 1), 240);
}
void Draw_Chkb_Line(const uint8_t line, const bool 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*/) {
DWINUI::Draw_Signed_Int(HMI_data.Text_Color, bcolor, iNum , VALX, MBASE(line) - 1, value);
}
void onDrawMenuItem(MenuItemClass* menuitem, int8_t line) {
if (menuitem->icon) DWINUI::Draw_Icon(menuitem->icon, ICOX, MBASE(line) - 3);
if (menuitem->frameid)
DWIN_Frame_AreaCopy(menuitem->frameid, menuitem->frame.left, menuitem->frame.top, menuitem->frame.right, menuitem->frame.bottom, LBLX, MBASE(line));
else if (menuitem->caption)
DWINUI::Draw_String(LBLX, MBASE(line) - 1, menuitem->caption);
DWIN_Draw_HLine(HMI_data.SplitLine_Color, 16, MYPOS(line + 1), 240);
}
void onDrawSubMenu(MenuItemClass* menuitem, int8_t line) {
onDrawMenuItem(menuitem, line);
DWINUI::Draw_Icon(ICON_More, VALX + 16, MBASE(line) - 3);
}
void onDrawIntMenu(MenuItemClass* menuitem, int8_t line, int32_t value) {
onDrawMenuItem(menuitem, line);
Draw_Menu_IntValue(HMI_data.Background_Color, line, 4, value);
}
void onDrawPIntMenu(MenuItemClass* menuitem, int8_t line) {
const int16_t value = *(int16_t*)static_cast<MenuItemPtrClass*>(menuitem)->value;
onDrawIntMenu(menuitem, line, value);
}
void onDrawPInt8Menu(MenuItemClass* menuitem, int8_t line) {
const uint8_t value = *(uint8_t*)static_cast<MenuItemPtrClass*>(menuitem)->value;
onDrawIntMenu(menuitem, line, value);
}
void onDrawPInt32Menu(MenuItemClass* menuitem, int8_t line) {
const uint32_t value = *(uint32_t*)static_cast<MenuItemPtrClass*>(menuitem)->value;
onDrawIntMenu(menuitem, line, value);
}
void onDrawFloatMenu(MenuItemClass* menuitem, int8_t line, uint8_t dp, const float value) {
onDrawMenuItem(menuitem, line);
DWINUI::Draw_Signed_Float(HMI_data.Text_Color, HMI_data.Background_Color, 3, dp, VALX - dp * DWINUI::fontWidth(DWIN_FONT_MENU), MBASE(line), value);
}
void onDrawPFloatMenu(MenuItemClass* menuitem, int8_t line) {
const float value = *(float*)static_cast<MenuItemPtrClass*>(menuitem)->value;
const int8_t dp = UNITFDIGITS;
onDrawFloatMenu(menuitem, line, dp, value);
}
void onDrawPFloat2Menu(MenuItemClass* menuitem, int8_t line) {
const float value = *(float*)static_cast<MenuItemPtrClass*>(menuitem)->value;
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);
}
void DrawItemEdit() {
switch (checkkey) {
case SetIntNoDraw: if (MenuData.LiveUpdate) MenuData.LiveUpdate(); break;
case SetInt:
case SetPInt: DWINUI::Draw_Signed_Int(HMI_data.Text_Color, HMI_data.Selected_Color, 4 , VALX, MBASE(CurrentMenu->line()) - 1, MenuData.Value); break;
case SetFloat:
case SetPFloat: DWINUI::Draw_Signed_Float(HMI_data.Text_Color, HMI_data.Selected_Color, 3, MenuData.dp, VALX - MenuData.dp * DWINUI::fontWidth(DWIN_FONT_MENU), MBASE(CurrentMenu->line()), MenuData.Value / POW(10, MenuData.dp)); break;
default: break;
}
}
//-----------------------------------------------------------------------------
// On click functions
//-----------------------------------------------------------------------------
// Generic onclick event without draw
// process: process id HMI destiny
// lo: low limit
// hi: high limit
// dp: decimal places, 0 for integers
// val: value / scaled value
// LiveUpdate: live update function when the encoder changes
// Apply: update function when the encoder is pressed
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*/) {
checkkey = process;
MenuData.MinValue = lo;
MenuData.MaxValue = hi;
MenuData.dp = dp;
MenuData.Apply = Apply;
MenuData.LiveUpdate = LiveUpdate;
MenuData.Value = constrain(val, lo, hi);
EncoderRate.enabled = true;
}
// Generic onclick event for integer values
// process: process id HMI destiny
// lo: scaled low limit
// hi: scaled high limit
// val: value
// LiveUpdate: live update function when the encoder changes
// Apply: update function when the encoder is pressed
void SetValueOnClick(uint8_t process, const int32_t lo, const int32_t hi, const int32_t val, void (*Apply)() /*= nullptr*/, void (*LiveUpdate)() /*= nullptr*/) {
SetOnClick(process, lo, hi, 0, val, Apply, LiveUpdate);
Draw_Menu_IntValue(HMI_data.Selected_Color, CurrentMenu->line(), 4, MenuData.Value);
}
// Generic onclick event for float values
// process: process id HMI destiny
// lo: scaled low limit
// hi: scaled high limit
// val: value
// LiveUpdate: live update function when the encoder changes
// Apply: update function when the encoder is pressed
void SetValueOnClick(uint8_t process, const float lo, const float hi, uint8_t dp, const float val, void (*Apply)() /*= nullptr*/, void (*LiveUpdate)() /*= nullptr*/) {
const int32_t value = round(val * POW(10, dp));
SetOnClick(process, lo * POW(10, dp), hi * POW(10, dp), dp, value, Apply, LiveUpdate);
DWINUI::Draw_Signed_Float(HMI_data.Text_Color, HMI_data.Selected_Color, 3, dp, VALX - dp * DWINUI::fontWidth(DWIN_FONT_MENU), MBASE(CurrentMenu->line()), val);
}
// Generic onclick event for integer values
// lo: scaled low limit
// hi: scaled high limit
// val: value
// LiveUpdate: live update function when the encoder changes
// Apply: update function when the encoder is pressed
void SetIntOnClick(const int32_t lo, const int32_t hi, const int32_t val, void (*Apply)() /*= nullptr*/, void (*LiveUpdate)() /*= nullptr*/) {
SetValueOnClick(SetInt, lo, hi, val, Apply, LiveUpdate);
}
// Generic onclick event for set pointer to 16 bit uinteger values
// lo: low limit
// hi: high limit
// LiveUpdate: live update function when the encoder changes
// Apply: update function when the encoder is pressed
void SetPIntOnClick(const int32_t lo, const int32_t hi, void (*Apply)() /*= nullptr*/, void (*LiveUpdate)() /*= nullptr*/) {
MenuData.P_Int = (int16_t*)static_cast<MenuItemPtrClass*>(CurrentMenu->SelectedItem())->value;
const int32_t value = *MenuData.P_Int;
SetValueOnClick(SetPInt, lo, hi, value, Apply, LiveUpdate);
}
// Generic onclick event for float values
// process: process id HMI destiny
// lo: low limit
// hi: high limit
// dp: decimal places
// val: value
void SetFloatOnClick(const float lo, const float hi, uint8_t dp, const float val, void (*Apply)() /*= nullptr*/, void (*LiveUpdate)() /*= nullptr*/) {
SetValueOnClick(SetFloat, lo, hi, dp, val, Apply, LiveUpdate);
}
// Generic onclick event for set pointer to float values
// lo: low limit
// hi: high limit
// LiveUpdate: live update function when the encoder changes
// Apply: update function when the encoder is pressed
void SetPFloatOnClick(const float lo, const float hi, uint8_t dp, void (*Apply)() /*= nullptr*/, void (*LiveUpdate)() /*= nullptr*/) {
MenuData.P_Float = (float*)static_cast<MenuItemPtrClass*>(CurrentMenu->SelectedItem())->value;
SetValueOnClick(SetPFloat, lo, hi, dp, *MenuData.P_Float, Apply, LiveUpdate);
}
// HMI Control functions ======================================================
// Generic menu control using the encoder
void HMI_Menu() {
EncoderState encoder_diffState = get_encoder_state();
if (encoder_diffState == ENCODER_DIFF_NO) return;
if (CurrentMenu) {
if (encoder_diffState == ENCODER_DIFF_ENTER)
CurrentMenu->onClick();
else
CurrentMenu->onScroll(encoder_diffState == ENCODER_DIFF_CW);
}
}
// Get an integer value using the encoder without draw anything
// lo: low limit
// hi: high limit
// Return value:
// 0 : no change
// 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)) {
EncoderRate.enabled = false;
checkkey = Menu;
return 2;
}
LIMIT(MenuData.Value, lo, hi);
}
return int8_t(cval != MenuData.Value);
}
// Get an integer value using the encoder
// lo: low limit
// hi: high limit
// Return value:
// 0 : no change
// 1 : live change
// 2 : apply change
int8_t HMI_GetInt(const int32_t lo, const int32_t hi) {
EncoderState encoder_diffState = Encoder_ReceiveAnalyze();
if (encoder_diffState != ENCODER_DIFF_NO) {
if (Apply_Encoder(encoder_diffState, MenuData.Value)) {
EncoderRate.enabled = false;
DWINUI::Draw_Signed_Int(HMI_data.Text_Color, HMI_data.Background_Color, 4 , VALX, MBASE(CurrentMenu->line()) - 1, MenuData.Value);
checkkey = Menu;
return 2;
}
LIMIT(MenuData.Value, lo, hi);
DrawItemEdit();
return 1;
}
return 0;
}
// Set an integer using the encoder
void HMI_SetInt() {
int8_t val = HMI_GetInt(MenuData.MinValue, MenuData.MaxValue);
switch (val) {
case 0: return; break;
case 1: if (MenuData.LiveUpdate) MenuData.LiveUpdate(); break;
case 2: if (MenuData.Apply) MenuData.Apply(); break;
}
}
// Set an integer without drawing
void HMI_SetIntNoDraw() {
int8_t val = HMI_GetIntNoDraw(MenuData.MinValue, MenuData.MaxValue);
switch (val) {
case 0: return; break;
case 1: if (MenuData.LiveUpdate) MenuData.LiveUpdate(); break;
case 2: if (MenuData.Apply) MenuData.Apply(); break;
}
}
// Set an integer pointer variable using the encoder
void HMI_SetPInt() {
int8_t val = HMI_GetInt(MenuData.MinValue, MenuData.MaxValue);
switch (val) {
case 0: return;
case 1: if (MenuData.LiveUpdate) MenuData.LiveUpdate(); break;
case 2: *MenuData.P_Int = MenuData.Value; if (MenuData.Apply) MenuData.Apply(); break;
}
}
// Get a scaled float value using the encoder
// dp: decimal places
// lo: scaled low limit
// hi: scaled high limit
// Return value:
// 0 : no change
// 1 : live change
// 2 : apply change
int8_t HMI_GetFloat(uint8_t dp, int32_t lo, int32_t hi) {
EncoderState encoder_diffState = Encoder_ReceiveAnalyze();
if (encoder_diffState != ENCODER_DIFF_NO) {
if (Apply_Encoder(encoder_diffState, MenuData.Value)) {
EncoderRate.enabled = false;
DWINUI::Draw_Signed_Float(HMI_data.Text_Color, HMI_data.Background_Color, 3, dp, VALX - dp * DWINUI::fontWidth(DWIN_FONT_MENU), MBASE(CurrentMenu->line()), MenuData.Value / POW(10, dp));
checkkey = Menu;
return 2;
}
LIMIT(MenuData.Value, lo, hi);
DrawItemEdit();
return 1;
}
return 0;
}
// Set a scaled float using the encoder
void HMI_SetFloat() {
const int8_t val = HMI_GetFloat(MenuData.dp, MenuData.MinValue, MenuData.MaxValue);
switch (val) {
case 0: return;
case 1: if (MenuData.LiveUpdate) MenuData.LiveUpdate(); break;
case 2: if (MenuData.Apply) MenuData.Apply(); break;
}
}
// Set a scaled float pointer variable using the encoder
void HMI_SetPFloat() {
const int8_t val = HMI_GetFloat(MenuData.dp, MenuData.MinValue, MenuData.MaxValue);
switch (val) {
case 0: return;
case 1: if (MenuData.LiveUpdate) MenuData.LiveUpdate(); break;
case 2: *MenuData.P_Float = MenuData.Value / POW(10, MenuData.dp); if (MenuData.Apply) MenuData.Apply(); break;
}
}
// 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 (!WITHIN(line, 0, TROWS - 1)) 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(const bool force/*=false*/) {
if (CurrentMenu && (force || checkkey == Menu)) CurrentMenu->draw();
if (force) DrawItemEdit();
}
#endif // DWIN_LCD_PROUI

View File

@@ -0,0 +1,188 @@
/**
* Marlin 3D Printer Firmware
* Copyright (c) 2022 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
*
* Based on Sprinter and grbl.
* Copyright (c) 2011 Camiel Gubbels / Erik van der Zalm
*
* 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/>.
*
*/
/**
* Menu functions for ProUI
* Author: Miguel A. Risco-Castillo
* Version: 1.5.1
* Date: 2022/05/23
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser 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 Lesser General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*
*/
#pragma once
#include "dwinui.h"
typedef struct {
int32_t MaxValue = 0; // Auxiliar max integer/scaled float value
int32_t MinValue = 0; // Auxiliar min integer/scaled float value
int8_t dp = 0; // Auxiliar decimal places
int32_t Value = 0; // Auxiliar integer / scaled float value
int16_t *P_Int = nullptr; // Auxiliar pointer to 16 bit integer variable
float *P_Float = nullptr; // Auxiliar pointer to float variable
void (*Apply)() = nullptr; // Auxiliar apply function
void (*LiveUpdate)() = nullptr; // Auxiliar live update function
} 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);
void Erase_Menu_Cursor(const int8_t line);
void Draw_Menu_Line(const uint8_t line, const uint8_t icon=0, const char * const label=nullptr, bool more=false);
void Draw_Chkb_Line(const uint8_t line, const bool checked);
void Draw_Menu_IntValue(uint16_t bcolor, const uint8_t line, uint8_t iNum, const int32_t value=0);
void onDrawMenuItem(MenuItemClass* menuitem, int8_t line);
void onDrawSubMenu(MenuItemClass* menuitem, int8_t line);
void onDrawIntMenu(MenuItemClass* menuitem, int8_t line, int32_t value);
void onDrawPIntMenu(MenuItemClass* menuitem, int8_t line);
void onDrawPInt8Menu(MenuItemClass* menuitem, int8_t line);
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);
void SetIntOnClick(const int32_t lo, const int32_t hi, const int32_t val, void (*Apply)() = nullptr, void (*LiveUpdate)() = nullptr);
void SetPIntOnClick(const int32_t lo, const int32_t hi, void (*Apply)() = nullptr, void (*LiveUpdate)() = nullptr);
void SetFloatOnClick(const float lo, const float hi, uint8_t dp, const float val, void (*Apply)() = nullptr, void (*LiveUpdate)() = nullptr);
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(const bool force=false);
// 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

@@ -0,0 +1,144 @@
/**
* Marlin 3D Printer Firmware
* Copyright (c) 2021 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
*
* Based on Sprinter and grbl.
* Copyright (c) 2011 Camiel Gubbels / Erik van der Zalm
*
* 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/>.
*
*/
/**
* Mesh Viewer for PRO UI
* Author: Miguel A. Risco-Castillo (MRISCOC)
* version: 3.14.1
* Date: 2022/04/11
*/
#include "../../../inc/MarlinConfigPre.h"
#if BOTH(DWIN_LCD_PROUI, HAS_MESH)
#include "../../../core/types.h"
#include "../../marlinui.h"
#include "dwin_lcd.h"
#include "dwinui.h"
#include "dwin.h"
#include "dwin_popup.h"
#include "../../../feature/bedlevel/bedlevel.h"
#include "meshviewer.h"
#if ENABLED(AUTO_BED_LEVELING_UBL)
#include "bedlevel_tools.h"
#endif
MeshViewerClass MeshViewer;
void MeshViewerClass::DrawMesh(bed_mesh_t zval, const uint8_t sizex, const uint8_t sizey) {
const int8_t mx = 25, my = 25; // Margins
const int16_t stx = (DWIN_WIDTH - 2 * mx) / (sizex - 1), // Steps
sty = (DWIN_WIDTH - 2 * my) / (sizey - 1);
const int8_t rmax = _MIN(mx - 2, stx / 2);
const int8_t rmin = 7;
int16_t zmesh[sizex][sizey];
#define px(xp) (mx + (xp) * stx)
#define py(yp) (30 + DWIN_WIDTH - my - (yp) * sty)
#define rm(z) ((z - minz) * (rmax - rmin) / _MAX(1, (maxz - minz)) + rmin)
#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;
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;
NOLESS(maxz, v);
NOMORE(minz, v);
}
max = (float)maxz / 100;
min = (float)minz / 100;
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);
LOOP_S_L_N(y, 1, sizey - 1) DrawMeshHLine(y);
LOOP_L_N(y, sizey) {
hal.watchdog_refresh();
LOOP_L_N(x, sizex) {
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) {
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;
switch (zmesh[x][y]) {
case -999 ... -100:
DWINUI::Draw_Signed_Float(font6x12, 1, 1, px(x) - 18, py(y) - 6, zval[x][y]);
break;
case -99 ... -1:
sprintf_P(str_1, PSTR("-.%02i"), -zmesh[x][y]);
break;
case 0:
DWIN_Draw_String(false, font6x12, DWINUI::textcolor, DWINUI::backcolor, px(x) - 4, py(y) - 6, "0");
break;
case 1 ... 99:
sprintf_P(str_1, PSTR(".%02i"), zmesh[x][y]);
break;
case 100 ... 999:
DWINUI::Draw_Signed_Float(font6x12, 1, 1, px(x) - 18, py(y) - 6, zval[x][y]);
break;
}
if (str_1[0])
DWIN_Draw_String(false, font6x12, DWINUI::textcolor, DWINUI::backcolor, px(x) - 12, py(y) - 6, str_1);
}
}
}
}
void MeshViewerClass::Draw(bool withsave /*= false*/) {
Title.ShowCaption(GET_TEXT_F(MSG_MESH_VIEWER));
#if USE_UBL_VIEWER
DWINUI::ClearMainArea();
BedLevelTools.viewer_print_value = true;
BedLevelTools.Draw_Bed_Mesh(-1, 1, 8, 10 + TITLE_HEIGHT);
#else
DrawMesh(bedlevel.z_values, 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);
Draw_Select_Highlight(HMI_flag.select_flag, 305);
}
else
DWINUI::Draw_Button(BTN_Continue, 86, 305);
#if USE_UBL_VIEWER
BedLevelTools.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) 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

@@ -0,0 +1,40 @@
/**
* Marlin 3D Printer Firmware
* Copyright (c) 2021 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
*
* Based on Sprinter and grbl.
* Copyright (c) 2011 Camiel Gubbels / Erik van der Zalm
*
* 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
/**
* Mesh Viewer for PRO UI
* Author: Miguel A. Risco-Castillo (MRISCOC)
* version: 3.14.1
* Date: 2022/04/11
*/
class MeshViewerClass {
public:
float max, min;
void Draw(bool withsave = false);
void DrawMesh(bed_mesh_t zval, const uint8_t sizex, const uint8_t sizey);
};
extern MeshViewerClass MeshViewer;
void Goto_MeshViewer();

View File

@@ -0,0 +1,99 @@
/**
* Marlin 3D Printer Firmware
* Copyright (c) 2022 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
*
* Based on Sprinter and grbl.
* Copyright (c) 2011 Camiel Gubbels / Erik van der Zalm
*
* 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/>.
*
*/
/**
* DWIN Single var plot
* Author: Miguel A. Risco-Castillo
* Version: 2.0
* Date: 2022/01/31
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser 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 Lesser General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*
* For commercial applications additional licenses can be requested
*/
#include "../../../inc/MarlinConfigPre.h"
#ifdef DWIN_LCD_PROUI
#include "dwin_defines.h"
#if HAS_PIDPLOT
#include "plot.h"
#include "../../../core/types.h"
#include "../../marlinui.h"
#include "dwin_lcd.h"
#include "dwinui.h"
#include "dwin.h"
#define Plot_Bg_Color RGB( 1, 12, 8)
PlotClass Plot;
uint16_t grphpoints, r, x2, y2 = 0;
frame_rect_t grphframe = {0};
float scale = 0;
void PlotClass::Draw(const frame_rect_t frame, const float max, const float ref) {
grphframe = frame;
grphpoints = 0;
scale = frame.h / max;
x2 = frame.x + frame.w - 1;
y2 = frame.y + frame.h - 1;
r = round((y2) - ref * scale);
DWINUI::Draw_Box(1, Plot_Bg_Color, frame);
for (uint8_t i = 1; i < 4; i++) if (i * 50 < frame.w) DWIN_Draw_VLine(Line_Color, i * 50 + frame.x, frame.y, frame.h);
DWINUI::Draw_Box(0, Color_White, DWINUI::ExtendFrame(frame, 1));
DWIN_Draw_HLine(Color_Red, frame.x, r, frame.w);
}
void PlotClass::Update(const float value) {
if (!scale) return;
uint16_t y = round((y2) - value * scale);
if (grphpoints < grphframe.w) {
DWIN_Draw_Point(Color_Yellow, 1, 1, grphpoints + grphframe.x, y);
}
else {
DWIN_Frame_AreaMove(1, 0, 1, Plot_Bg_Color, grphframe.x, grphframe.y, x2, y2);
if ((grphpoints % 50) == 0) DWIN_Draw_VLine(Line_Color, x2 - 1, grphframe.y + 1, grphframe.h - 2);
DWIN_Draw_Point(Color_Red, 1, 1, x2 - 1, r);
DWIN_Draw_Point(Color_Yellow, 1, 1, x2 - 1, y);
}
grphpoints++;
}
#endif // HAS_PIDPLOT
#endif // DWIN_LCD_PROUI

View File

@@ -0,0 +1,54 @@
/**
* Marlin 3D Printer Firmware
* Copyright (c) 2022 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
*
* Based on Sprinter and grbl.
* Copyright (c) 2011 Camiel Gubbels / Erik van der Zalm
*
* 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/>.
*
*/
/**
* DWIN Single var plot
* Author: Miguel A. Risco-Castillo
* Version: 1.0
* Date: 2022/01/30
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser 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 Lesser General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*
* For commercial applications additional licenses can be requested
*/
#pragma once
#include "dwinui.h"
class PlotClass {
public:
void Draw(frame_rect_t frame, float max, float ref = 0);
void Update(float value);
};
extern PlotClass Plot;

View File

@@ -0,0 +1,82 @@
/**
* Marlin 3D Printer Firmware
* Copyright (c) 2021 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
*
* Based on Sprinter and grbl.
* Copyright (c) 2011 Camiel Gubbels / Erik van der Zalm
*
* 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/>.
*
*/
/**
* Print Stats page for PRO UI
* Author: Miguel A. Risco-Castillo (MRISCOC)
* Version: 1.3.0
* Date: 2022/02/24
*/
#include "../../../inc/MarlinConfigPre.h"
#if BOTH(DWIN_LCD_PROUI, PRINTCOUNTER)
#include "printstats.h"
#include "../../../core/types.h"
#include "../../../MarlinCore.h"
#include "../../marlinui.h"
#include "../../../module/printcounter.h"
#include "dwin_lcd.h"
#include "dwinui.h"
#include "dwin_popup.h"
#include "dwin.h"
PrintStatsClass PrintStats;
void PrintStatsClass::Draw() {
char buf[50] = "";
char str[30] = "";
constexpr int8_t MRG = 30;
Title.ShowCaption(GET_TEXT_F(MSG_INFO_STATS_MENU));
DWINUI::ClearMainArea();
Draw_Popup_Bkgd();
DWINUI::Draw_Button(BTN_Continue, 86, 250);
printStatistics ps = print_job_timer.getStats();
sprintf_P(buf, PSTR(S_FMT ": %i"), GET_TEXT(MSG_INFO_PRINT_COUNT), ps.totalPrints);
DWINUI::Draw_String(MRG, 80, buf);
sprintf_P(buf, PSTR(S_FMT ": %i"), GET_TEXT(MSG_INFO_COMPLETED_PRINTS), ps.finishedPrints);
DWINUI::Draw_String(MRG, 100, buf);
duration_t(print_job_timer.getStats().printTime).toDigital(str, true);
sprintf_P(buf, PSTR(S_FMT ": %s"), GET_TEXT(MSG_INFO_PRINT_TIME), str);
DWINUI::Draw_String(MRG, 120, buf);
duration_t(print_job_timer.getStats().longestPrint).toDigital(str, true);
sprintf_P(buf, PSTR(S_FMT ": %s"), GET_TEXT(MSG_INFO_PRINT_LONGEST), str);
DWINUI::Draw_String(MRG, 140, buf);
sprintf_P(buf, PSTR(S_FMT ": %s m"), GET_TEXT(MSG_INFO_PRINT_FILAMENT), dtostrf(ps.filamentUsed / 1000, 1, 2, str));
DWINUI::Draw_String(MRG, 160, buf);
}
void PrintStatsClass::Reset() {
print_job_timer.initStats();
DONE_BUZZ(true);
}
void Goto_PrintStats() {
PrintStats.Draw();
HMI_SaveProcessID(WaitResponse);
}
#endif // DWIN_LCD_PROUI && PRINTCOUNTER

View File

@@ -0,0 +1,39 @@
/**
* Marlin 3D Printer Firmware
* Copyright (c) 2021 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
*
* Based on Sprinter and grbl.
* Copyright (c) 2011 Camiel Gubbels / Erik van der Zalm
*
* 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
/**
* Print Stats page for PRO UI
* Author: Miguel A. Risco-Castillo (MRISCOC)
* Version: 1.3.0
* Date: 2022/02/24
*/
class PrintStatsClass {
public:
static void Draw();
static void Reset();
};
extern PrintStatsClass PrintStats;
void Goto_PrintStats();