11#include " components/datetime/DateTimeController.h"
22#include < libraries/log/nrf_log.h>
33#include < systemtask/SystemTask.h>
4+ #include < hal/nrf_rtc.h>
45
56using namespace Pinetime ::Controllers;
67
@@ -12,11 +13,16 @@ namespace {
1213}
1314
1415DateTime::DateTime (Controllers::Settings& settingsController) : settingsController {settingsController} {
16+ mutex = xSemaphoreCreateMutex ();
17+ ASSERT (mutex != nullptr );
18+ xSemaphoreGive (mutex);
1519}
1620
1721void DateTime::SetCurrentTime (std::chrono::time_point<std::chrono::system_clock, std::chrono::nanoseconds> t) {
22+ xSemaphoreTake (mutex, portMAX_DELAY);
1823 this ->currentDateTime = t;
19- UpdateTime (previousSystickCounter); // Update internal state without updating the time
24+ UpdateTime (previousSystickCounter, true ); // Update internal state without updating the time
25+ xSemaphoreGive (mutex);
2026}
2127
2228void 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,
2935 /* .tm_year = */ year - 1900 ,
3036 };
3137
32- tm.tm_isdst = -1 ; // Use DST value from local time zone
33- currentDateTime = std::chrono::system_clock::from_time_t (std::mktime (&tm));
34-
3538 NRF_LOG_INFO (" %d %d %d " , day, month, year);
3639 NRF_LOG_INFO (" %d %d %d " , hour, minute, second);
3740
38- UpdateTime (previousSystickCounter);
41+ tm.tm_isdst = -1 ; // Use DST value from local time zone
42+
43+ xSemaphoreTake (mutex, portMAX_DELAY);
44+ currentDateTime = std::chrono::system_clock::from_time_t (std::mktime (&tm));
45+ UpdateTime (previousSystickCounter, true );
46+ xSemaphoreGive (mutex);
3947
4048 systemTask->PushMessage (System::Messages::OnNewTime);
4149}
@@ -45,25 +53,34 @@ void DateTime::SetTimeZone(int8_t timezone, int8_t dst) {
4553 dstOffset = dst;
4654}
4755
48- void DateTime::UpdateTime (uint32_t systickCounter) {
56+ std::chrono::time_point<std::chrono::system_clock, std::chrono::nanoseconds> DateTime::CurrentDateTime () {
57+ xSemaphoreTake (mutex, portMAX_DELAY);
58+ UpdateTime (nrf_rtc_counter_get (portNRF_RTC_REG), false );
59+ xSemaphoreGive (mutex);
60+ return currentDateTime;
61+ }
62+
63+ void DateTime::UpdateTime (uint32_t systickCounter, bool forceUpdate) {
4964 // Handle systick counter overflow
5065 uint32_t systickDelta = 0 ;
5166 if (systickCounter < previousSystickCounter) {
52- systickDelta = 0xffffff - previousSystickCounter;
67+ systickDelta = static_cast < uint32_t >(portNRF_RTC_MAXTICKS) - previousSystickCounter;
5368 systickDelta += systickCounter + 1 ;
5469 } else {
5570 systickDelta = systickCounter - previousSystickCounter;
5671 }
5772
58- /*
59- * 1000 ms = 1024 ticks
60- */
61- auto correctedDelta = systickDelta / 1024 ;
62- auto rest = systickDelta % 1024 ;
73+ auto correctedDelta = systickDelta / configTICK_RATE_HZ;
74+ // If a second hasn't passed, there is nothing to do
75+ // If the time has been changed, set forceUpdate to trigger internal state updates
76+ if (correctedDelta == 0 && !forceUpdate) {
77+ return ;
78+ }
79+ auto rest = systickDelta % configTICK_RATE_HZ;
6380 if (systickCounter >= rest) {
6481 previousSystickCounter = systickCounter - rest;
6582 } else {
66- previousSystickCounter = 0xffffff - (rest - systickCounter);
83+ previousSystickCounter = static_cast < uint32_t >(portNRF_RTC_MAXTICKS) - (rest - systickCounter - 1 );
6784 }
6885
6986 currentDateTime += std::chrono::seconds (correctedDelta);
0 commit comments