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.

status_screen.cpp 14KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443
  1. /*********************
  2. * status_screen.cpp *
  3. *********************/
  4. /****************************************************************************
  5. * Written By Mark Pelletier 2017 - Aleph Objects, Inc. *
  6. * Written By Marcio Teixeira 2018 - Aleph Objects, Inc. *
  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. * To view a copy of the GNU General Public License, go to the following *
  19. * location: <http://www.gnu.org/licenses/>. *
  20. ****************************************************************************/
  21. #include "../config.h"
  22. #if ENABLED(LULZBOT_TOUCH_UI) && DISABLED(LULZBOT_USE_BIOPRINTER_UI)
  23. #include "screens.h"
  24. #include "screen_data.h"
  25. #include "../archim2-flash/flash_storage.h"
  26. #if BOTH(SDSUPPORT, LULZBOT_MANUAL_USB_STARTUP)
  27. #include "../../../../../sd/cardreader.h"
  28. #endif
  29. using namespace FTDI;
  30. using namespace Theme;
  31. #ifdef TOUCH_UI_PORTRAIT
  32. #define GRID_ROWS 8
  33. #else
  34. #define GRID_ROWS 8
  35. #endif
  36. void StatusScreen::draw_axis_position(draw_mode_t what) {
  37. CommandProcessor cmd;
  38. #define GRID_COLS 3
  39. if (what & BACKGROUND) {
  40. cmd.tag(6)
  41. #ifdef TOUCH_UI_PORTRAIT
  42. .fgcolor(Theme::axis_label)
  43. .font(Theme::font_large)
  44. .button( BTN_POS(1,5), BTN_SIZE(2,1), F(""), OPT_FLAT)
  45. .button( BTN_POS(1,6), BTN_SIZE(2,1), F(""), OPT_FLAT)
  46. .button( BTN_POS(1,7), BTN_SIZE(2,1), F(""), OPT_FLAT)
  47. .font(Theme::font_small)
  48. .text ( BTN_POS(1,5), BTN_SIZE(1,1), GET_TEXTF(AXIS_X))
  49. .text ( BTN_POS(1,6), BTN_SIZE(1,1), GET_TEXTF(AXIS_Y))
  50. .text ( BTN_POS(1,7), BTN_SIZE(1,1), GET_TEXTF(AXIS_Z))
  51. .font(Theme::font_medium)
  52. .fgcolor(Theme::x_axis) .button( BTN_POS(2,5), BTN_SIZE(2,1), F(""), OPT_FLAT)
  53. .fgcolor(Theme::y_axis) .button( BTN_POS(2,6), BTN_SIZE(2,1), F(""), OPT_FLAT)
  54. .fgcolor(Theme::z_axis) .button( BTN_POS(2,7), BTN_SIZE(2,1), F(""), OPT_FLAT);
  55. #else
  56. .fgcolor(Theme::axis_label)
  57. .font(Theme::font_large)
  58. .button( BTN_POS(1,5), BTN_SIZE(1,2), F(""), OPT_FLAT)
  59. .button( BTN_POS(2,5), BTN_SIZE(1,2), F(""), OPT_FLAT)
  60. .button( BTN_POS(3,5), BTN_SIZE(1,2), F(""), OPT_FLAT)
  61. .font(Theme::font_small)
  62. .text ( BTN_POS(1,5), BTN_SIZE(1,1), GET_TEXTF(AXIS_X))
  63. .text ( BTN_POS(2,5), BTN_SIZE(1,1), GET_TEXTF(AXIS_Y))
  64. .text ( BTN_POS(3,5), BTN_SIZE(1,1), GET_TEXTF(AXIS_Z))
  65. .font(Theme::font_medium)
  66. .fgcolor(Theme::x_axis) .button( BTN_POS(1,6), BTN_SIZE(1,1), F(""), OPT_FLAT)
  67. .fgcolor(Theme::y_axis) .button( BTN_POS(2,6), BTN_SIZE(1,1), F(""), OPT_FLAT)
  68. .fgcolor(Theme::z_axis) .button( BTN_POS(3,6), BTN_SIZE(1,1), F(""), OPT_FLAT);
  69. #endif
  70. }
  71. if (what & FOREGROUND) {
  72. using namespace ExtUI;
  73. char x_str[15];
  74. char y_str[15];
  75. char z_str[15];
  76. if (isAxisPositionKnown(X)) {
  77. dtostrf(getAxisPosition_mm(X), 5, 1, x_str);
  78. strcat_P(x_str, " ");
  79. strcat_P(x_str, GET_TEXT(UNITS_MM));
  80. } else {
  81. strcpy_P(x_str, PSTR("?"));
  82. }
  83. if (isAxisPositionKnown(Y)) {
  84. dtostrf(getAxisPosition_mm(Y), 5, 1, y_str);
  85. strcat_P(y_str, " ");
  86. strcat_P(y_str, GET_TEXT(UNITS_MM));
  87. } else {
  88. strcpy_P(y_str, PSTR("?"));
  89. }
  90. if (isAxisPositionKnown(Z)) {
  91. dtostrf(getAxisPosition_mm(Z), 5, 1, z_str);
  92. strcat_P(z_str, " ");
  93. strcat_P(z_str, GET_TEXT(UNITS_MM));
  94. } else {
  95. strcpy_P(z_str, PSTR("?"));
  96. }
  97. cmd.tag(6).font(Theme::font_medium)
  98. #ifdef TOUCH_UI_PORTRAIT
  99. .text ( BTN_POS(2,5), BTN_SIZE(2,1), x_str)
  100. .text ( BTN_POS(2,6), BTN_SIZE(2,1), y_str)
  101. .text ( BTN_POS(2,7), BTN_SIZE(2,1), z_str);
  102. #else
  103. .text ( BTN_POS(1,6), BTN_SIZE(1,1), x_str)
  104. .text ( BTN_POS(2,6), BTN_SIZE(1,1), y_str)
  105. .text ( BTN_POS(3,6), BTN_SIZE(1,1), z_str);
  106. #endif
  107. }
  108. #undef GRID_COLS
  109. }
  110. #ifdef TOUCH_UI_PORTRAIT
  111. #define GRID_COLS 8
  112. #else
  113. #define GRID_COLS 12
  114. #endif
  115. void StatusScreen::draw_temperature(draw_mode_t what) {
  116. using namespace Theme;
  117. CommandProcessor cmd;
  118. if (what & BACKGROUND) {
  119. cmd.font(Theme::font_small)
  120. #ifdef TOUCH_UI_PORTRAIT
  121. .tag(5)
  122. .fgcolor(temp) .button( BTN_POS(1,1), BTN_SIZE(4,2), F(""), OPT_FLAT)
  123. .button( BTN_POS(1,1), BTN_SIZE(8,1), F(""), OPT_FLAT)
  124. .fgcolor(fan_speed) .button( BTN_POS(5,2), BTN_SIZE(4,1), F(""), OPT_FLAT)
  125. .tag(0)
  126. .fgcolor(progress) .button( BTN_POS(1,3), BTN_SIZE(4,1), F(""), OPT_FLAT)
  127. .button( BTN_POS(5,3), BTN_SIZE(4,1), F(""), OPT_FLAT);
  128. #else
  129. .tag(5)
  130. .fgcolor(temp) .button( BTN_POS(1,1), BTN_SIZE(4,2), F(""), OPT_FLAT)
  131. .button( BTN_POS(1,1), BTN_SIZE(8,1), F(""), OPT_FLAT)
  132. .fgcolor(fan_speed) .button( BTN_POS(5,2), BTN_SIZE(4,1), F(""), OPT_FLAT)
  133. .tag(0)
  134. .fgcolor(progress) .button( BTN_POS(9,1), BTN_SIZE(4,1), F(""), OPT_FLAT)
  135. .button( BTN_POS(9,2), BTN_SIZE(4,1), F(""), OPT_FLAT);
  136. #endif
  137. // Draw Extruder Bitmap on Extruder Temperature Button
  138. cmd.tag(5)
  139. .cmd(BITMAP_SOURCE(Extruder_Icon_Info))
  140. .cmd(BITMAP_LAYOUT(Extruder_Icon_Info))
  141. .cmd(BITMAP_SIZE (Extruder_Icon_Info))
  142. .icon (BTN_POS(1,1), BTN_SIZE(1,1), Extruder_Icon_Info, icon_scale)
  143. .icon (BTN_POS(5,1), BTN_SIZE(1,1), Extruder_Icon_Info, icon_scale);
  144. // Draw Bed Heat Bitmap on Bed Heat Button
  145. cmd.cmd(BITMAP_SOURCE(Bed_Heat_Icon_Info))
  146. .cmd(BITMAP_LAYOUT(Bed_Heat_Icon_Info))
  147. .cmd(BITMAP_SIZE (Bed_Heat_Icon_Info))
  148. .icon (BTN_POS(1,2), BTN_SIZE(1,1), Bed_Heat_Icon_Info, icon_scale);
  149. // Draw Fan Percent Bitmap on Bed Heat Button
  150. cmd.cmd(BITMAP_SOURCE(Fan_Icon_Info))
  151. .cmd(BITMAP_LAYOUT(Fan_Icon_Info))
  152. .cmd(BITMAP_SIZE (Fan_Icon_Info))
  153. .icon (BTN_POS(5,2), BTN_SIZE(1,1), Fan_Icon_Info, icon_scale);
  154. }
  155. if (what & FOREGROUND) {
  156. using namespace ExtUI;
  157. char e0_str[20];
  158. char e1_str[20];
  159. char bed_str[20];
  160. char fan_str[20];
  161. sprintf_P(
  162. fan_str,
  163. PSTR("%-3d %%"),
  164. int8_t(getActualFan_percent(FAN0))
  165. );
  166. if (isHeaterIdle(BED))
  167. sprintf_P(bed_str, PSTR("%3d%S / %S"), ROUND(getActualTemp_celsius(BED)), GET_TEXT(UNITS_C), GET_TEXT(TEMP_IDLE));
  168. else
  169. sprintf_P(bed_str, PSTR("%3d / %3d%S"), ROUND(getActualTemp_celsius(BED)), ROUND(getTargetTemp_celsius(BED)), GET_TEXT(UNITS_C));
  170. if (isHeaterIdle(H0))
  171. sprintf_P(e0_str, PSTR("%3d%S / %S"), ROUND(getActualTemp_celsius(H0)), GET_TEXT(UNITS_C), GET_TEXT(TEMP_IDLE));
  172. else
  173. sprintf_P(e0_str, PSTR("%3d / %3d%S"), ROUND(getActualTemp_celsius(H0)), ROUND(getTargetTemp_celsius(H0)), GET_TEXT(UNITS_C));
  174. #if EXTRUDERS == 2
  175. if (isHeaterIdle(H1))
  176. sprintf_P(e1_str, PSTR("%3d%S / %S"), ROUND(getActualTemp_celsius(H1)), PSTR(GET_TEXT(UNITS_C)), GET_TEXT(TEMP_IDLE));
  177. else
  178. sprintf_P(e1_str, PSTR("%3d / %3d%S"), ROUND(getActualTemp_celsius(H1)), ROUND(getTargetTemp_celsius(H1)), GET_TEXT(UNITS_C));
  179. #else
  180. strcpy_P(
  181. e1_str,
  182. PSTR("-")
  183. );
  184. #endif
  185. cmd.tag(5)
  186. .font(font_medium)
  187. .text(BTN_POS(2,1), BTN_SIZE(3,1), e0_str)
  188. .text(BTN_POS(6,1), BTN_SIZE(3,1), e1_str)
  189. .text(BTN_POS(2,2), BTN_SIZE(3,1), bed_str)
  190. .text(BTN_POS(6,2), BTN_SIZE(3,1), fan_str);
  191. }
  192. }
  193. void StatusScreen::draw_progress(draw_mode_t what) {
  194. using namespace ExtUI;
  195. using namespace Theme;
  196. CommandProcessor cmd;
  197. if (what & BACKGROUND) {
  198. cmd.tag(0).font(font_medium)
  199. #ifdef TOUCH_UI_PORTRAIT
  200. .fgcolor(progress) .button(BTN_POS(1,3), BTN_SIZE(4,1), F(""), OPT_FLAT)
  201. .button(BTN_POS(5,3), BTN_SIZE(4,1), F(""), OPT_FLAT);
  202. #else
  203. .fgcolor(progress) .button(BTN_POS(9,1), BTN_SIZE(4,1), F(""), OPT_FLAT)
  204. .button(BTN_POS(9,2), BTN_SIZE(4,1), F(""), OPT_FLAT);
  205. #endif
  206. }
  207. if (what & FOREGROUND) {
  208. const uint32_t elapsed = getProgress_seconds_elapsed();
  209. const uint8_t hrs = elapsed/3600;
  210. const uint8_t min = (elapsed/60)%60;
  211. char time_str[10];
  212. char progress_str[10];
  213. sprintf_P(time_str, PSTR(" %02d : %02d"), hrs, min);
  214. sprintf_P(progress_str, PSTR("%-3d %%"), getProgress_percent() );
  215. cmd.font(font_medium)
  216. #ifdef TOUCH_UI_PORTRAIT
  217. .tag(0).text(BTN_POS(1,3), BTN_SIZE(4,1), time_str)
  218. .text(BTN_POS(5,3), BTN_SIZE(4,1), progress_str);
  219. #else
  220. .tag(0).text(BTN_POS(9,1), BTN_SIZE(4,1), time_str)
  221. .text(BTN_POS(9,2), BTN_SIZE(4,1), progress_str);
  222. #endif
  223. }
  224. }
  225. #undef GRID_COLS
  226. void StatusScreen::draw_interaction_buttons(draw_mode_t what) {
  227. #define GRID_COLS 4
  228. if (what & FOREGROUND) {
  229. using namespace ExtUI;
  230. const bool has_media = isMediaInserted() && !isPrintingFromMedia();
  231. CommandProcessor cmd;
  232. cmd.colors(normal_btn)
  233. .font(Theme::font_medium)
  234. #if BOTH(SDSUPPORT, LULZBOT_MANUAL_USB_STARTUP)
  235. .enabled(!Sd2Card::ready() || has_media)
  236. #else
  237. .enabled(has_media)
  238. #endif
  239. .colors(has_media ? action_btn : normal_btn)
  240. #ifdef TOUCH_UI_PORTRAIT
  241. .tag(3).button( BTN_POS(1,8), BTN_SIZE(2,1),
  242. #else
  243. .tag(3).button( BTN_POS(1,7), BTN_SIZE(2,2),
  244. #endif
  245. isPrintingFromMedia() ? GET_TEXTF(PRINTING) :
  246. #if BOTH(SDSUPPORT, LULZBOT_MANUAL_USB_STARTUP)
  247. (!Sd2Card::ready() ? GET_TEXTF(ENABLE_MEDIA) :
  248. #else
  249. GET_TEXTF(MEDIA))
  250. #endif
  251. .colors(!has_media ? action_btn : normal_btn)
  252. #ifdef TOUCH_UI_PORTRAIT
  253. .tag(4).button( BTN_POS(3,8), BTN_SIZE(2,1), GET_TEXTF(MENU));
  254. #else
  255. .tag(4).button( BTN_POS(3,7), BTN_SIZE(2,2), GET_TEXTF(MENU));
  256. #endif
  257. }
  258. #undef GRID_COLS
  259. }
  260. void StatusScreen::draw_status_message(draw_mode_t what, const char* message) {
  261. #define GRID_COLS 1
  262. if (what & BACKGROUND) {
  263. CommandProcessor cmd;
  264. cmd.fgcolor(Theme::status_msg)
  265. .tag(0)
  266. #ifdef TOUCH_UI_PORTRAIT
  267. .button( BTN_POS(1,4), BTN_SIZE(1,1), F(""), OPT_FLAT);
  268. #else
  269. .button( BTN_POS(1,3), BTN_SIZE(1,2), F(""), OPT_FLAT);
  270. #endif
  271. draw_text_box(cmd,
  272. #ifdef TOUCH_UI_PORTRAIT
  273. BTN_POS(1,4), BTN_SIZE(1,1),
  274. #else
  275. BTN_POS(1,3), BTN_SIZE(1,2),
  276. #endif
  277. message, OPT_CENTER, font_large);
  278. }
  279. #undef GRID_COLS
  280. }
  281. void StatusScreen::setStatusMessage(progmem_str message) {
  282. char buff[strlen_P((const char * const)message)+1];
  283. strcpy_P(buff, (const char * const) message);
  284. setStatusMessage((const char *) buff);
  285. }
  286. void StatusScreen::setStatusMessage(const char* message) {
  287. CommandProcessor cmd;
  288. cmd.cmd(CMD_DLSTART)
  289. .cmd(CLEAR_COLOR_RGB(Theme::bg_color))
  290. .cmd(CLEAR(true,true,true));
  291. draw_temperature(BACKGROUND);
  292. #ifdef TOUCH_UI_USE_UTF8
  293. load_utf8_bitmaps(cmd);
  294. #endif
  295. draw_progress(BACKGROUND);
  296. draw_axis_position(BACKGROUND);
  297. draw_status_message(BACKGROUND, message);
  298. draw_interaction_buttons(BACKGROUND);
  299. storeBackground();
  300. #ifdef UI_FRAMEWORK_DEBUG
  301. SERIAL_ECHO_START();
  302. SERIAL_ECHOLNPAIR("New status message: ", message);
  303. #endif
  304. if (AT_SCREEN(StatusScreen)) {
  305. current_screen.onRefresh();
  306. }
  307. }
  308. void StatusScreen::loadBitmaps() {
  309. // Load the bitmaps for the status screen
  310. using namespace Theme;
  311. constexpr uint32_t base = ftdi_memory_map::RAM_G;
  312. CLCD::mem_write_pgm(base + TD_Icon_Info.RAMG_offset, TD_Icon, sizeof(TD_Icon));
  313. CLCD::mem_write_pgm(base + Extruder_Icon_Info.RAMG_offset, Extruder_Icon, sizeof(Extruder_Icon));
  314. CLCD::mem_write_pgm(base + Bed_Heat_Icon_Info.RAMG_offset, Bed_Heat_Icon, sizeof(Bed_Heat_Icon));
  315. CLCD::mem_write_pgm(base + Fan_Icon_Info.RAMG_offset, Fan_Icon, sizeof(Fan_Icon));
  316. // Load fonts for internationalization
  317. #ifdef TOUCH_UI_USE_UTF8
  318. load_utf8_data(base + UTF8_FONT_OFFSET);
  319. #endif
  320. }
  321. void StatusScreen::onStartup() {
  322. UIFlashStorage::initialize();
  323. }
  324. void StatusScreen::onRedraw(draw_mode_t what) {
  325. if (what & FOREGROUND) {
  326. draw_temperature(FOREGROUND);
  327. draw_progress(FOREGROUND);
  328. draw_axis_position(FOREGROUND);
  329. draw_interaction_buttons(FOREGROUND);
  330. }
  331. }
  332. void StatusScreen::onEntry() {
  333. onRefresh();
  334. }
  335. void StatusScreen::onIdle() {
  336. if (refresh_timer.elapsed(STATUS_UPDATE_INTERVAL)) {
  337. onRefresh();
  338. refresh_timer.start();
  339. }
  340. BaseScreen::onIdle();
  341. }
  342. bool StatusScreen::onTouchEnd(uint8_t tag) {
  343. using namespace ExtUI;
  344. switch (tag) {
  345. case 3:
  346. #if BOTH(SDSUPPORT, LULZBOT_MANUAL_USB_STARTUP)
  347. if (!Sd2Card::ready()) {
  348. StatusScreen::setStatusMessage(GET_TEXTF(INSERT_MEDIA));
  349. Sd2Card::usbStartup();
  350. } else {
  351. GOTO_SCREEN(FilesScreen);
  352. }
  353. #else
  354. GOTO_SCREEN(FilesScreen);
  355. #endif
  356. break;
  357. case 4:
  358. if (isPrinting()) {
  359. GOTO_SCREEN(TuneMenu);
  360. } else {
  361. GOTO_SCREEN(MainMenu);
  362. }
  363. break;
  364. case 5: GOTO_SCREEN(TemperatureScreen); break;
  365. case 6:
  366. if (!isPrinting()) {
  367. GOTO_SCREEN(MoveAxisScreen);
  368. }
  369. break;
  370. default:
  371. return true;
  372. }
  373. // If a passcode is enabled, the LockScreen will prevent the
  374. // user from proceeding.
  375. LockScreen::check_passcode();
  376. return true;
  377. }
  378. #endif // LULZBOT_TOUCH_UI