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

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