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

📄 chutest.c

📁 网络时间协议NTP 源码 版本v4.2.0b 该源码用于linux平台下
💻 C
📖 第 1 页 / 共 2 页
字号:
 * to come out at 300 ms.  Thus, peer.distance in the CHU peer structure * is set to 290 ms and we compute delays which are at least 10 ms long. * The following are 290 ms and 10 ms expressed in u_fp format */#define	CHUDISTANCE	0x00004a3d#define	CHUBASEDELAY	0x0000028f/* * To compute a quality for the estimate (a pseudo delay) we add a * fixed 10 ms for each missing code in the minute and add to this * the sum of the differences between the remaining offsets and the * estimated sample offset. */#define	CHUDELAYPENALTY	0x0000028f/* * Other constant stuff */#define	CHUPRECISION	(-9)		/* what the heck */#define	CHUREFID	"CHU\0"/* * Default fudge factors */#define	DEFPROPDELAY	0x00624dd3	/* 0.0015 seconds, 1.5 ms */#define	DEFFILTFUDGE	0x000d1b71	/* 0.0002 seconds, 200 us *//* * Hacks to avoid excercising the multiplier.  I have no pride. */#define	MULBY10(x)	(((x)<<3) + ((x)<<1))#define	MULBY60(x)	(((x)<<6) - ((x)<<2))	/* watch overflow */#define	MULBY24(x)	(((x)<<4) + ((x)<<3))/* * Constants for use when multiplying by 0.1.  ZEROPTONE is 0.1 * as an l_fp fraction, NZPOBITS is the number of significant bits * in ZEROPTONE. */#define	ZEROPTONE	0x1999999a#define	NZPOBITS	29/* * The CHU table.  This gives the expected time of arrival of each * character after the on-time second and is computed as follows: * The CHU time code is sent at 300 bps.  Your average UART will * synchronize at the edge of the start bit and will consider the * character complete at the center of the first stop bit, i.e. * 0.031667 ms later.  Thus the expected time of each interrupt * is the start bit time plus 0.031667 seconds.  These times are * in chutable[].  To this we add such things as propagation delay * and delay fudge factor. */#define	CHARDELAY	0x081b4e80static u_long chutable[NCHUCHARS] = {	0x2147ae14 + CHARDELAY,		/* 0.130 (exactly) */	0x2ac08312 + CHARDELAY,		/* 0.167 (exactly) */	0x34395810 + CHARDELAY,		/* 0.204 (exactly) */	0x3db22d0e + CHARDELAY,		/* 0.241 (exactly) */	0x472b020c + CHARDELAY,		/* 0.278 (exactly) */	0x50a3d70a + CHARDELAY,		/* 0.315 (exactly) */	0x5a1cac08 + CHARDELAY,		/* 0.352 (exactly) */	0x63958106 + CHARDELAY,		/* 0.389 (exactly) */	0x6d0e5604 + CHARDELAY,		/* 0.426 (exactly) */	0x76872b02 + CHARDELAY,		/* 0.463 (exactly) */};/* * Keep the fudge factors separately so they can be set even * when no clock is configured. */static l_fp propagation_delay;static l_fp fudgefactor;static l_fp offset_fudge;/* * We keep track of the start of the year, watching for changes. * We also keep track of whether the year is a leap year or not. * All because stupid CHU doesn't include the year in the time code. */static u_long yearstart;/* * Imported from the timer module */extern u_long current_time;extern struct event timerqueue[];/* * Time conversion tables imported from the library */extern u_long ustotslo[];extern u_long ustotsmid[];extern u_long ustotshi[];/* * init_chu - initialize internal chu driver data */voidinit_chu(void){	/*	 * Initialize fudge factors to default.	 */	propagation_delay.l_ui = 0;	propagation_delay.l_uf = DEFPROPDELAY;	fudgefactor.l_ui = 0;	fudgefactor.l_uf = DEFFILTFUDGE;	offset_fudge = propagation_delay;	L_ADD(&offset_fudge, &fudgefactor);	yearstart = 0;}voidchufilter(	struct chucode *chuc,	l_fp *rtime	){	register int i;	register u_long date_ui;	register u_long tmp;	register u_char *code;	int isneg;	int imin;	int imax;	u_long reftime;	l_fp off[NCHUCHARS];	l_fp ts;	int day, hour, minute, second;	static u_char lastcode[NCHUCHARS];	extern u_long calyearstart();	extern char *mfptoa();	void chu_process();	extern char *prettydate();	/*	 * We'll skip the checks made in the kernel, but assume they've	 * been done.  This means that all characters are BCD and	 * the intercharacter spacing isn't unreasonable.	 */	/*	 * print the code	 */	for (i = 0; i < NCHUCHARS; i++)	    printf("%c%c", (chuc->codechars[i] & 0xf) + '0',		   ((chuc->codechars[i]>>4) & 0xf) + '0');	printf("\n");	/*	 * Format check.  Make sure the two halves match.	 */	for (i = 0; i < NCHUCHARS/2; i++)	    if (chuc->codechars[i] != chuc->codechars[i+(NCHUCHARS/2)]) {		    (void) printf("Bad format, halves don't match\n");		    return;	    }		/*	 * Break out the code into the BCD nibbles.  Only need to fiddle	 * with the first half since both are identical.  Note the first	 * BCD character is the low order nibble, the second the high order.	 */	code = lastcode;	for (i = 0; i < NCHUCHARS/2; i++) {		*code++ = chuc->codechars[i] & 0xf;		*code++ = (chuc->codechars[i] >> 4) & 0xf;	}	/*	 * If the first nibble isn't a 6, we're up the creek	 */	code = lastcode;	if (*code++ != 6) {		(void) printf("Bad format, no 6 at start\n");		return;	}	/*	 * Collect the day, the hour, the minute and the second.	 */	day = *code++;	day = MULBY10(day) + *code++;	day = MULBY10(day) + *code++;	hour = *code++;	hour = MULBY10(hour) + *code++;	minute = *code++;	minute = MULBY10(minute) + *code++;	second = *code++;	second = MULBY10(second) + *code++;	/*	 * Sanity check the day and time.  Note that this	 * only occurs on the 31st through the 39th second	 * of the minute.	 */	if (day < 1 || day > 366	    || hour > 23 || minute > 59	    || second < 31 || second > 39) {		(void) printf("Failed date sanity check: %d %d %d %d\n",			      day, hour, minute, second);		return;	}	/*	 * Compute seconds into the year.	 */	tmp = (u_long)(MULBY24((day-1)) + hour);	/* hours */	tmp = MULBY60(tmp) + (u_long)minute;		/* minutes */	tmp = MULBY60(tmp) + (u_long)second;		/* seconds */	/*	 * Now the fun begins.  We demand that the received time code	 * be within CLOCK_WAYTOOBIG of the receive timestamp, but	 * there is uncertainty about the year the timestamp is in.	 * Use the current year start for the first check, this should	 * work most of the time.	 */	date_ui = tmp + yearstart;	if (date_ui < (rtime->l_ui + CLOCK_WAYTOOBIG)	    && date_ui > (rtime->l_ui - CLOCK_WAYTOOBIG))	    goto codeokay;	/* looks good */	/*	 * Trouble.  Next check is to see if the year rolled over and, if	 * so, try again with the new year's start.	 */	date_ui = calyearstart(rtime->l_ui);	if (date_ui != yearstart) {		yearstart = date_ui;		date_ui += tmp;		(void) printf("time %u, code %u, difference %d\n",			      date_ui, rtime->l_ui, (long)date_ui-(long)rtime->l_ui);		if (date_ui < (rtime->l_ui + CLOCK_WAYTOOBIG)		    && date_ui > (rtime->l_ui - CLOCK_WAYTOOBIG))		    goto codeokay;	/* okay this time */	}	ts.l_uf = 0;	ts.l_ui = yearstart;	printf("yearstart %s\n", prettydate(&ts));	printf("received %s\n", prettydate(rtime));	ts.l_ui = date_ui;	printf("date_ui %s\n", prettydate(&ts));	/*	 * Here we know the year start matches the current system	 * time.  One remaining possibility is that the time code	 * is in the year previous to that of the system time.  This	 * is only worth checking if the receive timestamp is less	 * than CLOCK_WAYTOOBIG seconds into the new year.	 */	if ((rtime->l_ui - yearstart) < CLOCK_WAYTOOBIG) {		date_ui = tmp + calyearstart(yearstart - CLOCK_WAYTOOBIG);		if ((rtime->l_ui - date_ui) < CLOCK_WAYTOOBIG)		    goto codeokay;	}	/*	 * One last possibility is that the time stamp is in the year	 * following the year the system is in.  Try this one before	 * giving up.	 */	date_ui = tmp + calyearstart(yearstart + (400*24*60*60)); /* 400 days */	if ((date_ui - rtime->l_ui) >= CLOCK_WAYTOOBIG) {		printf("Date hopelessly off\n");		return;		/* hopeless, let it sync to other peers */	}    codeokay:	reftime = date_ui;	/*	 * We've now got the integral seconds part of the time code (we hope).	 * The fractional part comes from the table.  We next compute	 * the offsets for each character.	 */	for (i = 0; i < NCHUCHARS; i++) {		register u_long tmp2;		off[i].l_ui = date_ui;		off[i].l_uf = chutable[i];		tmp = chuc->codetimes[i].tv_sec + JAN_1970;		TVUTOTSF(chuc->codetimes[i].tv_usec, tmp2);		M_SUB(off[i].l_ui, off[i].l_uf, tmp, tmp2);	}	/*	 * Here is a *big* problem.  What one would normally	 * do here on a machine with lots of clock bits (say	 * a Vax or the gizmo board) is pick the most positive	 * offset and the estimate, since this is the one that	 * is most likely suffered the smallest interrupt delay.	 * The trouble is that the low order clock bit on an IBM	 * RT, which is the machine I had in mind when doing this,	 * ticks at just under the millisecond mark.  This isn't	 * precise enough.  What we can do to improve this is to	 * average all 10 samples and rely on the second level	 * filtering to pick the least delayed estimate.  Trouble	 * is, this means we have to divide a 64 bit fixed point	 * number by 10, a procedure which really sucks.  Oh, well.	 * First compute the sum.	 */	date_ui = 0;	tmp = 0;	for (i = 0; i < NCHUCHARS; i++)	    M_ADD(date_ui, tmp, off[i].l_ui, off[i].l_uf);	if (M_ISNEG(date_ui, tmp))	    isneg = 1;	else	    isneg = 0;		/*	 * Here is a multiply-by-0.1 optimization that should apply	 * just about everywhere.  If the magnitude of the sum	 * is less than 9 we don't have to worry about overflow	 * out of a 64 bit product, even after rounding.	 */	if (date_ui < 9 || date_ui > 0xfffffff7) {		register u_long prod_ui;		register u_long prod_uf;		prod_ui = prod_uf = 0;		/*		 * This code knows the low order bit in 0.1 is zero		 */		for (i = 1; i < NZPOBITS; i++) {			M_LSHIFT(date_ui, tmp);			if (ZEROPTONE & (1<<i))			    M_ADD(prod_ui, prod_uf, date_ui, tmp);		}		/*		 * Done, round it correctly.  Prod_ui contains the		 * fraction.		 */		if (prod_uf & 0x80000000)		    prod_ui++;		if (isneg)		    date_ui = 0xffffffff;		else		    date_ui = 0;		tmp = prod_ui;		/*		 * date_ui is integral part, tmp is fraction.		 */	} else {		register u_long prod_ovr;		register u_long prod_ui;		register u_long prod_uf;		register u_long highbits;		prod_ovr = prod_ui = prod_uf = 0;		if (isneg)		    highbits = 0xffffffff;	/* sign extend */		else		    highbits = 0;		/*		 * This code knows the low order bit in 0.1 is zero		 */		for (i = 1; i < NZPOBITS; i++) {			M_LSHIFT3(highbits, date_ui, tmp);			if (ZEROPTONE & (1<<i))			    M_ADD3(prod_ovr, prod_uf, prod_ui,				   highbits, date_ui, tmp);		}		if (prod_uf & 0x80000000)		    M_ADDUF(prod_ovr, prod_ui, (u_long)1);		date_ui = prod_ovr;		tmp = prod_ui;	}	/*	 * At this point we have the mean offset, with the integral	 * part in date_ui and the fractional part in tmp.  Store	 * it in the structure.	 */	/*	 * Add in fudge factor.	 */	M_ADD(date_ui, tmp, offset_fudge.l_ui, offset_fudge.l_uf);	/*	 * Find the minimun and maximum offset	 */	imin = imax = 0;	for (i = 1; i < NCHUCHARS; i++) {		if (L_ISGEQ(&off[i], &off[imax])) {			imax = i;		} else if (L_ISGEQ(&off[imin], &off[i])) {			imin = i;		}	}	L_ADD(&off[imin], &offset_fudge);	if (imin != imax)	    L_ADD(&off[imax], &offset_fudge);	(void) printf("mean %s, min %s, max %s\n",		      mfptoa(date_ui, tmp, 8), lfptoa(&off[imin], 8),		      lfptoa(&off[imax], 8));}

⌨️ 快捷键说明

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