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.0KB

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