Skip to content

Commit 85e8d1f

Browse files
mriscocthinkyhead
authored andcommitted
🚸 ProUI G-code preview, PID plot (#24282)
1 parent 679f460 commit 85e8d1f

File tree

10 files changed

+749
-32
lines changed

10 files changed

+749
-32
lines changed

Marlin/src/lcd/e3v2/proui/base64.hpp

Lines changed: 208 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,208 @@
1+
/**
2+
* Base64 encoder/decoder for arduino repo
3+
* Uses common web conventions - '+' for 62, '/' for 63, '=' for padding.
4+
* Note that invalid base64 characters are interpreted as padding.
5+
* Author: Densaugeo
6+
* Maintainer: Densaugeo
7+
* Version: 1.2.1.1
8+
* Changed unsigned int to uint16_t for use in the professional Ender 3V2/S1 firmware
9+
* Url: https://www.arduino.cc/reference/en/libraries/base64/
10+
*/
11+
12+
#ifndef BASE64_H_INCLUDED
13+
#define BASE64_H_INCLUDED
14+
15+
/* binary_to_base64:
16+
* Description:
17+
* Converts a single byte from a binary value to the corresponding base64 character
18+
* Parameters:
19+
* v - Byte to convert
20+
* Returns:
21+
* ascii code of base64 character. If byte is >= 64, then there is not corresponding base64 character
22+
* and 255 is returned
23+
*/
24+
unsigned char binary_to_base64(unsigned char v);
25+
26+
/* base64_to_binary:
27+
* Description:
28+
* Converts a single byte from a base64 character to the corresponding binary value
29+
* Parameters:
30+
* c - Base64 character (as ascii code)
31+
* Returns:
32+
* 6-bit binary value
33+
*/
34+
unsigned char base64_to_binary(unsigned char c);
35+
36+
/* encode_base64_length:
37+
* Description:
38+
* Calculates length of base64 string needed for a given number of binary bytes
39+
* Parameters:
40+
* input_length - Amount of binary data in bytes
41+
* Returns:
42+
* Number of base64 characters needed to encode input_length bytes of binary data
43+
*/
44+
uint16_t encode_base64_length(uint16_t input_length);
45+
46+
/* decode_base64_length:
47+
* Description:
48+
* Calculates number of bytes of binary data in a base64 string
49+
* Variant that does not use input_length no longer used within library, retained for API compatibility
50+
* Parameters:
51+
* input - Base64-encoded null-terminated string
52+
* input_length (optional) - Number of bytes to read from input pointer
53+
* Returns:
54+
* Number of bytes of binary data in input
55+
*/
56+
uint16_t decode_base64_length(unsigned char input[]);
57+
uint16_t decode_base64_length(unsigned char input[], uint16_t input_length);
58+
59+
/* encode_base64:
60+
* Description:
61+
* Converts an array of bytes to a base64 null-terminated string
62+
* Parameters:
63+
* input - Pointer to input data
64+
* input_length - Number of bytes to read from input pointer
65+
* output - Pointer to output string. Null terminator will be added automatically
66+
* Returns:
67+
* Length of encoded string in bytes (not including null terminator)
68+
*/
69+
uint16_t encode_base64(unsigned char input[], uint16_t input_length, unsigned char output[]);
70+
71+
/* decode_base64:
72+
* Description:
73+
* Converts a base64 null-terminated string to an array of bytes
74+
* Parameters:
75+
* input - Pointer to input string
76+
* input_length (optional) - Number of bytes to read from input pointer
77+
* output - Pointer to output array
78+
* Returns:
79+
* Number of bytes in the decoded binary
80+
*/
81+
uint16_t decode_base64(unsigned char input[], unsigned char output[]);
82+
uint16_t decode_base64(unsigned char input[], uint16_t input_length, unsigned char output[]);
83+
84+
unsigned char binary_to_base64(unsigned char v) {
85+
// Capital letters - 'A' is ascii 65 and base64 0
86+
if (v < 26) return v + 'A';
87+
88+
// Lowercase letters - 'a' is ascii 97 and base64 26
89+
if (v < 52) return v + 71;
90+
91+
// Digits - '0' is ascii 48 and base64 52
92+
if (v < 62) return v - 4;
93+
94+
// '+' is ascii 43 and base64 62
95+
if (v == 62) return '+';
96+
97+
// '/' is ascii 47 and base64 63
98+
if (v == 63) return '/';
99+
100+
return 64;
101+
}
102+
103+
unsigned char base64_to_binary(unsigned char c) {
104+
// Capital letters - 'A' is ascii 65 and base64 0
105+
if ('A' <= c && c <= 'Z') return c - 'A';
106+
107+
// Lowercase letters - 'a' is ascii 97 and base64 26
108+
if ('a' <= c && c <= 'z') return c - 71;
109+
110+
// Digits - '0' is ascii 48 and base64 52
111+
if ('0' <= c && c <= '9') return c + 4;
112+
113+
// '+' is ascii 43 and base64 62
114+
if (c == '+') return 62;
115+
116+
// '/' is ascii 47 and base64 63
117+
if (c == '/') return 63;
118+
119+
return 255;
120+
}
121+
122+
uint16_t encode_base64_length(uint16_t input_length) {
123+
return (input_length + 2)/3*4;
124+
}
125+
126+
uint16_t decode_base64_length(unsigned char input[]) {
127+
return decode_base64_length(input, -1);
128+
}
129+
130+
uint16_t decode_base64_length(unsigned char input[], uint16_t input_length) {
131+
unsigned char *start = input;
132+
133+
while (base64_to_binary(input[0]) < 64 && (unsigned char)(input - start) < input_length) {
134+
++input;
135+
}
136+
137+
input_length = input - start;
138+
return input_length/4*3 + (input_length % 4 ? input_length % 4 - 1 : 0);
139+
}
140+
141+
uint16_t encode_base64(unsigned char input[], uint16_t input_length, unsigned char output[]) {
142+
uint16_t full_sets = input_length/3;
143+
144+
// While there are still full sets of 24 bits...
145+
for (uint16_t i = 0; i < full_sets; ++i) {
146+
output[0] = binary_to_base64( input[0] >> 2);
147+
output[1] = binary_to_base64((input[0] & 0x03) << 4 | input[1] >> 4);
148+
output[2] = binary_to_base64((input[1] & 0x0F) << 2 | input[2] >> 6);
149+
output[3] = binary_to_base64( input[2] & 0x3F);
150+
151+
input += 3;
152+
output += 4;
153+
}
154+
155+
switch(input_length % 3) {
156+
case 0:
157+
output[0] = '\0';
158+
break;
159+
case 1:
160+
output[0] = binary_to_base64( input[0] >> 2);
161+
output[1] = binary_to_base64((input[0] & 0x03) << 4);
162+
output[2] = '=';
163+
output[3] = '=';
164+
output[4] = '\0';
165+
break;
166+
case 2:
167+
output[0] = binary_to_base64( input[0] >> 2);
168+
output[1] = binary_to_base64((input[0] & 0x03) << 4 | input[1] >> 4);
169+
output[2] = binary_to_base64((input[1] & 0x0F) << 2);
170+
output[3] = '=';
171+
output[4] = '\0';
172+
break;
173+
}
174+
175+
return encode_base64_length(input_length);
176+
}
177+
178+
uint16_t decode_base64(unsigned char input[], unsigned char output[]) {
179+
return decode_base64(input, -1, output);
180+
}
181+
182+
uint16_t decode_base64(unsigned char input[], uint16_t input_length, unsigned char output[]) {
183+
uint16_t output_length = decode_base64_length(input, input_length);
184+
185+
// While there are still full sets of 24 bits...
186+
for (uint16_t i = 2; i < output_length; i += 3) {
187+
output[0] = base64_to_binary(input[0]) << 2 | base64_to_binary(input[1]) >> 4;
188+
output[1] = base64_to_binary(input[1]) << 4 | base64_to_binary(input[2]) >> 2;
189+
output[2] = base64_to_binary(input[2]) << 6 | base64_to_binary(input[3]);
190+
191+
input += 4;
192+
output += 3;
193+
}
194+
195+
switch(output_length % 3) {
196+
case 1:
197+
output[0] = base64_to_binary(input[0]) << 2 | base64_to_binary(input[1]) >> 4;
198+
break;
199+
case 2:
200+
output[0] = base64_to_binary(input[0]) << 2 | base64_to_binary(input[1]) >> 4;
201+
output[1] = base64_to_binary(input[1]) << 4 | base64_to_binary(input[2]) >> 2;
202+
break;
203+
}
204+
205+
return output_length;
206+
}
207+
208+
#endif // ifndef

Marlin/src/lcd/e3v2/proui/dwin.cpp

Lines changed: 86 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -129,6 +129,14 @@
129129
#include "endstop_diag.h"
130130
#endif
131131

132+
#if HAS_PIDPLOT
133+
#include "plot.h"
134+
#endif
135+
136+
#if HAS_GCODE_PREVIEW
137+
#include "gcode_preview.h"
138+
#endif
139+
132140
#if HAS_MESH
133141
#include "meshviewer.h"
134142
#endif
@@ -705,13 +713,19 @@ void Draw_PrintDone() {
705713
Title.ShowCaption(GET_TEXT_F(MSG_PRINT_DONE));
706714
DWINUI::ClearMainArea();
707715
DWIN_Print_Header(nullptr);
708-
Draw_Print_ProgressBar();
709-
Draw_Print_Labels();
710-
DWINUI::Draw_Icon(ICON_PrintTime, 15, 173);
711-
DWINUI::Draw_Icon(ICON_RemainTime, 150, 171);
712-
Draw_Print_ProgressElapsed();
713-
Draw_Print_ProgressRemain();
714-
DWINUI::Draw_Button(BTN_Continue, 86, 273);
716+
if (sdprint && TERN0(HAS_GCODE_PREVIEW, Preview_Valid())) {
717+
DWIN_ICON_Show(0, 0, 1, 21, 100, 0x00);
718+
DWINUI::Draw_Button(BTN_Continue, 86, 300);
719+
}
720+
else {
721+
Draw_Print_ProgressBar();
722+
Draw_Print_Labels();
723+
DWINUI::Draw_Icon(ICON_PrintTime, 15, 173);
724+
DWINUI::Draw_Icon(ICON_RemainTime, 150, 171);
725+
Draw_Print_ProgressElapsed();
726+
Draw_Print_ProgressRemain();
727+
DWINUI::Draw_Button(BTN_Continue, 86, 273);
728+
}
715729
}
716730

717731
void Goto_PrintDone() {
@@ -1409,6 +1423,9 @@ void EachMomentUpdate() {
14091423
#if HAS_ESDIAG
14101424
if (checkkey == ESDiagProcess) ESDiag.Update();
14111425
#endif
1426+
#if HAS_PIDPLOT
1427+
if (checkkey == PidProcess) Plot.Update((HMI_value.pidresult == PID_EXTR_START) ? thermalManager.wholeDegHotend(0) : thermalManager.wholeDegBed());
1428+
#endif
14121429
}
14131430

14141431
#if HAS_STATUS_MESSAGE_TIMEOUT
@@ -1635,15 +1652,49 @@ void DWIN_LevelingDone() {
16351652
#endif
16361653

16371654
// PID process
1655+
1656+
#if HAS_PIDPLOT
1657+
void DWIN_Draw_PIDPopup() {
1658+
frame_rect_t gfrm = {40, 180, DWIN_WIDTH - 80, 120};
1659+
DWINUI::ClearMainArea();
1660+
Draw_Popup_Bkgd();
1661+
DWINUI::Draw_CenteredString(HMI_data.PopupTxt_Color, 100, GET_TEXT_F(MSG_PID_AUTOTUNE));
1662+
DWINUI::Draw_String(HMI_data.PopupTxt_Color, gfrm.x, gfrm.y - DWINUI::fontHeight() - 4, F("PID target: Celsius"));
1663+
switch (HMI_value.pidresult) {
1664+
case PID_EXTR_START:
1665+
DWINUI::Draw_CenteredString(HMI_data.PopupTxt_Color, 120, F("for Nozzle is running."));
1666+
Plot.Draw(gfrm, thermalManager.hotend_maxtemp[0], HMI_data.HotendPidT);
1667+
DWINUI::Draw_Int(HMI_data.PopupTxt_Color, 3, gfrm.x + 90, gfrm.y - DWINUI::fontHeight() - 4, HMI_data.HotendPidT);
1668+
break;
1669+
case PID_BED_START:
1670+
DWINUI::Draw_CenteredString(HMI_data.PopupTxt_Color, 120, F("for BED is running."));
1671+
Plot.Draw(gfrm, BED_MAXTEMP, HMI_data.BedPidT);
1672+
DWINUI::Draw_Int(HMI_data.PopupTxt_Color, 3, gfrm.x + 90, gfrm.y - DWINUI::fontHeight() - 4, HMI_data.BedPidT);
1673+
break;
1674+
default:
1675+
break;
1676+
}
1677+
}
1678+
#endif
1679+
16381680
void DWIN_PidTuning(pidresult_t result) {
1681+
HMI_value.pidresult = result;
16391682
switch (result) {
16401683
case PID_BED_START:
1641-
HMI_SaveProcessID(NothingToDo);
1642-
DWIN_Draw_Popup(ICON_TempTooHigh, GET_TEXT_F(MSG_PID_AUTOTUNE), F("for BED is running."));
1684+
HMI_SaveProcessID(PidProcess);
1685+
#if HAS_PIDPLOT
1686+
DWIN_Draw_PIDPopup();
1687+
#else
1688+
DWIN_Draw_Popup(ICON_TempTooHigh, GET_TEXT_F(MSG_PID_AUTOTUNE), F("for BED is running."));
1689+
#endif
16431690
break;
16441691
case PID_EXTR_START:
1645-
HMI_SaveProcessID(NothingToDo);
1646-
DWIN_Draw_Popup(ICON_TempTooHigh, GET_TEXT_F(MSG_PID_AUTOTUNE), F("for Nozzle is running."));
1692+
HMI_SaveProcessID(PidProcess);
1693+
#if HAS_PIDPLOT
1694+
DWIN_Draw_PIDPopup();
1695+
#else
1696+
DWIN_Draw_Popup(ICON_TempTooHigh, GET_TEXT_F(MSG_PID_AUTOTUNE), F("for Nozzle is running."));
1697+
#endif
16471698
break;
16481699
case PID_BAD_EXTRUDER_NUM:
16491700
checkkey = last_checkkey;
@@ -1960,10 +2011,30 @@ void HMI_LockScreen() {
19602011
}
19612012

19622013

1963-
void Goto_ConfirmToPrint() {
1964-
card.openAndPrintFile(card.filename);
1965-
DWIN_Print_Started(true);
1966-
}
2014+
#if HAS_GCODE_PREVIEW
2015+
2016+
void onClick_ConfirmToPrint() {
2017+
if (HMI_flag.select_flag) { // Confirm
2018+
card.openAndPrintFile(card.filename);
2019+
return DWIN_Print_Started(true);
2020+
}
2021+
else { // Cancel
2022+
DWIN_ResetStatusLine();
2023+
checkkey = SelectFile;
2024+
return Draw_Print_File_Menu();
2025+
}
2026+
}
2027+
2028+
void Goto_ConfirmToPrint() {
2029+
Goto_Popup(Preview_DrawFromSD, onClick_ConfirmToPrint);
2030+
}
2031+
2032+
#else
2033+
void Goto_ConfirmToPrint() {
2034+
card.openAndPrintFile(card.filename);
2035+
DWIN_Print_Started(true);
2036+
}
2037+
#endif
19672038

19682039
#if HAS_ESDIAG
19692040
void Draw_EndStopDiag() {

Marlin/src/lcd/e3v2/proui/dwin_defines.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,8 @@
3535
#include <stddef.h>
3636

3737
#define HAS_ESDIAG 1
38+
#define HAS_PIDPLOT 1
39+
#define HAS_GCODE_PREVIEW 1
3840
#if defined(__STM32F1__) || defined(STM32F1)
3941
#define DASH_REDRAW 1
4042
#endif

0 commit comments

Comments
 (0)