[ntp:bk-ntp-stable-send] BitKeeper diffs

Harlan Stenn stenn at deacon.udel.edu
Sun Oct 24 05:59:35 UTC 2010


#### ChangeSet ####
2010-10-23 18:59:27+02:00, jnperlin at hydra.localnet 
  ntp_fp.h: HTONL_MFP() uses ntohl(), should use htonl() (benign error)

==== include/ntp_fp.h ====
2010-10-23 18:59:26+02:00, jnperlin at hydra.localnet +16 -16
  HTONL_MFP() uses ntohl(), should use htonl() (benign error)

--- 1.15/include/ntp_fp.h	2009-06-14 23:46:06 -04:00
+++ 1.16/include/ntp_fp.h	2010-10-23 12:59:26 -04:00
@@ -70,7 +70,7 @@ typedef int32 s_fp;
 typedef u_int32 u_fp;
 
 /*
- * A unit second in fp format.  Actually 2**(half_the_bits_in_a_long)
+ * A unit second in fp format.	Actually 2**(half_the_bits_in_a_long)
  */
 #define	FP_SECOND	(0x10000)
 
@@ -86,9 +86,9 @@ typedef u_int32 u_fp;
 #define	NTOHL_MFP(ni, nf, hi, hf) \
 	do { (hi) = ntohl(ni); (hf) = ntohl(nf); } while (0)
 #define	HTONL_MFP(hi, hf, ni, nf) \
-	do { (ni) = ntohl(hi); (nf) = ntohl(hf); } while (0)
+	do { (ni) = htonl(hi); (nf) = htonl(hf); } while (0)
 
-/* funny ones.  Converts ts fractions to net order ts */
+/* funny ones.	Converts ts fractions to net order ts */
 #define	HTONL_UF(uf, nts) \
 	do { (nts)->l_ui = 0; (nts)->l_uf = htonl(uf); } while (0)
 #define	HTONL_F(f, nts) do { (nts)->l_uf = htonl(f); \
@@ -118,7 +118,7 @@ typedef u_int32 u_fp;
  * be replaced by inline assembler for particular machines someday.
  * These are the (kind of inefficient) run-anywhere versions.
  */
-#define	M_NEG(v_i, v_f) 	/* v = -v */ \
+#define	M_NEG(v_i, v_f)		/* v = -v */ \
 	do { \
 		if ((v_f) == 0) \
 			(v_i) = -((s_fp)(v_i)); \
@@ -128,7 +128,7 @@ typedef u_int32 u_fp;
 		} \
 	} while(0)
 
-#define	M_NEGM(r_i, r_f, a_i, a_f) 	/* r = -a */ \
+#define	M_NEGM(r_i, r_f, a_i, a_f)	/* r = -a */ \
 	do { \
 		if ((a_f) == 0) { \
 			(r_f) = 0; \
@@ -139,7 +139,7 @@ typedef u_int32 u_fp;
 		} \
 	} while(0)
 
-#define M_ADD(r_i, r_f, a_i, a_f) 	/* r += a */ \
+#define M_ADD(r_i, r_f, a_i, a_f)	/* r += a */ \
 	do { \
 		register u_int32 lo_tmp; \
 		register u_int32 hi_tmp; \
@@ -238,7 +238,7 @@ typedef u_int32 u_fp;
 		(v_f) <<= 1; \
 	} while (0)
 
-#define	M_ADDUF(r_i, r_f, uf) 		/* r += uf, uf is u_int32 fraction */ \
+#define	M_ADDUF(r_i, r_f, uf)		/* r += uf, uf is u_int32 fraction */ \
 	M_ADD((r_i), (r_f), 0, (uf))	/* let optimizer worry about it */
 
 #define	M_SUBUF(r_i, r_f, uf)		/* r -= uf, uf is u_int32 fraction */ \
@@ -252,7 +252,7 @@ typedef u_int32 u_fp;
 			M_ADD((r_i), (r_f), (-1), (f));\
 	} while(0)
 
-#define	M_ISNEG(v_i, v_f) 		/* v < 0 */ \
+#define	M_ISNEG(v_i, v_f)		/* v < 0 */ \
 	(((v_i) & 0x80000000) != 0)
 
 #define	M_ISHIS(a_i, a_f, b_i, b_f)	/* a >= b unsigned */ \
@@ -291,7 +291,7 @@ typedef u_int32 u_fp;
 /*
  * s_fp/double and u_fp/double conversions
  */
-#define FRIC		65536.	 		/* 2^16 as a double */
+#define FRIC		65536.			/* 2^16 as a double */
 #define DTOFP(r)	((s_fp)((r) * FRIC))
 #define DTOUFP(r)	((u_fp)((r) * FRIC))
 #define FPTOD(r)	((double)(r) / FRIC)
@@ -299,8 +299,8 @@ typedef u_int32 u_fp;
 /*
  * l_fp/double conversions
  */
-#define FRAC		4294967296. 		/* 2^32 as a double */
-#define M_DTOLFP(d, r_i, r_uf) 			/* double to l_fp */ \
+#define FRAC		4294967296.		/* 2^32 as a double */
+#define M_DTOLFP(d, r_i, r_uf)			/* double to l_fp */ \
 	do { \
 		register double d_tmp; \
 		\
@@ -315,7 +315,7 @@ typedef u_int32 u_fp;
 			(r_uf) = (u_int32)(((d_tmp) - (double)(r_i)) * FRAC); \
 		} \
 	} while (0)
-#define M_LFPTOD(r_i, r_uf, d) 			/* l_fp to double */ \
+#define M_LFPTOD(r_i, r_uf, d)			/* l_fp to double */ \
 	do { \
 		register l_fp l_tmp; \
 		\
@@ -328,8 +328,8 @@ typedef u_int32 u_fp;
 			(d) = (double)l_tmp.l_i + ((double)l_tmp.l_uf) / FRAC; \
 		} \
 	} while (0)
