⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 refclock_hpgps.c

📁 网络时间协议NTP 源码 版本v4.2.0b 该源码用于linux平台下
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * refclock_hpgps - clock driver for HP 58503A GPS receiver */#ifdef HAVE_CONFIG_H# include <config.h>#endif#if defined(REFCLOCK) && defined(CLOCK_HPGPS)#include "ntpd.h"#include "ntp_io.h"#include "ntp_refclock.h"#include "ntp_stdlib.h"#include <stdio.h>#include <ctype.h>/* Version 0.1 April  1, 1995   *         0.2 April 25, 1995 *             tolerant of missing timecode response prompt and sends *             clear status if prompt indicates error; *             can use either local time or UTC from receiver; *             can get receiver status screen via flag4 * * WARNING!: This driver is UNDER CONSTRUCTION * Everything in here should be treated with suspicion. * If it looks wrong, it probably is. * * Comments and/or questions to: Dave Vitanye *                               Hewlett Packard Company *                               dave@scd.hp.com *                               (408) 553-2856 * * Thanks to the author of the PST driver, which was the starting point for * this one. * * This driver supports the HP 58503A Time and Frequency Reference Receiver. * This receiver uses HP SmartClock (TM) to implement an Enhanced GPS receiver. * The receiver accuracy when locked to GPS in normal operation is better * than 1 usec. The accuracy when operating in holdover is typically better * than 10 usec. per day. * * The same driver also handles the HP Z3801A which is available surplus * from the cell phone industry.  It's popular with hams. * It needs a different line setup: 19200 baud, 7 data bits, odd parity * That is selected by adding "mode 1" to the server line in ntp.conf * HP Z3801A code from Jeff Mock added by Hal Murray, Sep 2005 * * * The receiver should be operated with factory default settings. * Initial driver operation: expects the receiver to be already locked * to GPS, configured and able to output timecode format 2 messages. * * The driver uses the poll sequence :PTIME:TCODE? to get a response from * the receiver. The receiver responds with a timecode string of ASCII * printing characters, followed by a <cr><lf>, followed by a prompt string * issued by the receiver, in the following format: * T#yyyymmddhhmmssMFLRVcc<cr><lf>scpi >  * * The driver processes the response at the <cr> and <lf>, so what the * driver sees is the prompt from the previous poll, followed by this * timecode. The prompt from the current poll is (usually) left unread until * the next poll. So (except on the very first poll) the driver sees this: * * scpi > T#yyyymmddhhmmssMFLRVcc<cr><lf> * * The T is the on-time character, at 980 msec. before the next 1PPS edge. * The # is the timecode format type. We look for format 2. * Without any of the CLK or PPS stuff, then, the receiver buffer timestamp * at the <cr> is 24 characters later, which is about 25 msec. at 9600 bps, * so the first approximation for fudge time1 is nominally -0.955 seconds. * This number probably needs adjusting for each machine / OS type, so far: *  -0.955000 on an HP 9000 Model 712/80 HP-UX 9.05 *  -0.953175 on an HP 9000 Model 370    HP-UX 9.10  * * This receiver also provides a 1PPS signal, but I haven't figured out * how to deal with any of the CLK or PPS stuff yet. Stay tuned. * *//* * Fudge Factors * * Fudge time1 is used to accomodate the timecode serial interface adjustment. * Fudge flag4 can be set to request a receiver status screen summary, which * is recorded in the clockstats file. *//* * Interface definitions */#define	DEVICE		"/dev/hpgps%d" /* device name and unit */#define	SPEED232	B9600	/* uart speed (9600 baud) */#define	SPEED232Z	B19200	/* uart speed (19200 baud) */#define	PRECISION	(-10)	/* precision assumed (about 1 ms) */#define	REFID		"GPS\0"	/*  reference ID */#define	DESCRIPTION	"HP 58503A GPS Time and Frequency Reference Receiver" #define SMAX            23*80+1 /* for :SYSTEM:PRINT? status screen response */#define MTZONE          2       /* number of fields in timezone reply */#define MTCODET2        12      /* number of fields in timecode format T2 */#define NTCODET2        21      /* number of chars to checksum in format T2 *//* * Tables to compute the day of year from yyyymmdd 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 hpgpsunit {	int	pollcnt;	/* poll message counter */	int     tzhour;         /* timezone offset, hours */	int     tzminute;       /* timezone offset, minutes */	int     linecnt;        /* set for expected multiple line responses */	char	*lastptr;	/* pointer to receiver response data */	char    statscrn[SMAX]; /* receiver status screen buffer */};/* * Function prototypes */static	int	hpgps_start	P((int, struct peer *));static	void	hpgps_shutdown	P((int, struct peer *));static	void	hpgps_receive	P((struct recvbuf *));static	void	hpgps_poll	P((int, struct peer *));/* * Transfer vector */struct	refclock refclock_hpgps = {	hpgps_start,		/* start up driver */	hpgps_shutdown,		/* shut down driver */	hpgps_poll,		/* transmit poll message */	noentry,		/* not used (old hpgps_control) */	noentry,		/* initialize driver */	noentry,		/* not used (old hpgps_buginfo) */	NOFLAGS			/* not used */};/* * hpgps_start - open the devices and initialize data for processing */static inthpgps_start(	int unit,	struct peer *peer	){	register struct hpgpsunit *up;	struct refclockproc *pp;	int fd;	char device[20];	/*	 * Open serial port. Use CLK line discipline, if available.	 * Default is HP 58503A, mode arg selects HP Z3801A	 */	(void)sprintf(device, DEVICE, unit);	/* mode parameter to server config line shares ttl slot */	if ((peer->ttl == 1)) {		if (!(fd = refclock_open(device, SPEED232Z,				LDISC_CLK | LDISC_7O1)))			return (0);	} else {		if (!(fd = refclock_open(device, SPEED232, LDISC_CLK)))			return (0);	}	/*	 * Allocate and initialize unit structure	 */	if (!(up = (struct hpgpsunit *)	      emalloc(sizeof(struct hpgpsunit)))) {		(void) close(fd);		return (0);	}	memset((char *)up, 0, sizeof(struct hpgpsunit));	pp = peer->procptr;	pp->io.clock_recv = hpgps_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->tzhour = 0;	up->tzminute = 0;	*up->statscrn = '\0';	up->lastptr = up->statscrn;	up->pollcnt = 2;	/*	 * Get the identifier string, which is logged but otherwise ignored,	 * and get the local timezone information	 */	up->linecnt = 1;	if (write(pp->io.fd, "*IDN?\r:PTIME:TZONE?\r", 20) != 20)	    refclock_report(peer, CEVNT_FAULT);	return (1);}/* * hpgps_shutdown - shut down the clock */static voidhpgps_shutdown(	int unit,	struct peer *peer	){	register struct hpgpsunit *up;	struct refclockproc *pp;	pp = peer->procptr;	up = (struct hpgpsunit *)pp->unitptr;	io_closeclock(&pp->io);	free(up);}/* * hpgps_receive - receive data from the serial interface */static voidhpgps_receive(	struct recvbuf *rbufp	){	register struct hpgpsunit *up;	struct refclockproc *pp;	struct peer *peer;	l_fp trtmp;	char tcodechar1;        /* identifies timecode format */	char tcodechar2;        /* identifies timecode format */	char timequal;          /* time figure of merit: 0-9 */	char freqqual;          /* frequency figure of merit: 0-3 */	char leapchar;          /* leapsecond: + or 0 or - */	char servchar;          /* request for service: 0 = no, 1 = yes */	char syncchar;          /* time info is invalid: 0 = no, 1 = yes */	short expectedsm;       /* expected timecode byte checksum */	short tcodechksm;       /* computed timecode byte checksum */	int i,m,n;	int month, day, lastday;	char *tcp;              /* timecode pointer (skips over the prompt) */	char prompt[BMAX];      /* prompt in response from receiver */	/*	 * Initialize pointers and read the receiver response	 */	peer = (struct peer *)rbufp->recv_srcclock;	pp = peer->procptr;	up = (struct hpgpsunit *)pp->unitptr;	*pp->a_lastcode = '\0';	pp->lencode = refclock_gtlin(rbufp, pp->a_lastcode, BMAX, &trtmp);#ifdef DEBUG	if (debug)	    printf("hpgps: lencode: %d timecode:%s\n",		   pp->lencode, pp->a_lastcode);#endif	/*	 * If there's no characters in the reply, we can quit now	 */	if (pp->lencode == 0)	    return;	/*	 * If linecnt is greater than zero, we are getting information only,	 * such as the receiver identification string or the receiver status	 * screen, so put the receiver response at the end of the status	 * screen buffer. When we have the last line, write the buffer to	 * the clockstats file and return without further processing.	 *	 * If linecnt is zero, we are expecting either the timezone	 * or a timecode. At this point, also write the response	 * to the clockstats file, and go on to process the prompt (if any),	 * timezone, or timecode and timestamp.	 */	if (up->linecnt-- > 0) {		if ((int)(pp->lencode + 2) <= (SMAX - (up->lastptr - up->statscrn))) {			*up->lastptr++ = '\n';			(void)strcpy(up->lastptr, pp->a_lastcode);			up->lastptr += pp->lencode;		}		if (up->linecnt == 0) 		    record_clock_stats(&peer->srcadr, up->statscrn);               		return;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -