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

📄 refclock_oncore.c

📁 网络时间协议NTP 源码 版本v4.2.0b 该源码用于linux平台下
💻 C
📖 第 1 页 / 共 5 页
字号:
/* * ---------------------------------------------------------------------------- * "THE BEER-WARE LICENSE" (Revision 42): * <phk@FreeBSD.ORG> wrote this file.  As long as you retain this notice you * can do whatever you want with this stuff. If we meet some day, and you think * this stuff is worth it, you can buy me a beer in return.   Poul-Henning Kamp * ---------------------------------------------------------------------------- * * refclock_oncore.c * * Driver for some of the various the Motorola Oncore GPS receivers. *   should work with Basic, PVT6, VP, UT, UT+, GT, GT+, SL, M12, M12+T *	The receivers with TRAIM (VP, UT, UT+, M12+T), will be more accurate *	than the others. *	The receivers without position hold (GT, GT+) will be less accurate. * * Tested with: * *		(UT)				   (VP) *   COPYRIGHT 1991-1997 MOTOROLA INC.	COPYRIGHT 1991-1996 MOTOROLA INC. *   SFTW P/N #     98-P36848P		SFTW P/N # 98-P36830P *   SOFTWARE VER # 2			SOFTWARE VER # 8 *   SOFTWARE REV # 2			SOFTWARE REV # 8 *   SOFTWARE DATE  APR 24 1998 	SOFTWARE DATE  06 Aug 1996 *   MODEL #	R1121N1114		MODEL #    B4121P1155 *   HWDR P/N # 1			HDWR P/N # _ *   SERIAL #	R0010A			SERIAL #   SSG0226478 *   MANUFACTUR DATE 6H07		MANUFACTUR DATE 7E02 *					OPTIONS LIST	IB * *	      (Basic)				   (M12) *   COPYRIGHT 1991-1994 MOTOROLA INC.	COPYRIGHT 1991-2000 MOTOROLA INC. *   SFTW P/N # 98-P39949M		SFTW P/N # 61-G10002A *   SOFTWARE VER # 5			SOFTWARE VER # 1 *   SOFTWARE REV # 0			SOFTWARE REV # 3 *   SOFTWARE DATE  20 JAN 1994 	SOFTWARE DATE  Mar 13 2000 *   MODEL #	A11121P116		MODEL #    P143T12NR1 *   HDWR P/N # _			HWDR P/N # 1 *   SERIAL #	SSG0049809		SERIAL #   P003UD *   MANUFACTUR DATE 417AMA199		MANUFACTUR DATE 0C27 *   OPTIONS LIST    AB * * -------------------------------------------------------------------------- * Reg.Clemens (Mar 2004) * Support for interfaces other than PPSAPI removed, for Solaris, SunOS, * SCO, you now need to use one of the timepps.h files in the root dir. * this driver will 'grab' it for you if you dont have one in /usr/include * -------------------------------------------------------------------------- * This code uses the two devices *	/dev/oncore.serial.n *	/dev/oncore.pps.n * which may be linked to the same device. * and can read initialization data from the file *	/etc/ntp.oncoreN, /etc/ntp.oncore.N, or /etc/ntp.oncore, where *	n or N are the unit number, viz 127.127.30.N. * -------------------------------------------------------------------------- * Reg.Clemens <reg@dwf.com> Sep98. *  Original code written for FreeBSD. *  With these mods it works on FreeBSD, SunOS, Solaris and Linux *    (SunOS 4.1.3 + ppsclock) *    (Solaris7 + MU4) *    (RedHat 5.1 2.0.35 + PPSKit, 2.1.126 + or later). * *  Lat,Long,Ht, cable-delay, offset, and the ReceiverID (along with the *  state machine state) are printed to CLOCKSTATS if that file is enabled *  in /etc/ntp.conf. * * -------------------------------------------------------------------------- * * According to the ONCORE manual (TRM0003, Rev 3.2, June 1998, page 3.13) * doing an average of 10000 valid 2D and 3D fixes is what the automatic * site survey mode does.  Looking at the output from the receiver * it seems like it is only using 3D fixes. * When we do it ourselves, take 10000 3D fixes. */#define POS_HOLD_AVERAGE	10000	/* nb, 10000s ~= 2h45m *//* * ONCORE_SHMEM_STATUS will create a mmap(2)'ed file named according to a * "STATUS" line in the oncore config file, which contains the most recent * copy of all types of messages we recognize.	This file can be mmap(2)'ed * by monitoring and statistics programs. * * See separate HTML documentation for this option. */#ifdef HAVE_CONFIG_H#include <config.h>#endif#if defined(REFCLOCK) && defined(CLOCK_ONCORE)#include "ntpd.h"#include "ntp_io.h"#include "ntp_unixtime.h"#include "ntp_refclock.h"#include "ntp_stdlib.h"#include <stdio.h>#include <ctype.h>#include <sys/stat.h>#ifdef ONCORE_SHMEM_STATUS# ifdef HAVE_SYS_MMAN_H#  include <sys/mman.h>#  ifndef MAP_FAILED#   define MAP_FAILED ((u_char *) -1)#  endif  /* MAP_FAILED */# endif /* HAVE_SYS_MMAN_H */#endif /* ONCORE_SHMEM_STATUS */#ifdef HAVE_PPSAPI# include "ppsapi_timepps.h"#endif#ifdef HAVE_SYS_SIO_H# include <sys/sio.h>#endif#ifdef HAVE_SYS_TERMIOS_H# include <sys/termios.h>#endifenum receive_state {	ONCORE_NO_IDEA,	ONCORE_CHECK_ID,	ONCORE_CHECK_CHAN,	ONCORE_HAVE_CHAN,	ONCORE_RESET_SENT,	ONCORE_TEST_SENT,	ONCORE_INIT,	ONCORE_ALMANAC,	ONCORE_RUN};enum site_survey_state {	ONCORE_SS_UNKNOWN,	ONCORE_SS_TESTING,	ONCORE_SS_HW,	ONCORE_SS_SW,	ONCORE_SS_DONE};enum antenna_state {      ONCORE_ANTENNA_UNKNOWN = -1,      ONCORE_ANTENNA_OK      =	0,      ONCORE_ANTENNA_OC      =	1,      ONCORE_ANTENNA_UC      =	2,      ONCORE_ANTENNA_NV      =	3};/* Model Name, derived from the @@Cj message. * Used to initialize some variables. */enum oncore_model {	ONCORE_BASIC,	ONCORE_PVT6,	ONCORE_VP,	ONCORE_UT,	ONCORE_UTPLUS,	ONCORE_GT,	ONCORE_GTPLUS,	ONCORE_SL,	ONCORE_M12,	ONCORE_UNKNOWN};/* the bits that describe these properties are in the same place * on the VP/UT, but have moved on the M12.  As such we extract * them, and use them from this struct. * */struct RSM {	u_char	posn0D;	u_char	posn2D;	u_char	posn3D;	u_char	bad_almanac;	u_char	bad_fix;};/* It is possible to test the VP/UT each cycle (@@Ea or equivalent) to * see what mode it is in.  The bits on the M12 are multiplexed with * other messages, so we have to 'keep' the last known mode here. */enum posn_mode {	MODE_UNKNOWN,	MODE_0D,	MODE_2D,	MODE_3D};struct instance {	int	unit;		/* 127.127.30.unit */	struct	refclockproc *pp;	struct	peer *peer;	int	ttyfd;		/* TTY file descriptor */	int	ppsfd;		/* PPS file descriptor */	int	shmemfd;	/* Status shm descriptor */	pps_handle_t pps_h;	pps_params_t pps_p;	enum receive_state o_state;		/* Receive state */	enum posn_mode mode;			/* 0D, 2D, 3D */	enum site_survey_state site_survey;	/* Site Survey state */	enum antenna_state ant_state;		/* antenna state */	int	Bj_day;	u_long	delay;		/* ns */	long	offset; 	/* ns */	u_char	*shmem;	char	*shmem_fname;	u_int	shmem_Cb;	u_int	shmem_Ba;	u_int	shmem_Ea;	u_int	shmem_Ha;	u_char	shmem_reset;	u_char	shmem_Posn;	u_char	shmem_bad_Ea;	u_char	almanac_from_shmem;	double	ss_lat;	double	ss_long;	double	ss_ht;	double	dH;	int	ss_count;	u_char	posn_set;	enum oncore_model model;	u_int	version;	u_int	revision;	u_char	chan;		/* 6 for PVT6 or BASIC, 8 for UT/VP, 12 for m12, 0 if unknown */	s_char	traim;		/* do we have traim? yes UT/VP, M12+T, no BASIC, GT, M12, -1 unknown, 0 no, +1 yes */				/* the following 7 are all timing counters */	u_char	traim_delay;	/* seconds counter, waiting for reply */	u_char	count;		/* cycles thru Ea before starting */	u_char	count1; 	/* cycles thru Ea after SS_TESTING, waiting for SS_HW */	u_char	count2; 	/* cycles thru Ea after count, to check for @@Ea */	u_char	count3; 	/* cycles thru Ea checking for # channels */	u_char	count4; 	/* cycles thru leap after Gj to issue Bj */	u_char	pollcnt;	u_char	timeout;	/* count to retry Cj after Fa self-test */	struct	RSM rsm;	/* bits extracted from Receiver Status Msg in @@Ea */	u_char	printed;	u_char	polled;	u_long	ev_serial;	int	Rcvptr;	u_char	Rcvbuf[500];	u_char	BEHa[160];	/* Ba, Ea or Ha */	u_char	BEHn[80];	/* Bn , En , or Hn */	u_char	Cj[300];	u_char	Ag;		/* Satellite mask angle */	u_char	saw_At;	u_char	saw_Ay;	u_char	saw_Az;	s_char	saw_Gj;	u_char	have_dH;	u_char	init_type;	s_char	saw_tooth;	s_char	chan_in;	/* chan number from INPUT, will always use it */	u_char	chan_id;	/* chan number determined from part number */	u_char	chan_ck;	/* chan number determined by sending commands to hardware */	s_char	traim_in;	/* TRAIM from INPUT, will always use ON/OFF specified */	s_char	traim_id;	/* TRAIM determined from part number */	u_char	traim_ck;	/* TRAIM determined by sending commands to hardware */	u_char	once;		/* one pass code at top of BaEaHa */	s_char	assert;	u_char	hardpps;};#define rcvbuf	instance->Rcvbuf#define rcvptr	instance->Rcvptrstatic	int	oncore_start	      P((int, struct peer *));static	void	oncore_poll	      P((int, struct peer *));static	void	oncore_shutdown       P((int, struct peer *));static	void	oncore_consume	      P((struct instance *));static	void	oncore_read_config    P((struct instance *));static	void	oncore_receive	      P((struct recvbuf *));static	int	oncore_ppsapi	      P((struct instance *));static	void	oncore_get_timestamp  P((struct instance *, long, long));static	void	oncore_init_shmem     P((struct instance *));static	void	oncore_antenna_report P((struct instance *, enum antenna_state));static	void	oncore_chan_test      P((struct instance *));static	void	oncore_check_almanac  P((struct instance *));static	void	oncore_check_antenna  P((struct instance *));static	void	oncore_check_leap_sec P((struct instance *));static	int	oncore_checksum_ok    P((u_char *, int));static	void	oncore_compute_dH     P((struct instance *));static	void	oncore_load_almanac   P((struct instance *));static	void	oncore_print_Cb       P((struct instance *, u_char *));/* static  void    oncore_print_array	 P((u_char *, int));	*/static	void	oncore_print_posn     P((struct instance *));static	void	oncore_sendmsg	      P((int, u_char *, size_t));static	void	oncore_set_posn       P((struct instance *));static	void	oncore_set_traim      P((struct instance *));static	void	oncore_shmem_get_3D   P((struct instance *));static	void	oncore_ss	      P((struct instance *));static	int	oncore_wait_almanac   P((struct instance *));static	void	oncore_msg_any	   P((struct instance *, u_char *, size_t, int));static	void	oncore_msg_Adef    P((struct instance *, u_char *, size_t));static	void	oncore_msg_Ag	   P((struct instance *, u_char *, size_t));static	void	oncore_msg_As	   P((struct instance *, u_char *, size_t));static	void	oncore_msg_At	   P((struct instance *, u_char *, size_t));static	void	oncore_msg_Ay	   P((struct instance *, u_char *, size_t));static	void	oncore_msg_Az	   P((struct instance *, u_char *, size_t));static	void	oncore_msg_BaEaHa  P((struct instance *, u_char *, size_t));static	void	oncore_msg_Bd	   P((struct instance *, u_char *, size_t));static	void	oncore_msg_Bj	   P((struct instance *, u_char *, size_t));static	void	oncore_msg_BnEnHn  P((struct instance *, u_char *, size_t));static	void	oncore_msg_CaFaIa  P((struct instance *, u_char *, size_t));static	void	oncore_msg_Cb	   P((struct instance *, u_char *, size_t));static	void	oncore_msg_Cf	   P((struct instance *, u_char *, size_t));static	void	oncore_msg_Cj	   P((struct instance *, u_char *, size_t));static	void	oncore_msg_Cj_id   P((struct instance *, u_char *, size_t));static	void	oncore_msg_Cj_init P((struct instance *, u_char *, size_t));static	void	oncore_msg_Ga	   P((struct instance *, u_char *, size_t));static	void	oncore_msg_Gb	   P((struct instance *, u_char *, size_t));static	void	oncore_msg_Gj	   P((struct instance *, u_char *, size_t));static	void	oncore_msg_Sz	   P((struct instance *, u_char *, size_t));struct	refclock refclock_oncore = {	oncore_start,		/* start up driver */	oncore_shutdown,	/* shut down driver */	oncore_poll,		/* transmit poll message */	noentry,		/* not used */	noentry,		/* not used */	noentry,		/* not used */	NOFLAGS 		/* not used */};/* * Understanding the next bit here is not easy unless you have a manual * for the the various Oncore Models. */static struct msg_desc {	const char	flag[3];	const int	len;	void		(*handler) P((struct instance *, u_char *, size_t));	const char	*fmt;	int		shmem;} oncore_messages[] = {			/* Ea and En first since they're most common */	{ "Ea",  76,    oncore_msg_BaEaHa, "mdyyhmsffffaaaaoooohhhhmmmmvvhhddtntimsdimsdimsdimsdimsdimsdimsdimsdsC" },	{ "Ba",  68,    oncore_msg_BaEaHa, "mdyyhmsffffaaaaoooohhhhmmmmvvhhddtntimsdimsdimsdimsdimsdimsdsC" },	{ "Ha", 154,    oncore_msg_BaEaHa, "mdyyhmsffffaaaaoooohhhhmmmmaaaaoooohhhhmmmmVVvvhhddntimsiddimsiddimsiddimsiddimsiddimsiddimsiddimsiddimsiddimsiddimsiddimsiddssrrccooooTTushmvvvvvvC" },	{ "Bn",  59,    oncore_msg_BnEnHn, "otaapxxxxxxxxxxpysreensffffsffffsffffsffffsffffsffffC" },	{ "En",  69,    oncore_msg_BnEnHn, "otaapxxxxxxxxxxpysreensffffsffffsffffsffffsffffsffffsffffsffffC" },	{ "Hn",  78,    oncore_msg_BnEnHn, "" },	{ "Ab",  10,    0,                 "" },	{ "Ac",  11,    0,                 "" },	{ "Ad",  11,    oncore_msg_Adef,   "" },	{ "Ae",  11,    oncore_msg_Adef,   "" },	{ "Af",  15,    oncore_msg_Adef,   "" },	{ "Ag",   8,    oncore_msg_Ag,     "" }, /* Satellite mask angle */	{ "As",  20,    oncore_msg_As,     "" },	{ "At",   8,    oncore_msg_At,     "" },	{ "Au",  12,    0,                 "" },	{ "Av",   8,    0,                 "" },	{ "Aw",   8,    0,                 "" },	{ "Ay",  11,    oncore_msg_Ay,     "" },	{ "Az",  11,    oncore_msg_Az,     "" },	{ "AB",   8,    0,                 "" },	{ "Bb",  92,    0,                 "" },	{ "Bd",  23,    oncore_msg_Bd,     "" },	{ "Bj",   8,    oncore_msg_Bj,     "" },	{ "Ca",   9,    oncore_msg_CaFaIa, "" },	{ "Cb",  33,    oncore_msg_Cb,     "" },	{ "Cf",   7,    oncore_msg_Cf,     "" },	{ "Cg",   8,    0,                 "" },	{ "Ch",   9,    0,                 "" },	{ "Cj", 294,    oncore_msg_Cj,     "" },	{ "Ek",  71,    0,                 "" },	{ "Fa",   9,    oncore_msg_CaFaIa, "" },	{ "Ga",  20,    oncore_msg_Ga,     "" },	{ "Gb",  17,    oncore_msg_Gb,     "" },	{ "Gc",   8,    0,                 "" },	{ "Gd",   8,    0,                 "" },	{ "Ge",   8,    0,                 "" },	{ "Gj",  21,    oncore_msg_Gj,     "" },	{ "Ia",  10,    oncore_msg_CaFaIa, "" },	{ "Sz",   8,    oncore_msg_Sz,     "" },	{ {0},	  7,	0,		   "" }};static u_char oncore_cmd_Aa[]  = { 'A', 'a', 0, 0, 0 }; 			    /* 6/8	Time of Day				*/static u_char oncore_cmd_Ab[]  = { 'A', 'b', 0, 0, 0 }; 			    /* 6/8	GMT Correction				*/static u_char oncore_cmd_AB[]  = { 'A', 'B', 4 };				    /* VP	Application Type: Static		*/static u_char oncore_cmd_Ac[]  = { 'A', 'c', 0, 0, 0, 0 };			    /* 6/8	Date					*/static u_char oncore_cmd_Ad[]  = { 'A', 'd', 0,0,0,0 }; 			    /* 6/8	Latitude				*/static u_char oncore_cmd_Ae[]  = { 'A', 'e', 0,0,0,0 }; 			    /* 6/8	Longitude				*/static u_char oncore_cmd_Af[]  = { 'A', 'f', 0,0,0,0, 0 };			    /* 6/8	Height					*/static u_char oncore_cmd_Ag[]  = { 'A', 'g', 0 };				    /* 6/8/12	Satellite Mask Angle			*/static u_char oncore_cmd_Agx[] = { 'A', 'g', 0xff };				    /* 6/8/12	Satellite Mask Angle: read		*/static u_char oncore_cmd_As[]  = { 'A', 's', 0,0,0,0, 0,0,0,0, 0,0,0,0, 0 };	    /* 6/8/12	Posn Hold Parameters			*/static u_char oncore_cmd_Asx[] = { 'A', 's', 0x7f,0xff,0xff,0xff,		    /* 6/8/12	Posn Hold Readback			*/					     0x7f,0xff,0xff,0xff,		    /*		 on UT+ this doesnt work with 0xff	*/					     0x7f,0xff,0xff,0xff, 0xff };	    /*		 but does work with 0x7f (sigh).	*/static u_char oncore_cmd_At0[] = { 'A', 't', 0 };				    /* 6/8	Posn Hold: off				*/static u_char oncore_cmd_At1[] = { 'A', 't', 1 };				    /* 6/8	Posn Hold: on				*/static u_char oncore_cmd_At2[] = { 'A', 't', 2 };				    /* 6/8	Posn Hold: Start Site Survey		*/static u_char oncore_cmd_Atx[] = { 'A', 't', 0xff };				    /* 6/8	Posn Hold: Read Back			*/static u_char oncore_cmd_Au[]  = { 'A', 'u', 0,0,0,0, 0 };			    /* GT/M12	Altitude Hold Ht.			*/static u_char oncore_cmd_Av0[] = { 'A', 'v', 0 };				    /* VP/GT	Altitude Hold: off			*/static u_char oncore_cmd_Av1[] = { 'A', 'v', 1 };				    /* VP/GT	Altitude Hold: on			*/static u_char oncore_cmd_Aw[]  = { 'A', 'w', 1 };				    /* 6/8/12	UTC/GPS time selection			*/static u_char oncore_cmd_Ay[]  = { 'A', 'y', 0, 0, 0, 0 };			    /* Timing	1PPS time offset: set			*/static u_char oncore_cmd_Ayx[] = { 'A', 'y', 0xff, 0xff, 0xff, 0xff };		    /* Timing	1PPS time offset: Read			*/

⌨️ 快捷键说明

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