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

📄 refclock_mx4200.c

📁 网络时间协议NTP 源码 版本v4.2.0b 该源码用于linux平台下
💻 C
📖 第 1 页 / 共 3 页
字号:
	/*	 * "000" Initialization/Mode Control - Part A	 * Fix to our averaged position.	 */	if (up->central_meridian != NOT_INITIALIZED) {		up->avg_lon += up->central_meridian;		if (up->avg_lon < -180.0) up->avg_lon += 360.0;		if (up->avg_lon >  180.0) up->avg_lon -= 360.0;	}	if (up->avg_lat >= 0.0) {		lat = up->avg_lat;		nsc = 'N';	} else {		lat = up->avg_lat * (-1.0);		nsc = 'S';	}	if (up->avg_lon >= 0.0) {		lon = up->avg_lon;		ewc = 'E';	} else {		lon = up->avg_lon * (-1.0);		ewc = 'W';	}	alt = up->avg_alt;	minute = (lat - (double)(int)lat) * 60.0;	sprintf(lats,"%02d%02.4f", (int)lat, minute);	minute = (lon - (double)(int)lon) * 60.0;	sprintf(lons,"%03d%02.4f", (int)lon, minute);	mx4200_send(peer, "%s,%03d,,,,,%s,%c,%s,%c,%.2f,%d", pmvxg,	    PMVXG_S_INITMODEA,	    /* day of month */	    /* month of year */	    /* year */	    /* gmt */	    lats,	/* latitude   DDMM.MMMM */	    nsc,	/* north/south */	    lons,	/* longitude DDDMM.MMMM */	    ewc,	/* east/west */	    alt,	/* Altitude */	    1);		/* Altitude Reference (0=WGS84 ellipsoid, 1=MSL geoid)*/	msyslog(LOG_DEBUG,	    "mx4200: reconfig to fixed location: %s %c, %s %c, %.2f m",		lats, nsc, lons, ewc, alt );}/* * mx4200_poll - mx4200 watchdog routine */static voidmx4200_poll(	int unit,	struct peer *peer	){	register struct mx4200unit *up;	struct refclockproc *pp;	pp = peer->procptr;	up = (struct mx4200unit *)pp->unitptr;	/*	 * You don't need to poll this clock.  It puts out timecodes	 * once per second.  If asked for a timestamp, take note.	 * The next time a timecode comes in, it will be fed back.	 */	/*	 * If we haven't had a response in a while, reset the receiver.	 */	if (up->pollcnt > 0) {		up->pollcnt--;	} else {		refclock_report(peer, CEVNT_TIMEOUT);		/*		 * Request a "000" status message which should trigger a		 * reconfig		 */		mx4200_send(peer, "%s,%03d",		    "CDGPQ",		/* query from CDU to GPS */		    PMVXG_D_STATUS);	/* label of desired sentence */	}	/*	 * polled every 64 seconds. Ask mx4200_receive to hand in	 * a timestamp.	 */	up->polled = 1;	pp->polls++;	/*	 * Output receiver status information.	 */	if ((up->log_time > 0) && (current_time > up->log_time)) {		up->log_time = 0;		/*		 * Output the following messages once, for debugging.		 *    "004" Mode Data		 *    "523" Time Recovery Parameters		 */		mx4200_send(peer, "%s,%03d", "CDGPQ", PMVXG_D_MODEDATA);		mx4200_send(peer, "%s,%03d", "CDGPQ", PMVXG_D_TRECOVUSEAGE);	}}static char char2hex[] = "0123456789ABCDEF";/* * mx4200_receive - receive gps data */static voidmx4200_receive(	struct recvbuf *rbufp	){	register struct mx4200unit *up;	struct refclockproc *pp;	struct peer *peer;	char *cp;	int sentence_type;	u_char ck;	/*	 * Initialize pointers and read the timecode and timestamp.	 */	peer = (struct peer *)rbufp->recv_srcclock;	pp = peer->procptr;	up = (struct mx4200unit *)pp->unitptr;	/*	 * If operating mode has been changed, then reinitialize the receiver	 * before doing anything else.	 */	if ((pp->sloppyclockflag & CLK_FLAG2) !=	    (up->sloppyclockflag & CLK_FLAG2)) {		up->sloppyclockflag = pp->sloppyclockflag;		mx4200_debug(peer,		    "mx4200_receive: mode switch: reset receiver\n");		mx4200_config(peer);		return;	}	up->sloppyclockflag = pp->sloppyclockflag;	/*	 * Read clock output.  Automatically handles STREAMS, CLKLDISC.	 */	pp->lencode = refclock_gtlin(rbufp, pp->a_lastcode, BMAX, &pp->lastrec);	/*	 * There is a case where <cr><lf> generates 2 timestamps.	 */	if (pp->lencode == 0)		return;	up->pollcnt = 2;	pp->a_lastcode[pp->lencode] = '\0';	record_clock_stats(&peer->srcadr, pp->a_lastcode);	mx4200_debug(peer, "mx4200_receive: %d %s\n",		     pp->lencode, pp->a_lastcode);	/*	 * The structure of the control port sentences is based on the	 * NMEA-0183 Standard for interfacing Marine Electronics	 * Navigation Devices (Version 1.5)	 *	 *	$PMVXG,XXX, ....................*CK<cr><lf>	 *	 *		$	Sentence Start Identifier (reserved char)	 *			   (Start-of-Sentence Identifier)	 *		P	Special ID (Proprietary)	 *		MVX	Originator ID (Magnavox)	 *		G	Interface ID (GPS)	 *		,	Field Delimiters (reserved char)	 *		XXX	Sentence Type	 *		......	Data	 *		*	Checksum Field Delimiter (reserved char)	 *		CK	Checksum	 *		<cr><lf> Carriage-Return/Line Feed (reserved chars)	 *			   (End-of-Sentence Identifier)	 *	 * Reject if any important landmarks are missing.	 */	cp = pp->a_lastcode + pp->lencode - 3;	if (cp < pp->a_lastcode || *pp->a_lastcode != '$' || cp[0] != '*' ) {		mx4200_debug(peer, "mx4200_receive: bad format\n");		refclock_report(peer, CEVNT_BADREPLY);		return;	}	/*	 * Check and discard the checksum	 */	ck = mx4200_cksum(&pp->a_lastcode[1], pp->lencode - 4);	if (char2hex[ck >> 4] != cp[1] || char2hex[ck & 0xf] != cp[2]) {		mx4200_debug(peer, "mx4200_receive: bad checksum\n");		refclock_report(peer, CEVNT_BADREPLY);		return;	}	*cp = '\0';	/*	 * Get the sentence type.	 */	sentence_type = 0;	if ((cp = strchr(pp->a_lastcode, ',')) == NULL) {		mx4200_debug(peer, "mx4200_receive: no sentence\n");		refclock_report(peer, CEVNT_BADREPLY);		return;	}	cp++;	sentence_type = strtol(cp, &cp, 10);	/*	 * Process the sentence according to its type.	 */	switch (sentence_type) {	/*	 * "000" Status message	 */	case PMVXG_D_STATUS:		/*		 * XXX		 * Since we configure the receiver to not give us status		 * messages and since the receiver outputs status messages by		 * default after being reset to factory defaults when sent the		 * "$PMVXG,018,C\r\n" message, any status message we get		 * indicates the reciever needs to be initialized; thus, it is		 * not necessary to decode the status message.		 */		if ((cp = mx4200_parse_s(peer)) != NULL) {			mx4200_debug(peer,				     "mx4200_receive: status: %s\n", cp);		}		mx4200_debug(peer, "mx4200_receive: reset receiver\n");		mx4200_config(peer);		break;	/*	 * "021" Position, Height, Velocity message,	 *  if we are still averaging our position	 */	case PMVXG_D_PHV:		if (!up->known) {			/*			 * Parse the message, calculating our averaged position.			 */			if ((cp = mx4200_parse_p(peer)) != NULL) {				mx4200_debug(peer, "mx4200_receive: pos: %s\n", cp);				return;			}			mx4200_debug(peer,			    "mx4200_receive: position avg %f %.9f %.9f %.4f\n",			    up->N_fixes, up->avg_lat, up->avg_lon, up->avg_alt);			/*			 * Reinitialize as a reference station			 * if position is well known.			 */			if (current_time > up->clamp_time) {				up->known++;				mx4200_debug(peer, "mx4200_receive: reconfiguring!\n");				mx4200_ref(peer);			}		}		break;	/*	 * Print to the syslog:	 * "004" Mode Data	 * "030" Software Configuration	 * "523" Time Recovery Parameters Currently in Use	 */	case PMVXG_D_MODEDATA:	case PMVXG_D_SOFTCONF:	case PMVXG_D_TRECOVUSEAGE:		if ((cp = mx4200_parse_s(peer)) != NULL) {			mx4200_debug(peer,				     "mx4200_receive: multi-record: %s\n", cp);		}		break;	/*	 * "830" Time Recovery Results message	 */	case PMVXG_D_TRECOVOUT:		/*		 * Capture the last PPS signal.		 * Precision timestamp is returned in pp->lastrec		 */		if (mx4200_pps(peer) != NULL) {			mx4200_debug(peer, "mx4200_receive: pps failure\n");			refclock_report(peer, CEVNT_FAULT);			return;		}		/*		 * Parse the time recovery message, and keep the info		 * to print the pretty billboards.		 */		if ((cp = mx4200_parse_t(peer)) != NULL) {			mx4200_debug(peer, "mx4200_receive: time: %s\n", cp);			refclock_report(peer, CEVNT_BADREPLY);			return;		}		/*		 * Add the new sample to a median filter.		 */		if (!refclock_process(pp)) {			mx4200_debug(peer,"mx4200_receive: offset: %.6f\n",			    pp->offset);			refclock_report(peer, CEVNT_BADTIME);			return;		}		/*		 * The clock will blurt a timecode every second but we only		 * want one when polled.  If we havn't been polled, bail out.		 */		if (!up->polled)			return;		/*		 * Return offset and dispersion to control module.  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.		 */		mx4200_debug(peer, "mx4200_receive: process time: ");		mx4200_debug(peer, "%4d-%03d %02d:%02d:%02d at %s, %.6f\n",		    pp->year, pp->day, pp->hour, pp->minute, pp->second,		    prettydate(&pp->lastrec), pp->offset);		pp->lastref = pp->lastrec;		refclock_receive(peer);		/*		 * We have succeeded in answering the poll.		 * Turn off the flag and return		 */		up->polled = 0;		break;	/*	 * Ignore all other sentence types	 */	default:		break;	} /* switch (sentence_type) */	return;}/* * Parse a mx4200 time recovery message. Returns a string if error. * * A typical message looks like this.  Checksum has already been stripped. * *    $PMVXG,830,T,YYYY,MM,DD,HH:MM:SS,U,S,FFFFFF,PPPPP,BBBBBB,LL * *	Field	Field Contents *	-----	-------------- *		Block Label: $PMVXG *		Sentence Type: 830=Time Recovery Results *			This sentence is output approximately 1 second *			preceding the 1PPS output.  It indicates the *			exact time of the next pulse, whether or not the *			time mark will be valid (based on operator-specified *			error tolerance), the time to which the pulse is *			synchronized, the receiver operating mode, *			and the time error of the *last* 1PPS output. *	1  char Time Mark Valid: T=Valid, F=Not Valid *	2  int  Year: 1993- *	3  int  Month of Year: 1-12 *	4  int  Day of Month: 1-31 *	5  int  Time of Day: HH:MM:SS *	6  char Time Synchronization: U=UTC, G=GPS *	7  char Time Recovery Mode: D=Dynamic, S=Static, *			K=Known Position, N=No Time Recovery *	8  int  Oscillator Offset: The filter's estimate of the oscillator *			frequency error, in parts per billion (ppb). *	9  int  Time Mark Error: The computed error of the *last* pulse *			output, in nanoseconds. *	10 int  User Time Bias: Operator specified bias, in nanoseconds *	11 int  Leap Second Flag: Indicates that a leap second will *			occur.  This value is usually zero, except during *			the week prior to the leap second occurrence, when *			this value will be set to +1 or -1.  A value of *			+1 indicates that GPS time will be 1 second *			further ahead of UTC time. * */static char *mx4200_parse_t(	struct peer *peer	){	struct refclockproc *pp;	struct mx4200unit *up;	char   time_mark_valid, time_sync, op_mode;	int    sentence_type, valid;	int    year, day_of_year, month, day_of_month;	int    hour, minute, second, leapsec;	int    oscillator_offset, time_mark_error, time_bias;	pp = peer->procptr;	up = (struct mx4200unit *)pp->unitptr;	leapsec = 0;  /* Not all receivers output leap second warnings (!) */	sscanf(pp->a_lastcode,		"$PMVXG,%d,%c,%d,%d,%d,%d:%d:%d,%c,%c,%d,%d,%d,%d",		&sentence_type, &time_mark_valid, &year, &month, &day_of_month,		&hour, &minute, &second, &time_sync, &op_mode,		&oscillator_offset, &time_mark_error, &time_bias, &leapsec);	if (sentence_type != PMVXG_D_TRECOVOUT)		return ("wrong rec-type");	switch (time_mark_valid) {		case 'T':			valid = 1;			break;		case 'F':			valid = 0;			break;		default:			return ("bad pulse-valid");	}	switch (time_sync) {		case 'G':			return ("synchronized to GPS; should be UTC");		case 'U':			break; /* UTC -> ok */		default:			return ("not synchronized to UTC");	}	/*	 * Check for insane time (allow for possible leap seconds)	 */	if (second > 60 || minute > 59 || hour > 23 ||	    second <  0 || minute <  0 || hour <  0) {		mx4200_debug(peer,		    "mx4200_parse_t: bad time %02d:%02d:%02d",		    hour, minute, second);		if (leapsec != 0)			mx4200_debug(peer, " (leap %+d\n)", leapsec);		mx4200_debug(peer, "\n");		refclock_report(peer, CEVNT_BADTIME);		return ("bad time");	}	if ( second == 60 ) {		msyslog(LOG_DEBUG,		    "mx4200: leap second! %02d:%02d:%02d",		    hour, minute, second);	}	/*	 * Check for insane date	 * (Certainly can't be any year before this code was last altered!)	 */	if (day_of_month > 31 || month > 12 ||	    day_of_month <  1 || month <  1 || year < YEAR_LAST_MODIFIED) {		mx4200_debug(peer,		    "mx4200_parse_t: bad date (%4d-%02d-%02d)\n",		    year, month, day_of_month);		refclock_report(peer, CEVNT_BADDATE);		return ("bad date");	}	/*	 * Silly Hack for MX4200:	 * ASCII message is for *next* 1PPS signal, but we have the	 * timestamp for the *last* 1PPS signal.  So we have to subtract	 * a second.  Discard if we are on a month boundary to avoid	 * possible leap seconds and leap days.	 */	second--;	if (second < 0) {		second = 59;		minute--;		if (minute < 0) {			minute = 59;			hour--;			if (hour < 0) {				hour = 23;				day_of_month--;				if (day_of_month < 1) {					return ("sorry, month boundary");				}			}		}	}	/*	 * Calculate Julian date	 */	if (!(day_of_year = mx4200_jday(year, month, day_of_month))) {		mx4200_debug(peer,		    "mx4200_parse_t: bad julian date %d (%4d-%02d-%02d)\n",		    day_of_year, year, month, day_of_month);		refclock_report(peer, CEVNT_BADDATE);		return("invalid julian date");	}	/*	 * Setup leap second indicator	 */	switch (leapsec) {		case 0:			pp->leap = LEAP_NOWARNING;			break;		case 1:			pp->leap = LEAP_ADDSECOND;			break;		case -1:			pp->leap = LEAP_DELSECOND;			break;		default:			pp->leap = LEAP_NOTINSYNC;	}	/*	 * Any change to the leap second warning status?	 */	if (leapsec != up->last_leap ) {		msyslog(LOG_DEBUG,		    "mx4200: leap second warning: %d to %d (%d)",		    up->last_leap, leapsec, pp->leap);	}	up->last_leap = leapsec;	/*	 * Copy time data for billboard monitoring.	 */	pp->year   = year;	pp->day    = day_of_year;	pp->hour   = hour;	pp->minute = minute;

⌨️ 快捷键说明

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