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

📄 refclock_chu.c

📁 网络时间协议NTP 源码 版本v4.2.0b 该源码用于linux平台下
💻 C
📖 第 1 页 / 共 4 页
字号:
	noentry,		/* not used (old chu_control) */	noentry,		/* initialize driver (not used) */	noentry,		/* not used (old chu_buginfo) */	NOFLAGS			/* not used */};/* * chu_start - open the devices and initialize data for processing */static intchu_start(	int	unit,		/* instance number (not used) */	struct peer *peer	/* peer structure pointer */	){	struct chuunit *up;	struct refclockproc *pp;	char device[20];	/* device name */	int	fd;		/* file descriptor */#ifdef ICOM	int	temp;#endif /* ICOM */#ifdef HAVE_AUDIO	int	fd_audio;	/* audio port file descriptor */	int	i;		/* index */	double	step;		/* codec adjustment */	/*	 * Open audio device.	 */	fd_audio = audio_init(DEVICE_AUDIO, AUDIO_BUFSIZ, unit);#ifdef DEBUG	if (fd_audio > 0 && debug)		audio_show();#endif	/*	 * Open serial port in raw mode.	 */	if (fd_audio > 0) {		fd = fd_audio;	} else {		sprintf(device, DEVICE, unit);		fd = refclock_open(device, SPEED232, LDISC_RAW);	}#else /* HAVE_AUDIO */	/*	 * Open serial port in raw mode.	 */	sprintf(device, DEVICE, unit);	fd = refclock_open(device, SPEED232, LDISC_RAW);#endif /* HAVE_AUDIO */	if (fd <= 0)		return (0);	/*	 * Allocate and initialize unit structure	 */	if (!(up = (struct chuunit *)	      emalloc(sizeof(struct chuunit)))) {		close(fd);		return (0);	}	memset((char *)up, 0, sizeof(struct chuunit));	pp = peer->procptr;	pp->unitptr = (caddr_t)up;	pp->io.clock_recv = chu_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;	strcpy(up->ident, "CHU");	memcpy(&peer->refid, up->ident, 4); 	DTOLFP(CHAR, &up->charstamp);#ifdef HAVE_AUDIO	/*	 * The companded samples are encoded sign-magnitude. The table	 * contains all the 256 values in the interest of speed. We do	 * this even if the audio codec is not available. C'est la lazy.	 */	up->fd_audio = fd_audio;	up->gain = 127;	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);#endif /* HAVE_AUDIO */#ifdef ICOM	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) {		if (chu_newchan(peer, 0) != 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 */	return (1);}/* * chu_shutdown - shut down the clock */static voidchu_shutdown(	int	unit,		/* instance number (not used) */	struct peer *peer	/* peer structure pointer */	){	struct chuunit *up;	struct refclockproc *pp;	pp = peer->procptr;	up = (struct chuunit *)pp->unitptr;	if (up == NULL)		return;	io_closeclock(&pp->io);#ifdef ICOM	if (up->fd_icom > 0)		close(up->fd_icom);#endif /* ICOM */	free(up);}/* * chu_receive - receive data from the audio or serial device */static voidchu_receive(	struct recvbuf *rbufp	/* receive buffer structure pointer */	){#ifdef HAVE_AUDIO	struct chuunit *up;	struct refclockproc *pp;	struct peer *peer;	peer = (struct peer *)rbufp->recv_srcclock;	pp = peer->procptr;	up = (struct chuunit *)pp->unitptr;	/*	 * If the audio codec is warmed up, the buffer contains codec	 * samples which need to be demodulated and decoded into CHU	 * characters using the software UART. Otherwise, the buffer	 * contains CHU characters from the serial port, so the software	 * UART is bypassed. In this case the CPU will probably run a	 * few degrees cooler.	 */	if (up->fd_audio > 0)		chu_audio_receive(rbufp);	else		chu_serial_receive(rbufp);#else	chu_serial_receive(rbufp);#endif /* HAVE_AUDIO */}#ifdef HAVE_AUDIO/* * chu_audio_receive - receive data from the audio device */static voidchu_audio_receive(	struct recvbuf *rbufp	/* receive buffer structure pointer */	){	struct chuunit *up;	struct refclockproc *pp;	struct peer *peer;	double	sample;		/* codec sample */	u_char	*dpt;		/* buffer pointer */	int	bufcnt;		/* buffer counter */	l_fp	ltemp;		/* l_fp temp */	peer = (struct peer *)rbufp->recv_srcclock;	pp = peer->procptr;	up = (struct chuunit *)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++;		}		chu_rf(peer, sample);		L_ADD(&up->timestamp, &up->tick);		/*		 * Once each second ride gain.		 */		up->seccnt = (up->seccnt + 1) % SECOND;		if (up->seccnt == 0) {			pp->second = (pp->second + 1) % 60;			chu_gain(peer);		}	}	/*	 * 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;}/* * chu_rf - filter and demodulate the FSK signal * * This routine implements a 300-baud Bell 103 modem with mark 2225 Hz * and space 2025 Hz. It uses a bandpass filter followed by a soft * limiter, FM discriminator and lowpass filter. A maximum likelihood * decoder samples the baseband signal at eight times the baud rate and * detects the start bit of each character. * * The filters are built for speed, which explains the rather clumsy * code. Hopefully, the compiler will efficiently implement the move- * and-muiltiply-and-add operations. */static voidchu_rf(	struct peer *peer,	/* peer structure pointer */	double	sample		/* analog sample */	){	struct refclockproc *pp;	struct chuunit *up;	struct surv *sp;	/*	 * Local variables	 */	double	signal;		/* bandpass signal */	double	limit;		/* limiter signal */	double	disc;		/* discriminator signal */	double	lpf;		/* lowpass signal */	double	span;		/* UART signal span */	double	dist;		/* UART signal distance */	int	i, j;	pp = peer->procptr;	up = (struct chuunit *)pp->unitptr;	/*	 * Bandpass filter. 4th-order elliptic, 500-Hz bandpass centered	 * at 2125 Hz. Passband ripple 0.3 dB, stopband ripple 50 dB.	 */	signal = (up->bpf[8] = up->bpf[7]) * 5.844676e-01;	signal += (up->bpf[7] = up->bpf[6]) * 4.884860e-01;	signal += (up->bpf[6] = up->bpf[5]) * 2.704384e+00;	signal += (up->bpf[5] = up->bpf[4]) * 1.645032e+00;	signal += (up->bpf[4] = up->bpf[3]) * 4.644557e+00;	signal += (up->bpf[3] = up->bpf[2]) * 1.879165e+00;	signal += (up->bpf[2] = up->bpf[1]) * 3.522634e+00;	signal += (up->bpf[1] = up->bpf[0]) * 7.315738e-01;	up->bpf[0] = sample - signal;	signal = up->bpf[0] * 6.176213e-03	    + up->bpf[1] * 3.156599e-03	    + up->bpf[2] * 7.567487e-03	    + up->bpf[3] * 4.344580e-03	    + up->bpf[4] * 1.190128e-02	    + up->bpf[5] * 4.344580e-03	    + up->bpf[6] * 7.567487e-03	    + up->bpf[7] * 3.156599e-03	    + up->bpf[8] * 6.176213e-03;	up->monitor = signal / 4.;	/* note monitor after filter */	/*	 * Soft limiter/discriminator. The 11-sample discriminator lag	 * interval corresponds to three cycles of 2125 Hz, which	 * requires the sample frequency to be 2125 * 11 / 3 = 7791.7	 * Hz. The discriminator output varies +-0.5 interval for input	 * frequency 2025-2225 Hz. However, we don't get to sample at	 * this frequency, so the discriminator output is biased. Life	 * at 8000 Hz sucks.	 */	limit = signal;	if (limit > LIMIT)		limit = LIMIT;	else if (limit < -LIMIT)		limit = -LIMIT;	disc = up->disc[up->discptr] * -limit;	up->disc[up->discptr] = limit;	up->discptr = (up->discptr + 1 ) % LAG;	if (disc >= 0)		disc = SQRT(disc);	else		disc = -SQRT(-disc);	/*	 * Lowpass filter. Raised cosine, Ts = 1 / 300, beta = 0.1.	 */	lpf = (up->lpf[26] = up->lpf[25]) * 2.538771e-02;	lpf += (up->lpf[25] = up->lpf[24]) * 1.084671e-01;	lpf += (up->lpf[24] = up->lpf[23]) * 2.003159e-01;	lpf += (up->lpf[23] = up->lpf[22]) * 2.985303e-01;	lpf += (up->lpf[22] = up->lpf[21]) * 4.003697e-01;	lpf += (up->lpf[21] = up->lpf[20]) * 5.028552e-01;	lpf += (up->lpf[20] = up->lpf[19]) * 6.028795e-01;	lpf += (up->lpf[19] = up->lpf[18]) * 6.973249e-01;	lpf += (up->lpf[18] = up->lpf[17]) * 7.831828e-01;	lpf += (up->lpf[17] = up->lpf[16]) * 8.576717e-01;	lpf += (up->lpf[16] = up->lpf[15]) * 9.183463e-01;	lpf += (up->lpf[15] = up->lpf[14]) * 9.631951e-01;	lpf += (up->lpf[14] = up->lpf[13]) * 9.907208e-01;	lpf += (up->lpf[13] = up->lpf[12]) * 1.000000e+00;	lpf += (up->lpf[12] = up->lpf[11]) * 9.907208e-01;	lpf += (up->lpf[11] = up->lpf[10]) * 9.631951e-01;	lpf += (up->lpf[10] = up->lpf[9]) * 9.183463e-01;	lpf += (up->lpf[9] = up->lpf[8]) * 8.576717e-01;	lpf += (up->lpf[8] = up->lpf[7]) * 7.831828e-01;	lpf += (up->lpf[7] = up->lpf[6]) * 6.973249e-01;	lpf += (up->lpf[6] = up->lpf[5]) * 6.028795e-01;	lpf += (up->lpf[5] = up->lpf[4]) * 5.028552e-01;	lpf += (up->lpf[4] = up->lpf[3]) * 4.003697e-01;	lpf += (up->lpf[3] = up->lpf[2]) * 2.985303e-01;	lpf += (up->lpf[2] = up->lpf[1]) * 2.003159e-01;	lpf += (up->lpf[1] = up->lpf[0]) * 1.084671e-01;	lpf += up->lpf[0] = disc * 2.538771e-02;	/*	 * Maximum likelihood decoder. The UART updates each of the	 * eight survivors and determines the span, slice level and	 * tentative decoded character. Valid 11-bit characters are	 * framed so that bit 1 and bit 11 (stop bits) are mark and bit	 * 2 (start bit) is space. When a valid character is found, the	 * survivor with maximum distance determines the final decoded	 * character.	 */	up->baud += 1. / SECOND;	if (up->baud > 1. / (BAUD * 8.)) {		up->baud -= 1. / (BAUD * 8.);		sp = &up->surv[up->decptr];		span = sp->es_max - sp->es_min;		up->maxsignal += (span - up->maxsignal) / 80.;		if (up->dbrk > 0) {			up->dbrk--;		} else if ((sp->uart & 0x403) == 0x401 && span > 1000.)		    {			dist = 0;			j = 0;			for (i = 0; i < 8; i++) {				if (up->surv[i].dist > dist) {					dist = up->surv[i].dist;					j = i;				}			}			chu_decode(peer, (up->surv[j].uart >> 2) &			    0xff);			up->dbrk = 80;		}		up->decptr = (up->decptr + 1) % 8;		chu_uart(sp, -lpf * AGAIN);	}

⌨️ 快捷键说明

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