#include #include "config.h" #include "config_pins.h" #include "lcd.h" #if (defined(USE_20X4_TEXT_LCD) && defined(USE_FULL_GRAPHIC_LCD)) || (!defined(USE_20X4_TEXT_LCD) && !defined(USE_FULL_GRAPHIC_LCD)) #error define one of USE_20X4_TEXT_LCD or USE_FULL_GRAPHIC_LCD #endif #ifdef USE_20X4_TEXT_LCD #include #define LCD_HEADING_LINES 1 #define LCD_HEADING_WIDTH 20 #define LCD_TEXT_LINES 3 #define LCD_TEXT_WIDTH 20 LiquidCrystal lcd(LCD_PINS_RS, LCD_PINS_ENABLE, LCD_PINS_D4, LCD_PINS_D5, LCD_PINS_D6, LCD_PINS_D7); #endif // USE_20X4_TEXT_LCD #ifdef USE_FULL_GRAPHIC_LCD #include #define LCD_HEADING_LINES 1 #define LCD_HEADING_WIDTH 15 #define LCD_TEXT_LINES 5 #define LCD_TEXT_WIDTH 25 #define LCD_HEADING_FONT u8g2_font_torussansbold8_8r #define LCD_TEXT_FONT u8g2_font_5x7_tr #define LCD_HEADING_TEXT_OFFSET 3 #define LCD_HEADING_HEIGHT 8 #define LCD_TEXT_HEIGHT 9 U8G2_ST7920_128X64_1_SW_SPI lcd(U8G2_R0, LCD_PINS_SCK, LCD_PINS_MOSI, LCD_PINS_CS); #endif // USE_FULL_GRAPHIC_LCD String heading[LCD_HEADING_LINES]; String text[LCD_TEXT_LINES]; String heading_pre, heading_post; String text_pre, text_post; int heading_direction, text_direction; String menu_pre[LCD_TEXT_LINES], menu_post[LCD_TEXT_LINES]; int menu_dir[LCD_TEXT_LINES]; boolean redraw = false; enum lcd_text_mode { lcd_mode_none, lcd_mode_multiline, lcd_mode_menu }; enum lcd_text_mode text_mode = lcd_mode_none; #define SCROLL_DELAY 500 unsigned long last_scroll_time = 0; void lcd_shorten_multiline(String s[], int n, int w, String *remainder) { // if a line is longer then w, take end off and put in front of next line String for_next_line = ""; for (int i = 0; i < n; i++) { s[i] = for_next_line + s[i]; for_next_line = ""; if (s[i].length() > w) { for_next_line = s[i].substring(w); s[i] = s[i].substring(0, w); } } // if something remains at end, store remainder, if given, otherwise leave at last line if (remainder != NULL) { *remainder = for_next_line; } else { s[n - 1] = s[n - 1] + for_next_line; } last_scroll_time = millis(); } void lcd_scroll_multiline(String s[], int n, int w, String &pre, String &post, int &dir) { if (dir == 0) { // switch directions if done scrolling in current direction if (post.length() == 0) { dir = 1; return; } // take first char of first line, append to pre pre = pre + s[0][0]; s[0] = s[0].substring(1); // shift now empty spot to the left through lines for (int i = 1; i < n; i++) { s[i - 1] = s[i - 1] + s[i][0]; s[i] = s[i].substring(1); } // fill empty spot at end of last line with first char of post s[n - 1] = s[n - 1] + post[0]; post = post.substring(1); } else { // switch directions if done scrolling in current direction if (pre.length() == 0) { dir = 0; return; } // take last char of last line, prepend to post post = s[n - 1][s[n - 1].length() - 1] + post; s[n - 1] = s[n - 1].substring(0, s[n - 1].length() - 1); // shift now empty sport to the right through lines for (int i = n - 1; i >= 1; i--) { s[i] = s[i - 1][s[i - 1].length() - 1] + s[i]; s[i - 1] = s[i - 1].substring(0, s[i - 1].length() - 1); } // fill empty spot at beginning with last char of pre s[0] = pre[pre.length() - 1] + s[0]; pre = pre.substring(0, pre.length() - 1); } redraw = true; } void lcd_scrolling(void) { if (text_mode != lcd_mode_none) { if ((heading_pre.length() > 0) || (heading_post.length() > 0)) { lcd_scroll_multiline(heading, LCD_HEADING_LINES, LCD_HEADING_WIDTH, heading_pre, heading_post, heading_direction); } } if (text_mode == lcd_mode_multiline) { if ((text_pre.length() > 0) || (text_post.length() > 0)) { lcd_scroll_multiline(text, LCD_TEXT_LINES, LCD_TEXT_WIDTH, text_pre, text_post, text_direction); } } else if (text_mode == lcd_mode_menu) { for (int i = 0; i < LCD_TEXT_LINES; i++) { if ((menu_pre[i].length() > 0) || (menu_post[i].length() > 0)) { lcd_scroll_multiline(text + i, 1, LCD_TEXT_WIDTH, menu_pre[i], menu_post[i], menu_dir[i]); } } } } int lcd_text_lines(void) { return LCD_TEXT_LINES; } void lcd_init(void) { #ifdef USE_20X4_TEXT_LCD lcd.begin(20, 4); lcd.clear(); lcd.print(F(" Fuellfix v2 ")); lcd.print(F(" Initializing.... ")); lcd.print(F("Software Version ")); lcd.print(F(FIRMWARE_VERSION)); lcd.print(F("made by: xythobuz.de")); #endif // USE_20X4_TEXT_LCD #ifdef USE_FULL_GRAPHIC_LCD lcd.begin(); lcd.firstPage(); do { lcd.setFont(u8g2_font_luBS12_tr); lcd.drawStr(0, 14 * 1, "Fuellfix v2"); lcd.drawStr(0, 14 * 2, "Initializing"); lcd.setFont(u8g2_font_t0_12b_tr); lcd.drawStr(0, 14 * 2 + 8 + 12 * 1, "Software Version " FIRMWARE_VERSION); lcd.drawStr(0, 14 * 2 + 8 + 12 * 2, "made by: xythobuz.de"); } while (lcd.nextPage()); #endif // USE_FULL_GRAPHIC_LCD } void lcd_loop(void) { if ((millis() - last_scroll_time) >= SCROLL_DELAY) { last_scroll_time = millis(); lcd_scrolling(); } #ifdef USE_FULL_GRAPHIC_LCD if (redraw) { lcd.firstPage(); do { lcd.setFont(LCD_HEADING_FONT); for (int i = 0; i < LCD_HEADING_LINES; i++) { lcd.drawStr(0, LCD_HEADING_HEIGHT * (i + 1), heading[i].c_str()); } lcd.setFont(LCD_TEXT_FONT); for (int i = 0; i < LCD_TEXT_LINES; i++) { lcd.drawStr(0, LCD_HEADING_HEIGHT * LCD_HEADING_LINES + LCD_HEADING_TEXT_OFFSET + LCD_TEXT_HEIGHT * (i + 1), text[i].c_str()); } } while (lcd.nextPage()); redraw = false; } #endif // USE_FULL_GRAPHIC_LCD } void lcd_clear(void) { Serial.println(); text_mode = lcd_mode_none; #ifdef USE_20X4_TEXT_LCD lcd.clear(); #endif // USE_20X4_TEXT_LCD #ifdef USE_FULL_GRAPHIC_LCD for (int i = 0; i < LCD_HEADING_LINES; i++) { heading[i] = ""; } for (int i = 0; i < LCD_TEXT_LINES; i++) { text[i] = ""; } redraw = true; #endif // USE_FULL_GRAPHIC_LCD } void lcd_set_heading(const char *h) { Serial.println(h); #ifdef USE_20X4_TEXT_LCD lcd.setCursor(0, 0); lcd.print(h); #endif // USE_20X4_TEXT_LCD #ifdef USE_FULL_GRAPHIC_LCD heading[0] = h; heading_pre = ""; heading_direction = 0; lcd_shorten_multiline(heading, LCD_HEADING_LINES, LCD_HEADING_WIDTH, &heading_post); redraw = true; #endif // USE_FULL_GRAPHIC_LCD } void lcd_set_text(const char *t) { Serial.println(t); text_mode = lcd_mode_multiline; #ifdef USE_20X4_TEXT_LCD lcd.setCursor(0, LCD_HEADING_LINES); lcd.print(t); #endif // USE_20X4_TEXT_LCD #ifdef USE_FULL_GRAPHIC_LCD text[0] = t; text_pre = ""; text_direction = 0; lcd_shorten_multiline(text, LCD_TEXT_LINES, LCD_TEXT_WIDTH, &text_post); redraw = true; #endif // USE_FULL_GRAPHIC_LCD } void lcd_set_menu_text(int line, const char *t) { Serial.print(line); Serial.print(": "); Serial.println(t); text_mode = lcd_mode_menu; #ifdef USE_20X4_TEXT_LCD lcd.setCursor(0, LCD_HEADING_LINES + line); lcd.print(t); #endif // USE_20X4_TEXT_LCD #ifdef USE_FULL_GRAPHIC_LCD text[line] = t; menu_pre[line] = ""; menu_dir[line] = 0; lcd_shorten_multiline(text + line, 1, LCD_TEXT_WIDTH, menu_post + line); redraw = true; #endif // USE_FULL_GRAPHIC_LCD }