File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / ntp / ntpd / refclock_hpgps.c
Revision 1.1.1.1 (vendor branch): download - view: text, annotated - select for diffs - revision graph
Tue May 29 12:08:38 2012 UTC (12 years, 2 months ago) by misho
Branches: ntp, MAIN
CVS tags: v4_2_6p5p0, v4_2_6p5, HEAD
ntp 4.2.6p5

    1: /*
    2:  * refclock_hpgps - clock driver for HP 58503A GPS receiver
    3:  */
    4: 
    5: #ifdef HAVE_CONFIG_H
    6: # include <config.h>
    7: #endif
    8: 
    9: #if defined(REFCLOCK) && defined(CLOCK_HPGPS)
   10: 
   11: #include "ntpd.h"
   12: #include "ntp_io.h"
   13: #include "ntp_refclock.h"
   14: #include "ntp_stdlib.h"
   15: 
   16: #include <stdio.h>
   17: #include <ctype.h>
   18: 
   19: /* Version 0.1 April  1, 1995  
   20:  *         0.2 April 25, 1995
   21:  *             tolerant of missing timecode response prompt and sends
   22:  *             clear status if prompt indicates error;
   23:  *             can use either local time or UTC from receiver;
   24:  *             can get receiver status screen via flag4
   25:  *
   26:  * WARNING!: This driver is UNDER CONSTRUCTION
   27:  * Everything in here should be treated with suspicion.
   28:  * If it looks wrong, it probably is.
   29:  *
   30:  * Comments and/or questions to: Dave Vitanye
   31:  *                               Hewlett Packard Company
   32:  *                               dave@scd.hp.com
   33:  *                               (408) 553-2856
   34:  *
   35:  * Thanks to the author of the PST driver, which was the starting point for
   36:  * this one.
   37:  *
   38:  * This driver supports the HP 58503A Time and Frequency Reference Receiver.
   39:  * This receiver uses HP SmartClock (TM) to implement an Enhanced GPS receiver.
   40:  * The receiver accuracy when locked to GPS in normal operation is better
   41:  * than 1 usec. The accuracy when operating in holdover is typically better
   42:  * than 10 usec. per day.
   43:  *
   44:  * The same driver also handles the HP Z3801A which is available surplus
   45:  * from the cell phone industry.  It's popular with hams.
   46:  * It needs a different line setup: 19200 baud, 7 data bits, odd parity
   47:  * That is selected by adding "mode 1" to the server line in ntp.conf
   48:  * HP Z3801A code from Jeff Mock added by Hal Murray, Sep 2005
   49:  *
   50:  *
   51:  * The receiver should be operated with factory default settings.
   52:  * Initial driver operation: expects the receiver to be already locked
   53:  * to GPS, configured and able to output timecode format 2 messages.
   54:  *
   55:  * The driver uses the poll sequence :PTIME:TCODE? to get a response from
   56:  * the receiver. The receiver responds with a timecode string of ASCII
   57:  * printing characters, followed by a <cr><lf>, followed by a prompt string
   58:  * issued by the receiver, in the following format:
   59:  * T#yyyymmddhhmmssMFLRVcc<cr><lf>scpi > 
   60:  *
   61:  * The driver processes the response at the <cr> and <lf>, so what the
   62:  * driver sees is the prompt from the previous poll, followed by this
   63:  * timecode. The prompt from the current poll is (usually) left unread until
   64:  * the next poll. So (except on the very first poll) the driver sees this:
   65:  *
   66:  * scpi > T#yyyymmddhhmmssMFLRVcc<cr><lf>
   67:  *
   68:  * The T is the on-time character, at 980 msec. before the next 1PPS edge.
   69:  * The # is the timecode format type. We look for format 2.
   70:  * Without any of the CLK or PPS stuff, then, the receiver buffer timestamp
   71:  * at the <cr> is 24 characters later, which is about 25 msec. at 9600 bps,
   72:  * so the first approximation for fudge time1 is nominally -0.955 seconds.
   73:  * This number probably needs adjusting for each machine / OS type, so far:
   74:  *  -0.955000 on an HP 9000 Model 712/80 HP-UX 9.05
   75:  *  -0.953175 on an HP 9000 Model 370    HP-UX 9.10 
   76:  *
   77:  * This receiver also provides a 1PPS signal, but I haven't figured out
   78:  * how to deal with any of the CLK or PPS stuff yet. Stay tuned.
   79:  *
   80:  */
   81: 
   82: /*
   83:  * Fudge Factors
   84:  *
   85:  * Fudge time1 is used to accomodate the timecode serial interface adjustment.
   86:  * Fudge flag4 can be set to request a receiver status screen summary, which
   87:  * is recorded in the clockstats file.
   88:  */
   89: 
   90: /*
   91:  * Interface definitions
   92:  */
   93: #define	DEVICE		"/dev/hpgps%d" /* device name and unit */
   94: #define	SPEED232	B9600	/* uart speed (9600 baud) */
   95: #define	SPEED232Z	B19200	/* uart speed (19200 baud) */
   96: #define	PRECISION	(-10)	/* precision assumed (about 1 ms) */
   97: #define	REFID		"GPS\0"	/*  reference ID */
   98: #define	DESCRIPTION	"HP 58503A GPS Time and Frequency Reference Receiver" 
   99: 
  100: #define SMAX            23*80+1 /* for :SYSTEM:PRINT? status screen response */
  101: 
  102: #define MTZONE          2       /* number of fields in timezone reply */
  103: #define MTCODET2        12      /* number of fields in timecode format T2 */
  104: #define NTCODET2        21      /* number of chars to checksum in format T2 */
  105: 
  106: /*
  107:  * Tables to compute the day of year from yyyymmdd timecode.
  108:  * Viva la leap.
  109:  */
  110: static int day1tab[] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
  111: static int day2tab[] = {31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
  112: 
  113: /*
  114:  * Unit control structure
  115:  */
  116: struct hpgpsunit {
  117: 	int	pollcnt;	/* poll message counter */
  118: 	int     tzhour;         /* timezone offset, hours */
  119: 	int     tzminute;       /* timezone offset, minutes */
  120: 	int     linecnt;        /* set for expected multiple line responses */
  121: 	char	*lastptr;	/* pointer to receiver response data */
  122: 	char    statscrn[SMAX]; /* receiver status screen buffer */
  123: };
  124: 
  125: /*
  126:  * Function prototypes
  127:  */
  128: static	int	hpgps_start	(int, struct peer *);
  129: static	void	hpgps_shutdown	(int, struct peer *);
  130: static	void	hpgps_receive	(struct recvbuf *);
  131: static	void	hpgps_poll	(int, struct peer *);
  132: 
  133: /*
  134:  * Transfer vector
  135:  */
  136: struct	refclock refclock_hpgps = {
  137: 	hpgps_start,		/* start up driver */
  138: 	hpgps_shutdown,		/* shut down driver */
  139: 	hpgps_poll,		/* transmit poll message */
  140: 	noentry,		/* not used (old hpgps_control) */
  141: 	noentry,		/* initialize driver */
  142: 	noentry,		/* not used (old hpgps_buginfo) */
  143: 	NOFLAGS			/* not used */
  144: };
  145: 
  146: 
  147: /*
  148:  * hpgps_start - open the devices and initialize data for processing
  149:  */
  150: static int
  151: hpgps_start(
  152: 	int unit,
  153: 	struct peer *peer
  154: 	)
  155: {
  156: 	register struct hpgpsunit *up;
  157: 	struct refclockproc *pp;
  158: 	int fd;
  159: 	char device[20];
  160: 
  161: 	/*
  162: 	 * Open serial port. Use CLK line discipline, if available.
  163: 	 * Default is HP 58503A, mode arg selects HP Z3801A
  164: 	 */
  165: 	snprintf(device, sizeof(device), DEVICE, unit);
  166: 	/* mode parameter to server config line shares ttl slot */
  167: 	if ((peer->ttl == 1)) {
  168: 		if (!(fd = refclock_open(device, SPEED232Z,
  169: 				LDISC_CLK | LDISC_7O1)))
  170: 			return (0);
  171: 	} else {
  172: 		if (!(fd = refclock_open(device, SPEED232, LDISC_CLK)))
  173: 			return (0);
  174: 	}
  175: 	/*
  176: 	 * Allocate and initialize unit structure
  177: 	 */
  178: 	up = emalloc(sizeof(*up));
  179: 	memset(up, 0, sizeof(*up));
  180: 	pp = peer->procptr;
  181: 	pp->io.clock_recv = hpgps_receive;
  182: 	pp->io.srcclock = (caddr_t)peer;
  183: 	pp->io.datalen = 0;
  184: 	pp->io.fd = fd;
  185: 	if (!io_addclock(&pp->io)) {
  186: 		close(fd);
  187: 		pp->io.fd = -1;
  188: 		free(up);
  189: 		return (0);
  190: 	}
  191: 	pp->unitptr = (caddr_t)up;
  192: 
  193: 	/*
  194: 	 * Initialize miscellaneous variables
  195: 	 */
  196: 	peer->precision = PRECISION;
  197: 	pp->clockdesc = DESCRIPTION;
  198: 	memcpy((char *)&pp->refid, REFID, 4);
  199: 	up->tzhour = 0;
  200: 	up->tzminute = 0;
  201: 
  202: 	*up->statscrn = '\0';
  203: 	up->lastptr = up->statscrn;
  204: 	up->pollcnt = 2;
  205: 
  206: 	/*
  207: 	 * Get the identifier string, which is logged but otherwise ignored,
  208: 	 * and get the local timezone information
  209: 	 */
  210: 	up->linecnt = 1;
  211: 	if (write(pp->io.fd, "*IDN?\r:PTIME:TZONE?\r", 20) != 20)
  212: 	    refclock_report(peer, CEVNT_FAULT);
  213: 
  214: 	return (1);
  215: }
  216: 
  217: 
  218: /*
  219:  * hpgps_shutdown - shut down the clock
  220:  */
  221: static void
  222: hpgps_shutdown(
  223: 	int unit,
  224: 	struct peer *peer
  225: 	)
  226: {
  227: 	register struct hpgpsunit *up;
  228: 	struct refclockproc *pp;
  229: 
  230: 	pp = peer->procptr;
  231: 	up = (struct hpgpsunit *)pp->unitptr;
  232: 	if (-1 != pp->io.fd)
  233: 		io_closeclock(&pp->io);
  234: 	if (NULL != up)
  235: 		free(up);
  236: }
  237: 
  238: 
  239: /*
  240:  * hpgps_receive - receive data from the serial interface
  241:  */
  242: static void
  243: hpgps_receive(
  244: 	struct recvbuf *rbufp
  245: 	)
  246: {
  247: 	register struct hpgpsunit *up;
  248: 	struct refclockproc *pp;
  249: 	struct peer *peer;
  250: 	l_fp trtmp;
  251: 	char tcodechar1;        /* identifies timecode format */
  252: 	char tcodechar2;        /* identifies timecode format */
  253: 	char timequal;          /* time figure of merit: 0-9 */
  254: 	char freqqual;          /* frequency figure of merit: 0-3 */
  255: 	char leapchar;          /* leapsecond: + or 0 or - */
  256: 	char servchar;          /* request for service: 0 = no, 1 = yes */
  257: 	char syncchar;          /* time info is invalid: 0 = no, 1 = yes */
  258: 	short expectedsm;       /* expected timecode byte checksum */
  259: 	short tcodechksm;       /* computed timecode byte checksum */
  260: 	int i,m,n;
  261: 	int month, day, lastday;
  262: 	char *tcp;              /* timecode pointer (skips over the prompt) */
  263: 	char prompt[BMAX];      /* prompt in response from receiver */
  264: 
  265: 	/*
  266: 	 * Initialize pointers and read the receiver response
  267: 	 */
  268: 	peer = (struct peer *)rbufp->recv_srcclock;
  269: 	pp = peer->procptr;
  270: 	up = (struct hpgpsunit *)pp->unitptr;
  271: 	*pp->a_lastcode = '\0';
  272: 	pp->lencode = refclock_gtlin(rbufp, pp->a_lastcode, BMAX, &trtmp);
  273: 
  274: #ifdef DEBUG
  275: 	if (debug)
  276: 	    printf("hpgps: lencode: %d timecode:%s\n",
  277: 		   pp->lencode, pp->a_lastcode);
  278: #endif
  279: 
  280: 	/*
  281: 	 * If there's no characters in the reply, we can quit now
  282: 	 */
  283: 	if (pp->lencode == 0)
  284: 	    return;
  285: 
  286: 	/*
  287: 	 * If linecnt is greater than zero, we are getting information only,
  288: 	 * such as the receiver identification string or the receiver status
  289: 	 * screen, so put the receiver response at the end of the status
  290: 	 * screen buffer. When we have the last line, write the buffer to
  291: 	 * the clockstats file and return without further processing.
  292: 	 *
  293: 	 * If linecnt is zero, we are expecting either the timezone
  294: 	 * or a timecode. At this point, also write the response
  295: 	 * to the clockstats file, and go on to process the prompt (if any),
  296: 	 * timezone, or timecode and timestamp.
  297: 	 */
  298: 
  299: 
  300: 	if (up->linecnt-- > 0) {
  301: 		if ((int)(pp->lencode + 2) <= (SMAX - (up->lastptr - up->statscrn))) {
  302: 			*up->lastptr++ = '\n';
  303: 			(void)strcpy(up->lastptr, pp->a_lastcode);
  304: 			up->lastptr += pp->lencode;
  305: 		}
  306: 		if (up->linecnt == 0) 
  307: 		    record_clock_stats(&peer->srcadr, up->statscrn);
  308:                
  309: 		return;
  310: 	}
  311: 
  312: 	record_clock_stats(&peer->srcadr, pp->a_lastcode);
  313: 	pp->lastrec = trtmp;
  314:             
  315: 	up->lastptr = up->statscrn;
  316: 	*up->lastptr = '\0';
  317: 	up->pollcnt = 2;
  318: 
  319: 	/*
  320: 	 * We get down to business: get a prompt if one is there, issue
  321: 	 * a clear status command if it contains an error indication.
  322: 	 * Next, check for either the timezone reply or the timecode reply
  323: 	 * and decode it.  If we don't recognize the reply, or don't get the
  324: 	 * proper number of decoded fields, or get an out of range timezone,
  325: 	 * or if the timecode checksum is bad, then we declare bad format
  326: 	 * and exit.
  327: 	 *
  328: 	 * Timezone format (including nominal prompt):
  329: 	 * scpi > -H,-M<cr><lf>
  330: 	 *
  331: 	 * Timecode format (including nominal prompt):
  332: 	 * scpi > T2yyyymmddhhmmssMFLRVcc<cr><lf>
  333: 	 *
  334: 	 */
  335: 
  336: 	(void)strcpy(prompt,pp->a_lastcode);
  337: 	tcp = strrchr(pp->a_lastcode,'>');
  338: 	if (tcp == NULL)
  339: 	    tcp = pp->a_lastcode; 
  340: 	else
  341: 	    tcp++;
  342: 	prompt[tcp - pp->a_lastcode] = '\0';
  343: 	while ((*tcp == ' ') || (*tcp == '\t')) tcp++;
  344: 
  345: 	/*
  346: 	 * deal with an error indication in the prompt here
  347: 	 */
  348: 	if (strrchr(prompt,'E') > strrchr(prompt,'s')){
  349: #ifdef DEBUG
  350: 		if (debug)
  351: 		    printf("hpgps: error indicated in prompt: %s\n", prompt);
  352: #endif
  353: 		if (write(pp->io.fd, "*CLS\r\r", 6) != 6)
  354: 		    refclock_report(peer, CEVNT_FAULT);
  355: 	}
  356: 
  357: 	/*
  358: 	 * make sure we got a timezone or timecode format and 
  359: 	 * then process accordingly
  360: 	 */
  361: 	m = sscanf(tcp,"%c%c", &tcodechar1, &tcodechar2);
  362: 
  363: 	if (m != 2){
  364: #ifdef DEBUG
  365: 		if (debug)
  366: 		    printf("hpgps: no format indicator\n");
  367: #endif
  368: 		refclock_report(peer, CEVNT_BADREPLY);
  369: 		return;
  370: 	}
  371: 
  372: 	switch (tcodechar1) {
  373: 
  374: 	    case '+':
  375: 	    case '-':
  376: 		m = sscanf(tcp,"%d,%d", &up->tzhour, &up->tzminute);
  377: 		if (m != MTZONE) {
  378: #ifdef DEBUG
  379: 			if (debug)
  380: 			    printf("hpgps: only %d fields recognized in timezone\n", m);
  381: #endif
  382: 			refclock_report(peer, CEVNT_BADREPLY);
  383: 			return;
  384: 		}
  385: 		if ((up->tzhour < -12) || (up->tzhour > 13) || 
  386: 		    (up->tzminute < -59) || (up->tzminute > 59)){
  387: #ifdef DEBUG
  388: 			if (debug)
  389: 			    printf("hpgps: timezone %d, %d out of range\n",
  390: 				   up->tzhour, up->tzminute);
  391: #endif
  392: 			refclock_report(peer, CEVNT_BADREPLY);
  393: 			return;
  394: 		}
  395: 		return;
  396: 
  397: 	    case 'T':
  398: 		break;
  399: 
  400: 	    default:
  401: #ifdef DEBUG
  402: 		if (debug)
  403: 		    printf("hpgps: unrecognized reply format %c%c\n",
  404: 			   tcodechar1, tcodechar2);
  405: #endif
  406: 		refclock_report(peer, CEVNT_BADREPLY);
  407: 		return;
  408: 	} /* end of tcodechar1 switch */
  409: 
  410: 
  411: 	switch (tcodechar2) {
  412: 
  413: 	    case '2':
  414: 		m = sscanf(tcp,"%*c%*c%4d%2d%2d%2d%2d%2d%c%c%c%c%c%2hx",
  415: 			   &pp->year, &month, &day, &pp->hour, &pp->minute, &pp->second,
  416: 			   &timequal, &freqqual, &leapchar, &servchar, &syncchar,
  417: 			   &expectedsm);
  418: 		n = NTCODET2;
  419: 
  420: 		if (m != MTCODET2){
  421: #ifdef DEBUG
  422: 			if (debug)
  423: 			    printf("hpgps: only %d fields recognized in timecode\n", m);
  424: #endif
  425: 			refclock_report(peer, CEVNT_BADREPLY);
  426: 			return;
  427: 		}
  428: 		break;
  429: 
  430: 	    default:
  431: #ifdef DEBUG
  432: 		if (debug)
  433: 		    printf("hpgps: unrecognized timecode format %c%c\n",
  434: 			   tcodechar1, tcodechar2);
  435: #endif
  436: 		refclock_report(peer, CEVNT_BADREPLY);
  437: 		return;
  438: 	} /* end of tcodechar2 format switch */
  439:            
  440: 	/* 
  441: 	 * Compute and verify the checksum.
  442: 	 * Characters are summed starting at tcodechar1, ending at just
  443: 	 * before the expected checksum.  Bail out if incorrect.
  444: 	 */
  445: 	tcodechksm = 0;
  446: 	while (n-- > 0) tcodechksm += *tcp++;
  447: 	tcodechksm &= 0x00ff;
  448: 
  449: 	if (tcodechksm != expectedsm) {
  450: #ifdef DEBUG
  451: 		if (debug)
  452: 		    printf("hpgps: checksum %2hX doesn't match %2hX expected\n",
  453: 			   tcodechksm, expectedsm);
  454: #endif
  455: 		refclock_report(peer, CEVNT_BADREPLY);
  456: 		return;
  457: 	}
  458: 
  459: 	/* 
  460: 	 * Compute the day of year from the yyyymmdd format.
  461: 	 */
  462: 	if (month < 1 || month > 12 || day < 1) {
  463: 		refclock_report(peer, CEVNT_BADTIME);
  464: 		return;
  465: 	}
  466: 
  467: 	if ( ! isleap_4(pp->year) ) {				/* Y2KFixes */
  468: 		/* not a leap year */
  469: 		if (day > day1tab[month - 1]) {
  470: 			refclock_report(peer, CEVNT_BADTIME);
  471: 			return;
  472: 		}
  473: 		for (i = 0; i < month - 1; i++) day += day1tab[i];
  474: 		lastday = 365;
  475: 	} else {
  476: 		/* a leap year */
  477: 		if (day > day2tab[month - 1]) {
  478: 			refclock_report(peer, CEVNT_BADTIME);
  479: 			return;
  480: 		}
  481: 		for (i = 0; i < month - 1; i++) day += day2tab[i];
  482: 		lastday = 366;
  483: 	}
  484: 
  485: 	/*
  486: 	 * Deal with the timezone offset here. The receiver timecode is in
  487: 	 * local time = UTC + :PTIME:TZONE, so SUBTRACT the timezone values.
  488: 	 * For example, Pacific Standard Time is -8 hours , 0 minutes.
  489: 	 * Deal with the underflows and overflows.
  490: 	 */
  491: 	pp->minute -= up->tzminute;
  492: 	pp->hour -= up->tzhour;
  493: 
  494: 	if (pp->minute < 0) {
  495: 		pp->minute += 60;
  496: 		pp->hour--;
  497: 	}
  498: 	if (pp->minute > 59) {
  499: 		pp->minute -= 60;
  500: 		pp->hour++;
  501: 	}
  502: 	if (pp->hour < 0)  {
  503: 		pp->hour += 24;
  504: 		day--;
  505: 		if (day < 1) {
  506: 			pp->year--;
  507: 			if ( isleap_4(pp->year) )		/* Y2KFixes */
  508: 			    day = 366;
  509: 			else
  510: 			    day = 365;
  511: 		}
  512: 	}
  513: 
  514: 	if (pp->hour > 23) {
  515: 		pp->hour -= 24;
  516: 		day++;
  517: 		if (day > lastday) {
  518: 			pp->year++;
  519: 			day = 1;
  520: 		}
  521: 	}
  522: 
  523: 	pp->day = day;
  524: 
  525: 	/*
  526: 	 * Decode the MFLRV indicators.
  527: 	 * NEED TO FIGURE OUT how to deal with the request for service,
  528: 	 * time quality, and frequency quality indicators some day. 
  529: 	 */
  530: 	if (syncchar != '0') {
  531: 		pp->leap = LEAP_NOTINSYNC;
  532: 	}
  533: 	else {
  534: 		pp->leap = LEAP_NOWARNING;
  535: 		switch (leapchar) {
  536: 
  537: 		    case '0':
  538: 			break;
  539:                      
  540: 		    /* See http://bugs.ntp.org/1090
  541: 		     * Ignore leap announcements unless June or December.
  542: 		     * Better would be to use :GPSTime? to find the month,
  543: 		     * but that seems too likely to introduce other bugs.
  544: 		     */
  545: 		    case '+':
  546: 			if ((month==6) || (month==12))
  547: 			    pp->leap = LEAP_ADDSECOND;
  548: 			break;
  549:                      
  550: 		    case '-':
  551: 			if ((month==6) || (month==12))
  552: 			    pp->leap = LEAP_DELSECOND;
  553: 			break;
  554:                      
  555: 		    default:
  556: #ifdef DEBUG
  557: 			if (debug)
  558: 			    printf("hpgps: unrecognized leap indicator: %c\n",
  559: 				   leapchar);
  560: #endif
  561: 			refclock_report(peer, CEVNT_BADTIME);
  562: 			return;
  563: 		} /* end of leapchar switch */
  564: 	}
  565: 
  566: 	/*
  567: 	 * Process the new sample in the median filter and determine the
  568: 	 * reference clock offset and dispersion. We use lastrec as both
  569: 	 * the reference time and receive time in order to avoid being
  570: 	 * cute, like setting the reference time later than the receive
  571: 	 * time, which may cause a paranoid protocol module to chuck out
  572: 	 * the data.
  573: 	 */
  574: 	if (!refclock_process(pp)) {
  575: 		refclock_report(peer, CEVNT_BADTIME);
  576: 		return;
  577: 	}
  578: 	pp->lastref = pp->lastrec;
  579: 	refclock_receive(peer);
  580: 
  581: 	/*
  582: 	 * If CLK_FLAG4 is set, ask for the status screen response.
  583: 	 */
  584: 	if (pp->sloppyclockflag & CLK_FLAG4){
  585: 		up->linecnt = 22; 
  586: 		if (write(pp->io.fd, ":SYSTEM:PRINT?\r", 15) != 15)
  587: 		    refclock_report(peer, CEVNT_FAULT);
  588: 	}
  589: }
  590: 
  591: 
  592: /*
  593:  * hpgps_poll - called by the transmit procedure
  594:  */
  595: static void
  596: hpgps_poll(
  597: 	int unit,
  598: 	struct peer *peer
  599: 	)
  600: {
  601: 	register struct hpgpsunit *up;
  602: 	struct refclockproc *pp;
  603: 
  604: 	/*
  605: 	 * Time to poll the clock. The HP 58503A responds to a
  606: 	 * ":PTIME:TCODE?" by returning a timecode in the format specified
  607: 	 * above. If nothing is heard from the clock for two polls,
  608: 	 * declare a timeout and keep going.
  609: 	 */
  610: 	pp = peer->procptr;
  611: 	up = (struct hpgpsunit *)pp->unitptr;
  612: 	if (up->pollcnt == 0)
  613: 	    refclock_report(peer, CEVNT_TIMEOUT);
  614: 	else
  615: 	    up->pollcnt--;
  616: 	if (write(pp->io.fd, ":PTIME:TCODE?\r", 14) != 14) {
  617: 		refclock_report(peer, CEVNT_FAULT);
  618: 	}
  619: 	else
  620: 	    pp->polls++;
  621: }
  622: 
  623: #else
  624: int refclock_hpgps_bs;
  625: #endif /* REFCLOCK */

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>