From 928c234b0ebec37f302d5c1e4b0c0f03b6e58d2d Mon Sep 17 00:00:00 2001 From: Jason Reiss Date: Mon, 21 Nov 2022 11:37:12 -0600 Subject: gps: fix calculation of cnt in the past, PPS may be updated after packet is received and stamped --- libloragw/src/loragw_gps.c | 34 +++++++++++++++++++++++++++++----- 1 file changed, 29 insertions(+), 5 deletions(-) (limited to 'libloragw/src') diff --git a/libloragw/src/loragw_gps.c b/libloragw/src/loragw_gps.c index d02e23a..b461439 100644 --- a/libloragw/src/loragw_gps.c +++ b/libloragw/src/loragw_gps.c @@ -720,12 +720,19 @@ int lgw_cnt2utc(struct tref ref, uint32_t count_us, struct timespec *utc) { } /* calculate delta in seconds between reference count_us and target count_us */ - delta_sec = (double)(count_us - ref.count_us) / (TS_CPS * ref.xtal_err); + if (count_us > ref.count_us) { + delta_sec = (double)(count_us - ref.count_us) / (TS_CPS * ref.xtal_err); + } else { + delta_sec = -(double)(ref.count_us - count_us) / (TS_CPS * ref.xtal_err); + } /* now add that delta to reference UTC time */ fractpart = modf (delta_sec , &intpart); tmp = ref.utc.tv_nsec + (long)(fractpart * 1E9); - if (tmp < (long)1E9) { /* the nanosecond part doesn't overflow */ + if (tmp < 0) { + utc->tv_sec = ref.utc.tv_sec + (time_t)intpart - 1; + utc->tv_nsec = (long)1E9 + tmp; + } else if (tmp < (long)1E9) { /* the nanosecond part doesn't overflow */ utc->tv_sec = ref.utc.tv_sec + (time_t)intpart; utc->tv_nsec = tmp; } else { /* must carry one second */ @@ -747,6 +754,11 @@ int lgw_utc2cnt(struct tref ref, struct timespec utc, uint32_t *count_us) { return LGW_GPS_ERROR; } + if (utc.tv_sec < ref.utc.tv_sec || (utc.tv_sec == ref.utc.tv_sec && utc.tv_nsec < ref.utc.tv_nsec)) { + DEBUG_MSG("ERROR: UTC time has passed\n"); + return LGW_GPS_ERROR; + } + /* calculate delta in seconds between reference utc and target utc */ delta_sec = (double)(utc.tv_sec - ref.utc.tv_sec); delta_sec += 1E-9 * (double)(utc.tv_nsec - ref.utc.tv_nsec); @@ -770,13 +782,20 @@ int lgw_cnt2gps(struct tref ref, uint32_t count_us, struct timespec *gps_time) { return LGW_GPS_ERROR; } - /* calculate delta in milliseconds between reference count_us and target count_us */ - delta_sec = (double)(count_us - ref.count_us) / (TS_CPS * ref.xtal_err); + /* calculate delta in seconds between reference count_us and target count_us */ + if (count_us > ref.count_us) { + delta_sec = (double)(count_us - ref.count_us) / (TS_CPS * ref.xtal_err); + } else { + delta_sec = -(double)(ref.count_us - count_us) / (TS_CPS * ref.xtal_err); + } /* now add that delta to reference GPS time */ fractpart = modf (delta_sec , &intpart); tmp = ref.gps.tv_nsec + (long)(fractpart * 1E9); - if (tmp < (long)1E9) { /* the nanosecond part doesn't overflow */ + if (tmp < 0) { + gps_time->tv_sec = ref.gps.tv_sec + (time_t)intpart - 1; + gps_time->tv_nsec = (long)1E9 + tmp; + } else if (tmp < (long)1E9) { /* the nanosecond part doesn't overflow */ gps_time->tv_sec = ref.gps.tv_sec + (time_t)intpart; gps_time->tv_nsec = tmp; } else { /* must carry one second */ @@ -798,6 +817,11 @@ int lgw_gps2cnt(struct tref ref, struct timespec gps_time, uint32_t *count_us) { return LGW_GPS_ERROR; } + if (gps_time.tv_sec < ref.gps.tv_sec || (gps_time.tv_sec == ref.gps.tv_sec && gps_time.tv_nsec < ref.gps.tv_nsec)) { + DEBUG_MSG("ERROR: GPS time has passed\n"); + return LGW_GPS_ERROR; + } + /* calculate delta in seconds between reference gps time and target gps time */ delta_sec = (double)(gps_time.tv_sec - ref.gps.tv_sec); delta_sec += 1E-9 * (double)(gps_time.tv_nsec - ref.gps.tv_nsec); -- cgit v1.2.3