My Marlin configs for Fabrikator Mini and CTC i3 Pro B
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

dwinui.cpp 14KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454
  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. * DWIN UI Enhanced implementation
  24. * Author: Miguel A. Risco-Castillo
  25. * Version: 3.6.3
  26. * Date: 2021/09/08
  27. */
  28. #include "../../../inc/MarlinConfigPre.h"
  29. #if ENABLED(DWIN_CREALITY_LCD_ENHANCED)
  30. #include "../../../inc/MarlinConfig.h"
  31. #include "../../../core/macros.h"
  32. #include "dwin_lcd.h"
  33. #include "dwinui.h"
  34. //#define DEBUG_OUT 1
  35. #include "../../../core/debug_out.h"
  36. uint8_t MenuItemTotal = 0;
  37. uint8_t MenuItemCount = 0;
  38. MenuItemClass** MenuItems = nullptr;
  39. MenuClass *CurrentMenu = nullptr;
  40. MenuClass *PreviousMenu = nullptr;
  41. xy_int_t DWINUI::cursor = { 0 };
  42. uint16_t DWINUI::pencolor = Color_White;
  43. uint16_t DWINUI::textcolor = Def_Text_Color;
  44. uint16_t DWINUI::backcolor = Def_Background_Color;
  45. uint8_t DWINUI::font = font8x16;
  46. void (*DWINUI::onCursorErase)(uint8_t line)=nullptr;
  47. void (*DWINUI::onCursorDraw)(uint8_t line)=nullptr;
  48. void (*DWINUI::onTitleDraw)(TitleClass* title)=nullptr;
  49. void (*DWINUI::onMenuDraw)(MenuClass* menu)=nullptr;
  50. void DWINUI::init() {
  51. DEBUG_ECHOPGM("\r\nDWIN handshake ");
  52. delay(750); // Delay here or init later in the boot process
  53. const bool success = DWIN_Handshake();
  54. if (success) DEBUG_ECHOLNPGM("ok."); else DEBUG_ECHOLNPGM("error.");
  55. DWIN_Frame_SetDir(1);
  56. TERN(SHOW_BOOTSCREEN,,DWIN_Frame_Clear(Color_Bg_Black));
  57. DWIN_UpdateLCD();
  58. cursor.x = 0;
  59. cursor.y = 0;
  60. pencolor = Color_White;
  61. textcolor = Def_Text_Color;
  62. backcolor = Def_Background_Color;
  63. font = font8x16;
  64. }
  65. // Set text/number font
  66. void DWINUI::setFont(uint8_t cfont) {
  67. font = cfont;
  68. }
  69. // Get font character width
  70. uint8_t DWINUI::fontWidth(uint8_t cfont) {
  71. switch (cfont) {
  72. case font6x12 : return 6;
  73. case font8x16 : return 8;
  74. case font10x20: return 10;
  75. case font12x24: return 12;
  76. case font14x28: return 14;
  77. case font16x32: return 16;
  78. case font20x40: return 20;
  79. case font24x48: return 24;
  80. case font28x56: return 28;
  81. case font32x64: return 32;
  82. default: return 0;
  83. }
  84. }
  85. // Get font character heigh
  86. uint8_t DWINUI::fontHeight(uint8_t cfont) {
  87. switch (cfont) {
  88. case font6x12 : return 12;
  89. case font8x16 : return 16;
  90. case font10x20: return 20;
  91. case font12x24: return 24;
  92. case font14x28: return 28;
  93. case font16x32: return 32;
  94. case font20x40: return 40;
  95. case font24x48: return 48;
  96. case font28x56: return 56;
  97. case font32x64: return 64;
  98. default: return 0;
  99. }
  100. }
  101. // Get screen x coodinates from text column
  102. uint16_t DWINUI::ColToX(uint8_t col) {
  103. return col * fontWidth(font);
  104. }
  105. // Get screen y coodinates from text row
  106. uint16_t DWINUI::RowToY(uint8_t row) {
  107. return row * fontHeight(font);
  108. }
  109. // Set text/number color
  110. void DWINUI::SetColors(uint16_t fgcolor, uint16_t bgcolor) {
  111. textcolor = fgcolor;
  112. backcolor = bgcolor;
  113. }
  114. void DWINUI::SetTextColor(uint16_t fgcolor) {
  115. textcolor = fgcolor;
  116. }
  117. void DWINUI::SetBackgroundColor(uint16_t bgcolor) {
  118. backcolor = bgcolor;
  119. }
  120. // Moves cursor to point
  121. // x: abscissa of the display
  122. // y: ordinate of the display
  123. // point: xy coordinate
  124. void DWINUI::MoveTo(int16_t x, int16_t y) {
  125. cursor.x = x;
  126. cursor.y = y;
  127. }
  128. void DWINUI::MoveTo(xy_int_t point) {
  129. cursor = point;
  130. }
  131. // Moves cursor relative to the actual position
  132. // x: abscissa of the display
  133. // y: ordinate of the display
  134. // point: xy coordinate
  135. void DWINUI::MoveBy(int16_t x, int16_t y) {
  136. cursor.x += x;
  137. cursor.y += y;
  138. }
  139. void DWINUI::MoveBy(xy_int_t point) {
  140. cursor += point;
  141. }
  142. // Draw a Centered string using DWIN_WIDTH
  143. void DWINUI::Draw_CenteredString(bool bShow, uint8_t size, uint16_t color, uint16_t bColor, uint16_t y, const char * const string) {
  144. const int8_t x = _MAX(0U, DWIN_WIDTH - strlen_P(string) * fontWidth(size)) / 2 - 1;
  145. DWIN_Draw_String(bShow, size, color, bColor, x, y, string);
  146. }
  147. // Draw a char at cursor position
  148. void DWINUI::Draw_Char(const char c) {
  149. const char string[2] = { c, 0};
  150. DWIN_Draw_String(false, font, textcolor, backcolor, cursor.x, cursor.y, string, 1);
  151. MoveBy(fontWidth(font), 0);
  152. }
  153. // Draw a string at cursor position
  154. // color: Character color
  155. // *string: The string
  156. // rlimit: For draw less chars than string length use rlimit
  157. void DWINUI::Draw_String(const char * const string, uint16_t rlimit) {
  158. DWIN_Draw_String(false, font, textcolor, backcolor, cursor.x, cursor.y, string, rlimit);
  159. MoveBy(strlen(string) * fontWidth(font), 0);
  160. }
  161. void DWINUI::Draw_String(uint16_t color, const char * const string, uint16_t rlimit) {
  162. DWIN_Draw_String(false, font, color, backcolor, cursor.x, cursor.y, string, rlimit);
  163. MoveBy(strlen(string) * fontWidth(font), 0);
  164. }
  165. // Draw a signed floating point number
  166. // bShow: true=display background color; false=don't display background color
  167. // zeroFill: true=zero fill; false=no zero fill
  168. // zeroMode: 1=leading 0 displayed as 0; 0=leading 0 displayed as a space
  169. // size: Font size
  170. // bColor: Background color
  171. // iNum: Number of whole digits
  172. // fNum: Number of decimal digits
  173. // x/y: Upper-left point
  174. // value: Float value
  175. void DWINUI::Draw_Signed_Float(uint8_t bShow, bool zeroFill, uint8_t zeroMode, uint8_t size, uint16_t color, uint16_t bColor, uint8_t iNum, uint8_t fNum, uint16_t x, uint16_t y, float value) {
  176. DWIN_Draw_FloatValue(bShow, zeroFill, zeroMode, size, color, bColor, iNum, fNum, x, y, value < 0 ? -value : value);
  177. DWIN_Draw_String(bShow, size, color, bColor, x - 6, y, value < 0 ? F("-") : F(" "));
  178. }
  179. // Draw a circle
  180. // color: circle color
  181. // x: the abscissa of the center of the circle
  182. // y: ordinate of the center of the circle
  183. // r: circle radius
  184. void DWINUI::Draw_Circle(uint16_t color, uint16_t x, uint16_t y, uint8_t r) {
  185. int a = 0, b = 0;
  186. while (a <= b) {
  187. b = SQRT(sq(r) - sq(a));
  188. if (a == 0) b--;
  189. DWIN_Draw_Point(color, 1, 1, x + a, y + b); // Draw some sector 1
  190. DWIN_Draw_Point(color, 1, 1, x + b, y + a); // Draw some sector 2
  191. DWIN_Draw_Point(color, 1, 1, x + b, y - a); // Draw some sector 3
  192. DWIN_Draw_Point(color, 1, 1, x + a, y - b); // Draw some sector 4
  193. DWIN_Draw_Point(color, 1, 1, x - a, y - b); // Draw some sector 5
  194. DWIN_Draw_Point(color, 1, 1, x - b, y - a); // Draw some sector 6
  195. DWIN_Draw_Point(color, 1, 1, x - b, y + a); // Draw some sector 7
  196. DWIN_Draw_Point(color, 1, 1, x - a, y + b); // Draw some sector 8
  197. a++;
  198. }
  199. }
  200. // Draw a circle filled with color
  201. // bcolor: fill color
  202. // x: the abscissa of the center of the circle
  203. // y: ordinate of the center of the circle
  204. // r: circle radius
  205. void DWINUI::Draw_FillCircle(uint16_t bcolor, uint16_t x,uint16_t y,uint8_t r) {
  206. int a = 0, b = 0;
  207. while (a <= b) {
  208. b = SQRT(sq(r) - sq(a)); // b=sqrt(r*r-a*a);
  209. if (a == 0) b--;
  210. DWIN_Draw_Line(bcolor, x-b,y-a,x+b,y-a);
  211. DWIN_Draw_Line(bcolor, x-a,y-b,x+a,y-b);
  212. DWIN_Draw_Line(bcolor, x-b,y+a,x+b,y+a);
  213. DWIN_Draw_Line(bcolor, x-a,y+b,x+a,y+b);
  214. a++;
  215. }
  216. }
  217. // Color Interpolator
  218. // val : Interpolator minv..maxv
  219. // minv : Minimum value
  220. // maxv : Maximum value
  221. // color1 : Start color
  222. // color2 : End color
  223. uint16_t DWINUI::ColorInt(int16_t val, int16_t minv, int16_t maxv, uint16_t color1, uint16_t color2) {
  224. uint8_t B,G,R;
  225. float n;
  226. n = (float)(val-minv)/(maxv-minv);
  227. R = (1-n)*GetRColor(color1) + n*GetRColor(color2);
  228. G = (1-n)*GetGColor(color1) + n*GetGColor(color2);
  229. B = (1-n)*GetBColor(color1) + n*GetBColor(color2);
  230. return RGB(R,G,B);
  231. }
  232. // Color Interpolator through Red->Yellow->Green->Blue
  233. // val : Interpolator minv..maxv
  234. // minv : Minimum value
  235. // maxv : Maximum value
  236. uint16_t DWINUI::RainbowInt(int16_t val, int16_t minv, int16_t maxv) {
  237. uint8_t B,G,R;
  238. const uint8_t maxB = 28;
  239. const uint8_t maxR = 28;
  240. const uint8_t maxG = 38;
  241. const int16_t limv = _MAX(abs(minv), abs(maxv));
  242. float n;
  243. if (minv>=0) {
  244. n = (float)(val-minv)/(maxv-minv);
  245. } else {
  246. n = (float)val/limv;
  247. }
  248. n = _MIN(1, n);
  249. n = _MAX(-1, n);
  250. if (n < 0) {
  251. R = 0;
  252. G = (1+n)*maxG;
  253. B = (-n)*maxB;
  254. } else if (n < 0.5) {
  255. R = maxR*n*2;
  256. G = maxG;
  257. B = 0;
  258. } else {
  259. R = maxR;
  260. G = maxG*(1-n);
  261. B = 0;
  262. }
  263. return RGB(R,G,B);
  264. }
  265. // Draw a checkbox
  266. // Color: frame color
  267. // bColor: Background color
  268. // x/y: Upper-left point
  269. // mode : 0 : unchecked, 1 : checked
  270. void DWINUI::Draw_Checkbox(uint16_t color, uint16_t bcolor, uint16_t x, uint16_t y, bool checked=false) {
  271. DWIN_Draw_String(true, font8x16, color, bcolor, x + 4, y, checked ? F("x") : F(" "));
  272. DWIN_Draw_Rectangle(0, color, x + 2, y + 2, x + 17, y + 17);
  273. }
  274. // Clear Menu by filling the menu area with background color
  275. void DWINUI::ClearMenuArea() {
  276. DWIN_Draw_Rectangle(1, backcolor, 0, TITLE_HEIGHT, DWIN_WIDTH - 1, STATUS_Y - 1);
  277. }
  278. void DWINUI::MenuItemsClear() {
  279. if (MenuItems == nullptr) return;
  280. for (uint8_t i = 0; i < MenuItemCount; i++) delete MenuItems[i];
  281. delete[] MenuItems;
  282. MenuItems = nullptr;
  283. MenuItemCount = 0;
  284. MenuItemTotal = 0;
  285. }
  286. void DWINUI::MenuItemsPrepare(uint8_t totalitems) {
  287. MenuItemsClear();
  288. MenuItemTotal = totalitems;
  289. MenuItems = new MenuItemClass*[totalitems];
  290. }
  291. MenuItemClass* DWINUI::MenuItemsAdd(MenuItemClass* menuitem) {
  292. if (MenuItemCount < MenuItemTotal) {
  293. MenuItems[MenuItemCount] = menuitem;
  294. menuitem->pos = MenuItemCount++;
  295. return menuitem;
  296. }
  297. else {
  298. delete menuitem;
  299. return nullptr;
  300. }
  301. }
  302. /* Title Class ==============================================================*/
  303. TitleClass Title;
  304. void TitleClass::draw() {
  305. if (DWINUI::onTitleDraw != nullptr) (*DWINUI::onTitleDraw)(this);
  306. }
  307. void TitleClass::SetCaption(const char * const title) {
  308. frameid = 0;
  309. if ( caption == title ) return;
  310. const uint8_t len = _MIN(sizeof(caption) - 1, strlen(title));
  311. memcpy(&caption[0], title, len);
  312. caption[len] = '\0';
  313. }
  314. void TitleClass::ShowCaption(const char * const title) {
  315. SetCaption(title);
  316. draw();
  317. }
  318. void TitleClass::SetFrame(uint8_t id, uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2) {
  319. caption[0] = '\0';
  320. frameid = id;
  321. frame = { x1, y1, x2, y2 };
  322. }
  323. void TitleClass::SetFrame(uint16_t x, uint16_t y, uint16_t w, uint16_t h) {
  324. SetFrame(1, x, y, x + w - 1, y + h - 1);
  325. }
  326. void TitleClass::FrameCopy(uint8_t id, uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2) {
  327. SetFrame(id, x1, y1, x2, y2);
  328. draw();
  329. }
  330. void TitleClass::FrameCopy(uint16_t x, uint16_t y, uint16_t w, uint16_t h) {
  331. FrameCopy(1, x, y, x + w - 1, y + h - 1);
  332. }
  333. /* Menu Class ===============================================================*/
  334. MenuClass::MenuClass() {
  335. selected = 0;
  336. topline = 0;
  337. }
  338. void MenuClass::draw() {
  339. MenuTitle.draw();
  340. if (DWINUI::onMenuDraw != nullptr) (*DWINUI::onMenuDraw)(this);
  341. for (uint8_t i = 0; i < MenuItemCount; i++)
  342. MenuItems[i]->draw(i - topline);
  343. if (DWINUI::onCursorDraw != nullptr) DWINUI::onCursorDraw(line());
  344. DWIN_UpdateLCD();
  345. }
  346. void MenuClass::onScroll(bool dir) {
  347. int8_t sel = selected;
  348. if (dir) sel++; else sel--;
  349. LIMIT(sel, 0, MenuItemCount - 1);
  350. if (sel != selected) {
  351. if (DWINUI::onCursorErase != nullptr) DWINUI::onCursorErase(line());
  352. if ((sel - topline) == TROWS) {
  353. DWIN_Frame_AreaMove(1, DWIN_SCROLL_UP, MLINE, DWINUI::backcolor, 0, TITLE_HEIGHT + 1, DWIN_WIDTH, STATUS_Y - 1);
  354. topline++;
  355. MenuItems[sel]->draw(TROWS - 1);
  356. }
  357. if ((sel < topline)) {
  358. DWIN_Frame_AreaMove(1, DWIN_SCROLL_DOWN, MLINE, DWINUI::backcolor, 0, TITLE_HEIGHT + 1, DWIN_WIDTH, STATUS_Y - 1);
  359. topline--;
  360. MenuItems[sel]->draw(0);
  361. }
  362. selected = sel;
  363. if (DWINUI::onCursorDraw != nullptr) DWINUI::onCursorDraw(line());
  364. DWIN_UpdateLCD();
  365. }
  366. }
  367. void MenuClass::onClick() {
  368. if (MenuItems[selected]->onClick != nullptr) (*MenuItems[selected]->onClick)();
  369. }
  370. MenuItemClass *MenuClass::SelectedItem() {
  371. return MenuItems[selected];
  372. }
  373. /* MenuItem Class ===========================================================*/
  374. MenuItemClass::MenuItemClass(uint8_t cicon, const char * const text, void (*ondraw)(MenuItemClass* menuitem, int8_t line), void (*onclick)()) {
  375. icon = cicon;
  376. onClick = onclick;
  377. onDraw = ondraw;
  378. const uint8_t len = _MIN(sizeof(caption) - 1, strlen(text));
  379. memcpy(&caption[0], text, len);
  380. caption[len] = '\0';
  381. }
  382. MenuItemClass::MenuItemClass(uint8_t cicon, uint8_t id, uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2, void (*ondraw)(MenuItemClass* menuitem, int8_t line), void (*onclick)()) {
  383. icon = cicon;
  384. onClick = onclick;
  385. onDraw = ondraw;
  386. caption[0] = '\0';
  387. frameid = id;
  388. frame = { x1, y1, x2, y2 };
  389. }
  390. void MenuItemClass::SetFrame(uint8_t id, uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2) {
  391. caption[0] = '\0';
  392. frameid = id;
  393. frame = { x1, y1, x2, y2 };
  394. }
  395. void MenuItemClass::draw(int8_t line) {
  396. if (line < 0 || line >= TROWS) return;
  397. if (onDraw != nullptr) (*onDraw)(this, line);
  398. };
  399. MenuItemPtrClass::MenuItemPtrClass(uint8_t cicon, const char * const text, void (*ondraw)(MenuItemClass* menuitem, int8_t line), void (*onclick)(), void* val) : MenuItemClass(cicon, text, ondraw, onclick) {
  400. value = val;
  401. };
  402. #endif // DWIN_CREALITY_LCD_ENHANCED