No Description
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.

lcd.cpp 9.1KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331
  1. #include <Arduino.h>
  2. #include "config.h"
  3. #include "config_pins.h"
  4. #include "lcd.h"
  5. #if (defined(USE_20X4_TEXT_LCD) && defined(USE_FULL_GRAPHIC_LCD)) || (!defined(USE_20X4_TEXT_LCD) && !defined(USE_FULL_GRAPHIC_LCD))
  6. #error define one of USE_20X4_TEXT_LCD or USE_FULL_GRAPHIC_LCD
  7. #endif
  8. #ifdef USE_20X4_TEXT_LCD
  9. #include <LiquidCrystal.h>
  10. #define LCD_HEADING_LINES 1
  11. #define LCD_HEADING_WIDTH 20
  12. #define LCD_TEXT_LINES 3
  13. #define LCD_TEXT_WIDTH 20
  14. LiquidCrystal lcd(LCD_PINS_RS, LCD_PINS_ENABLE, LCD_PINS_D4, LCD_PINS_D5, LCD_PINS_D6, LCD_PINS_D7);
  15. #endif // USE_20X4_TEXT_LCD
  16. #ifdef USE_FULL_GRAPHIC_LCD
  17. #include <U8g2lib.h>
  18. //#define ENABLE_DYNAMIC_SCROLLING
  19. #define LCD_HEADING_LINES 1
  20. #define LCD_HEADING_WIDTH 15
  21. #define LCD_TEXT_LINES 5
  22. #define LCD_TEXT_WIDTH 25
  23. #define LCD_HEADING_FONT u8g2_font_torussansbold8_8r
  24. #define LCD_TEXT_FONT u8g2_font_5x7_tr
  25. #define LCD_HEADING_TEXT_OFFSET 3
  26. #define LCD_HEADING_HEIGHT 8
  27. #define LCD_TEXT_HEIGHT 9
  28. U8G2_ST7920_128X64_1_SW_SPI lcd(U8G2_R0, LCD_PINS_SCK, LCD_PINS_MOSI, LCD_PINS_CS);
  29. #endif // USE_FULL_GRAPHIC_LCD
  30. String heading[LCD_HEADING_LINES];
  31. String text[LCD_TEXT_LINES];
  32. String heading_pre, heading_post;
  33. String text_pre, text_post;
  34. int heading_direction, text_direction;
  35. String menu_pre[LCD_TEXT_LINES], menu_post[LCD_TEXT_LINES];
  36. int menu_dir[LCD_TEXT_LINES];
  37. boolean redraw = false;
  38. enum lcd_text_mode {
  39. lcd_mode_none,
  40. lcd_mode_multiline,
  41. lcd_mode_menu
  42. };
  43. enum lcd_text_mode text_mode = lcd_mode_none;
  44. #define SCROLL_DELAY 500
  45. unsigned long last_scroll_time = 0;
  46. #define IS_TEXT_CHAR(x) (((x >= 'a') && (x <= 'z')) || ((x >= 'A') && (x <= 'Z')))
  47. void lcd_shorten_multiline(String s[], int n, int w, String *remainder) {
  48. String for_next_line = "";
  49. for (int i = 0; i < n; i++) {
  50. // take previously stored string and put in front of line
  51. s[i] = for_next_line + s[i];
  52. for_next_line = "";
  53. // if a line is longer then w, take end off and store
  54. if (s[i].length() > w) {
  55. for_next_line += s[i].substring(w);
  56. s[i] = s[i].substring(0, w);
  57. }
  58. // if a newline is in this line, end the text there and split it
  59. for (int j = 0; j < s[i].length(); j++) {
  60. if (s[i][j] == '\n') {
  61. for_next_line = s[i].substring(j + 1) + for_next_line;
  62. s[i] = s[i].substring(0, j);
  63. break;
  64. }
  65. }
  66. // if the last char of this line and the first char of for_next_line
  67. // exist and are both upper/lowercase characters, check if one of the
  68. // previous 5 chars is a space, and instead split there
  69. if ((n > 1) && (for_next_line.length() > 0) && IS_TEXT_CHAR(s[i][s[i].length() - 1]) && IS_TEXT_CHAR(for_next_line[0])) {
  70. for (int j = s[i].length() - 2; (j >= 0) && (j >= s[i].length() - 2 - 5); j--) {
  71. if (s[i][j] == ' ') {
  72. for_next_line = s[i].substring(j + 1) + for_next_line;
  73. s[i] = s[i].substring(0, j + 1);
  74. break;
  75. }
  76. }
  77. }
  78. }
  79. // if something remains at end, store remainder, if given, otherwise leave at last line
  80. if (remainder != NULL) {
  81. *remainder = for_next_line;
  82. } else {
  83. s[n - 1] = s[n - 1] + for_next_line;
  84. }
  85. last_scroll_time = millis();
  86. }
  87. #ifdef ENABLE_DYNAMIC_SCROLLING
  88. void lcd_scroll_multiline(String s[], int n, int w, String &pre, String &post, int &dir) {
  89. if (dir == 0) {
  90. // switch directions if done scrolling in current direction
  91. if (post.length() == 0) {
  92. dir = 1;
  93. return;
  94. }
  95. // take first char of first line, append to pre
  96. pre = pre + s[0][0];
  97. s[0] = s[0].substring(1);
  98. // shift now empty spot to the left through lines
  99. for (int i = 1; i < n; i++) {
  100. s[i - 1] = s[i - 1] + s[i][0];
  101. s[i] = s[i].substring(1);
  102. }
  103. // fill empty spot at end of last line with first char of post
  104. s[n - 1] = s[n - 1] + post[0];
  105. post = post.substring(1);
  106. } else {
  107. // switch directions if done scrolling in current direction
  108. if (pre.length() == 0) {
  109. dir = 0;
  110. return;
  111. }
  112. // take last char of last line, prepend to post
  113. post = s[n - 1][s[n - 1].length() - 1] + post;
  114. s[n - 1] = s[n - 1].substring(0, s[n - 1].length() - 1);
  115. // shift now empty sport to the right through lines
  116. for (int i = n - 1; i >= 1; i--) {
  117. s[i] = s[i - 1][s[i - 1].length() - 1] + s[i];
  118. s[i - 1] = s[i - 1].substring(0, s[i - 1].length() - 1);
  119. }
  120. // fill empty spot at beginning with last char of pre
  121. s[0] = pre[pre.length() - 1] + s[0];
  122. pre = pre.substring(0, pre.length() - 1);
  123. }
  124. redraw = true;
  125. }
  126. void lcd_scrolling(void) {
  127. if (text_mode != lcd_mode_none) {
  128. if ((heading_pre.length() > 0) || (heading_post.length() > 0)) {
  129. lcd_scroll_multiline(heading, LCD_HEADING_LINES, LCD_HEADING_WIDTH,
  130. heading_pre, heading_post, heading_direction);
  131. }
  132. }
  133. if (text_mode == lcd_mode_multiline) {
  134. if ((text_pre.length() > 0) || (text_post.length() > 0)) {
  135. lcd_scroll_multiline(text, LCD_TEXT_LINES, LCD_TEXT_WIDTH,
  136. text_pre, text_post, text_direction);
  137. }
  138. } else if (text_mode == lcd_mode_menu) {
  139. for (int i = 0; i < LCD_TEXT_LINES; i++) {
  140. if ((menu_pre[i].length() > 0) || (menu_post[i].length() > 0)) {
  141. lcd_scroll_multiline(text + i, 1, LCD_TEXT_WIDTH,
  142. menu_pre[i], menu_post[i], menu_dir[i]);
  143. }
  144. }
  145. }
  146. }
  147. #endif // ENABLE_DYNAMIC_SCROLLING
  148. int lcd_text_lines(void) {
  149. return LCD_TEXT_LINES;
  150. }
  151. void lcd_init(void) {
  152. #ifdef USE_20X4_TEXT_LCD
  153. lcd.begin(20, 4);
  154. lcd.clear();
  155. lcd.print(F(" Fuellfix v2 "));
  156. lcd.print(F(" Initializing.... "));
  157. lcd.print(F("Software Version "));
  158. lcd.print(F(FIRMWARE_VERSION));
  159. lcd.print(F("made by: xythobuz.de"));
  160. #endif // USE_20X4_TEXT_LCD
  161. #ifdef USE_FULL_GRAPHIC_LCD
  162. lcd.begin();
  163. lcd.firstPage();
  164. do {
  165. lcd.setFont(u8g2_font_luBS12_tr);
  166. String s = F("Fuellfix v2");
  167. lcd.drawStr(0, 14 * 1, s.c_str());
  168. s = F("Initializing");
  169. lcd.drawStr(0, 14 * 2, s.c_str());
  170. lcd.setFont(u8g2_font_t0_12b_tr);
  171. s = F("Software Version " FIRMWARE_VERSION);
  172. lcd.drawStr(0, 14 * 2 + 8 + 12 * 1, s.c_str());
  173. s = F("made by: xythobuz.de");
  174. lcd.drawStr(0, 14 * 2 + 8 + 12 * 2, s.c_str());
  175. } while (lcd.nextPage());
  176. #endif // USE_FULL_GRAPHIC_LCD
  177. }
  178. void lcd_loop(void) {
  179. #ifdef ENABLE_DYNAMIC_SCROLLING
  180. if ((millis() - last_scroll_time) >= SCROLL_DELAY) {
  181. last_scroll_time = millis();
  182. lcd_scrolling();
  183. }
  184. #endif // ENABLE_DYNAMIC_SCROLLING
  185. #ifdef USE_FULL_GRAPHIC_LCD
  186. if (redraw) {
  187. lcd.firstPage();
  188. do {
  189. lcd.setFont(LCD_HEADING_FONT);
  190. for (int i = 0; i < LCD_HEADING_LINES; i++) {
  191. lcd.drawStr(0, LCD_HEADING_HEIGHT * (i + 1), heading[i].c_str());
  192. }
  193. lcd.setFont(LCD_TEXT_FONT);
  194. for (int i = 0; i < LCD_TEXT_LINES; i++) {
  195. lcd.drawStr(0, LCD_HEADING_HEIGHT * LCD_HEADING_LINES + LCD_HEADING_TEXT_OFFSET + LCD_TEXT_HEIGHT * (i + 1), text[i].c_str());
  196. }
  197. } while (lcd.nextPage());
  198. redraw = false;
  199. }
  200. #endif // USE_FULL_GRAPHIC_LCD
  201. }
  202. void lcd_clear(void) {
  203. Serial.println();
  204. text_mode = lcd_mode_none;
  205. #ifdef USE_20X4_TEXT_LCD
  206. lcd.clear();
  207. #endif // USE_20X4_TEXT_LCD
  208. #ifdef USE_FULL_GRAPHIC_LCD
  209. for (int i = 0; i < LCD_HEADING_LINES; i++) {
  210. heading[i] = "";
  211. }
  212. for (int i = 0; i < LCD_TEXT_LINES; i++) {
  213. text[i] = "";
  214. }
  215. redraw = true;
  216. #endif // USE_FULL_GRAPHIC_LCD
  217. }
  218. void lcd_set_heading(const char *h) {
  219. Serial.println(h);
  220. #ifdef USE_20X4_TEXT_LCD
  221. lcd.setCursor(0, 0);
  222. lcd.print(h);
  223. #endif // USE_20X4_TEXT_LCD
  224. #ifdef USE_FULL_GRAPHIC_LCD
  225. heading[0] = h;
  226. heading_pre = "";
  227. heading_direction = 0;
  228. lcd_shorten_multiline(heading, LCD_HEADING_LINES, LCD_HEADING_WIDTH, &heading_post);
  229. redraw = true;
  230. #endif // USE_FULL_GRAPHIC_LCD
  231. }
  232. void lcd_set_text(const char *t) {
  233. Serial.println(t);
  234. text_mode = lcd_mode_multiline;
  235. #ifdef USE_20X4_TEXT_LCD
  236. lcd.setCursor(0, LCD_HEADING_LINES);
  237. lcd.print(t);
  238. #endif // USE_20X4_TEXT_LCD
  239. #ifdef USE_FULL_GRAPHIC_LCD
  240. text[0] = t;
  241. text_pre = "";
  242. text_direction = 0;
  243. lcd_shorten_multiline(text, LCD_TEXT_LINES, LCD_TEXT_WIDTH, &text_post);
  244. redraw = true;
  245. #endif // USE_FULL_GRAPHIC_LCD
  246. }
  247. void lcd_set_menu_text(int line, const char *t) {
  248. Serial.print(line);
  249. Serial.print(F(": "));
  250. Serial.println(t);
  251. text_mode = lcd_mode_menu;
  252. #ifdef USE_20X4_TEXT_LCD
  253. lcd.setCursor(0, LCD_HEADING_LINES + line);
  254. lcd.print(t);
  255. #endif // USE_20X4_TEXT_LCD
  256. #ifdef USE_FULL_GRAPHIC_LCD
  257. text[line] = t;
  258. menu_pre[line] = "";
  259. menu_dir[line] = 0;
  260. lcd_shorten_multiline(text + line, 1, LCD_TEXT_WIDTH, menu_post + line);
  261. redraw = true;
  262. #endif // USE_FULL_GRAPHIC_LCD
  263. }