ultralcd_implementation_hitachi_HD44780.h 31 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936
  1. #ifndef ULTRA_LCD_IMPLEMENTATION_HITACHI_HD44780_H
  2. #define ULTRA_LCD_IMPLEMENTATION_HITACHI_HD44780_H
  3. int scrollstuff = 0;
  4. char longFilenameOLD[LONG_FILENAME_LENGTH];
  5. /**
  6. * Implementation of the LCD display routines for a Hitachi HD44780 display. These are common LCD character displays.
  7. * When selecting the Russian language, a slightly different LCD implementation is used to handle UTF8 characters.
  8. **/
  9. #ifndef REPRAPWORLD_KEYPAD
  10. extern volatile uint8_t buttons; //the last checked buttons in a bit array.
  11. #else
  12. extern volatile uint16_t buttons; //an extended version of the last checked buttons in a bit array.
  13. #endif
  14. ////////////////////////////////////
  15. // Setup button and encode mappings for each panel (into 'buttons' variable
  16. //
  17. // This is just to map common functions (across different panels) onto the same
  18. // macro name. The mapping is independent of whether the button is directly connected or
  19. // via a shift/i2c register.
  20. #ifdef ULTIPANEL
  21. // All UltiPanels might have an encoder - so this is always be mapped onto first two bits
  22. #define BLEN_B 1
  23. #define BLEN_A 0
  24. #define EN_B (1<<BLEN_B) // The two encoder pins are connected through BTN_EN1 and BTN_EN2
  25. #define EN_A (1<<BLEN_A)
  26. #if defined(BTN_ENC) && BTN_ENC > -1
  27. // encoder click is directly connected
  28. #define BLEN_C 2
  29. #define EN_C (1<<BLEN_C)
  30. #endif
  31. //
  32. // Setup other button mappings of each panel
  33. //
  34. #if defined(LCD_I2C_VIKI)
  35. #define B_I2C_BTN_OFFSET 3 // (the first three bit positions reserved for EN_A, EN_B, EN_C)
  36. // button and encoder bit positions within 'buttons'
  37. #define B_LE (BUTTON_LEFT<<B_I2C_BTN_OFFSET) // The remaining normalized buttons are all read via I2C
  38. #define B_UP (BUTTON_UP<<B_I2C_BTN_OFFSET)
  39. #define B_MI (BUTTON_SELECT<<B_I2C_BTN_OFFSET)
  40. #define B_DW (BUTTON_DOWN<<B_I2C_BTN_OFFSET)
  41. #define B_RI (BUTTON_RIGHT<<B_I2C_BTN_OFFSET)
  42. #if defined(BTN_ENC) && BTN_ENC > -1
  43. // the pause/stop/restart button is connected to BTN_ENC when used
  44. #define B_ST (EN_C) // Map the pause/stop/resume button into its normalized functional name
  45. #define LCD_CLICKED (buttons&(B_MI|B_RI|B_ST)) // pause/stop button also acts as click until we implement proper pause/stop.
  46. #else
  47. #define LCD_CLICKED (buttons&(B_MI|B_RI))
  48. #endif
  49. // I2C buttons take too long to read inside an interrupt context and so we read them during lcd_update
  50. #define LCD_HAS_SLOW_BUTTONS
  51. #elif defined(LCD_I2C_PANELOLU2)
  52. // encoder click can be read through I2C if not directly connected
  53. #if BTN_ENC <= 0
  54. #define B_I2C_BTN_OFFSET 3 // (the first three bit positions reserved for EN_A, EN_B, EN_C)
  55. #define B_MI (PANELOLU2_ENCODER_C<<B_I2C_BTN_OFFSET) // requires LiquidTWI2 library v1.2.3 or later
  56. #define LCD_CLICKED (buttons&B_MI)
  57. // I2C buttons take too long to read inside an interrupt context and so we read them during lcd_update
  58. #define LCD_HAS_SLOW_BUTTONS
  59. #else
  60. #define LCD_CLICKED (buttons&EN_C)
  61. #endif
  62. #elif defined(REPRAPWORLD_KEYPAD)
  63. // define register bit values, don't change it
  64. #define BLEN_REPRAPWORLD_KEYPAD_F3 0
  65. #define BLEN_REPRAPWORLD_KEYPAD_F2 1
  66. #define BLEN_REPRAPWORLD_KEYPAD_F1 2
  67. #define BLEN_REPRAPWORLD_KEYPAD_UP 3
  68. #define BLEN_REPRAPWORLD_KEYPAD_RIGHT 4
  69. #define BLEN_REPRAPWORLD_KEYPAD_MIDDLE 5
  70. #define BLEN_REPRAPWORLD_KEYPAD_DOWN 6
  71. #define BLEN_REPRAPWORLD_KEYPAD_LEFT 7
  72. #define REPRAPWORLD_BTN_OFFSET 3 // bit offset into buttons for shift register values
  73. #define EN_REPRAPWORLD_KEYPAD_F3 (1<<(BLEN_REPRAPWORLD_KEYPAD_F3+REPRAPWORLD_BTN_OFFSET))
  74. #define EN_REPRAPWORLD_KEYPAD_F2 (1<<(BLEN_REPRAPWORLD_KEYPAD_F2+REPRAPWORLD_BTN_OFFSET))
  75. #define EN_REPRAPWORLD_KEYPAD_F1 (1<<(BLEN_REPRAPWORLD_KEYPAD_F1+REPRAPWORLD_BTN_OFFSET))
  76. #define EN_REPRAPWORLD_KEYPAD_UP (1<<(BLEN_REPRAPWORLD_KEYPAD_UP+REPRAPWORLD_BTN_OFFSET))
  77. #define EN_REPRAPWORLD_KEYPAD_RIGHT (1<<(BLEN_REPRAPWORLD_KEYPAD_RIGHT+REPRAPWORLD_BTN_OFFSET))
  78. #define EN_REPRAPWORLD_KEYPAD_MIDDLE (1<<(BLEN_REPRAPWORLD_KEYPAD_MIDDLE+REPRAPWORLD_BTN_OFFSET))
  79. #define EN_REPRAPWORLD_KEYPAD_DOWN (1<<(BLEN_REPRAPWORLD_KEYPAD_DOWN+REPRAPWORLD_BTN_OFFSET))
  80. #define EN_REPRAPWORLD_KEYPAD_LEFT (1<<(BLEN_REPRAPWORLD_KEYPAD_LEFT+REPRAPWORLD_BTN_OFFSET))
  81. #define LCD_CLICKED ((buttons&EN_C) || (buttons&EN_REPRAPWORLD_KEYPAD_F1))
  82. #define REPRAPWORLD_KEYPAD_MOVE_Y_DOWN (buttons&EN_REPRAPWORLD_KEYPAD_DOWN)
  83. #define REPRAPWORLD_KEYPAD_MOVE_Y_UP (buttons&EN_REPRAPWORLD_KEYPAD_UP)
  84. #define REPRAPWORLD_KEYPAD_MOVE_HOME (buttons&EN_REPRAPWORLD_KEYPAD_MIDDLE)
  85. #elif defined(NEWPANEL)
  86. #define LCD_CLICKED (buttons&EN_C)
  87. #else // old style ULTIPANEL
  88. //bits in the shift register that carry the buttons for:
  89. // left up center down right red(stop)
  90. #define BL_LE 7
  91. #define BL_UP 6
  92. #define BL_MI 5
  93. #define BL_DW 4
  94. #define BL_RI 3
  95. #define BL_ST 2
  96. //automatic, do not change
  97. #define B_LE (1<<BL_LE)
  98. #define B_UP (1<<BL_UP)
  99. #define B_MI (1<<BL_MI)
  100. #define B_DW (1<<BL_DW)
  101. #define B_RI (1<<BL_RI)
  102. #define B_ST (1<<BL_ST)
  103. #define LCD_CLICKED (buttons&(B_MI|B_ST))
  104. #endif
  105. ////////////////////////
  106. // Setup Rotary Encoder Bit Values (for two pin encoders to indicate movement)
  107. // These values are independent of which pins are used for EN_A and EN_B indications
  108. // The rotary encoder part is also independent to the chipset used for the LCD
  109. #if defined(EN_A) && defined(EN_B)
  110. #define encrot0 0
  111. #define encrot1 2
  112. #define encrot2 3
  113. #define encrot3 1
  114. #endif
  115. #endif //ULTIPANEL
  116. ////////////////////////////////////
  117. // Create LCD class instance and chipset-specific information
  118. #if defined(LCD_I2C_TYPE_PCF8575)
  119. // note: these are register mapped pins on the PCF8575 controller not Arduino pins
  120. #define LCD_I2C_PIN_BL 3
  121. #define LCD_I2C_PIN_EN 2
  122. #define LCD_I2C_PIN_RW 1
  123. #define LCD_I2C_PIN_RS 0
  124. #define LCD_I2C_PIN_D4 4
  125. #define LCD_I2C_PIN_D5 5
  126. #define LCD_I2C_PIN_D6 6
  127. #define LCD_I2C_PIN_D7 7
  128. #include <Wire.h>
  129. #include <LCD.h>
  130. #include <LiquidCrystal_I2C.h>
  131. #define LCD_CLASS LiquidCrystal_I2C
  132. LCD_CLASS lcd(LCD_I2C_ADDRESS,LCD_I2C_PIN_EN,LCD_I2C_PIN_RW,LCD_I2C_PIN_RS,LCD_I2C_PIN_D4,LCD_I2C_PIN_D5,LCD_I2C_PIN_D6,LCD_I2C_PIN_D7);
  133. #elif defined(LCD_I2C_TYPE_MCP23017)
  134. //for the LED indicators (which maybe mapped to different things in lcd_implementation_update_indicators())
  135. #define LED_A 0x04 //100
  136. #define LED_B 0x02 //010
  137. #define LED_C 0x01 //001
  138. #define LCD_HAS_STATUS_INDICATORS
  139. #include <Wire.h>
  140. #include <LiquidTWI2.h>
  141. #define LCD_CLASS LiquidTWI2
  142. #if defined(DETECT_DEVICE)
  143. LCD_CLASS lcd(LCD_I2C_ADDRESS, 1);
  144. #else
  145. LCD_CLASS lcd(LCD_I2C_ADDRESS);
  146. #endif
  147. #elif defined(LCD_I2C_TYPE_MCP23008)
  148. #include <Wire.h>
  149. #include <LiquidTWI2.h>
  150. #define LCD_CLASS LiquidTWI2
  151. #if defined(DETECT_DEVICE)
  152. LCD_CLASS lcd(LCD_I2C_ADDRESS, 1);
  153. #else
  154. LCD_CLASS lcd(LCD_I2C_ADDRESS);
  155. #endif
  156. #elif defined(LCD_I2C_TYPE_PCA8574)
  157. #include <LiquidCrystal_I2C.h>
  158. #define LCD_CLASS LiquidCrystal_I2C
  159. LCD_CLASS lcd(LCD_I2C_ADDRESS, LCD_WIDTH, LCD_HEIGHT);
  160. // 2 wire Non-latching LCD SR from:
  161. // https://bitbucket.org/fmalpartida/new-liquidcrystal/wiki/schematics#!shiftregister-connection
  162. #elif defined(SR_LCD_2W_NL)
  163. extern "C" void __cxa_pure_virtual() { while (1); }
  164. #include <LCD.h>
  165. #include <LiquidCrystal_SR.h>
  166. #define LCD_CLASS LiquidCrystal_SR
  167. LCD_CLASS lcd(SR_DATA_PIN, SR_CLK_PIN);
  168. #else
  169. // Standard directly connected LCD implementations
  170. #ifdef LANGUAGE_RU
  171. #include "LiquidCrystalRus.h"
  172. #define LCD_CLASS LiquidCrystalRus
  173. #else
  174. #include "LiquidCrystal.h"
  175. #define LCD_CLASS LiquidCrystal
  176. #endif
  177. LCD_CLASS lcd(LCD_PINS_RS, LCD_PINS_ENABLE, LCD_PINS_D4, LCD_PINS_D5,LCD_PINS_D6,LCD_PINS_D7); //RS,Enable,D4,D5,D6,D7
  178. #endif
  179. #if defined(LCD_PROGRESS_BAR) && defined(SDSUPPORT)
  180. static uint16_t progressBarTick = 0;
  181. #if PROGRESS_MSG_EXPIRE > 0
  182. static uint16_t messageTick = 0;
  183. #endif
  184. #define LCD_STR_PROGRESS "\x03\x04\x05"
  185. #endif
  186. /* Custom characters defined in the first 8 characters of the LCD */
  187. #define LCD_STR_BEDTEMP "\x00"
  188. #define LCD_STR_DEGREE "\x01"
  189. #define LCD_STR_THERMOMETER "\x02"
  190. #define LCD_STR_UPLEVEL "\x03"
  191. #define LCD_STR_REFRESH "\x04"
  192. #define LCD_STR_FOLDER "\x05"
  193. #define LCD_STR_FEEDRATE "\x06"
  194. #define LCD_STR_CLOCK "\x07"
  195. #define LCD_STR_ARROW_RIGHT "\x7E" /* from the default character set */
  196. static void lcd_set_custom_characters(
  197. #if defined(LCD_PROGRESS_BAR) && defined(SDSUPPORT)
  198. bool progress_bar_set=true
  199. #endif
  200. ) {
  201. byte bedTemp[8] = {
  202. B00000,
  203. B11111,
  204. B10101,
  205. B10001,
  206. B10101,
  207. B11111,
  208. B00000,
  209. B00000
  210. }; //thanks Sonny Mounicou
  211. byte degree[8] = {
  212. B01100,
  213. B10010,
  214. B10010,
  215. B01100,
  216. B00000,
  217. B00000,
  218. B00000,
  219. B00000
  220. };
  221. byte thermometer[8] = {
  222. B00100,
  223. B01010,
  224. B01010,
  225. B01010,
  226. B01010,
  227. B10001,
  228. B10001,
  229. B01110
  230. };
  231. byte uplevel[8] = {
  232. B00100,
  233. B01110,
  234. B11111,
  235. B00100,
  236. B11100,
  237. B00000,
  238. B00000,
  239. B00000
  240. }; //thanks joris
  241. byte refresh[8] = {
  242. B00000,
  243. B00110,
  244. B11001,
  245. B11000,
  246. B00011,
  247. B10011,
  248. B01100,
  249. B00000,
  250. }; //thanks joris
  251. byte folder[8] = {
  252. B00000,
  253. B11100,
  254. B11111,
  255. B10001,
  256. B10001,
  257. B11111,
  258. B00000,
  259. B00000
  260. }; //thanks joris
  261. byte feedrate[8] = {
  262. B11100,
  263. B10000,
  264. B11000,
  265. B10111,
  266. B00101,
  267. B00110,
  268. B00101,
  269. B00000
  270. }; //thanks Sonny Mounicou
  271. byte clock[8] = {
  272. B00000,
  273. B01110,
  274. B10011,
  275. B10101,
  276. B10001,
  277. B01110,
  278. B00000,
  279. B00000
  280. }; //thanks Sonny Mounicou
  281. #if defined(LCD_PROGRESS_BAR) && defined(SDSUPPORT)
  282. static bool char_mode = false;
  283. byte progress[3][8] = { {
  284. B00000,
  285. B10000,
  286. B10000,
  287. B10000,
  288. B10000,
  289. B10000,
  290. B10000,
  291. B00000
  292. }, {
  293. B00000,
  294. B10100,
  295. B10100,
  296. B10100,
  297. B10100,
  298. B10100,
  299. B10100,
  300. B00000
  301. }, {
  302. B00000,
  303. B10101,
  304. B10101,
  305. B10101,
  306. B10101,
  307. B10101,
  308. B10101,
  309. B00000
  310. } };
  311. if (progress_bar_set != char_mode) {
  312. char_mode = progress_bar_set;
  313. lcd.createChar(LCD_STR_BEDTEMP[0], bedTemp);
  314. lcd.createChar(LCD_STR_DEGREE[0], degree);
  315. lcd.createChar(LCD_STR_THERMOMETER[0], thermometer);
  316. lcd.createChar(LCD_STR_FEEDRATE[0], feedrate);
  317. lcd.createChar(LCD_STR_CLOCK[0], clock);
  318. if (progress_bar_set) {
  319. // Progress bar characters for info screen
  320. for (int i=3; i--;) lcd.createChar(LCD_STR_PROGRESS[i], progress[i]);
  321. }
  322. else {
  323. // Custom characters for submenus
  324. lcd.createChar(LCD_STR_UPLEVEL[0], uplevel);
  325. lcd.createChar(LCD_STR_REFRESH[0], refresh);
  326. lcd.createChar(LCD_STR_FOLDER[0], folder);
  327. }
  328. }
  329. #else
  330. lcd.createChar(LCD_STR_BEDTEMP[0], bedTemp);
  331. lcd.createChar(LCD_STR_DEGREE[0], degree);
  332. lcd.createChar(LCD_STR_THERMOMETER[0], thermometer);
  333. lcd.createChar(LCD_STR_UPLEVEL[0], uplevel);
  334. lcd.createChar(LCD_STR_REFRESH[0], refresh);
  335. lcd.createChar(LCD_STR_FOLDER[0], folder);
  336. lcd.createChar(LCD_STR_FEEDRATE[0], feedrate);
  337. lcd.createChar(LCD_STR_CLOCK[0], clock);
  338. #endif
  339. }
  340. static void lcd_implementation_init(
  341. #if defined(LCD_PROGRESS_BAR) && defined(SDSUPPORT)
  342. bool progress_bar_set=true
  343. #endif
  344. ) {
  345. #if defined(LCD_I2C_TYPE_PCF8575)
  346. lcd.begin(LCD_WIDTH, LCD_HEIGHT);
  347. #ifdef LCD_I2C_PIN_BL
  348. lcd.setBacklightPin(LCD_I2C_PIN_BL,POSITIVE);
  349. lcd.setBacklight(HIGH);
  350. #endif
  351. #elif defined(LCD_I2C_TYPE_MCP23017)
  352. lcd.setMCPType(LTI_TYPE_MCP23017);
  353. lcd.begin(LCD_WIDTH, LCD_HEIGHT);
  354. lcd.setBacklight(0); //set all the LEDs off to begin with
  355. #elif defined(LCD_I2C_TYPE_MCP23008)
  356. lcd.setMCPType(LTI_TYPE_MCP23008);
  357. lcd.begin(LCD_WIDTH, LCD_HEIGHT);
  358. #elif defined(LCD_I2C_TYPE_PCA8574)
  359. lcd.init();
  360. lcd.backlight();
  361. #else
  362. lcd.begin(LCD_WIDTH, LCD_HEIGHT);
  363. #endif
  364. lcd_set_custom_characters(
  365. #if defined(LCD_PROGRESS_BAR) && defined(SDSUPPORT)
  366. progress_bar_set
  367. #endif
  368. );
  369. lcd.clear();
  370. }
  371. static void lcd_implementation_init_noclear(
  372. #if defined(LCD_PROGRESS_BAR) && defined(SDSUPPORT)
  373. bool progress_bar_set=true
  374. #endif
  375. ) {
  376. #if defined(LCD_I2C_TYPE_PCF8575)
  377. lcd.begin_noclear(LCD_WIDTH, LCD_HEIGHT);
  378. #ifdef LCD_I2C_PIN_BL
  379. lcd.setBacklightPin(LCD_I2C_PIN_BL,POSITIVE);
  380. lcd.setBacklight(HIGH);
  381. #endif
  382. #elif defined(LCD_I2C_TYPE_MCP23017)
  383. lcd.setMCPType(LTI_TYPE_MCP23017);
  384. lcd.begin_noclear(LCD_WIDTH, LCD_HEIGHT);
  385. lcd.setBacklight(0); //set all the LEDs off to begin with
  386. #elif defined(LCD_I2C_TYPE_MCP23008)
  387. lcd.setMCPType(LTI_TYPE_MCP23008);
  388. lcd.begin_noclear(LCD_WIDTH, LCD_HEIGHT);
  389. #elif defined(LCD_I2C_TYPE_PCA8574)
  390. lcd.init();
  391. lcd.backlight();
  392. #else
  393. lcd.begin_noclear(LCD_WIDTH, LCD_HEIGHT);
  394. #endif
  395. lcd_set_custom_characters(
  396. #if defined(LCD_PROGRESS_BAR) && defined(SDSUPPORT)
  397. progress_bar_set
  398. #endif
  399. );
  400. }
  401. static void lcd_implementation_nodisplay()
  402. {
  403. lcd.noDisplay();
  404. }
  405. static void lcd_implementation_display()
  406. {
  407. lcd.display();
  408. }
  409. static void lcd_implementation_clear()
  410. {
  411. lcd.clear();
  412. }
  413. /* Arduino < 1.0.0 is missing a function to print PROGMEM strings, so we need to implement our own */
  414. static void lcd_printPGM(const char* str)
  415. {
  416. char c;
  417. while((c = pgm_read_byte(str++)) != '\0')
  418. {
  419. lcd.write(c);
  420. }
  421. }
  422. /*
  423. 20x4 |01234567890123456789|
  424. |T 000/000D Z000.0 |
  425. |B 000/000D F100% |
  426. |SD100% T--:-- |
  427. |Status line.........|
  428. */
  429. static void lcd_implementation_status_screen()
  430. {
  431. int tHotend=int(degHotend(0) + 0.5);
  432. int tTarget=int(degTargetHotend(0) + 0.5);
  433. //Print the hotend temperature
  434. lcd.setCursor(0, 0);
  435. lcd.print(LCD_STR_THERMOMETER[0]);
  436. lcd.print(itostr3(tHotend));
  437. lcd.print('/');
  438. lcd.print(itostr3left(tTarget));
  439. lcd_printPGM(PSTR(LCD_STR_DEGREE " "));
  440. lcd.print(" ");
  441. //Print the Z coordinates
  442. lcd.setCursor(LCD_WIDTH - 8-2, 0);
  443. lcd.print(" Z");
  444. lcd.print(ftostr32sp(current_position[Z_AXIS] + 0.00001));
  445. lcd.print(' ');
  446. //Print the Bedtemperature
  447. lcd.setCursor(0, 1);
  448. tHotend=int(degBed() + 0.5);
  449. tTarget=int(degTargetBed() + 0.5);
  450. lcd.print(LCD_STR_BEDTEMP[0]);
  451. lcd.print(itostr3(tHotend));
  452. lcd.print('/');
  453. lcd.print(itostr3left(tTarget));
  454. lcd_printPGM(PSTR(LCD_STR_DEGREE " "));
  455. lcd.print(" ");
  456. //Print Feedrate
  457. lcd.setCursor(LCD_WIDTH - 8-2, 1);
  458. lcd.print(" ");
  459. lcd.print(LCD_STR_FEEDRATE[0]);
  460. lcd.print(itostr3(feedmultiply));
  461. lcd.print('%');
  462. lcd.print(" ");
  463. //Print SD status
  464. lcd.setCursor(0, 2);
  465. lcd_printPGM(PSTR("SD"));
  466. if (IS_SD_PRINTING)
  467. lcd.print(itostr3(card.percentDone()));
  468. else
  469. lcd_printPGM(PSTR("---"));
  470. lcd.print('%');
  471. lcd.print(" ");
  472. //Print time elapsed
  473. lcd.setCursor(LCD_WIDTH - 8 -2, 2);
  474. lcd.print(" ");
  475. lcd.print(LCD_STR_CLOCK[0]);
  476. if(starttime != 0)
  477. {
  478. uint16_t time = millis()/60000 - starttime/60000;
  479. lcd.print(itostr2(time/60));
  480. lcd.print(':');
  481. lcd.print(itostr2(time%60));
  482. }else{
  483. lcd_printPGM(PSTR("--:--"));
  484. }
  485. lcd.print(" ");
  486. //Print status line
  487. lcd.setCursor(0, 3);
  488. if(strcmp(lcd_status_message, "SD-PRINTING ") == 0){
  489. if(strcmp(longFilenameOLD, card.longFilename) != 0){
  490. memset(longFilenameOLD,'\0',strlen(longFilenameOLD));
  491. sprintf(longFilenameOLD, "%s", card.longFilename);
  492. scrollstuff = 0;
  493. }
  494. if(strlen(card.longFilename) > LCD_WIDTH){
  495. int inters = 0;
  496. int gh = scrollstuff;
  497. while( ((gh-scrollstuff)<LCD_WIDTH) && (inters == 0) ){
  498. if(card.longFilename[gh] == '\0'){
  499. lcd.setCursor(gh-scrollstuff, 3);
  500. lcd.print(card.longFilename[gh-1]);
  501. scrollstuff = 0;
  502. gh = scrollstuff;
  503. inters = 1;
  504. }else{
  505. lcd.setCursor(gh-scrollstuff, 3);
  506. lcd.print(card.longFilename[gh-1]);
  507. gh++;
  508. }
  509. }
  510. scrollstuff++;
  511. }else{
  512. lcd.print(longFilenameOLD);
  513. }
  514. }else{
  515. lcd.print(lcd_status_message);
  516. }
  517. for(int fillspace = 0; fillspace<20;fillspace++){
  518. if((lcd_status_message[fillspace] > 31 )){
  519. }else{
  520. lcd.print(' ');
  521. }
  522. }
  523. }
  524. static void lcd_implementation_drawmenu_generic(uint8_t row, const char* pstr, char pre_char, char post_char)
  525. {
  526. char c;
  527. //Use all characters in narrow LCDs
  528. #if LCD_WIDTH < 20
  529. uint8_t n = LCD_WIDTH - 1 - 1;
  530. #else
  531. uint8_t n = LCD_WIDTH - 1 - 2;
  532. #endif
  533. lcd.setCursor(0, row);
  534. lcd.print(pre_char);
  535. while( ((c = pgm_read_byte(pstr)) != '\0') && (n>0) )
  536. {
  537. lcd.print(c);
  538. pstr++;
  539. n--;
  540. }
  541. while(n--)
  542. lcd.print(' ');
  543. lcd.print(post_char);
  544. lcd.print(' ');
  545. }
  546. static void lcd_implementation_drawmenu_setting_edit_generic(uint8_t row, const char* pstr, char pre_char, char* data)
  547. {
  548. char c;
  549. //Use all characters in narrow LCDs
  550. #if LCD_WIDTH < 20
  551. uint8_t n = LCD_WIDTH - 1 - 1 - strlen(data);
  552. #else
  553. uint8_t n = LCD_WIDTH - 1 - 2 - strlen(data);
  554. #endif
  555. lcd.setCursor(0, row);
  556. lcd.print(pre_char);
  557. while( ((c = pgm_read_byte(pstr)) != '\0') && (n>0) )
  558. {
  559. lcd.print(c);
  560. pstr++;
  561. n--;
  562. }
  563. lcd.print(':');
  564. while(n--)
  565. lcd.print(' ');
  566. lcd.print(data);
  567. }
  568. static void lcd_implementation_drawmenu_setting_edit_generic_P(uint8_t row, const char* pstr, char pre_char, const char* data)
  569. {
  570. char c;
  571. //Use all characters in narrow LCDs
  572. #if LCD_WIDTH < 20
  573. uint8_t n = LCD_WIDTH - 1 - 1 - strlen_P(data);
  574. #else
  575. uint8_t n = LCD_WIDTH - 1 - 2 - strlen_P(data);
  576. #endif
  577. lcd.setCursor(0, row);
  578. lcd.print(pre_char);
  579. while( ((c = pgm_read_byte(pstr)) != '\0') && (n>0) )
  580. {
  581. lcd.print(c);
  582. pstr++;
  583. n--;
  584. }
  585. lcd.print(':');
  586. while(n--)
  587. lcd.print(' ');
  588. lcd_printPGM(data);
  589. }
  590. #define lcd_implementation_drawmenu_setting_edit_int3_selected(row, pstr, pstr2, data, minValue, maxValue) lcd_implementation_drawmenu_setting_edit_generic(row, pstr, '>', itostr3(*(data)))
  591. #define lcd_implementation_drawmenu_setting_edit_int3(row, pstr, pstr2, data, minValue, maxValue) lcd_implementation_drawmenu_setting_edit_generic(row, pstr, ' ', itostr3(*(data)))
  592. #define lcd_implementation_drawmenu_setting_edit_float3_selected(row, pstr, pstr2, data, minValue, maxValue) lcd_implementation_drawmenu_setting_edit_generic(row, pstr, '>', ftostr3(*(data)))
  593. #define lcd_implementation_drawmenu_setting_edit_float3(row, pstr, pstr2, data, minValue, maxValue) lcd_implementation_drawmenu_setting_edit_generic(row, pstr, ' ', ftostr3(*(data)))
  594. #define lcd_implementation_drawmenu_setting_edit_float32_selected(row, pstr, pstr2, data, minValue, maxValue) lcd_implementation_drawmenu_setting_edit_generic(row, pstr, '>', ftostr32(*(data)))
  595. #define lcd_implementation_drawmenu_setting_edit_float32(row, pstr, pstr2, data, minValue, maxValue) lcd_implementation_drawmenu_setting_edit_generic(row, pstr, ' ', ftostr32(*(data)))
  596. #define lcd_implementation_drawmenu_setting_edit_float43_selected(row, pstr, pstr2, data, minValue, maxValue) lcd_implementation_drawmenu_setting_edit_generic(row, pstr, '>', ftostr43(*(data)))
  597. #define lcd_implementation_drawmenu_setting_edit_float43(row, pstr, pstr2, data, minValue, maxValue) lcd_implementation_drawmenu_setting_edit_generic(row, pstr, ' ', ftostr43(*(data)))
  598. #define lcd_implementation_drawmenu_setting_edit_float5_selected(row, pstr, pstr2, data, minValue, maxValue) lcd_implementation_drawmenu_setting_edit_generic(row, pstr, '>', ftostr5(*(data)))
  599. #define lcd_implementation_drawmenu_setting_edit_float5(row, pstr, pstr2, data, minValue, maxValue) lcd_implementation_drawmenu_setting_edit_generic(row, pstr, ' ', ftostr5(*(data)))
  600. #define lcd_implementation_drawmenu_setting_edit_float52_selected(row, pstr, pstr2, data, minValue, maxValue) lcd_implementation_drawmenu_setting_edit_generic(row, pstr, '>', ftostr52(*(data)))
  601. #define lcd_implementation_drawmenu_setting_edit_float52(row, pstr, pstr2, data, minValue, maxValue) lcd_implementation_drawmenu_setting_edit_generic(row, pstr, ' ', ftostr52(*(data)))
  602. #define lcd_implementation_drawmenu_setting_edit_float51_selected(row, pstr, pstr2, data, minValue, maxValue) lcd_implementation_drawmenu_setting_edit_generic(row, pstr, '>', ftostr51(*(data)))
  603. #define lcd_implementation_drawmenu_setting_edit_float51(row, pstr, pstr2, data, minValue, maxValue) lcd_implementation_drawmenu_setting_edit_generic(row, pstr, ' ', ftostr51(*(data)))
  604. #define lcd_implementation_drawmenu_setting_edit_long5_selected(row, pstr, pstr2, data, minValue, maxValue) lcd_implementation_drawmenu_setting_edit_generic(row, pstr, '>', ftostr5(*(data)))
  605. #define lcd_implementation_drawmenu_setting_edit_long5(row, pstr, pstr2, data, minValue, maxValue) lcd_implementation_drawmenu_setting_edit_generic(row, pstr, ' ', ftostr5(*(data)))
  606. #define lcd_implementation_drawmenu_setting_edit_bool_selected(row, pstr, pstr2, data) lcd_implementation_drawmenu_setting_edit_generic_P(row, pstr, '>', (*(data))?PSTR(MSG_ON):PSTR(MSG_OFF))
  607. #define lcd_implementation_drawmenu_setting_edit_bool(row, pstr, pstr2, data) lcd_implementation_drawmenu_setting_edit_generic_P(row, pstr, ' ', (*(data))?PSTR(MSG_ON):PSTR(MSG_OFF))
  608. //Add version for callback functions
  609. #define lcd_implementation_drawmenu_setting_edit_callback_int3_selected(row, pstr, pstr2, data, minValue, maxValue, callback) lcd_implementation_drawmenu_setting_edit_generic(row, pstr, '>', itostr3(*(data)))
  610. #define lcd_implementation_drawmenu_setting_edit_callback_int3(row, pstr, pstr2, data, minValue, maxValue, callback) lcd_implementation_drawmenu_setting_edit_generic(row, pstr, ' ', itostr3(*(data)))
  611. #define lcd_implementation_drawmenu_setting_edit_callback_float3_selected(row, pstr, pstr2, data, minValue, maxValue, callback) lcd_implementation_drawmenu_setting_edit_generic(row, pstr, '>', ftostr3(*(data)))
  612. #define lcd_implementation_drawmenu_setting_edit_callback_float3(row, pstr, pstr2, data, minValue, maxValue, callback) lcd_implementation_drawmenu_setting_edit_generic(row, pstr, ' ', ftostr3(*(data)))
  613. #define lcd_implementation_drawmenu_setting_edit_callback_float32_selected(row, pstr, pstr2, data, minValue, maxValue, callback) lcd_implementation_drawmenu_setting_edit_generic(row, pstr, '>', ftostr32(*(data)))
  614. #define lcd_implementation_drawmenu_setting_edit_callback_float32(row, pstr, pstr2, data, minValue, maxValue, callback) lcd_implementation_drawmenu_setting_edit_generic(row, pstr, ' ', ftostr32(*(data)))
  615. #define lcd_implementation_drawmenu_setting_edit_callback_float43_selected(row, pstr, pstr2, data, minValue, maxValue, callback) lcd_implementation_drawmenu_setting_edit_generic(row, pstr, '>', ftostr43(*(data)))
  616. #define lcd_implementation_drawmenu_setting_edit_callback_float43(row, pstr, pstr2, data, minValue, maxValue, callback) lcd_implementation_drawmenu_setting_edit_generic(row, pstr, ' ', ftostr43(*(data)))
  617. #define lcd_implementation_drawmenu_setting_edit_callback_float5_selected(row, pstr, pstr2, data, minValue, maxValue, callback) lcd_implementation_drawmenu_setting_edit_generic(row, pstr, '>', ftostr5(*(data)))
  618. #define lcd_implementation_drawmenu_setting_edit_callback_float5(row, pstr, pstr2, data, minValue, maxValue, callback) lcd_implementation_drawmenu_setting_edit_generic(row, pstr, ' ', ftostr5(*(data)))
  619. #define lcd_implementation_drawmenu_setting_edit_callback_float52_selected(row, pstr, pstr2, data, minValue, maxValue, callback) lcd_implementation_drawmenu_setting_edit_generic(row, pstr, '>', ftostr52(*(data)))
  620. #define lcd_implementation_drawmenu_setting_edit_callback_float52(row, pstr, pstr2, data, minValue, maxValue, callback) lcd_implementation_drawmenu_setting_edit_generic(row, pstr, ' ', ftostr52(*(data)))
  621. #define lcd_implementation_drawmenu_setting_edit_callback_float51_selected(row, pstr, pstr2, data, minValue, maxValue, callback) lcd_implementation_drawmenu_setting_edit_generic(row, pstr, '>', ftostr51(*(data)))
  622. #define lcd_implementation_drawmenu_setting_edit_callback_float51(row, pstr, pstr2, data, minValue, maxValue, callback) lcd_implementation_drawmenu_setting_edit_generic(row, pstr, ' ', ftostr51(*(data)))
  623. #define lcd_implementation_drawmenu_setting_edit_callback_long5_selected(row, pstr, pstr2, data, minValue, maxValue, callback) lcd_implementation_drawmenu_setting_edit_generic(row, pstr, '>', ftostr5(*(data)))
  624. #define lcd_implementation_drawmenu_setting_edit_callback_long5(row, pstr, pstr2, data, minValue, maxValue, callback) lcd_implementation_drawmenu_setting_edit_generic(row, pstr, ' ', ftostr5(*(data)))
  625. #define lcd_implementation_drawmenu_setting_edit_callback_bool_selected(row, pstr, pstr2, data, callback) lcd_implementation_drawmenu_setting_edit_generic_P(row, pstr, '>', (*(data))?PSTR(MSG_ON):PSTR(MSG_OFF))
  626. #define lcd_implementation_drawmenu_setting_edit_callback_bool(row, pstr, pstr2, data, callback) lcd_implementation_drawmenu_setting_edit_generic_P(row, pstr, ' ', (*(data))?PSTR(MSG_ON):PSTR(MSG_OFF))
  627. void lcd_implementation_drawedit(const char* pstr, char* value)
  628. {
  629. lcd.setCursor(1, 1);
  630. lcd_printPGM(pstr);
  631. lcd.print(':');
  632. #if LCD_WIDTH < 20
  633. lcd.setCursor(LCD_WIDTH - strlen(value), 1);
  634. #else
  635. lcd.setCursor(LCD_WIDTH -1 - strlen(value), 1);
  636. #endif
  637. lcd.print(value);
  638. }
  639. static void lcd_implementation_drawmenu_sdfile_selected(uint8_t row, const char* pstr, const char* filename, char* longFilename)
  640. {
  641. char c;
  642. int enc_dif = encoderDiff;
  643. uint8_t n = LCD_WIDTH - 1;
  644. for(int g = 0; g<4;g++){
  645. lcd.setCursor(0, g);
  646. lcd.print(' ');
  647. }
  648. lcd.setCursor(0, row);
  649. lcd.print('>');
  650. if (longFilename[0] != '\0')
  651. {
  652. filename = longFilename;
  653. //longFilename[LCD_WIDTH-1] = '\0';
  654. }
  655. int i = 1;
  656. int j = 0;
  657. int inter = 0;
  658. char* longFilenameTMP = longFilename;
  659. while( ((c = *longFilenameTMP) != '\0') && (inter == 0) )
  660. {
  661. lcd.setCursor(i, row);
  662. lcd.print(c);
  663. i++;
  664. longFilenameTMP++;
  665. if(i==LCD_WIDTH){
  666. i=1;
  667. j++;
  668. longFilenameTMP = longFilename;
  669. longFilenameTMP = longFilenameTMP+j;
  670. n = LCD_WIDTH - 1;
  671. for(int g = 0; ((g<300)&&(inter == 0)) ;g++){
  672. if(LCD_CLICKED || ( enc_dif != encoderDiff )){
  673. inter = 1;
  674. }else{
  675. delay(1);
  676. }
  677. }
  678. }
  679. }
  680. if(c!='\0'){
  681. lcd.setCursor(i, row);
  682. lcd.print(c);
  683. i++;
  684. }
  685. n=n-i+1;
  686. while(n--)
  687. lcd.print(' ');
  688. }
  689. static void lcd_implementation_drawmenu_sdfile(uint8_t row, const char* pstr, const char* filename, char* longFilename)
  690. {
  691. char c;
  692. uint8_t n = LCD_WIDTH - 1;
  693. lcd.setCursor(0, row);
  694. lcd.print(' ');
  695. if (longFilename[0] != '\0')
  696. {
  697. filename = longFilename;
  698. longFilename[LCD_WIDTH-1] = '\0';
  699. }
  700. while( ((c = *filename) != '\0') && (n>0) )
  701. {
  702. lcd.print(c);
  703. filename++;
  704. n--;
  705. }
  706. while(n--)
  707. lcd.print(' ');
  708. }
  709. static void lcd_implementation_drawmenu_sddirectory_selected(uint8_t row, const char* pstr, const char* filename, char* longFilename)
  710. {
  711. char c;
  712. uint8_t n = LCD_WIDTH - 2;
  713. lcd.setCursor(0, row);
  714. lcd.print('>');
  715. lcd.print(LCD_STR_FOLDER[0]);
  716. if (longFilename[0] != '\0')
  717. {
  718. filename = longFilename;
  719. longFilename[LCD_WIDTH-2] = '\0';
  720. }
  721. while( ((c = *filename) != '\0') && (n>0) )
  722. {
  723. lcd.print(c);
  724. filename++;
  725. n--;
  726. }
  727. while(n--)
  728. lcd.print(' ');
  729. }
  730. static void lcd_implementation_drawmenu_sddirectory(uint8_t row, const char* pstr, const char* filename, char* longFilename)
  731. {
  732. char c;
  733. uint8_t n = LCD_WIDTH - 2;
  734. lcd.setCursor(0, row);
  735. lcd.print(' ');
  736. lcd.print(LCD_STR_FOLDER[0]);
  737. if (longFilename[0] != '\0')
  738. {
  739. filename = longFilename;
  740. longFilename[LCD_WIDTH-2] = '\0';
  741. }
  742. while( ((c = *filename) != '\0') && (n>0) )
  743. {
  744. lcd.print(c);
  745. filename++;
  746. n--;
  747. }
  748. while(n--)
  749. lcd.print(' ');
  750. }
  751. #define lcd_implementation_drawmenu_back_selected(row, pstr, data) lcd_implementation_drawmenu_generic(row, pstr, LCD_STR_UPLEVEL[0], LCD_STR_UPLEVEL[0])
  752. #define lcd_implementation_drawmenu_back(row, pstr, data) lcd_implementation_drawmenu_generic(row, pstr, ' ', LCD_STR_UPLEVEL[0])
  753. #define lcd_implementation_drawmenu_submenu_selected(row, pstr, data) lcd_implementation_drawmenu_generic(row, pstr, '>', LCD_STR_ARROW_RIGHT[0])
  754. #define lcd_implementation_drawmenu_submenu(row, pstr, data) lcd_implementation_drawmenu_generic(row, pstr, ' ', LCD_STR_ARROW_RIGHT[0])
  755. #define lcd_implementation_drawmenu_gcode_selected(row, pstr, gcode) lcd_implementation_drawmenu_generic(row, pstr, '>', ' ')
  756. #define lcd_implementation_drawmenu_gcode(row, pstr, gcode) lcd_implementation_drawmenu_generic(row, pstr, ' ', ' ')
  757. #define lcd_implementation_drawmenu_function_selected(row, pstr, data) lcd_implementation_drawmenu_generic(row, pstr, '>', ' ')
  758. #define lcd_implementation_drawmenu_function(row, pstr, data) lcd_implementation_drawmenu_generic(row, pstr, ' ', ' ')
  759. static void lcd_implementation_quick_feedback()
  760. {
  761. #ifdef LCD_USE_I2C_BUZZER
  762. #if !defined(LCD_FEEDBACK_FREQUENCY_HZ) || !defined(LCD_FEEDBACK_FREQUENCY_DURATION_MS)
  763. lcd_buzz(1000/6,100);
  764. #else
  765. lcd_buzz(LCD_FEEDBACK_FREQUENCY_DURATION_MS,LCD_FEEDBACK_FREQUENCY_HZ);
  766. #endif
  767. #elif defined(BEEPER) && BEEPER > -1
  768. SET_OUTPUT(BEEPER);
  769. #if !defined(LCD_FEEDBACK_FREQUENCY_HZ) || !defined(LCD_FEEDBACK_FREQUENCY_DURATION_MS)
  770. for(int8_t i=0;i<10;i++)
  771. {
  772. WRITE(BEEPER,HIGH);
  773. delayMicroseconds(100);
  774. WRITE(BEEPER,LOW);
  775. delayMicroseconds(100);
  776. }
  777. #else
  778. for(int8_t i=0;i<(LCD_FEEDBACK_FREQUENCY_DURATION_MS / (1000 / LCD_FEEDBACK_FREQUENCY_HZ));i++)
  779. {
  780. WRITE(BEEPER,HIGH);
  781. delayMicroseconds(1000000 / LCD_FEEDBACK_FREQUENCY_HZ / 2);
  782. WRITE(BEEPER,LOW);
  783. delayMicroseconds(1000000 / LCD_FEEDBACK_FREQUENCY_HZ / 2);
  784. }
  785. #endif
  786. #endif
  787. }
  788. #ifdef LCD_HAS_STATUS_INDICATORS
  789. static void lcd_implementation_update_indicators()
  790. {
  791. #if defined(LCD_I2C_PANELOLU2) || defined(LCD_I2C_VIKI)
  792. //set the LEDS - referred to as backlights by the LiquidTWI2 library
  793. static uint8_t ledsprev = 0;
  794. uint8_t leds = 0;
  795. if (target_temperature_bed > 0) leds |= LED_A;
  796. if (target_temperature[0] > 0) leds |= LED_B;
  797. if (fanSpeed) leds |= LED_C;
  798. #if EXTRUDERS > 1
  799. if (target_temperature[1] > 0) leds |= LED_C;
  800. #endif
  801. if (leds != ledsprev) {
  802. lcd.setBacklight(leds);
  803. ledsprev = leds;
  804. }
  805. #endif
  806. }
  807. #endif
  808. #ifdef LCD_HAS_SLOW_BUTTONS
  809. extern uint32_t blocking_enc;
  810. static uint8_t lcd_implementation_read_slow_buttons()
  811. {
  812. #ifdef LCD_I2C_TYPE_MCP23017
  813. uint8_t slow_buttons;
  814. // Reading these buttons this is likely to be too slow to call inside interrupt context
  815. // so they are called during normal lcd_update
  816. slow_buttons = lcd.readButtons() << B_I2C_BTN_OFFSET;
  817. #if defined(LCD_I2C_VIKI)
  818. if(slow_buttons & (B_MI|B_RI)) { //LCD clicked
  819. if(blocking_enc > millis()) {
  820. slow_buttons &= ~(B_MI|B_RI); // Disable LCD clicked buttons if screen is updated
  821. }
  822. }
  823. #endif
  824. return slow_buttons;
  825. #endif
  826. }
  827. #endif
  828. #endif//ULTRA_LCD_IMPLEMENTATION_HITACHI_HD44780_H