Index: gpsd.h-tail
===================================================================
--- gpsd.h-tail	(revision 5865)
+++ gpsd.h-tail	(working copy)
@@ -453,7 +453,7 @@
 extern int ntpshm_alloc(struct gps_context_t *);
 extern bool ntpshm_free(struct gps_context_t *, int);
 extern int ntpshm_put(struct gps_device_t *, double);
-extern int ntpshm_pps(struct gps_device_t *,struct timeval *);
+extern int ntpshm_pps(struct gps_device_t *,struct timeval *, int rate);
 
 extern void ecef_to_wgs84fix(/*@out@*/struct gps_data_t *,
 			     double, double, double, 
Index: libgpsd_core.c
===================================================================
--- libgpsd_core.c	(revision 5865)
+++ libgpsd_core.c	(working copy)
@@ -196,34 +196,38 @@
 	    duration = timediff(tv, pulse[state == 0]);
 #undef timediff
 
-	    if (cycle > 199000 && cycle < 201000 ) {
+#define min_interval(center) ((center) * 9 / 10)
+#define max_interval(center) ((center) * 11 / 10)
+#define in_interval(x, center) ((x) > min_interval(center) && (x) < max_interval(center))
+
+	    if (in_interval(cycle, 200000)) {
 		/* 5Hz cycle */
 		/* looks like 5hz PPS pulse */
-		if (duration > 45000)
-		    (void)ntpshm_pps(session, &tv);
+		if (duration > min_interval(160000))
+		    (void)ntpshm_pps(session, &tv, 5);
 		gpsd_report(LOG_RAW, "5Hz PPS pulse. cycle: %d, duration: %d\n",
 			cycle, duration);
-	    } else if (cycle > 999000 && cycle < 1001000 ) {
+	    } else if (in_interval(cycle, 1000000)) {
 		/* looks like PPS pulse or square wave */
-		if (duration > 499000 && duration < 501000
+		if (in_interval(duration, 500000)
 #if defined(NMEA_ENABLE) && defined(GPSCLOCK_ENABLE)
 		  && session->driver.nmea.ignore_trailing_edge
 #endif /* GPSCLOCK_ENABLE */
 		  ) {
 		    /* looks like 1.0 Hz square wave, ignore trailing edge */
 		    if (state == 1) {
-			 (void)ntpshm_pps(session, &tv);
+			 (void)ntpshm_pps(session, &tv, 1);
 		    }
-		} else {
+		} else if (duration > min_interval(800000)) {
 		    /* looks like PPS pulse */
-		    (void)ntpshm_pps(session, &tv);
+		    (void)ntpshm_pps(session, &tv, 1);
 		}
 		gpsd_report(LOG_RAW, "PPS pulse. cycle: %d, duration: %d\n",
 			cycle, duration);
 
-	    } else if (cycle > 1999000 && cycle < 2001000) {
+	    } else if (in_interval(cycle, 2000000)) {
 		/* looks like 0.5 Hz square wave */
-		(void)ntpshm_pps(session, &tv);
+		(void)ntpshm_pps(session, &tv, 1);
 		gpsd_report(LOG_RAW, "PPS square wave. cycle: %d, duration: %d\n",
 			cycle, duration);
 	    } else {
@@ -235,6 +239,10 @@
 	}
 	/*@ -boolint @*/
 
+#undef min_interval
+#undef max_interval
+#undef in_interval
+
 	pulse[state] = tv;
     }
 
Index: ntpshm.c
===================================================================
--- ntpshm.c	(revision 5865)
+++ ntpshm.c	(working copy)
@@ -22,9 +22,6 @@
 #include <sys/ipc.h>
 #include <sys/shm.h>
 
-#define PPS_MAX_OFFSET	100000		/* microseconds the PPS can 'pull' */
-#define PUT_MAX_OFFSET	500000		/* microseconds for lost lock */
-
 #define NTPD_BASE	0x4e545030	/* "NTP0" */
 #define SHM_UNIT	0		/* SHM driver unit number (0..3) */
 
@@ -151,10 +148,11 @@
 #ifdef PPS_ENABLE
 /* put NTP shared memory info based on received PPS pulse */
 
-int ntpshm_pps(struct gps_device_t *session, struct timeval *tv)
+int ntpshm_pps(struct gps_device_t *session, struct timeval *tv, int rate)
 {
     struct shmTime *shmTime = NULL, *shmTimeP = NULL;
     time_t seconds;
+    int usecs;
     double offset;
     long l_offset;
 
@@ -168,36 +166,28 @@
 #ifdef S_SPLINT_S	/* avoids an internal error in splint 3.1.1 */
     l_offset = 0;
 #else
-    l_offset = shmTime->receiveTimeStampSec - shmTime->clockTimeStampSec;
+    l_offset = tv->tv_sec - shmTime->receiveTimeStampSec;
 #endif
-    /*@ -ignorequals @*/
     l_offset *= 1000000;
-    l_offset += shmTime->receiveTimeStampUSec - shmTime->clockTimeStampUSec;
-    /*@ +ignorequals @*/
-    if (labs( l_offset ) > PUT_MAX_OFFSET) {
+    l_offset += tv->tv_usec - shmTime->receiveTimeStampUSec;
+
+    if (l_offset > 1000000 / rate || l_offset < 0) {
         gpsd_report(LOG_RAW, "ntpshm_pps: not in locking range: %ld\n"
 		, (long)l_offset);
 	return -1;
     }
-    /*@ -ignorequals @*/
 
-    if (tv->tv_usec < PPS_MAX_OFFSET) {
-	seconds = (time_t)tv->tv_sec;
-	offset = (double)tv->tv_usec / 1000000.0;
-    } else {
-	if (tv->tv_usec > (1000000 - PPS_MAX_OFFSET)) {
-	    seconds = (time_t)(tv->tv_sec + 1);
-	    offset = 1 - ((double)tv->tv_usec / 1000000.0);
-	} else {
-	    shmTimeP->precision = -1;	/* lost lock */
-	    gpsd_report(LOG_INF, "ntpshm_pps: lost PPS lock\n");
-	    return -1;
-	}
-    }
+    usecs = shmTime->clockTimeStampUSec + 1000000 / rate;
+    seconds = shmTime->clockTimeStampSec + usecs / 1000000;;
+    usecs %= 1000000;
 
+    offset = tv->tv_sec - seconds + (tv->tv_usec - usecs) / 1e6;
+    if (offset < 0.0)
+	    offset = -offset;
+
     shmTimeP->count++;
     shmTimeP->clockTimeStampSec = seconds;
-    shmTimeP->clockTimeStampUSec = 0;
+    shmTimeP->clockTimeStampUSec = usecs;
     shmTimeP->receiveTimeStampSec = (time_t)tv->tv_sec;
     shmTimeP->receiveTimeStampUSec = (int)tv->tv_usec;
     shmTimeP->precision = offset != 0 ? (int)(ceil(log(offset) / M_LN2)) : -20;
