summaryrefslogtreecommitdiff
path: root/ppsthread.c
diff options
context:
space:
mode:
authorMiroslav Lichvar <mlichvar@redhat.com>2014-05-27 18:37:02 +0200
committerEric S. Raymond <esr@thyrsus.com>2014-08-17 11:14:14 -0400
commita3ca7297044d71cf743e6b975a47f16810bf071f (patch)
tree84f05472f20f4b4f3c16a77d6c767301d5de87cd /ppsthread.c
parent5c7a4fe2eb6d6ce071d3c50aba76f9a9b4753931 (diff)
downloadgpsd-a3ca7297044d71cf743e6b975a47f16810bf071f.tar.gz
Fix PPS with large offsets.
This was broken by commit 575444. The check if the PPS time isn't referenced with an old message time used PPS offset instead of the difference between local PPS time and local time of the last message. The PPS sample was reported via SHM or chrony socket only if the offset was between -1 and 1000001 seconds. Keep the local timestamp of the last fix in struct gps_device_t in addition to the real timestamp and use it to check the PPS delay. Rename the l_offset variable to delay to avoid further confusion. Signed-off-by: Eric S. Raymond <esr@thyrsus.com>
Diffstat (limited to 'ppsthread.c')
-rw-r--r--ppsthread.c22
1 files changed, 12 insertions, 10 deletions
diff --git a/ppsthread.c b/ppsthread.c
index d9e431e0..ed5c7efd 100644
--- a/ppsthread.c
+++ b/ppsthread.c
@@ -238,7 +238,7 @@ static int init_kernel_pps(struct gps_device_t *session)
static /*@null@*/ void *gpsd_ppsmonitor(void *arg)
{
struct gps_device_t *session = (struct gps_device_t *)arg;
- double last_fixtime = 0;
+ double last_fixtime_real = 0, last_fixtime_clock = 0;
#ifndef HAVE_CLOCK_GETTIME
struct timeval clock_tv = {0, 0};
#endif /* HAVE_CLOCK_GETTIME */
@@ -299,7 +299,8 @@ static /*@null@*/ void *gpsd_ppsmonitor(void *arg)
break;
}
/* quick, grab a copy of last_fixtime before it changes */
- last_fixtime = session->last_fixtime;
+ last_fixtime_real = session->last_fixtime.real;
+ last_fixtime_clock = session->last_fixtime.clock;
/*@-noeffect@*/
/* get the time after we just woke up */
@@ -541,7 +542,7 @@ static /*@null@*/ void *gpsd_ppsmonitor(void *arg)
log = "Too long for 0.5Hz\n";
}
#endif /* TIOCMIWAIT */
- if ( ok && last_second_used >= last_fixtime ) {
+ if ( ok && last_second_used >= last_fixtime_real ) {
/* uh, oh, this second already handled */
ok = 0;
log = "this second already handled\n";
@@ -550,7 +551,8 @@ static /*@null@*/ void *gpsd_ppsmonitor(void *arg)
if (ok) {
/* offset is the skew from expected to observed pulse time */
double offset;
- long l_offset;
+ /* delay after last fix */
+ double delay;
char *log1 = NULL;
/* drift.real is the time we think the pulse represents */
struct timedrift_t drift;
@@ -580,7 +582,7 @@ static /*@null@*/ void *gpsd_ppsmonitor(void *arg)
*/
/*@+relaxtypes@*/
- drift.real.tv_sec = last_fixtime + 1;
+ drift.real.tv_sec = last_fixtime_real + 1;
drift.real.tv_nsec = 0; /* need to be fixed for 5Hz */
drift.clock = clock_ts;
/*@-relaxtypes@*/
@@ -589,15 +591,15 @@ static /*@null@*/ void *gpsd_ppsmonitor(void *arg)
* GPS serial input then use that */
offset = (drift.real.tv_sec - drift.clock.tv_sec);
offset += ((drift.real.tv_nsec - drift.clock.tv_nsec) / 1e9);
- l_offset = (long) offset;
- if (0 > l_offset || 1000000 < l_offset) {
+ delay = (drift.clock.tv_sec + drift.clock.tv_nsec / 1e9) - last_fixtime_clock;
+ if (0.0 > delay || 1.0 < delay) {
gpsd_report(session->context->debug, LOG_RAW,
- "PPS: no current GPS seconds: %ld\n",
- (long)l_offset);
+ "PPS: no current GPS seconds: %f\n",
+ delay);
log1 = "timestamp out of range";
} else {
/*@-compdef@*/
- last_second_used = last_fixtime;
+ last_second_used = last_fixtime_real;
if (session->thread_report_hook != NULL)
log1 = session->thread_report_hook(session, &drift);
else