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

📄 refclock_wwv.c

📁 网络时间协议NTP 源码 版本v4.2.0b 该源码用于linux平台下
💻 C
📖 第 1 页 / 共 5 页
字号:
	 * but as early as possible if the second epoch is not exact.	 */	if (up->rphase == 15 * MS)		sigmin = sigzer = sigone = up->irig;	/*	 * The zero bit is defined as the maximum data signal over the	 * interval 190-210 ms. Keep this around until the end of the	 * second.	 */	else if (up->rphase >= 190 * MS && up->rphase < 210 * MS &&	    up->irig > sigzer) 		sigzer = up->irig;	/*	 * The one bit is defined as the maximum data signal over the	 * interval 490-510 ms. Keep this around until the end of the	 * second.	 */	else if (up->rphase >= 490 * MS && up->rphase < 510 * MS &&	    up->irig > sigone)		sigone = up->irig;	/*	 * At the end of the second crank the clock state machine and	 * adjust the codec gain. Note the epoch is buffered from the	 * center of the second in order to avoid jitter while the	 * seconds synch is diddling the epoch. Then, determine the true	 * offset and update the median filter in the driver interface.	 *	 * Use the energy as the noise to compute the SNR for the pulse.	 * This gives a better measurement than the beginning of the	 * second, especially when returning from the probe channel.	 * This gives a guard time of 30 ms from the decay of the	 * longest pulse to the rise of the next pulse.	 */	up->rphase++;	if (up->mphase % SECOND == up->repoch) {		up->status &= ~(DGATE | BGATE);		engmin = sqrt(up->irig * up->irig + up->qrig *		    up->qrig);		up->datsig = engmax;		up->datsnr = wwv_snr(engmax, engmin);		/*		 * If the amplitude or SNR is below threshold, average a		 * 0 in the the integrators; otherwise, average the		 * bipolar signal. This is done to avoid noise polution.		 */		if (engmax < DTHR || up->datsnr < DSNR) {			up->status |= DGATE;			wwv_rsec(peer, 0);		} else {			sigzer -= sigone;			sigone -= sigmin;			wwv_rsec(peer, sigone - sigzer);		}		if (up->status & (DGATE | BGATE))			up->errcnt++;		if (up->errcnt > MAXERR)			up->alarm |= LOWERR;		wwv_gain(peer);		up->rphase = 0;	}}/* * wwv_rsec - process receiver second * * This routine is called at the end of each receiver second to * implement the per-second state machine. The machine assembles BCD * digit bits, decodes miscellaneous bits and dances the leap seconds. * * Normally, the minute has 60 seconds numbered 0-59. If the leap * warning bit is set, the last minute (1439) of 30 June (day 181 or 182 * for leap years) or 31 December (day 365 or 366 for leap years) is * augmented by one second numbered 60. This is accomplished by * extending the minute interval by one second and teaching the state * machine to ignore it. */static voidwwv_rsec(	struct peer *peer,	/* peer structure pointer */	double bit	){	static int iniflg;	/* initialization flag */	static double bcddld[4]; /* BCD data bits */	static double bitvec[61]; /* bit integrator for misc bits */	struct refclockproc *pp;	struct wwvunit *up;	struct chan *cp;	struct sync *sp, *rp;	char	tbuf[80];	/* monitor buffer */	int	sw, arg, nsec;	pp = peer->procptr;	up = (struct wwvunit *)pp->unitptr;	if (!iniflg) {		iniflg = 1;		memset((char *)bitvec, 0, sizeof(bitvec));	}	/*	 * The bit represents the probability of a hit on zero (negative	 * values), a hit on one (positive values) or a miss (zero	 * value). The likelihood vector is the exponential average of	 * these probabilities. Only the bits of this vector	 * corresponding to the miscellaneous bits of the timecode are	 * used, but it's easier to do them all. After that, crank the	 * seconds state machine.	 */	nsec = up->rsec;	up->rsec++;	bitvec[nsec] += (bit - bitvec[nsec]) / TCONST;	sw = progx[nsec].sw;	arg = progx[nsec].arg;	/*	 * The minute state machine. Fly off to a particular section as	 * directed by the transition matrix and second number.	 */	switch (sw) {	/*	 * Ignore this second.	 */	case IDLE:			/* 9, 45-49 */		break;	/*	 * Probe channel stuff	 *	 * The WWV/H format contains data pulses in second 59 (position	 * identifier) and second 1, but not in second 0. The minute	 * sync pulse is contained in second 0. second 0. At the end of	 * second 58 QSY to the probe channel, which rotates in turn	 * over all WWV/H frequencies. At the end of second 0 measure	 * the minute sync pulse. At the end of second 1 measure the	 * data pulse and QSY back to the data channel. Note that the	 * seconds numbering here applies to the end of the second, so	 * appears one second earlier than the clock displayed on the	 * radio itself.	 *	 * At the end of second 0 save the minute sync pulse peak	 * amplitude previously latched at 800 ms. 	 */	case SYNC2:			/* 0 */		cp = &up->mitig[up->achan];		cp->wwv.synmax = cp->wwv.syneng;		cp->wwvh.synmax = cp->wwvh.syneng;		break;	/*	 * At the end of second 1 measure the minute sync pulse	 * minimum amplitude and calculate the SNR. If the minute sync	 * pulse and SNR are above threshold and the data pulse	 * amplitude and SNR are above thresold and, shift a 1 into the	 * station reachability register; otherwise, shift a 0. The	 * number of 1 bits in the last six intervals is a component of	 * the channel metric computed by the mitigation routine.	 * Finally, QSY back to the data channel.	 */	case SYNC3:			/* 1 */		cp = &up->mitig[up->achan];		/*		 * WWV station		 */		sp = &cp->wwv;		sp->synsnr = wwv_snr(sp->synmax, sp->syneng);		sp->reach <<= 1;		if (sp->reach & (1 << AMAX))			sp->count--;		if (sp->synmax >= QTHR && sp->synsnr >= QSNR &&		    ~(up->status & (DGATE | BGATE))) {			sp->reach |= 1;			sp->count++;		}		sp->metric = wwv_metric(sp);		/*		 * WWVH station		 */		rp = &cp->wwvh;		rp->synsnr = wwv_snr(rp->synmax, rp->syneng);		rp->reach <<= 1;		if (rp->reach & (1 << AMAX))			rp->count--;		if (rp->synmax >= QTHR && rp->synsnr >= QSNR &&		    ~(up->status & (DGATE | BGATE))) {			rp->reach |= 1;			rp->count++;		}		rp->metric = wwv_metric(rp);		if (pp->sloppyclockflag & CLK_FLAG4) {			sprintf(tbuf,			    "wwv5 %04x %3d %4d %.0f/%.1f %.0f/%.1f %s %04x %.0f %.0f/%.1f %s %04x %.0f %.0f/%.1f",			    up->status, up->gain, up->yepoch,			    up->epomax, up->eposnr, up->datsig,			    up->datsnr,			    sp->refid, sp->reach & 0xffff,			    sp->metric, sp->synmax, sp->synsnr,			    rp->refid, rp->reach & 0xffff,			    rp->metric, rp->synmax, rp->synsnr);			record_clock_stats(&peer->srcadr, tbuf);#ifdef DEBUG			if (debug)				printf("%s\n", tbuf);#endif /* DEBUG */		}		up->errcnt = up->digcnt = up->alarm = 0;		/*		 * We now begin the minute scan. Before first		 * synchronizing to a station, reset and step to the		 * next channel immediately if no station has been		 * heard. Reset and step after the DATA timeout (4 min)		 * if a station has been heard, but too few good data		 * bits have been found. In any case, reset and step		 * after the SYNCH timeout (30 min).		 *		 * After synchronizing to a station, reset and step		 * after the PANIC timeout (2 days).		 */		if (!(up->status & INSYNC)) {			if (!wwv_newchan(peer)) {				wwv_newgame(peer, DCHAN);				return;			}			if (up->watch > DATA && !(up->status & DSYNC)) {				wwv_newgame(peer, DCHAN);				return;			}			if (up->watch > SYNCH) {				wwv_newgame(peer, DCHAN);				return;			}		} else {			wwv_newchan(peer);			if (up->watch > PANIC) {				wwv_newgame(peer, DCHAN);				return;			}		}#ifdef ICOM		if (up->fd_icom > 0)			wwv_qsy(peer, up->dchan);#endif /* ICOM */		break;	/*	 * Save the bit probability in the BCD data vector at the index	 * given by the argument. Bits not used in the digit are forced	 * to zero.	 */	case COEF1:			/* 4-7 */ 		bcddld[arg] = bit;		break;	case COEF:			/* 10-13, 15-17, 20-23, 25-26,					   30-33, 35-38, 40-41, 51-54 */		if (up->status & DSYNC) 			bcddld[arg] = bit;		else			bcddld[arg] = 0;		break;	case COEF2:			/* 18, 27-28, 42-43 */		bcddld[arg] = 0;		break;	/*	 * Correlate coefficient vector with each valid digit vector and	 * save in decoding matrix. We step through the decoding matrix	 * digits correlating each with the coefficients and saving the	 * greatest and the next lower for later SNR calculation.	 */	case DECIM2:			/* 29 */		wwv_corr4(peer, &up->decvec[arg], bcddld, bcd2);		break;	case DECIM3:			/* 44 */		wwv_corr4(peer, &up->decvec[arg], bcddld, bcd3);		break;	case DECIM6:			/* 19 */		wwv_corr4(peer, &up->decvec[arg], bcddld, bcd6);		break;	case DECIM9:			/* 8, 14, 24, 34, 39 */		wwv_corr4(peer, &up->decvec[arg], bcddld, bcd9);		break;	/*	 * Miscellaneous bits. If above the positive threshold, declare	 * 1; if below the negative threshold, declare 0; otherwise	 * raise the BGATE bit. The design is intended to avoid	 * integrating noise under low SNR conditions.	 */	case MSC20:			/* 55 */		wwv_corr4(peer, &up->decvec[YR + 1], bcddld, bcd9);		/* fall through */	case MSCBIT:			/* 2-3, 50, 56-57 */		if (bitvec[nsec] > BTHR)			up->misc |= arg;		else if (bitvec[nsec] < -BTHR)			up->misc &= ~arg;		else			up->status |= BGATE;		break;	/*	 * Save the data channel gain, then QSY to the probe channel and	 * dim the seconds comb filters. The newchan() routine will	 * light them back up.	 */	case MSC21:			/* 58 */		if (bitvec[nsec] > BTHR)			up->misc |= arg;		else if (bitvec[nsec] < -BTHR)			up->misc &= ~arg;		else			up->status |= BGATE;		up->status &= ~(SELV | SELH);#ifdef ICOM		if (up->fd_icom > 0) {			up->schan = (up->schan + 1) % NCHAN;			wwv_qsy(peer, up->schan);		}#endif /* ICOM */		break;	/*	 * The endgames	 *	 * During second 59 the receiver and codec AGC are settling	 * down, so the data pulse is unusable as quality metric. If	 * LEPSEC is set on the last minute of 30 June or 31 December,	 * the transmitter and receiver insert an extra second (60) in	 * the timescale and the minute sync repeats the second. Once we	 * tested this wrinkle at intervals of about 18 months, but	 * strangely enough a leap has not been declared since the end	 * of 1998.	 */	case MIN1:			/* 59 */		if (up->status & LEPSEC)			break;		/* fall through */	case MIN2:			/* 60 */		up->status &= ~LEPSEC;		wwv_tsec(peer);		up->rsec = 0;		wwv_clock(peer);		break;	}	if ((pp->sloppyclockflag & CLK_FLAG4) && !(up->status &	    DSYNC)) {		sprintf(tbuf,		    "wwv3 %2d %04x %3d %4d %5.0f %5.1f %5.0f %5.1f %5.0f",		    nsec, up->status, up->gain, up->yepoch, up->epomax,		    up->eposnr, up->datsig, up->datsnr, bit);		record_clock_stats(&peer->srcadr, tbuf);#ifdef DEBUG		if (debug)			printf("%s\n", tbuf);#endif /* DEBUG */	}	pp->disp += AUDIO_PHI;}/* * If victory has been declared and seconds sync is lit, strike * a timestamp. It should not be a surprise, especially if the * radio is not tunable, that sometimes no stations are above * the noise and the reference ID set to NONE. */static voidwwv_clock(	struct peer *peer	/* peer unit pointer */	){	struct refclockproc *pp;	struct wwvunit *up;	l_fp	offset;		/* offset in NTP seconds */	pp = peer->procptr;	up = (struct wwvunit *)pp->unitptr;	if (!(up->status & SSYNC))		up->alarm |= SYNERR;	if (up->digcnt < 9)		up->alarm |= NINERR;	if (!(up->alarm)) {		up->status |= INSYNC;		if (up->misc & SECWAR)			pp->leap = LEAP_ADDSECOND;		else			pp->leap = LEAP_NOWARNING;		pp->second = up->rsec;		pp->minute = up->decvec[MN].digit + up->decvec[MN +		    1].digit * 10;		pp->hour = up->decvec[HR].digit + up->decvec[HR +		    1].digit * 10;		pp->day = up->decvec[DA].digit + up->decvec[DA +		    1].digit * 10 + up->decvec[DA + 2].digit * 100;		pp->year = up->decvec[YR].digit + up->decvec[YR +		    1].digit * 10;		pp->year += 2000;		L_CLR(&offset);		if (!clocktime(pp->day, pp->hour, pp->minute,		    pp->second, GMT, up->timestamp.l_ui,		    &pp->yearstart, &offset.l_ui)) {			up->errflg = CEVNT_BADTIME;		} else {			up->watch = 0;			pp->disp = 0;			refclock_process_offset(pp, offset,			    up->timestamp, PDELAY);			refclock_receive(peer);		}	}	pp->lencode = timecode(up, pp->a_lastcode);	record_clock_stats(

⌨️ 快捷键说明

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