I have it working under FreeBSD w/ a custom ntp refclock.  It does
not work with the hpgps refclock.  PTIME:TCODE is not on-time.
The 1-PPS output is a couple 100ms wide, so there is no need for a
PPS stretcher.  I'm using a soekris net4501 w/ the tmrin mod
that is documented on febo.com.  Attached is a patch
which should work on both linux and freebsd, but for
kernel pps support, you will need to apply one of the various
kernel patches... Older 2.4kernels are better supported.  FreeBSD
has it natively.

Here's a sample ntp.conf

server 127.127.45.0 prefer minpoll 4 maxpoll 4 iburst
fudge 127.127.45.0 time1 0.012 #115200
fudge 127.127.45.0 flag3 1
server 127.127.22.0 minpoll 4 maxpoll 4
tos mindist 0.050

driftfile /media/log/ntpd.drift

statsdir /media/log/
statistics loopstats peerstats clockstats
filegen loopstats file loopstats type day enable
filegen peerstats file peerstats type day enable
filegen clockstats file clockstats type day enable


sysctl.conf

machdep.elan_gpio_config=-----P...--..--------..---------


also I have to modify the sio driver in the kernel:
/sys/dev/sio/sio.c

diff -u sio.c.orig sio.c
--- sio.c.orig  2008-06-27 15:11:52.000000000 -0500
+++ sio.c       2008-10-04 10:32:57.000000000 -0500
@@ -1928,7 +1928,7 @@
         * (about 3 ticks if input flow control is not used or not honoured,
         * but a bit less for CS5-CS7 modes).
         */
-       cp4ticks = speed / 10 / hz * 4;
+       cp4ticks = speed / 10 / hz * 40;
        for (ibufsize = 128; ibufsize < cp4ticks;)
                ibufsize <<= 1;
        if (ibufsize == com->ibufsize) {





        Scott

Bruce Taylor wrote:
Folks,

  Has anyone gotten a Jackson Labs 'Fury' gps-do to work as a time/pps
source for Linux?

  Our lab is looking to use both the stable 10MHz clock for various
LOs on a radio-telescope, and also get reasonably tight timing for a
software correllator to use in discriminating pulsar signals.

  Our Linux guy has lost most of his hair out trying to get the NTP
daemon to receive the PPS signal and thus get NTP to see the GPS-DO as
a stratum 0 source.

  Our configuration is: vanilla Linux from kernel.org (version 2.6.23)
running on an intel platform.  We've applied the LinuxPPS kernel
patch, and we're feeding the serial port with the Fury in NMEA mode.
We made the required internal mod on the Fury to feed the PPS signal
out on the serial port, and can see it blinking using a scope.

  Apologies if my description is vague, as I'm just getting into the
fun and joy of kernel hacking :-)

  Many thanks for any advice,

  - Bruce Taylor

_______________________________________________
time-nuts mailing list -- [email protected]
To unsubscribe, go to https://www.febo.com/cgi-bin/mailman/listinfo/time-nuts
and follow the instructions there.


--- ntp-4.2.4p4.orig/configure.ac	2006-12-28 06:01:44.000000000 -0600
+++ ntp-4.2.4p4/configure.ac	2008-07-06 17:33:28.000000000 -0500
@@ -2405,6 +2405,16 @@
 fi
 AC_MSG_RESULT($ntp_ok)
 
