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

📄 refclock_wwv.c

📁 网络时间协议NTP 源码 版本v4.2.0b 该源码用于linux平台下
💻 C
📖 第 1 页 / 共 5 页
字号:
 * DST decode (DST2 DST1) for prettyprint */char dstcod[] = {	'S',			/* 00 standard time */	'I',			/* 01 set clock ahead at 0200 local */	'O',			/* 10 set clock back at 0200 local */	'D'			/* 11 daylight time */};/* * The decoding matrix consists of nine row vectors, one for each digit * of the timecode. The digits are stored from least to most significant * order. The maximum likelihood timecode is formed from the digits * corresponding to the maximum likelihood values reading in the * opposite order: yy ddd hh:mm. */struct decvec {	int radix;		/* radix (3, 4, 6, 10) */	int digit;		/* current clock digit */	int mldigit;		/* maximum likelihood digit */	int count;		/* match count */	double digprb;		/* max digit probability */	double digsnr;		/* likelihood function (dB) */	double like[10];	/* likelihood integrator 0-9 */};/* * The station structure (sp) is used to acquire the minute pulse from * WWV and/or WWVH. These stations are distinguished by the frequency * used for the second and minute sync pulses, 1000 Hz for WWV and 1200 * Hz for WWVH. Other than frequency, the format is the same. */struct sync {	double	epoch;		/* accumulated epoch differences */	double	maxeng;		/* sync max energy */	double	noieng;		/* sync noise energy */	long	pos;		/* max amplitude position */	long	lastpos;	/* last max position */	long	mepoch;		/* minute synch epoch */	double	amp;		/* sync signal */	double	syneng;		/* sync signal max 800 ms */	double	synmax;		/* sync signal max 0 s */	double	synsnr;		/* sync signal SNR */	double	metric;		/* signal quality metric */	int	reach;		/* reachability register */	int	count;		/* bit counter */	int	select;		/* select bits */	char	refid[5];	/* reference identifier */};/* * The channel structure (cp) is used to mitigate between channels. */struct chan {	int	gain;		/* audio gain */	struct sync wwv;	/* wwv station */	struct sync wwvh;	/* wwvh station */};/* * WWV unit control structure (up) */struct wwvunit {	l_fp	timestamp;	/* audio sample timestamp */	l_fp	tick;		/* audio sample increment */	double	phase, freq;	/* logical clock phase and frequency */	double	monitor;	/* audio monitor point */#ifdef ICOM	int	fd_icom;	/* ICOM file descriptor */#endif /* ICOM */	int	errflg;		/* error flags */	int	watch;		/* watchcat */	/*	 * Audio codec variables	 */	double	comp[SIZE];	/* decompanding table */	int	port;		/* codec port */	int	gain;		/* codec gain */	int	mongain;	/* codec monitor gain */	int	clipcnt;	/* sample clipped count */	/*	 * Variables used to establish basic system timing	 */	int	avgint;		/* master time constant */	int	tepoch;		/* sync epoch median */	int	yepoch;		/* sync epoch */	int	repoch;		/* buffered sync epoch */	double	epomax;		/* second sync amplitude */	double	eposnr;		/* second sync SNR */	double	irig;		/* data I channel amplitude */	double	qrig;		/* data Q channel amplitude */	int	datapt;		/* 100 Hz ramp */	double	datpha;		/* 100 Hz VFO control */	int	rphase;		/* second sample counter */	long	mphase;		/* minute sample counter */	/*	 * Variables used to mitigate which channel to use	 */	struct chan mitig[NCHAN]; /* channel data */	struct sync *sptr;	/* station pointer */	int	dchan;		/* data channel */	int	schan;		/* probe channel */	int	achan;		/* active channel */	/*	 * Variables used by the clock state machine	 */	struct decvec decvec[9]; /* decoding matrix */	int	rsec;		/* seconds counter */	int	digcnt;		/* count of digits synchronized */	/*	 * Variables used to estimate signal levels and bit/digit	 * probabilities	 */	double	datsig;		/* data signal max */	double	datsnr;		/* data signal SNR (dB) */	/*	 * Variables used to establish status and alarm conditions	 */	int	status;		/* status bits */	int	alarm;		/* alarm flashers */	int	misc;		/* miscellaneous timecode bits */	int	errcnt;		/* data bit error counter */};/* * Function prototypes */static	int	wwv_start	P((int, struct peer *));static	void	wwv_shutdown	P((int, struct peer *));static	void	wwv_receive	P((struct recvbuf *));static	void	wwv_poll	P((int, struct peer *));/* * More function prototypes */static	void	wwv_epoch	P((struct peer *));static	void	wwv_rf		P((struct peer *, double));static	void	wwv_endpoc	P((struct peer *, int));static	void	wwv_rsec	P((struct peer *, double));static	void	wwv_qrz		P((struct peer *, struct sync *, int));static	void	wwv_corr4	P((struct peer *, struct decvec *,				    double [], double [][4]));static	void	wwv_gain	P((struct peer *));static	void	wwv_tsec	P((struct peer *));static	int	timecode	P((struct wwvunit *, char *));static	double	wwv_snr		P((double, double));static	int	carry		P((struct decvec *));static	int	wwv_newchan	P((struct peer *));static	void	wwv_newgame	P((struct peer *, int));static	double	wwv_metric	P((struct sync *));static	void	wwv_clock	P((struct peer *));#ifdef ICOMstatic	int	wwv_qsy		P((struct peer *, int));#endif /* ICOM */static double qsy[NCHAN] = {2.5, 5, 10, 15, 20}; /* frequencies (MHz) *//* * Transfer vector */struct	refclock refclock_wwv = {	wwv_start,		/* start up driver */	wwv_shutdown,		/* shut down driver */	wwv_poll,		/* transmit poll message */	noentry,		/* not used (old wwv_control) */	noentry,		/* initialize driver (not used) */	noentry,		/* not used (old wwv_buginfo) */	NOFLAGS			/* not used */};/* * wwv_start - open the devices and initialize data for processing */static intwwv_start(	int	unit,		/* instance number (used by PCM) */	struct peer *peer	/* peer structure pointer */	){	struct refclockproc *pp;	struct wwvunit *up;#ifdef ICOM	int	temp;#endif /* ICOM */	/*	 * Local variables	 */	int	fd;		/* file descriptor */	int	i;		/* index */	double	step;		/* codec adjustment */	/*	 * Open audio device	 */	fd = audio_init(DEVICE_AUDIO, AUDIO_BUFSIZ, unit);	if (fd < 0)		return (0);#ifdef DEBUG	if (debug)		audio_show();#endif	/*	 * Allocate and initialize unit structure	 */	if (!(up = (struct wwvunit *)emalloc(sizeof(struct wwvunit)))) {		close(fd);		return (0);	}	memset(up, 0, sizeof(struct wwvunit));	pp = peer->procptr;	pp->unitptr = (caddr_t)up;	pp->io.clock_recv = wwv_receive;	pp->io.srcclock = (caddr_t)peer;	pp->io.datalen = 0;	pp->io.fd = fd;	if (!io_addclock(&pp->io)) {		close(fd);		free(up);		return (0);	}	/*	 * Initialize miscellaneous variables	 */	peer->precision = PRECISION;	pp->clockdesc = DESCRIPTION;	/*	 * The companded samples are encoded sign-magnitude. The table	 * contains all the 256 values in the interest of speed.	 */	up->comp[0] = up->comp[OFFSET] = 0.;	up->comp[1] = 1.; up->comp[OFFSET + 1] = -1.;	up->comp[2] = 3.; up->comp[OFFSET + 2] = -3.;	step = 2.;	for (i = 3; i < OFFSET; i++) {		up->comp[i] = up->comp[i - 1] + step;		up->comp[OFFSET + i] = -up->comp[i];                if (i % 16 == 0)		    step *= 2.;	}	DTOLFP(1. / SECOND, &up->tick);	/*	 * Initialize the decoding matrix with the radix for each digit	 * position.	 */	up->decvec[MN].radix = 10;	/* minutes */	up->decvec[MN + 1].radix = 6;	up->decvec[HR].radix = 10;	/* hours */	up->decvec[HR + 1].radix = 3;	up->decvec[DA].radix = 10;	/* days */	up->decvec[DA + 1].radix = 10;	up->decvec[DA + 2].radix = 4;	up->decvec[YR].radix = 10;	/* years */	up->decvec[YR + 1].radix = 10;#ifdef ICOM	/*	 * Initialize autotune if available. Note that the ICOM select	 * code must be less than 128, so the high order bit can be used	 * to select the line speed 0 (9600 bps) or 1 (1200 bps).	 */	temp = 0;#ifdef DEBUG	if (debug > 1)		temp = P_TRACE;#endif	if (peer->ttl != 0) {		if (peer->ttl & 0x80)			up->fd_icom = icom_init("/dev/icom", B1200,			    temp);		else			up->fd_icom = icom_init("/dev/icom", B9600,			    temp);		if (up->fd_icom < 0) {			NLOG(NLOG_SYNCEVENT | NLOG_SYSEVENT)			    msyslog(LOG_NOTICE,			    "icom: %m");			up->errflg = CEVNT_FAULT;		}	}	if (up->fd_icom > 0) {		if (wwv_qsy(peer, DCHAN) != 0) {			NLOG(NLOG_SYNCEVENT | NLOG_SYSEVENT)			    msyslog(LOG_NOTICE,			    "icom: radio not found");			up->errflg = CEVNT_FAULT;			close(up->fd_icom);			up->fd_icom = 0;		} else {			NLOG(NLOG_SYNCEVENT | NLOG_SYSEVENT)			    msyslog(LOG_NOTICE,			    "icom: autotune enabled");		}	}#endif /* ICOM */	/*	 * Let the games begin.	 */	wwv_newgame(peer, DCHAN);	return (1);}/* * wwv_shutdown - shut down the clock */static voidwwv_shutdown(	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;	io_closeclock(&pp->io);#ifdef ICOM	if (up->fd_icom > 0)		close(up->fd_icom);#endif /* ICOM */	free(up);}/* * wwv_receive - receive data from the audio device * * This routine reads input samples and adjusts the logical clock to * track the A/D sample clock by dropping or duplicating codec samples. * It also controls the A/D signal level with an AGC loop to mimimize * quantization noise and avoid overload. */static voidwwv_receive(	struct recvbuf *rbufp	/* receive buffer structure pointer */	){	struct peer *peer;	struct refclockproc *pp;	struct wwvunit *up;	/*	 * Local variables	 */	double	sample;		/* codec sample */	u_char	*dpt;		/* buffer pointer */	int	bufcnt;		/* buffer counter */	l_fp	ltemp;	peer = (struct peer *)rbufp->recv_srcclock;	pp = peer->procptr;	up = (struct wwvunit *)pp->unitptr;	/*	 * Main loop - read until there ain't no more. Note codec	 * samples are bit-inverted.	 */	DTOLFP((double)rbufp->recv_length / SECOND, &ltemp);	L_SUB(&rbufp->recv_time, &ltemp);	up->timestamp = rbufp->recv_time;	dpt = rbufp->recv_buffer;	for (bufcnt = 0; bufcnt < rbufp->recv_length; bufcnt++) {		sample = up->comp[~*dpt++ & 0xff];		/*		 * Clip noise spikes greater than MAXSIG. If no clips,		 * increase the gain a tad; if the clips are too high, 		 * decrease a tad.		 */		if (sample > MAXSIG) {			sample = MAXSIG;			up->clipcnt++;		} else if (sample < -MAXSIG) {			sample = -MAXSIG;			up->clipcnt++;		}		/*		 * Variable frequency oscillator. The codec oscillator		 * runs at the nominal rate of 8000 samples per second,		 * or 125 us per sample. A frequency change of one unit		 * results in either duplicating or deleting one sample		 * per second, which results in a frequency change of		 * 125 PPM.		 */		up->phase += up->freq / SECOND;		up->phase += pp->fudgetime2 / 1e6;		if (up->phase >= .5) {			up->phase -= 1.;		} else if (up->phase < -.5) {			up->phase += 1.;			wwv_rf(peer, sample);			wwv_rf(peer, sample);		} else {			wwv_rf(peer, sample);		}		L_ADD(&up->timestamp, &up->tick);	}	/*	 * Set the input port and monitor gain for the next buffer.	 */	if (pp->sloppyclockflag & CLK_FLAG2)		up->port = 2;	else		up->port = 1;	if (pp->sloppyclockflag & CLK_FLAG3)		up->mongain = MONGAIN;	else		up->mongain = 0;}/*

⌨️ 快捷键说明

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