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

📄 dcfd.c

📁 网络时间协议NTP 源码 版本v4.2.0b 该源码用于linux平台下
💻 C
📖 第 1 页 / 共 3 页
字号:
/* * /src/NTP/REPOSITORY/ntp4-dev/parseutil/dcfd.c,v 4.18 2005/10/07 22:08:18 kardel RELEASE_20051008_A *   * dcfd.c,v 4.18 2005/10/07 22:08:18 kardel RELEASE_20051008_A * * DCF77 100/200ms pulse synchronisation daemon program (via 50Baud serial line) * * Features: *  DCF77 decoding *  simple NTP loopfilter logic for local clock *  interactive display for debugging * * Lacks: *  Leap second handling (at that level you should switch to NTP Version 4 - really!) * * Copyright (c) 1995-2005 by Frank Kardel <kardel <AT> ntp.org> * Copyright (c) 1989-1994 by Frank Kardel, Friedrich-Alexander Universit鋞 Erlangen-N黵nberg, Germany * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright *    notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright *    notice, this list of conditions and the following disclaimer in the *    documentation and/or other materials provided with the distribution. * 3. Neither the name of the author nor the names of its contributors *    may be used to endorse or promote products derived from this software *    without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * */#ifdef HAVE_CONFIG_H# include <config.h>#endif#include <sys/ioctl.h>#include <unistd.h>#include <stdio.h>#include <fcntl.h>#include <sys/types.h>#include <sys/time.h>#include <signal.h>#include <syslog.h>#include <time.h>/* * NTP compilation environment */#include "ntp_stdlib.h"#include "ntpd.h"   /* indirectly include ntp.h to get YEAR_PIVOT   Y2KFixes *//* * select which terminal handling to use (currently only SysV variants) */#if defined(HAVE_TERMIOS_H) || defined(STREAM)#include <termios.h>#define TTY_GETATTR(_FD_, _ARG_) tcgetattr((_FD_), (_ARG_))#define TTY_SETATTR(_FD_, _ARG_) tcsetattr((_FD_), TCSANOW, (_ARG_))#else  /* not HAVE_TERMIOS_H || STREAM */# if defined(HAVE_TERMIO_H) || defined(HAVE_SYSV_TTYS)#  include <termio.h>#  define TTY_GETATTR(_FD_, _ARG_) ioctl((_FD_), TCGETA, (_ARG_))#  define TTY_SETATTR(_FD_, _ARG_) ioctl((_FD_), TCSETAW, (_ARG_))# endif/* HAVE_TERMIO_H || HAVE_SYSV_TTYS */#endif /* not HAVE_TERMIOS_H || STREAM */#ifndef TTY_GETATTR#include "Bletch: MUST DEFINE ONE OF 'HAVE_TERMIOS_H' or 'HAVE_TERMIO_H'"#endif#ifndef days_per_year#define days_per_year(_x_) (((_x_) % 4) ? 365 : (((_x_) % 400) ? 365 : 366))#endif#define timernormalize(_a_) \	if ((_a_)->tv_usec >= 1000000) \	{ \		(_a_)->tv_sec  += (_a_)->tv_usec / 1000000; \		(_a_)->tv_usec  = (_a_)->tv_usec % 1000000; \	} \	if ((_a_)->tv_usec < 0) \	{ \		(_a_)->tv_sec  -= 1 + (-(_a_)->tv_usec / 1000000); \		(_a_)->tv_usec = 999999 - (-(_a_)->tv_usec - 1); \	}#ifdef timeradd#undef timeradd#endif#define timeradd(_a_, _b_) \	(_a_)->tv_sec  += (_b_)->tv_sec; \	(_a_)->tv_usec += (_b_)->tv_usec; \	timernormalize((_a_))#ifdef timersub#undef timersub#endif#define timersub(_a_, _b_) \	(_a_)->tv_sec  -= (_b_)->tv_sec; \	(_a_)->tv_usec -= (_b_)->tv_usec; \	timernormalize((_a_))/* * debug macros */#define PRINTF if (interactive) printf#define LPRINTF if (interactive && loop_filter_debug) printf#ifdef DEBUG#define dprintf(_x_) LPRINTF _x_#else#define dprintf(_x_)#endif#ifdef DECL_ERRNO     extern int errno;#endifstatic char *revision = "4.18";/* * display received data (avoids also detaching from tty) */static int interactive = 0;/* * display loopfilter (clock control) variables */static int loop_filter_debug = 0;/* * do not set/adjust system time */static int no_set = 0;/* * time that passes between start of DCF impulse and time stamping (fine * adjustment) in microseconds (receiver/OS dependent) */#define DEFAULT_DELAY	230000	/* rough estimate *//* * The two states we can be in - eithe we receive nothing * usable or we have the correct time */#define NO_SYNC		0x01#define SYNC		0x02static int    sync_state = NO_SYNC;static time_t last_sync;static unsigned long ticks = 0;static char pat[] = "-\\|/";#define LINES		(24-2)	/* error lines after which the two headlines are repeated */#define MAX_UNSYNC	(10*60)	/* allow synchronisation loss for 10 minutes */#define NOTICE_INTERVAL (20*60)	/* mention missing synchronisation every 20 minutes *//* * clock adjustment PLL - see NTP protocol spec (RFC1305) for details */#define USECSCALE	10#define TIMECONSTANT	2#define ADJINTERVAL	0#define FREQ_WEIGHT	18#define PHASE_WEIGHT	7#define MAX_DRIFT	0x3FFFFFFF#define R_SHIFT(_X_, _Y_) (((_X_) < 0) ? -(-(_X_) >> (_Y_)) : ((_X_) >> (_Y_)))static struct timeval max_adj_offset = { 0, 128000 };static long clock_adjust = 0;	/* current adjustment value (usec * 2^USECSCALE) */static long accum_drift   = 0;	/* accumulated drift value  (usec / ADJINTERVAL) */static long adjustments  = 0;static char skip_adjust  = 1;	/* discard first adjustment (bad samples) *//* * DCF77 state flags */#define DCFB_ANNOUNCE           0x0001 /* switch time zone warning (DST switch) */#define DCFB_DST                0x0002 /* DST in effect */#define DCFB_LEAP		0x0004 /* LEAP warning (1 hour prior to occurrence) */#define DCFB_ALTERNATE		0x0008 /* alternate antenna used */struct clocktime		/* clock time broken up from time code */{	long wday;		/* Day of week: 1: Monday - 7: Sunday */	long day;	long month;	long year;	long hour;	long minute;	long second;	long usecond;	long utcoffset;	/* in minutes */	long flags;		/* current clock status  (DCF77 state flags) */};typedef struct clocktime clocktime_t;/* * (usually) quick constant multiplications */#define TIMES10(_X_) (((_X_) << 3) + ((_X_) << 1))	/* *8 + *2 */#define TIMES24(_X_) (((_X_) << 4) + ((_X_) << 3))      /* *16 + *8 */#define TIMES60(_X_) ((((_X_) << 4)  - (_X_)) << 2)     /* *(16 - 1) *4 *//* * generic l_abs() function */#define l_abs(_x_)     (((_x_) < 0) ? -(_x_) : (_x_))/* * conversion related return/error codes */#define CVT_MASK	0x0000000F /* conversion exit code */#define   CVT_NONE	0x00000001 /* format not applicable */#define   CVT_FAIL	0x00000002 /* conversion failed - error code returned */#define   CVT_OK	0x00000004 /* conversion succeeded */#define CVT_BADFMT	0x00000010 /* general format error - (unparsable) */#define CVT_BADDATE	0x00000020 /* invalid date */#define CVT_BADTIME	0x00000040 /* invalid time *//* * DCF77 raw time code * * From "Zur Zeit", Physikalisch-Technische Bundesanstalt (PTB), Braunschweig * und Berlin, Maerz 1989 * * Timecode transmission: * AM: *	time marks are send every second except for the second before the *	next minute mark *	time marks consist of a reduction of transmitter power to 25% *	of the nominal level *	the falling edge is the time indication (on time) *	time marks of a 100ms duration constitute a logical 0 *	time marks of a 200ms duration constitute a logical 1 * FM: *	see the spec. (basically a (non-)inverted psuedo random phase shift) * * Encoding: * Second	Contents * 0  - 10	AM: free, FM: 0 * 11 - 14	free * 15		R     - alternate antenna * 16		A1    - expect zone change (1 hour before) * 17 - 18	Z1,Z2 - time zone *		 0  0 illegal *		 0  1 MEZ  (MET) *		 1  0 MESZ (MED, MET DST) *		 1  1 illegal * 19		A2    - expect leap insertion/deletion (1 hour before) * 20		S     - start of time code (1) * 21 - 24	M1    - BCD (lsb first) Minutes * 25 - 27	M10   - BCD (lsb first) 10 Minutes * 28		P1    - Minute Parity (even) * 29 - 32	H1    - BCD (lsb first) Hours * 33 - 34      H10   - BCD (lsb first) 10 Hours * 35		P2    - Hour Parity (even) * 36 - 39	D1    - BCD (lsb first) Days * 40 - 41	D10   - BCD (lsb first) 10 Days * 42 - 44	DW    - BCD (lsb first) day of week (1: Monday -> 7: Sunday) * 45 - 49	MO    - BCD (lsb first) Month * 50           MO0   - 10 Months * 51 - 53	Y1    - BCD (lsb first) Years * 54 - 57	Y10   - BCD (lsb first) 10 Years * 58 		P3    - Date Parity (even) * 59		      - usually missing (minute indication), except for leap insertion *//*----------------------------------------------------------------------- * conversion table to map DCF77 bit stream into data fields. * Encoding: *   Each field of the DCF77 code is described with two adjacent entries in *   this table. The first entry specifies the offset into the DCF77 data stream *   while the length is given as the difference between the start index and *   the start index of the following field. */static struct rawdcfcode {	char offset;			/* start bit */} rawdcfcode[] ={	{  0 }, { 15 }, { 16 }, { 17 }, { 19 }, { 20 }, { 21 }, { 25 }, { 28 }, { 29 },	{ 33 }, { 35 }, { 36 }, { 40 }, { 42 }, { 45 }, { 49 }, { 50 }, { 54 }, { 58 }, { 59 }};/*----------------------------------------------------------------------- * symbolic names for the fields of DCF77 describes in "rawdcfcode". * see comment above for the structure of the DCF77 data */#define DCF_M	0#define DCF_R	1#define DCF_A1	2#define DCF_Z	3#define DCF_A2	4#define DCF_S	5#define DCF_M1	6#define DCF_M10	7#define DCF_P1	8#define DCF_H1	9#define DCF_H10	10#define DCF_P2	11#define DCF_D1	12#define DCF_D10	13#define DCF_DW	14#define DCF_MO	15#define DCF_MO0	16#define DCF_Y1	17#define DCF_Y10	18#define DCF_P3	19/*----------------------------------------------------------------------- * parity field table (same encoding as rawdcfcode) * This table describes the sections of the DCF77 code that are * parity protected */static struct partab{	char offset;			/* start bit of parity field */} partab[] ={	{ 21 }, { 29 }, { 36 }, { 59 }};/*----------------------------------------------------------------------- * offsets for parity field descriptions */#define DCF_P_P1	0#define DCF_P_P2	1#define DCF_P_P3	2/*----------------------------------------------------------------------- * legal values for time zone information */#define DCF_Z_MET 0x2#define DCF_Z_MED 0x1/*----------------------------------------------------------------------- * symbolic representation if the DCF77 data stream */static struct dcfparam{	unsigned char onebits[60];	unsigned char zerobits[60];} dcfparam = {	"###############RADMLS1248124P124812P1248121241248112481248P", /* 'ONE' representation */	"--------------------s-------p------p----------------------p"  /* 'ZERO' representation */};/*----------------------------------------------------------------------- * extract a bitfield from DCF77 datastream * All numeric fields are LSB first. * buf holds a pointer to a DCF77 data buffer in symbolic *     representation * idx holds the index to the field description in rawdcfcode */static unsigned longext_bf(	register unsigned char *buf,	register int   idx	){	register unsigned long sum = 0;	register int i, first;	first = rawdcfcode[idx].offset;  	for (i = rawdcfcode[idx+1].offset - 1; i >= first; i--)	{		sum <<= 1;		sum |= (buf[i] != dcfparam.zerobits[i]);	}	return sum;}/*----------------------------------------------------------------------- * check even parity integrity for a bitfield * * buf holds a pointer to a DCF77 data buffer in symbolic *     representation * idx holds the index to the field description in partab */static unsignedpcheck(	register unsigned char *buf,	register int   idx	){	register int i,last;	register unsigned psum = 1;	last = partab[idx+1].offset;	for (i = partab[idx].offset; i < last; i++)	    psum ^= (buf[i] != dcfparam.zerobits[i]);	return psum;}/*----------------------------------------------------------------------- * convert a DCF77 data buffer into wall clock time + flags * * buffer holds a pointer to a DCF77 data buffer in symbolic *        representation * size   describes the length of DCF77 information in bits (represented *        as chars in symbolic notation * clock  points to a wall clock time description of the DCF77 data (result) */static unsigned longconvert_rawdcf(	       unsigned char   *buffer,	       int              size,	       clocktime_t     *clock_time	       ){	if (size < 57)	{		PRINTF("%-30s", "*** INCOMPLETE");		return CVT_NONE;	}  	/*	 * check Start and Parity bits	 */	if ((ext_bf(buffer, DCF_S) == 1) &&	    pcheck(buffer, DCF_P_P1) &&	    pcheck(buffer, DCF_P_P2) &&	    pcheck(buffer, DCF_P_P3))	{		/*		 * buffer OK - extract all fields and build wall clock time from them		 */		clock_time->flags  = 0;		clock_time->usecond= 0;		clock_time->second = 0;		clock_time->minute = ext_bf(buffer, DCF_M10);		clock_time->minute = TIMES10(clock_time->minute) + ext_bf(buffer, DCF_M1);		clock_time->hour   = ext_bf(buffer, DCF_H10);		clock_time->hour   = TIMES10(clock_time->hour)   + ext_bf(buffer, DCF_H1);		clock_time->day    = ext_bf(buffer, DCF_D10);		clock_time->day    = TIMES10(clock_time->day)    + ext_bf(buffer, DCF_D1);		clock_time->month  = ext_bf(buffer, DCF_MO0);		clock_time->month  = TIMES10(clock_time->month)  + ext_bf(buffer, DCF_MO);		clock_time->year   = ext_bf(buffer, DCF_Y10);		clock_time->year   = TIMES10(clock_time->year)   + ext_bf(buffer, DCF_Y1);		clock_time->wday   = ext_bf(buffer, DCF_DW);		/*		 * determine offset to UTC by examining the time zone		 */		switch (ext_bf(buffer, DCF_Z))		{		    case DCF_Z_MET:			clock_time->utcoffset = -60;			break;		    case DCF_Z_MED:			clock_time->flags     |= DCFB_DST;			clock_time->utcoffset  = -120;			break;		    default:			PRINTF("%-30s", "*** BAD TIME ZONE");			return CVT_FAIL|CVT_BADFMT;		}		/*		 * extract various warnings from DCF77		 */		if (ext_bf(buffer, DCF_A1))		    clock_time->flags |= DCFB_ANNOUNCE;		if (ext_bf(buffer, DCF_A2))		    clock_time->flags |= DCFB_LEAP;		if (ext_bf(buffer, DCF_R))		    clock_time->flags |= DCFB_ALTERNATE;		return CVT_OK;	}	else	{		/*		 * bad format - not for us		 */		PRINTF("%-30s", "*** BAD FORMAT (invalid/parity)");		return CVT_FAIL|CVT_BADFMT;	}}/*----------------------------------------------------------------------- * raw dcf input routine - fix up 50 baud * characters for 1/0 decision */static unsigned longcvt_rawdcf(	   unsigned char   *buffer,	   int              size,	   clocktime_t     *clock_time	   ){	register unsigned char *s = buffer;	register unsigned char *e = buffer + size;	register unsigned char *b = dcfparam.onebits;	register unsigned char *c = dcfparam.zerobits;	register unsigned rtc = CVT_NONE;	register unsigned int i, lowmax, highmax, cutoff, span;#define BITS 9	unsigned char     histbuf[BITS];	/*	 * the input buffer contains characters with runs of consecutive	 * bits set. These set bits are an indication of the DCF77 pulse	 * length. We assume that we receive the pulse at 50 Baud. Thus	 * a 100ms pulse would generate a 4 bit train (20ms per bit and	 * start bit)	 * a 200ms pulse would create all zeroes (and probably a frame error)	 *	 * The basic idea is that on corret reception we must have two	 * maxima in the pulse length distribution histogram. (one for	 * the zero representing pulses and one for the one representing	 * pulses)	 * There will always be ones in the datastream, thus we have to see	 * two maxima.	 * The best point to cut for a 1/0 decision is the minimum between those	 * between the maxima. The following code tries to find this cutoff point.	 */	/*	 * clear histogram buffer	 */	for (i = 0; i < BITS; i++)	{		histbuf[i] = 0;	}	cutoff = 0;	lowmax = 0;	/*	 * convert sequences of set bits into bits counts updating	 * the histogram alongway	 */	while (s < e)	{		register unsigned int ch = *s ^ 0xFF;		/*		 * check integrity and update histogramm		 */		if (!((ch+1) & ch) || !*s)		{			/*			 * character ok			 */			for (i = 0; ch; i++)			{				ch >>= 1;			}			*s = i;			histbuf[i]++;			cutoff += i;			lowmax++;		}		else		{			/*			 * invalid character (no consecutive bit sequence)			 */			dprintf(("parse: cvt_rawdcf: character check for 0x%x@%d FAILED\n", *s, s - buffer));			*s = (unsigned char)~0;			rtc = CVT_FAIL|CVT_BADFMT;		}		s++;	}	/*	 * first cutoff estimate (average bit count - must be between both	 * maxima)	 */	if (lowmax)	{		cutoff /= lowmax;	}	else	{		cutoff = 4;	/* doesn't really matter - it'll fail anyway, but gives error output */	}	dprintf(("parse: cvt_rawdcf: average bit count: %d\n", cutoff));	lowmax = 0;  /* weighted sum */	highmax = 0; /* bitcount */	/*	 * collect weighted sum of lower bits (left of initial guess)	 */	dprintf(("parse: cvt_rawdcf: histogram:"));	for (i = 0; i <= cutoff; i++)	{		lowmax  += histbuf[i] * i;		highmax += histbuf[i];		dprintf((" %d", histbuf[i]));	}	dprintf((" <M>"));	/*	 * round up	 */	lowmax += highmax / 2;	/*	 * calculate lower bit maximum (weighted sum / bit count)	 *	 * avoid divide by zero

⌨️ 快捷键说明

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