+AC_MSG_CHECKING(Fury GPS)
+AC_ARG_ENABLE(FURY,
+    AC_HELP_STRING([--enable-FURY], [+ Fury GPS]),
+    [ntp_ok=$enableval], [ntp_ok=$ntp_eac])
+if test "$ntp_ok" = "yes"; then
+    ntp_refclock=yes
+    AC_DEFINE(CLOCK_FURY, 1, [Fury GPS Receiver?])
+fi
+AC_MSG_RESULT($ntp_ok)
+
 # Requires modem control
 AC_MSG_CHECKING(Heath GC-1000 WWV/WWVH receiver)
 AC_ARG_ENABLE(HEATH,
--- ntp-4.2.4p4.orig/include/ntp.h	2006-12-28 06:03:04.000000000 -0600
+++ ntp-4.2.4p4/include/ntp.h	2008-07-06 17:33:28.000000000 -0500
@@ -501,7 +501,8 @@
 #define REFCLK_ZYFER		42	/* Zyfer GPStarplus receiver  */
 #define REFCLK_RIPENCC		43	/* RIPE NCC Trimble driver */
 #define REFCLK_NEOCLOCK4X	44	/* NeoClock4X DCF77 or TDF receiver */
-#define REFCLK_MAX		44	/* NeoClock4X DCF77 or TDF receiver */
+#define REFCLK_FURY		45	/* Fury GPS receiver */
+#define REFCLK_MAX		45	/* Fury GPS receiver */
 
  /*
  * Macro for sockaddr_storage structures operations
--- ntp-4.2.4p4.orig/libntp/clocktypes.c	2006-06-06 15:16:26.000000000 -0500
+++ ntp-4.2.4p4/libntp/clocktypes.c	2008-07-06 17:33:28.000000000 -0500
@@ -100,6 +100,8 @@
 	  "GPS_RIPENCC" },
 	{ REFCLK_NEOCLOCK4X,	"NeoClock4X DCF77 / TDF receiver (44)",
 	  "NEOCLK4X"},
+	{ REFCLK_FURY,	        "Fury GPS receiver (45)",
+	  "GPS_FURY"},
 	{ -1,			"", "" }
 };
 
--- ntp-4.2.4p4.orig/ntpd/Makefile.am	2007-04-14 06:06:59.000000000 -0500
+++ ntp-4.2.4p4/ntpd/Makefile.am	2008-07-06 17:33:28.000000000 -0500
@@ -59,7 +59,7 @@
 	refclock_fg.c refclock_gpsvme.c refclock_heath.c refclock_hopfser.c \
 	refclock_hopfpci.c refclock_hpgps.c refclock_irig.c refclock_jjy.c \
 	refclock_jupiter.c refclock_leitch.c refclock_local.c \
-	refclock_mx4200.c refclock_neoclock4x.c \
+	refclock_mx4200.c refclock_neoclock4x.c refclock_fury.c \
 	refclock_nmea.c refclock_oncore.c refclock_palisade.c \
 	refclock_palisade.h refclock_parse.c \
 	refclock_pcf.c refclock_pst.c refclock_ripencc.c refclock_shm.c \
--- ntp-4.2.4p4.orig/ntpd/ntp_control.c	2006-12-28 06:03:27.000000000 -0600
+++ ntp-4.2.4p4/ntpd/ntp_control.c	2008-07-06 17:33:28.000000000 -0500
@@ -406,6 +406,7 @@
 	CTL_SST_TS_UHF,		/* REFCLK_ZYFER (42) */
 	CTL_SST_TS_UHF,		/* REFCLK_RIPENCC (43) */
 	CTL_SST_TS_UHF,		/* REFCLK_NEOCLOCK4X (44) */
+	CTL_SST_TS_UHF,		/* REFCLK_FURY (45) */
 };
 
 
--- ntp-4.2.4p4.orig/ntpd/refclock_conf.c	2006-12-28 06:03:44.000000000 -0600
+++ ntp-4.2.4p4/ntpd/refclock_conf.c	2008-07-06 17:33:28.000000000 -0500
@@ -258,6 +258,12 @@
 #define	refclock_neoclock4x	refclock_none
 #endif
 
+#ifdef CLOCK_FURY
+extern	struct refclock	refclock_fury;
+#else
+#define	refclock_fury	refclock_none
+#endif
+
 /*
  * Order is clock_start(), clock_shutdown(), clock_poll(),
  * clock_control(), clock_init(), clock_buginfo, clock_flags;
@@ -309,7 +315,8 @@
 	&refclock_tt560,	/* 41 REFCLK_TT560 */
 	&refclock_zyfer,	/* 42 REFCLK_ZYFER */
 	&refclock_ripencc,	/* 43 REFCLK_RIPENCC */
-	&refclock_neoclock4x    /* 44 REFCLK_NEOCLOCK4X */
+	&refclock_neoclock4x,   /* 44 REFCLK_NEOCLOCK4X */
+	&refclock_fury          /* 45 REFCLK_FURY */
 };
 
 u_char num_refclock_conf = sizeof(refclock_conf)/sizeof(struct refclock *);
