big timesync code sanitization
This commit is contained in:
parent
3f2c08432d
commit
2cf52f1af6
@ -127,7 +127,6 @@ extern SemaphoreHandle_t I2Caccess;
|
||||
extern TaskHandle_t irqHandlerTask, ClockTask;
|
||||
extern TimerHandle_t WifiChanTimer;
|
||||
extern Timezone myTZ;
|
||||
extern time_t userUTCTime;
|
||||
extern RTC_DATA_ATTR runmode_t RTC_runmode;
|
||||
|
||||
// application includes
|
||||
|
@ -5,9 +5,6 @@
|
||||
#include "rcommand.h"
|
||||
#include "timekeeper.h"
|
||||
#include <driver/rtc_io.h>
|
||||
#if (TIME_SYNC_LORASERVER)
|
||||
#include "timesync.h"
|
||||
#endif
|
||||
|
||||
// LMIC-Arduino LoRaWAN Stack
|
||||
#include <lmic.h>
|
||||
@ -54,9 +51,4 @@ const char *getSfName(rps_t rps);
|
||||
const char *getBwName(rps_t rps);
|
||||
const char *getCrName(rps_t rps);
|
||||
|
||||
#if (TIME_SYNC_LORAWAN)
|
||||
void user_request_network_time_callback(void *pVoidUserUTCTime,
|
||||
int flagSuccess);
|
||||
#endif
|
||||
|
||||
#endif
|
@ -5,6 +5,7 @@
|
||||
#include "rtctime.h"
|
||||
#include "TimeLib.h"
|
||||
#include "irqhandler.h"
|
||||
#include "timesync.h"
|
||||
|
||||
#if (HAS_GPS)
|
||||
#include "gpsread.h"
|
||||
|
@ -1,30 +1,31 @@
|
||||
#ifndef _TIMESYNC_H
|
||||
#define _TIMESYNC_H
|
||||
|
||||
#include <chrono>
|
||||
#include "globals.h"
|
||||
#include "irqhandler.h"
|
||||
#include "timekeeper.h"
|
||||
|
||||
//#define TIME_SYNC_TRIGGER 100 // threshold for time sync [milliseconds]
|
||||
#define TIME_SYNC_FRAME_LENGTH 0x07 // timeserver answer frame length [bytes]
|
||||
#define TIME_SYNC_FIXUP 16 // empirical calibration to fixup processing time [milliseconds]
|
||||
#define TIME_SYNC_FIXUP 16 // compensation for processing time [milliseconds]
|
||||
#define TIMEREQUEST_MAX_SEQNO 0xfe // threshold for wrap around seqno
|
||||
#define TIMEREQUEST_FINISH \
|
||||
(TIMEREQUEST_MAX_SEQNO + 1) // marker for end of timesync handshake
|
||||
#define GPS_UTC_DIFF 315964800
|
||||
|
||||
enum timesync_t {
|
||||
timesync_tx,
|
||||
timesync_rx,
|
||||
gwtime_sec,
|
||||
gwtime_msec,
|
||||
gwtime_tzsec,
|
||||
no_of_timestamps
|
||||
};
|
||||
|
||||
void timesync_init(void);
|
||||
void send_timesync_req(void);
|
||||
int recv_timesync_ans(const uint8_t buf[], uint8_t buf_len);
|
||||
void process_timesync_req(void *taskparameter);
|
||||
void store_timestamp(uint32_t timestamp, timesync_t timestamp_type);
|
||||
void IRAM_ATTR process_timesync_req(void *taskparameter);
|
||||
void IRAM_ATTR process_timesync_req(void *pVoidUserUTCTime, int flagSuccess);
|
||||
|
||||
#endif
|
||||
|
@ -381,56 +381,6 @@ void lora_enqueuedata(MessageBuffer_t *message) {
|
||||
|
||||
void lora_queuereset(void) { xQueueReset(LoraSendQueue); }
|
||||
|
||||
#if (TIME_SYNC_LORAWAN)
|
||||
void IRAM_ATTR user_request_network_time_callback(void *pVoidUserUTCTime,
|
||||
int flagSuccess) {
|
||||
// Explicit conversion from void* to uint32_t* to avoid compiler errors
|
||||
time_t *pUserUTCTime = (time_t *)pVoidUserUTCTime;
|
||||
|
||||
// A struct that will be populated by LMIC_getNetworkTimeReference.
|
||||
// It contains the following fields:
|
||||
// - tLocal: the value returned by os_GetTime() when the time
|
||||
// request was sent to the gateway, and
|
||||
// - tNetwork: the seconds between the GPS epoch and the time
|
||||
// the gateway received the time request
|
||||
lmic_time_reference_t lmicTimeReference;
|
||||
|
||||
if (flagSuccess != 1) {
|
||||
ESP_LOGW(TAG, "LoRaWAN network did not answer time request");
|
||||
return;
|
||||
}
|
||||
|
||||
// Populate lmic_time_reference
|
||||
flagSuccess = LMIC_getNetworkTimeReference(&lmicTimeReference);
|
||||
if (flagSuccess != 1) {
|
||||
ESP_LOGW(TAG, "LoRaWAN time request failed");
|
||||
return;
|
||||
}
|
||||
|
||||
// mask application irq to ensure accurate timing
|
||||
mask_user_IRQ();
|
||||
|
||||
// Update userUTCTime, considering the difference between the GPS and UTC
|
||||
// time, and the leap seconds until year 2019
|
||||
*pUserUTCTime = lmicTimeReference.tNetwork + 315964800;
|
||||
// Current time, in ticks
|
||||
ostime_t ticksNow = os_getTime();
|
||||
// Time when the request was sent, in ticks
|
||||
ostime_t ticksRequestSent = lmicTimeReference.tLocal;
|
||||
// Add the delay between the instant the time was transmitted and
|
||||
// the current time
|
||||
time_t requestDelaySec = osticks2ms(ticksNow - ticksRequestSent) / 1000;
|
||||
|
||||
// Update system time with time read from the network
|
||||
setMyTime(*pUserUTCTime + requestDelaySec, 0, _lora);
|
||||
|
||||
finish:
|
||||
// end of time critical section: release app irq lock
|
||||
unmask_user_IRQ();
|
||||
|
||||
} // user_request_network_time_callback
|
||||
#endif // TIME_SYNC_LORAWAN
|
||||
|
||||
// LMIC lorawan stack task
|
||||
void lmictask(void *pvParameters) {
|
||||
configASSERT(((uint32_t)pvParameters) == 1);
|
||||
|
@ -87,7 +87,6 @@ hw_timer_t *ppsIRQ = NULL, *displayIRQ = NULL, *matrixDisplayIRQ = NULL;
|
||||
TaskHandle_t irqHandlerTask = NULL, ClockTask = NULL;
|
||||
SemaphoreHandle_t I2Caccess;
|
||||
bool volatile TimePulseTick = false;
|
||||
time_t userUTCTime = 0;
|
||||
timesource_t timeSource = _unsynced;
|
||||
|
||||
// container holding unique MAC address hashes with Memory Alloctor using PSRAM,
|
||||
|
@ -37,12 +37,9 @@ void calibrateTime(void) {
|
||||
}
|
||||
#endif
|
||||
|
||||
// kick off asychronous Lora timeserver timesync if we have
|
||||
#if (HAS_LORA) && (TIME_SYNC_LORASERVER)
|
||||
// kick off asychronous lora timesync if we have
|
||||
#if (HAS_LORA) && (TIME_SYNC_LORASERVER) || (TIME_SYNC_LORAWAN)
|
||||
send_timesync_req();
|
||||
// kick off asychronous lora network sync if we have
|
||||
#elif (HAS_LORA) && (TIME_SYNC_LORAWAN)
|
||||
LMIC_requestNetworkTime(user_request_network_time_callback, &userUTCTime);
|
||||
#endif
|
||||
|
||||
// no time from GPS -> fallback to RTC time while trying lora sync
|
||||
@ -233,7 +230,7 @@ void clock_init(void) {
|
||||
pinMode(HAS_DCF77, OUTPUT);
|
||||
#endif
|
||||
|
||||
userUTCTime = now();
|
||||
time_t userUTCTime = now();
|
||||
|
||||
xTaskCreatePinnedToCore(clock_loop, // task function
|
||||
"clockloop", // name of task
|
||||
|
@ -1,31 +1,37 @@
|
||||
/*
|
||||
|
||||
///--> IMPORTANT LICENSE NOTE for this file <--///
|
||||
///--> IMPORTANT LICENSE NOTE for timesync option 1 in this file <--///
|
||||
|
||||
PLEASE NOTE: There is a patent filed for the time sync algorithm used in the
|
||||
code of this file. The shown implementation example is covered by the
|
||||
repository's licencse, but you may not be eligible to deploy the applied
|
||||
algorithm in applications without granted license by the patent holder.
|
||||
|
||||
You may use timesync option 2 if you do not want or cannot accept this.
|
||||
|
||||
*/
|
||||
|
||||
#if (TIME_SYNC_LORASERVER) && (HAS_LORA)
|
||||
|
||||
#include "timesync.h"
|
||||
|
||||
#if (TIME_SYNC_LORASERVER) && (TIME_SYNC_LORAWAN) && (HAS_LORA)
|
||||
#error Duplicate timesync method selected. You must select either LORASERVER or LORAWAN timesync.
|
||||
#endif
|
||||
|
||||
// Local logging tag
|
||||
static const char TAG[] = __FILE__;
|
||||
|
||||
TaskHandle_t timeSyncReqTask = NULL;
|
||||
// timesync option 1: use external timeserver (for LoRAWAN < 1.0.3)
|
||||
|
||||
#if (TIME_SYNC_LORASERVER) && (HAS_LORA)
|
||||
|
||||
static TaskHandle_t timeSyncReqTask = NULL;
|
||||
static bool timeSyncPending = false;
|
||||
static uint8_t time_sync_seqNo = (uint8_t)random(TIMEREQUEST_MAX_SEQNO);
|
||||
static uint8_t sample_idx = 0;
|
||||
static bool timeSyncPending = false;
|
||||
static uint32_t timesync_timestamp[TIME_SYNC_SAMPLES][no_of_timestamps] = {0};
|
||||
|
||||
// send time request message
|
||||
void send_timesync_req() {
|
||||
|
||||
void send_timesync_req(void) {
|
||||
// if a timesync handshake is pending then exit
|
||||
if (timeSyncPending)
|
||||
return;
|
||||
@ -37,7 +43,7 @@ void send_timesync_req() {
|
||||
}
|
||||
|
||||
// task for sending time sync requests
|
||||
void process_timesync_req(void *taskparameter) {
|
||||
void IRAM_ATTR process_timesync_req(void *taskparameter) {
|
||||
|
||||
uint32_t rcv_seq_no = TIMEREQUEST_FINISH, time_offset_ms;
|
||||
|
||||
@ -175,22 +181,24 @@ int recv_timesync_ans(const uint8_t buf[], const uint8_t buf_len) {
|
||||
|
||||
else { // we received a probably valid time frame
|
||||
|
||||
// pointers to 4 bytes containing UTC seconds since unix epoch, msb
|
||||
// pointers to 4 bytes msb order
|
||||
uint32_t timestamp_sec, *timestamp_ptr;
|
||||
|
||||
// extract 1 byte timezone from payload (one step being 15min * 60s = 900s)
|
||||
// uint32_t timezone_sec = buf[0] * 900; // for future use
|
||||
// extract 1 byte containing timezone offset
|
||||
// one step being 15min * 60sec = 900sec
|
||||
uint32_t timestamp_tzsec = buf[0] * 900; // timezone offset in secs
|
||||
buf++;
|
||||
|
||||
// extract 4 bytes timestamp from payload
|
||||
// and convert it to uint32_t, octet order is big endian
|
||||
// extract 4 bytes containing gateway time in UTC seconds since unix
|
||||
// epoch and convert it to uint32_t, octet order is big endian
|
||||
timestamp_ptr = (uint32_t *)buf;
|
||||
// swap byte order from msb to lsb, note: this is platform dependent
|
||||
// swap byte order from msb to lsb, note: this is a platform dependent hack
|
||||
timestamp_sec = __builtin_bswap32(*timestamp_ptr);
|
||||
buf += 4;
|
||||
// extract 1 byte fractional seconds in 2^-8 second steps
|
||||
// (= 1/250th sec), we convert this to ms
|
||||
uint16_t timestamp_msec = 4 * buf[0];
|
||||
|
||||
// extract 1 byte containing fractional seconds in 2^-8 second steps
|
||||
// one step being 1/250th sec * 1000 = 4msec
|
||||
uint16_t timestamp_msec = buf[0] * 4;
|
||||
// calculate absolute time received from gateway
|
||||
time_t t = timestamp_sec + timestamp_msec / 1000;
|
||||
|
||||
@ -202,6 +210,7 @@ int recv_timesync_ans(const uint8_t buf[], const uint8_t buf_len) {
|
||||
// store time received from gateway
|
||||
store_timestamp(timestamp_sec, gwtime_sec);
|
||||
store_timestamp(timestamp_msec, gwtime_msec);
|
||||
store_timestamp(timestamp_tzsec, gwtime_tzsec);
|
||||
|
||||
// inform processing task
|
||||
xTaskNotify(timeSyncReqTask, seq_no, eSetBits);
|
||||
@ -227,3 +236,56 @@ void timesync_init() {
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
// timesync option 2: use LoRAWAN network time (requires LoRAWAN >= 1.0.3)
|
||||
|
||||
#if (TIME_SYNC_LORAWAN) && (HAS_LORA)
|
||||
|
||||
static time_t networkUTCTime;
|
||||
|
||||
// send time request message
|
||||
void send_timesync_req(void) {
|
||||
LMIC_requestNetworkTime(process_timesync_req, &networkUTCTime);
|
||||
}
|
||||
|
||||
void IRAM_ATTR process_timesync_req(void *pVoidUserUTCTime, int flagSuccess) {
|
||||
// Explicit conversion from void* to uint32_t* to avoid compiler errors
|
||||
time_t *pUserUTCTime = (time_t *)pVoidUserUTCTime;
|
||||
|
||||
// A struct that will be populated by LMIC_getNetworkTimeReference.
|
||||
// It contains the following fields:
|
||||
// - tLocal: the value returned by os_GetTime() when the time
|
||||
// request was sent to the gateway, and
|
||||
// - tNetwork: the seconds between the GPS epoch and the time
|
||||
// the gateway received the time request
|
||||
lmic_time_reference_t lmicTimeReference;
|
||||
|
||||
if (flagSuccess != 1) {
|
||||
ESP_LOGW(TAG, "LoRaWAN network did not answer time request");
|
||||
return;
|
||||
}
|
||||
|
||||
// Populate lmic_time_reference
|
||||
flagSuccess = LMIC_getNetworkTimeReference(&lmicTimeReference);
|
||||
if (flagSuccess != 1) {
|
||||
ESP_LOGW(TAG, "LoRaWAN time request failed");
|
||||
return;
|
||||
}
|
||||
|
||||
// mask application irq to ensure accurate timing
|
||||
mask_user_IRQ();
|
||||
|
||||
// Update networkUTCTime, considering the difference between GPS and UTC time
|
||||
*pUserUTCTime = lmicTimeReference.tNetwork + GPS_UTC_DIFF;
|
||||
// Add delay between the instant the time was transmitted and the current time
|
||||
uint16_t requestDelaymSec =
|
||||
osticks2ms(os_getTime() - lmicTimeReference.tLocal);
|
||||
|
||||
// Update system time with time read from the network
|
||||
setMyTime(*pUserUTCTime, requestDelaymSec, _lora);
|
||||
|
||||
// end of time critical section: release app irq lock
|
||||
unmask_user_IRQ();
|
||||
|
||||
} // user_request_network_time_callback
|
||||
#endif // TIME_SYNC_LORAWAN
|
Loading…
Reference in New Issue
Block a user