-#define DTOLFP(d, v) 	M_DTOLFP((d), (v)->l_ui, (v)->l_uf)
-#define LFPTOD(v, d) 	M_LFPTOD((v)->l_ui, (v)->l_uf, (d))
+#define DTOLFP(d, v)	M_DTOLFP((d), (v)->l_ui, (v)->l_uf)
+#define LFPTOD(v, d)	M_LFPTOD((v)->l_ui, (v)->l_uf, (d))
 
 /*
  * Prototypes
@@ -342,12 +342,12 @@ extern	int	buftvtots	(const char *, l_fp
 extern	char *	fptoa		(s_fp, short);
 extern	char *	fptoms		(s_fp, short);
 extern	int	hextolfp	(const char *, l_fp *);
-extern  void    gpstolfp        (int, int, unsigned long, l_fp *);
+extern	void	gpstolfp	(int, int, unsigned long, l_fp *);
 extern	int	mstolfp		(const char *, l_fp *);
 extern	char *	prettydate	(l_fp *);
 extern	char *	gmprettydate	(l_fp *);
 extern	char *	uglydate	(l_fp *);
-extern  void    mfp_mul         (int32 *, u_int32 *, int32, u_int32, int32, u_int32);
+extern	void	mfp_mul		(int32 *, u_int32 *, int32, u_int32, int32, u_int32);
 
 extern	void	get_systime	(l_fp *);
 extern	int	step_systime	(double);

#### ChangeSet ####
2010-10-23 03:07:11+02:00, jnperlin at hydra.localnet 
  polish to NMEA driver

==== ntpd/refclock_nmea.c ====
2010-10-23 03:07:11+02:00, jnperlin at hydra.localnet +55 -53
  formatting issues

--- 1.52/ntpd/refclock_nmea.c	2010-10-22 20:24:08 -04:00
+++ 1.53/ntpd/refclock_nmea.c	2010-10-22 21:07:11 -04:00
@@ -4,8 +4,8 @@
  *		 based on refclock_heathn.c
  *
  * Updated to add support for Accord GPS Clock
- * 		Venu Gopal Dec 05, 2007
- * 		neo.venu at gmail.com, venugopal_d at pgad.gov.in
+ *		Venu Gopal Dec 05, 2007
+ *		neo.venu at gmail.com, venugopal_d at pgad.gov.in
  *
  * Updated to process 'time1' fudge factor
  *		Venu Gopal May 05, 2008
@@ -46,10 +46,10 @@ extern int async_write(int, const void *
 
 #ifndef TIMESPECTOTS
 #define TIMESPECTOTS(ptspec, pts)					\
-        do {								\
-                DTOLFP((ptspec)->tv_nsec * 1.0e-9, pts);		\
-                (pts)->l_ui += (u_int32)((ptspec)->tv_sec) + JAN_1970;  \
-        } while (0)
+	do {								\
+		DTOLFP((ptspec)->tv_nsec * 1.0e-9, pts);		\
+		(pts)->l_ui += (u_int32)((ptspec)->tv_sec) + JAN_1970;	\
+	} while (0)
 #endif
 
 
@@ -59,7 +59,7 @@ extern int async_write(int, const void *
  * Prototype was refclock_trak.c, Thanks a lot.
  *
  * The receiver used spits out the NMEA sentences for boat navigation.
- * And you thought it was an information superhighway.  Try a raging river
+ * And you thought it was an information superhighway.	Try a raging river
  * filled with rapids and whirlpools that rip away your data and warp time.
  *
  * If HAVE_PPSAPI is defined code to use the PPSAPI will be compiled in.
@@ -91,12 +91,12 @@ extern int async_write(int, const void *
  *		4 for 57600 
  *		5 for 115200 
  */
-#define NMEA_MESSAGE_MASK_OLD    0x07
+#define NMEA_MESSAGE_MASK_OLD	 0x07
 #define NMEA_MESSAGE_MASK_SINGLE 0x08
-#define NMEA_MESSAGE_MASK        (NMEA_MESSAGE_MASK_OLD | NMEA_MESSAGE_MASK_SINGLE)
+#define NMEA_MESSAGE_MASK	 (NMEA_MESSAGE_MASK_OLD | NMEA_MESSAGE_MASK_SINGLE)
 
-#define NMEA_BAUDRATE_MASK       0x70
-#define NMEA_BAUDRATE_SHIFT      4
+#define NMEA_BAUDRATE_MASK	 0x70
+#define NMEA_BAUDRATE_SHIFT	 4
 
 /*
  * Definitions
@@ -128,9 +128,9 @@ extern int async_write(int, const void *
 /*
  * $GPZDG is a proprietary sentence that violates the spec, by not
  * using $P and an assigned company identifier to prefix the sentence
- * identifier.  When used with this driver, the system needs to be
+ * identifier.	When used with this driver, the system needs to be
  * isolated from other NTP networks, as it operates in GPS time, not
- * UTC as is much more common.  GPS time is >15 seconds different from
+ * UTC as is much more common.	GPS time is >15 seconds different from
  * UTC due to not respecting leap seconds since 1970 or so.  Other
  * than the different timebase, $GPZDG is similar to $GPZDA.
  */
@@ -165,7 +165,7 @@ struct nmeaunit {
 	int	ppsapi_tried;	/* attempt PPSAPI once */
 	int	ppsapi_lit;	/* time_pps_create() worked */
 	int	ppsapi_fd;	/* fd used with PPSAPI */
-	int     ppsapi_gate;	/* allow edge detection processing */
+	int	ppsapi_gate;	/* allow edge detection processing */
 	int	tcount;		/* timecode sample counter */
 	int	pcount;		/* PPS sample counter */
 #endif /* HAVE_PPSAPI */
@@ -185,7 +185,7 @@ static	void	nmea_poll	(int, struct peer 
 #ifdef HAVE_PPSAPI
 static	void	nmea_control	(int, struct refclockstat *,
 				 struct refclockstat *, struct peer *);
-static  void	nmea_timer	(int, struct peer *);
+static	void	nmea_timer	(int, struct peer *);
 #define		NMEA_CONTROL	nmea_control
 #define		NMEA_TIMER	nmea_timer
 #else
@@ -239,33 +239,33 @@ nmea_start(
 	 * based on the value of bit 4/5/6
 	 */
 	switch ((peer->ttl & NMEA_BAUDRATE_MASK) >> NMEA_BAUDRATE_SHIFT) {
-	    case 0:
-	    case 6:
-	    case 7:
-	    default:
+	case 0:
+	case 6:
+	case 7:
+	default:
 		baudrate = SPEED232;
 		baudtext = "4800";
 		break;
-	    case 1:
+	case 1:
 		baudrate = B9600;
 		baudtext = "9600";
 		break;
-	    case 2:
+	case 2:
 		baudrate = B19200;
 		baudtext = "19200";
 		break;
-	    case 3:
+	case 3:
 		baudrate = B38400;
 		baudtext = "38400";
 		break;
 #ifdef B57600
-	    case 4:
+	case 4:
 		baudrate = B57600;
 		baudtext = "57600";
 		break;
 #endif
 #ifdef B115200
-	    case 5:
+	case 5:
 		baudrate = B115200;
 		baudtext = "115200";
 		break;
@@ -281,8 +281,9 @@ nmea_start(
 		 * See http://home.hiwaay.net/~taylorc/gps/nmea-server/
 		 * for information about nmead
 		 *
-		 * To use this, you need to create a link from /dev/gpsX to
-		 * the server:port where nmead is running.  Something like this:
+		 * To use this, you need to create a link from /dev/gpsX
+		 * to the server:port where nmead is running.  Something
+		 * like this:
 		 *
 		 * ln -s server:port /dev/gps1
 		 */
@@ -530,23 +531,23 @@ nmea_timer(
  * is updated to reflect the proper fudge time to apply. (This implies
  * that 'refclock_process_f()' must be used!)
  */
-#define PPS_RELATE_NONE  0	/* no pps correlation possible    */
-#define PPS_RELATE_EDGE  1	/* recv time fixed, no phase lock */
+#define PPS_RELATE_NONE	 0	/* no pps correlation possible	  */
+#define PPS_RELATE_EDGE	 1	/* recv time fixed, no phase lock */
 #define PPS_RELATE_PHASE 2	/* recv time fixed, phase lock ok */
 
 static int
 refclock_ppsrelate(
-	const struct refclockproc  *pp      ,	/* for sanity     */
-	const struct refclock_atom *ap      ,	/* for PPS io     */
-	const l_fp                 *reftime ,
-	l_fp                       *rd_stamp,	/* i/o read stamp */
-	double                      pp_fudge,	/* pps fudge      */
-	double                     *rd_fudge)	/* i/o read fudge */
+	const struct refclockproc  *pp	    ,	/* for sanity	  */
+	const struct refclock_atom *ap	    ,	/* for PPS io	  */
+	const l_fp		   *reftime ,
+	l_fp			   *rd_stamp,	/* i/o read stamp */
+	double			    pp_fudge,	/* pps fudge	  */
+	double			   *rd_fudge)	/* i/o read fudge */
 {
-	pps_info_t      pps_info;
+	pps_info_t	pps_info;
 	struct timespec timeout;
-	l_fp            pp_stamp, pp_delta;
-	double          delta, idelta;
+	l_fp		pp_stamp, pp_delta;
+	double		delta, idelta;
 
 	if (pp->leap == LEAP_NOTINSYNC)
 		return PPS_RELATE_NONE;	/* clock is insane, no chance */
@@ -576,9 +577,9 @@ refclock_ppsrelate(
 		return PPS_RELATE_NONE; /* PPS timeout control */
 	
 	/* eventually warp edges, check phase */
-	idelta    = floor(delta + 0.5);
+	idelta	  = floor(delta + 0.5);
 	pp_fudge -= idelta;
-	delta    -= idelta;
+	delta	 -= idelta;
 	if (fabs(delta) > 0.45)
 		return PPS_RELATE_NONE; /* dead band control */
 
@@ -616,11 +617,12 @@ nmea_receive(
 	struct peer *peer;
 	char *cp, *dp, *msg;
 	u_char sentence;
-	/* Use these variables to hold data until we decide its worth keeping */
+	/* Use these variables to hold data until we decide its worth
+	 * keeping */
 	char	rd_lastcode[BMAX];
 	l_fp	rd_timestamp, reftime;
 	int	rd_lencode;
-	double  rd_fudge;
+	double	rd_fudge;
 	struct calendar date;
 
 	/*
@@ -672,7 +674,7 @@ nmea_receive(
 	 *  It contains the GPS timestamp valid for next PPS pulse.
 	 *  Apart from the familiar fields, 
 	 *  'AA.BB' denotes the signal strength( should be < 05.00 ) 
-	 *  'V'     denotes the GPS sync status : 
+	 *  'V'	    denotes the GPS sync status : 
 	 *	   '0' indicates INVALID time, 
 	 *	   '1' indicates accuracy of +/-20 ms
 	 *	   '2' indicates accuracy of +/-100 ns
@@ -872,7 +874,7 @@ nmea_receive(
 		date.month = 10 * (dp[0] - '0') + (dp[1] - '0');
 		dp = field_parse(cp, 4);
 		date.year = 1000 * (dp[0] - '0') + 100 * (dp[1] - '0')
-		          + 10 * (dp[2] - '0') + (dp[3] - '0');
+			  + 10 * (dp[2] - '0') + (dp[3] - '0');
 
 	} else
 		nmea_day_unfold(&date);
@@ -982,21 +984,21 @@ nmea_receive(
 #ifdef HAVE_PPSAPI
 	up->tcount++;
 	/*
-	 * If we have PPS running, we try to associate the sentence with the last
-	 * active edge of the PPS signal.
+	 * If we have PPS running, we try to associate the sentence with
+	 * the last active edge of the PPS signal.
 	 */
 	if (up->ppsapi_lit)
-		switch(refclock_ppsrelate(pp, &up->atom, &reftime,
+		switch (refclock_ppsrelate(pp, &up->atom, &reftime,
 					  &rd_timestamp, pp->fudgetime1,
 					  &rd_fudge))
 		{
-		    case PPS_RELATE_EDGE:
+		case PPS_RELATE_EDGE:
 			up->ppsapi_gate = 0;
 			break;
-		    case PPS_RELATE_PHASE:
+		case PPS_RELATE_PHASE:
 			up->ppsapi_gate = 1;
 			break;
-		    default:
+		default:
 			break;
 		}
 	else 
@@ -1067,7 +1069,7 @@ nmea_poll(
 
 /*
  *
- *	gps_send(fd,cmd, peer)  Sends a command to the GPS receiver.
+ *	gps_send(fd,cmd, peer)	Sends a command to the GPS receiver.
  *	 as	gps_send(fd,"rqts,u\r", peer);
  *
  *	We don't currently send any data, but would like to send
@@ -1204,7 +1206,7 @@ nmea_day_unfold(
 
 	value = ((time_t)jd->hour * MINSPERHR
 		 + (time_t)jd->minute) * SECSPERMIN
-	          + (time_t)jd->second;
+		  + (time_t)jd->second;
 	pivot = time(NULL) - SECSPERDAY/2;
 
 	value = nmea_periodic_unfold(pivot, value, SECSPERDAY);
@@ -1240,9 +1242,9 @@ static void
 nmea_century_unfold(
 	struct calendar *jd)
 {
-	time_t     pivot_time;
+	time_t	   pivot_time;
 	struct tm *pivot_date;
-	time_t     pivot_year;
+	time_t	   pivot_year;
 
 	/* get warp limit and century start of pivot from system time */
 	pivot_time = time(NULL);

#### ChangeSet ####
2010-10-23 02:24:08+02:00, jnperlin at hydra.localnet 
  final update for [Bug 1571] and [Bug 1572]

==== ChangeLog ====
2010-10-23 02:24:08+02:00, jnperlin at hydra.localnet +5 -0
  [Bug 1571] NMEA does not relate data to PPS edge
  [Bug 1572] NMEA time adjustment for GPZDG buggy

--- 1.658/ChangeLog	2010-10-22 03:46:01 -04:00
+++ 1.659/ChangeLog	2010-10-22 20:24:08 -04:00
@@ -1,4 +1,9 @@
 ---
+
+* [Bug 1571] NMEA does not relate data to PPS edge
+* [Bug 1572] NMEA time adjustment for GPZDG buggy
+
+---
 (4.2.6p3-RC5) 2010/10/22 Released by Harlan Stenn <stenn at ntp.org>
 
 * [Bug 1649] Require NMEA checksum if $GPRMC or previously seen.

==== ntpd/refclock_nmea.c ====
2010-10-23 02:24:08+02:00, jnperlin at hydra.localnet +0 -10
  removed tag for temporary version

--- 1.51/ntpd/refclock_nmea.c	2010-10-22 19:48:50 -04:00
+++ 1.52/ntpd/refclock_nmea.c	2010-10-22 20:24:08 -04:00
@@ -16,16 +16,6 @@
  *		hart at ntp.org, davehart at davehart.com
  */
 
-/*
-************************************************************************
-* MODIFIED FOR ENHANCED PPS PROCESSING AND SYNC TO ABSOLUTE TIME       *
-*                                                                      *
-* THIS IS AN INOFFICAL / UNPUBLISHED WORK; USE AT OWN RISK AND DO NOT  *
-* FILE ERRORS AGAINST ANY NTPD VERSION THAT USES IT!                   *
-************************************************************************
-*/
-const char NMEA_DISCLAIMER[] = "refclock_nmea: inofficial version -- no support";
-
 #ifdef HAVE_CONFIG_H
 #include <config.h>
 #endif

#### ChangeSet ####
2010-10-23 01:48:37+02:00, jnperlin at hydra.localnet 
  nmea calendar cleanup

==== ntpd/refclock_nmea.c ====
2010-10-23 01:48:37+02:00, jnperlin at hydra.localnet +16 -40
  calendar cleanup

--- 1.49/ntpd/refclock_nmea.c	2010-09-22 14:14:51 -04:00
+++ 1.49.1.1/ntpd/refclock_nmea.c	2010-10-22 19:48:37 -04:00
@@ -1126,13 +1126,10 @@ nmea_checksum_ok(
  */
 /*
  * Do a periodic unfolding of a truncated value around a given pivot
- * value. The code will augment the given value with the pivot in such
- * manner that the absolute difference between the pivot value and the
- * result value will be less than or equal to half a period.
- *
- * This will only work for strictly positive periods; the code does
- * *not* check against such a flagrant misuse. The result is undefined
- * for negative periods.
+ * value.
+ * The result r will hold to pivot <= r < pivot+period (period>0) or
+ * pivot+period < r <= pivot (period < 0) and value % period == r % period,
+ * using floor division convention.
  */
 static time_t
 nmea_periodic_unfold(
@@ -1140,27 +1137,14 @@ nmea_periodic_unfold(
 	time_t value,
 	time_t period)
 {
-	time_t epoch_start, epoch_limit;
-
-	/* get warp limit and warp epoch start from pivot and period */ 
-	epoch_start = pivot + period / 2;
-	epoch_limit = epoch_start % period;
-	if (epoch_limit < 0) {
-		epoch_limit += period;
-		epoch_start -= period;
-	}
-	epoch_start -= epoch_limit;
-
-	/* normalise value and unfold into epoch */
-	value %= period;
-	if (value < 0)
+	/*
+	 * This will only work as long as 'value - pivot%period' does
+	 * not create a signed overflow condition.
+	 */
+	value = (value - (pivot % period)) % period;
+	if (value && (value ^ period) < 0)
 		value += period;
-	if (value >= epoch_limit)
-		value -= period;
-	value += epoch_start;
-
-	/* that's all folks! */
-	return value;
+	return pivot + value;
 }
 
 /*
@@ -1181,14 +1165,15 @@ static void
 nmea_day_unfold(
 	struct calendar *jd)
 {
-	time_t value;
+	time_t value, pivot;
 	struct tm *tdate;
 
 	value = ((time_t)jd->hour * MINSPERHR
 		 + (time_t)jd->minute) * SECSPERMIN
-	          + (time_t)jd->second;	
+	          + (time_t)jd->second;
+	pivot = time(NULL) - SECSPERDAY/2;
 
-	value = nmea_periodic_unfold(time(NULL), value, SECSPERDAY);
+	value = nmea_periodic_unfold(pivot, value, SECSPERDAY);
 	tdate = gmtime(&value);
 	if (tdate) {
 		jd->year     = tdate->tm_year + 1900;
@@ -1221,14 +1206,6 @@ static void
 nmea_century_unfold(
 	struct calendar *jd)
 {
-#if 0
-	/* assume that until AD2070 somebody has changed this... */
-	jd->year %= 100;
-	if (jd->year > 70)
-		jd->year += 1900;
-	else
-		jd->year += 2000
-#else
 	time_t     pivot_time;
 	struct tm *pivot_date;
 	time_t     pivot_year;
@@ -1236,9 +1213,8 @@ nmea_century_unfold(
 	/* get warp limit and century start of pivot from system time */
 	pivot_time = time(NULL);
 	pivot_date = gmtime(&pivot_time);
-	pivot_year = pivot_date->tm_year + 1900 + 30;
+	pivot_year = pivot_date->tm_year + 1900 - 20;
 	jd->year = nmea_periodic_unfold(pivot_year, jd->year, 100);
-#endif
 }
 
 #else

#### ChangeSet ####
2010-09-22 20:14:51+02:00, jnperlin at hydra.localnet 
  [Bug 1571][Bug 1572] first clean-running version

==== ntpd/refclock_nmea.c ====
2010-09-22 20:14:51+02:00, jnperlin at hydra.localnet +42 -27
  some more cleanup

--- 1.48/ntpd/refclock_nmea.c	2010-06-08 17:35:48 -04:00
+++ 1.49/ntpd/refclock_nmea.c	2010-09-22 14:14:51 -04:00
@@ -15,6 +15,17 @@
  *		Dave Hart July 1, 2009
  *		hart at ntp.org, davehart at davehart.com
  */
+
+/*
+************************************************************************
+* MODIFIED FOR ENHANCED PPS PROCESSING AND SYNC TO ABSOLUTE TIME       *
+*                                                                      *
+* THIS IS AN INOFFICAL / UNPUBLISHED WORK; USE AT OWN RISK AND DO NOT  *
+* FILE ERRORS AGAINST ANY NTPD VERSION THAT USES IT!                   *
+************************************************************************
+*/
+const char NMEA_DISCLAIMER[] = "refclock_nmea: inofficial version -- no support";
+
 #ifdef HAVE_CONFIG_H
 #include <config.h>
 #endif
@@ -34,7 +45,7 @@
 
 #ifdef HAVE_PPSAPI
 # include "ppsapi_timepps.h"
-#include "refclock_atom.h"
+# include "refclock_atom.h"
 #endif /* HAVE_PPSAPI */
 
 #ifdef SYS_WINNT
@@ -43,6 +54,15 @@ extern int async_write(int, const void *
 #define write(fd, data, octets)	async_write(fd, data, octets)
 #endif
 
+#ifndef TIMESPECTOTS
+#define TIMESPECTOTS(ptspec, pts)					\
+        do {								\
+                DTOLFP((ptspec)->tv_nsec * 1.0e-9, pts);		\
+                (pts)->l_ui += (u_int32)((ptspec)->tv_sec) + JAN_1970;  \
+        } while (0)
+#endif
+
+
 /*
  * This driver supports NMEA-compatible GPS receivers
  *
@@ -447,15 +467,6 @@ nmea_timer(
 #endif	/* HAVE_PPSAPI */
 
 #ifdef HAVE_PPSAPI
-
-#ifndef TIMESPECTOTS
-#define TIMESPECTOTS(ptspec, pts)					\
-        do {								\
-                DTOLFP((ptspec)->tv_nsec / 1e9, pts);			\
-                (pts)->l_ui += (u_int32)((ptspec)->tv_sec) + JAN_1970;  \
-        } while (0)
-#endif
-
 /*
  * This function is used to correlate a receive time stamp and a
  * reference time with a PPS edge time stamp. It applies the necessary
@@ -905,10 +916,15 @@ nmea_receive(
 	}
 
 	/*
-	 * Process the new sample in the median filter and determine the
-	 * timecode timestamp, but only if the PPS is not in control.
+	 * Get the reference time stamp from the calendar buffer.
+	 * Process the new sample in the median filter and determine
+	 * the timecode timestamp, but only if the PPS is not in
+	 * control.
 	 */
 	rd_fudge = pp->fudgetime2;
+	date.yearday = 0; /* make sure it's not used */
+	DTOLFP(pp->nsec * 1.0e-9, &reftime);
+	reftime.l_ui += caltontp(&date);
 
 	/* $GPZDG postprocessing first... */
 	if (cmdtypezdg) {
@@ -922,23 +938,13 @@ nmea_receive(
 				refnumtoa(&peer->srcadr));
 		}
 		/*
-		 * $GPZDG uses GPS/TAI, and it indicates the second
-		 * after the *next* PPS pulse. Instead of butchering
-		 * the received reference timestamp, which is a
-		 * nuisance, we use the fudge-time to get the
-		 * necessary offset of -1 second.
+		 * $GPZDG indicates the second after the *next* PPS
+		 * pulse. So we remove 1 second from the reference
+		 * time now.
 		 */
-		if (rd_fudge >= 0.0)
-			rd_fudge -= 1.0; /* one second early */
+		reftime.l_ui--;
 	}
 
-	/*
-	 * get the reference time stamp from the calendar buffer
-	 */
-	date.yearday = 0; /* make sure it's not used */
-	DTOLFP(pp->nsec * 1.0e-9, &reftime);
-	reftime.l_ui += caltontp(&date);
-
 #ifdef HAVE_PPSAPI
 	up->tcount++;
 	/*
@@ -964,8 +970,8 @@ nmea_receive(
 
 	if (up->ppsapi_gate && (peer->flags & FLAG_PPS))
 		return;
-
 #endif /* HAVE_PPSAPI */
+
 	refclock_process_offset(pp, reftime, rd_timestamp, rd_fudge);
 }
 
@@ -1215,6 +1221,14 @@ static void
 nmea_century_unfold(
 	struct calendar *jd)
 {
+#if 0
+	/* assume that until AD2070 somebody has changed this... */
+	jd->year %= 100;
+	if (jd->year > 70)
+		jd->year += 1900;
+	else
+		jd->year += 2000
+#else
 	time_t     pivot_time;
 	struct tm *pivot_date;
 	time_t     pivot_year;
@@ -1224,6 +1238,7 @@ nmea_century_unfold(
 	pivot_date = gmtime(&pivot_time);
 	pivot_year = pivot_date->tm_year + 1900 + 30;
 	jd->year = nmea_periodic_unfold(pivot_year, jd->year, 100);
+#endif
 }
 
 #else

==== ntpd/refclock_nmea.c ====
2010-06-08 23:35:48+02:00, jnperlin at hydra.localnet +310 -70
  [Bug 1571][Bug 1572] first clean-running version

--- 1.47/ntpd/refclock_nmea.c	2010-04-30 04:53:58 -04:00
+++ 1.48/ntpd/refclock_nmea.c	2010-06-08 17:35:48 -04:00
@@ -30,6 +30,7 @@
 #include "ntp_unixtime.h"
 #include "ntp_refclock.h"
 #include "ntp_stdlib.h"
+#include "ntp_calendar.h"
 
 #ifdef HAVE_PPSAPI
 # include "ppsapi_timepps.h"
@@ -97,8 +98,6 @@ extern int async_write(int, const void *
 #define	PPS_PRECISION	(-20)	/* precision assumed (about 1 us) */
 #define	REFID		"GPS\0"	/* reference id */
 #define	DESCRIPTION	"NMEA GPS Clock" /* who we are */
-#define NANOSECOND	1000000000 /* one second (ns) */
-#define RANGEGATE	500000	/* range gate (ns) */
 #ifndef O_NOCTTY
 #define M_NOCTTY	0
 #else
@@ -120,6 +119,7 @@ struct nmeaunit {
 	int	ppsapi_tried;	/* attempt PPSAPI once */
 	int	ppsapi_lit;	/* time_pps_create() worked */
 	int	ppsapi_fd;	/* fd used with PPSAPI */
+	int     ppsapi_gate;	/* allow edge detection processing */
 	int	tcount;		/* timecode sample counter */
 	int	pcount;		/* PPS sample counter */
 #endif /* HAVE_PPSAPI */
@@ -147,6 +147,8 @@ static  void	nmea_timer	(int, struct pee
 static	void	gps_send	(int, const char *, struct peer *);
 static	char *	field_parse	(char *, int);
 static	int	nmea_checksum_ok(const char *);
+static void nmea_day_unfold(struct calendar*);
+static void nmea_century_unfold(struct calendar*);
 
 /*
  * Transfer vector
@@ -404,6 +406,8 @@ nmea_control(
 	if (refclock_ppsapi(pps_fd, &up->atom)) {
 		up->ppsapi_lit = 1;
 		up->ppsapi_fd = pps_fd;
+		/* prepare to use the PPS API for our own purposes now. */
+		refclock_params(pp->sloppyclockflag, &up->atom);
 		return;
 	}
 
@@ -433,7 +437,7 @@ nmea_timer(
 	pp = peer->procptr;
 	up = (struct nmeaunit *)pp->unitptr;
 
-	if (up->ppsapi_lit &&
+	if (up->ppsapi_lit && up->ppsapi_gate &&
 	    refclock_pps(peer, &up->atom, pp->sloppyclockflag) > 0) {
 		up->pcount++,
 		peer->flags |= FLAG_PPS;
@@ -442,6 +446,123 @@ nmea_timer(
 }
 #endif	/* HAVE_PPSAPI */
 
+#ifdef HAVE_PPSAPI
+
+#ifndef TIMESPECTOTS
+#define TIMESPECTOTS(ptspec, pts)					\
+        do {								\
+                DTOLFP((ptspec)->tv_nsec / 1e9, pts);			\
+                (pts)->l_ui += (u_int32)((ptspec)->tv_sec) + JAN_1970;  \
+        } while (0)
+#endif
+
+/*
+ * This function is used to correlate a receive time stamp and a
+ * reference time with a PPS edge time stamp. It applies the necessary
+ * fudges (fudge1 for PPS, fudge2 for receive time) and then tries to
+ * move the receive time stamp to the corresponding edge. This can
+ * warp into future, if a transmission delay of more than 500ms is not
+ * compensated with a corresponding fudge time2 value, because then
+ * the next PPS edge is nearer than the last. (Similiar to what the
+ * PPS ATOM driver does, but we deal with full time stamps here, not
+ * just phase shift information.) Likewise, a negative fudge time2
+ * value must be used if the reference time stamp correlates with the
+ * *following* PPS pulse.
+ *
+ * Note that the receive time fudge value only needs to move the receive
+ * stamp near a PPS edge but that close proximity is not required;
+ * +/-100ms precision should be enough. But since the fudge value will
+ * probably also be used to compensate the transmission delay when no PPS
+ * edge can be related to the time stamp, it's best to get it as close
+ * as possible.
+ *
+ * It should also be noted that the typical use case is matching to
+ * the preceeding edge, as most units relate their sentences to the
+ * current second.
+ *
+ * The function returns PPS_RELATE_NONE (0) if no PPS edge correlation
+ * can be fixed; PPS_RELATE_EDGE (1) when a PPS edge could be fixed, but
+ * the distance to the reference time stamp is too big (exceeds +/-400ms)
+ * and the ATOM driver PLL cannot be used to fix the phase; and
+ * PPS_RELATE_PHASE (2) when the ATOM driver PLL code can be used.
+ *
+ * On output, the receive time stamp is replaced with the
+ * corresponding PPS edge time if a fix could be made; the PPS fudge
+ * is updated to reflect the proper fudge time to apply. (This implies
+ * that 'refclock_process_f()' must be used!)
+ */
+#define PPS_RELATE_NONE  0	/* no pps correlation possible    */
+#define PPS_RELATE_EDGE  1	/* recv time fixed, no phase lock */
+#define PPS_RELATE_PHASE 2	/* recv time fixed, phase lock ok */
+
+static int
+refclock_ppsrelate(
+	const struct refclockproc  *pp      ,	/* for sanity     */
+	const struct refclock_atom *ap      ,	/* for PPS io     */
+	const l_fp                 *reftime ,
+	l_fp                       *rd_stamp,	/* i/o read stamp */
+	double                      pp_fudge,	/* pps fudge      */
+	double                     *rd_fudge)	/* i/o read fudge */
+{
+	pps_info_t      pps_info;
+	struct timespec timeout;
+	l_fp            pp_stamp, pp_delta;
+	double          delta, idelta;
+
+	if (pp->leap == LEAP_NOTINSYNC)
+		return PPS_RELATE_NONE;	/* clock is insane, no chance */
+	
+	memset(&timeout, 0, sizeof(timeout));
+	memset(&pps_info, 0, sizeof(pps_info_t));
+
+	if (time_pps_fetch(ap->handle, PPS_TSFMT_TSPEC,
+			   &pps_info, &timeout) < 0)
+		return PPS_RELATE_NONE;
+
+	/* get last active PPS edge before receive */
+	if (ap->pps_params.mode & PPS_CAPTUREASSERT)
+		timeout = pps_info.assert_timestamp;
+	else if (ap->pps_params.mode & PPS_CAPTURECLEAR)
+		timeout = pps_info.clear_timestamp;
+	else
+		return PPS_RELATE_NONE;
+
+	/* get delta between receive time and PPS time */
+	TIMESPECTOTS(&timeout, &pp_stamp);
+	pp_delta = *rd_stamp;
+	L_SUB(&pp_delta, &pp_stamp);
+	LFPTOD(&pp_delta, delta);
+	delta += pp_fudge - *rd_fudge;
+	if (fabs(delta) > 1.5)
+		return PPS_RELATE_NONE; /* PPS timeout control */
+	
+	/* eventually warp edges, check phase */
+	idelta    = floor(delta + 0.5);
+	pp_fudge -= idelta;
+	delta    -= idelta;
+	if (fabs(delta) > 0.45)
+		return PPS_RELATE_NONE; /* dead band control */
+
+	/* we actually have a PPS edge to relate with! */
+	*rd_stamp = pp_stamp;
+	*rd_fudge = pp_fudge;
+
+	/* if whole system out-of-sync, do not try to PLL */
+	if (sys_leap == LEAP_NOTINSYNC)
+		return PPS_RELATE_EDGE;	/* cannot PLL with atom code */
+
+	/* check against reftime if ATOM PLL can be used */
+	pp_delta = *reftime;
+	L_SUB(&pp_delta, &pp_stamp);
+	LFPTOD(&pp_delta, delta);
+	delta += pp_fudge;
+	if (fabs(delta) > 0.45)
+		return PPS_RELATE_EDGE;	/* cannot PLL with atom code */
+
+	/* all checks passed, gets an AAA rating here! */
+	return PPS_RELATE_PHASE; /* can PLL with atom code */
+}
+#endif	/* HAVE_PPSAPI */
 
 /*
  * nmea_receive - receive data from the serial interface
@@ -454,14 +575,15 @@ nmea_receive(
 	register struct nmeaunit *up;
 	struct refclockproc *pp;
 	struct peer *peer;
-	int month, day;
 	char *cp, *dp, *msg;
 	int cmdtype;
 	int cmdtypezdg = 0;
 	/* Use these variables to hold data until we decide its worth keeping */
 	char	rd_lastcode[BMAX];
-	l_fp	rd_timestamp;
+	l_fp	rd_timestamp, reftime;
 	int	rd_lencode;
+	double  rd_fudge;
+	struct calendar date;
 
 	/*
 	 * Initialize pointers and read the timecode and timestamp
@@ -573,6 +695,7 @@ nmea_receive(
 	DPRINTF(1, ("nmea: timecode %d %s\n", pp->lencode, pp->a_lastcode));
 
 	/* Grab field depending on clock string type */
+	memset(&date, 0, sizeof(date));
 	switch (cmdtype) {
 
 	case GPRMC:
@@ -657,9 +780,9 @@ nmea_receive(
 	/*
 	 * Convert time and check values.
 	 */
-	pp->hour = ((dp[0] - '0') * 10) + dp[1] - '0';
-	pp->minute = ((dp[2] - '0') * 10) + dp[3] -  '0';
-	pp->second = ((dp[4] - '0') * 10) + dp[5] - '0';
+	date.hour = ((dp[0] - '0') * 10) + dp[1] - '0';
+	date.minute = ((dp[2] - '0') * 10) + dp[3] -  '0';
+	date.second = ((dp[4] - '0') * 10) + dp[5] - '0';
 	/* 
 	 * Default to 0 milliseconds, if decimal convert milliseconds in
 	 * one, two or three digits
@@ -677,25 +800,8 @@ nmea_receive(
 		}
 	}
 
-	/*
-	 * Manipulating GPS timestamp in GPZDG as the seconds field
-	 * is valid for next PPS tick. Just rolling back the second,
-	 * minute and hour fields appopriately
-	 */
-	if (cmdtypezdg) {
-		if (pp->second == 0) {
-			pp->second = 59;
-			if (pp->minute == 0) {
-				pp->minute = 59;
-				if (pp->hour == 0)
-					pp->hour = 23;
-			}
-		} else
-			pp->second -= 1;
-	}
-
-	if (pp->hour > 23 || pp->minute > 59 || 
-	    pp->second > 59 || pp->nsec > 1000000000) {
+	if (date.hour > 23 || date.minute > 59 || 
+	    date.second > 59 || pp->nsec > 1000000000) {
 
 		DPRINTF(1, ("NMEA hour/min/sec/nsec range %02d:%02d:%02d.%09ld\n",
 			    pp->hour, pp->minute, pp->second, pp->nsec));
@@ -709,51 +815,29 @@ nmea_receive(
 	if (GPRMC == cmdtype) {
 
 		dp = field_parse(cp,9);
-		day = dp[0] - '0';
-		day = (day * 10) + dp[1] - '0';
-		month = dp[2] - '0';
-		month = (month * 10) + dp[3] - '0';
-		pp->year = dp[4] - '0';
-		pp->year = (pp->year * 10) + dp[5] - '0';
+		date.monthday = 10 * (dp[0] - '0') + (dp[1] - '0');
+		date.month    = 10 * (dp[2] - '0') + (dp[3] - '0');
+		date.year     = 10 * (dp[4] - '0') + (dp[5] - '0');
+		nmea_century_unfold(&date);
 
 	} else if (GPZDG_ZDA == cmdtype) {
 
 		dp = field_parse(cp, 2);
-		day = 10 * (dp[0] - '0') + (dp[1] - '0');
+		date.monthday = 10 * (dp[0] - '0') + (dp[1] - '0');
 		dp = field_parse(cp, 3);
-		month = 10 * (dp[0] - '0') + (dp[1] - '0');
+		date.month = 10 * (dp[0] - '0') + (dp[1] - '0');
 		dp = field_parse(cp, 4);
-		pp->year = /* 1000 * (dp[0] - '0') + 100 * (dp[1] - '0') + */ 10 * (dp[2] - '0') + (dp[3] - '0');
-
-	} else {
-		/* only time */
-		time_t tt = time(NULL);
-		struct tm * t = gmtime(&tt);
-		day = t->tm_mday;
-		month = t->tm_mon + 1;
-		pp->year= t->tm_year + 1900;
-	}
-
-	if (month < 1 || month > 12 || day < 1) {
-		refclock_report(peer, CEVNT_BADDATE);
-		return;
-	}
+		date.year = 1000 * (dp[0] - '0') + 100 * (dp[1] - '0')
+		          + 10 * (dp[2] - '0') + (dp[3] - '0');
 
-	/* pp->year will be 2 or 4 digits if read from GPS, 4 from gmtime */
-	if (pp->year < 100) {
-		if (pp->year < 9)	/* year of our line of code is 2009 */
-			pp->year += 2100;
-		else
-			pp->year += 2000;
-	}
+	} else
+		nmea_day_unfold(&date);
 
-	/* pp->year now 4 digits as ymd2yd requires */
-	day = ymd2yd(pp->year, month, day);
-	if (-1 == day) {
+	if (date.month < 1 || date.month > 12 ||
+	    date.monthday < 1 || date.monthday > 31) {
 		refclock_report(peer, CEVNT_BADDATE);
 		return;
 	}
-	pp->day = day;
 
 	/*
 	 * If "fudge 127.127.20.__ flag4 1" is configured in ntp.conf,
@@ -821,26 +905,68 @@ nmea_receive(
 	}
 
 	/*
-	 * Note if we're only using GPS timescale from now on.
+	 * Process the new sample in the median filter and determine the
+	 * timecode timestamp, but only if the PPS is not in control.
 	 */
-	if (cmdtypezdg && !up->gps_time) {
-		up->gps_time = 1;
-		NLOG(NLOG_CLOCKINFO)
+	rd_fudge = pp->fudgetime2;
+
+	/* $GPZDG postprocessing first... */
+	if (cmdtypezdg) {
+		/*
+		 * Note if we're only using GPS timescale from now on.
+		 */
+		if (!up->gps_time) {
+			up->gps_time = 1;
+			NLOG(NLOG_CLOCKINFO)
 			msyslog(LOG_INFO, "%s using only $GPZDG",
 				refnumtoa(&peer->srcadr));
+		}
+		/*
+		 * $GPZDG uses GPS/TAI, and it indicates the second
+		 * after the *next* PPS pulse. Instead of butchering
+		 * the received reference timestamp, which is a
+		 * nuisance, we use the fudge-time to get the
+		 * necessary offset of -1 second.
+		 */
+		if (rd_fudge >= 0.0)
+			rd_fudge -= 1.0; /* one second early */
 	}
 
 	/*
-	 * Process the new sample in the median filter and determine the
-	 * timecode timestamp, but only if the PPS is not in control.
+	 * get the reference time stamp from the calendar buffer
 	 */
+	date.yearday = 0; /* make sure it's not used */
+	DTOLFP(pp->nsec * 1.0e-9, &reftime);
+	reftime.l_ui += caltontp(&date);
+
 #ifdef HAVE_PPSAPI
 	up->tcount++;
-	if (peer->flags & FLAG_PPS)
+	/*
+	 * If we have PPS running, we try to associate the sentence with the last
+	 * active edge of the PPS signal.
+	 */
+	if (up->ppsapi_lit)
+		switch(refclock_ppsrelate(pp, &up->atom, &reftime,
+					  &rd_timestamp, pp->fudgetime1,
+					  &rd_fudge))
+		{
+		    case PPS_RELATE_EDGE:
+			up->ppsapi_gate = 0;
+			break;
+		    case PPS_RELATE_PHASE:
+			up->ppsapi_gate = 1;
+			break;
+		    default:
+			break;
+		}
+	else 
+		up->ppsapi_gate = 0;
+
+	if (up->ppsapi_gate && (peer->flags & FLAG_PPS))
 		return;
+
 #endif /* HAVE_PPSAPI */
-	if (!refclock_process_f(pp, pp->fudgetime2))
-		refclock_report(peer, CEVNT_BADTIME);
+	refclock_process_offset(pp, reftime, rd_timestamp, rd_fudge);
 }
 
 
@@ -986,6 +1112,120 @@ nmea_checksum_ok(
 
 	return 1;
 }
+
+/*
+ * -------------------------------------------------------------------
+ * funny calendar-oriented stuff -- a bit hard to grok.
+ * -------------------------------------------------------------------
+ */
+/*
+ * Do a periodic unfolding of a truncated value around a given pivot
+ * value. The code will augment the given value with the pivot in such
+ * manner that the absolute difference between the pivot value and the
+ * result value will be less than or equal to half a period.
+ *
+ * This will only work for strictly positive periods; the code does
+ * *not* check against such a flagrant misuse. The result is undefined
+ * for negative periods.
+ */
+static time_t
+nmea_periodic_unfold(
+	time_t pivot,
+	time_t value,
+	time_t period)
+{
+	time_t epoch_start, epoch_limit;
+
+	/* get warp limit and warp epoch start from pivot and period */ 
+	epoch_start = pivot + period / 2;
+	epoch_limit = epoch_start % period;
+	if (epoch_limit < 0) {
+		epoch_limit += period;
+		epoch_start -= period;
+	}
+	epoch_start -= epoch_limit;
+
+	/* normalise value and unfold into epoch */
+	value %= period;
+	if (value < 0)
+		value += period;
+	if (value >= epoch_limit)
+		value -= period;
+	value += epoch_start;
+
+	/* that's all folks! */
+	return value;
+}
+
+/*
+ * Unfold a time-of-day (seconds since midnight) around the current
+ * system time in a manner that guarantees an absolute difference of
+ * less than 12hrs.
+ *
+ * This function is used for NMEA sentences that contain no date
+ * information. This requires the system clock to be in +/-12hrs
+ * around the true time, or the clock will synchronize the system 1day
+ * off if not augmented with a time sources that also provide the
+ * necessary date information.
+ *
+ * The function updates the refclockproc structure is also uses as
+ * input to fetch the time from.
+ */
+static void
+nmea_day_unfold(
+	struct calendar *jd)
+{
+	time_t value;
+	struct tm *tdate;
+
+	value = ((time_t)jd->hour * MINSPERHR
+		 + (time_t)jd->minute) * SECSPERMIN
+	          + (time_t)jd->second;	
+
+	value = nmea_periodic_unfold(time(NULL), value, SECSPERDAY);
+	tdate = gmtime(&value);
+	if (tdate) {
+		jd->year     = tdate->tm_year + 1900;
+		jd->yearday  = tdate->tm_yday + 1;
+		jd->monthday = tdate->tm_mon + 1;
+		jd->monthday = tdate->tm_mday;
+		jd->hour     = tdate->tm_hour;
+		jd->minute   = tdate->tm_min;
+		jd->second   = tdate->tm_sec;
+	} else {
+		jd->year     = 0;
+		jd->yearday  = 0;
+		jd->month    = 0;
+		jd->monthday = 0;
+	}
+}
+
+/*
+ * Unfold a 2-digit year into full year spec around the current year
+ * of the system time. This requires the system clock to be in -79/+19
+ * years around the true time, or the result will be off by
+ * 100years. The assymetric behaviour was chosen to enable inital sync
+ * for systems that do not have a battery-backup-clock and start with
+ * a date that is typically years in the past.
+ *
+ * The function updates the calendar structure that is also used as
+ * input to fetch the year from.
+ */
+static void
+nmea_century_unfold(
+	struct calendar *jd)
+{
+	time_t     pivot_time;
+	struct tm *pivot_date;
+	time_t     pivot_year;
+
+	/* get warp limit and century start of pivot from system time */
+	pivot_time = time(NULL);
+	pivot_date = gmtime(&pivot_time);
+	pivot_year = pivot_date->tm_year + 1900 + 30;
+	jd->year = nmea_periodic_unfold(pivot_year, jd->year, 100);
+}
+
 #else
 int refclock_nmea_bs;
 #endif /* REFCLOCK && CLOCK_NMEA */


More information about the bk-ntp-stable-send mailing list