summaryrefslogtreecommitdiff
path: root/libgpsd_core.c
diff options
context:
space:
mode:
authorMick Durkin <mick.durkin@saunalahti.fi>2007-12-18 18:24:41 +0000
committerMick Durkin <mick.durkin@saunalahti.fi>2007-12-18 18:24:41 +0000
commitfb5752876219eb38859ba346286c6b737b4b3ea7 (patch)
treed1cad61c72d6b4827f32d25b0c4ef50c27f987b3 /libgpsd_core.c
parent6c638a2651735e42f477c28dd2c1fe215a45b702 (diff)
downloadgpsd-fb5752876219eb38859ba346286c6b737b4b3ea7.tar.gz
A first attempt at changing the 1pps waveform monitoring...
...so that it accepts 3 formats, independent of polarity:- 1) conventional 1pps, with a 1 second repetition rate and a <200ms pulse whose leading edge marks the second 2) a square wave of 2 second repetition rate (0.5 Hz) each transition of which marks the second 3) a square wave of 1 second repetition rate (1 Hz). The two transitions are filtered against the timestamp of their arrival time so that the one nearest to the full second is chosen and it marks the second.
Diffstat (limited to 'libgpsd_core.c')
-rw-r--r--libgpsd_core.c89
1 files changed, 54 insertions, 35 deletions
diff --git a/libgpsd_core.c b/libgpsd_core.c
index 5711b35f..1eff81fe 100644
--- a/libgpsd_core.c
+++ b/libgpsd_core.c
@@ -22,6 +22,12 @@
#endif
#endif
+#define PLS_HALF_SEC 500000 /* half a second in microseconds */
+#define PLS_LONG_PLS 800000 /* duration of minimum idle time in a "real" pps pulse */
+#define PLS_ONE_SEC 1000000 /* one second in microseconds */
+#define PLS_TWO_SEC 2000000 /* two seconds in microseconds */
+#define PLS_JITTER 50000 /* 50 usec allowance for jitter on the detection of an event */
+#define PLS_DELAY 110000 /* max delay for delviery of 1pps pulse microseconds */
int gpsd_switch_driver(struct gps_device_t *session, char* typename)
{
@@ -138,7 +144,6 @@ static void *gpsd_ppsmonitor(void *arg)
pps_device = TIOCM_CTS;
#endif
-
/* wait for status change on the device's carrier-detect line */
while (ioctl(session->gpsdata.gps_fd, TIOCMIWAIT, pps_device) == 0) {
(void)gettimeofday(&tv,NULL);
@@ -147,7 +152,7 @@ static void *gpsd_ppsmonitor(void *arg)
break;
/*@ -ignoresigns */
- state = (int)((state & pps_device) != 0);
+ state = (int)((state & pps_device) != 0);
if (state == laststate) {
if (++unchanged == 10) {
@@ -166,48 +171,62 @@ static void *gpsd_ppsmonitor(void *arg)
if ( session->context->fixcnt > 3 ) {
/* Garmin doc says PPS is valid after four good fixes. */
/*
- * The PPS pulse is normally a short pulse with a frequency of
- * 1 Hz, and the UTC second is defined by the front edge. But we
- * don't know the polarity of the pulse (different receivers
- * emit different polarities). The duration variable is used to
- * determine which way the pulse is going. The code assumes
- * that the UTC second is changing when the signal has not
- * been changing for at least 800ms, i.e. it assumes the duty
+  * The PPS pulse is normally a short pulse with a frequency of
+  * 1 Hz, and the UTC second is defined by the front edge. But we
+  * don't know the polarity of the pulse (different receivers
+  * emit different polarities).  The duration variable is used to
+  * determine which way the pulse is going.  The code assumes
+  * that the UTC second is changing when the signal has not
+  * been changing for at least 800ms, i.e. it assumes the duty
* cycle is at most 20%.
- *
- * Some GPS instead output a square wave that is 0.5 Hz and each
- * edge denotes the start of a second.
- */
+   *
+  * Some GPS instead output a square wave that is 0.5 Hz and each
+  * edge denotes the start of a second.
+  *
+  * At least one gps (Furuno Electronics GH-79L4 GPSClock-200)
+  * outputs a square wave that is 1 Hz and only the rising edge
+  * is significant. This complicates things since the code is
+  * otherwise insensitive to the direction of the transitions,
+  * as it works by measuring the relative timing of the transitions.
+  */
#define timediff(x, y) (int)((x.tv_sec-y.tv_sec)*1000000+x.tv_usec-y.tv_usec)
cycle = timediff(tv, pulse[state]);
duration = timediff(tv, pulse[state == 0]);
#undef timediff
- if ( 800000 > duration) {
- /* less than 800mS, duration too short for anything */
- gpsd_report(LOG_RAW,
- "PPS pulse rejected too short. cycle: %d, duration: %d\n",
- cycle, duration);
-#ifdef GPSCLOCK_ENABLE
- /*
- * Ugly hack to cope with the Furuno GPSClock, which has the
- * odd property that you have to ignore the trailing
- * edge of the PPS. Someday we'll autoconfigure this.
- */
- if (state == 1) (void)ntpshm_pps(session, &tv);
-#endif /* GPSCLOCK_ENABLE */
- } else if (cycle > 999000 && cycle < 1001000 ) {
- /* looks like PPS pulse */
- (void)ntpshm_pps(session, &tv);
- } else if (cycle > 1999000 && cycle < 2001000) {
+
+ if (duration < PLS_HALF_SEC - PLS_JITTER) {
+ /* duration too short for anything */
+ gpsd_report(LOG_RAW, "PPS pulse rejected too short. cycle: %d, duration: %d\n",
+ cycle, duration);
+ } else if (cycle > PLS_ONE_SEC - PLS_JITTER && cycle < PLS_ONE_SEC + PLS_JITTER ) {
+ /* frequency is 1 Hz , check if it is a pulse or square wave */
+ if (duration < PLS_HALF_SEC + PLS_JITTER) {
+ /* looks like 1 Hz square wave */
+ if (PLS_ONE_SEC - tv.tv_usec < PLS_DELAY || tv.tv_usec < PLS_DELAY)
+ /* this edge is near to a second, so use it */
+ (void)ntpshm_pps(session, &tv);
+ else
+ gpsd_report(LOG_RAW, "PPS 1 Hz signal ignoring inactive edge\n");
+ } else {
+ /* looks like it might be a 1PPS pulse */
+ if (duration > PLS_LONG_PLS - PLS_JITTER)
+ /* looks like conventional PPS pulse */
+ (void)ntpshm_pps(session, &tv);
+ else
+ gpsd_report(LOG_RAW, "PPS pulse rejected invalid length. cycle: %d, duration: %d\n",
+ cycle, duration);
+ }
+ } else if (cycle > PLS_TWO_SEC - PLS_JITTER && cycle < PLS_TWO_SEC + PLS_JITTER ) {
/* looks like 0.5 Hz square wave */
(void)ntpshm_pps(session, &tv);
- } else {
- gpsd_report(LOG_RAW, "PPS pulse rejected. cycle: %d, duration: %d\n",
- cycle, duration);
+ } else {
+ /* general failure */
+ gpsd_report(LOG_RAW, "PPS pulse rejected. cycle: %d, duration: %d\n",
+ cycle, duration);
}
} else {
gpsd_report(LOG_RAW, "PPS pulse rejected. No fix.\n");
- }
+ }
/*@ -boolint @*/
pulse[state] = tv;
@@ -215,7 +234,7 @@ static void *gpsd_ppsmonitor(void *arg)
return NULL;
}
-#endif /* PPS_ENABLE */
+#endif /* defined(PPS_ENABLE) && defined(TIOCMIWAIT) */
/*@ -branchstate @*/
int gpsd_activate(struct gps_device_t *session, bool reconfigurable)