InfiniTime.git

commit a449b272f77ea43733be4b3449f6ef57e6d09a02

Author: mark9064 <30447455+mark9064@users.noreply.github.com>

Continuous time updates

 src/components/ble/SimpleWeatherService.cpp | 2 
 src/components/ble/SimpleWeatherService.h | 4 
 src/components/datetime/DateTimeController.cpp | 43 +++++++++++++------
 src/components/datetime/DateTimeController.h | 16 ++++---
 src/displayapp/screens/WatchFaceAnalog.h | 2 
 src/systemtask/SystemTask.cpp | 2 


diff --git a/src/components/ble/SimpleWeatherService.cpp b/src/components/ble/SimpleWeatherService.cpp
index 146152f8e419a32ca1af3d9ed49cafd662fbfd18..504cad14b5491259a82a541029ece3f16f035df5 100644
--- a/src/components/ble/SimpleWeatherService.cpp
+++ b/src/components/ble/SimpleWeatherService.cpp
@@ -80,7 +80,7 @@ int WeatherCallback(uint16_t /*connHandle*/, uint16_t /*attrHandle*/, struct ble_gatt_access_ctxt* ctxt, void* arg) {
   return static_cast<Pinetime::Controllers::SimpleWeatherService*>(arg)->OnCommand(ctxt);
 }
 
-SimpleWeatherService::SimpleWeatherService(const DateTime& dateTimeController) : dateTimeController(dateTimeController) {
+SimpleWeatherService::SimpleWeatherService(DateTime& dateTimeController) : dateTimeController(dateTimeController) {
 }
 
 void SimpleWeatherService::Init() {




diff --git a/src/components/ble/SimpleWeatherService.h b/src/components/ble/SimpleWeatherService.h
index 4bbefcfcfcbce13dfeec8c1fa75f9acbf7f68c0b..03d2f6ff038c5637145645f4aa3444e437d2639f 100644
--- a/src/components/ble/SimpleWeatherService.h
+++ b/src/components/ble/SimpleWeatherService.h
@@ -40,7 +40,7 @@   namespace Controllers {
 
     class SimpleWeatherService {
     public:
-      explicit SimpleWeatherService(const DateTime& dateTimeController);
+      explicit SimpleWeatherService(DateTime& dateTimeController);
 
       void Init();
 
@@ -140,7 +140,7 @@         {0}};
 
       uint16_t eventHandle {};
 
-      const Pinetime::Controllers::DateTime& dateTimeController;
+      Pinetime::Controllers::DateTime& dateTimeController;
 
       std::optional<CurrentWeather> currentWeather;
       std::optional<Forecast> forecast;




diff --git a/src/components/datetime/DateTimeController.cpp b/src/components/datetime/DateTimeController.cpp
index f0ccb5e579c37595adf758a7889a3c603ea5e1b6..39bba15f5ff17e3e21311f83218ccfd0b1846d31 100644
--- a/src/components/datetime/DateTimeController.cpp
+++ b/src/components/datetime/DateTimeController.cpp
@@ -1,6 +1,7 @@
 #include "components/datetime/DateTimeController.h"
 #include <libraries/log/nrf_log.h>
 #include <systemtask/SystemTask.h>
+#include <hal/nrf_rtc.h>
 
 using namespace Pinetime::Controllers;
 
@@ -12,11 +13,16 @@   char const* MonthsStringLow[] = {"--", "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"};
 }
 
 DateTime::DateTime(Controllers::Settings& settingsController) : settingsController {settingsController} {
+  mutex = xSemaphoreCreateMutex();
+  ASSERT(mutex != nullptr);
+  xSemaphoreGive(mutex);
 }
 
 void DateTime::SetCurrentTime(std::chrono::time_point<std::chrono::system_clock, std::chrono::nanoseconds> t) {
+  xSemaphoreTake(mutex, portMAX_DELAY);
   this->currentDateTime = t;
-  UpdateTime(previousSystickCounter); // Update internal state without updating the time
+  UpdateTime(previousSystickCounter, true); // Update internal state without updating the time
+  xSemaphoreGive(mutex);
 }
 
 void DateTime::SetTime(uint16_t year, uint8_t month, uint8_t day, uint8_t hour, uint8_t minute, uint8_t second) {
@@ -28,14 +34,16 @@     /* .tm_mday = */ day,
     /* .tm_mon  = */ month - 1,
     /* .tm_year = */ year - 1900,
   };
-
-  tm.tm_isdst = -1; // Use DST value from local time zone
-  currentDateTime = std::chrono::system_clock::from_time_t(std::mktime(&tm));
 
   NRF_LOG_INFO("%d %d %d ", day, month, year);
   NRF_LOG_INFO("%d %d %d ", hour, minute, second);
 
-  UpdateTime(previousSystickCounter);
+  tm.tm_isdst = -1; // Use DST value from local time zone
+
+  xSemaphoreTake(mutex, portMAX_DELAY);
+  currentDateTime = std::chrono::system_clock::from_time_t(std::mktime(&tm));
+  UpdateTime(previousSystickCounter, true);
+  xSemaphoreGive(mutex);
 
   systemTask->PushMessage(System::Messages::OnNewTime);
 }
@@ -45,25 +53,34 @@   tzOffset = timezone;
   dstOffset = dst;
 }
 
