From 3376a7f57ec2546966e2965e831cc9517c9aff80 Mon Sep 17 00:00:00 2001 From: Verkehrsrot Date: Sun, 31 Mar 2019 19:13:06 +0200 Subject: [PATCH] time sync accuracy fixes --- README.md | 4 +++- include/if482.h | 2 +- include/irqhandler.h | 2 ++ include/timesync.h | 6 +++--- src/irqhandler.cpp | 28 ++++++++++++++++++++-------- src/lorawan.cpp | 5 ++--- src/main.cpp | 1 - src/rcommand.cpp | 1 + src/timekeeper.cpp | 4 ++-- src/timesync.cpp | 18 +++++++++--------- 10 files changed, 43 insertions(+), 28 deletions(-) diff --git a/README.md b/README.md index 217dcfc5..0879017d 100644 --- a/README.md +++ b/README.md @@ -389,7 +389,9 @@ Note: all settings are stored in NVRAM and will be reloaded when device starts. 0x86 get time/date - Device answers with it's local time/date (UTC Unix epoch) on Port 2. + Device answers with it's local time/date (UTC Unix epoch) on Port 2: + bytes 1..4 = local time/date in UTC epoch seconds + byte 5 = bits 0..3 timeSource, bits 4..7 timeStatus 0x87 set time/date diff --git a/include/if482.h b/include/if482.h index ce5a3f2b..05e4af01 100644 --- a/include/if482.h +++ b/include/if482.h @@ -4,7 +4,7 @@ #include "globals.h" #define IF482_FRAME_SIZE (17) -#define IF482_SYNC_FIXUP (3) // calibration to fixup processing time [milliseconds] +#define IF482_SYNC_FIXUP (2) // calibration to fixup processing time [milliseconds] String IRAM_ATTR IF482_Frame(time_t tt); diff --git a/include/irqhandler.h b/include/irqhandler.h index 61d1f347..3b0921c1 100644 --- a/include/irqhandler.h +++ b/include/irqhandler.h @@ -16,6 +16,8 @@ #include "timekeeper.h" void irqHandler(void *pvParameters); +int mask_user_IRQ(); +int unmask_user_IRQ(); #ifdef HAS_DISPLAY #include "display.h" diff --git a/include/timesync.h b/include/timesync.h index 80b7b1b1..0e96f084 100644 --- a/include/timesync.h +++ b/include/timesync.h @@ -1,9 +1,9 @@ -#ifndef _TIME_SYNC_LORASERVER_H -#define _TIME_SYNC_LORASERVER_H +#ifndef _TIMESYNC_H +#define _TIMESYNC_H #include #include "globals.h" -#include "timesync.h" +#include "irqhandler.h" #include "timekeeper.h" //#define TIME_SYNC_TRIGGER 100 // threshold for time sync [milliseconds] diff --git a/src/irqhandler.cpp b/src/irqhandler.cpp index 938dba96..8bd3313d 100644 --- a/src/irqhandler.cpp +++ b/src/irqhandler.cpp @@ -18,15 +18,14 @@ void irqHandler(void *pvParameters) { &InterruptStatus, // Receives the notification value portMAX_DELAY); // wait forever - // interrupt handler to be enabled? - if (InterruptStatus & UNMASK_IRQ) + if (InterruptStatus & UNMASK_IRQ) // interrupt handler to be enabled? mask_irq = false; - else if (mask_irq) - continue; // suppress processing if interrupt handler is disabled - - // interrupt handler to be disabled? - if (InterruptStatus & MASK_IRQ) + else if (mask_irq) // suppress processing if interrupt handler is disabled + continue; + else if (InterruptStatus & MASK_IRQ) { // interrupt handler to be disabled? mask_irq = true; + continue; + } // button pressed? #ifdef HAS_BUTTON @@ -36,7 +35,7 @@ void irqHandler(void *pvParameters) { // display needs refresh? #ifdef HAS_DISPLAY - if (InterruptStatus & DISPLAY_IRQ) + if (InterruptStatus & DISPLAY_IRQ) refreshtheDisplay(); #endif @@ -85,3 +84,16 @@ void IRAM_ATTR ButtonIRQ() { portYIELD_FROM_ISR(); } #endif + +int mask_user_IRQ() { + // begin of time critical section: lock I2C bus to ensure accurate timing + if (!I2C_MUTEX_LOCK()) + return 1; // failure + xTaskNotify(irqHandlerTask, MASK_IRQ, eSetBits); +} + +int unmask_user_IRQ() { + // end of time critical section: release I2C bus + I2C_MUTEX_UNLOCK(); + xTaskNotify(irqHandlerTask, UNMASK_IRQ, eSetBits); +} diff --git a/src/lorawan.cpp b/src/lorawan.cpp index 264a3620..a9302432 100644 --- a/src/lorawan.cpp +++ b/src/lorawan.cpp @@ -495,8 +495,7 @@ void IRAM_ATTR user_request_network_time_callback(void *pVoidUserUTCTime, } // begin of time critical section: lock I2C bus to ensure accurate timing - // don't move the mutex, will impact accuracy of time up to 1 sec! - if (!I2C_MUTEX_LOCK()) + if (!mask_user_IRQ()) return; // failure // Update userUTCTime, considering the difference between the GPS and UTC @@ -514,7 +513,7 @@ void IRAM_ATTR user_request_network_time_callback(void *pVoidUserUTCTime, setMyTime(*pUserUTCTime + requestDelaySec, 0); // end of time critical section: release I2C bus - I2C_MUTEX_UNLOCK(); + unmask_user_IRQ(); } // user_request_network_time_callback #endif // TIME_SYNC_LORAWAN diff --git a/src/main.cpp b/src/main.cpp index 21a2a946..dd6fe4e9 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -415,7 +415,6 @@ void setup() { !defined HAS_GPS && !defined HAS_RTC) #warning you did not specify a time source, time will not be synched #endif -#else // start pps timepulse ESP_LOGI(TAG, "Starting Timekeeper..."); assert(timepulse_init()); // setup timepulse diff --git a/src/rcommand.cpp b/src/rcommand.cpp index 1b124ca8..8e43e24d 100644 --- a/src/rcommand.cpp +++ b/src/rcommand.cpp @@ -277,6 +277,7 @@ void get_time(uint8_t val[]) { ESP_LOGI(TAG, "Remote command: get time"); payload.reset(); payload.addTime(now()); + payload.addByte(timeStatus() << 4 | timeSource); SendPayload(STATUSPORT, prio_high); }; diff --git a/src/timekeeper.cpp b/src/timekeeper.cpp index ef49410b..addd7f85 100644 --- a/src/timekeeper.cpp +++ b/src/timekeeper.cpp @@ -175,9 +175,9 @@ TickType_t tx_Ticks(uint32_t framesize, unsigned long baud, uint32_t config, return round(txTime); } -#if defined HAS_IF482 || defined HAS_DCF77 +#if (defined HAS_IF482 || defined HAS_DCF77) -#if defined HAS_DCF77 && defined HAS_IF482 +#if (defined HAS_DCF77 && defined HAS_IF482) #error You must define at most one of IF482 or DCF77! #endif diff --git a/src/timesync.cpp b/src/timesync.cpp index 066ae9df..0bac12e2 100644 --- a/src/timesync.cpp +++ b/src/timesync.cpp @@ -9,7 +9,7 @@ algorithm in applications without granted license by the patent holder. */ -#if(TIME_SYNC_LORASERVER) +#if (TIME_SYNC_LORASERVER) #include "timesync.h" @@ -111,8 +111,7 @@ void process_timesync_req(void *taskparameter) { } // for // begin of time critical section: lock I2C bus to ensure accurate timing - // don't move the mutex, will impact accuracy of time up to 1 sec! - if (!I2C_MUTEX_LOCK()) + if (!mask_user_IRQ()) goto error; // failure // average time offset from collected diffs @@ -133,9 +132,10 @@ void process_timesync_req(void *taskparameter) { setMyTime(time_to_set, time_to_set_fraction_msec); // end of time critical section: release I2C bus - I2C_MUTEX_UNLOCK(); + unmask_user_IRQ(); finish: + lora_time_sync_pending = false; timeSyncReqTask = NULL; vTaskDelete(NULL); // end task @@ -215,7 +215,8 @@ int recv_timesync_ans(uint8_t buf[], uint8_t buf_len) { // adjust system time, calibrate RTC and RTC_INT pps void IRAM_ATTR setMyTime(uint32_t t_sec, uint16_t t_msec) { - time_t time_to_set = (time_t)t_sec; + // advance time 1 sec wait time + time_t time_to_set = (time_t)(t_sec + 1); ESP_LOGD(TAG, "[%0.3f] Calculated UTC epoch time: %d.%03d sec", millis() / 1000.0, time_to_set, t_msec); @@ -225,16 +226,15 @@ void IRAM_ATTR setMyTime(uint32_t t_sec, uint16_t t_msec) { // wait until top of second with millisecond precision vTaskDelay(pdMS_TO_TICKS(1000 - t_msec)); +// set RTC time and calibrate RTC_INT pulse on top of second #ifdef HAS_RTC - time_to_set++; // advance time 1 sec wait time - // set RTC time and calibrate RTC_INT pulse on top of second set_rtctime(time_to_set, no_mutex); #endif +// sync pps timer to top of second #if (!defined GPS_INT && !defined RTC_INT) - // sync pps timer to top of second timerWrite(ppsIRQ, 0); // reset pps timer - CLOCKIRQ(); // fire clock pps, this advances time 1 sec + CLOCKIRQ(); // fire clock pps, this advances time 1 sec #endif setTime(time_to_set); // set the time on top of second