Merge pull request #16847 from LeonPoon/development

Support nanos in rtc for sync from ntp
This commit is contained in:
Theo Arends 2022-10-17 16:48:05 +02:00 committed by GitHub
commit 0be740850a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 42 additions and 12 deletions

View File

@ -158,6 +158,7 @@ RTC_NOINIT_ATTR TRtcSettings RtcDataSettings;
#endif // ESP32
struct TIME_T {
uint32_t nanos;
uint8_t second;
uint8_t minute;
uint8_t hour;

View File

@ -43,10 +43,12 @@ struct RTC {
uint32_t standard_time = 0;
uint32_t midnight = 0;
uint32_t restart_time = 0;
uint32_t nanos = 0;
uint32_t millis = 0;
// uint32_t last_sync = 0;
int32_t time_timezone = 0;
bool time_synced = false;
bool last_synced = false;
bool midnight_now = false;
bool user_time_entry = false; // Override NTP by user setting
} Rtc;
@ -235,11 +237,14 @@ uint32_t RtcMillis(void) {
return (millis() - Rtc.millis) % 1000;
}
void BreakTime(uint32_t time_input, TIME_T &tm) {
void BreakNanoTime(uint32_t time_input, uint32_t time_nanos, TIME_T &tm) {
// break the given time_input into time components
// this is a more compact version of the C library localtime function
// note that year is offset from 1970 !!!
time_input += time_nanos / 1000000000U;
tm.nanos = time_nanos % 1000000000U;
uint8_t year;
uint8_t month;
uint8_t month_length;
@ -290,6 +295,10 @@ void BreakTime(uint32_t time_input, TIME_T &tm) {
tm.valid = (time_input > START_VALID_TIME); // 2016-01-01
}
void BreakTime(uint32_t time_input, TIME_T &tm) {
BreakNanoTime(time_input, 0, tm);
}
uint32_t MakeTime(TIME_T &tm) {
// assemble time elements into time_t
// note year argument is offset from 1970
@ -403,6 +412,7 @@ void RtcSecond(void) {
mutex = true;
Rtc.time_synced = false;
Rtc.last_synced = true;
last_sync = Rtc.utc_time;
if (Rtc.restart_time == 0) {
@ -420,6 +430,12 @@ void RtcSecond(void) {
TasmotaGlobal.rules_flag.time_set = 1;
}
} else {
if (Rtc.last_synced) {
Rtc.last_synced = false;
uint32_t nanos = Rtc.nanos + (millis() - Rtc.millis) * 1000000U;
Rtc.utc_time += nanos / 1000000000U;
Rtc.nanos = nanos % 1000000000U;
} else
Rtc.utc_time++; // Increment every second
}
Rtc.millis = millis();
@ -442,7 +458,7 @@ void RtcSecond(void) {
}
}
BreakTime(Rtc.local_time, RtcTime);
BreakNanoTime(Rtc.local_time, Rtc.nanos, RtcTime);
if (RtcTime.valid) {
if (!Rtc.midnight) {
Rtc.midnight = Rtc.local_time - (RtcTime.hour * 3600) - (RtcTime.minute * 60) - RtcTime.second;

View File

@ -878,13 +878,15 @@ void WifiPollNtp() {
AddLog(LOG_LEVEL_DEBUG_MORE, PSTR("NTP: Sync time..."));
ntp_run_time = millis();
uint32_t ntp_time = WifiGetNtp();
uint64_t ntp_nanos = WifiGetNtp();
uint32_t ntp_time = ntp_nanos / 1000000000;
ntp_run_time = (millis() - ntp_run_time) / 1000;
// AddLog(LOG_LEVEL_DEBUG, PSTR("NTP: Runtime %d"), ntp_run_time);
if (ntp_run_time < 5) { ntp_run_time = 0; } // DNS timeout is around 10s
if (ntp_time > START_VALID_TIME) {
Rtc.utc_time = ntp_time;
Rtc.nanos = ntp_nanos % 1000000000;
ntp_sync_minute = 60; // Sync so block further requests
RtcSync("NTP");
} else {
@ -893,7 +895,7 @@ void WifiPollNtp() {
}
}
uint32_t WifiGetNtp(void) {
uint64_t WifiGetNtp(void) {
static uint8_t ntp_server_id = 0;
// AddLog(LOG_LEVEL_DEBUG, PSTR("NTP: Start NTP Sync %d ..."), ntp_server_id);
@ -983,7 +985,13 @@ uint32_t WifiGetNtp(void) {
ntp_server_id++; // Next server next time
return 0;
}
return secs_since_1900 - 2208988800UL;
uint32_t highWord = word(packet_buffer[44], packet_buffer[45]);
uint32_t lowWord = word(packet_buffer[46], packet_buffer[47]);
uint32_t currentNano = (((uint64_t)(highWord << 16 | lowWord)) * 1000000000) >> 32;
return (((uint64_t) secs_since_1900) - 2208988800UL) * 1000000000 + currentNano;
}
delay(10);
}

View File

@ -987,9 +987,12 @@ bool CmndTM1637Clock(void)
\*********************************************************************************************/
void TM1637ShowTime()
{
uint8_t hr = RtcTime.hour;
uint8_t mn = RtcTime.minute;
uint8_t sc = RtcTime.second;
struct TIME_T t = RtcTime;
BreakNanoTime(Rtc.local_time, Rtc.nanos + (millis() - Rtc.millis) * 1000000, t);
uint8_t hr = t.hour;
uint8_t mn = t.minute;
uint8_t sc = t.second;
uint16_t ms = t.nanos / 1000000;
if (!TM1637Data.clock_24)
{
@ -1009,12 +1012,14 @@ void TM1637ShowTime()
if (TM1637 == TM1637Data.display_type)
{
uint8_t colon = ms > 500? 0: 128;
uint8_t rawBytes[1];
for (uint32_t i = 0; i < 4; i++)
uint8_t width = Settings->display_width >= 6? 6: 4;
for (uint32_t i = 0; i < width; i++)
{
rawBytes[0] = tm1637display->encode(tm[i]);
if ((millis() % 1000) > 500 && (i == 1))
rawBytes[0] = rawBytes[0] | 128;
if (i == 1 || (i == 3 && width > 4))
rawBytes[0] = rawBytes[0] | colon;
tm1637display->printRaw(rawBytes, 1, TM1637Data.digit_order[i]);
}
}