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

📄 refclock_wwv.c

📁 网络时间协议NTP 源码 版本v4.2.0b 该源码用于linux平台下
💻 C
📖 第 1 页 / 共 5 页
字号:
 * wwv_poll - called by the transmit procedure * * This routine keeps track of status. If no offset samples have been * processed during a poll interval, a timeout event is declared. If * errors have have occurred during the interval, they are reported as * well. Once the clock is set, it always appears reachable, unless * reset by watchcat timeout. */static voidwwv_poll(	int	unit,		/* instance number (not used) */	struct peer *peer	/* peer structure pointer */	){	struct refclockproc *pp;	struct wwvunit *up;	pp = peer->procptr;	up = (struct wwvunit *)pp->unitptr;	if (pp->coderecv == pp->codeproc)		up->errflg = CEVNT_TIMEOUT;	if (up->errflg)		refclock_report(peer, up->errflg);	up->errflg = 0;	pp->polls++;}/* * wwv_rf - process signals and demodulate to baseband * * This routine grooms and filters decompanded raw audio samples. The * output signals include the 100-Hz baseband data signal in quadrature * form, plus the epoch index of the second sync signal and the second * index of the minute sync signal. * * There are two 1-s ramps used by this program. Both count the 8000 * logical clock samples spanning exactly one second. The epoch ramp * counts the samples starting at an arbitrary time. The rphase ramp * counts the samples starting at the 5-ms second sync pulse found * during the epoch ramp. * * There are two 1-m ramps used by this program. The mphase ramp counts * the 480,000 logical clock samples spanning exactly one minute and * starting at an arbitrary time. The rsec ramp counts the 60 seconds of * the minute starting at the 800-ms minute sync pulse found during the * mphase ramp. The rsec ramp drives the seconds state machine to * determine the bits and digits of the timecode.  * * Demodulation operations are based on three synthesized quadrature * sinusoids: 100 Hz for the data signal, 1000 Hz for the WWV sync * signal and 1200 Hz for the WWVH sync signal. These drive synchronous * matched filters for the data signal (170 ms at 100 Hz), WWV minute * sync signal (800 ms at 1000 Hz) and WWVH minute sync signal (800 ms * at 1200 Hz). Two additional matched filters are switched in * as required for the WWV second sync signal (5 ms at 1000 Hz) and * WWVH second sync signal (5 ms at 1200 Hz). */static voidwwv_rf(	struct peer *peer,	/* peerstructure pointer */	double isig		/* input signal */	){	struct refclockproc *pp;	struct wwvunit *up;	struct sync *sp, *rp;	static double lpf[5];	/* 150-Hz lpf delay line */	double data;		/* lpf output */	static double bpf[9];	/* 1000/1200-Hz bpf delay line */	double syncx;		/* bpf output */	static double mf[41];	/* 1000/1200-Hz mf delay line */	double mfsync;		/* mf output */	static int iptr;	/* data channel pointer */	static double ibuf[DATSIZ]; /* data I channel delay line */	static double qbuf[DATSIZ]; /* data Q channel delay line */	static int jptr;	/* sync channel pointer */	static int kptr;	/* tick channel pointer */	static int csinptr;	/* wwv channel phase */	static double cibuf[SYNSIZ]; /* wwv I channel delay line */	static double cqbuf[SYNSIZ]; /* wwv Q channel delay line */	static double ciamp;	/* wwv I channel amplitude */	static double cqamp;	/* wwv Q channel amplitude */	static double csibuf[TCKSIZ]; /* wwv I tick delay line */	static double csqbuf[TCKSIZ]; /* wwv Q tick delay line */	static double csiamp;	/* wwv I tick amplitude */	static double csqamp;	/* wwv Q tick amplitude */	static int hsinptr;	/* wwvh channels phase */	static double hibuf[SYNSIZ]; /* wwvh I channel delay line */	static double hqbuf[SYNSIZ]; /* wwvh Q channel delay line */	static double hiamp;	/* wwvh I channel amplitude */	static double hqamp;	/* wwvh Q channel amplitude */	static double hsibuf[TCKSIZ]; /* wwvh I tick delay line */	static double hsqbuf[TCKSIZ]; /* wwvh Q tick delay line */	static double hsiamp;	/* wwvh I tick amplitude */	static double hsqamp;	/* wwvh Q tick amplitude */	static double epobuf[SECOND]; /* epoch sync comb filter */	static double epomax;	/* epoch sync amplitude buffer */	static int epopos;	/* epoch sync position buffer */	static int iniflg;	/* initialization flag */	int	epoch;		/* comb filter index */	int	pdelay;		/* propagation delay (samples) */	double	dtemp;	int	i;	pp = peer->procptr;	up = (struct wwvunit *)pp->unitptr;	if (!iniflg) {		iniflg = 1;		memset((char *)lpf, 0, sizeof(lpf));		memset((char *)bpf, 0, sizeof(bpf));		memset((char *)mf, 0, sizeof(mf));		memset((char *)ibuf, 0, sizeof(ibuf));		memset((char *)qbuf, 0, sizeof(qbuf));		memset((char *)cibuf, 0, sizeof(cibuf));		memset((char *)cqbuf, 0, sizeof(cqbuf));		memset((char *)csibuf, 0, sizeof(csibuf));		memset((char *)csqbuf, 0, sizeof(csqbuf));		memset((char *)hibuf, 0, sizeof(hibuf));		memset((char *)hqbuf, 0, sizeof(hqbuf));		memset((char *)hsibuf, 0, sizeof(hsibuf));		memset((char *)hsqbuf, 0, sizeof(hsqbuf));		memset((char *)epobuf, 0, sizeof(epobuf));	}	/*	 * Baseband data demodulation. The 100-Hz subcarrier is	 * extracted using a 150-Hz IIR lowpass filter. This attenuates	 * the 1000/1200-Hz sync signals, as well as the 440-Hz and	 * 600-Hz tones and most of the noise and voice modulation	 * components.	 *	 * The subcarrier is transmitted 10 dB down from the carrier.	 * The DGAIN parameter can be adjusted for this and to	 * compensate for the radio audio response at 100 Hz.	 *	 * Matlab IIR 4th-order IIR elliptic, 150 Hz lowpass, 0.2 dB	 * passband ripple, -50 dB stopband ripple.	 */	data = (lpf[4] = lpf[3]) * 8.360961e-01;	data += (lpf[3] = lpf[2]) * -3.481740e+00;	data += (lpf[2] = lpf[1]) * 5.452988e+00;	data += (lpf[1] = lpf[0]) * -3.807229e+00;	lpf[0] = isig * DGAIN - data;	data = lpf[0] * 3.281435e-03	    + lpf[1] * -1.149947e-02	    + lpf[2] * 1.654858e-02	    + lpf[3] * -1.149947e-02	    + lpf[4] * 3.281435e-03;	/*	 * The 100-Hz data signal is demodulated using a pair of	 * quadrature multipliers, matched filters and a phase lock	 * loop. The I and Q quadrature data signals are produced by	 * multiplying the filtered signal by 100-Hz sine and cosine	 * signals, respectively. The signals are processed by 170-ms	 * synchronous matched filters to produce the amplitude and	 * phase signals used by the demodulator. The signals are scaled	 * to produce unit energy at the maximum value.	 */	i = up->datapt;	up->datapt = (up->datapt + IN100) % 80;	dtemp = sintab[i] * data / (MS / 2. * DATCYC);	up->irig -= ibuf[iptr];	ibuf[iptr] = dtemp;	up->irig += dtemp;	i = (i + 20) % 80;	dtemp = sintab[i] * data / (MS / 2. * DATCYC);	up->qrig -= qbuf[iptr];	qbuf[iptr] = dtemp;	up->qrig += dtemp;	iptr = (iptr + 1) % DATSIZ;	/*	 * Baseband sync demodulation. The 1000/1200 sync signals are	 * extracted using a 600-Hz IIR bandpass filter. This removes	 * the 100-Hz data subcarrier, as well as the 440-Hz and 600-Hz	 * tones and most of the noise and voice modulation components.	 *	 * Matlab 4th-order IIR elliptic, 800-1400 Hz bandpass, 0.2 dB	 * passband ripple, -50 dB stopband ripple.	 */	syncx = (bpf[8] = bpf[7]) * 4.897278e-01;	syncx += (bpf[7] = bpf[6]) * -2.765914e+00;	syncx += (bpf[6] = bpf[5]) * 8.110921e+00;	syncx += (bpf[5] = bpf[4]) * -1.517732e+01;	syncx += (bpf[4] = bpf[3]) * 1.975197e+01;	syncx += (bpf[3] = bpf[2]) * -1.814365e+01;	syncx += (bpf[2] = bpf[1]) * 1.159783e+01;	syncx += (bpf[1] = bpf[0]) * -4.735040e+00;	bpf[0] = isig - syncx;	syncx = bpf[0] * 8.203628e-03	    + bpf[1] * -2.375732e-02	    + bpf[2] * 3.353214e-02	    + bpf[3] * -4.080258e-02	    + bpf[4] * 4.605479e-02	    + bpf[5] * -4.080258e-02	    + bpf[6] * 3.353214e-02	    + bpf[7] * -2.375732e-02	    + bpf[8] * 8.203628e-03;	/*	 * The 1000/1200 sync signals are demodulated using a pair of	 * quadrature multipliers and matched filters. However,	 * synchronous demodulation at these frequencies is impractical,	 * so only the signal amplitude is used. The I and Q quadrature	 * sync signals are produced by multiplying the filtered signal	 * by 1000-Hz (WWV) and 1200-Hz (WWVH) sine and cosine signals,	 * respectively. The WWV and WWVH signals are processed by 800-	 * ms synchronous matched filters and combined to produce the	 * minute sync signal and detect which one (or both) the WWV or	 * WWVH signal is present. The WWV and WWVH signals are also	 * processed by 5-ms synchronous matched filters and combined to	 * produce the second sync signal. The signals are scaled to	 * produce unit energy at the maximum value.	 *	 * Note the master timing ramps, which run continuously. The	 * minute counter (mphase) counts the samples in the minute,	 * while the second counter (epoch) counts the samples in the	 * second.	 */	up->mphase = (up->mphase + 1) % MINUTE;	epoch = up->mphase % SECOND;	/*	 * WWV	 */	i = csinptr;	csinptr = (csinptr + IN1000) % 80;	dtemp = sintab[i] * syncx / (MS / 2.);	ciamp -= cibuf[jptr];	cibuf[jptr] = dtemp;	ciamp += dtemp;	csiamp -= csibuf[kptr];	csibuf[kptr] = dtemp;	csiamp += dtemp;	i = (i + 20) % 80;	dtemp = sintab[i] * syncx / (MS / 2.);	cqamp -= cqbuf[jptr];	cqbuf[jptr] = dtemp;	cqamp += dtemp;	csqamp -= csqbuf[kptr];	csqbuf[kptr] = dtemp;	csqamp += dtemp;	sp = &up->mitig[up->achan].wwv;	sp->amp = sqrt(ciamp * ciamp + cqamp * cqamp) / SYNCYC;	if (!(up->status & MSYNC))		wwv_qrz(peer, sp, (int)(pp->fudgetime1 * SECOND));	/*	 * WWVH	 */	i = hsinptr;	hsinptr = (hsinptr + IN1200) % 80;	dtemp = sintab[i] * syncx / (MS / 2.);	hiamp -= hibuf[jptr];	hibuf[jptr] = dtemp;	hiamp += dtemp;	hsiamp -= hsibuf[kptr];	hsibuf[kptr] = dtemp;	hsiamp += dtemp;	i = (i + 20) % 80;	dtemp = sintab[i] * syncx / (MS / 2.);	hqamp -= hqbuf[jptr];	hqbuf[jptr] = dtemp;	hqamp += dtemp;	hsqamp -= hsqbuf[kptr];	hsqbuf[kptr] = dtemp;	hsqamp += dtemp;	rp = &up->mitig[up->achan].wwvh;	rp->amp = sqrt(hiamp * hiamp + hqamp * hqamp) / SYNCYC;	if (!(up->status & MSYNC))		wwv_qrz(peer, rp, (int)(pp->fudgetime2 * SECOND));	jptr = (jptr + 1) % SYNSIZ;	kptr = (kptr + 1) % TCKSIZ;	/*	 * The following section is called once per minute. It does	 * housekeeping and timeout functions and empties the dustbins.	 */	if (up->mphase == 0) {		up->watch++;		if (!(up->status & MSYNC)) {			/*			 * If minute sync has not been acquired before			 * timeout, or if no signal is heard, the			 * program cycles to the next frequency and			 * tries again.			 */			if (!wwv_newchan(peer) || up->watch > ACQSN) {#ifdef ICOM				if (up->fd_icom > 0)					up->dchan = (up->dchan + 1) %					    NCHAN;#endif /* ICOM */				wwv_newgame(peer, up->dchan);			}		} else {			/*			 * If the leap bit is set, set the minute epoch			 * back one second so the station processes			 * don't miss a beat.			 */			if (up->status & LEPSEC) {				up->mphase -= SECOND;				if (up->mphase < 0)					up->mphase += MINUTE;			}		}	}	/*	 * When the channel metric reaches threshold and the second	 * counter matches the minute epoch within the second, the	 * driver has synchronized to the station. The second number is	 * the remaining seconds until the next minute epoch, while the	 * sync epoch is zero. Watch out for the first second; if	 * already synchronized to the second, the buffered sync epoch	 * must be set.	 */	if (up->status & MSYNC) {		wwv_epoch(peer);	} else if (up->sptr != NULL) {		struct chan *cp;		sp = up->sptr;		if (sp->metric >= TTHR && epoch == sp->mepoch % SECOND)		    {			up->rsec = (60 - sp->mepoch / SECOND) % 60;			up->rphase = 0;			up->status |= MSYNC;			up->watch = 0;			if (!(up->status & SSYNC))				up->repoch = up->yepoch = epoch;			else				up->repoch = up->yepoch;			/*			 * Clear the crud and initialize fairly.			 */			for (i = 0; i < NCHAN; i++) {				cp = &up->mitig[i];				cp->wwv.count = cp->wwv.reach = 0;				cp->wwvh.count = cp->wwvh.reach = 0;			}			sp->count = sp->reach = 1;		}	}	/*	 * The second sync pulse is extracted using 5-ms (40 sample) FIR	 * matched filters at 1000 Hz for WWV or 1200 Hz for WWVH. This	 * pulse is used for the most precise synchronization, since if	 * provides a resolution of one sample (125 us). The filters run	 * only if the station has been reliably determined.	 */	if (up->status & SELV) {		pdelay = (int)(pp->fudgetime1 * SECOND);		mfsync = sqrt(csiamp * csiamp + csqamp * csqamp) /		    TCKCYC;	} else if (up->status & SELH) {		pdelay = (int)(pp->fudgetime2 * SECOND);		mfsync = sqrt(hsiamp * hsiamp + hsqamp * hsqamp) /		    TCKCYC;	} else {		pdelay = 0;		mfsync = 0;	}	/*	 * Enhance the seconds sync pulse using a 1-s (8000-sample) comb	 * filter. Correct for the FIR matched filter delay, which is 5	 * ms for both the WWV and WWVH filters, and also for the	 * propagation delay. Once each second look for second sync. If	 * not in minute sync, fiddle the codec gain. Note the SNR is	 * computed from the maximum sample and the envelope of the	 * sample 10 ms before it, so if we slip more than a cycle the	 * SNR should plummet. The signal is scaled to produce unit	 * energy at the maximum value.	 */	dtemp = (epobuf[epoch] += (mfsync - epobuf[epoch]) /	    up->avgint);	if (dtemp > epomax) {		epomax = dtemp;		epopos = epoch;	}	if (epoch == 0) {		int j;		up->epomax = epomax;		dtemp = 0;		j = epopos - 10 * MS;		if (j < 0)			j += SECOND;		up->eposnr = wwv_snr(epomax, epobuf[j]);		epopos -= pdelay + TCKCYC * MS;		if (epopos < 0)			epopos += SECOND;		wwv_endpoc(peer, epopos);		if (!(up->status & SSYNC))			up->alarm |= SYNERR;		epomax = 0;		if (!(up->status & MSYNC))			wwv_gain(peer);	}}/* * wwv_qrz - identify and acquire WWV/WWVH minute sync pulse

⌨️ 快捷键说明

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