@@ -128,6 +128,8 @@ long lastDownloadUpdate = millis();
128128uint16_t screen = 0 ;
129129long timerPress;
130130bool canBtnPress;
131+ bool sleep_mode ();
132+ char * make12_24 (int hour);
131133
132134void connectWifi () {
133135 if (WiFi.status () == WL_CONNECTED) return ;
@@ -237,60 +239,101 @@ TS_Point points[10];
237239uint8_t currentTouchPoint = 0 ;
238240
239241void loop () {
242+ static bool asleep = false ; // asleep used to stop screen change after touch for wake-up
240243 gfx.fillBuffer (MINI_BLACK);
241244 if (touchController.isTouched (0 )) {
242245 TS_Point p = touchController.getPoint ();
246+ timerPress = millis ();
243247
244248 Serial.printf (" Touch point detected at %d/%d.\n " , p.x , p.y );
245-
246- if (p.y < 80 ) {
247- IS_STYLE_12HR = !IS_STYLE_12HR;
248- } else {
249- screen = (screen + 1 ) % screenCount;
249+ if (!asleep) { // no need to change screens;
250+ if (p.y < 80 ) {
251+ IS_STYLE_12HR = !IS_STYLE_12HR;
252+ } else {
253+ screen = (screen + 1 ) % screenCount;
254+ }
250255 }
251- }
256+ } // isTouched()
257+
258+ if (!(asleep = sleep_mode ())) {
259+ if (screen == 0 ) {
260+ drawTime ();
261+
262+ drawWifiQuality ();
263+ int remainingTimeBudget = carousel.update ();
264+ if (remainingTimeBudget > 0 ) {
265+ // You can do some work here
266+ // Don't do stuff if you are below your
267+ // time budget.
268+ delay (remainingTimeBudget);
269+ }
270+ drawCurrentWeather ();
271+ drawAstronomy ();
272+ } else if (screen == 1 ) {
273+ drawCurrentWeatherDetail ();
274+ } else if (screen == 2 ) {
275+ drawForecastTable (0 );
276+ } else if (screen == 3 ) {
277+ drawForecastTable (4 );
278+ } else if (screen == 4 ) {
279+ drawAbout ();
280+ }
281+ gfx.commit ();
252282
253- if (screen == 0 ) {
254- drawTime ();
255- drawWifiQuality ();
256- int remainingTimeBudget = carousel.update ();
257- if (remainingTimeBudget > 0 ) {
258- // You can do some work here
259- // Don't do stuff if you are below your
260- // time budget.
261- delay (remainingTimeBudget);
283+ // Check if we should update weather information
284+ if (millis () - lastDownloadUpdate > 1000 * UPDATE_INTERVAL_SECS) {
285+ updateData ();
286+ lastDownloadUpdate = millis ();
262287 }
263- drawCurrentWeather ();
264- drawAstronomy ();
265- } else if (screen == 1 ) {
266- drawCurrentWeatherDetail ();
267- } else if (screen == 2 ) {
268- drawForecastTable (0 );
269- } else if (screen == 3 ) {
270- drawForecastTable (4 );
271- } else if (screen == 4 ) {
272- drawAbout ();
273- }
274- gfx.commit ();
288+ } // !asleep
289+ }
275290
276- // Check if we should update weather information
277- if (millis () - lastDownloadUpdate > 1000 * UPDATE_INTERVAL_SECS) {
278- updateData ();
279- lastDownloadUpdate = millis ();
280- }
291+ /*
292+
293+ Check and activate when it is time to go to sleep
294+
295+ parameters: (defined in settings)
296+ SLEEP_INTERVAL_SECS time between screen touches in seconds before activating sleep mode
297+ HARD_SLEEP true -> deep sleep requiring interrupt or reset to wake
298+ false -> soft sleep turning off backlight wake with screen press
281299
282- if (SLEEP_INTERVAL_SECS && millis () - timerPress >= SLEEP_INTERVAL_SECS * 1000 ) { // after 2 minutes go to sleep
283- drawProgress (25 , " Going to Sleep!" );
284- delay (1000 );
285- drawProgress (50 , " Going to Sleep!" );
286- delay (1000 );
287- drawProgress (75 , " Going to Sleep!" );
288- delay (1000 );
289- drawProgress (100 , " Going to Sleep!" );
290- // go to deepsleep for xx minutes or 0 = permanently
291- ESP.deepSleep (0 , WAKE_RF_DEFAULT); // 0 delay = permanently to sleep
300+ returns: true when sleep mode is active
301+ */
302+ bool sleep_mode () {
303+ static bool sleeping = false ; // no need to waste time painting going to sleep screens
304+ if (SLEEP_INTERVAL_SECS
305+ && millis () - timerPress >= SLEEP_INTERVAL_SECS * 1000 ) { // after 2 minutes go to sleep
306+ if (true == sleeping)
307+ return sleeping; // all-ready asleep
308+
309+ int s = 0 ;
310+ do {
311+ drawProgress (s, " Going to Sleep!" );
312+ delay (10 );
313+ yield ();
314+ } while (s++ < 100 && !touchController.isTouched (0 ));
315+ if (s < 100 ) { // early exit abort
316+ timerPress = millis (); // reset sleep timeout
317+ touchController.getPoint (); // throw away
318+ if (touchController.isTouched (0 )) // resets lastTouched
319+ touchController.getPoint (); // throw away
320+ } else {
321+ sleeping = true ;
322+ if (true == HARD_SLEEP) {
323+ // go to deepsleep for xx minutes or 0 = permanently
324+ ESP.deepSleep (0 , WAKE_RF_DEFAULT); // 0 delay = permanently to sleep
325+ } else {
326+ digitalWrite (TFT_LED, LOW); // Back light OFF
327+ }
328+ }
329+ } else { // Not time to sleep
330+ if (sleeping) { // Wake up
331+ digitalWrite (TFT_LED, HIGH); // Back light ON
332+ sleeping = false ;
333+ }
292334 }
293- }
335+ return sleeping; // used to prevent screen changes on wake-up screen press
336+ } // sleep_mode()
294337
295338// Update the internet based information and update screen
296339void updateData () {
@@ -441,7 +484,12 @@ void drawForecastDetail(uint16_t x, uint16_t y, uint8_t dayIndex) {
441484 gfx.setTextAlignment (TEXT_ALIGN_CENTER);
442485 time_t time = forecasts[dayIndex].observationTime ;
443486 struct tm * timeinfo = localtime (&time);
444- gfx.drawString (x + 25 , y - 15 , WDAY_NAMES[timeinfo->tm_wday ] + " " + String (timeinfo->tm_hour ) + " :00" );
487+ // Added 24hr / 12hr conversion //
488+ if (IS_STYLE_12HR){
489+ gfx.drawString (x + 25 , y - 15 , WDAY_NAMES[timeinfo->tm_wday ] + " " + String (make12_24 (timeinfo->tm_hour )));
490+ } else {
491+ gfx.drawString (x + 25 , y - 15 , WDAY_NAMES[timeinfo->tm_wday ] + " " + String (timeinfo->tm_hour ) + " :00" );
492+ }
445493
446494 gfx.setColor (MINI_WHITE);
447495 gfx.drawString (x + 25 , y, String (forecasts[dayIndex].temp , 1 ) + (IS_METRIC ? " °C" : " °F" ));
@@ -567,7 +615,12 @@ void drawForecastTable(uint8_t start) {
567615 gfx.setTextAlignment (TEXT_ALIGN_CENTER);
568616 time_t time = forecasts[i].observationTime ;
569617 struct tm * timeinfo = localtime (&time);
570- gfx.drawString (120 , y - 15 , WDAY_NAMES[timeinfo->tm_wday ] + " " + String (timeinfo->tm_hour ) + " :00" );
618+ // Added 24hr / 12hr conversion //
619+ if (IS_STYLE_12HR){
620+ gfx.drawString (120 , y - 15 , WDAY_NAMES[timeinfo->tm_wday ] + " " + String (make12_24 (timeinfo->tm_hour )));
621+ } else {
622+ gfx.drawString (120 , y - 15 , WDAY_NAMES[timeinfo->tm_wday ] + " " + String (timeinfo->tm_hour ) + " :00" );
623+ }
571624
572625
573626 gfx.drawPalettedBitmapFromPgm (0 , 5 + y, getMiniMeteoconIconFromProgmem (forecasts[i].icon ));
@@ -648,14 +701,45 @@ void calibrationCallback(int16_t x, int16_t y) {
648701 gfx.fillCircle (x, y, 10 );
649702}
650703
704+ // Added 24hr / 12hr conversion //
651705String getTime (time_t *timestamp) {
652706 struct tm *timeInfo = localtime (timestamp);
653707
654- char buf[6 ];
655- sprintf (buf, " %02d:%02d" , timeInfo->tm_hour , timeInfo->tm_min );
708+ // char buf[6];
709+ char buf[9 ]; // "12:34 pm\0"
710+ char ampm[3 ]; ampm[0 ]=' \0 ' ; // Ready for 24hr clock
711+ uint8_t hour = timeInfo->tm_hour ;
712+
713+ if (IS_STYLE_12HR){
714+ if (hour > 12 ){
715+ hour = hour - 12 ;
716+ sprintf (ampm," pm" );
717+ } else {
718+ sprintf (ampm," am" );
719+ }
720+ sprintf (buf, " %2d:%02d %s" , hour, timeInfo->tm_min , ampm);
721+ } else {
722+ sprintf (buf, " %02d:%02d %s" , hour, timeInfo->tm_min , ampm);
723+ }
656724 return String (buf);
657725}
658726
727+ /*
728+ * Convert hour from 24 hr time to 12 hr time
729+ * @return cString with 2 digit hour + am or pm
730+ *
731+ */
732+ char * make12_24 (int hour){
733+ static char hr[6 ];
734+ if (hour > 12 ){
735+ sprintf (hr, " %2d pm" , (hour -12 ) );
736+ // sprintf(buf, "%02d:%02d %s", hour, timeInfo->tm_min, ampm);
737+ } else {
738+ sprintf (hr, " %2d am" , hour);
739+ }
740+ return hr;
741+ }
742+
659743void loadPropertiesFromSpiffs () {
660744 if (SPIFFS.begin ()) {
661745 const char *msg = " Using '%s' from SPIFFS\n " ;
0 commit comments