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

📄 refclock_mx4200.c

📁 网络时间协议NTP 源码 版本v4.2.0b 该源码用于linux平台下
💻 C
📖 第 1 页 / 共 3 页
字号:
/* * This software was developed by the Computer Systems Engineering group * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66. * * Copyright (c) 1992 The Regents of the University of California. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright *    notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright *    notice, this list of conditions and the following disclaimer in the *    documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software *    must display the following acknowledgement: *	This product includes software developed by the University of *	California, Lawrence Berkeley Laboratory. * 4. The name of the University may not be used to endorse or promote *    products derived from this software without specific prior *    written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. *//* * Modified: Marc Brett <marc.brett@westgeo.com>   Sept, 1999. * * 1. Added support for alternate PPS schemes, with code mostly *    copied from the Oncore driver (Thanks, Poul-Henning Kamp). *    This code runs on SunOS 4.1.3 with ppsclock-1.6a1 and Solaris 7. */#ifdef HAVE_CONFIG_H# include <config.h>#endif#if defined(REFCLOCK) && defined(CLOCK_MX4200) && defined(HAVE_PPSAPI)#include "ntpd.h"#include "ntp_io.h"#include "ntp_refclock.h"#include "ntp_unixtime.h"#include "ntp_stdlib.h"#include <stdio.h>#include <ctype.h>#include "mx4200.h"#ifdef HAVE_SYS_TERMIOS_H# include <sys/termios.h>#endif#ifdef HAVE_SYS_PPSCLOCK_H# include <sys/ppsclock.h>#endif#include "ntp_sprintf.h"#ifndef HAVE_STRUCT_PPSCLOCKEVstruct ppsclockev {# ifdef HAVE_STRUCT_TIMESPEC	struct timespec tv;# else	struct timeval tv;# endif	u_int serial;};#endif /* ! HAVE_STRUCT_PPSCLOCKEV */#ifdef HAVE_PPSAPI# include "ppsapi_timepps.h"#endif /* HAVE_PPSAPI *//* * This driver supports the Magnavox Model MX 4200 GPS Receiver * adapted to precision timing applications.  It requires the * ppsclock line discipline or streams module described in the * Line Disciplines and Streams Drivers page. It also requires a * gadget box and 1-PPS level converter, such as described in the * Pulse-per-second (PPS) Signal Interfacing page. * * It's likely that other compatible Magnavox receivers such as the * MX 4200D, MX 9212, MX 9012R, MX 9112 will be supported by this code. *//* * Check this every time you edit the code! */#define YEAR_LAST_MODIFIED 2000/* * GPS Definitions */#define	DEVICE		"/dev/gps%d"	/* device name and unit */#define	SPEED232	B4800		/* baud *//* * Radio interface parameters */#define	PRECISION	(-18)	/* precision assumed (about 4 us) */#define	REFID	"GPS\0"		/* reference id */#define	DESCRIPTION	"Magnavox MX4200 GPS Receiver" /* who we are */#define	DEFFUDGETIME	0	/* default fudge time (ms) */#define	SLEEPTIME	32	/* seconds to wait for reconfig to complete *//* * Position Averaging. */#define INTERVAL	1	/* Interval between position measurements (s) */#define AVGING_TIME	24	/* Number of hours to average */#define NOT_INITIALIZED	-9999.	/* initial pivot longitude *//* * MX4200 unit control structure. */struct mx4200unit {	u_int  pollcnt;			/* poll message counter */	u_int  polled;			/* Hand in a time sample? */	u_int  lastserial;		/* last pps serial number */	struct ppsclockev ppsev;	/* PPS control structure */	double avg_lat;			/* average latitude */	double avg_lon;			/* average longitude */	double avg_alt;			/* average height */	double central_meridian;	/* central meridian */	double N_fixes;			/* Number of position measurements */	int    last_leap;		/* leap second warning */	u_int  moving;			/* mobile platform? */	u_long sloppyclockflag;		/* fudge flags */	u_int  known;			/* position known yet? */	u_long clamp_time;		/* when to stop postion averaging */	u_long log_time;		/* when to print receiver status */	pps_handle_t	pps_h;	pps_params_t	pps_p;	pps_info_t	pps_i;};static char pmvxg[] = "PMVXG";/* XXX should be somewhere else */#ifdef __GNUC__#if __GNUC__ < 2  || (__GNUC__ == 2 && __GNUC_MINOR__ < 5)#ifndef __attribute__#define __attribute__(args)#endif /* __attribute__ */#endif /* __GNUC__ < 2  || (__GNUC__ == 2 && __GNUC_MINOR__ < 5) */#else#ifndef __attribute__#define __attribute__(args)#endif /* __attribute__ */#endif /* __GNUC__ *//* XXX end *//* * Function prototypes */static	int	mx4200_start	P((int, struct peer *));static	void	mx4200_shutdown	P((int, struct peer *));static	void	mx4200_receive	P((struct recvbuf *));static	void	mx4200_poll	P((int, struct peer *));static	char *	mx4200_parse_t	P((struct peer *));static	char *	mx4200_parse_p	P((struct peer *));static	char *	mx4200_parse_s	P((struct peer *));#ifdef QSORT_USES_VOID_Pint	mx4200_cmpl_fp	P((const void *, const void *));#elseint	mx4200_cmpl_fp	P((const l_fp *, const l_fp *));#endif /* not QSORT_USES_VOID_P */static	int	mx4200_config	P((struct peer *));static	void	mx4200_ref	P((struct peer *));static	void	mx4200_send	P((struct peer *, char *, ...))    __attribute__ ((format (printf, 2, 3)));static	u_char	mx4200_cksum	P((char *, int));static	int	mx4200_jday	P((int, int, int));static	void	mx4200_debug	P((struct peer *, char *, ...))    __attribute__ ((format (printf, 2, 3)));static	int	mx4200_pps	P((struct peer *));/* * Transfer vector */struct	refclock refclock_mx4200 = {	mx4200_start,		/* start up driver */	mx4200_shutdown,	/* shut down driver */	mx4200_poll,		/* transmit poll message */	noentry,		/* not used (old mx4200_control) */	noentry,		/* initialize driver (not used) */	noentry,		/* not used (old mx4200_buginfo) */	NOFLAGS			/* not used */};/* * mx4200_start - open the devices and initialize data for processing */static intmx4200_start(	int unit,	struct peer *peer	){	register struct mx4200unit *up;	struct refclockproc *pp;	int fd;	char gpsdev[20];	/*	 * Open serial port	 */	(void)sprintf(gpsdev, DEVICE, unit);	if (!(fd = refclock_open(gpsdev, SPEED232, LDISC_PPS))) {	    return (0);	}	/*	 * Allocate unit structure	 */	if (!(up = (struct mx4200unit *) emalloc(sizeof(struct mx4200unit)))) {		perror("emalloc");		(void) close(fd);		return (0);	}	memset((char *)up, 0, sizeof(struct mx4200unit));	pp = peer->procptr;	pp->io.clock_recv = mx4200_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);	/* Ensure the receiver is properly configured */	return mx4200_config(peer);}/* * mx4200_shutdown - shut down the clock */static voidmx4200_shutdown(	int unit,	struct peer *peer	){	register struct mx4200unit *up;	struct refclockproc *pp;	pp = peer->procptr;	up = (struct mx4200unit *)pp->unitptr;	io_closeclock(&pp->io);	free(up);}/* * mx4200_config - Configure the receiver */static intmx4200_config(	struct peer *peer	){	char tr_mode;	int add_mode;	register struct mx4200unit *up;	struct refclockproc *pp;	int mode;	pp = peer->procptr;	up = (struct mx4200unit *)pp->unitptr;	/*	 * Initialize the unit variables	 *	 * STRANGE BEHAVIOUR WARNING: The fudge flags are not available	 * at the time mx4200_start is called.  These are set later,	 * and so the code must be prepared to handle changing flags.	 */	up->sloppyclockflag = pp->sloppyclockflag;	if (pp->sloppyclockflag & CLK_FLAG2) {		up->moving   = 1;	/* Receiver on mobile platform */		msyslog(LOG_DEBUG, "mx4200_config: mobile platform");	} else {		up->moving   = 0;	/* Static Installation */	}	up->pollcnt     	= 2;	up->polled      	= 0;	up->known       	= 0;	up->avg_lat     	= 0.0;	up->avg_lon     	= 0.0;	up->avg_alt     	= 0.0;	up->central_meridian	= NOT_INITIALIZED;	up->N_fixes    		= 0.0;	up->last_leap   	= 0;	/* LEAP_NOWARNING */	up->clamp_time  	= current_time + (AVGING_TIME * 60 * 60);	up->log_time    	= current_time + SLEEPTIME;	if (time_pps_create(pp->io.fd, &up->pps_h) < 0) {		perror("time_pps_create");		msyslog(LOG_ERR,			"mx4200_config: time_pps_create failed: %m");		return (0);	}	if (time_pps_getcap(up->pps_h, &mode) < 0) {		msyslog(LOG_ERR,			"mx4200_config: time_pps_getcap failed: %m");		return (0);	}	if (time_pps_getparams(up->pps_h, &up->pps_p) < 0) {		msyslog(LOG_ERR,			"mx4200_config: time_pps_getparams failed: %m");		return (0);	}	/* nb. only turn things on, if someone else has turned something	 *      on before we get here, leave it alone!	 */	up->pps_p.mode = PPS_CAPTUREASSERT | PPS_TSFMT_TSPEC;	up->pps_p.mode &= mode;		/* only set what is legal */	if (time_pps_setparams(up->pps_h, &up->pps_p) < 0) {		perror("time_pps_setparams");		msyslog(LOG_ERR,			"mx4200_config: time_pps_setparams failed: %m");		exit(1);	}	if (time_pps_kcbind(up->pps_h, PPS_KC_HARDPPS, PPS_CAPTUREASSERT,			PPS_TSFMT_TSPEC) < 0) {		perror("time_pps_kcbind");		msyslog(LOG_ERR,			"mx4200_config: time_pps_kcbind failed: %m");		exit(1);	}	/*	 * "007" Control Port Configuration	 * Zero the output list (do it twice to flush possible junk)	 */	mx4200_send(peer, "%s,%03d,,%d,,,,,,", pmvxg,	    PMVXG_S_PORTCONF,	    /* control port output block Label */	    1);		/* clear current output control list (1=yes) */	/* add/delete sentences from list */	/* must be null */	/* sentence output rate (sec) */	/* precision for position output */	/* nmea version for cga & gll output */	/* pass-through control */	mx4200_send(peer, "%s,%03d,,%d,,,,,,", pmvxg,	    PMVXG_S_PORTCONF, 1);	/*	 * Request software configuration so we can syslog the firmware version	 */	mx4200_send(peer, "%s,%03d", "CDGPQ", PMVXG_D_SOFTCONF);	/*	 * "001" Initialization/Mode Control, Part A	 * Where ARE we?	 */	mx4200_send(peer, "%s,%03d,,,,,,,,,,", pmvxg,	    PMVXG_S_INITMODEA);	/* day of month */	/* month of year */	/* year */	/* gmt */	/* latitude   DDMM.MMMM */	/* north/south */	/* longitude DDDMM.MMMM */	/* east/west */	/* height */	/* Altitude Reference 1=MSL */	/*	 * "001" Initialization/Mode Control, Part B	 * Start off in 2d/3d coast mode, holding altitude to last known	 * value if only 3 satellites available.	 */	mx4200_send(peer, "%s,%03d,%d,,%.1f,%.1f,%d,%d,%d,%c,%d",	    pmvxg, PMVXG_S_INITMODEB,	    3,		/* 2d/3d coast */	    /* reserved */	    0.1,	/* hor accel fact as per Steve (m/s**2) */	    0.1,	/* ver accel fact as per Steve (m/s**2) */	    10,		/* vdop */	    10,		/* hdop limit as per Steve */	    5,		/* elevation limit as per Steve (deg) */	    'U',	/* time output mode (UTC) */	    0);		/* local time offset from gmt (HHHMM) */	/*	 * "023" Time Recovery Configuration	 * Get UTC time from a stationary receiver.	 * (Set field 1 'D' == dynamic if we are on a moving platform).	 * (Set field 1 'S' == static  if we are not moving).	 * (Set field 1 'K' == known position if we can initialize lat/lon/alt).	 */	if (pp->sloppyclockflag & CLK_FLAG2)		up->moving   = 1;	/* Receiver on mobile platform */	else		up->moving   = 0;	/* Static Installation */	up->pollcnt  = 2;	if (up->moving) {		/* dynamic: solve for pos, alt, time, while moving */		tr_mode = 'D';	} else {		/* static: solve for pos, alt, time, while stationary */		tr_mode = 'S';	}	mx4200_send(peer, "%s,%03d,%c,%c,%c,%d,%d,%d,", pmvxg,	    PMVXG_S_TRECOVCONF,	    tr_mode,	/* time recovery mode (see above ) */	    'U',	/* synchronize to UTC */	    'A',	/* always output a time pulse */	    500,	/* max time error in ns */	    0,		/* user bias in ns */	    1);		/* output "830" sentences to control port */			/* Multi-satellite mode */	/*	 * Output position information (to calculate fixed installation	 * location) only if we are not moving	 */	if (up->moving) {		add_mode = 2;	/* delete from list */	} else {		add_mode = 1;	/* add to list */	}	/*	 * "007" Control Port Configuration	 * Output "021" position, height, velocity reports	 */	mx4200_send(peer, "%s,%03d,%03d,%d,%d,,%d,,,", pmvxg,	    PMVXG_S_PORTCONF,	    PMVXG_D_PHV, /* control port output block Label */	    0,		/* clear current output control list (0=no) */	    add_mode,	/* add/delete sentences from list (1=add, 2=del) */	    		/* must be null */	    INTERVAL);	/* sentence output rate (sec) */			/* precision for position output */			/* nmea version for cga & gll output */			/* pass-through control */	return (1);}/* * mx4200_ref - Reconfigure unit as a reference station at a known position. */static voidmx4200_ref(	struct peer *peer	){	register struct mx4200unit *up;	struct refclockproc *pp;	double minute, lat, lon, alt;	char lats[16], lons[16];	char nsc, ewc;	pp = peer->procptr;	up = (struct mx4200unit *)pp->unitptr;	/* Should never happen! */	if (up->moving) return;	/*	 * Set up to output status information in the near future	 */	up->log_time    = current_time + SLEEPTIME;	/*	 * "007" Control Port Configuration	 * Stop outputting "021" position, height, velocity reports	 */	mx4200_send(peer, "%s,%03d,%03d,%d,%d,,,,,", pmvxg,	    PMVXG_S_PORTCONF,	    PMVXG_D_PHV, /* control port output block Label */	    0,		/* clear current output control list (0=no) */	    2);		/* add/delete sentences from list (2=delete) */			/* must be null */	    		/* sentence output rate (sec) */			/* precision for position output */			/* nmea version for cga & gll output */			/* pass-through control */	/*	 * "001" Initialization/Mode Control, Part B	 * Put receiver in fully-constrained 2d nav mode	 */	mx4200_send(peer, "%s,%03d,%d,,%.1f,%.1f,%d,%d,%d,%c,%d",	    pmvxg, PMVXG_S_INITMODEB,	    2,		/* 2d nav */	    /* reserved */	    0.1,	/* hor accel fact as per Steve (m/s**2) */	    0.1,	/* ver accel fact as per Steve (m/s**2) */	    10,		/* vdop */	    10,		/* hdop limit as per Steve */	    5,		/* elevation limit as per Steve (deg) */	    'U',	/* time output mode (UTC) */	    0);		/* local time offset from gmt (HHHMM) */	/*	 * "023" Time Recovery Configuration	 * Get UTC time from a stationary receiver.  Solve for time only.	 * This should improve the time resolution dramatically.	 */	mx4200_send(peer, "%s,%03d,%c,%c,%c,%d,%d,%d,", pmvxg,	    PMVXG_S_TRECOVCONF,	    'K',	/* known position: solve for time only */	    'U',	/* synchronize to UTC */	    'A',	/* always output a time pulse */	    500,	/* max time error in ns */	    0,		/* user bias in ns */	    1);		/* output "830" sentences to control port */	/* Multi-satellite mode */

⌨️ 快捷键说明

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