--- ntp-4.2.4p4.orig/ntpd/refclock_fury.c	1969-12-31 18:00:00.000000000 -0600
+++ ntp-4.2.4p4/ntpd/refclock_fury.c	2008-08-23 20:46:08.000000000 -0500
@@ -0,0 +1,603 @@
+/*
+ * refclock_fury.c - clock driver for an FURY GPS CLOCK
+ *		Scott Mace 6/20/2008
+ *		 based on refclock_nmea.c
+ */
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#if defined(SYS_WINNT)
+#undef close
+#define close closesocket
+#endif
+
+#if defined(REFCLOCK) && defined(CLOCK_FURY)
+
+
+#include <stdio.h>
+#include <ctype.h>
+
+#include "ntpd.h"
+#include "ntp_io.h"
+#include "ntp_unixtime.h"
+#include "ntp_refclock.h"
+#include "ntp_stdlib.h"
+
+/*
+ * This driver supports the FURY GPS Receiver with
+ *
+ * Based on refclock_nmea.c, some code from reflock_hpgps.c
+ *
+ * The Fury supports a partial SCPI command set, which is useful
+ * for gather various health and performance stats
+ * The only on-time marker is the NMEA GPGGA sentence that is generated
+ * once per second when the Fury is placed in NMEA mode
+ *
+ * Other interesting data is collected from GPS?,SYNC?,DIAG?,and MEAS?
+ *
+ */
+
+/*
+ * Definitions
+ */
+#ifdef SYS_WINNT
+# define DEVICE "COM%d:" 	/* COM 1 - 3 supported */
+#else
+# define DEVICE	"/dev/gps%d"	/* name of radio device */
+#endif
+#define	SPEED232	B115200	/* uart speed (115200 bps) */
+#define	PRECISION	(-9)	/* precision assumed (about 2 ms) */
+#define	PPS_PRECISION	(-20)	/* precision assumed (about 1 us) */
+#define	REFID		"GPS\0"	/* reference id */
+#define	DESCRIPTION	"FURY GPS Clock" /* who we are */
+#define NANOSECOND	1000000000 /* one second (ns) */
+#define RANGEGATE	500000	/* range gate (ns) */
+
+#define LENNMEA		75	/* min timecode length */
+
+/*
+ * Tables to compute the ddd of year form icky dd/mm timecode. Viva la
+ * leap.
+ */
+static int day1tab[] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
+static int day2tab[] = {31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
+
+/*
+ * Unit control structure
+ */
+struct furyunit {
+	int	pollcnt;	/* poll message counter */
+	int	polled;		/* Hand in a sample? */
+	l_fp	tstamp;		/* timestamp of last poll */
+	int	tscnt;
+	float	stat_efc;
+	unsigned long	stat_life;
+	int	stat_ppslock;
+	unsigned long	stat_holddur;
+	int	stat_holdover;
+	float	stat_fee;
+	float	stat_tint;
+	float	stat_temp;
+	float	stat_amp;
+	float	stat_volt;	
+	int	stat_track;
+	int	stat_vis;
+	int	stat_pulsestat;
+	int	stat_pulseacc;
+	int	stat_pulsesaw;
+	int	stat_leap;
+};
+
+/*
+ * Function prototypes
+ */
+static	int	fury_start	P((int, struct peer *));
+static	void	fury_shutdown	P((int, struct peer *));
+static	void	fury_receive	P((struct recvbuf *));
+static	void	fury_poll	P((int, struct peer *));
+static	void	gps_send	P((int, const char *, struct peer *));
+static	char	*field_parse	P((char *, int));
+
+/*
+ * Transfer vector
+ */
+struct	refclock refclock_fury = {
+	fury_start,		/* start up driver */
+	fury_shutdown,	/* shut down driver */
+	fury_poll,		/* transmit poll message */
+	noentry,		/* fudge control */
+	noentry,		/* initialize driver */
+	noentry,		/* buginfo */
+	NOFLAGS			/* not used */
+};
+
+/*
+ * fury_start - open the GPS devices and initialize data for processing
+ */
+static int
+fury_start(
+	int unit,
+	struct peer *peer
+	)
+{
+	register struct furyunit *up;
+	struct refclockproc *pp;
+	int fd;
+	char device[20];
+
+	/*
+	 * Open serial port. Use CLK line discipline, if available.
+	 */
+	(void)sprintf(device, DEVICE, unit);
+
+	fd = refclock_open(device, SPEED232, LDISC_CLK);
+	if (fd <= 0) {
+            return (0);
+        }
+
+	/*
+	 * Allocate and initialize unit structure
+	 */
+	up = (struct furyunit *)emalloc(sizeof(struct furyunit));
+	if (up == NULL) {
+	    (void) close(fd);
+	    return (0);
+	}
+	memset((char *)up, 0, sizeof(struct furyunit));
+	pp = peer->procptr;
+	pp->io.clock_recv = fury_receive;
+	pp->io.srcclock = (caddr_t)peer;
+	pp->io.datalen = 0;
+	pp->io.fd = fd;
+	if (!io_addclock(&pp->io)) {
+	    (void) close(fd);
+	    free(up);
+	    return (0);
+	}
+	pp->unitptr = (caddr_t)up;
+
+	/*
+	 * Initialize miscellaneous variables
+	 */
+	peer->precision = PRECISION;
+	pp->clockdesc = DESCRIPTION;
+	memcpy((char *)&pp->refid, REFID, 4);
+	up->pollcnt = 2;
+	up->tscnt=0;
+
+	/* turn off command echo */
+	gps_send(pp->io.fd,"SYST:COMM:SER:ECHO OFF\r", peer);
+
+	/* turn off prompt */
+	gps_send(pp->io.fd,"SYST:COMM:SER:PRO OFF\r", peer);
+
+	/* query the receiver ID */
+	gps_send(pp->io.fd,"*IDN?\r", peer);
+
+	/* place the fury in NMEA mode */
+	gps_send(pp->io.fd,"GPS:GPGGA 1\r", peer);
+
+	return (1);
+}
+
+/*
+ * fury_shutdown - shut down a GPS clock
+ */
+static void
+fury_shutdown(
+	int unit,
+	struct peer *peer
+	)
+{
+	register struct furyunit *up;
+	struct refclockproc *pp;
+
+	pp = peer->procptr;
+	up = (struct furyunit *)pp->unitptr;
+	io_closeclock(&pp->io);
+	free(up);
+}
+
+/*
+ * fury_receive - receive data from the serial interface
+ */
+static void
+fury_receive(
+	struct recvbuf *rbufp
+	)
+{
+	register struct furyunit *up;
+	struct refclockproc *pp;
+	struct peer *peer;
+	int month, day;
+	int i,m;
+	char *cp, *dp;
+	char *tcp;
+	/* Use these variables to hold data until we decide its worth keeping */
+	char	rd_lastcode[BMAX];
+	l_fp	rd_tmp;
+	u_short	rd_lencode;
+	static char logbuf[1024]; /* logging string buffer */
+
+
+	/*
+	 * Initialize pointers and read the timecode and timestamp
+	 */
+	peer = (struct peer *)rbufp->recv_srcclock;
+	pp = peer->procptr;
+	up = (struct furyunit *)pp->unitptr;
+	rd_lencode = (u_short)refclock_gtlin(rbufp, rd_lastcode, BMAX, &rd_tmp);
+
+	/*
+	 * There is a case that a <CR><LF> gives back a "blank" line
+	 */
+	if (rd_lencode == 0)
+	    return;
+
+#ifdef DEBUG
+	if (debug)
+	    printf("fury: gpsread %d %s\n", rd_lencode, rd_lastcode);
+#endif
+
+	pp->lencode = rd_lencode;
+	strcpy(pp->a_lastcode,rd_lastcode);
+	cp = pp->a_lastcode;
+
+	pp->lastrec = up->tstamp = rd_tmp;
+	up->pollcnt = 2;
+
+
+
+	/* clean off a leading "scpi > " if needed */
+        if (strrchr(pp->a_lastcode,'>')==0) {
+            tcp = cp;
+	} else {
+            tcp = cp+7;
+	}
+
+	/* do not process null lines after prompt stripping */
+	if (strlen(tcp)==0) {
+	    return;
+	}
+
+	/* handle command errors */
+	if (strstr(tcp,"Command Error")){
+#ifdef DEBUG
+	    if (debug)
+		printf("fury: error indicated in prompt: %s\n", tcp);
+#endif
+	    if (write(pp->io.fd, "*CLS\r\r", 6) != 6)
+		refclock_report(peer, CEVNT_FAULT);
+	}
+
+	if(strncmp(tcp,"$GPGGA",6)==0) {
+	    up->tscnt++;
+	    dp = field_parse(tcp,1);
+	} else if (strncmp(tcp,"EFControl Absolute:",19)==0) {
+	    m = sscanf(tcp,"EFControl Absolute: %f",&up->stat_efc);
+	    return;
+	} else if (strncmp(tcp,"Lifetime :",10)==0) {
+	    m = sscanf(tcp,"Lifetime : %lu",&up->stat_life);
+	    return;
+	} else if (strncmp(tcp,"1PPS LOCK STATUS  :",19)==0) {
+	    m = sscanf(tcp,"1PPS LOCK STATUS  : %d",&up->stat_ppslock);
+	    return;
+	} else if (strncmp(tcp,"LAST HOLDOVER DURATION",22)==0) {
+	    m = sscanf(tcp,"LAST HOLDOVER DURATION %lu,%d",
+		&up->stat_holddur,&up->stat_holdover);
+	    return;
+	} else if (strncmp(tcp,"FREQ ERROR ESTIMATE",19)==0) {
+	    m = sscanf(tcp,"FREQ ERROR ESTIMATE %f",&up->stat_fee);
+	    return;
+	} else if (strncmp(tcp,"TIME INTERVAL DIFFERENCE",24)==0) {
+	    m = sscanf(tcp,"TIME INTERVAL DIFFERENCE %f",&up->stat_tint);
+	    return;
+	} else if (strncmp(tcp,"OCXO Temperature:",16)==0) {
+	    m = sscanf(tcp,"OCXO Temperature: %f",&up->stat_temp);
+	    return;
+	} else if (strncmp(tcp,"OCXO Current:",13)==0) {
+	    m = sscanf(tcp,"OCXO Current: %f",&up->stat_amp);
+	    return;
+	} else if (strncmp(tcp,"OCXO Voltage:",13)==0) {
+	    m = sscanf(tcp,"OCXO Voltage: %f",&up->stat_volt);
+	    return;
+	} else if (strncmp(tcp,"TRACKED SATS :",14)==0) {
+	    m = sscanf(tcp,"TRACKED SATS : %d",&up->stat_track);
+	    return;
+	} else if (strncmp(tcp,"VISIBLE SATS :",14)==0) {
+	    m = sscanf(tcp,"VISIBLE SATS : %d",&up->stat_vis);
+	    return;
+	} else if (strncmp(tcp,"PULSE STATUS:",13)==0) {
+	    m = sscanf(tcp,"PULSE STATUS:%d",&up->stat_pulsestat);
+	    return;
+	} else if (strncmp(tcp,"PULSE ACCURACY:",15)==0) {
+	    m = sscanf(tcp,"PULSE ACCURACY:%d",&up->stat_pulseacc);
+	    return;
+	} else if (strncmp(tcp,"PULSE SAWTOOTH:",15)==0) {
+	    m = sscanf(tcp,"PULSE SAWTOOTH:%d",&up->stat_pulsesaw);
+	    return;
+	} else if (strncmp(tcp,"59",2)==0) {
+	    m = sscanf(tcp,"%d",&up->stat_leap);
+	    pp->leap = LEAP_DELSECOND;	
+#ifdef DEBUG
+	    if (debug)
+		printf("fury: leap del pending\n");
+#endif
+	    return;
+	} else if (strncmp(tcp,"60",2)==0) {
+	    m = sscanf(tcp,"%d",&up->stat_leap);
+	    pp->leap = LEAP_NOWARNING;	
+#ifdef DEBUG
+	    if (debug)
+		printf("fury: leap no warning\n");
+#endif
+	    return;
+	} else if (strncmp(tcp,"61",2)==0) {
+	    m = sscanf(tcp,"%d",&up->stat_leap);
+	    pp->leap = LEAP_ADDSECOND;	
+#ifdef DEBUG
+	    if (debug)
+		printf("fury: leap add pending\n");
+#endif
+	    return;
+	} else if (strncmp(tcp,"Jackson",7)==0) {
+	    sprintf(logbuf, "IDN: %s", tcp);
+ 	    record_clock_stats(&peer->srcadr, logbuf);
+	    return;
+	}
+	else {
+	    /* unwanted response */
+#ifdef DEBUG
+	    if (debug)
+		printf("fury: unknown code %d %s\n", strlen(tcp),tcp);
+#endif
+	    return;
+	}
+
+#ifdef DEBUG
+	if (debug)
+	    printf("fury: timecode %d %s\n", strlen(tcp),tcp);
+#endif
+
+
+	/*
+	 *	Check time code format of NMEA
+	 */
+
+	if( !isdigit((int)dp[0]) ||
+	    !isdigit((int)dp[1]) ||
+	    !isdigit((int)dp[2]) ||
+	    !isdigit((int)dp[3]) ||
+	    !isdigit((int)dp[4]) ||
+	    !isdigit((int)dp[5])	
+	    ) {
+		refclock_report(peer, CEVNT_BADREPLY);
+		return;
+	}
+
+	/* initial holdover */
+	if ((up->stat_ppslock == 1) && (up->stat_holdover == 1) && (up->stat_holddur <= 86400)) {
+	    sprintf(logbuf, "HOLDOVER INITIAL ppslock: %d holdstate: %d holddur: %lu",
+		up->stat_ppslock, up->stat_holdover, up->stat_holddur);
+ 	    record_clock_stats(&peer->srcadr, logbuf);
+	}
+
+	/* holdover threshold exceeded */
+	if ((up->stat_holdover == 1) && (up->stat_holddur > 86400)) {
+	    pp->leap = LEAP_NOTINSYNC;
+	    sprintf(logbuf, "HOLDOVER EXCEEDED NOTINSYNC ppslock: %d holdstate: %d holddur: %lu",
+		up->stat_ppslock, up->stat_holdover, up->stat_holddur);
+ 	    record_clock_stats(&peer->srcadr, logbuf);
+	}
+
+	/* check if we are unlocked */
+	if (up->stat_ppslock == 0) {
+	    /* check if we are in holdover recovery */
+	    if ((up->stat_holddur > 0) && (up->stat_pulsestat == 1)) {
+		sprintf(logbuf, "HOLDOVER RECOVERY ppslock: %d holdstate: %d holddur: %lu",
+		    up->stat_ppslock, up->stat_holdover, up->stat_holddur);
+		record_clock_stats(&peer->srcadr, logbuf);
+	    /* check if we are in normal holdover */
+	    } else if ((up->stat_holdover == 1) && (up->stat_holddur <= 86400)) {
+		sprintf(logbuf, "HOLDOVER ppslock: %d holdstate: %d holddur: %lu",
+		    up->stat_ppslock, up->stat_holdover, up->stat_holddur);
+		record_clock_stats(&peer->srcadr, logbuf);
+	    /* we are not synced at all */
+	    } else {
+		pp->leap = LEAP_NOTINSYNC;
+		sprintf(logbuf, "NOTINSYNC ppslock: %d holdstate: %d holddur: %lu",
+		    up->stat_ppslock, up->stat_holdover, up->stat_holddur);
+		record_clock_stats(&peer->srcadr, logbuf);
+	    }
+	}
+
+			
+	/*
+	 * 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';
+	/* Default to 0 milliseconds, if decimal convert milliseconds in
+	   one, two or three digits
+	*/
+	pp->nsec = 0; 
+	if (dp[6] == '.') {
+	    if (isdigit((int)dp[7])) {
+		pp->nsec = (dp[7] - '0') * 100000000;
+		if (isdigit((int)dp[8])) {
+		    pp->nsec += (dp[8] - '0') * 10000000;
+		    if (isdigit((int)dp[9])) {
+			pp->nsec += (dp[9] - '0') * 1000000;
+		    }
+		}
+	    }
+	}
+
+	if (pp->hour > 23 || pp->minute > 59 || pp->second > 59
+	    || pp->nsec > 1000000000) {
+	    refclock_report(peer, CEVNT_BADTIME);
+	    return;
+	}
+
+
+	/*
+	 * Convert date and check values.
+	 */
+	/* 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;
+
+	if (month < 1 || month > 12 || day < 1) {
+	    refclock_report(peer, CEVNT_BADTIME);
+	    return;
+	}
+
+        /* Hmmmm this will be a nono for 2100,2200,2300 but I don't think I'll be here */
+        /* good thing that 2000 is a leap year */
+	/* pp->year will be 00-99 if read from GPS, 00->  (years since 1900) from tm_year */
+	if (pp->year % 4) {
+	    if (day > day1tab[month - 1]) {
+		refclock_report(peer, CEVNT_BADTIME);
+		return;
+	    }
+	    for (i = 0; i < month - 1; i++)
+		day += day1tab[i];
+	} else {
+	    if (day > day2tab[month - 1]) {
+		refclock_report(peer, CEVNT_BADTIME);
+		return;
+	    }
+	    for (i = 0; i < month - 1; i++)
+		day += day2tab[i];
+	}
+	pp->day = day;
+
+	/*
+	 * Process the new sample in the median filter and determine the
+	 * reference clock offset and dispersion. We use lastrec as both
+	 * the reference time and receive time, in order to avoid being
+	 * cute, like setting the reference time later than the receive
+	 * time, which may cause a paranoid protocol module to chuck out
+	 * the data.
+	 */
+
+	if (!refclock_process(pp)) {
+	    refclock_report(peer, CEVNT_BADTIME);
+	    return;
+	}
+
+	/*
+	 * Only go on if we had been polled.
+	 */
+	if (up->polled) {
+	    up->polled = 0;
+	    pp->lastref = pp->lastrec;
+	    refclock_receive(peer);
+
+            /* If we get here - what we got from the clock is OK, so say so */
+	    refclock_report(peer, CEVNT_NOMINAL);
+
+	    if (pp->sloppyclockflag & CLK_FLAG4){
+	    	record_clock_stats(&peer->srcadr, tcp);
+	    }
+	}
+
+	if (pp->sloppyclockflag & CLK_FLAG3){
+	    if ((up->tscnt == 1) && (up->stat_efc > 0)) {
+		sprintf(logbuf, "%lu %d %lu %d %.2e %.2e %.2f %f %f %.2f %d %d %d %d %d %d",
+		    up->stat_life, up->stat_ppslock, up->stat_holddur,
+		    up->stat_holdover, up->stat_fee, up->stat_tint, up->stat_temp,
+		    up->stat_efc, up->stat_amp, up->stat_volt, up->stat_track,
+		    up->stat_vis, up->stat_pulsestat, up->stat_pulseacc, up->stat_pulsesaw, up->stat_leap);
+		record_clock_stats(&peer->srcadr, logbuf);
+	    }
+	    if (up->tscnt == 10) {
+		up->tscnt=0;
+	    }
+	}
+	/* send these for holdover parsing */
+		gps_send(pp->io.fd,"DIAG?\r", peer);
+		gps_send(pp->io.fd,"MEAS?\r", peer);
+	gps_send(pp->io.fd,"SYNC?\r", peer);
+	gps_send(pp->io.fd,"GPS?\r", peer);
+
+
+}
+
+/*
+ * fury_poll - called by the transmit procedure
+ *
+ * We go to great pains to avoid changing state here, since there may be
+ * more than one eavesdropper receiving the same timecode.
+ */
+static void
+fury_poll(
+	int unit,
+	struct peer *peer
+	)
+{
+	register struct furyunit *up;
+	struct refclockproc *pp;
+
+	pp = peer->procptr;
+	up = (struct furyunit *)pp->unitptr;
+	if (up->pollcnt == 0)
+	    refclock_report(peer, CEVNT_TIMEOUT);
+	else
+	    up->pollcnt--;
+	pp->polls++;
+	up->polled = 1;
+
+	/*
+	 * send cmd to check for leap second
+	 * 59 del
+	 * 60 nowarn
+	 * 61 add
+	 */
+	gps_send(pp->io.fd,"PTIME:LEAP:DUR?\r", peer);
+}
+
+/*
+ *
+ *	gps_send(fd,cmd, peer)  Sends a command to the GPS receiver.
+ *
+ */
+static void
+gps_send(
+	int fd,
+	const char *cmd,
+	struct peer *peer
+	)
+{
+
+	if (write(fd, cmd, strlen(cmd)) == -1) {
+	    refclock_report(peer, CEVNT_FAULT);
+	}
+	/* usleep(50000); */
+}
+
+static char *
+field_parse(
+	char *cp,
+	int fn
+	)
+{
+	char *tp;
+	int i = fn;
+
+	for (tp = cp; *tp != '\0'; tp++) {
+	    if (*tp == ',')
+		i--;
+	    if (i == 0)
+		break;
+	}
+	return (++tp);
+}
+#else
+int refclock_fury_bs;
+#endif /* REFCLOCK */
_______________________________________________
time-nuts mailing list -- [email protected]
To unsubscribe, go to https://www.febo.com/cgi-bin/mailman/listinfo/time-nuts
and follow the instructions there.

Reply via email to