-void DateTime::UpdateTime(uint32_t systickCounter) {
+std::chrono::time_point<std::chrono::system_clock, std::chrono::nanoseconds> DateTime::CurrentDateTime() {
+  xSemaphoreTake(mutex, portMAX_DELAY);
+  UpdateTime(nrf_rtc_counter_get(portNRF_RTC_REG), false);
+  xSemaphoreGive(mutex);
+  return currentDateTime;
+}
+
+void DateTime::UpdateTime(uint32_t systickCounter, bool forceUpdate) {
   // Handle systick counter overflow
   uint32_t systickDelta = 0;
   if (systickCounter < previousSystickCounter) {
-    systickDelta = 0xffffff - previousSystickCounter;
+    systickDelta = static_cast<uint32_t>(portNRF_RTC_MAXTICKS) - previousSystickCounter;
     systickDelta += systickCounter + 1;
   } else {
     systickDelta = systickCounter - previousSystickCounter;
   }
 
-  /*
-   * 1000 ms = 1024 ticks
-   */
-  auto correctedDelta = systickDelta / 1024;
-  auto rest = systickDelta % 1024;
+  auto correctedDelta = systickDelta / configTICK_RATE_HZ;
+  // If a second hasn't passed, there is nothing to do
+  // If the time has been changed, set forceUpdate to trigger internal state updates
+  if (correctedDelta == 0 && !forceUpdate) {
+    return;
+  }
+  auto rest = systickDelta % configTICK_RATE_HZ;
   if (systickCounter >= rest) {
     previousSystickCounter = systickCounter - rest;
   } else {
-    previousSystickCounter = 0xffffff - (rest - systickCounter);
+    previousSystickCounter = static_cast<uint32_t>(portNRF_RTC_MAXTICKS) - (rest - systickCounter - 1);
   }
 
   currentDateTime += std::chrono::seconds(correctedDelta);




diff --git a/src/components/datetime/DateTimeController.h b/src/components/datetime/DateTimeController.h
index f719df7d52470afb0a773aa90196659c2fadfeab..5a453f20609a841158e587b3302061ce4106234e 100644
--- a/src/components/datetime/DateTimeController.h
+++ b/src/components/datetime/DateTimeController.h
@@ -5,6 +5,8 @@ #include 
 #include <ctime>
 #include <string>
 #include "components/settings/Settings.h"
+#include <FreeRTOS.h>
+#include <semphr.h>
 
 namespace Pinetime {
   namespace System {
@@ -44,8 +46,6 @@        * timezone is expected to be constant over DST which will be reported in
        * dst field.
        */
       void SetTimeZone(int8_t timezone, int8_t dst);
-
-      void UpdateTime(uint32_t systickCounter);
 
       uint16_t Year() const {
         return 1900 + localTime.tm_year;
@@ -124,12 +124,10 @@       const char* DayOfWeekShortToString() const;
       static const char* MonthShortToStringLow(Months month);
       static const char* DayOfWeekShortToStringLow(Days day);
 
-      std::chrono::time_point<std::chrono::system_clock, std::chrono::nanoseconds> CurrentDateTime() const {
-        return currentDateTime;
-      }
+      std::chrono::time_point<std::chrono::system_clock, std::chrono::nanoseconds> CurrentDateTime();
 
-      std::chrono::time_point<std::chrono::system_clock, std::chrono::nanoseconds> UTCDateTime() const {
-        return currentDateTime - std::chrono::seconds((tzOffset + dstOffset) * 15 * 60);
+      std::chrono::time_point<std::chrono::system_clock, std::chrono::nanoseconds> UTCDateTime() {
+        return CurrentDateTime() - std::chrono::seconds((tzOffset + dstOffset) * 15 * 60);
       }
 
       std::chrono::seconds Uptime() const {
@@ -141,9 +139,13 @@       void SetCurrentTime(std::chrono::time_point t);
       std::string FormattedTime();
 
     private:
+      void UpdateTime(uint32_t systickCounter, bool forceUpdate);
+
       std::tm localTime;
       int8_t tzOffset = 0;
       int8_t dstOffset = 0;
+
+      SemaphoreHandle_t mutex = nullptr;
 
       uint32_t previousSystickCounter = 0;
       std::chrono::time_point<std::chrono::system_clock, std::chrono::nanoseconds> currentDateTime;




diff --git a/src/displayapp/screens/WatchFaceAnalog.h b/src/displayapp/screens/WatchFaceAnalog.h
index 2eee657e9baf5234630df356d47290bcbe4a408b..958ff64dc4bce4f09b077572d76df6cf4d4aa0ca 100644
--- a/src/displayapp/screens/WatchFaceAnalog.h
+++ b/src/displayapp/screens/WatchFaceAnalog.h
@@ -75,7 +75,7 @@         lv_obj_t* bleIcon;
 
         BatteryIcon batteryIcon;
 
-        const Controllers::DateTime& dateTimeController;
+        Controllers::DateTime& dateTimeController;
         const Controllers::Battery& batteryController;
         const Controllers::Ble& bleController;
         Controllers::NotificationManager& notificationManager;




diff --git a/src/systemtask/SystemTask.cpp b/src/systemtask/SystemTask.cpp
index e3d40d35c655c044b31ff883ff9c0a2dcb2a7559..a56c259105145b4e5856e99d7e9f998efa418617 100644
--- a/src/systemtask/SystemTask.cpp
+++ b/src/systemtask/SystemTask.cpp
@@ -410,8 +410,6 @@       }
     }
 
     monitor.Process();
-    uint32_t systick_counter = nrf_rtc_counter_get(portNRF_RTC_REG);
-    dateTimeController.UpdateTime(systick_counter);
     NoInit_BackUpTime = dateTimeController.CurrentDateTime();
     if (nrf_gpio_pin_read(PinMap::Button) == 0) {
       watchdog.Reload();