diff options
| author | mark9064 <30447455+mark9064@users.noreply.github.com> | 2023-12-28 20:56:37 +0000 |
|---|---|---|
| committer | JF <JF002@users.noreply.github.com> | 2024-06-09 18:34:07 +0200 |
| commit | a449b272f77ea43733be4b3449f6ef57e6d09a02 (patch) | |
| tree | 1fadb72dbe5b37198c1fe617c8d283ae5ff46675 /src/components/datetime | |
| parent | 9e406c70f95c2db93bbf84965c210ee274da1dd2 (diff) | |
Continuous time updates
Diffstat (limited to 'src/components/datetime')
| -rw-r--r-- | src/components/datetime/DateTimeController.cpp | 43 | ||||
| -rw-r--r-- | src/components/datetime/DateTimeController.h | 16 |
2 files changed, 39 insertions, 20 deletions
diff --git a/src/components/datetime/DateTimeController.cpp b/src/components/datetime/DateTimeController.cpp index f0ccb5e5..39bba15f 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 @@ namespace { } 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) { @@ -29,13 +35,15 @@ void DateTime::SetTime(uint16_t year, uint8_t month, uint8_t day, uint8_t hour, /* .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 @@ void DateTime::SetTimeZone(int8_t timezone, int8_t dst) { 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 f719df7d..5a453f20 100644 --- a/src/components/datetime/DateTimeController.h +++ b/src/components/datetime/DateTimeController.h @@ -5,6 +5,8 @@ #include <ctime> #include <string> #include "components/settings/Settings.h" +#include <FreeRTOS.h> +#include <semphr.h> namespace Pinetime { namespace System { @@ -45,8 +47,6 @@ namespace Pinetime { */ 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 @@ namespace Pinetime { 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,10 +139,14 @@ namespace Pinetime { 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; std::chrono::seconds uptime {0}; |
