Line |
Branch |
Decision |
Exec |
Source |
1 |
|
|
|
/** |
2 |
|
|
|
* @file rtc_helper.cpp |
3 |
|
|
|
* @brief Real Time Clock helper |
4 |
|
|
|
* |
5 |
|
|
|
* @date Feb 5, 2014 |
6 |
|
|
|
* @author Andrey Belomutskiy, (c) 2012-2020 |
7 |
|
|
|
*/ |
8 |
|
|
|
|
9 |
|
|
|
#include "pch.h" |
10 |
|
|
|
|
11 |
|
|
|
#include <string.h> |
12 |
|
|
|
|
13 |
|
|
|
#include "rtc_helper.h" |
14 |
|
|
|
|
15 |
|
|
|
#if EFI_RTC |
16 |
|
|
|
#include "rusefi_types.h" |
17 |
|
|
|
#endif // EFI_RTC |
18 |
|
|
|
|
19 |
|
|
|
#if EFI_PROD_CODE |
20 |
|
|
|
#include <sys/time.h> |
21 |
|
|
|
|
22 |
|
|
|
// Lua needs this function, but we don't necessarily have to implement it |
23 |
|
|
|
extern "C" int _gettimeofday(timeval* tv, void* tzvp) { |
24 |
|
|
|
(void)tv; (void)tzvp; |
25 |
|
|
|
return 0; |
26 |
|
|
|
} |
27 |
|
|
|
#endif // EFI_PROD_CODE |
28 |
|
|
|
|
29 |
|
|
|
#if EFI_RTC |
30 |
|
|
|
|
31 |
|
|
|
void PUBLIC_API_WEAK hal_lld_rtc_fixup(void) { |
32 |
|
|
|
/* nop */ |
33 |
|
|
|
} |
34 |
|
|
|
|
35 |
|
|
|
void initRtc() { |
36 |
|
|
|
efiPrintf("initRtc()"); |
37 |
|
|
|
hal_lld_rtc_fixup(); |
38 |
|
|
|
printDateTime(); // this would test RTC, see #311 |
39 |
|
|
|
} |
40 |
|
|
|
|
41 |
|
|
|
static const char * const monthAbbrs[] = { |
42 |
|
|
|
"Jan", "Feb", "Mar", |
43 |
|
|
|
"Apr", "May", "Jun", |
44 |
|
|
|
"Jul", "Aug", "Sep", |
45 |
|
|
|
"Oct", "Nov", "Dec" |
46 |
|
|
|
}; |
47 |
|
|
|
|
48 |
|
|
|
void printRtcDateTime() { |
49 |
|
|
|
efidatetime_t dateTime = getRtcDateTime(); |
50 |
|
|
|
// prints the date like: 19 sep 2022 21:19:55 |
51 |
|
|
|
efiPrintf("Current RTC time: %02u %s %04lu %02u:%02u:%02u", |
52 |
|
|
|
dateTime.day, monthAbbrs[dateTime.month - 1], dateTime.year, |
53 |
|
|
|
dateTime.hour, dateTime.minute, dateTime.second); |
54 |
|
|
|
} |
55 |
|
|
|
|
56 |
|
|
|
void setRtcDateTime(efidatetime_t const * const dateTime) { |
57 |
|
|
|
RTCDateTime timespec = convertRtcDateTimeFromEfi(dateTime); |
58 |
|
|
|
rtcSetTime(&RTCD1, ×pec); |
59 |
|
|
|
} |
60 |
|
|
|
|
61 |
|
|
|
static time_t rtc_encode(const RTCDateTime *timespec) { |
62 |
|
|
|
struct tm tim; |
63 |
|
|
|
|
64 |
|
|
|
// todo: looks like this pulls a lot of library code? 4K+? |
65 |
|
|
|
// todo: reimplement lighter? https://github.com/rusefi/rusefi/issues/6876 |
66 |
|
|
|
rtcConvertDateTimeToStructTm(timespec, &tim, NULL); |
67 |
|
|
|
return mktime(&tim); |
68 |
|
|
|
} |
69 |
|
|
|
|
70 |
|
|
|
uint32_t getEpochTime() { |
71 |
|
|
|
RTCDateTime timespec; |
72 |
|
|
|
rtcGetTime(&RTCD1, ×pec); |
73 |
|
|
|
return rtc_encode(×pec); |
74 |
|
|
|
} |
75 |
|
|
|
|
76 |
|
|
|
efidatetime_t getRtcDateTime() { |
77 |
|
|
|
RTCDateTime timespec; |
78 |
|
|
|
rtcGetTime(&RTCD1, ×pec); |
79 |
|
|
|
return convertRtcDateTimeToEfi(×pec); |
80 |
|
|
|
} |
81 |
|
|
|
|
82 |
|
|
|
efidatetime_t convertRtcDateTimeToEfi(RTCDateTime const * const timespec) { |
83 |
|
|
|
uint32_t second = timespec->millisecond / 1000; |
84 |
|
|
|
uint16_t minute = second / 60; |
85 |
|
|
|
second -= minute * 60; |
86 |
|
|
|
uint8_t hour = minute / 60; |
87 |
|
|
|
minute -= hour * 60; |
88 |
|
|
|
|
89 |
|
|
|
efidatetime_t const dateTime = { |
90 |
|
|
|
.year = timespec->year + RTC_BASE_YEAR, |
91 |
|
|
|
.month = (uint8_t)timespec->month, |
92 |
|
|
|
.day = (uint8_t)timespec->day, |
93 |
|
|
|
.hour = hour, |
94 |
|
|
|
.minute = (uint8_t)minute, |
95 |
|
|
|
.second = (uint8_t)second, |
96 |
|
|
|
}; |
97 |
|
|
|
return dateTime; |
98 |
|
|
|
} |
99 |
|
|
|
|
100 |
|
|
|
RTCDateTime convertRtcDateTimeFromEfi(efidatetime_t const * const dateTime) { |
101 |
|
|
|
RTCDateTime timespec; |
102 |
|
|
|
timespec.year = dateTime->year - RTC_BASE_YEAR; // ChibiOS year origin is e.g. 1980 |
103 |
|
|
|
timespec.month = dateTime->month; // [1..12] |
104 |
|
|
|
timespec.day = dateTime->day; // [1..31] |
105 |
|
|
|
timespec.millisecond = (((dateTime->hour * 60) + dateTime->minute) * 60 + dateTime->second) * 1000; // ms since midnight |
106 |
|
|
|
timespec.dayofweek = RTC_DAY_CATURDAY; // CATURDAY: 0 ... ? |
107 |
|
|
|
timespec.dstflag = 0; // 0 ... ? |
108 |
|
|
|
return timespec; |
109 |
|
|
|
} |
110 |
|
|
|
|
111 |
|
|
|
// TODO(nms): move to e.g. efitime ? |
112 |
|
|
|
|
113 |
|
|
|
static void putTwoSymbolDecimal(int offset, char *destination, int value) { |
114 |
|
|
|
static char buff[_MAX_FILLER]; |
115 |
|
|
|
efiAssertVoid(ObdCode::CUSTOM_ERR_6666, value >=0 && value <100, "value"); |
116 |
|
|
|
itoa10(buff, value); |
117 |
|
|
|
if (value < 10) { |
118 |
|
|
|
destination[offset] = '0'; |
119 |
|
|
|
destination[offset + 1] = buff[0]; |
120 |
|
|
|
} else { |
121 |
|
|
|
destination[offset] = buff[0]; |
122 |
|
|
|
destination[offset + 1] = buff[1]; |
123 |
|
|
|
} |
124 |
|
|
|
} |
125 |
|
|
|
#endif // EFI_RTC |
126 |
|
|
|
|
127 |
|
|
|
|
128 |
|
|
|
/** |
129 |
|
|
|
* @return true if we seem to know current date, false if no valid RTC state |
130 |
|
|
|
*/ |
131 |
|
|
✗ |
bool dateToStringShort(char *destination) { |
132 |
|
|
|
#if EFI_RTC |
133 |
|
|
|
strcpy(destination, "000000_000000\0"); |
134 |
|
|
|
efidatetime_t dateTime = getRtcDateTime(); |
135 |
|
|
|
if (dateTime.year < 2016 || dateTime.year > 2030) { |
136 |
|
|
|
// 2016 to 2030 is the valid range |
137 |
|
|
|
destination[0] = 0; |
138 |
|
|
|
return false; |
139 |
|
|
|
} |
140 |
|
|
|
|
141 |
|
|
|
putTwoSymbolDecimal(0, destination, dateTime.year % 100); // year, format as just the last two digits |
142 |
|
|
|
putTwoSymbolDecimal(2, destination, dateTime.month); // month 1-12 |
143 |
|
|
|
putTwoSymbolDecimal(4, destination, dateTime.day); // day of the month 1-31 |
144 |
|
|
|
|
145 |
|
|
|
putTwoSymbolDecimal(7, destination, dateTime.hour); // hours since midnight 0-23 |
146 |
|
|
|
putTwoSymbolDecimal(9, destination, dateTime.minute); // minutes |
147 |
|
|
|
putTwoSymbolDecimal(11, destination, dateTime.second); // seconds |
148 |
|
|
|
|
149 |
|
|
|
return true; |
150 |
|
|
|
#else // EFI_RTC |
151 |
|
|
✗ |
destination[0] = 0; |
152 |
|
|
✗ |
return false; |
153 |
|
|
|
#endif // EFI_RTC |
154 |
|
|
|
} |
155 |
|
|
|
|
156 |
|
|
|
/* |
157 |
|
|
|
void dateToString(char *destination) { |
158 |
|
|
|
#if EFI_RTC |
159 |
|
|
|
// todo: |
160 |
|
|
|
// re-implement this along the lines of chvprintf("%04u-%02u-%02u %02u:%02u:%02u\r\n", timp.tm_year + 1900, timp.tm_mon + 1, timp.tm_mday, timp.tm_hour, |
161 |
|
|
|
// timp.tm_min, timp.tm_sec); |
162 |
|
|
|
// this would require a temporary mem stream - see datalogging and other existing usages |
163 |
|
|
|
|
164 |
|
|
|
strcpy(destination, "00/00 00:00:00\0"); |
165 |
|
|
|
efidatetime_t dateTime = getRtcDateTime(); |
166 |
|
|
|
|
167 |
|
|
|
putTwoSymbolDecimal(0, destination, dateTime.month); |
168 |
|
|
|
putTwoSymbolDecimal(3, destination, dateTime.day); |
169 |
|
|
|
putTwoSymbolDecimal(6, destination, dateTime.hour); |
170 |
|
|
|
putTwoSymbolDecimal(9, destination, dateTime.minute); |
171 |
|
|
|
putTwoSymbolDecimal(12, destination, dateTime.second); |
172 |
|
|
|
#else // EFI_RTC |
173 |
|
|
|
destination[0] = 0; |
174 |
|
|
|
#endif // EFI_RTC |
175 |
|
|
|
} |
176 |
|
|
|
*/ |
177 |
|
|
|
|