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

📄 refclock_chu.c

📁 网络时间协议NTP 源码 版本v4.2.0b 该源码用于linux平台下
💻 C
📖 第 1 页 / 共 4 页
字号:
		up->errflg = CEVNT_TIMEOUT;	else		pp->polls++;	/*	 * If once in sync and the radio has not been heard for awhile	 * (30 m), it is no longer reachable. If not heard in a long	 * while (one day), turn out the lights and start from scratch.	 */	minset = ((current_time - peer->update) + 30) / 60;	if (up->status & INSYNC) {		if (minset > PANIC)			up->status = 0;		else if (minset <= HOLD)			peer->reach |= 1;	}	/*	 * Process the last burst, if still in the burst buffer.	 * Don't mess with anything if nothing has been heard. If the	 * minute contains a valid A frame and valid B frame, assume	 * synchronized; however, believe the time only if within metric	 * threshold. Note the quality indicator is only for	 * diagnostics; the data are used only if in sync and above	 * metric threshold.	 */	chu_burst(peer);	if (up->burstcnt == 0) {#ifdef ICOM		chu_newchan(peer, 0);#endif /* ICOM */		return;	}	dtemp = chu_major(peer);	qual = 0;	if (up->status & (BFRAME | AFRAME))		qual |= SYNERR;	if (up->status & (BFORMAT | AFORMAT))		qual |= FMTERR;	if (up->status & DECODE)		qual |= DECERR;	if (up->status & STAMP)		qual |= TSPERR;	if (up->status & AVALID && up->status & BVALID)		up->status |= INSYNC;	synchar = leapchar = ' ';	if (!(up->status & INSYNC)) {		pp->leap = LEAP_NOTINSYNC;		synchar = '?';	} else if (up->leap & 0x2) {		pp->leap = LEAP_ADDSECOND;		leapchar = 'L';	} else if (up->leap & 0x4) {		pp->leap = LEAP_DELSECOND;		leapchar = 'l';	} else {		pp->leap = LEAP_NOWARNING;	}#ifdef HAVE_AUDIO	if (up->fd_audio)		sprintf(pp->a_lastcode,		    "%c%1X %04d %3d %02d:%02d:%02d %c%x %+d %d %d %s %.0f %d",		    synchar, qual, pp->year, pp->day, pp->hour,		    pp->minute, pp->second, leapchar, up->dst, up->dut,		    minset, up->gain, up->ident, dtemp, up->ntstamp);	else		sprintf(pp->a_lastcode,		    "%c%1X %04d %3d %02d:%02d:%02d %c%x %+d %d %s %.0f %d",		    synchar, qual, pp->year, pp->day, pp->hour,		    pp->minute, pp->second, leapchar, up->dst, up->dut,		    minset, up->ident, dtemp, up->ntstamp);#else	sprintf(pp->a_lastcode,	    "%c%1X %04d %3d %02d:%02d:%02d %c%x %+d %d %s %.0f %d",	    synchar, qual, pp->year, pp->day, pp->hour, pp->minute,	    pp->second, leapchar, up->dst, up->dut, minset, up->ident,	    dtemp, up->ntstamp);#endif /* HAVE_AUDIO */	pp->lencode = strlen(pp->a_lastcode);	/*	 * If in sync and the signal metric is above threshold, the	 * timecode is ipso fatso valid and can be selected to	 * discipline the clock. Be sure not to leave stray timestamps	 * around if signals are too weak or the clock time is invalid.	 */	if (up->status & INSYNC && dtemp > METRIC) {		if (!clocktime(pp->day, pp->hour, pp->minute, 0, GMT,		    up->tstamp[0].l_ui, &pp->yearstart, &offset.l_ui)) {			up->errflg = CEVNT_BADTIME;		} else {			offset.l_uf = 0;			for (i = 0; i < up->ntstamp; i++)				refclock_process_offset(pp, offset,				    up->tstamp[i], FUDGE +				    pp->fudgetime1);			pp->lastref = up->timestamp;			refclock_receive(peer);		}		record_clock_stats(&peer->srcadr, pp->a_lastcode);	} else if (pp->sloppyclockflag & CLK_FLAG4) {		record_clock_stats(&peer->srcadr, pp->a_lastcode);	}#ifdef DEBUG	if (debug)		printf("chu: timecode %d %s\n", pp->lencode,		    pp->a_lastcode);#endif#ifdef ICOM	chu_newchan(peer, dtemp);#endif /* ICOM */	chu_clear(peer);	if (up->errflg)		refclock_report(peer, up->errflg);	up->errflg = 0;}/* * chu_major - majority decoder */static doublechu_major(	struct peer *peer	/* peer structure pointer */	){	struct refclockproc *pp;	struct chuunit *up;	u_char	code[11];	/* decoded timecode */	int	mindist;	/* minimum distance */	int	val1, val2;	/* maximum distance */	int	synchar;	/* stray cat */	int	temp;	int	i, j, k;	pp = peer->procptr;	up = (struct chuunit *)pp->unitptr;	/*	 * Majority decoder. Each burst encodes two replications at each	 * digit position in the timecode. Each row of the decoding	 * matrix encodes the number of occurrences of each digit found	 * at the corresponding position. The maximum over all	 * occurrences at each position is the distance for this	 * position and the corresponding digit is the maximum	 * likelihood candidate. If the distance is zero, assume a miss	 * '_'; if the distance is not more than half the total number	 * of occurrences, assume a soft error '*'; if two different	 * digits with the same distance are found, assume a hard error	 * '='. These will later cause a format error when the timecode	 * is interpreted. The decoding distance is defined as the	 * minimum distance over the first nine digits. The tenth digit	 * varies over the seconds, so we don't count it.	 */	mindist = 16;	for (i = 0; i < 9; i++) {		val1 = val2 = 0;		k = 0;		for (j = 0; j < 16; j++) {			temp = up->decode[i][j] + up->decode[i + 10][j];			if (temp > val1) {				val2 = val1;				val1 = temp;				k = j;			}		}		if (val1 == 0)			code[i] = HEX_MISS;		else if (val1 == val2)			code[i] = HEX_HARD;		else if (val1 <= up->burstcnt)			code[i] = HEX_SOFT;		else			code[i] = k;		if (val1 < mindist)			mindist = val1;		code[i] = hexchar[code[i]];	}	code[i] = 0;	/*	 * A valid timecode requires a minimum distance at least half	 * the total number of occurrences. A valid timecode also	 * requires at least 20 valid timestamps.	 */	if (up->burstcnt < MINBURST || mindist < up->burstcnt)		up->status |= DECODE;	if (up->ntstamp < MINSTAMP)		up->status |= STAMP;	/*	 * Compute the timecode timestamp from the days, hours and	 * minutes of the timecode. Use clocktime() for the aggregate	 * minutes and the minute offset computed from the burst	 * seconds. Note that this code relies on the filesystem time	 * for the years and does not use the years of the timecode.	 */	if (sscanf((char *)code, "%1x%3d%2d%2d", &synchar, &pp->day,	    &pp->hour, &pp->minute) != 4) {		up->status |= AFORMAT;		return (0);	}	if (up->status & (DECODE | STAMP)) {		up->errflg = CEVNT_BADREPLY;		return (0);	}	return (mindist * 100. / (2. * up->burstcnt));}/* * chu_clear - clear decoding matrix */static voidchu_clear(	struct peer *peer	/* peer structure pointer */	){	struct refclockproc *pp;	struct chuunit *up;	int	i, j;	pp = peer->procptr;	up = (struct chuunit *)pp->unitptr;	/*	 * Clear stuff for the minute.	 */	up->ndx = up->prevsec = 0;	up->burstcnt = up->ntstamp = 0;	up->status &= INSYNC;	for (i = 0; i < 20; i++) {		for (j = 0; j < 16; j++)			up->decode[i][j] = 0;	}}#ifdef ICOM/* * chu_newchan - called once per minute to find the best channel; * returns zero on success, nonzero if ICOM error. */static intchu_newchan(	struct peer *peer,	double	met	){	struct chuunit *up;	struct refclockproc *pp;	struct xmtr *sp;	char	tbuf[80];	/* trace buffer */	int	rval;	double	metric;	int	i, j;	pp = peer->procptr;	up = (struct chuunit *)pp->unitptr;	/*	 * The radio can be tuned to three channels: 0 (3330 kHz), 1	 * (7335 kHz) and 2 (14670 kHz). There are five one-minute	 * dwells in each cycle. During the first dwell the radio is	 * tuned to one of three probe channels; during the remaining	 * four dwells the radio is tuned to the data channel. The probe	 * channel is selects as the least recently used. At the end of	 * each dwell the channel metrics are measured and the highest	 * one is selected as the data channel. 	 */	if (up->fd_icom <= 0)		return (0);	sp = &up->xmtr[up->achan];	sp->metric -= sp->integ[sp->iptr];	sp->integ[sp->iptr] = met;	sp->metric += sp->integ[sp->iptr];	sp->iptr = (sp->iptr + 1) % ISTAGE;	metric = 0;	j = 0;	for (i = 0; i < NCHAN; i++) {		up->xmtr[i].probe++;		if (i == up->achan)			up->xmtr[i].probe = 0;		if (up->xmtr[i].metric < metric)			continue;		metric = up->xmtr[i].metric;		j = i;	}	if (j != up->chan && metric > 0) {		up->chan = j;		sprintf(tbuf, "chu: QSY to %.3f MHz metric %.0f",		    qsy[up->chan], metric);		if (pp->sloppyclockflag & CLK_FLAG4)			record_clock_stats(&peer->srcadr, tbuf);#ifdef DEBUG		if (debug)			printf("%s\n", tbuf);#endif	}	/*	 * Start the next dwell. We speed up the initial sync a little.	 * If not in sync and no bursts were heard the previous dwell,	 * restart the probe.	 */	rval = 0;	if (up->burstcnt == 0 && !(up->status & INSYNC))		up->dwell = 0;#ifdef DEBUG	if (debug)		printf(		    "chu: at %ld dwell %d achan %d metric %.0f chan %d\n",		    current_time, up->dwell, up->achan, sp->metric,		    up->chan);#endif	if (up->dwell == 0) {		rval = 0;		for (i = 0; i < NCHAN; i++) {			if (up->xmtr[i].probe < rval)				continue;			rval = up->xmtr[i].probe;			up->achan = i;		}		rval = icom_freq(up->fd_icom, peer->ttl & 0x7f,		    qsy[up->achan] + TUNE);#ifdef DEBUG		if (debug)			printf("chu: at %ld probe channel %d\n",		    current_time, up->achan);#endif	} else {		if (up->achan != up->chan) {			rval = icom_freq(up->fd_icom, peer->ttl & 0x7f,			    qsy[up->chan] + TUNE);			up->achan = up->chan;		}	}	sprintf(up->ident, "CHU%d", up->achan);	memcpy(&peer->refid, up->ident, 4); 	up->dwell = (up->dwell + 1) % DWELL;	return (rval);}#endif /* ICOM *//* * chu_dist - determine the distance of two octet arguments */static intchu_dist(	int	x,		/* an octet of bits */	int	y		/* another octet of bits */	){	int	val;		/* bit count */ 	int	temp;	int	i;	/*	 * The distance is determined as the weight of the exclusive OR	 * of the two arguments. The weight is determined by the number	 * of one bits in the result. Each one bit increases the weight,	 * while each zero bit decreases it.	 */	temp = x ^ y;	val = 0;	for (i = 0; i < 8; i++) {		if ((temp & 0x1) == 0)			val++;		else			val--;		temp >>= 1;	}	return (val);}#ifdef HAVE_AUDIO/* * chu_gain - adjust codec gain * * This routine is called once each second. If the signal envelope * amplitude is too low, the codec gain is bumped up by four units; if * too high, it is bumped down. The decoder is relatively insensitive to * amplitude, so this crudity works just fine. The input port is set and * the error flag is cleared, mostly to be ornery. */static voidchu_gain(	struct peer *peer	/* peer structure pointer */	){	struct refclockproc *pp;	struct chuunit *up;	pp = peer->procptr;	up = (struct chuunit *)pp->unitptr;	/*	 * Apparently, the codec uses only the high order bits of the	 * gain control field. Thus, it may take awhile for changes to	 * wiggle the hardware bits.	 */	if (up->clipcnt == 0) {		up->gain += 4;		if (up->gain > MAXGAIN)			up->gain = MAXGAIN;	} else if (up->clipcnt > MAXCLP) {		up->gain -= 4;		if (up->gain < 0)			up->gain = 0;	}	audio_gain(up->gain, up->mongain, up->port);	up->clipcnt = 0;}#endif /* HAVE_AUDIO */#elseint refclock_chu_bs;#endif /* REFCLOCK */

⌨️ 快捷键说明

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