diff --git a/EleksTubeHAX_pio/src/Backlights.h b/EleksTubeHAX_pio/src/Backlights.h index df63dc1..84800f6 100644 --- a/EleksTubeHAX_pio/src/Backlights.h +++ b/EleksTubeHAX_pio/src/Backlights.h @@ -60,7 +60,7 @@ class Backlights: public Adafruit_NeoPixel { void adjustIntensity(int16_t adj); uint8_t getIntensity() { return config->intensity; } - bool dimming = false; + void setDimming(bool dim) { dimming = dim; pattern_needs_init = true; } // Helper methods uint32_t phaseToColor(uint16_t phase); @@ -72,6 +72,7 @@ class Backlights: public Adafruit_NeoPixel { const uint8_t max_intensity = 8; // 0 to 7 private: + bool dimming = false; bool pattern_needs_init; bool off; diff --git a/EleksTubeHAX_pio/src/main.cpp b/EleksTubeHAX_pio/src/main.cpp index 8d1cad9..1b4fd7c 100644 --- a/EleksTubeHAX_pio/src/main.cpp +++ b/EleksTubeHAX_pio/src/main.cpp @@ -41,8 +41,10 @@ Clock uclock; Menu menu; StoredConfig stored_config; -bool FullHour = false; +#ifdef DIMMING +bool isDimmingNeeded = false; uint8_t hour_old = 255; +#endif bool DstNeedsUpdate = false; uint8_t yesterday = 0; @@ -51,7 +53,10 @@ uint32_t lastMqttCommandExecuted = (uint32_t) -1; // Helper function, defined below. void updateClockDisplay(TFTs::show_t show=TFTs::yes); void setupMenu(void); -void EveryFullHour(bool loopUpdate=false); +#ifdef DIMMING +bool isNightTime(uint8_t current_hour); +void checkDimmingNeeded(void); +#endif void UpdateDstEveryNight(void); #ifdef HARDWARE_NovelLife_SE_CLOCK // NovelLife_SE Clone XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX void GestureStart(); @@ -409,7 +414,9 @@ void loop() { backlights.loop(); uclock.loop(); - EveryFullHour(true); // night or daytime +#ifdef DIMMING + checkDimmingNeeded(); // night or day time brightness change +#endif updateClockDisplay(); // Draw only the changed clock digits! @@ -421,9 +428,9 @@ void loop() { int8_t menu_change = menu.getChange(); if (menu_state == Menu::idle) { - // We just changed into idle, so force redraw everything, and save the config. - updateClockDisplay(TFTs::force); - Serial.print("Saving config..."); + // We just changed into idle, so force a redraw of all clock digits and save the config. + updateClockDisplay(TFTs::force); // redraw all the clock digits + Serial.println(); Serial.print("Saving config! Triggered from leaving menu..."); stored_config.save(); Serial.println(" Done."); } @@ -433,7 +440,6 @@ void loop() { if (menu_change != 0) { backlights.setNextPattern(menu_change); } - setupMenu(); tfts.println("Pattern:"); tfts.println(backlights.getPatternStr()); @@ -462,8 +468,7 @@ void loop() { uclock.toggleTwelveHour(); tfts.setDigit(HOURS_TENS, uclock.getHoursTens(), TFTs::force); tfts.setDigit(HOURS_ONES, uclock.getHoursOnes(), TFTs::force); - } - + } setupMenu(); tfts.println("Hour format"); tfts.println(uclock.getTwelveHour() ? "12 hour" : "24 hour"); @@ -473,77 +478,122 @@ void loop() { if (menu_change != 0) { uclock.toggleBlankHoursZero(); tfts.setDigit(HOURS_TENS, uclock.getHoursTens(), TFTs::force); - } - + } setupMenu(); tfts.println("Blank zero?"); tfts.println(uclock.getBlankHoursZero() ? "yes" : "no"); } // UTC Offset, hours else if (menu_state == Menu::utc_offset_hour) { + time_t currOffset = uclock.getTimeZoneOffset(); + if (menu_change != 0) { - uclock.adjustTimeZoneOffset(menu_change * 3600); - - EveryFullHour(); - - tfts.setDigit(HOURS_TENS, uclock.getHoursTens(), TFTs::yes); - tfts.setDigit(HOURS_ONES, uclock.getHoursOnes(), TFTs::yes); + // calculate the new offset + time_t newOffsetAdjustmentValue = menu_change * 3600; + time_t newOffset = currOffset + newOffsetAdjustmentValue; + double newOffsetInHours = static_cast(newOffset) / 3600; + + // check if the new offset is within the allowed range of -12 to +12 hours + // If the minutes part of the offset is 0, we want to change from +12 to -12 or vice versa (without changing the shown time on the displays) + // If the minutes part is not 0: We want to wrap around to the other side and change the minutes part (i.e. from 11:45 directly to -11:15) + bool offsetWrapAround = false; + if (newOffset > 43200) { // we just "passed" +12 hours -> set to -12 hours + newOffset = -43200; + offsetWrapAround = true; + } + if (newOffset < -43200 && !offsetWrapAround) { // we just passed -12 hours -> set to +12 hours + newOffset = 43200; + } + + uclock.setTimeZoneOffset(newOffset); // set the new offset + uclock.loop(); // update the clock time and redraw the changed digits -> will "flicker" the menu for a short time, but without, menu is not redrawn correctly +#ifdef DIMMING + checkDimmingNeeded(); // check if we need dimming for the night, because timezone was changed +#endif + currOffset = uclock.getTimeZoneOffset(); // get the new offset as current offset for the menu } - setupMenu(); tfts.println("UTC Offset"); tfts.println(" +/- Hour"); - time_t offset = uclock.getTimeZoneOffset(); - int8_t offset_hour = offset/3600; - int8_t offset_min = (offset%3600)/60; - if(offset_min < 0) { + char offsetStr[11]; + int8_t offset_hour = currOffset/3600; + int8_t offset_min = (currOffset%3600)/60; + if(offset_min <= 0 && offset_hour <= 0) { // negative timezone value -> Make them positive and print a minus in front offset_min = -offset_min; + offset_hour = -offset_hour; + snprintf(offsetStr, sizeof(offsetStr), "-%d:%02d", offset_hour, offset_min); + } else { + if(offset_min >= 0 && offset_hour >= 0) {// postive timezone value for hours and minutes -> show a plus in front + snprintf(offsetStr, sizeof(offsetStr), "+%d:%02d", offset_hour, offset_min); + } } - tfts.printf("%d:%02d\n", offset_hour, offset_min); - } - // UTC Offset, 15 minutes + if(offset_min == 0 && offset_hour == 0) { // we don't want a sign in front of the 0:00 case + snprintf(offsetStr, sizeof(offsetStr), "%d:%02d", offset_hour, offset_min); + } + tfts.println(offsetStr); + } // END UTC Offset, hours + // BEGIN UTC Offset, 15 minutes else if (menu_state == Menu::utc_offset_15m) { + time_t currOffset = uclock.getTimeZoneOffset(); + if (menu_change != 0) { - uclock.adjustTimeZoneOffset(menu_change * 900); - - EveryFullHour(); - - tfts.setDigit(HOURS_TENS, uclock.getHoursTens(), TFTs::yes); - tfts.setDigit(HOURS_ONES, uclock.getHoursOnes(), TFTs::yes); - tfts.setDigit(MINUTES_TENS, uclock.getMinutesTens(), TFTs::yes); - tfts.setDigit(MINUTES_ONES, uclock.getMinutesOnes(), TFTs::yes); + time_t newOffsetAdjustmentValue = menu_change * 900; // calculate the new offset + time_t newOffset = currOffset + newOffsetAdjustmentValue; + + // check if the new offset is within the allowed range of -12 to +12 hours + // same behaviour as for the +/-1 hour offset, but with 15 minutes steps + bool offsetWrapAround = false; + if (newOffset > 43200) { // we just "passed" +12 hours -> set to -12 hours + newOffset = -43200; + offsetWrapAround = true; + } + if (newOffset < -43200 && !offsetWrapAround) { // we just passed -12 hours -> set to +12 hours + newOffset = 43200; + } + + uclock.setTimeZoneOffset(newOffset); // set the new offset + uclock.loop(); // update the clock time and redraw the changed digits -> will "flicker" the menu for a short time, but without, menu is not redrawn correctly +#ifdef DIMMING + checkDimmingNeeded(); // check if we need dimming for the night, because timezone was changed +#endif + currOffset = uclock.getTimeZoneOffset(); // get the new offset as current offset for the menu } - setupMenu(); tfts.println("UTC Offset"); tfts.println(" +/- 15m"); - time_t offset = uclock.getTimeZoneOffset(); - int8_t offset_hour = offset/3600; - int8_t offset_min = (offset%3600)/60; - if(offset_min < 0) { + char offsetStr[11]; + int8_t offset_hour = currOffset/3600; + int8_t offset_min = (currOffset%3600)/60; + if(offset_min <= 0 && offset_hour <= 0) { // negative timezone value -> Make them positive and print a minus in front offset_min = -offset_min; + offset_hour = -offset_hour; + snprintf(offsetStr, sizeof(offsetStr), "-%d:%02d", offset_hour, offset_min); + } else { + if(offset_min >= 0 && offset_hour >= 0) {// postive timezone value for hours and minutes -> show a plus in front + snprintf(offsetStr, sizeof(offsetStr), "+%d:%02d", offset_hour, offset_min); + } } - tfts.printf("%d:%02d\n", offset_hour, offset_min); - } - // select clock "font" + if(offset_min == 0 && offset_hour == 0) { // we don't want a sign in front of the 0:00 case so overwrite the string + snprintf(offsetStr, sizeof(offsetStr), "%d:%02d", offset_hour, offset_min); + } + tfts.println(offsetStr); + } // END UTC Offset, 15 minutes + // select clock face else if (menu_state == Menu::selected_graphic) { if (menu_change != 0) { uclock.adjustClockGraphicsIdx(menu_change); - + if(tfts.current_graphic != uclock.getActiveGraphicIdx()) { tfts.current_graphic = uclock.getActiveGraphicIdx(); - updateClockDisplay(TFTs::force); // redraw everything + updateClockDisplay(TFTs::force); // redraw all the clock digits } } - setupMenu(); tfts.println("Selected"); - tfts.println(" graphic:"); + tfts.println("graphic:"); tfts.printf(" %d\n", uclock.getActiveGraphicIdx()); } - - -#ifdef WIFI_USE_WPS //// WPS code +#ifdef WIFI_USE_WPS // WPS code // connect to WiFi using wps pushbutton mode else if (menu_state == Menu::start_wps) { if (menu_change != 0) { // button was pressed @@ -555,15 +605,14 @@ void loop() { tfts.setCursor(0, 0, 4); // Font 4. 26 pixel high WiFiStartWps(); } - } - + } setupMenu(); tfts.println("Connect to WiFi?"); tfts.println("Left=WPS"); } -#endif +#endif } - } + } // if (menu.stateChanged()) uint32_t time_in_loop = millis() - millis_at_top; if (time_in_loop < 20) { @@ -602,6 +651,7 @@ void loop() { } #endif } + #ifdef HARDWARE_NovelLife_SE_CLOCK // NovelLife_SE Clone XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX void GestureStart() { @@ -684,53 +734,42 @@ void HandleGesture() { } #endif // NovelLife_SE Clone XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX -void setupMenu() { - tfts.chip_select.setHoursTens(); - tfts.setTextColor(TFT_WHITE, TFT_BLACK); - tfts.fillRect(0, 120, 135, 120, TFT_BLACK); - tfts.setCursor(0, 124, 4); // Font 4. 26 pixel high +void setupMenu() { // Prepare drawing of the menu texts + tfts.chip_select.setHoursTens(); // use most left display + tfts.setTextColor(TFT_WHITE, TFT_BLACK); + tfts.fillRect(0, 120, 135, 120, TFT_BLACK); //use lower half of the display, fill with black + tfts.setCursor(0, 124, 4); // use font 4 - 26 pixel high - for the menu text } -bool isNightTime(uint8_t current_hour) { - if (DAY_TIME < NIGHT_TIME) { - // "Night" spans across midnight - return (current_hour < DAY_TIME) || (current_hour >= NIGHT_TIME); - } - else { - // "Night" starts after midnight, entirely contained within the day - return (current_hour >= NIGHT_TIME) && (current_hour < DAY_TIME); - } +#ifdef DIMMING +bool isNightTime(uint8_t current_hour) { // check the actual hour is in the defined "night time" + if (DAY_TIME < NIGHT_TIME) { // "Night" spans across midnight so it is split between two days + return (current_hour < DAY_TIME) || (current_hour >= NIGHT_TIME); + } + else { // "Night" starts after midnight, entirely contained within the current day + return (current_hour >= NIGHT_TIME) && (current_hour < DAY_TIME); + } } -void EveryFullHour(bool loopUpdate) { - // dim the clock at night - #ifdef DIMMING - uint8_t current_hour = uclock.getHour24(); - FullHour = current_hour != hour_old; - if (FullHour) { - Serial.print("current hour = "); - Serial.println(current_hour); - if (isNightTime(current_hour)) { - Serial.println("Setting night mode (dimmed)"); +void checkDimmingNeeded() { // dim the display in the defined night time + uint8_t current_hour = uclock.getHour24(); // for internal calcs we always use 24h format + isDimmingNeeded = current_hour != hour_old; //check, if the hour has changed since last loop (from time passing by or from timezone change) + if (isDimmingNeeded) { + Serial.print("Current hour = "); Serial.print(current_hour); Serial.print(", Night Time Start = "); Serial.print(NIGHT_TIME); Serial.print(", Day Time Start = "); Serial.println(DAY_TIME); + if (isNightTime(current_hour)) { //check if it is in the defined night time + Serial.println("Set to night time mode (dimmed)!"); tfts.dimming = TFT_DIMMED_INTENSITY; - tfts.InvalidateImageInBuffer(); // invalidate; reload images with new dimming value - backlights.dimming = true; - if (menu.getState() == Menu::idle || !loopUpdate) { // otherwise erases the menu - updateClockDisplay(TFTs::force); // update all - } + backlights.setDimming(true); } else { - Serial.println("Setting daytime mode (normal brightness)"); + Serial.println("Set to day time mode (normal brightness)!"); tfts.dimming = 255; // 0..255 - tfts.InvalidateImageInBuffer(); // invalidate; reload images with new dimming value - backlights.dimming = false; - if (menu.getState() == Menu::idle || !loopUpdate) { // otherwise erases the menu - updateClockDisplay(TFTs::force); // update all - } + backlights.setDimming(false); } + updateClockDisplay(TFTs::force); // redraw all the clock digits -> software dimming will be done here hour_old = current_hour; } - #endif } +#endif // DIMMING void UpdateDstEveryNight() { uint8_t currentDay = uclock.getDay();