Browse Source

✨ MarlinUI for Ender 3 v2 DWIN LCD (#22594)

Co-Authored-By: Taylor Talkington <taylor.talkington@gmail.com>
Scott Lahteine 2 years ago
parent
commit
7d416bd055
35 changed files with 56500 additions and 41 deletions
  1. 6
    0
      Marlin/Configuration.h
  2. 13
    11
      Marlin/Configuration_adv.h
  3. 2
    2
      Marlin/src/feature/pause.cpp
  4. 5
    2
      Marlin/src/inc/Conditionals_LCD.h
  5. 5
    1
      Marlin/src/inc/Conditionals_post.h
  6. 4
    3
      Marlin/src/inc/SanityCheck.h
  7. 470
    0
      Marlin/src/lcd/e3v2/marlinui/dwin_lcd.cpp
  8. 302
    0
      Marlin/src/lcd/e3v2/marlinui/dwin_lcd.h
  9. 180
    0
      Marlin/src/lcd/e3v2/marlinui/dwin_string.cpp
  10. 1007
    0
      Marlin/src/lcd/e3v2/marlinui/dwin_string.h
  11. 193
    0
      Marlin/src/lcd/e3v2/marlinui/lcdprint_dwin.cpp
  12. 30
    0
      Marlin/src/lcd/e3v2/marlinui/lcdprint_dwin.h
  13. 146
    0
      Marlin/src/lcd/e3v2/marlinui/marlinui_dwin.h
  14. 595
    0
      Marlin/src/lcd/e3v2/marlinui/ui_common.cpp
  15. 391
    0
      Marlin/src/lcd/e3v2/marlinui/ui_status_480x272.cpp
  16. 1
    1
      Marlin/src/lcd/lcdprint.cpp
  17. 19
    2
      Marlin/src/lcd/lcdprint.h
  18. 8
    0
      Marlin/src/lcd/marlinui.cpp
  19. 15
    11
      Marlin/src/lcd/marlinui.h
  20. 2
    0
      Marlin/src/lcd/menu/menu.cpp
  21. 1
    1
      Marlin/src/lcd/menu/menu.h
  22. 2
    2
      Marlin/src/pins/stm32f1/pins_CREALITY_V4.h
  23. 64
    0
      buildroot/share/fonts/buildhzk.py
  24. 4104
    0
      buildroot/share/fonts/marlin-10x20.bdf
  25. 4558
    0
      buildroot/share/fonts/marlin-12x24.bdf
  26. 5078
    0
      buildroot/share/fonts/marlin-14x28.bdf
  27. 5492
    0
      buildroot/share/fonts/marlin-16x32.bdf
  28. 6458
    0
      buildroot/share/fonts/marlin-20x40.bdf
  29. 6462
    0
      buildroot/share/fonts/marlin-24x48.bdf
  30. 7311
    0
      buildroot/share/fonts/marlin-28x56.bdf
  31. 9870
    0
      buildroot/share/fonts/marlin-32x64.bdf
  32. 3701
    0
      buildroot/share/fonts/marlin-8x16.bdf
  33. 2
    4
      buildroot/tests/STM32F103RET6_creality
  34. 1
    0
      ini/features.ini
  35. 2
    1
      platformio.ini

+ 6
- 0
Marlin/Configuration.h View File

@@ -2747,6 +2747,12 @@
2747 2747
 //#define DWIN_CREALITY_LCD
2748 2748
 
2749 2749
 //
2750
+// MarlinUI for Creality's DWIN display (and others)
2751
+//
2752
+//#define DWIN_MARLINUI_PORTRAIT
2753
+//#define DWIN_MARLINUI_LANDSCAPE
2754
+
2755
+//
2750 2756
 // Touch Screen Settings
2751 2757
 //
2752 2758
 //#define TOUCH_SCREEN

+ 13
- 11
Marlin/Configuration_adv.h View File

@@ -1306,7 +1306,7 @@
1306 1306
 
1307 1307
 // LCD Print Progress options
1308 1308
 #if EITHER(SDSUPPORT, LCD_SET_PROGRESS_MANUALLY)
1309
-  #if ANY(HAS_MARLINUI_U8GLIB, EXTENSIBLE_UI, HAS_MARLINUI_HD44780, IS_TFTGLCD_PANEL)
1309
+  #if ANY(HAS_MARLINUI_U8GLIB, EXTENSIBLE_UI, HAS_MARLINUI_HD44780, IS_TFTGLCD_PANEL, IS_DWIN_MARLINUI)
1310 1310
     //#define SHOW_REMAINING_TIME         // Display estimated time to completion
1311 1311
     #if ENABLED(SHOW_REMAINING_TIME)
1312 1312
       //#define USE_M73_REMAINING_TIME    // Use remaining time from M73 command instead of estimation
@@ -1579,16 +1579,10 @@
1579 1579
  * printing performance versus fast display updates.
1580 1580
  */
1581 1581
 #if HAS_MARLINUI_U8GLIB
1582
-  // Show SD percentage next to the progress bar
1583
-  //#define SHOW_SD_PERCENT
1584
-
1585 1582
   // Save many cycles by drawing a hollow frame or no frame on the Info Screen
1586 1583
   //#define XYZ_NO_FRAME
1587 1584
   #define XYZ_HOLLOW_FRAME
1588 1585
 
1589
-  // Enable to save many cycles by drawing a hollow frame on Menu Screens
1590
-  #define MENU_HOLLOW_FRAME
1591
-
1592 1586
   // A bigger font is available for edit items. Costs 3120 bytes of PROGMEM.
1593 1587
   // Western only. Not available for Cyrillic, Kana, Turkish, Greek, or Chinese.
1594 1588
   //#define USE_BIG_EDIT_FONT
@@ -1597,9 +1591,6 @@
1597 1591
   // Western only. Not available for Cyrillic, Kana, Turkish, Greek, or Chinese.
1598 1592
   //#define USE_SMALL_INFOFONT
1599 1593
 
1600
-  // Swap the CW/CCW indicators in the graphics overlay
1601
-  //#define OVERLAY_GFX_REVERSE
1602
-
1603 1594
   /**
1604 1595
    * ST7920-based LCDs can emulate a 16 x 4 character display using
1605 1596
    * the ST7920 character-generator for very fast screen updates.
@@ -1651,6 +1642,17 @@
1651 1642
 
1652 1643
 #endif // HAS_MARLINUI_U8GLIB
1653 1644
 
1645
+#if HAS_MARLINUI_U8GLIB || IS_DWIN_MARLINUI
1646
+  // Show SD percentage next to the progress bar
1647
+  //#define SHOW_SD_PERCENT
1648
+
1649
+  // Enable to save many cycles by drawing a hollow frame on Menu Screens
1650
+  #define MENU_HOLLOW_FRAME
1651
+
1652
+  // Swap the CW/CCW indicators in the graphics overlay
1653
+  //#define OVERLAY_GFX_REVERSE
1654
+#endif
1655
+
1654 1656
 //
1655 1657
 // Additional options for DGUS / DWIN displays
1656 1658
 //
@@ -1716,7 +1718,7 @@
1716 1718
 //
1717 1719
 // Specify additional languages for the UI. Default specified by LCD_LANGUAGE.
1718 1720
 //
1719
-#if ANY(DOGLCD, TFT_COLOR_UI, TOUCH_UI_FTDI_EVE)
1721
+#if ANY(DOGLCD, TFT_COLOR_UI, TOUCH_UI_FTDI_EVE, IS_DWIN_MARLINUI)
1720 1722
   //#define LCD_LANGUAGE_2 fr
1721 1723
   //#define LCD_LANGUAGE_3 de
1722 1724
   //#define LCD_LANGUAGE_4 es

+ 2
- 2
Marlin/src/feature/pause.cpp View File

@@ -238,8 +238,8 @@ bool load_filament(const_float_t slow_load_length/*=0*/, const_float_t fast_load
238 238
 
239 239
     if (show_lcd) ui.pause_show_message(PAUSE_MESSAGE_PURGE);
240 240
 
241
-    TERN_(EXTENSIBLE_UI, ExtUI::onUserConfirmRequired_P(PSTR("Filament Purging...")));
242
-    TERN_(HOST_PROMPT_SUPPORT, host_prompt_do(PROMPT_USER_CONTINUE, PSTR("Filament Purging..."), CONTINUE_STR));
241
+    TERN_(EXTENSIBLE_UI, ExtUI::onUserConfirmRequired_P(GET_TEXT(MSG_FILAMENT_CHANGE_PURGE)));
242
+    TERN_(HOST_PROMPT_SUPPORT, host_prompt_do(PROMPT_USER_CONTINUE, GET_TEXT(MSG_FILAMENT_CHANGE_PURGE), CONTINUE_STR));
243 243
     wait_for_user = true; // A click or M108 breaks the purge_length loop
244 244
     for (float purge_count = purge_length; purge_count > 0 && wait_for_user; --purge_count)
245 245
       unscaled_e_move(1, ADVANCED_PAUSE_PURGE_FEEDRATE);

+ 5
- 2
Marlin/src/inc/Conditionals_LCD.h View File

@@ -488,7 +488,10 @@
488 488
     #define HAS_MARLINUI_U8GLIB 1
489 489
   #elif IS_TFTGLCD_PANEL
490 490
     // Neither DOGM nor HD44780. Fully customized interface.
491
-  #elif DISABLED(HAS_GRAPHICAL_TFT)
491
+  #elif IS_DWIN_MARLINUI
492
+    // Since HAS_MARLINUI_U8GLIB refers to U8G displays
493
+    // the DWIN display can define its own flags
494
+  #elif !HAS_GRAPHICAL_TFT
492 495
     #define HAS_MARLINUI_HD44780 1
493 496
   #endif
494 497
 #endif
@@ -1087,7 +1090,7 @@
1087 1090
   #define HAS_ETHERNET 1
1088 1091
 #endif
1089 1092
 
1090
-#if ENABLED(DWIN_CREALITY_LCD)
1093
+#if EITHER(DWIN_CREALITY_LCD, IS_DWIN_MARLINUI)
1091 1094
   #define SERIAL_CATCHALL 0
1092 1095
   #ifndef LCD_SERIAL_PORT
1093 1096
     #if MB(BTT_SKR_MINI_E3_V1_0, BTT_SKR_MINI_E3_V1_2, BTT_SKR_MINI_E3_V2_0, BTT_SKR_E3_TURBO)

+ 5
- 1
Marlin/src/inc/Conditionals_post.h View File

@@ -461,7 +461,7 @@
461 461
 
462 462
 #endif
463 463
 
464
-#if ANY(HAS_GRAPHICAL_TFT, LCD_USE_DMA_FSMC, HAS_FSMC_GRAPHICAL_TFT, HAS_SPI_GRAPHICAL_TFT) || !PIN_EXISTS(SD_DETECT)
464
+#if ANY(HAS_GRAPHICAL_TFT, LCD_USE_DMA_FSMC, HAS_FSMC_GRAPHICAL_TFT, HAS_SPI_GRAPHICAL_TFT, IS_DWIN_MARLINUI) || !PIN_EXISTS(SD_DETECT)
465 465
   #define NO_LCD_REINIT 1  // Suppress LCD re-initialization
466 466
 #endif
467 467
 
@@ -3258,6 +3258,8 @@
3258 3258
   #ifndef LCD_WIDTH
3259 3259
     #if HAS_MARLINUI_U8GLIB
3260 3260
       #define LCD_WIDTH 21
3261
+    #elif IS_DWIN_MARLINUI
3262
+      // Defined by header
3261 3263
     #else
3262 3264
       #define LCD_WIDTH TERN(IS_ULTIPANEL, 20, 16)
3263 3265
     #endif
@@ -3265,6 +3267,8 @@
3265 3267
   #ifndef LCD_HEIGHT
3266 3268
     #if HAS_MARLINUI_U8GLIB
3267 3269
       #define LCD_HEIGHT 5
3270
+    #elif IS_DWIN_MARLINUI
3271
+      // Defined by header
3268 3272
     #else
3269 3273
       #define LCD_HEIGHT TERN(IS_ULTIPANEL, 4, 2)
3270 3274
     #endif

+ 4
- 3
Marlin/src/inc/SanityCheck.h View File

@@ -798,8 +798,8 @@ static_assert(Y_MAX_LENGTH >= Y_BED_SIZE, "Movement bounds (Y_MIN_POS, Y_MAX_POS
798 798
     #error "PROGRESS_MSG_EXPIRE must be greater than or equal to 0."
799 799
   #endif
800 800
 #elif ENABLED(LCD_SET_PROGRESS_MANUALLY)
801
-  #if NONE(HAS_MARLINUI_U8GLIB, HAS_GRAPHICAL_TFT, HAS_MARLINUI_HD44780, EXTENSIBLE_UI)
802
-    #error "LCD_SET_PROGRESS_MANUALLY requires LCD_PROGRESS_BAR, Character LCD, Graphical LCD, TFT, or EXTENSIBLE_UI."
801
+  #if NONE(HAS_MARLINUI_U8GLIB, HAS_GRAPHICAL_TFT, HAS_MARLINUI_HD44780, EXTENSIBLE_UI, IS_DWIN_MARLINUI)
802
+    #error "LCD_SET_PROGRESS_MANUALLY requires LCD_PROGRESS_BAR, Character LCD, Graphical LCD, TFT, EXTENSIBLE_UI, OR DWIN MarlinUI."
803 803
   #endif
804 804
 #endif
805 805
 
@@ -1721,7 +1721,7 @@ static_assert(Y_MAX_LENGTH >= Y_BED_SIZE, "Movement bounds (Y_MIN_POS, Y_MAX_POS
1721 1721
   #endif
1722 1722
 #endif
1723 1723
 
1724
-#if ENABLED(MESH_EDIT_GFX_OVERLAY) && !BOTH(AUTO_BED_LEVELING_UBL, HAS_MARLINUI_U8GLIB)
1724
+#if ENABLED(MESH_EDIT_GFX_OVERLAY) && !(ENABLED(AUTO_BED_LEVELING_UBL) && EITHER(HAS_MARLINUI_U8GLIB, IS_DWIN_MARLINUI))
1725 1725
   #error "MESH_EDIT_GFX_OVERLAY requires AUTO_BED_LEVELING_UBL and a Graphical LCD."
1726 1726
 #endif
1727 1727
 
@@ -2640,6 +2640,7 @@ static_assert(Y_MAX_LENGTH >= Y_BED_SIZE, "Movement bounds (Y_MIN_POS, Y_MAX_POS
2640 2640
   + COUNT_ENABLED(ANYCUBIC_LCD_I3MEGA, ANYCUBIC_LCD_CHIRON, ANYCUBIC_TFT35) \
2641 2641
   + COUNT_ENABLED(DGUS_LCD_UI_ORIGIN, DGUS_LCD_UI_FYSETC, DGUS_LCD_UI_HIPRECY, DGUS_LCD_UI_MKS) \
2642 2642
   + COUNT_ENABLED(ENDER2_STOCKDISPLAY, CR10_STOCKDISPLAY, DWIN_CREALITY_LCD) \
2643
+  + COUNT_ENABLED(DWIN_MARLINUI_PORTRAIT, DWIN_MARLINUI_LANDSCAPE) \
2643 2644
   + COUNT_ENABLED(FYSETC_MINI_12864_X_X, FYSETC_MINI_12864_1_2, FYSETC_MINI_12864_2_0, FYSETC_MINI_12864_2_1, FYSETC_GENERIC_12864_1_1) \
2644 2645
   + COUNT_ENABLED(LCD_SAINSMART_I2C_1602, LCD_SAINSMART_I2C_2004) \
2645 2646
   + COUNT_ENABLED(MKS_12864OLED, MKS_12864OLED_SSD1306) \

+ 470
- 0
Marlin/src/lcd/e3v2/marlinui/dwin_lcd.cpp View File

@@ -0,0 +1,470 @@
1
+/**
2
+ * Marlin 3D Printer Firmware
3
+ * Copyright (c) 2021 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
4
+ *
5
+ * Based on Sprinter and grbl.
6
+ * Copyright (c) 2011 Camiel Gubbels / Erik van der Zalm
7
+ *
8
+ * This program is free software: you can redistribute it and/or modify
9
+ * it under the terms of the GNU General Public License as published by
10
+ * the Free Software Foundation, either version 3 of the License, or
11
+ * (at your option) any later version.
12
+ *
13
+ * This program is distributed in the hope that it will be useful,
14
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
15
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16
+ * GNU General Public License for more details.
17
+ *
18
+ * You should have received a copy of the GNU General Public License
19
+ * along with this program.  If not, see <https://www.gnu.org/licenses/>.
20
+ *
21
+ */
22
+
23
+/********************************************************************************
24
+ * @file     lcd/e3v2/marlinui/dwin_lcd.cpp
25
+ * @brief    DWIN screen control functions
26
+ ********************************************************************************/
27
+
28
+#include "../../../inc/MarlinConfigPre.h"
29
+
30
+#if IS_DWIN_MARLINUI
31
+
32
+#include "../../../inc/MarlinConfig.h"
33
+
34
+#include "dwin_lcd.h"
35
+#include <string.h> // for memset
36
+
37
+//#define DEBUG_OUT 1
38
+#include "../../../core/debug_out.h"
39
+
40
+// Make sure DWIN_SendBuf is large enough to hold the largest string plus draw command and tail.
41
+// Assume the narrowest (6 pixel) font and 2-byte gb2312-encoded characters.
42
+uint8_t DWIN_SendBuf[11 + DWIN_WIDTH / 6 * 2] = { 0xAA };
43
+uint8_t DWIN_BufTail[4] = { 0xCC, 0x33, 0xC3, 0x3C };
44
+uint8_t databuf[26] = { 0 };
45
+uint8_t receivedType;
46
+
47
+int recnum = 0;
48
+
49
+inline void DWIN_Byte(size_t &i, const uint16_t bval) {
50
+  DWIN_SendBuf[++i] = bval;
51
+}
52
+
53
+inline void DWIN_Word(size_t &i, const uint16_t wval) {
54
+  DWIN_SendBuf[++i] = wval >> 8;
55
+  DWIN_SendBuf[++i] = wval & 0xFF;
56
+}
57
+
58
+inline void DWIN_Long(size_t &i, const uint32_t lval) {
59
+  DWIN_SendBuf[++i] = (lval >> 24) & 0xFF;
60
+  DWIN_SendBuf[++i] = (lval >> 16) & 0xFF;
61
+  DWIN_SendBuf[++i] = (lval >>  8) & 0xFF;
62
+  DWIN_SendBuf[++i] = lval & 0xFF;
63
+}
64
+
65
+inline void DWIN_String(size_t &i, char * const string) {
66
+  const size_t len = _MIN(sizeof(DWIN_SendBuf) - i, strlen(string));
67
+  memcpy(&DWIN_SendBuf[i+1], string, len);
68
+  i += len;
69
+}
70
+
71
+inline void DWIN_String(size_t &i, const __FlashStringHelper * string) {
72
+  if (!string) return;
73
+  const size_t len = strlen_P((PGM_P)string); // cast it to PGM_P, which is basically const char *, and measure it using the _P version of strlen.
74
+  if (len == 0) return;
75
+  memcpy(&DWIN_SendBuf[i+1], string, len);
76
+  i += len;
77
+}
78
+
79
+// Send the data in the buffer and the packet end
80
+inline void DWIN_Send(size_t &i) {
81
+  ++i;
82
+  LOOP_L_N(n, i) { LCD_SERIAL.write(DWIN_SendBuf[n]); delayMicroseconds(1); }
83
+  LOOP_L_N(n, 4) { LCD_SERIAL.write(DWIN_BufTail[n]); delayMicroseconds(1); }
84
+}
85
+
86
+/*-------------------------------------- System variable function --------------------------------------*/
87
+
88
+// Handshake (1: Success, 0: Fail)
89
+bool DWIN_Handshake(void) {
90
+  #ifndef LCD_BAUDRATE
91
+    #define LCD_BAUDRATE 115200
92
+  #endif
93
+  LCD_SERIAL.begin(LCD_BAUDRATE);
94
+  const millis_t serial_connect_timeout = millis() + 1000UL;
95
+  while (!LCD_SERIAL.connected() && PENDING(millis(), serial_connect_timeout)) { /*nada*/ }
96
+
97
+  size_t i = 0;
98
+  DWIN_Byte(i, 0x00);
99
+  DWIN_Send(i);
100
+
101
+  while (LCD_SERIAL.available() > 0 && recnum < (signed)sizeof(databuf)) {
102
+    databuf[recnum] = LCD_SERIAL.read();
103
+    // ignore the invalid data
104
+    if (databuf[0] != FHONE) { // prevent the program from running.
105
+      if (recnum > 0) {
106
+        recnum = 0;
107
+        ZERO(databuf);
108
+      }
109
+      continue;
110
+    }
111
+    delay(10);
112
+    recnum++;
113
+  }
114
+
115
+  return ( recnum >= 3
116
+        && databuf[0] == FHONE
117
+        && databuf[1] == '\0'
118
+        && databuf[2] == 'O'
119
+        && databuf[3] == 'K' );
120
+}
121
+
122
+void DWIN_Startup(void) {
123
+  DEBUG_ECHOPGM("\r\nDWIN handshake ");
124
+  delay(750);   // Delay here or init later in the boot process
125
+  const bool success = DWIN_Handshake();
126
+  if (success) DEBUG_ECHOLNPGM("ok."); else DEBUG_ECHOLNPGM("error.");
127
+  DWIN_Frame_SetDir(TERN(DWIN_MARLINUI_LANDSCAPE, 0, 1));
128
+  DWIN_Frame_Clear(Color_Bg_Black); // MarlinUI handles the bootscreen so just clear here
129
+  DWIN_UpdateLCD();
130
+}
131
+
132
+// Set the backlight luminance
133
+//  luminance: (0x00-0xFF)
134
+void DWIN_Backlight_SetLuminance(const uint8_t luminance) {
135
+  size_t i = 0;
136
+  DWIN_Byte(i, 0x30);
137
+  DWIN_Byte(i, _MAX(luminance, 0x1F));
138
+  DWIN_Send(i);
139
+}
140
+
141
+// Set screen display direction
142
+//  dir: 0=0°, 1=90°, 2=180°, 3=270°
143
+void DWIN_Frame_SetDir(uint8_t dir) {
144
+  size_t i = 0;
145
+  DWIN_Byte(i, 0x34);
146
+  DWIN_Byte(i, 0x5A);
147
+  DWIN_Byte(i, 0xA5);
148
+  DWIN_Byte(i, dir);
149
+  DWIN_Send(i);
150
+}
151
+
152
+// Update display
153
+void DWIN_UpdateLCD(void) {
154
+  size_t i = 0;
155
+  DWIN_Byte(i, 0x3D);
156
+  DWIN_Send(i);
157
+}
158
+
159
+/*---------------------------------------- Drawing functions ----------------------------------------*/
160
+
161
+// Clear screen
162
+//  color: Clear screen color
163
+void DWIN_Frame_Clear(const uint16_t color) {
164
+  size_t i = 0;
165
+  DWIN_Byte(i, 0x01);
166
+  DWIN_Word(i, color);
167
+  DWIN_Send(i);
168
+}
169
+
170
+// Draw a point
171
+//  width: point width   0x01-0x0F
172
+//  height: point height 0x01-0x0F
173
+//  x,y: upper left point
174
+void DWIN_Draw_Point(uint16_t color, uint8_t width, uint8_t height, uint16_t x, uint16_t y) {
175
+  size_t i = 0;
176
+  DWIN_Byte(i, 0x02);
177
+  DWIN_Word(i, color);
178
+  DWIN_Byte(i, width);
179
+  DWIN_Byte(i, height);
180
+  DWIN_Word(i, x);
181
+  DWIN_Word(i, y);
182
+  DWIN_Send(i);
183
+}
184
+
185
+// Draw a line
186
+//  color: Line segment color
187
+//  xStart/yStart: Start point
188
+//  xEnd/yEnd: End point
189
+void DWIN_Draw_Line(uint16_t color, uint16_t xStart, uint16_t yStart, uint16_t xEnd, uint16_t yEnd) {
190
+  size_t i = 0;
191
+  DWIN_Byte(i, 0x03);
192
+  DWIN_Word(i, color);
193
+  DWIN_Word(i, xStart);
194
+  DWIN_Word(i, yStart);
195
+  DWIN_Word(i, xEnd);
196
+  DWIN_Word(i, yEnd);
197
+  DWIN_Send(i);
198
+}
199
+
200
+// Draw a rectangle
201
+//  mode: 0=frame, 1=fill, 2=XOR fill
202
+//  color: Rectangle color
203
+//  xStart/yStart: upper left point
204
+//  xEnd/yEnd: lower right point
205
+void DWIN_Draw_Rectangle(uint8_t mode, uint16_t color,
206
+                         uint16_t xStart, uint16_t yStart, uint16_t xEnd, uint16_t yEnd) {
207
+  size_t i = 0;
208
+  DWIN_Byte(i, 0x05);
209
+  DWIN_Byte(i, mode);
210
+  DWIN_Word(i, color);
211
+  DWIN_Word(i, xStart);
212
+  DWIN_Word(i, yStart);
213
+  DWIN_Word(i, xEnd);
214
+  DWIN_Word(i, yEnd);
215
+  DWIN_Send(i);
216
+}
217
+
218
+// Move a screen area
219
+//  mode: 0, circle shift; 1, translation
220
+//  dir: 0=left, 1=right, 2=up, 3=down
221
+//  dis: Distance
222
+//  color: Fill color
223
+//  xStart/yStart: upper left point
224
+//  xEnd/yEnd: bottom right point
225
+void DWIN_Frame_AreaMove(uint8_t mode, uint8_t dir, uint16_t dis,
226
+                         uint16_t color, uint16_t xStart, uint16_t yStart, uint16_t xEnd, uint16_t yEnd) {
227
+  size_t i = 0;
228
+  DWIN_Byte(i, 0x09);
229
+  DWIN_Byte(i, (mode << 7) | dir);
230
+  DWIN_Word(i, dis);
231
+  DWIN_Word(i, color);
232
+  DWIN_Word(i, xStart);
233
+  DWIN_Word(i, yStart);
234
+  DWIN_Word(i, xEnd);
235
+  DWIN_Word(i, yEnd);
236
+  DWIN_Send(i);
237
+}
238
+
239
+/*---------------------------------------- Text related functions ----------------------------------------*/
240
+
241
+// Draw a string
242
+//  bShow: true=display background color; false=don't display background color
243
+//  size: Font size
244
+//  color: Character color
245
+//  bColor: Background color
246
+//  x/y: Upper-left coordinate of the string
247
+//  *string: The string
248
+void DWIN_Draw_String(bool bShow, uint8_t size, uint16_t color, uint16_t bColor, uint16_t x, uint16_t y, char *string) {
249
+  uint8_t widthAdjust = 0;
250
+  size_t i = 0;
251
+  DWIN_Byte(i, 0x11);
252
+  // Bit 7: widthAdjust
253
+  // Bit 6: bShow
254
+  // Bit 5-4: Unused (0)
255
+  // Bit 3-0: size
256
+  DWIN_Byte(i, (widthAdjust * 0x80) | (bShow * 0x40) | size);
257
+  DWIN_Word(i, color);
258
+  DWIN_Word(i, bColor);
259
+  DWIN_Word(i, x);
260
+  DWIN_Word(i, y);
261
+  DWIN_String(i, string);
262
+  DWIN_Send(i);
263
+}
264
+
265
+// Draw a positive integer
266
+//  bShow: true=display background color; false=don't display background color
267
+//  zeroFill: true=zero fill; false=no zero fill
268
+//  zeroMode: 1=leading 0 displayed as 0; 0=leading 0 displayed as a space
269
+//  size: Font size
270
+//  color: Character color
271
+//  bColor: Background color
272
+//  iNum: Number of digits
273
+//  x/y: Upper-left coordinate
274
+//  value: Integer value
275
+void DWIN_Draw_IntValue(uint8_t bShow, bool zeroFill, uint8_t zeroMode, uint8_t size, uint16_t color,
276
+                          uint16_t bColor, uint8_t iNum, uint16_t x, uint16_t y, uint16_t value) {
277
+  size_t i = 0;
278
+  DWIN_Byte(i, 0x14);
279
+  // Bit 7: bshow
280
+  // Bit 6: 1 = signed; 0 = unsigned number;
281
+  // Bit 5: zeroFill
282
+  // Bit 4: zeroMode
283
+  // Bit 3-0: size
284
+  DWIN_Byte(i, (bShow * 0x80) | (zeroFill * 0x20) | (zeroMode * 0x10) | size);
285
+  DWIN_Word(i, color);
286
+  DWIN_Word(i, bColor);
287
+  DWIN_Byte(i, iNum);
288
+  DWIN_Byte(i, 0); // fNum
289
+  DWIN_Word(i, x);
290
+  DWIN_Word(i, y);
291
+  #if 0
292
+    for (char count = 0; count < 8; count++) {
293
+      DWIN_Byte(i, value);
294
+      value >>= 8;
295
+      if (!(value & 0xFF)) break;
296
+    }
297
+  #else
298
+    // Write a big-endian 64 bit integer
299
+    const size_t p = i + 1;
300
+    for (char count = 8; count--;) { // 7..0
301
+      ++i;
302
+      DWIN_SendBuf[p + count] = value;
303
+      value >>= 8;
304
+    }
305
+  #endif
306
+
307
+  DWIN_Send(i);
308
+}
309
+
310
+// Draw a floating point number
311
+//  bShow: true=display background color; false=don't display background color
312
+//  zeroFill: true=zero fill; false=no zero fill
313
+//  zeroMode: 1=leading 0 displayed as 0; 0=leading 0 displayed as a space
314
+//  size: Font size
315
+//  color: Character color
316
+//  bColor: Background color
317
+//  iNum: Number of whole digits
318
+//  fNum: Number of decimal digits
319
+//  x/y: Upper-left point
320
+//  value: Float value
321
+void DWIN_Draw_FloatValue(uint8_t bShow, bool zeroFill, uint8_t zeroMode, uint8_t size, uint16_t color,
322
+                            uint16_t bColor, uint8_t iNum, uint8_t fNum, uint16_t x, uint16_t y, long value) {
323
+  //uint8_t *fvalue = (uint8_t*)&value;
324
+  size_t i = 0;
325
+  DWIN_Byte(i, 0x14);
326
+  DWIN_Byte(i, (bShow * 0x80) | (zeroFill * 0x20) | (zeroMode * 0x10) | size);
327
+  DWIN_Word(i, color);
328
+  DWIN_Word(i, bColor);
329
+  DWIN_Byte(i, iNum);
330
+  DWIN_Byte(i, fNum);
331
+  DWIN_Word(i, x);
332
+  DWIN_Word(i, y);
333
+  DWIN_Long(i, value);
334
+  /*
335
+  DWIN_Byte(i, fvalue[3]);
336
+  DWIN_Byte(i, fvalue[2]);
337
+  DWIN_Byte(i, fvalue[1]);
338
+  DWIN_Byte(i, fvalue[0]);
339
+  */
340
+  DWIN_Send(i);
341
+}
342
+
343
+/*---------------------------------------- Picture related functions ----------------------------------------*/
344
+
345
+// Draw JPG and cached in #0 virtual display area
346
+// id: Picture ID
347
+void DWIN_JPG_ShowAndCache(const uint8_t id) {
348
+  size_t i = 0;
349
+  DWIN_Word(i, 0x2200);
350
+  DWIN_Byte(i, id);
351
+  DWIN_Send(i);     // AA 23 00 00 00 00 08 00 01 02 03 CC 33 C3 3C
352
+}
353
+
354
+// Draw an Icon
355
+//  libID: Icon library ID
356
+//  picID: Icon ID
357
+//  x/y: Upper-left point
358
+void DWIN_ICON_Show(uint8_t libID, uint8_t picID, uint16_t x, uint16_t y) {
359
+  NOMORE(x, DWIN_WIDTH - 1);
360
+  NOMORE(y, DWIN_HEIGHT - 1); // -- ozy -- srl
361
+  size_t i = 0;
362
+  DWIN_Byte(i, 0x23);
363
+  DWIN_Word(i, x);
364
+  DWIN_Word(i, y);
365
+  DWIN_Byte(i, 0x80 | libID);
366
+  //DWIN_Byte(i, libID);
367
+  DWIN_Byte(i, picID);
368
+  DWIN_Send(i);
369
+}
370
+
371
+// Unzip the JPG picture to a virtual display area
372
+//  n: Cache index
373
+//  id: Picture ID
374
+void DWIN_JPG_CacheToN(uint8_t n, uint8_t id) {
375
+  size_t i = 0;
376
+  DWIN_Byte(i, 0x25);
377
+  DWIN_Byte(i, n);
378
+  DWIN_Byte(i, id);
379
+  DWIN_Send(i);
380
+}
381
+
382
+// Copy area from virtual display area to current screen
383
+//  cacheID: virtual area number
384
+//  xStart/yStart: Upper-left of virtual area
385
+//  xEnd/yEnd: Lower-right of virtual area
386
+//  x/y: Screen paste point
387
+void DWIN_Frame_AreaCopy(uint8_t cacheID, uint16_t xStart, uint16_t yStart,
388
+                         uint16_t xEnd, uint16_t yEnd, uint16_t x, uint16_t y) {
389
+  size_t i = 0;
390
+  DWIN_Byte(i, 0x27);
391
+  DWIN_Byte(i, 0x80 | cacheID);
392
+  DWIN_Word(i, xStart);
393
+  DWIN_Word(i, yStart);
394
+  DWIN_Word(i, xEnd);
395
+  DWIN_Word(i, yEnd);
396
+  DWIN_Word(i, x);
397
+  DWIN_Word(i, y);
398
+  DWIN_Send(i);
399
+}
400
+
401
+// Animate a series of icons
402
+//  animID: Animation ID; 0x00-0x0F
403
+//  animate: true on; false off;
404
+//  libID: Icon library ID
405
+//  picIDs: Icon starting ID
406
+//  picIDe: Icon ending ID
407
+//  x/y: Upper-left point
408
+//  interval: Display time interval, unit 10mS
409
+void DWIN_ICON_Animation(uint8_t animID, bool animate, uint8_t libID, uint8_t picIDs, uint8_t picIDe, uint16_t x, uint16_t y, uint16_t interval) {
410
+  NOMORE(x, DWIN_WIDTH - 1);
411
+  NOMORE(y, DWIN_HEIGHT - 1); // -- ozy -- srl
412
+  size_t i = 0;
413
+  DWIN_Byte(i, 0x28);
414
+  DWIN_Word(i, x);
415
+  DWIN_Word(i, y);
416
+  // Bit 7: animation on or off
417
+  // Bit 6: start from begin or end
418
+  // Bit 5-4: unused (0)
419
+  // Bit 3-0: animID
420
+  DWIN_Byte(i, (animate * 0x80) | 0x40 | animID);
421
+  DWIN_Byte(i, libID);
422
+  DWIN_Byte(i, picIDs);
423
+  DWIN_Byte(i, picIDe);
424
+  DWIN_Byte(i, interval);
425
+  DWIN_Send(i);
426
+}
427
+
428
+// Animation Control
429
+//  state: 16 bits, each bit is the state of an animation id
430
+void DWIN_ICON_AnimationControl(uint16_t state) {
431
+  size_t i = 0;
432
+  DWIN_Byte(i, 0x29);
433
+  DWIN_Word(i, state);
434
+  DWIN_Send(i);
435
+}
436
+
437
+/*---------------------------------------- Memory functions ----------------------------------------*/
438
+// The LCD has an additional 32KB SRAM and 16KB Flash
439
+
440
+// Data can be written to the sram and save to one of the jpeg page files
441
+
442
+// Write Data Memory
443
+//  command 0x31
444
+//  Type: Write memory selection; 0x5A=SRAM; 0xA5=Flash
445
+//  Address: Write data memory address; 0x000-0x7FFF for SRAM; 0x000-0x3FFF for Flash
446
+//  Data: data
447
+//
448
+//  Flash writing returns 0xA5 0x4F 0x4B
449
+
450
+// Read Data Memory
451
+//  command 0x32
452
+//  Type: Read memory selection; 0x5A=SRAM; 0xA5=Flash
453
+//  Address: Read data memory address; 0x000-0x7FFF for SRAM; 0x000-0x3FFF for Flash
454
+//  Length: leangth of data to read; 0x01-0xF0
455
+//
456
+//  Response:
457
+//    Type, Address, Length, Data
458
+
459
+// Write Picture Memory
460
+//  Write the contents of the 32KB SRAM data memory into the designated image memory space
461
+//  Issued: 0x5A, 0xA5, PIC_ID
462
+//  Response: 0xA5 0x4F 0x4B
463
+//
464
+//  command 0x33
465
+//  0x5A, 0xA5
466
+//  PicId: Picture Memory location, 0x00-0x0F
467
+//
468
+//  Flash writing returns 0xA5 0x4F 0x4B
469
+
470
+#endif // IS_DWIN_MARLINUI

+ 302
- 0
Marlin/src/lcd/e3v2/marlinui/dwin_lcd.h View File

@@ -0,0 +1,302 @@
1
+/**
2
+ * Marlin 3D Printer Firmware
3
+ * Copyright (c) 2021 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
4
+ *
5
+ * Based on Sprinter and grbl.
6
+ * Copyright (c) 2011 Camiel Gubbels / Erik van der Zalm
7
+ *
8
+ * This program is free software: you can redistribute it and/or modify
9
+ * it under the terms of the GNU General Public License as published by
10
+ * the Free Software Foundation, either version 3 of the License, or
11
+ * (at your option) any later version.
12
+ *
13
+ * This program is distributed in the hope that it will be useful,
14
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
15
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16
+ * GNU General Public License for more details.
17
+ *
18
+ * You should have received a copy of the GNU General Public License
19
+ * along with this program.  If not, see <https://www.gnu.org/licenses/>.
20
+ *
21
+ */
22
+#pragma once
23
+
24
+/********************************************************************************
25
+ * @file     lcd/e3v2/marlinui/dwin_lcd.h
26
+ * @brief    DWIN screen control functions
27
+ ********************************************************************************/
28
+
29
+#include <stdint.h>
30
+
31
+#define RECEIVED_NO_DATA         0x00
32
+#define RECEIVED_SHAKE_HAND_ACK  0x01
33
+
34
+#define FHONE                    0xAA
35
+
36
+#define DWIN_SCROLL_UP   2
37
+#define DWIN_SCROLL_DOWN 3
38
+
39
+#if DISABLED(DWIN_MARLINUI_LANDSCAPE)
40
+  #define DWIN_WIDTH  272
41
+  #define DWIN_HEIGHT 480
42
+#else
43
+  #define DWIN_WIDTH  480
44
+  #define DWIN_HEIGHT 272
45
+#endif
46
+
47
+// Picture ID
48
+#define DWIN_Boot_Horiz      0
49
+#define DWIN_Boot_Vert       1
50
+#define DWIN_MarlinUI_Assets 2
51
+
52
+/**
53
+ * 3-.0:The font size, 0x00-0x09, corresponds to the font size below:
54
+ * 0x00=6*12   0x01=8*16   0x02=10*20  0x03=12*24  0x04=14*28
55
+ * 0x05=16*32  0x06=20*40  0x07=24*48  0x08=28*56  0x09=32*64
56
+ */
57
+#define font6x12  0x00
58
+#define font8x16  0x01
59
+#define font10x20 0x02
60
+#define font12x24 0x03
61
+#define font14x28 0x04
62
+#define font16x32 0x05
63
+#define font20x40 0x06
64
+#define font24x48 0x07
65
+#define font28x56 0x08
66
+#define font32x64 0x09
67
+
68
+#define DWIN_FONT_MENU  font10x20
69
+#define DWIN_FONT_STAT  font14x28
70
+#define DWIN_FONT_HEAD  font10x20
71
+#define DWIN_FONT_ALERT font14x28
72
+
73
+// Color
74
+#define Color_White       0xFFFF
75
+#define Color_Yellow      0xFF0F
76
+#define Color_Error_Red   0xB000  // Error!
77
+#define Color_Bg_Red      0xF00F  // Red background color
78
+#define Color_Bg_Window   0x31E8  // Popup background color
79
+#define Color_Bg_Heading  0x3344  // Static Heading
80
+#define Color_Bg_Blue     0x1125  // Dark blue background color
81
+#define Color_Bg_Black    0x0841  // Black background color
82
+#define Color_IconBlue    0x45FA  // Lighter blue that matches icons/accents
83
+#define Popup_Text_Color  0xD6BA  // Popup font background color
84
+#define Line_Color        0x3A6A  // Split line color
85
+#define Rectangle_Color   0xEE2F  // Blue square cursor color
86
+#define Percent_Color     0xFE29  // Percentage color
87
+#define BarFill_Color     0x10E4  // Fill color of progress bar
88
+#define Select_Color      0x33BB  // Selected color
89
+
90
+// Character matrix width x height
91
+//#define LCD_WIDTH ((DWIN_WIDTH) / 8)
92
+//#define LCD_HEIGHT ((DWIN_HEIGHT) / 12)
93
+
94
+// ICON ID
95
+#define BOOT_ICON           3 // Icon set file 3.ICO
96
+#define ICON                4 // Icon set file 4.ICO
97
+
98
+// MarlinUI Boot Icons
99
+#define ICON_MarlinBoot            0
100
+#define ICON_OpenSource            1
101
+#define ICON_GitHubURL             2
102
+#define ICON_MarlinURL             3
103
+#define ICON_Copyright             4
104
+
105
+// MarlinUI Icons
106
+#define ICON_LOGO_Marlin           0
107
+#define ICON_HotendOff             1
108
+#define ICON_HotendOn              2
109
+#define ICON_BedOff                3
110
+#define ICON_BedOn                 4
111
+#define ICON_Fan0                  5
112
+#define ICON_Fan1                  6
113
+#define ICON_Fan2                  7
114
+#define ICON_Fan3                  8
115
+#define ICON_Halted                9
116
+#define ICON_Question             10
117
+#define ICON_Alert                11
118
+#define ICON_RotateCW             12
119
+#define ICON_RotateCCW            13
120
+#define ICON_UpArrow              14
121
+#define ICON_DownArrow            15
122
+#define ICON_BedLine              16
123
+
124
+#define ICON_AdvSet               ICON_Language
125
+#define ICON_HomeOff              ICON_AdvSet
126
+#define ICON_HomeOffX             ICON_StepX
127
+#define ICON_HomeOffY             ICON_StepY
128
+#define ICON_HomeOffZ             ICON_StepZ
129
+#define ICON_ProbeOff             ICON_AdvSet
130
+#define ICON_ProbeOffX            ICON_StepX
131
+#define ICON_ProbeOffY            ICON_StepY
132
+#define ICON_PIDNozzle            ICON_SetEndTemp
133
+#define ICON_PIDbed               ICON_SetBedTemp
134
+
135
+/*-------------------------------------- System variable function --------------------------------------*/
136
+
137
+// Handshake (1: Success, 0: Fail)
138
+bool DWIN_Handshake(void);
139
+
140
+// Common DWIN startup
141
+void DWIN_Startup(void);
142
+
143
+// Set the backlight luminance
144
+//  luminance: (0x00-0xFF)
145
+void DWIN_Backlight_SetLuminance(const uint8_t luminance);
146
+
147
+// Set screen display direction
148
+//  dir: 0=0°, 1=90°, 2=180°, 3=270°
149
+void DWIN_Frame_SetDir(uint8_t dir);
150
+
151
+// Update display
152
+void DWIN_UpdateLCD(void);
153
+
154
+/*---------------------------------------- Drawing functions ----------------------------------------*/
155
+
156
+// Clear screen
157
+//  color: Clear screen color
158
+void DWIN_Frame_Clear(const uint16_t color);
159
+
160
+// Draw a point
161
+//  color: point color
162
+//  width: point width   0x01-0x0F
163
+//  height: point height 0x01-0x0F
164
+//  x,y: upper left point
165
+void DWIN_Draw_Point(uint16_t color, uint8_t width, uint8_t height, uint16_t x, uint16_t y);
166
+
167
+// Draw a line
168
+//  color: Line segment color
169
+//  xStart/yStart: Start point
170
+//  xEnd/yEnd: End point
171
+void DWIN_Draw_Line(uint16_t color, uint16_t xStart, uint16_t yStart, uint16_t xEnd, uint16_t yEnd);
172
+
173
+// Draw a Horizontal line
174
+//  color: Line segment color
175
+//  xStart/yStart: Start point
176
+//  xLength: Line Length
177
+inline void DWIN_Draw_HLine(uint16_t color, uint16_t xStart, uint16_t yStart, uint16_t xLength) {
178
+  DWIN_Draw_Line(color, xStart, yStart, xStart + xLength - 1, yStart);
179
+}
180
+
181
+// Draw a Vertical line
182
+//  color: Line segment color
183
+//  xStart/yStart: Start point
184
+//  yLength: Line Length
185
+inline void DWIN_Draw_VLine(uint16_t color, uint16_t xStart, uint16_t yStart, uint16_t yLength) {
186
+  DWIN_Draw_Line(color, xStart, yStart, xStart, yStart + yLength - 1);
187
+}
188
+
189
+// Draw a rectangle
190
+//  mode: 0=frame, 1=fill, 2=XOR fill
191
+//  color: Rectangle color
192
+//  xStart/yStart: upper left point
193
+//  xEnd/yEnd: lower right point
194
+void DWIN_Draw_Rectangle(uint8_t mode, uint16_t color,
195
+                         uint16_t xStart, uint16_t yStart, uint16_t xEnd, uint16_t yEnd);
196
+
197
+// Draw a box
198
+//  mode: 0=frame, 1=fill, 2=XOR fill
199
+//  color: Rectangle color
200
+//  xStart/yStart: upper left point
201
+//  xSize/ySize: box size
202
+inline void DWIN_Draw_Box(uint8_t mode, uint16_t color, uint16_t xStart, uint16_t yStart, uint16_t xSize, uint16_t ySize) {
203
+  DWIN_Draw_Rectangle(mode, color, xStart, yStart, xStart + xSize - 1, yStart + ySize - 1);
204
+}
205
+
206
+// Move a screen area
207
+//  mode: 0, circle shift; 1, translation
208
+//  dir: 0=left, 1=right, 2=up, 3=down
209
+//  dis: Distance
210
+//  color: Fill color
211
+//  xStart/yStart: upper left point
212
+//  xEnd/yEnd: bottom right point
213
+void DWIN_Frame_AreaMove(uint8_t mode, uint8_t dir, uint16_t dis,
214
+                         uint16_t color, uint16_t xStart, uint16_t yStart, uint16_t xEnd, uint16_t yEnd);
215
+
216
+/*---------------------------------------- Text related functions ----------------------------------------*/
217
+
218
+// Draw a string
219
+//  bShow: true=display background color; false=don't display background color
220
+//  size: Font size
221
+//  color: Character color
222
+//  bColor: Background color
223
+//  x/y: Upper-left coordinate of the string
224
+//  *string: The string
225
+void DWIN_Draw_String(bool bShow, uint8_t size, uint16_t color, uint16_t bColor, uint16_t x, uint16_t y, char *string);
226
+
227
+class __FlashStringHelper;
228
+
229
+inline void DWIN_Draw_String(bool bShow, uint8_t size, uint16_t color, uint16_t bColor, uint16_t x, uint16_t y, const __FlashStringHelper *title) {
230
+  DWIN_Draw_String(bShow, size, color, bColor, x, y, (char *)title);
231
+}
232
+
233
+// Draw a positive integer
234
+//  bShow: true=display background color; false=don't display background color
235
+//  zeroFill: true=zero fill; false=no zero fill
236
+//  zeroMode: 1=leading 0 displayed as 0; 0=leading 0 displayed as a space
237
+//  size: Font size
238
+//  color: Character color
239
+//  bColor: Background color
240
+//  iNum: Number of digits
241
+//  x/y: Upper-left coordinate
242
+//  value: Integer value
243
+void DWIN_Draw_IntValue(uint8_t bShow, bool zeroFill, uint8_t zeroMode, uint8_t size, uint16_t color,
244
+                          uint16_t bColor, uint8_t iNum, uint16_t x, uint16_t y, uint16_t value);
245
+
246
+// Draw a floating point number
247
+//  bShow: true=display background color; false=don't display background color
248
+//  zeroFill: true=zero fill; false=no zero fill
249
+//  zeroMode: 1=leading 0 displayed as 0; 0=leading 0 displayed as a space
250
+//  size: Font size
251
+//  color: Character color
252
+//  bColor: Background color
253
+//  iNum: Number of whole digits
254
+//  fNum: Number of decimal digits
255
+//  x/y: Upper-left point
256
+//  value: Float value
257
+void DWIN_Draw_FloatValue(uint8_t bShow, bool zeroFill, uint8_t zeroMode, uint8_t size, uint16_t color,
258
+                            uint16_t bColor, uint8_t iNum, uint8_t fNum, uint16_t x, uint16_t y, long value);
259
+
260
+/*---------------------------------------- Picture related functions ----------------------------------------*/
261
+
262
+// Draw JPG and cached in #0 virtual display area
263
+// id: Picture ID
264
+void DWIN_JPG_ShowAndCache(const uint8_t id);
265
+
266
+// Draw an Icon
267
+//  libID: Icon library ID
268
+//  picID: Icon ID
269
+//  x/y: Upper-left point
270
+void DWIN_ICON_Show(uint8_t libID, uint8_t picID, uint16_t x, uint16_t y);
271
+
272
+// Unzip the JPG picture to a virtual display area
273
+//  n: Cache index
274
+//  id: Picture ID
275
+void DWIN_JPG_CacheToN(uint8_t n, uint8_t id);
276
+
277
+// Unzip the JPG picture to virtual display area #1
278
+//  id: Picture ID
279
+inline void DWIN_JPG_CacheTo1(uint8_t id) { DWIN_JPG_CacheToN(1, id); }
280
+
281
+// Copy area from virtual display area to current screen
282
+//  cacheID: virtual area number
283
+//  xStart/yStart: Upper-left of virtual area
284
+//  xEnd/yEnd: Lower-right of virtual area
285
+//  x/y: Screen paste point
286
+void DWIN_Frame_AreaCopy(uint8_t cacheID, uint16_t xStart, uint16_t yStart,
287
+                         uint16_t xEnd, uint16_t yEnd, uint16_t x, uint16_t y);
288
+
289
+// Animate a series of icons
290
+//  animID: Animation ID  up to 16
291
+//  animate: animation on or off
292
+//  libID: Icon library ID
293
+//  picIDs: Icon starting ID
294
+//  picIDe: Icon ending ID
295
+//  x/y: Upper-left point
296
+//  interval: Display time interval, unit 10mS
297
+void DWIN_ICON_Animation(uint8_t animID, bool animate, uint8_t libID, uint8_t picIDs,
298
+                         uint8_t picIDe, uint16_t x, uint16_t y, uint16_t interval);
299
+
300
+// Animation Control
301
+//  state: 16 bits, each bit is the state of an animation id
302
+void DWIN_ICON_AnimationControl(uint16_t state);

+ 180
- 0
Marlin/src/lcd/e3v2/marlinui/dwin_string.cpp View File

@@ -0,0 +1,180 @@
1
+/**
2
+ * Marlin 3D Printer Firmware
3
+ * Copyright (c) 2021 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
4
+ *
5
+ * Based on Sprinter and grbl.
6
+ * Copyright (c) 2011 Camiel Gubbels / Erik van der Zalm
7
+ *
8
+ * This program is free software: you can redistribute it and/or modify
9
+ * it under the terms of the GNU General Public License as published by
10
+ * the Free Software Foundation, either version 3 of the License, or
11
+ * (at your option) any later version.
12
+ *
13
+ * This program is distributed in the hope that it will be useful,
14
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
15
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16
+ * GNU General Public License for more details.
17
+ *
18
+ * You should have received a copy of the GNU General Public License
19
+ * along with this program.  If not, see <https://www.gnu.org/licenses/>.
20
+ *
21
+ */
22
+
23
+#include "../../../inc/MarlinConfig.h"
24
+
25
+#if IS_DWIN_MARLINUI
26
+
27
+#include "dwin_string.h"
28
+//#include "../../fontutils.h"
29
+
30
+uint8_t DWIN_String::data[];
31
+uint16_t DWIN_String::span;
32
+uint8_t DWIN_String::len;
33
+
34
+void DWIN_String::set() {
35
+  //*data = 0x00;
36
+  memset(data, 0x00, sizeof(data));
37
+  span = 0;
38
+  len = 0;
39
+}
40
+
41
+uint8_t read_byte(uint8_t *byte) { return *byte; }
42
+
43
+/**
44
+ * Add a string, applying substitutions for the following characters:
45
+ *
46
+ *   = displays  '0'....'10' for indexes 0 - 10
47
+ *   ~ displays  '1'....'11' for indexes 0 - 10
48
+ *   * displays 'E1'...'E11' for indexes 0 - 10 (By default. Uses LCD_FIRST_TOOL)
49
+ */
50
+void DWIN_String::add(uint8_t *string, int8_t index, uint8_t *itemString) {
51
+  wchar_t wchar;
52
+
53
+  while (*string) {
54
+    string = get_utf8_value_cb(string, read_byte, &wchar);
55
+    if (wchar > 255) wchar |= 0x0080;
56
+    uint8_t ch = uint8_t(wchar & 0x00FF);
57
+
58
+    if (ch == '=' || ch == '~' || ch == '*') {
59
+      if (index >= 0) {
60
+        int8_t inum = index + ((ch == '=') ? 0 : LCD_FIRST_TOOL);
61
+        if (ch == '*') add_character('E');
62
+        if (inum >= 10) { add_character('0' + (inum / 10)); inum %= 10; }
63
+        add_character('0' + inum);
64
+      }
65
+      else {
66
+        add(index == -2 ? GET_TEXT(MSG_CHAMBER) : GET_TEXT(MSG_BED));
67
+      }
68
+      continue;
69
+    }
70
+    else if (ch == '$' && itemString) {
71
+      add(itemString);
72
+      continue;
73
+    }
74
+
75
+    add_character(ch);
76
+  }
77
+  eol();
78
+}
79
+
80
+void DWIN_String::add(uint8_t *string, uint8_t max_len) {
81
+  wchar_t wchar;
82
+  while (*string && max_len) {
83
+    string = get_utf8_value_cb(string, read_byte, &wchar);
84
+    /*
85
+    if (wchar > 255) wchar |= 0x0080;
86
+    uint8_t ch = uint8_t(wchar & 0x00FF);
87
+    add_character(ch);
88
+    */
89
+    add(wchar);
90
+    max_len--;
91
+  }
92
+  eol();
93
+}
94
+
95
+void DWIN_String::add(wchar_t character) {
96
+  int ret;
97
+  size_t idx = 0;
98
+  dwin_charmap_t pinval;
99
+  dwin_charmap_t *copy_address = nullptr;
100
+  pinval.uchar = character;
101
+  pinval.idx = -1;
102
+
103
+  // For 8-bit ASCII just print the single character
104
+  char str[] = { '?', 0 };
105
+  if (character < 255) {
106
+    str[0] = (char)character;
107
+  }
108
+  else {
109
+    copy_address = nullptr;
110
+    ret = pf_bsearch_r((void *)g_dwin_charmap_device, COUNT(g_dwin_charmap_device), pf_bsearch_cb_comp_dwinmap_pgm, (void *)&pinval, &idx);
111
+    if (ret >= 0) {
112
+      copy_address = (dwin_charmap_t*)(g_dwin_charmap_device + idx);
113
+    }
114
+    else {
115
+      ret = pf_bsearch_r((void *)g_dwin_charmap_common, COUNT(g_dwin_charmap_common), pf_bsearch_cb_comp_dwinmap_pgm, (void *)&pinval, &idx);
116
+      if (ret >= 0)
117
+        copy_address = (dwin_charmap_t*)(g_dwin_charmap_common + idx);
118
+    }
119
+    if (ret >= 0) {
120
+      dwin_charmap_t localval;
121
+      memcpy_P(&localval, copy_address, sizeof(localval));
122
+      str[0] = localval.idx;
123
+      str[1] = localval.idx2;
124
+    }
125
+  }
126
+  if (str[0]) add_character(str[0]);
127
+  if (str[1]) add_character(str[1]);
128
+}
129
+
130
+void DWIN_String::add_character(uint8_t character) {
131
+  if (len < MAX_STRING_LENGTH) {
132
+    data[len] = character;
133
+    len++;
134
+    //span += glyph(character)->DWidth;
135
+  }
136
+}
137
+
138
+void DWIN_String::rtrim(uint8_t character) {
139
+  while (len) {
140
+    if (data[len - 1] == 0x20 || data[len - 1] == character) {
141
+      len--;
142
+      //span -= glyph(data[length])->DWidth;
143
+      eol();
144
+    }
145
+    else
146
+      break;
147
+  }
148
+}
149
+
150
+void DWIN_String::ltrim(uint8_t character) {
151
+  uint16_t i, j;
152
+  for (i = 0; (i < len) && (data[i] == 0x20 || data[i] == character); i++) {
153
+    //span -= glyph(data[i])->DWidth;
154
+  }
155
+  if (i == 0) return;
156
+  for (j = 0; i < len; data[j++] = data[i++]);
157
+  len = j;
158
+  eol();
159
+}
160
+
161
+void DWIN_String::trim(uint8_t character) {
162
+  rtrim(character);
163
+  ltrim(character);
164
+}
165
+
166
+/* return v1 - v2 */
167
+int dwin_charmap_compare(dwin_charmap_t *v1, dwin_charmap_t *v2) {
168
+  return (v1->uchar < v2->uchar) ? -1 : (v1->uchar > v2->uchar) ? 1 : 0;
169
+}
170
+
171
+int pf_bsearch_cb_comp_dwinmap_pgm(void *userdata, size_t idx, void * data_pin) {
172
+  dwin_charmap_t localval;
173
+  dwin_charmap_t *p_dwin_charmap = (dwin_charmap_t *)userdata;
174
+  memcpy_P(&localval, p_dwin_charmap + idx, sizeof(localval));
175
+  return dwin_charmap_compare(&localval, (dwin_charmap_t *)data_pin);
176
+}
177
+
178
+DWIN_String dwin_string;
179
+
180
+#endif // IS_DWIN_MARLINUI

+ 1007
- 0
Marlin/src/lcd/e3v2/marlinui/dwin_string.h
File diff suppressed because it is too large
View File


+ 193
- 0
Marlin/src/lcd/e3v2/marlinui/lcdprint_dwin.cpp View File

@@ -0,0 +1,193 @@
1
+/**
2
+ * Marlin 3D Printer Firmware
3
+ * Copyright (c) 2021 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
4
+ *
5
+ * Based on Sprinter and grbl.
6
+ * Copyright (c) 2011 Camiel Gubbels / Erik van der Zalm
7
+ *
8
+ * This program is free software: you can redistribute it and/or modify
9
+ * it under the terms of the GNU General Public License as published by
10
+ * the Free Software Foundation, either version 3 of the License, or
11
+ * (at your option) any later version.
12
+ *
13
+ * This program is distributed in the hope that it will be useful,
14
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
15
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16
+ * GNU General Public License for more details.
17
+ *
18
+ * You should have received a copy of the GNU General Public License
19
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
20
+ *
21
+ */
22
+
23
+/**
24
+ * lcd/e3v2/marlinui/lcdprint_dwin.cpp
25
+ *
26
+ * Due to DWIN hardware limitations simplified characters are used
27
+ */
28
+
29
+#include "../../../inc/MarlinConfigPre.h"
30
+
31
+#if IS_DWIN_MARLINUI
32
+
33
+#include "lcdprint_dwin.h"
34
+#include "dwin_lcd.h"
35
+#include "dwin_string.h"
36
+
37
+#include "../../marlinui.h"
38
+#include "../../../MarlinCore.h"
39
+
40
+#include <string.h>
41
+
42
+cursor_t cursor;
43
+
44
+extern dwin_font_t dwin_font;
45
+
46
+void lcd_moveto_xy(const lcd_uint_t x, const lcd_uint_t y) { cursor.x = x; cursor.y = y; }
47
+
48
+void lcd_moveto(const lcd_uint_t col, const lcd_uint_t row) {
49
+  cursor.x = col * dwin_font.width;
50
+  cursor.y = (row * (dwin_font.height + EXTRA_ROW_HEIGHT)) + (EXTRA_ROW_HEIGHT / 2);
51
+}
52
+
53
+inline void lcd_advance_cursor() { cursor.x += dwin_font.width; }
54
+
55
+void lcd_put_int(const int i) {
56
+  // TODO: Draw an int at the cursor position, advance the cursor
57
+}
58
+
59
+int lcd_put_dwin_string() {
60
+  DWIN_Draw_String(dwin_font.solid, dwin_font.index, dwin_font.fg, dwin_font.bg, cursor.x, cursor.y, (char*)dwin_string.string());
61
+  cursor.x += dwin_string.length() * dwin_font.width;
62
+  return dwin_string.length();
63
+}
64
+
65
+// return < 0 on error
66
+// return the advanced cols
67
+int lcd_put_wchar_max(wchar_t c, pixel_len_t max_length) {
68
+  dwin_string.set();
69
+  dwin_string.add(c);
70
+  dwin_string.truncate(max_length);
71
+  // Draw the char(s) at the cursor and advance the cursor
72
+  DWIN_Draw_String(dwin_font.solid, dwin_font.index, dwin_font.fg, dwin_font.bg, cursor.x, cursor.y, (char*)dwin_string.string());
73
+  cursor.x += dwin_string.length() * dwin_font.width;
74
+  return dwin_string.length();
75
+}
76
+
77
+/**
78
+ * @brief Draw a UTF-8 string
79
+ *
80
+ * @param utf8_str : the UTF-8 string
81
+ * @param cb_read_byte : the callback function to read one byte from the utf8_str (from RAM or ROM)
82
+ * @param max_length : the pixel length of the string allowed (or number of slots in HD44780)
83
+ *
84
+ * @return the number of pixels advanced
85
+ *
86
+ * Draw a UTF-8 string
87
+ */
88
+static int lcd_put_u8str_max_cb(const char * utf8_str, uint8_t (*cb_read_byte)(uint8_t * str), pixel_len_t max_length) {
89
+  uint8_t *p = (uint8_t *)utf8_str;
90
+  dwin_string.set();
91
+  while (dwin_string.length() < max_length) {
92
+    wchar_t ch = 0;
93
+    p = get_utf8_value_cb(p, cb_read_byte, &ch);
94
+    if (!ch) break;
95
+    dwin_string.add(ch);
96
+  }
97
+  DWIN_Draw_String(dwin_font.solid, dwin_font.index, dwin_font.fg, dwin_font.bg, cursor.x, cursor.y, (char*)dwin_string.string());
98
+  cursor.x += dwin_string.length() * dwin_font.width;
99
+  return dwin_string.length();
100
+}
101
+
102
+int lcd_put_u8str_max(const char * utf8_str, pixel_len_t max_length) {
103
+  return lcd_put_u8str_max_cb(utf8_str, read_byte_ram, max_length);
104
+}
105
+
106
+int lcd_put_u8str_max_P(PGM_P utf8_str_P, pixel_len_t max_length) {
107
+  return lcd_put_u8str_max_cb(utf8_str_P, read_byte_rom, max_length);
108
+}
109
+
110
+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*/) {
111
+  dwin_string.set();
112
+  dwin_string.add((uint8_t*)pstr, ind, (uint8_t*)inStr);
113
+  dwin_string.truncate(maxlen);
114
+  DWIN_Draw_String(dwin_font.solid, dwin_font.index, dwin_font.fg, dwin_font.bg, cursor.x, cursor.y, (char*)dwin_string.string());
115
+  cursor.x += dwin_string.length() * dwin_font.width;
116
+  return dwin_string.length();
117
+}
118
+
119
+#if ENABLED(DEBUG_LCDPRINT)
120
+
121
+  int test_dwin_charmap(dwin_charmap_t *data, size_t size, char *name, char flg_show_contents) {
122
+    int ret;
123
+    size_t idx = 0;
124
+    dwin_charmap_t preval = { 0, 0, 0 };
125
+    dwin_charmap_t pinval = { 0, 0, 0 };
126
+    char flg_error = 0;
127
+
128
+    int i;
129
+
130
+    TRACE("Test %s\n", name);
131
+
132
+    for (i = 0; i < size; i ++) {
133
+      memcpy_P(&pinval, &(data[i]), sizeof(pinval));
134
+
135
+      if (flg_show_contents) {
136
+        #if 1
137
+          TRACE("[% 4d] % 6" PRIu32 "(0x%04" PRIX32 ") --> 0x%02X,0x%02X%s\n", i, pinval.uchar, pinval.uchar, (unsigned int)(pinval.idx), (unsigned int)(pinval.idx2), (preval.uchar < pinval.uchar?"":" <--- ERROR"));
138
+        #else
139
+          TRACE("[% 4d]", i);
140
+          TRACE("% 6" PRIu32 "(0x%04" PRIX32 "),", pinval.uchar, pinval.uchar);
141
+          TRACE("0x%02X,", (unsigned int)(pinval.idx));
142
+          TRACE("0x%02X,", (unsigned int)(pinval.idx2));
143
+          TRACE("%s", (preval.uchar < pinval.uchar?"":" <--- ERROR"));
144
+        #endif
145
+      }
146
+      if (preval.uchar >= pinval.uchar) {
147
+        flg_error = 1;
148
+        //TRACE("Error: out of order in array %s: idx=%d, val=%d(0x%x)\n", name, i, pinval.uchar, pinval.uchar);
149
+        //return -1;
150
+      }
151
+      memcpy(&preval, &pinval, sizeof(pinval));
152
+
153
+      ret = pf_bsearch_r((void *)data, size, pf_bsearch_cb_comp_dwinmap_pgm, (void *)&pinval, &idx);
154
+      if (ret < 0) {
155
+        flg_error = 1;
156
+        TRACE("Error: not found item in array %s: idx=%d, val=%d(0x%x)\n", name, i, pinval.uchar, pinval.uchar);
157
+        //return -1;
158
+      }
159
+      if (idx != i) {
160
+        flg_error = 1;
161
+        TRACE("Error: wrong index found item in array %s: idx=%d, val=%d(0x%x)\n", name, i, pinval.uchar, pinval.uchar);
162
+        //return -1;
163
+      }
164
+    }
165
+    if (flg_error) {
166
+      TRACE("\nError: in array %s\n\n", name);
167
+      return -1;
168
+    }
169
+    TRACE("\nPASS array %s\n\n", name);
170
+    return 0;
171
+  }
172
+
173
+  int test_dwin_charmap_all() {
174
+    int flg_error = 0;
175
+    if (test_dwin_charmap(g_dwin_charmap_device, COUNT(g_dwin_charmap_device), "g_dwin_charmap_device", 0) < 0) {
176
+      flg_error = 1;
177
+      test_dwin_charmap(g_dwin_charmap_device, COUNT(g_dwin_charmap_device), "g_dwin_charmap_device", 1);
178
+    }
179
+    if (test_dwin_charmap(g_dwin_charmap_common, COUNT(g_dwin_charmap_common), "g_dwin_charmap_common", 0) < 0) {
180
+      flg_error = 1;
181
+      test_dwin_charmap(g_dwin_charmap_common, COUNT(g_dwin_charmap_common), "g_dwin_charmap_common", 1);
182
+    }
183
+    if (flg_error) {
184
+      TRACE("\nFAILED in dwin tests!\n");
185
+      return -1;
186
+    }
187
+    TRACE("\nPASS in dwin tests.\n");
188
+    return 0;
189
+  }
190
+
191
+#endif // DEBUG_LCDPRINT
192
+
193
+#endif // IS_DWIN_MARLINUI

+ 30
- 0
Marlin/src/lcd/e3v2/marlinui/lcdprint_dwin.h View File

@@ -0,0 +1,30 @@
1
+/**
2
+ * Marlin 3D Printer Firmware
3
+ * Copyright (c) 2021 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
4
+ *
5
+ * Based on Sprinter and grbl.
6
+ * Copyright (c) 2011 Camiel Gubbels / Erik van der Zalm
7
+ *
8
+ * This program is free software: you can redistribute it and/or modify
9
+ * it under the terms of the GNU General Public License as published by
10
+ * the Free Software Foundation, either version 3 of the License, or
11
+ * (at your option) any later version.
12
+ *
13
+ * This program is distributed in the hope that it will be useful,
14
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
15
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16
+ * GNU General Public License for more details.
17
+ *
18
+ * You should have received a copy of the GNU General Public License
19
+ * along with this program.  If not, see <https://www.gnu.org/licenses/>.
20
+ *
21
+ */
22
+#pragma once
23
+
24
+#include "../../lcdprint.h"
25
+
26
+typedef struct { int16_t x, y; } cursor_t;
27
+extern cursor_t cursor;
28
+
29
+int lcd_put_dwin_string();
30
+void lcd_moveto_xy(const lcd_uint_t, const lcd_uint_t);

+ 146
- 0
Marlin/src/lcd/e3v2/marlinui/marlinui_dwin.h View File

@@ -0,0 +1,146 @@
1
+/**
2
+ * Marlin 3D Printer Firmware
3
+ * Copyright (c) 2021 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
4
+ *
5
+ * Based on Sprinter and grbl.
6
+ * Copyright (c) 2011 Camiel Gubbels / Erik van der Zalm
7
+ *
8
+ * This program is free software: you can redistribute it and/or modify
9
+ * it under the terms of the GNU General Public License as published by
10
+ * the Free Software Foundation, either version 3 of the License, or
11
+ * (at your option) any later version.
12
+ *
13
+ * This program is distributed in the hope that it will be useful,
14
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
15
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16
+ * GNU General Public License for more details.
17
+ *
18
+ * You should have received a copy of the GNU General Public License
19
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
20
+ *
21
+ */
22
+#pragma once
23
+
24
+/**
25
+ * lcd/e3v2/marlinui/lcdprint_dwin.h
26
+ */
27
+
28
+#include "../../../inc/MarlinConfigPre.h"
29
+#include "dwin_lcd.h"
30
+
31
+typedef uint16_t dwin_coord_t;  // Screen can be pretty big
32
+typedef uint16_t lcd_uint_t;
33
+typedef int16_t lcd_int_t;
34
+
35
+typedef struct {
36
+  uint8_t index, width, height;
37
+  uint16_t fg, bg;
38
+  bool solid;
39
+} dwin_font_t;
40
+
41
+extern dwin_font_t dwin_font;
42
+
43
+// Only Western languages support big / small fonts
44
+//#if DISABLED(DISPLAY_CHARSET_ISO10646_1)
45
+//  #undef USE_BIG_EDIT_FONT
46
+//  #undef USE_SMALL_INFOFONT
47
+//#endif
48
+
49
+#if ENABLED(USE_BIG_EDIT_FONT)
50
+  #define DWIN_FONT_EDIT font10x20
51
+#else
52
+  #define DWIN_FONT_EDIT font8x16
53
+#endif
54
+
55
+#define DWIN_FONT_INFO font8x16
56
+
57
+#if DWIN_FONT_MENU == font6x12
58
+  #define MENU_FONT_WIDTH    6
59
+  #define MENU_FONT_ASCENT  10
60
+  #define MENU_FONT_DESCENT  2
61
+#elif DWIN_FONT_MENU == font8x16
62
+  #define MENU_FONT_WIDTH    8
63
+  #define MENU_FONT_ASCENT  13
64
+  #define MENU_FONT_DESCENT  3
65
+#elif DWIN_FONT_MENU == font10x20
66
+  #define MENU_FONT_WIDTH   10
67
+  #define MENU_FONT_ASCENT  16
68
+  #define MENU_FONT_DESCENT  4
69
+#endif
70
+#define MENU_FONT_HEIGHT (MENU_FONT_ASCENT + MENU_FONT_DESCENT)
71
+
72
+#define EXTRA_ROW_HEIGHT 8
73
+#define MENU_LINE_HEIGHT (MENU_FONT_HEIGHT + EXTRA_ROW_HEIGHT)
74
+
75
+#if DWIN_FONT_EDIT == font6x12
76
+  #define EDIT_FONT_WIDTH    6
77
+  #define EDIT_FONT_ASCENT  10
78
+  #define EDIT_FONT_DESCENT  2
79
+#elif DWIN_FONT_EDIT == font8x16
80
+  #define EDIT_FONT_WIDTH    8
81
+  #define EDIT_FONT_ASCENT  13
82
+  #define EDIT_FONT_DESCENT  3
83
+#elif DWIN_FONT_EDIT == font10x20
84
+  #define EDIT_FONT_WIDTH   10
85
+  #define EDIT_FONT_ASCENT  16
86
+  #define EDIT_FONT_DESCENT  4
87
+#endif
88
+#define EDIT_FONT_HEIGHT (EDIT_FONT_ASCENT + EDIT_FONT_DESCENT)
89
+
90
+#if DWIN_FONT_INFO == font6x12
91
+  #define INFO_FONT_WIDTH    6
92
+  #define INFO_FONT_ASCENT  10
93
+  #define INFO_FONT_DESCENT  2
94
+#elif DWIN_FONT_INFO == font8x16
95
+  #define INFO_FONT_WIDTH    8
96
+  #define INFO_FONT_ASCENT  13
97
+  #define INFO_FONT_DESCENT  3
98
+#elif DWIN_FONT_INFO == font10x20
99
+  #define INFO_FONT_WIDTH   10
100
+  #define INFO_FONT_ASCENT  16
101
+  #define INFO_FONT_DESCENT  4
102
+#endif
103
+#define INFO_FONT_HEIGHT (INFO_FONT_ASCENT + INFO_FONT_DESCENT)
104
+
105
+#if DWIN_FONT_STAT == font6x12
106
+  #define STAT_FONT_WIDTH    6
107
+  #define STAT_FONT_ASCENT  10
108
+  #define STAT_FONT_DESCENT  2
109
+#elif DWIN_FONT_STAT == font8x16
110
+  #define STAT_FONT_WIDTH    8
111
+  #define STAT_FONT_ASCENT  13
112
+  #define STAT_FONT_DESCENT  3
113
+#elif DWIN_FONT_STAT == font10x20
114
+  #define STAT_FONT_WIDTH   10
115
+  #define STAT_FONT_ASCENT  16
116
+  #define STAT_FONT_DESCENT  4
117
+#elif DWIN_FONT_STAT == font12x24
118
+  #define STAT_FONT_WIDTH   12
119
+  #define STAT_FONT_ASCENT  19
120
+  #define STAT_FONT_DESCENT  5
121
+#elif DWIN_FONT_STAT == font14x28
122
+  #define STAT_FONT_WIDTH   14
123
+  #define STAT_FONT_ASCENT  22
124
+  #define STAT_FONT_DESCENT  6
125
+#elif DWIN_FONT_STAT == font16x32
126
+  #define STAT_FONT_WIDTH   16
127
+  #define STAT_FONT_ASCENT  26
128
+  #define STAT_FONT_DESCENT  6
129
+#elif DWIN_FONT_STAT == font20x40
130
+  #define STAT_FONT_WIDTH   20
131
+  #define STAT_FONT_ASCENT  32
132
+  #define STAT_FONT_DESCENT  8
133
+#elif DWIN_FONT_STAT == font24x48
134
+  #define STAT_FONT_WIDTH   24
135
+  #define STAT_FONT_ASCENT  38
136
+  #define STAT_FONT_DESCENT 10
137
+#elif DWIN_FONT_STAT == font28x56
138
+  #define STAT_FONT_WIDTH   28
139
+  #define STAT_FONT_ASCENT  44
140
+  #define STAT_FONT_DESCENT 12
141
+#elif DWIN_FONT_STAT == font32x64
142
+  #define STAT_FONT_WIDTH   32
143
+  #define STAT_FONT_ASCENT  50
144
+  #define STAT_FONT_DESCENT 14
145
+#endif
146
+#define STAT_FONT_HEIGHT (STAT_FONT_ASCENT + STAT_FONT_DESCENT)

+ 595
- 0
Marlin/src/lcd/e3v2/marlinui/ui_common.cpp View File

@@ -0,0 +1,595 @@
1
+/**
2
+ * Marlin 3D Printer Firmware
3
+ * Copyright (c) 2021 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
4
+ *
5
+ * Based on Sprinter and grbl.
6
+ * Copyright (c) 2011 Camiel Gubbels / Erik van der Zalm
7
+ *
8
+ * This program is free software: you can redistribute it and/or modify
9
+ * it under the terms of the GNU General Public License as published by
10
+ * the Free Software Foundation, either version 3 of the License, or
11
+ * (at your option) any later version.
12
+ *
13
+ * This program is distributed in the hope that it will be useful,
14
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
15
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16
+ * GNU General Public License for more details.
17
+ *
18
+ * You should have received a copy of the GNU General Public License
19
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
20
+ *
21
+ */
22
+
23
+#include "../../../inc/MarlinConfigPre.h"
24
+
25
+#if IS_DWIN_MARLINUI
26
+
27
+#include "marlinui_dwin.h"
28
+#include "dwin_lcd.h"
29
+#include "dwin_string.h"
30
+
31
+//#include "../../lcdprint.h"
32
+#include "lcdprint_dwin.h"
33
+#include "../../fontutils.h"
34
+#include "../../../libs/numtostr.h"
35
+#include "../../marlinui.h"
36
+
37
+#include "../../../sd/cardreader.h"
38
+#include "../../../module/motion.h"
39
+#include "../../../module/temperature.h"
40
+#include "../../../module/printcounter.h"
41
+
42
+#if ENABLED(SDSUPPORT)
43
+  #include "../../../libs/duration_t.h"
44
+#endif
45
+
46
+#if ENABLED(AUTO_BED_LEVELING_UBL)
47
+  #include "../../../feature/bedlevel/bedlevel.h"
48
+#endif
49
+
50
+// DWIN printing specifies the font on each string operation
51
+// but we'll make the font modal for Marlin
52
+dwin_font_t dwin_font = { font8x16, 8, 16, Color_White, Color_Bg_Black, true };
53
+void MarlinUI::set_font(const uint8_t font_nr) {
54
+  if (font_nr != dwin_font.index) {
55
+    dwin_font.index = font_nr;
56
+    uint8_t w, h;
57
+    switch (font_nr) {
58
+      default:
59
+      case font6x12:  w =  6; h = 12; break;
60
+      case font8x16:  w =  8; h = 16; break;
61
+      case font10x20: w = 10; h = 20; break;
62
+      case font12x24: w = 12; h = 24; break;
63
+      case font14x28: w = 14; h = 28; break;
64
+      case font16x32: w = 16; h = 32; break;
65
+      case font20x40: w = 20; h = 40; break;
66
+      case font24x48: w = 24; h = 48; break;
67
+      case font28x56: w = 28; h = 56; break;
68
+      case font32x64: w = 32; h = 64; break;
69
+    }
70
+    dwin_font.width = w;
71
+    dwin_font.height = h;
72
+    // TODO: Array with dimensions, auto fit menu items,
73
+    // update char width / height of the screen based on
74
+    // new (fixed-width) font size.
75
+  }
76
+}
77
+
78
+// This display is always detected
79
+bool MarlinUI::detected() { return true; }
80
+
81
+// Initialize or re-initialize the LCD
82
+void MarlinUI::init_lcd() {
83
+  DWIN_Startup();
84
+
85
+  // Load the assets JPG (currently just the status screen 'icon')
86
+  DWIN_JPG_CacheToN(1, DWIN_MarlinUI_Assets);
87
+}
88
+
89
+// This LCD should clear where it will draw anew
90
+void MarlinUI::clear_lcd() {
91
+  DWIN_ICON_AnimationControl(0x0000); // disable all icon animations
92
+  DWIN_Frame_Clear(Color_Bg_Black);
93
+  DWIN_UpdateLCD();
94
+
95
+  did_first_redraw = false;
96
+}
97
+
98
+#if ENABLED(SHOW_BOOTSCREEN)
99
+
100
+  void MarlinUI::show_bootscreen() {
101
+    clear_lcd();
102
+    dwin_string.set(F(SHORT_BUILD_VERSION));
103
+
104
+    #if ENABLED(DWIN_MARLINUI_PORTRAIT)
105
+      #define LOGO_CENTER ((LCD_PIXEL_WIDTH) / 2)
106
+      #define INFO_CENTER LOGO_CENTER
107
+      #define VERSION_Y   330
108
+      DWIN_ICON_Show(BOOT_ICON, ICON_MarlinBoot, LOGO_CENTER - 266 / 2,  15);
109
+      DWIN_ICON_Show(BOOT_ICON, ICON_OpenSource, LOGO_CENTER - 174 / 2, 280);
110
+      DWIN_ICON_Show(BOOT_ICON, ICON_GitHubURL,  LOGO_CENTER - 180 / 2, 420);
111
+      DWIN_ICON_Show(BOOT_ICON, ICON_MarlinURL,  LOGO_CENTER - 100 / 2, 440);
112
+      DWIN_ICON_Show(BOOT_ICON, ICON_Copyright,  LOGO_CENTER - 126 / 2, 460);
113
+    #else
114
+      #define LOGO_CENTER (280 / 2)
115
+      #define INFO_CENTER ((LCD_PIXEL_WIDTH) - 200 / 2)
116
+      #define VERSION_Y   84
117
+      DWIN_ICON_Show(BOOT_ICON, ICON_MarlinBoot, LOGO_CENTER - 266 / 2,  15);
118
+      DWIN_ICON_Show(BOOT_ICON, ICON_OpenSource, INFO_CENTER - 174 / 2,  60);
119
+      DWIN_ICON_Show(BOOT_ICON, ICON_GitHubURL,  INFO_CENTER - 180 / 2, 130);
120
+      DWIN_ICON_Show(BOOT_ICON, ICON_MarlinURL,  INFO_CENTER - 100 / 2, 152);
121
+      DWIN_ICON_Show(BOOT_ICON, ICON_Copyright,  INFO_CENTER - 126 / 2, 200);
122
+    #endif
123
+
124
+    DWIN_Draw_String(false, font10x20, Color_Yellow, Color_Bg_Black, INFO_CENTER - (dwin_string.length() * 10) / 2, VERSION_Y, S(dwin_string.string()));
125
+    DWIN_UpdateLCD();
126
+  }
127
+
128
+  void MarlinUI::bootscreen_completion(const millis_t sofar) {
129
+    if ((BOOTSCREEN_TIMEOUT) > sofar) safe_delay((BOOTSCREEN_TIMEOUT) - sofar);
130
+    clear_lcd();
131
+  }
132
+
133
+#endif
134
+
135
+// The kill screen is displayed for unrecoverable conditions
136
+void MarlinUI::draw_kill_screen() {
137
+  set_font(DWIN_FONT_ALERT);
138
+  DWIN_Frame_Clear(Color_Bg_Black);
139
+  dwin_font.fg = Color_Error_Red;
140
+  dwin_font.solid = false;
141
+  DWIN_Draw_Rectangle(1, Color_Bg_Window, 20, 20, LCD_PIXEL_WIDTH - 20, LCD_PIXEL_HEIGHT - 20);
142
+  // make the frame a few pixels thick
143
+  DWIN_Draw_Rectangle(0, Color_Yellow, 20, 20, LCD_PIXEL_WIDTH - 20, LCD_PIXEL_HEIGHT - 20);
144
+  DWIN_Draw_Rectangle(0, Color_Yellow, 21, 21, LCD_PIXEL_WIDTH - 21, LCD_PIXEL_HEIGHT - 21);
145
+  DWIN_Draw_Rectangle(0, Color_Yellow, 22, 22, LCD_PIXEL_WIDTH - 22, LCD_PIXEL_HEIGHT - 22);
146
+
147
+  uint8_t cx = (LCD_PIXEL_WIDTH / dwin_font.width / 2),
148
+          cy = (LCD_PIXEL_HEIGHT / dwin_font.height / 2);
149
+
150
+  #if ENABLED(DWIN_MARLINUI_LANDSCAPE)
151
+    cx += (96 / 2 / dwin_font.width);
152
+    DWIN_ICON_Show(ICON, ICON_Halted, 40, (LCD_PIXEL_HEIGHT - 96) / 2);
153
+  #else
154
+    DWIN_ICON_Show(ICON, ICON_Halted, (LCD_PIXEL_WIDTH - 96) / 2, 40);
155
+  #endif
156
+
157
+  uint8_t slen = utf8_strlen(status_message);
158
+  lcd_moveto(cx - (slen / 2), cy - 1);
159
+  lcd_put_u8str(status_message);
160
+
161
+  slen = utf8_strlen(S(GET_TEXT_F(MSG_HALTED)));
162
+  lcd_moveto(cx - (slen / 2), cy);
163
+  lcd_put_u8str_P((const char*)GET_TEXT_F(MSG_HALTED));
164
+
165
+  slen = utf8_strlen(S(GET_TEXT_F(MSG_HALTED)));
166
+  lcd_moveto(cx - (slen / 2), cy + 1);
167
+  lcd_put_u8str_P((const char*)GET_TEXT_F(MSG_HALTED));
168
+}
169
+
170
+//
171
+// Status Message
172
+//
173
+void MarlinUI::draw_status_message(const bool blink) {
174
+  set_font(DWIN_FONT_STAT);
175
+  dwin_font.solid = true;
176
+  dwin_font.fg = Color_White;
177
+  dwin_font.bg = Color_Bg_Black;
178
+  lcd_moveto_xy(0, LCD_PIXEL_HEIGHT - (STAT_FONT_HEIGHT) - 1);
179
+
180
+  constexpr uint8_t max_status_chars = (LCD_PIXEL_WIDTH) / (STAT_FONT_WIDTH);
181
+
182
+  auto status_changed = []{
183
+    static uint16_t old_hash = 0x0000;
184
+    uint16_t hash = 0x0000;
185
+    for (uint8_t i = 0; i < MAX_MESSAGE_LENGTH; i++) {
186
+      const char c = ui.status_message[i];
187
+      if (!c) break;
188
+      hash = ((hash << 1) | (hash >> 15)) ^ c;
189
+    }
190
+    const bool hash_changed = hash != old_hash;
191
+    old_hash = hash;
192
+    return hash_changed || !ui.did_first_redraw;
193
+  };
194
+
195
+  #if ENABLED(STATUS_MESSAGE_SCROLLING)
196
+    static bool last_blink = false;
197
+
198
+    // Get the UTF8 character count of the string
199
+    uint8_t slen = utf8_strlen(status_message);
200
+
201
+    // If the string fits into the LCD, just print it and do not scroll it
202
+    if (slen <= max_status_chars) {
203
+
204
+      if (status_changed()) {
205
+
206
+        // The string isn't scrolling and may not fill the screen
207
+        lcd_put_u8str(status_message);
208
+
209
+        // Fill the rest with spaces
210
+        while (slen < max_status_chars) { lcd_put_wchar(' '); ++slen; }
211
+      }
212
+    }
213
+    else {
214
+      // String is larger than the available line space
215
+
216
+      // Get a pointer to the next valid UTF8 character
217
+      // and the string remaining length
218
+      uint8_t rlen;
219
+      const char *stat = status_and_len(rlen);
220
+      lcd_put_u8str_max(stat, max_status_chars);
221
+
222
+      // If the string doesn't completely fill the line...
223
+      if (rlen < max_status_chars) {
224
+        lcd_put_wchar('.');                   // Always at 1+ spaces left, draw a dot
225
+        uint8_t chars = max_status_chars - rlen;  // Amount of space left in characters
226
+        if (--chars) {                        // Draw a second dot if there's space
227
+          lcd_put_wchar('.');
228
+          if (--chars)
229
+            lcd_put_u8str_max(status_message, chars); // Print a second copy of the message
230
+        }
231
+      }
232
+
233
+      if (last_blink != blink) {
234
+        last_blink = blink;
235
+        advance_status_scroll();
236
+      }
237
+    }
238
+
239
+  #else
240
+
241
+    UNUSED(blink);
242
+
243
+    if (status_changed()) {
244
+      // Get the UTF8 character count of the string
245
+      uint8_t slen = utf8_strlen(status_message);
246
+
247
+      // Just print the string to the LCD
248
+      lcd_put_u8str_max(status_message, max_status_chars);
249
+
250
+      // Fill the rest with spaces if there are missing spaces
251
+      while (slen < max_status_chars) { lcd_put_wchar(' '); ++slen; }
252
+    }
253
+
254
+  #endif
255
+}
256
+
257
+#if HAS_LCD_MENU
258
+
259
+  #include "../../menu/menu.h"
260
+
261
+  #if ENABLED(ADVANCED_PAUSE_FEATURE)
262
+
263
+    void MarlinUI::draw_hotend_status(const uint8_t row, const uint8_t extruder) {
264
+
265
+      dwin_font.solid = false;
266
+      dwin_font.fg = Color_White;
267
+      dwin_string.set("E");
268
+      dwin_string.add('1' + extruder);
269
+      dwin_string.add(' ');
270
+      dwin_string.add(i16tostr3rj(thermalManager.degHotend(extruder)));
271
+      dwin_string.add('/');
272
+      if (get_blink() || !thermalManager.heater_idle[thermalManager.idle_index_for_id(extruder)].timed_out)
273
+        dwin_string.add(i16tostr3rj(thermalManager.degTargetHotend(extruder)));
274
+      else
275
+        dwin_string.add(PSTR("    "));
276
+
277
+      lcd_moveto(LCD_WIDTH - dwin_string.length(), row);
278
+      lcd_put_dwin_string();
279
+    }
280
+
281
+  #endif
282
+
283
+  // Set the colors for a menu item based on whether it is selected
284
+  static bool mark_as_selected(const uint8_t row, const bool sel, const bool is_static=false) {
285
+    const dwin_coord_t y = row * (MENU_LINE_HEIGHT) + 1;
286
+    if (y >= LCD_PIXEL_HEIGHT) return false;
287
+
288
+    if (is_static && sel)
289
+      DWIN_Draw_Box(1, Color_Bg_Heading, 0, y, LCD_PIXEL_WIDTH, MENU_LINE_HEIGHT - 1);
290
+    else {
291
+      #if ENABLED(MENU_HOLLOW_FRAME)
292
+                 DWIN_Draw_Box(1, Color_Bg_Black, 0, y, LCD_PIXEL_WIDTH, MENU_LINE_HEIGHT - 1);
293
+        if (sel) DWIN_Draw_Box(0, Select_Color,   0, y, LCD_PIXEL_WIDTH, MENU_LINE_HEIGHT - 1);
294
+      #else
295
+        DWIN_Draw_Box(1, sel ? Select_Color : Color_Bg_Black, 0, y, LCD_PIXEL_WIDTH, MENU_LINE_HEIGHT - 1);
296
+      #endif
297
+    }
298
+
299
+    return true;
300
+  }
301
+
302
+  // Draw a static line of text in the same idiom as a menu item
303
+
304
+  void MenuItem_static::draw(const uint8_t row, PGM_P const pstr, const uint8_t style/*=SS_DEFAULT*/, const char * const vstr/*=nullptr*/) {
305
+    // Call mark_as_selected to draw a bigger selection box
306
+    // and draw the text without a background
307
+    if (mark_as_selected(row, (bool)(style & SS_INVERT), true)) {
308
+      ui.set_font(DWIN_FONT_MENU);
309
+      dwin_font.solid = false;
310
+      dwin_font.fg = Color_White;
311
+
312
+      dwin_string.set();
313
+      const int8_t plen = pstr ? utf8_strlen_P(pstr) : 0,
314
+                   vlen = vstr ? utf8_strlen(vstr) : 0;
315
+      if (style & SS_CENTER) {
316
+        int8_t pad = (LCD_WIDTH - 1 - plen - vlen) / 2;
317
+        while (--pad) dwin_string.add(' ');
318
+      }
319
+
320
+      if (plen) dwin_string.add((uint8_t*)pstr, itemIndex, (uint8_t*)itemString);
321
+      if (vlen) dwin_string.add((uint8_t*)vstr);
322
+      if (style & SS_CENTER) {
323
+        int8_t pad = (LCD_WIDTH - 1 - plen - vlen) / 2;
324
+        while (--pad) dwin_string.add(' ');
325
+      }
326
+
327
+      lcd_moveto(1, row);
328
+      lcd_put_dwin_string();
329
+    }
330
+  }
331
+
332
+  // Draw a generic menu item
333
+  void MenuItemBase::_draw(const bool sel, const uint8_t row, PGM_P const pstr, const char, const char post_char) {
334
+    if (mark_as_selected(row, sel)) {
335
+      ui.set_font(DWIN_FONT_MENU);
336
+      dwin_font.solid = false;
337
+      dwin_font.fg = Color_White;
338
+
339
+      dwin_string.set(pstr, itemIndex, itemString);
340
+
341
+      pixel_len_t n = LCD_WIDTH - 1 - dwin_string.length();
342
+      while (--n > 1) dwin_string.add(' ');
343
+
344
+      dwin_string.add(post_char);
345
+
346
+      lcd_moveto(1, row);
347
+      lcd_put_dwin_string();
348
+    }
349
+  }
350
+
351
+  //
352
+  // Draw a menu item with an editable value
353
+  //
354
+  void MenuEditItemBase::draw(const bool sel, const uint8_t row, PGM_P const pstr, const char* const data, const bool pgm) {
355
+    if (mark_as_selected(row, sel)) {
356
+      ui.set_font(DWIN_FONT_MENU);
357
+      dwin_font.solid = false;
358
+      dwin_font.fg = Color_White;
359
+
360
+      const uint8_t vallen = (pgm ? utf8_strlen_P(data) : utf8_strlen(S(data)));
361
+
362
+      dwin_string.set(pstr, itemIndex, itemString);
363
+      if (vallen) dwin_string.add(':');
364
+
365
+      lcd_moveto(1, row);
366
+      lcd_put_dwin_string();
367
+
368
+      if (vallen) {
369
+        dwin_font.fg = Color_Yellow;
370
+        dwin_string.set(data);
371
+        lcd_moveto(LCD_WIDTH - vallen - 1, row);
372
+        lcd_put_dwin_string();
373
+      }
374
+    }
375
+  }
376
+
377
+  //
378
+  // Draw an edit screen with label and current value
379
+  //
380
+  void MenuEditItemBase::draw_edit_screen(PGM_P const pstr, const char* const value/*=nullptr*/) {
381
+    ui.encoder_direction_normal();
382
+
383
+    const dwin_coord_t labellen = utf8_strlen_P(pstr), vallen = utf8_strlen(value);
384
+
385
+    dwin_string.set();
386
+    dwin_string.add((uint8_t*)pstr, itemIndex);
387
+    if (vallen) dwin_string.add(':');  // If a value is included, add a colon
388
+
389
+    // Assume the label is alpha-numeric (with a descender)
390
+    const uint16_t row = (LCD_HEIGHT / 2) - 1;
391
+
392
+    dwin_font.fg = Color_White;
393
+    dwin_font.solid = true;
394
+    lcd_moveto((LCD_WIDTH - labellen + !!vallen) / 2, row);
395
+    lcd_put_dwin_string();
396
+
397
+    // If a value is included, print the value in larger text below the label
398
+    if (vallen) {
399
+      dwin_string.set();
400
+      dwin_string.add(value);
401
+
402
+      const dwin_coord_t by = (row * MENU_LINE_HEIGHT) + MENU_FONT_HEIGHT + EXTRA_ROW_HEIGHT / 2;
403
+      DWIN_Draw_String(true, font16x32, Color_Yellow, Color_Bg_Black, (LCD_PIXEL_WIDTH - vallen * 16) / 2, by, S(dwin_string.string()));
404
+
405
+      extern screenFunc_t _manual_move_func_ptr;
406
+      if (ui.currentScreen != _manual_move_func_ptr && !ui.external_control) {
407
+
408
+        const dwin_coord_t slider_length = LCD_PIXEL_WIDTH - TERN(DWIN_MARLINUI_LANDSCAPE, 120, 20),
409
+                           slider_height = 16,
410
+                           slider_x = (LCD_PIXEL_WIDTH - slider_length) / 2,
411
+                           slider_y = by + 32 + 4,
412
+                           amount = ui.encoderPosition * slider_length / maxEditValue;
413
+
414
+        DWIN_Draw_Rectangle(1, Color_Bg_Window, slider_x - 1, slider_y - 1, slider_x - 1 + slider_length + 2 - 1, slider_y - 1 + slider_height + 2 - 1);
415
+        if (amount > 0)
416
+          DWIN_Draw_Box(1, BarFill_Color, slider_x, slider_y, amount, slider_height);
417
+        if (amount < slider_length)
418
+          DWIN_Draw_Box(1, Color_Bg_Black, slider_x + amount, slider_y, slider_length - amount, slider_height);
419
+      }
420
+    }
421
+  }
422
+
423
+  inline void draw_boxed_string(const bool yesopt, PGM_P const pstr, const bool inv) {
424
+    const uint8_t len = utf8_strlen_P(pstr),
425
+                  mar = TERN(DWIN_MARLINUI_PORTRAIT, 1, 4),
426
+                  col = yesopt ? LCD_WIDTH - mar - len : mar,
427
+                  row = (LCD_HEIGHT >= 8 ? LCD_HEIGHT / 2 + 3 : LCD_HEIGHT - 1);
428
+    lcd_moveto(col, row);
429
+    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);
430
+    lcd_put_u8str_P(col, row, pstr);
431
+  }
432
+
433
+  void MenuItem_confirm::draw_select_screen(
434
+    PGM_P const yes, PGM_P const no, const bool yesno,
435
+    PGM_P const pref, const char * const string/*=nullptr*/, PGM_P const suff/*=nullptr*/
436
+  ) {
437
+    ui.set_font(DWIN_FONT_MENU);
438
+    dwin_font.solid = false;
439
+    dwin_font.fg = Color_White;
440
+    ui.draw_select_screen_prompt(pref, string, suff);
441
+    draw_boxed_string(false, no, !yesno);
442
+    draw_boxed_string(true, yes,  yesno);
443
+  }
444
+
445
+  #if ENABLED(SDSUPPORT)
446
+
447
+    void MenuItem_sdbase::draw(const bool sel, const uint8_t row, PGM_P const, CardReader &theCard, const bool isDir) {
448
+      if (mark_as_selected(row, sel)) {
449
+        dwin_string.set();
450
+
451
+        uint8_t maxlen = LCD_WIDTH - 1;
452
+        if (isDir) {
453
+          dwin_string.add(LCD_STR_FOLDER " ");
454
+          maxlen -= 2;
455
+        }
456
+
457
+        dwin_string.add((uint8_t*)ui.scrolled_filename(theCard, maxlen, row, sel), maxlen);
458
+        uint8_t n = maxlen - dwin_string.length();
459
+        while (n > 0) { dwin_string.add(' '); --n; }
460
+        lcd_moveto(1, row);
461
+        lcd_put_dwin_string();
462
+      }
463
+    }
464
+
465
+  #endif // SDSUPPORT
466
+
467
+  #if ENABLED(AUTO_BED_LEVELING_UBL)
468
+
469
+    /**
470
+     * UBL LCD "radar" map data
471
+     */
472
+    #define MAP_UPPER_LEFT_CORNER_X   5  // These probably should be moved to the .h file  But for now,
473
+    #define MAP_UPPER_LEFT_CORNER_Y   5  // it is easier to play with things having them here
474
+    #define MAP_MAX_PIXELS_X        262  // 272 - 10
475
+    #define MAP_MAX_PIXELS_Y        262
476
+
477
+    void MarlinUI::ubl_plot(const uint8_t x_plot, const uint8_t y_plot) {
478
+      // Scale the box pixels appropriately
479
+      dwin_coord_t x_map_pixels = ((MAP_MAX_PIXELS_X - 4) / (GRID_MAX_POINTS_X)) * (GRID_MAX_POINTS_X),
480
+                   y_map_pixels = ((MAP_MAX_PIXELS_Y - 4) / (GRID_MAX_POINTS_Y)) * (GRID_MAX_POINTS_Y),
481
+
482
+              pixels_per_x_mesh_pnt = x_map_pixels / (GRID_MAX_POINTS_X),
483
+              pixels_per_y_mesh_pnt = y_map_pixels / (GRID_MAX_POINTS_Y),
484
+
485
+              x_offset = MAP_UPPER_LEFT_CORNER_X + 1 + (MAP_MAX_PIXELS_X - x_map_pixels - 2) / 2,
486
+              y_offset = MAP_UPPER_LEFT_CORNER_Y + 1 + (MAP_MAX_PIXELS_Y - y_map_pixels - 2) / 2;
487
+
488
+      // Clear the Mesh Map
489
+
490
+      // First draw the bigger box in White so we have a border around the mesh map box
491
+      DWIN_Draw_Rectangle(1, Color_White, x_offset - 2, y_offset - 2, x_offset + 2 + x_map_pixels, y_offset + 2 + y_map_pixels);
492
+      // Now actually clear the mesh map box
493
+      DWIN_Draw_Rectangle(1, Color_Bg_Black, x_offset, y_offset, x_offset + x_map_pixels, y_offset + y_map_pixels);
494
+
495
+      // Fill in the Specified Mesh Point
496
+
497
+      const uint8_t y_plot_inv = (GRID_MAX_POINTS_Y - 1) - y_plot;  // The origin is typically in the lower right corner.  We need to
498
+                                                                    // invert the Y to get it to plot in the right location.
499
+
500
+      const dwin_coord_t by = y_offset + y_plot_inv * pixels_per_y_mesh_pnt;
501
+      DWIN_Draw_Rectangle(1, Select_Color,
502
+        x_offset + (x_plot * pixels_per_x_mesh_pnt), by,
503
+        x_offset + (x_plot * pixels_per_x_mesh_pnt) + pixels_per_x_mesh_pnt, by + pixels_per_y_mesh_pnt
504
+      );
505
+
506
+      // Display Mesh Point Locations
507
+      const dwin_coord_t sx = x_offset + pixels_per_x_mesh_pnt / 2;
508
+            dwin_coord_t  y = y_offset + pixels_per_y_mesh_pnt / 2;
509
+      for (uint8_t j = 0; j < GRID_MAX_POINTS_Y; j++, y += pixels_per_y_mesh_pnt)
510
+        for (uint8_t i = 0, x = sx; i < GRID_MAX_POINTS_X; i++, x += pixels_per_x_mesh_pnt)
511
+          DWIN_Draw_Point(Color_White, 1, 1, x, y);
512
+
513
+      // Put Relevant Text on Display
514
+
515
+      // Show X and Y positions at top of screen
516
+      dwin_font.fg = Color_White;
517
+      dwin_font.solid = true;
518
+      const xy_pos_t pos = { ubl.mesh_index_to_xpos(x_plot), ubl.mesh_index_to_ypos(y_plot) },
519
+                     lpos = pos.asLogical();
520
+
521
+      lcd_moveto(
522
+        TERN(DWIN_MARLINUI_LANDSCAPE, ((x_offset + x_map_pixels) / MENU_FONT_WIDTH) + 2, 1),
523
+        TERN(DWIN_MARLINUI_LANDSCAPE, 1, ((y_offset + y_map_pixels) / MENU_LINE_HEIGHT) + 1)
524
+      );
525
+      lcd_put_u8str_P(X_LBL);
526
+      lcd_put_u8str(ftostr52(lpos.x));
527
+      lcd_moveto(
528
+        TERN(DWIN_MARLINUI_LANDSCAPE, ((x_offset + x_map_pixels) / MENU_FONT_WIDTH) + 2, 1),
529
+        TERN(DWIN_MARLINUI_LANDSCAPE, 3, ((y_offset + y_map_pixels) / MENU_LINE_HEIGHT) + 2)
530
+      );
531
+      lcd_put_u8str_P(Y_LBL);
532
+      lcd_put_u8str(ftostr52(lpos.y));
533
+
534
+      // Print plot position
535
+      dwin_string.set("(");
536
+      dwin_string.add(i8tostr3rj(x_plot));
537
+      dwin_string.add(",");
538
+      dwin_string.add(i8tostr3rj(y_plot));
539
+      dwin_string.add(")");
540
+      lcd_moveto(
541
+        TERN(DWIN_MARLINUI_LANDSCAPE, ((x_offset + x_map_pixels) / MENU_FONT_WIDTH) + 2, LCD_WIDTH - dwin_string.length()),
542
+        TERN(DWIN_MARLINUI_LANDSCAPE, LCD_HEIGHT - 2, ((y_offset + y_map_pixels) / MENU_LINE_HEIGHT) + 1)
543
+      );
544
+      lcd_put_dwin_string();
545
+
546
+      // Show the location value
547
+      dwin_string.set(Z_LBL);
548
+      if (!isnan(ubl.z_values[x_plot][y_plot]))
549
+        dwin_string.add(ftostr43sign(ubl.z_values[x_plot][y_plot]));
550
+      else
551
+        dwin_string.add(PSTR(" -----"));
552
+      lcd_moveto(
553
+        TERN(DWIN_MARLINUI_LANDSCAPE, ((x_offset + x_map_pixels) / MENU_FONT_WIDTH) + 2, LCD_WIDTH - dwin_string.length()),
554
+        TERN(DWIN_MARLINUI_LANDSCAPE, LCD_HEIGHT - 1, ((y_offset + y_map_pixels) / MENU_LINE_HEIGHT) + 2)
555
+      );
556
+      lcd_put_dwin_string();
557
+    }
558
+
559
+  #endif // AUTO_BED_LEVELING_UBL
560
+
561
+  #if ANY(BABYSTEP_ZPROBE_GFX_OVERLAY, MESH_EDIT_GFX_OVERLAY, BABYSTEP_GFX_OVERLAY)
562
+
563
+    void _lcd_zoffset_overlay_gfx(const float zvalue) {
564
+      // Determine whether the user is raising or lowering the nozzle.
565
+      static int8_t dir;
566
+      static float old_zvalue;
567
+      if (zvalue != old_zvalue) {
568
+        dir = zvalue ? zvalue < old_zvalue ? -1 : 1 : 0;
569
+        old_zvalue = zvalue;
570
+      }
571
+
572
+      const int rot_up = TERN(OVERLAY_GFX_REVERSE, ICON_RotateCCW, ICON_RotateCW),
573
+                rot_down = TERN(OVERLAY_GFX_REVERSE, ICON_RotateCW, ICON_RotateCCW);
574
+
575
+      const int nozzle = (LCD_PIXEL_WIDTH / 2) - 20;
576
+
577
+      // Draw a representation of the nozzle
578
+      DWIN_Draw_Box(1, Color_Bg_Black, nozzle + 3, 8, 48, 52); // 'clear' the area where the nozzle is drawn in case it was moved up/down
579
+      DWIN_ICON_Show(ICON, ICON_HotendOff, nozzle + 3, 10 - dir);
580
+      DWIN_ICON_Show(ICON, ICON_BedLine, nozzle, 10 + 36);
581
+
582
+      // Draw cw/ccw indicator and up/down arrows
583
+      const int arrow_y = LCD_PIXEL_HEIGHT / 2 - 24;
584
+      DWIN_ICON_Show(ICON, ICON_DownArrow, 0, arrow_y - dir);
585
+      DWIN_ICON_Show(ICON, rot_down, 48, arrow_y);
586
+
587
+      DWIN_ICON_Show(ICON, ICON_UpArrow, LCD_PIXEL_WIDTH - 10 - (48*2), arrow_y - dir);
588
+      DWIN_ICON_Show(ICON, rot_up, LCD_PIXEL_WIDTH - 10 - 48, arrow_y);
589
+    }
590
+
591
+  #endif // BABYSTEP_ZPROBE_GFX_OVERLAY || MESH_EDIT_GFX_OVERLAY
592
+
593
+#endif // HAS_LCD_MENU
594
+
595
+#endif // IS_DWIN_MARLINUI

+ 391
- 0
Marlin/src/lcd/e3v2/marlinui/ui_status_480x272.cpp View File

@@ -0,0 +1,391 @@
1
+/**
2
+ * Marlin 3D Printer Firmware
3
+ * Copyright (c) 2021 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
4
+ *
5
+ * Based on Sprinter and grbl.
6
+ * Copyright (c) 2011 Camiel Gubbels / Erik van der Zalm
7
+ *
8
+ * This program is free software: you can redistribute it and/or modify
9
+ * it under the terms of the GNU General Public License as published by
10
+ * the Free Software Foundation, either version 3 of the License, or
11
+ * (at your option) any later version.
12
+ *
13
+ * This program is distributed in the hope that it will be useful,
14
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
15
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16
+ * GNU General Public License for more details.
17
+ *
18
+ * You should have received a copy of the GNU General Public License
19
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
20
+ *
21
+ */
22
+
23
+#include "../../../inc/MarlinConfigPre.h"
24
+
25
+#if IS_DWIN_MARLINUI
26
+
27
+#include "marlinui_dwin.h"
28
+#include "dwin_lcd.h"
29
+#include "dwin_string.h"
30
+#include "lcdprint_dwin.h"
31
+
32
+#include "../../fontutils.h"
33
+#include "../../../libs/numtostr.h"
34
+#include "../../marlinui.h"
35
+
36
+#include "../../../sd/cardreader.h"
37
+#include "../../../module/motion.h"
38
+#include "../../../module/temperature.h"
39
+#include "../../../module/printcounter.h"
40
+
41
+#if ENABLED(SDSUPPORT)
42
+  #include "../../../libs/duration_t.h"
43
+#endif
44
+
45
+#if ENABLED(LCD_SHOW_E_TOTAL)
46
+  #include "../../../MarlinCore.h" // for printingIsActive
47
+#endif
48
+
49
+#define STATUS_HEATERS_X      15
50
+#define STATUS_HEATERS_Y      56
51
+#define STATUS_HEATERS_XSPACE 64
52
+#define STATUS_FAN_WIDTH      48
53
+#define STATUS_FAN_HEIGHT     48
54
+#define STATUS_FAN_Y          STATUS_HEATERS_Y + 22
55
+#define STATUS_CHR_WIDTH      14
56
+#define STATUS_CHR_HEIGHT     28
57
+
58
+//
59
+// Before homing, blink '123' <-> '???'.
60
+// Homed but unknown... '123' <-> '   '.
61
+// Homed and known, display constantly.
62
+//
63
+FORCE_INLINE void _draw_axis_value(const AxisEnum axis, const char *value, const bool blink, const uint16_t x, const uint16_t y) {
64
+  uint8_t vallen = utf8_strlen(value);
65
+
66
+  if (!ui.did_first_redraw) {
67
+    dwin_string.set();
68
+    dwin_string.add('X' + axis);
69
+    DWIN_Draw_String(true, font16x32, Color_IconBlue, Color_Bg_Black, x + (vallen * 14 - 14) / 2, y + 2, S(dwin_string.string()));
70
+  }
71
+
72
+  dwin_string.set();
73
+  if (blink)
74
+    dwin_string.add(value);
75
+  else {
76
+    if (!TEST(axis_homed, axis))
77
+      while (const char c = *value++) dwin_string.add(c <= '.' ? c : '?');
78
+    else {
79
+      #if NONE(HOME_AFTER_DEACTIVATE, DISABLE_REDUCED_ACCURACY_WARNING)
80
+        if (!TEST(axis_trusted, axis))
81
+          dwin_string.add(TERN1(DWIN_MARLINUI_PORTRAIT, axis == Z_AXIS) ? PSTR("       ") : PSTR("    "));
82
+        else
83
+      #endif
84
+          dwin_string.add(value);
85
+    }
86
+  }
87
+
88
+  // For E_TOTAL there may be some characters to cover up
89
+  if (BOTH(DWIN_MARLINUI_PORTRAIT, LCD_SHOW_E_TOTAL) && axis == X_AXIS)
90
+    dwin_string.add("   ");
91
+
92
+  DWIN_Draw_String(true, font14x28, Color_White, Color_Bg_Black, x, y + 32, S(dwin_string.string()));
93
+}
94
+
95
+#if ENABLED(LCD_SHOW_E_TOTAL)
96
+
97
+  FORCE_INLINE void _draw_e_value(const_float_t value, const uint16_t x, const uint16_t y) {
98
+    const uint8_t scale = value >= 100000.0f ? 10 : 1; // show cm after 99,999mm
99
+
100
+    if (!ui.did_first_redraw) {
101
+      // Extra spaces so we don't have to clear the 'Y' label separately
102
+      dwin_string.set("E         ");
103
+      DWIN_Draw_String(true, font16x32, Color_IconBlue, Color_Bg_Black, x + (4 * 14 / 2) - 7, y + 2, S(dwin_string.string()));
104
+    }
105
+
106
+    dwin_string.set(ui16tostr5rj(value / scale));
107
+    DWIN_Draw_String(true, font14x28, Color_White, Color_Bg_Black, x, y + 32, S(dwin_string.string()));
108
+
109
+    // Extra spaces so we don't have to clear out the Y value separately
110
+    DWIN_Draw_String(true, font14x28, Color_IconBlue, Color_Bg_Black, x + (5 * 14), y + 32, S(scale == 1 ? "mm      " : "cm      "));
111
+  }
112
+
113
+#endif
114
+
115
+//
116
+// Fan Icon and Percentage
117
+//
118
+FORCE_INLINE void _draw_fan_status(const uint16_t x, const uint16_t y) {
119
+  const uint16_t fanx = (4 * STATUS_CHR_WIDTH - STATUS_FAN_WIDTH) / 2;
120
+  const uint8_t fan_pct = thermalManager.scaledFanSpeedPercent(0);
121
+  const bool fan_on = !!fan_pct;
122
+  if (fan_on) {
123
+    DWIN_ICON_Animation(0, fan_on, ICON, ICON_Fan0, ICON_Fan3, x + fanx, y, 25);
124
+    dwin_string.set(i8tostr3rj(fan_pct));
125
+    dwin_string.add('%');
126
+    DWIN_Draw_String(true, font14x28, Color_White, Color_Bg_Black, x, y + STATUS_FAN_HEIGHT, S(dwin_string.string()));
127
+  }
128
+  else {
129
+    DWIN_ICON_Show(ICON, ICON_Fan0, x + fanx, y);
130
+    dwin_string.set(PSTR("    "));
131
+    DWIN_Draw_String(true, font14x28, Color_White, Color_Bg_Black, x, y + STATUS_FAN_HEIGHT, S(dwin_string.string()));
132
+  }
133
+}
134
+
135
+#if HOTENDS > 2
136
+  #define HOTEND_STATS 3
137
+#elif HOTENDS > 1
138
+  #define HOTEND_STATS 2
139
+#elif HAS_HOTEND
140
+  #define HOTEND_STATS 1
141
+#endif
142
+
143
+/**
144
+ * Draw a single heater icon with current and target temperature, at the given XY
145
+ */
146
+FORCE_INLINE void _draw_heater_status(const heater_id_t heater, const uint16_t x, const uint16_t y) {
147
+
148
+  #if HAS_HOTEND
149
+    static celsius_t old_temp[HOTEND_STATS] = ARRAY_N_1(HOTEND_STATS, 500),
150
+                     old_target[HOTEND_STATS] = ARRAY_N_1(HOTEND_STATS, 500);
151
+    static bool old_on[HOTEND_STATS] = ARRAY_N_1(HOTEND_STATS, false);
152
+  #endif
153
+
154
+  #if HAS_HEATED_BED
155
+    static celsius_t old_bed_temp = 500, old_bed_target = 500;
156
+    static bool old_bed_on = false;
157
+  #endif
158
+
159
+  #if HAS_HOTEND && HAS_HEATED_BED
160
+    const bool isBed = heater < 0;
161
+    const float tc = (isBed ? thermalManager.degBed()       : thermalManager.degHotend(heater)),
162
+                tt = (isBed ? thermalManager.degTargetBed() : thermalManager.degTargetHotend(heater));
163
+    const uint8_t ta = isBed ? thermalManager.isHeatingBed() : thermalManager.isHeatingHotend(heater);
164
+    const bool c_draw = tc != (isBed ? old_bed_temp : old_temp[heater]),
165
+               t_draw = tt != (isBed ? old_bed_target : old_target[heater]),
166
+               i_draw = ta != (isBed ? old_bed_on : old_on[heater]);
167
+    if (isBed) { old_bed_temp = tc; old_bed_target = tt; old_bed_on = ta; }
168
+    else { old_temp[heater] = tc; old_target[heater] = tt; old_on[heater] = ta; }
169
+  #elif HAS_HOTEND
170
+    constexpr bool isBed = false;
171
+    const float tc = thermalManager.degHotend(heater), tt = thermalManager.degTargetHotend(heater);
172
+    const uint8_t ta = thermalManager.isHeatingHotend(heater);
173
+    const bool c_draw = tc != old_bed_temp, t_draw = tt != old_bed_target, i_draw = ta != old_bed_on;
174
+    old_temp[heater] = tc; old_target[heater] = tt; old_on[heater] = ta;
175
+  #elif HAS_HEATED_BED
176
+    constexpr bool isBed = true;
177
+    const float tc = thermalManager.degBed(), tt = thermalManager.degTargetBed();
178
+    const uint8_t ta = thermalManager.isHeatingBed();
179
+    const bool c_draw = tc != old_temp[heater], t_draw = tt != old_target[heater], i_draw = ta != old_on[heater];
180
+    old_bed_temp = tc; old_bed_target = tt; old_bed_on = ta;
181
+  #endif
182
+
183
+  if (!ui.did_first_redraw || t_draw) {
184
+    dwin_string.set(i16tostr3rj(tt + 0.5));
185
+    dwin_string.add(LCD_STR_DEGREE);
186
+    DWIN_Draw_String(true, font14x28, Color_White, Color_Bg_Black, x, y, S(dwin_string.string()));
187
+  }
188
+
189
+  if (!ui.did_first_redraw || i_draw)
190
+    DWIN_ICON_Show(ICON, (isBed ? ICON_BedOff : ICON_HotendOff) + ta, x, y + STATUS_CHR_HEIGHT + 2);
191
+
192
+  if (!ui.did_first_redraw || c_draw) {
193
+    dwin_string.set(i16tostr3rj(tc + 0.5));
194
+    dwin_string.add(LCD_STR_DEGREE);
195
+    DWIN_Draw_String(true, font14x28, Color_White, Color_Bg_Black, x, y + 70, S(dwin_string.string()));
196
+  }
197
+}
198
+
199
+/**
200
+ * Draw the current "feed rate" percentage preceded by the >> character
201
+ */
202
+FORCE_INLINE void _draw_feedrate_status(const char *value, uint16_t x, uint16_t y) {
203
+  if (!ui.did_first_redraw) {
204
+    dwin_string.set(LCD_STR_FEEDRATE);
205
+    DWIN_Draw_String(true, font14x28, Color_IconBlue, Color_Bg_Black, x, y, S(dwin_string.string()));
206
+  }
207
+
208
+  dwin_string.set(value);
209
+  dwin_string.add(PSTR("%"));
210
+  DWIN_Draw_String(true, font14x28, Color_White, Color_Bg_Black, x + 14, y, S(dwin_string.string()));
211
+}
212
+
213
+/**
214
+ * Draw the MarlinUI Status Screen for Ender 3 V2
215
+ */
216
+void MarlinUI::draw_status_screen() {
217
+  const bool blink = get_blink();
218
+
219
+  // Draw elements that never change
220
+  if (!ui.did_first_redraw) {
221
+    // Logo/Status Icon
222
+    #define STATUS_LOGO_WIDTH  128
223
+    #define STATUS_LOGO_HEIGHT  40
224
+    DWIN_ICON_Show(ICON, ICON_LOGO_Marlin, (LCD_PIXEL_WIDTH - (STATUS_LOGO_WIDTH)) / 2, ((STATUS_HEATERS_Y - 4) - (STATUS_LOGO_HEIGHT)) / 2);
225
+
226
+    // Draw a frame around the x/y/z values
227
+    #if ENABLED(DWIN_MARLINUI_PORTRAIT)
228
+      DWIN_Draw_Rectangle(0, Select_Color, 0, 193, LCD_PIXEL_WIDTH, 260);
229
+    #else
230
+      //DWIN_Draw_Rectangle(0, Select_Color, LCD_PIXEL_WIDTH - 106, 50, LCD_PIXEL_WIDTH - 1, 230);
231
+    #endif
232
+  }
233
+
234
+  uint16_t hx = STATUS_HEATERS_X;
235
+  #if HAS_HOTEND
236
+    _draw_heater_status(H_E0, hx, STATUS_HEATERS_Y);
237
+    hx += STATUS_HEATERS_XSPACE;
238
+  #endif
239
+  #if HAS_MULTI_HOTEND
240
+    _draw_heater_status(H_E1, hx, STATUS_HEATERS_Y);
241
+    hx += STATUS_HEATERS_XSPACE;
242
+  #endif
243
+  #if HAS_HEATED_BED
244
+    _draw_heater_status(H_BED, hx, STATUS_HEATERS_Y);
245
+  #endif
246
+
247
+  #if HAS_FAN
248
+    // Fan display, pinned to the right side
249
+    #if ENABLED(DWIN_MARLINUI_PORTRAIT)
250
+      _draw_fan_status(LCD_PIXEL_WIDTH - STATUS_CHR_WIDTH * 4, STATUS_FAN_Y);
251
+    #else
252
+      _draw_fan_status(212, STATUS_FAN_Y);
253
+    #endif
254
+  #endif
255
+
256
+  // Axis values
257
+  const xyz_pos_t lpos = current_position.asLogical();
258
+  const bool show_e_total = TERN0(LCD_SHOW_E_TOTAL, printingIsActive()); UNUSED(show_e_total);
259
+  #if ENABLED(DWIN_MARLINUI_PORTRAIT)
260
+    constexpr int16_t cpy = 195;
261
+    if (show_e_total) {
262
+      TERN_(LCD_SHOW_E_TOTAL, _draw_e_value(e_move_accumulator, 6, cpy));
263
+    }
264
+    else {
265
+                        _draw_axis_value(X_AXIS, ftostr4sign(lpos.x), blink,  6, cpy);
266
+      TERN_(HAS_Y_AXIS, _draw_axis_value(Y_AXIS, ftostr4sign(lpos.y), blink, 95, cpy));
267
+    }
268
+    TERN_(HAS_Z_AXIS, _draw_axis_value(Z_AXIS, ftostr52sp(lpos.z), blink, 165, cpy));
269
+  #else
270
+    constexpr int16_t cpx = LCD_PIXEL_WIDTH - 104;
271
+                      _draw_axis_value(X_AXIS, ftostr52sp(lpos.x), blink, cpx, STATUS_HEATERS_Y);
272
+    TERN_(HAS_Y_AXIS, _draw_axis_value(Y_AXIS, ftostr52sp(lpos.y), blink, cpx, STATUS_HEATERS_Y + 59));
273
+    TERN_(HAS_Z_AXIS, _draw_axis_value(Z_AXIS, ftostr52sp(lpos.z), blink, cpx, STATUS_HEATERS_Y + 118));
274
+  #endif
275
+
276
+  // Feedrate
277
+  static uint16_t old_fp = 0;
278
+  if (!ui.did_first_redraw || old_fp != feedrate_percentage) {
279
+    old_fp = feedrate_percentage;
280
+    _draw_feedrate_status(i16tostr3rj(feedrate_percentage),
281
+      #if ENABLED(DWIN_MARLINUI_PORTRAIT)
282
+        5, 290
283
+      #else
284
+        294, STATUS_HEATERS_Y
285
+      #endif
286
+    );
287
+  }
288
+
289
+  //
290
+  // Elapsed time
291
+  //
292
+  char buffer[14];
293
+  duration_t time;
294
+
295
+  #if ENABLED(DWIN_MARLINUI_PORTRAIT)
296
+
297
+    // Portrait mode only shows one value at a time, and will rotate if ROTATE_PROGRESS_DISPLAY
298
+    dwin_string.set();
299
+    char prefix = ' ';
300
+    #if ENABLED(SHOW_REMAINING_TIME)
301
+      if (TERN1(ROTATE_PROGRESS_DISPLAY, blink) && print_job_timer.isRunning()) {
302
+        time = get_remaining_time();
303
+        prefix = 'R';
304
+      }
305
+      else
306
+    #endif
307
+        time = print_job_timer.duration();
308
+
309
+    time.toDigital(buffer);
310
+    dwin_string.add(prefix);
311
+    dwin_string.add(buffer);
312
+    DWIN_Draw_String(true, font14x28, Color_White, Color_Bg_Black, (LCD_PIXEL_WIDTH - ((dwin_string.length() + 1) * 14)), 290, S(dwin_string.string()));
313
+
314
+  #else
315
+
316
+    // landscape mode shows both elapsed and remaining (if SHOW_REMAINING_TIME)
317
+    time = print_job_timer.duration();
318
+    time.toDigital(buffer);
319
+    dwin_string.set(" ");
320
+    dwin_string.add(buffer);
321
+    DWIN_Draw_String(true, font14x28, Color_White, Color_Bg_Black, 280, 100, S(dwin_string.string()));
322
+
323
+    #if ENABLED(LCD_SHOW_E_TOTAL)
324
+      if (show_e_total && TERN1(SHOW_REMAINING_TIME, !blink)) { // if SHOW_REMAINING_TIME is also
325
+        const uint8_t escale = e_move_accumulator >= 100000.0f ? 10 : 1; // show cm after 99,000mm
326
+
327
+        DWIN_Draw_String(true, font14x28, Color_IconBlue, Color_Bg_Black, 249, 135, S("E"));
328
+        dwin_string.set(ui16tostr5rj(e_move_accumulator * escale));
329
+        DWIN_Draw_String(true, font14x28, Color_White, Color_Bg_Black, 263, 135, S(dwin_string.string()));
330
+        DWIN_Draw_String(true, font14x28, Color_IconBlue, Color_Bg_Black, 333, 135, S(escale==1 ? "mm" : "cm"));
331
+      }
332
+    #endif
333
+    #if ENABLED(SHOW_REMAINING_TIME)
334
+      if (!show_e_total || blink) {
335
+        DWIN_Draw_String(true, font14x28, Color_IconBlue, Color_Bg_Black, 249, 135, S(" R "));
336
+        time = get_remaining_time();
337
+        time.toDigital(buffer);
338
+        dwin_string.set(buffer);
339
+        DWIN_Draw_String(true, font14x28, Color_White, Color_Bg_Black, 291, 135, S(dwin_string.string()));
340
+      }
341
+    #endif
342
+  #endif
343
+
344
+  //
345
+  // Progress Bar
346
+  //
347
+  constexpr int16_t pb_margin = 5, pb_left = pb_margin, pb_height = 60,
348
+                    pb_right = LCD_PIXEL_WIDTH - TERN(DWIN_MARLINUI_PORTRAIT, 0, 107) - pb_margin,
349
+                    pb_bottom = TERN(DWIN_MARLINUI_PORTRAIT, 410, 230),
350
+                    pb_top = pb_bottom - pb_height,
351
+                    pb_width = pb_right - pb_left;
352
+
353
+  const progress_t progress = TERN(HAS_PRINT_PROGRESS_PERMYRIAD, get_progress_permyriad, get_progress_percent)();
354
+
355
+  if (!ui.did_first_redraw)
356
+    DWIN_Draw_Rectangle(0, Select_Color, pb_left, pb_top, pb_right, pb_bottom);   // Outline
357
+
358
+  static uint16_t old_solid = 50;
359
+  const uint16_t pb_solid = (pb_width - 2) * (progress / (PROGRESS_SCALE)) * 0.01f;
360
+  const bool p_draw = !ui.did_first_redraw || old_solid != pb_solid;
361
+
362
+  if (p_draw) {
363
+    //if (pb_solid)
364
+      DWIN_Draw_Rectangle(1, Select_Color, pb_left + 1, pb_top + 1, pb_left + pb_solid, pb_bottom - 1); // Fill the solid part
365
+
366
+    //if (pb_solid < old_solid)
367
+      DWIN_Draw_Rectangle(1, Color_Bg_Black, pb_left + 1 + pb_solid, pb_top + 1, pb_right - 1, pb_bottom - 1); // Erase the rest
368
+
369
+    #if ENABLED(SHOW_SD_PERCENT)
370
+      dwin_string.set(TERN(PRINT_PROGRESS_SHOW_DECIMALS, permyriadtostr4(progress), ui8tostr3rj(progress / (PROGRESS_SCALE))));
371
+      dwin_string.add(PSTR("%"));
372
+      DWIN_Draw_String(
373
+        false, font16x32, Percent_Color, Color_Bg_Black,
374
+        pb_left + (pb_width - dwin_string.length() * 16) / 2,
375
+        pb_top + (pb_height - 32) / 2,
376
+        S(dwin_string.string())
377
+      );
378
+    #endif
379
+
380
+    old_solid = pb_solid;
381
+  }
382
+
383
+  //
384
+  // Status Message
385
+  //
386
+  draw_status_message(blink);
387
+
388
+  ui.did_first_redraw = true;
389
+}
390
+
391
+#endif // IS_DWIN_MARLINUI

+ 1
- 1
Marlin/src/lcd/lcdprint.cpp View File

@@ -26,7 +26,7 @@
26 26
 
27 27
 #include "../inc/MarlinConfigPre.h"
28 28
 
29
-#if HAS_WIRED_LCD && !HAS_GRAPHICAL_TFT
29
+#if HAS_WIRED_LCD && !HAS_GRAPHICAL_TFT && !IS_DWIN_MARLINUI
30 30
 
31 31
 #include "marlinui.h"
32 32
 #include "lcdprint.h"

+ 19
- 2
Marlin/src/lcd/lcdprint.h View File

@@ -34,7 +34,21 @@
34 34
 
35 35
 #include "../inc/MarlinConfig.h"
36 36
 
37
-#if HAS_MARLINUI_U8GLIB
37
+#if IS_DWIN_MARLINUI
38
+
39
+  #include "e3v2/marlinui/marlinui_dwin.h"
40
+
41
+  #define LCD_PIXEL_WIDTH     DWIN_WIDTH
42
+  #define LCD_PIXEL_HEIGHT    DWIN_HEIGHT
43
+  #define LCD_WIDTH           ((LCD_PIXEL_WIDTH)  / (MENU_FONT_WIDTH))
44
+  #define LCD_HEIGHT          ((LCD_PIXEL_HEIGHT) / (MENU_LINE_HEIGHT))
45
+
46
+  // The DWIN lcd_moveto function uses row / column, not pixels
47
+  #define LCD_COL_X(col)    (col)
48
+  #define LCD_ROW_Y(row)    (row)
49
+  #define LCD_COL_X_RJ(len) (LCD_WIDTH - LCD_COL_X(len))
50
+
51
+#elif HAS_MARLINUI_U8GLIB
38 52
 
39 53
   #include "dogm/u8g_fontutf8.h"
40 54
   typedef u8g_uint_t lcd_uint_t;
@@ -105,7 +119,10 @@
105 119
   #define MENU_LINE_HEIGHT MENU_FONT_HEIGHT
106 120
 #endif
107 121
 
108
-#define LCD_COL_X_RJ(len)      (LCD_PIXEL_WIDTH - LCD_COL_X(len))
122
+#ifndef LCD_COL_X_RJ
123
+  #define LCD_COL_X_RJ(len)    (LCD_PIXEL_WIDTH - LCD_COL_X(len))
124
+#endif
125
+
109 126
 #define SETCURSOR(col, row)    lcd_moveto(LCD_COL_X(col), LCD_ROW_Y(row))
110 127
 #define SETCURSOR_RJ(len, row) lcd_moveto(LCD_COL_X_RJ(len), LCD_ROW_Y(row))
111 128
 #define SETCURSOR_X(col)       SETCURSOR(col, _lcdLineNr)

+ 8
- 0
Marlin/src/lcd/marlinui.cpp View File

@@ -202,6 +202,10 @@ constexpr uint8_t epps = ENCODER_PULSES_PER_STEP;
202 202
     bool MarlinUI::drawing_screen, MarlinUI::first_page; // = false
203 203
   #endif
204 204
 
205
+  #if IS_DWIN_MARLINUI
206
+    bool MarlinUI::did_first_redraw;
207
+  #endif
208
+
205 209
   // Encoder Handling
206 210
   #if HAS_ENCODER_ACTION
207 211
     uint32_t MarlinUI::encoderPosition;
@@ -335,6 +339,7 @@ constexpr uint8_t epps = ENCODER_PULSES_PER_STEP;
335 339
           col = (LCD_WIDTH - plen - slen) / 2;
336 340
           row = LCD_HEIGHT > 3 ? 1 : 0;
337 341
         }
342
+        if (LCD_HEIGHT >= 8) row = LCD_HEIGHT / 2 - 2;
338 343
         wrap_string_P(col, row, pref, true);
339 344
         if (string) {
340 345
           if (col) { col = 0; row++; } // Move to the start of the next line
@@ -1073,6 +1078,9 @@ constexpr uint8_t epps = ENCODER_PULSES_PER_STEP;
1073 1078
 
1074 1079
           run_current_screen();
1075 1080
 
1081
+          // Apply all DWIN drawing after processing
1082
+          TERN_(IS_DWIN_MARLINUI, DWIN_UpdateLCD());
1083
+
1076 1084
         #endif
1077 1085
 
1078 1086
         TERN_(HAS_LCD_MENU, lcd_clicked = false);

+ 15
- 11
Marlin/src/lcd/marlinui.h View File

@@ -387,22 +387,22 @@ public:
387 387
       #endif
388 388
 
389 389
       #if HAS_MARLINUI_U8GLIB
390
-
391 390
         static void set_font(const MarlinFont font_nr);
391
+      #elif IS_DWIN_MARLINUI
392
+        static void set_font(const uint8_t font_nr);
393
+      #endif
392 394
 
393
-      #else
394
-
395
+      #if HAS_MARLINUI_HD44780
395 396
         static void set_custom_characters(const HD44780CharSet screen_charset=CHARSET_INFO);
397
+      #endif
396 398
 
397
-        #if ENABLED(LCD_PROGRESS_BAR)
398
-          static millis_t progress_bar_ms;  // Start time for the current progress bar cycle
399
-          static void draw_progress_bar(const uint8_t percent);
400
-          #if PROGRESS_MSG_EXPIRE > 0
401
-            static millis_t expire_status_ms; // = 0
402
-            FORCE_INLINE static void reset_progress_bar_timeout() { expire_status_ms = 0; }
403
-          #endif
399
+      #if ENABLED(LCD_PROGRESS_BAR) && !HAS_MARLINUI_U8GLIB
400
+        static millis_t progress_bar_ms;  // Start time for the current progress bar cycle
401
+        static void draw_progress_bar(const uint8_t percent);
402
+        #if PROGRESS_MSG_EXPIRE > 0
403
+          static millis_t expire_status_ms; // = 0
404
+          FORCE_INLINE static void reset_progress_bar_timeout() { expire_status_ms = 0; }
404 405
         #endif
405
-
406 406
       #endif
407 407
 
408 408
       static uint8_t lcd_status_update_delay;
@@ -447,6 +447,10 @@ public:
447 447
       static constexpr bool drawing_screen = false, first_page = true;
448 448
     #endif
449 449
 
450
+    #if IS_DWIN_MARLINUI
451
+      static bool did_first_redraw;
452
+    #endif
453
+
450 454
     static bool get_blink();
451 455
     static void kill_screen(PGM_P const lcd_error, PGM_P const lcd_component);
452 456
     static void draw_kill_screen();

+ 2
- 0
Marlin/src/lcd/menu/menu.cpp View File

@@ -179,6 +179,8 @@ bool printer_busy() {
179 179
 void MarlinUI::goto_screen(screenFunc_t screen, const uint16_t encoder/*=0*/, const uint8_t top/*=0*/, const uint8_t items/*=0*/) {
180 180
   if (currentScreen != screen) {
181 181
 
182
+    TERN_(IS_DWIN_MARLINUI, did_first_redraw = false);
183
+
182 184
     TERN_(HAS_TOUCH_BUTTONS, repeat_delay = BUTTON_DELAY_MENU);
183 185
 
184 186
     TERN_(LCD_SET_PROGRESS_MANUALLY, progress_reset());

+ 1
- 1
Marlin/src/lcd/menu/menu.h View File

@@ -39,7 +39,7 @@ typedef void (*selectFunc_t)();
39 39
 #define SS_INVERT  0x02
40 40
 #define SS_DEFAULT SS_CENTER
41 41
 
42
-#if HAS_MARLINUI_U8GLIB && EITHER(BABYSTEP_ZPROBE_GFX_OVERLAY, MESH_EDIT_GFX_OVERLAY)
42
+#if EITHER(HAS_MARLINUI_U8GLIB, IS_DWIN_MARLINUI) && EITHER(BABYSTEP_ZPROBE_GFX_OVERLAY, MESH_EDIT_GFX_OVERLAY)
43 43
   void _lcd_zoffset_overlay_gfx(const_float_t zvalue);
44 44
 #endif
45 45
 

+ 2
- 2
Marlin/src/pins/stm32f1/pins_CREALITY_V4.h View File

@@ -184,7 +184,7 @@
184 184
   #define BTN_EN1                           PB10
185 185
   #define BTN_EN2                           PA6
186 186
 
187
-#elif ENABLED(DWIN_CREALITY_LCD)
187
+#elif EITHER(DWIN_CREALITY_LCD, IS_DWIN_MARLINUI)
188 188
 
189 189
   // RET6 DWIN ENCODER LCD
190 190
   #define BTN_ENC                           PB14
@@ -194,7 +194,7 @@
194 194
   //#define LCD_LED_PIN                     PB2
195 195
   #ifndef BEEPER_PIN
196 196
     #define BEEPER_PIN                      PB13
197
-    #undef SPEAKER
197
+    //#undef SPEAKER
198 198
   #endif
199 199
 
200 200
 #elif ENABLED(DWIN_VET6_CREALITY_LCD)

+ 64
- 0
buildroot/share/fonts/buildhzk.py View File

@@ -0,0 +1,64 @@
1
+# Generate a 'HZK' font file for the T5UIC1 DWIN LCD
2
+# from multiple bdf font files.
3
+# Note: the 16x16 glyphs are not produced
4
+# Author: Taylor Talkington
5
+# License: GPL
6
+
7
+import bdflib.reader
8
+import math
9
+
10
+def glyph_bits(size_x, size_y, font, glyph_ord):
11
+    asc = font[b'FONT_ASCENT']
12
+    desc = font[b'FONT_DESCENT']
13
+    bits = [0 for y in range(size_y)]
14
+
15
+    glyph_bytes = math.ceil(size_x / 8)
16
+    try:
17
+        glyph = font[glyph_ord]
18
+        for y, row in enumerate(glyph.data):
19
+            v = row
20
+            rpad = size_x - glyph.bbW
21
+            if rpad < 0: rpad = 0
22
+            if glyph.bbW > size_x: v = v >> (glyph.bbW - size_x) # some glyphs are actually too wide to fit!
23
+            v = v << (glyph_bytes * 8) - size_x + rpad
24
+            v = v >> glyph.bbX
25
+            bits[y + desc + glyph.bbY] |= v
26
+    except KeyError:
27
+        pass
28
+
29
+    bits.reverse()
30
+    return bits
31
+
32
+def marlin_font_hzk():
33
+    fonts = [
34
+        [6,12,'marlin-6x12-3.bdf'],
35
+        [8,16,'marlin-8x16.bdf'],
36
+        [10,20,'marlin-10x20.bdf'],
37
+        [12,24,'marlin-12x24.bdf'],
38
+        [14,28,'marlin-14x28.bdf'],
39
+        [16,32,'marlin-16x32.bdf'],
40
+        [20,40,'marlin-20x40.bdf'],
41
+        [24,48,'marlin-24x48.bdf'],
42
+        [28,56,'marlin-28x56.bdf'],
43
+        [32,64,'marlin-32x64.bdf']
44
+    ]
45
+
46
+    with open('marlin_fixed.hzk','wb') as output:
47
+        for f in fonts:
48
+            with open(f[2], 'rb') as file:
49
+                print(f'{f[0]}x{f[1]}')
50
+                font = bdflib.reader.read_bdf(file)
51
+                for glyph in range(128):
52
+                    bits = glyph_bits(f[0], f[1], font, glyph)
53
+                    glyph_bytes = math.ceil(f[0]/8)
54
+
55
+                    for b in bits:
56
+                        try:
57
+                            z = b.to_bytes(glyph_bytes, 'big')
58
+                            output.write(z)
59
+                        except OverflowError:
60
+                            print('Overflow')
61
+                            print(f'{glyph}')
62
+                            print(font[glyph])
63
+                            for b in bits: print(f'{b:0{f[0]}b}')
64
+                            return

+ 4104
- 0
buildroot/share/fonts/marlin-10x20.bdf
File diff suppressed because it is too large
View File


+ 4558
- 0
buildroot/share/fonts/marlin-12x24.bdf
File diff suppressed because it is too large
View File


+ 5078
- 0
buildroot/share/fonts/marlin-14x28.bdf
File diff suppressed because it is too large
View File


+ 5492
- 0
buildroot/share/fonts/marlin-16x32.bdf
File diff suppressed because it is too large
View File


+ 6458
- 0
buildroot/share/fonts/marlin-20x40.bdf
File diff suppressed because it is too large
View File


+ 6462
- 0
buildroot/share/fonts/marlin-24x48.bdf
File diff suppressed because it is too large
View File


+ 7311
- 0
buildroot/share/fonts/marlin-28x56.bdf
File diff suppressed because it is too large
View File


+ 9870
- 0
buildroot/share/fonts/marlin-32x64.bdf
File diff suppressed because it is too large
View File


+ 3701
- 0
buildroot/share/fonts/marlin-8x16.bdf
File diff suppressed because it is too large
View File


+ 2
- 4
buildroot/tests/STM32F103RET6_creality View File

@@ -13,11 +13,9 @@ use_example_configs "Creality/Ender-3 V2/CrealityUI"
13 13
 opt_enable MARLIN_DEV_MODE BUFFER_MONITORING
14 14
 exec_test $1 $2 "Ender 3 v2 with CrealityUI" "$3"
15 15
 
16
-use_example_configs "Creality/Ender-3 V2/CrealityUI"
17
-opt_disable CLASSIC_JERK
16
+use_example_configs "Creality/Ender-3 V2/MarlinUI"
18 17
 opt_add SDCARD_EEPROM_EMULATION
19
-opt_set TEMP_SENSOR_BED 0
20
-exec_test $1 $2 "Ender 3 v2, SD EEPROM, no CLASSIC_JERK, no Bed" "$3"
18
+exec_test $1 $2 "Ender 3 v2 with MarlinUI" "$3"
21 19
 
22 20
 restore_configs
23 21
 opt_set MOTHERBOARD BOARD_CREALITY_V452 SERIAL_PORT 1

+ 1
- 0
ini/features.ini View File

@@ -45,6 +45,7 @@ I2C_EEPROM                             = src_filter=+<src/HAL/shared/eeprom_if_i
45 45
 SOFT_I2C_EEPROM                        = SlowSoftI2CMaster, SlowSoftWire=https://github.com/felias-fogg/SlowSoftWire/archive/master.zip
46 46
 SPI_EEPROM                             = src_filter=+<src/HAL/shared/eeprom_if_spi.cpp>
47 47
 DWIN_CREALITY_LCD                      = src_filter=+<src/lcd/e3v2/creality>
48
+DWIN_MARLINUI_.+                       = src_filter=+<src/lcd/e3v2/marlinui>
48 49
 HAS_GRAPHICAL_TFT                      = src_filter=+<src/lcd/tft>
49 50
 IS_TFTGLCD_PANEL                       = src_filter=+<src/lcd/TFTGLCD>
50 51
 HAS_TOUCH_BUTTONS                      = src_filter=+<src/lcd/touch/touch_buttons.cpp>

+ 2
- 1
platformio.ini View File

@@ -48,7 +48,8 @@ extra_scripts      =
48 48
   post:buildroot/share/PlatformIO/scripts/common-dependencies-post.py
49 49
 lib_deps           =
50 50
 default_src_filter = +<src/*> -<src/config> -<src/HAL> +<src/HAL/shared>
51
-  -<src/lcd/HD44780> -<src/lcd/TFTGLCD> -<src/lcd/e3v2/creality> -<src/lcd/dogm> -<src/lcd/tft> -<src/lcd/tft_io>
51
+  -<src/lcd/HD44780> -<src/lcd/TFTGLCD> -<src/lcd/dogm> -<src/lcd/tft> -<src/lcd/tft_io>
52
+  -<src/lcd/e3v2/creality> -<src/lcd/e3v2/marlinui>
52 53
   -<src/HAL/STM32/tft> -<src/HAL/STM32F1/tft>
53 54
   -<src/lcd/menu>
54 55
   -<src/lcd/menu/game/game.cpp> -<src/lcd/menu/game/brickout.cpp> -<src/lcd/menu/game/invaders.cpp>

Loading…
Cancel
Save