5151#define BOOT_PROGRESS_WIDTH 300
5252#define BOOT_PROGRESS_HEIGHT 16
5353#define BOOT_PROGRESS_X ((TFT_SCREEN_WIDTH - BOOT_PROGRESS_WIDTH) / 2 )
54- #define BOOT_PROGRESS_Y 235
54+ #define BOOT_PROGRESS_Y 195
5555
5656#include " web_server.h"
5757
@@ -67,8 +67,39 @@ struct image_render_state {
6767 int16_t ypos;
6868};
6969
70+ LcdTask::Message::Message (const __FlashStringHelper *msg, int x, int y, int time, uint32_t flags) :
71+ _next(NULL ),
72+ _msg(" " ),
73+ _x(x),
74+ _y(y),
75+ _time(time),
76+ _clear(flags & LCD_CLEAR_LINE ? 1 : 0 )
77+ {
78+ strncpy_P (_msg, reinterpret_cast <PGM_P>(msg), LCD_MAX_LEN);
79+ _msg[LCD_MAX_LEN] = ' \0 ' ;
80+ }
81+
82+ LcdTask::Message::Message (String &msg, int x, int y, int time, uint32_t flags) :
83+ Message(msg.c_str(), x, y, time, flags)
84+ {
85+ }
86+
87+ LcdTask::Message::Message (const char *msg, int x, int y, int time, uint32_t flags) :
88+ _next(NULL ),
89+ _msg(" " ),
90+ _x(x),
91+ _y(y),
92+ _time(time),
93+ _clear(flags & LCD_CLEAR_LINE ? 1 : 0 )
94+ {
95+ strncpy (_msg, msg, LCD_MAX_LEN);
96+ _msg[LCD_MAX_LEN] = ' \0 ' ;
97+ }
98+
7099LcdTask::LcdTask () :
71100 MicroTasks::Task(),
101+ _head(NULL ),
102+ _tail(NULL ),
72103 _tft(),
73104#ifdef ENABLE_DOUBLE_BUFFER
74105 _back_buffer (&_tft),
@@ -77,18 +108,53 @@ LcdTask::LcdTask() :
77108 _screen (_tft)
78109#endif
79110{
111+ for (int i = 0 ; i < LCD_MAX_LINES; i++) {
112+ clearLine (i);
113+ }
114+ _msg_cleared = true ;
115+ }
116+
117+ void LcdTask::display (Message *msg, uint32_t flags)
118+ {
119+ if (flags & LCD_DISPLAY_NOW)
120+ {
121+ for (Message *next, *node = _head; node; node = next) {
122+ next = node->getNext ();
123+ delete node;
124+ }
125+ _head = NULL ;
126+ _tail = NULL ;
127+ }
128+
129+ if (_tail) {
130+ _tail->setNext (msg);
131+ } else {
132+ _head = msg;
133+ _nextMessageTime = millis ();
134+ }
135+ _tail = msg;
136+
137+ if (flags & LCD_DISPLAY_NOW) {
138+ displayNextMessage ();
139+ }
80140}
81141
82142void LcdTask::display (const __FlashStringHelper *msg, int x, int y, int time, uint32_t flags)
83143{
144+ DBUGVAR (msg);
145+ display (new Message (msg, x, y, time, flags), flags);
84146}
85147
86148void LcdTask::display (String &msg, int x, int y, int time, uint32_t flags)
87149{
150+ DBUGVAR (msg);
151+ display (new Message (msg, x, y, time, flags), flags);
88152}
89153
90154void LcdTask::display (const char *msg, int x, int y, int time, uint32_t flags)
91155{
156+ DBUGVAR (msg);
157+ display (new Message (msg, x, y, time, flags), flags);
92158}
93159
94160void LcdTask::begin (EvseManager &evse, Scheduler &scheduler, ManualOverride &manual)
@@ -134,6 +200,20 @@ unsigned long LcdTask::loop(MicroTasks::WakeReason reason)
134200 _initialise = false ;
135201 }
136202
203+ // If we have messages to display, do it
204+ if (_head) {
205+ nextUpdate = displayNextMessage ();
206+ }
207+ DBUGVAR (_nextMessageTime);
208+ if (!_msg_cleared && millis () >= _nextMessageTime)
209+ {
210+ DBUGLN (" Clearing message lines" );
211+ for (int i = 0 ; i < LCD_MAX_LINES; i++) {
212+ clearLine (i);
213+ }
214+ _msg_cleared = true ;
215+ }
216+
137217#ifdef ENABLE_DOUBLE_BUFFER
138218 _tft.startWrite ();
139219#endif
@@ -147,8 +227,8 @@ unsigned long LcdTask::loop(MicroTasks::WakeReason reason)
147227 if (_full_update)
148228 {
149229 _screen.fillScreen (TFT_OPENEVSE_BACK);
150- _screen.fillSmoothRoundRect (90 , 90 , 300 , 110 , 15 , TFT_WHITE);
151- render_image (" /logo.png" , 104 , 115 );
230+ _screen.fillSmoothRoundRect (90 , 60 , 300 , 110 , 15 , TFT_WHITE);
231+ render_image (" /logo.png" , 104 , 85 );
152232 _full_update = false ;
153233 }
154234
@@ -170,6 +250,15 @@ unsigned long LcdTask::loop(MicroTasks::WakeReason reason)
170250 sprite.deleteSprite ();
171251 _boot_progress += 10 ;
172252
253+ String line = getLine (0 );
254+ if (line.length () > 0 ) {
255+ render_centered_text_box (line.c_str (), 0 , 250 , TFT_SCREEN_WIDTH, &FreeSans9pt7b, TFT_WHITE, TFT_OPENEVSE_BACK, !_full_update);
256+ }
257+ line = getLine (1 );
258+ if (line.length () > 0 ) {
259+ render_centered_text_box (line.c_str (), 0 , 270 , TFT_SCREEN_WIDTH, &FreeSans9pt7b, TFT_WHITE, TFT_OPENEVSE_BACK, !_full_update);
260+ }
261+
173262 nextUpdate = 166 ;
174263 if (_boot_progress >= 300 ) {
175264 _state = State::Charge;
@@ -234,14 +323,23 @@ unsigned long LcdTask::loop(MicroTasks::WakeReason reason)
234323 render_left_text_box (" A" , 224 , 200 , 34 , &FreeSans24pt7b, TFT_BLACK, TFT_WHITE, false , 1 );
235324 }
236325
237- render_centered_text_box (esp_hostname.c_str (), INFO_BOX_X, 74 , INFO_BOX_WIDTH, &FreeSans9pt7b, TFT_OPENEVSE_TEXT, TFT_WHITE, !_full_update);
326+ String line = getLine (0 );
327+ if (line.length () == 0 ) {
328+ line = esp_hostname;
329+ }
330+ render_centered_text_box (line.c_str (), INFO_BOX_X, 74 , INFO_BOX_WIDTH, &FreeSans9pt7b, TFT_OPENEVSE_TEXT, TFT_WHITE, !_full_update);
238331
239- timeval local_time;
240- gettimeofday (&local_time, NULL );
241- struct tm timeinfo;
242- localtime_r (&local_time.tv_sec , &timeinfo);
243- strftime (buffer, sizeof (buffer), " %d/%m/%Y, %l:%M %p" , &timeinfo);
244- render_centered_text_box (buffer, INFO_BOX_X, 96 , INFO_BOX_WIDTH, &FreeSans9pt7b, TFT_OPENEVSE_TEXT, TFT_WHITE, !_full_update);
332+ line = getLine (1 );
333+ if (line.length () == 0 )
334+ {
335+ timeval local_time;
336+ gettimeofday (&local_time, NULL );
337+ struct tm timeinfo;
338+ localtime_r (&local_time.tv_sec , &timeinfo);
339+ strftime (buffer, sizeof (buffer), " %d/%m/%Y, %l:%M %p" , &timeinfo);
340+ line = buffer;
341+ }
342+ render_centered_text_box (line.c_str (), INFO_BOX_X, 96 , INFO_BOX_WIDTH, &FreeSans9pt7b, TFT_OPENEVSE_TEXT, TFT_WHITE, !_full_update);
245343
246344 uint32_t elapsed = _evse->getSessionElapsed ();
247345 uint32_t hours = elapsed / 3600 ;
@@ -349,17 +447,17 @@ void LcdTask::render_image(const char *filename, int16_t x, int16_t y)
349447 StaticFile *file = NULL ;
350448 if (embedded_get_file (filename, lcd_gui_static_files, ARRAY_LENGTH (lcd_gui_static_files), &file))
351449 {
352- DBUGF (" Found %s (%d bytes)" , filename, file->length );
450+ // DBUGF("Found %s (%d bytes)", filename, file->length);
353451 int16_t rc = png.openFLASH ((uint8_t *)file->data , file->length , png_draw);
354452 if (rc == PNG_SUCCESS)
355453 {
356- DBUGLN (" Successfully opened png file" );
357- DBUGF (" image specs: (%d x %d), %d bpp, pixel type: %d\n " , png.getWidth (), png.getHeight (), png.getBpp (), png.getPixelType ());
454+ // DBUGLN("Successfully opened png file");
455+ // DBUGF("image specs: (%d x %d), %d bpp, pixel type: %d", png.getWidth(), png.getHeight(), png.getBpp(), png.getPixelType());
358456 _screen.startWrite ();
359457 uint32_t dt = millis ();
360458 image_render_state state = {&_screen, x, y};
361459 rc = png.decode (&state, 0 );
362- DBUG (millis () - dt); DBUGLN (" ms" );
460+ // DBUG(millis() - dt); DBUGLN("ms");
363461 _screen.endWrite ();
364462 // png.close(); // not needed for memory->memory decode
365463 }
@@ -386,6 +484,76 @@ void LcdTask::png_draw(PNGDRAW *pDraw)
386484 state->tft ->pushImage (state->xpos , state->ypos + pDraw->y , pDraw->iWidth , 1 , lineBuffer);
387485}
388486
487+ unsigned long LcdTask::displayNextMessage ()
488+ {
489+ while (_head && millis () >= _nextMessageTime)
490+ {
491+ // Pop a message from the queue
492+ Message *msg = _head;
493+ DBUGF (" msg = %p" , msg);
494+ _head = _head->getNext ();
495+ if (NULL == _head) {
496+ _tail = NULL ;
497+ }
498+
499+ // Display the message
500+ showText (msg->getX (), msg->getY (), msg->getMsg (), msg->getClear ());
501+
502+ _nextMessageTime = millis () + msg->getTime ();
503+
504+ // delete the message
505+ delete msg;
506+ }
507+
508+ unsigned long nextUpdate = _nextMessageTime - millis ();
509+ DBUGVAR (nextUpdate);
510+ return nextUpdate;
511+ }
512+
513+ void LcdTask::showText (int x, int y, const char *msg, bool clear)
514+ {
515+ DBUGF (" LCD: %d %d %s, clear=%s" , x, y, msg, clear ? " true" : " false" );
516+
517+ if (clear) {
518+ clearLine (y);
519+ }
520+
521+ strncpy (_msg[y], msg + x, LCD_MAX_LEN - x);
522+ _msg[y][LCD_MAX_LEN] = ' \0 ' ;
523+ _msg_cleared = false ;
524+ }
525+
526+ void LcdTask::clearLine (int line)
527+ {
528+ if (line < 0 || line >= LCD_MAX_LINES) {
529+ return ;
530+ }
531+
532+ memset (_msg[line], ' ' , LCD_MAX_LEN);
533+ _msg[line][LCD_MAX_LEN] = ' \0 ' ;
534+ }
535+
536+ String LcdTask::getLine (int line)
537+ {
538+ if (line < 0 || line >= LCD_MAX_LINES) {
539+ return " " ;
540+ }
541+
542+ // trim leading and trailing spaces
543+ int len = LCD_MAX_LEN;
544+ while (len > 0 && _msg[line][len - 1 ] == ' ' ) {
545+ len--;
546+ }
547+ char *start = _msg[line];
548+ while (len > 0 && *start == ' ' ) {
549+ start++;
550+ len--;
551+ }
552+
553+ return String (start, len);
554+ }
555+
556+
389557LcdTask lcd;
390558
391559#endif // ENABLE_SCREEN_LCD_lcd
0 commit comments