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

📄 refclock_irig.c

📁 网络时间协议NTP 源码 版本v4.2.0b 该源码用于linux平台下
💻 C
📖 第 1 页 / 共 3 页
字号:
/* * refclock_irig - audio IRIG-B/E demodulator/decoder */#ifdef HAVE_CONFIG_H#include <config.h>#endif#if defined(REFCLOCK) && defined(CLOCK_IRIG)#include "ntpd.h"#include "ntp_io.h"#include "ntp_refclock.h"#include "ntp_calendar.h"#include "ntp_stdlib.h"#include <stdio.h>#include <ctype.h>#include <math.h>#ifdef HAVE_SYS_IOCTL_H#include <sys/ioctl.h>#endif /* HAVE_SYS_IOCTL_H */#include "audio.h"/* * Audio IRIG-B/E demodulator/decoder * * This driver receives, demodulates and decodes IRIG-B/E signals when * connected to the audio codec /dev/audio. The IRIG signal format is an * amplitude-modulated carrier with pulse-width modulated data bits. For * IRIG-B, the carrier frequency is 1000 Hz and bit rate 100 b/s; for * IRIG-E, the carrier frequenchy is 100 Hz and bit rate 10 b/s. The * driver automatically recognizes which format is in use. * * The program processes 8000-Hz mu-law companded samples using separate * signal filters for IRIG-B and IRIG-E, a comb filter, envelope * detector and automatic threshold corrector. Cycle crossings relative * to the corrected slice level determine the width of each pulse and * its value - zero, one or position identifier. The data encode 20 BCD * digits which determine the second, minute, hour and day of the year * and sometimes the year and synchronization condition. The comb filter * exponentially averages the corresponding samples of successive baud * intervals in order to reliably identify the reference carrier cycle. * A type-II phase-lock loop (PLL) performs additional integration and * interpolation to accurately determine the zero crossing of that * cycle, which determines the reference timestamp. A pulse-width * discriminator demodulates the data pulses, which are then encoded as * the BCD digits of the timecode. * * The timecode and reference timestamp are updated once each second * with IRIG-B (ten seconds with IRIG-E) and local clock offset samples * saved for later processing. At poll intervals of 64 s, the saved * samples are processed by a trimmed-mean filter and used to update the * system clock. * * An automatic gain control feature provides protection against * overdriven or underdriven input signal amplitudes. It is designed to * maintain adequate demodulator signal amplitude while avoiding * occasional noise spikes. In order to assure reliable capture, the * decompanded input signal amplitude must be greater than 100 units and * the codec sample frequency error less than 250 PPM (.025 percent). * * The program performs a number of error checks to protect against * overdriven or underdriven input signal levels, incorrect signal * format or improper hardware configuration. Specifically, if any of * the following errors occur for a time measurement, the data are * rejected. * * o The peak carrier amplitude is less than DRPOUT (100). This usually *   means dead IRIG signal source, broken cable or wrong input port. * * o The frequency error is greater than MAXFREQ +-250 PPM (.025%). This *   usually means broken codec hardware or wrong codec configuration. * * o The modulation index is less than MODMIN (0.5). This usually means *   overdriven IRIG signal or wrong IRIG format. * * o A frame synchronization error has occurred. This usually means *   wrong IRIG signal format or the IRIG signal source has lost *   synchronization (signature control). * * o A data decoding error has occurred. This usually means wrong IRIG *   signal format. * * o The current second of the day is not exactly one greater than the *   previous one. This usually means a very noisy IRIG signal or *   insufficient CPU resources. * * o An audio codec error (overrun) occurred. This usually means *   insufficient CPU resources, as sometimes happens with Sun SPARC *   IPCs when doing something useful. * * Note that additional checks are done elsewhere in the reference clock * interface routines. * * Debugging aids * * The timecode format used for debugging and data recording includes * data helpful in diagnosing problems with the IRIG signal and codec * connections. With debugging enabled (-d on the ntpd command line), * the driver produces one line for each timecode in the following * format: * * 00 1 98 23 19:26:52 721 143 0.694 20 0.1 66.5 3094572411.00027 * * The most recent line is also written to the clockstats file at 64-s * intervals. * * The first field contains the error flags in hex, where the hex bits * are interpreted as below. This is followed by the IRIG status * indicator, year of century, day of year and time of day. The status * indicator and year are not produced by some IRIG devices. Following * these fields are the signal amplitude (0-8100), codec gain (0-255), * modulation index (0-1), time constant (2-20), carrier phase error * (us) and carrier frequency error (PPM). The last field is the on-time * timestamp in NTP format. * * The fraction part of the on-time timestamp is a good indicator of how * well the driver is doing. Once upon a time, an UltrSPARC 30 and * Solaris 2.7 kept the clock within a few tens of microseconds relative * to the IRIG-B signal. Accuracy with IRIG-E was about ten times worse. * Unfortunately, Sun broke the 2.7 audio driver in 2.8, which has a 10- * ms sawtooth modulation. The driver attempts to remove the modulation * by some clever estimation techniques which mostly work. With the * "mixerctl -o" command before starting the daemon, the jitter is down * to about 100 microseconds. Your experience may vary. * * Unlike other drivers, which can have multiple instantiations, this * one supports only one. It does not seem likely that more than one * audio codec would be useful in a single machine. More than one would * probably chew up too much CPU time anyway. * * Fudge factors * * Fudge flag4 causes the dubugging output described above to be * recorded in the clockstats file. Fudge flag2 selects the audio input * port, where 0 is the mike port (default) and 1 is the line-in port. * It does not seem useful to select the compact disc player port. Fudge * flag3 enables audio monitoring of the input signal. For this purpose, * the monitor gain is set to a default value. Fudgetime2 is used as a * frequency vernier for broken codec sample frequency. *//* * Interface definitions */#define	DEVICE_AUDIO	"/dev/audio" /* audio device name */#define	PRECISION	(-17)	/* precision assumed (about 10 us) */#define	REFID		"IRIG"	/* reference ID */#define	DESCRIPTION	"Generic IRIG Audio Driver" /* WRU */#define	AUDIO_BUFSIZ	320	/* audio buffer size (40 ms) */#define SECOND		8000	/* nominal sample rate (Hz) */#define BAUD		80	/* samples per baud interval */#define OFFSET		128	/* companded sample offset */#define SIZE		256	/* decompanding table size */#define CYCLE		8	/* samples per carrier cycle */#define SUBFLD		10	/* bits per subfield */#define FIELD		10	/* subfields per field */#define MINTC		2	/* min PLL time constant */#define MAXTC		20	/* max PLL time constant max */#define	MAXSIG		6000.	/* maximum signal level */#define	MAXCLP		100	/* max clips above reference per s */#define DRPOUT		100.	/* dropout signal level */#define MODMIN		0.5	/* minimum modulation index */#define MAXFREQ		(250e-6 * SECOND) /* freq tolerance (.025%) */#define PI		3.1415926535 /* the real thing */#ifdef IRIG_SUCKS#define	WIGGLE		11	/* wiggle filter length */#endif /* IRIG_SUCKS *//* * Experimentally determined filter delays */#define IRIG_B		.0019	/* IRIG-B filter delay */#define IRIG_E		.0019	/* IRIG-E filter delay *//* * Data bit definitions */#define BIT0		0	/* zero */#define BIT1		1	/* one */#define BITP		2	/* position identifier *//* * Error flags (up->errflg) */#define IRIG_ERR_AMP	0x01	/* low carrier amplitude */#define IRIG_ERR_FREQ	0x02	/* frequency tolerance exceeded */#define IRIG_ERR_MOD	0x04	/* low modulation index */#define IRIG_ERR_SYNCH	0x08	/* frame synch error */#define IRIG_ERR_DECODE	0x10	/* frame decoding error */#define IRIG_ERR_CHECK	0x20	/* second numbering discrepancy */#define IRIG_ERR_ERROR	0x40	/* codec error (overrun) */#define IRIG_ERR_SIGERR	0x80	/* IRIG status error (Spectracom) *//* * IRIG unit control structure */struct irigunit {	u_char	timecode[21];	/* timecode string */	l_fp	timestamp;	/* audio sample timestamp */	l_fp	tick;		/* audio sample increment */	double	integ[BAUD];	/* baud integrator */	double	phase, freq;	/* logical clock phase and frequency */	double	zxing;		/* phase detector integrator */	double	yxing;		/* cycle phase */	double	exing;		/* envelope phase */	double	modndx;		/* modulation index */	double	irig_b;		/* IRIG-B signal amplitude */	double	irig_e;		/* IRIG-E signal amplitude */	int	errflg;		/* error flags */	/*	 * 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 */	int	seccnt;		/* second interval counter */	/*	 * RF variables	 */	double	hpf[5];		/* IRIG-B filter shift register */	double	lpf[5];		/* IRIG-E filter shift register */	double	intmin, intmax;	/* integrated envelope min and max */	double	envmax;		/* peak amplitude */	double	envmin;		/* noise amplitude */	double	maxsignal;	/* integrated peak amplitude */	double	noise;		/* integrated noise amplitude */	double	lastenv[CYCLE];	/* last cycle amplitudes */	double	lastint[CYCLE];	/* last integrated cycle amplitudes */	double	lastsig;	/* last carrier sample */	double	fdelay;		/* filter delay */	int	decim;		/* sample decimation factor */	int	envphase;	/* envelope phase */	int	envptr;		/* envelope phase pointer */	int	carphase;	/* carrier phase */	int	envsw;		/* envelope state */	int	envxing;	/* envelope slice crossing */	int	tc;		/* time constant */	int	tcount;		/* time constant counter */	int	badcnt;		/* decimation interval counter */	/*	 * Decoder variables	 */	int	pulse;		/* cycle counter */	int	cycles;		/* carrier cycles */	int	dcycles;	/* data cycles */	int	xptr;		/* translate table pointer */	int	lastbit;	/* last code element length */	int	second;		/* previous second */	int	fieldcnt;	/* subfield count in field */	int	bits;		/* demodulated bits */	int	bitcnt;		/* bit count in subfield */#ifdef IRIG_SUCKS	l_fp	wigwag;		/* wiggle accumulator */	int	wp;		/* wiggle filter pointer */	l_fp	wiggle[WIGGLE];	/* wiggle filter */	l_fp	wigbot[WIGGLE];	/* wiggle bottom fisher*/#endif /* IRIG_SUCKS */	l_fp	wuggle;};/* * Function prototypes */static	int	irig_start	P((int, struct peer *));static	void	irig_shutdown	P((int, struct peer *));static	void	irig_receive	P((struct recvbuf *));static	void	irig_poll	P((int, struct peer *));/* * More function prototypes */static	void	irig_base	P((struct peer *, double));static	void	irig_rf		P((struct peer *, double));static	void	irig_decode	P((struct peer *, int));static	void	irig_gain	P((struct peer *));/* * Transfer vector */struct	refclock refclock_irig = {	irig_start,		/* start up driver */	irig_shutdown,		/* shut down driver */	irig_poll,		/* transmit poll message */	noentry,		/* not used (old irig_control) */	noentry,		/* initialize driver (not used) */	noentry,		/* not used (old irig_buginfo) */	NOFLAGS			/* not used */};/* * Global variables */static char	hexchar[] = {	/* really quick decoding table */	'0', '8', '4', 'c',	/* 0000 0001 0010 0011 */	'2', 'a', '6', 'e',	/* 0100 0101 0110 0111 */	'1', '9', '5', 'd',	/* 1000 1001 1010 1011 */	'3', 'b', '7', 'f'	/* 1100 1101 1110 1111 */};/* * irig_start - open the devices and initialize data for processing */static intirig_start(	int	unit,		/* instance number (used for PCM) */	struct peer *peer	/* peer structure pointer */	){	struct refclockproc *pp;	struct irigunit *up;	/*	 * 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 irigunit *)	      emalloc(sizeof(struct irigunit)))) {		(void) close(fd);		return (0);	}	memset((char *)up, 0, sizeof(struct irigunit));	pp = peer->procptr;	pp->unitptr = (caddr_t)up;	pp->io.clock_recv = irig_receive;	pp->io.srcclock = (caddr_t)peer;	pp->io.datalen = 0;	pp->io.fd = fd;

⌨️ 快捷键说明

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