1
1
#include " components/datetime/DateTimeController.h"
2
2
#include < libraries/log/nrf_log.h>
3
3
#include < systemtask/SystemTask.h>
4
+ #include < hal/nrf_rtc.h>
4
5
5
6
using namespace Pinetime ::Controllers;
6
7
@@ -12,11 +13,16 @@ namespace {
12
13
}
13
14
14
15
DateTime::DateTime (Controllers::Settings& settingsController) : settingsController {settingsController} {
16
+ mutex = xSemaphoreCreateMutex ();
17
+ ASSERT (mutex != nullptr );
18
+ xSemaphoreGive (mutex);
15
19
}
16
20
17
21
void DateTime::SetCurrentTime (std::chrono::time_point<std::chrono::system_clock, std::chrono::nanoseconds> t) {
22
+ xSemaphoreTake (mutex, portMAX_DELAY);
18
23
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);
20
26
}
21
27
22
28
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,
29
35
/* .tm_year = */ year - 1900 ,
30
36
};
31
37
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
-
35
38
NRF_LOG_INFO (" %d %d %d " , day, month, year);
36
39
NRF_LOG_INFO (" %d %d %d " , hour, minute, second);
37
40
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);
39
47
40
48
systemTask->PushMessage (System::Messages::OnNewTime);
41
49
}
@@ -45,25 +53,34 @@ void DateTime::SetTimeZone(int8_t timezone, int8_t dst) {
45
53
dstOffset = dst;
46
54
}
47
55
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) {
49
64
// Handle systick counter overflow
50
65
uint32_t systickDelta = 0 ;
51
66
if (systickCounter < previousSystickCounter) {
52
- systickDelta = 0xffffff - previousSystickCounter;
67
+ systickDelta = static_cast < uint32_t >(portNRF_RTC_MAXTICKS) - previousSystickCounter;
53
68
systickDelta += systickCounter + 1 ;
54
69
} else {
55
70
systickDelta = systickCounter - previousSystickCounter;
56
71
}
57
72
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;
63
80
if (systickCounter >= rest) {
64
81
previousSystickCounter = systickCounter - rest;
65
82
} else {
66
- previousSystickCounter = 0xffffff - (rest - systickCounter);
83
+ previousSystickCounter = static_cast < uint32_t >(portNRF_RTC_MAXTICKS) - (rest - systickCounter - 1 );
67
84
}
68
85
69
86
currentDateTime += std::chrono::seconds (correctedDelta);
0 commit comments