📄 refclock_msfees.c
字号:
/* refclock_ees - clock driver for the EES M201 receiver */#ifdef HAVE_CONFIG_H#include <config.h>#endif#if defined(REFCLOCK) && defined(CLOCK_MSFEES) && defined(PPS)/* Currently REQUIRES STREAM and PPSCD. CLK and CBREAK modes * were removed as the code was overly hairy, they weren't in use * (hence probably didn't work). Still in RCS file at cl.cam.ac.uk */#include "ntpd.h"#include "ntp_io.h"#include "ntp_refclock.h"#include "ntp_unixtime.h"#include "ntp_calendar.h"#include <ctype.h>#if defined(HAVE_BSD_TTYS)#include <sgtty.h>#endif /* HAVE_BSD_TTYS */#if defined(HAVE_SYSV_TTYS)#include <termio.h>#endif /* HAVE_SYSV_TTYS */#if defined(HAVE_TERMIOS)#include <termios.h>#endif#if defined(STREAM)#include <stropts.h>#endif#ifdef HAVE_SYS_TERMIOS_H# include <sys/termios.h>#endif#ifdef HAVE_SYS_PPSCLOCK_H# include <sys/ppsclock.h>#endif#include "ntp_stdlib.h"/* fudgefactor = fudgetime1; os_delay = fudgetime2; offset_fudge = os_delay + fudgefactor + inherent_delay; stratumtouse = fudgeval1 & 0xf debug = fudgeval2; sloppyclockflag = flags & CLK_FLAG1; 1 log smoothing summary when processing sample 4 dump the buffer from the clock 8 EIOGETKD the last n uS time stamps if (flags & CLK_FLAG2 && unitinuse) ees->leaphold = 0; ees->dump_vals = flags & CLK_FLAG3; ees->usealldata = flags & CLK_FLAG4; bug->values[0] = (ees->lasttime) ? current_time - ees->lasttime : 0; bug->values[1] = (ees->clocklastgood)?current_time-ees->clocklastgood:0; bug->values[2] = (u_long)ees->status; bug->values[3] = (u_long)ees->lastevent; bug->values[4] = (u_long)ees->reason; bug->values[5] = (u_long)ees->nsamples; bug->values[6] = (u_long)ees->codestate; bug->values[7] = (u_long)ees->day; bug->values[8] = (u_long)ees->hour; bug->values[9] = (u_long)ees->minute; bug->values[10] = (u_long)ees->second; bug->values[11] = (u_long)ees->tz; bug->values[12] = ees->yearstart; bug->values[13] = (ees->leaphold > current_time) ? ees->leaphold - current_time : 0; bug->values[14] = inherent_delay[unit].l_uf; bug->values[15] = offset_fudge[unit].l_uf; bug->times[0] = ees->reftime; bug->times[1] = ees->arrvtime; bug->times[2] = ees->lastsampletime; bug->times[3] = ees->offset; bug->times[4] = ees->lowoffset; bug->times[5] = ees->highoffset; bug->times[6] = inherent_delay[unit]; bug->times[8] = os_delay[unit]; bug->times[7] = fudgefactor[unit]; bug->times[9] = offset_fudge[unit]; bug->times[10]= ees->yearstart, 0; *//* This should support the use of an EES M201 receiver with RS232 * output (modified to transmit time once per second). * * For the format of the message sent by the clock, see the EESM_ * definitions below. * * It appears to run free for an integral number of minutes, until the error * reaches 4mS, at which point it steps at second = 01. * It appears that sometimes it steps 4mS (say at 7 min interval), * then the next minute it decides that it was an error, so steps back. * On the next minute it steps forward again :-( * This is typically 16.5uS/S then 3975uS at the 4min re-sync, * or 9.5uS/S then 3990.5uS at a 7min re-sync, * at which point it may lose the "00" second time stamp. * I assume that the most accurate time is just AFTER the re-sync. * Hence remember the last cycle interval, * * Can run in any one of: * * PPSCD PPS signal sets CD which interupts, and grabs the current TOD * (sun) *in the interupt code*, so as to avoid problems with * the STREAMS scheduling. * * It appears that it goes 16.5 uS slow each second, then every 4 mins it * generates no "00" second tick, and gains 3975 uS. Ho Hum ! (93/2/7) *//* Definitions */#ifndef MAXUNITS#define MAXUNITS 4 /* maximum number of EES units permitted */#endif#ifndef EES232#define EES232 "/dev/ees%d" /* Device to open to read the data */#endif/* Other constant stuff */#ifndef EESPRECISION#define EESPRECISION (-10) /* what the heck - 2**-10 = 1ms */#endif#ifndef EESREFID#define EESREFID "MSF\0" /* String to identify the clock */#endif#ifndef EESHSREFID#define EESHSREFID (0x7f7f0000 | ((REFCLK_MSF_EES) << 8)) /* Numeric refid */#endif/* Description of clock */#define EESDESCRIPTION "EES M201 MSF Receiver"/* Speed we run the clock port at. If this is changed the UARTDELAY * value should be recomputed to suit. */#ifndef SPEED232#define SPEED232 B9600 /* 9600 baud */#endif/* What is the inherent delay for this mode of working, i.e. when is the * data time stamped. */#define SAFETY_SHIFT 10 /* Split the shift to avoid overflow */#define BITS_TO_L_FP(bits, baud) \(((((bits)*2 +1) << (FRACTION_PREC-SAFETY_SHIFT)) / (2*baud)) << SAFETY_SHIFT)#define INH_DELAY_CBREAK BITS_TO_L_FP(119, 9600)#define INH_DELAY_PPS BITS_TO_L_FP( 0, 9600)#ifndef STREAM_PP1#define STREAM_PP1 "ppsclocd\0<-- patch space for module name1 -->"#endif#ifndef STREAM_PP2#define STREAM_PP2 "ppsclock\0<-- patch space for module name2 -->"#endif /* Offsets of the bytes of the serial line code. The clock gives * local time with a GMT/BST indication. The EESM_ definitions * give offsets into ees->lastcode. */#define EESM_CSEC 0 /* centiseconds - always zero in our clock */#define EESM_SEC 1 /* seconds in BCD */#define EESM_MIN 2 /* minutes in BCD */#define EESM_HOUR 3 /* hours in BCD */#define EESM_DAYWK 4 /* day of week (Sun = 0 etc) */#define EESM_DAY 5 /* day of month in BCD */#define EESM_MON 6 /* month in BCD */#define EESM_YEAR 7 /* year MOD 100 in BCD */#define EESM_LEAP 8 /* 0x0f if leap year, otherwise zero */#define EESM_BST 9 /* 0x03 if BST, 0x00 if GMT */#define EESM_MSFOK 10 /* 0x3f if radio good, otherwise zero */ /* followed by a frame alignment byte (0xff) / / which is not put into the lastcode buffer*//* Length of the serial time code, in characters. The first length * is less the frame alignment byte. */#define LENEESPRT (EESM_MSFOK+1)#define LENEESCODE (LENEESPRT+1) /* Code state. */#define EESCS_WAIT 0 /* waiting for start of timecode */#define EESCS_GOTSOME 1 /* have an incomplete time code buffered */ /* Default fudge factor and character to receive */#define DEFFUDGETIME 0 /* Default user supplied fudge factor */#ifndef DEFOSTIME#define DEFOSTIME 0 /* Default OS delay -- passed by Make ? */#endif#define DEFINHTIME INH_DELAY_PPS /* inherent delay due to sample point*/ /* Limits on things. Reduce the number of samples to SAMPLEREDUCE by median * elimination. If we're running with an accurate clock, chose the BESTSAMPLE * as the estimated offset, otherwise average the remainder. */#define FULLSHIFT 6 /* NCODES root 2 */#define NCODES (1<< FULLSHIFT) /* 64 */#define REDUCESHIFT (FULLSHIFT -1) /* SAMPLEREDUCE root 2 */ /* Towards the high ( Why ?) end of half */#define BESTSAMPLE ((samplereduce * 3) /4) /* 24 */ /* Leap hold time. After a leap second the clock will no longer be * reliable until it resynchronizes. Hope 40 minutes is enough. */#define EESLEAPHOLD (40 * 60)#define EES_STEP_F (1 << 24) /* the receiver steps in units of about 4ms */#define EES_STEP_F_GRACE (EES_STEP_F/8) /*Allow for slop of 1/8 which is .5ms*/#define EES_STEP_NOTE (1 << 21)/* Log any unexpected jumps, say .5 ms .... */#define EES_STEP_NOTES 50 /* Only do a limited number */#define MAX_STEP 16 /* Max number of steps to remember */ /* debug is a bit mask of debugging that is wanted */#define DB_SYSLOG_SMPLI 0x0001#define DB_SYSLOG_SMPLE 0x0002#define DB_SYSLOG_SMTHI 0x0004#define DB_SYSLOG_NSMTHE 0x0008#define DB_SYSLOG_NSMTHI 0x0010#define DB_SYSLOG_SMTHE 0x0020#define DB_PRINT_EV 0x0040#define DB_PRINT_CDT 0x0080#define DB_PRINT_CDTC 0x0100#define DB_SYSLOG_KEEPD 0x0800#define DB_SYSLOG_KEEPE 0x1000#define DB_LOG_DELTAS 0x2000#define DB_PRINT_DELTAS 0x4000#define DB_LOG_AWAITMORE 0x8000#define DB_LOG_SAMPLES 0x10000#define DB_NO_PPS 0x20000#define DB_INC_PPS 0x40000#define DB_DUMP_DELTAS 0x80000 struct eesunit { /* EES unit control structure. */ struct peer *peer; /* associated peer structure */ struct refclockio io; /* given to the I/O handler */ l_fp reftime; /* reference time */ l_fp lastsampletime; /* time as in txt from last EES msg */ l_fp arrvtime; /* Time at which pkt arrived */ l_fp codeoffsets[NCODES]; /* the time of arrival of 232 codes */ l_fp offset; /* chosen offset (for clkbug) */ l_fp lowoffset; /* lowest sample offset (for clkbug) */ l_fp highoffset; /* highest " " (for clkbug) */ char lastcode[LENEESCODE+6]; /* last time code we received */ u_long lasttime; /* last time clock heard from */ u_long clocklastgood; /* last time good radio seen */ u_char lencode; /* length of code in buffer */ u_char nsamples; /* number of samples we've collected */ u_char codestate; /* state of 232 code reception */ u_char unit; /* unit number for this guy */ u_char status; /* clock status */ u_char lastevent; /* last clock event */ u_char reason; /* reason for last abort */ u_char hour; /* hour of day */ u_char minute; /* minute of hour */ u_char second; /* seconds of minute */ char tz; /* timezone from clock */ u_char ttytype; /* method used */ u_char dump_vals; /* Should clock values be dumped */ u_char usealldata; /* Use ALL samples */ u_short day; /* day of year from last code */ u_long yearstart; /* start of current year */ u_long leaphold; /* time of leap hold expiry */ u_long badformat; /* number of bad format codes */ u_long baddata; /* number of invalid time codes */ u_long timestarted; /* time we started this */ long last_pps_no; /* The serial # of the last PPS */ char fix_pending; /* Is a "sync to time" pending ? */ /* Fine tuning - compensate for 4 mS ramping .... */ l_fp last_l; /* last time stamp */ u_char last_steps[MAX_STEP]; /* Most recent n steps */ int best_av_step; /* Best guess at average step */ char best_av_step_count; /* # of steps over used above */ char this_step; /* Current pos in buffer */ int last_step_late; /* How late the last step was (0-59) */ long jump_fsecs; /* # of fractions of a sec last jump */ u_long last_step; /* time of last step */ int last_step_secs; /* Number of seconds in last step */ int using_ramp; /* 1 -> noemal, -1 -> over stepped */ };#define last_sec last_l.l_ui#define last_sfsec last_l.l_f#define this_uisec ((ees->arrvtime).l_ui)#define this_sfsec ((ees->arrvtime).l_f)#define msec(x) ((x) / (1<<22))#define LAST_STEPS (sizeof ees->last_steps / sizeof ees->last_steps[0])#define subms(x) ((((((x < 0) ? (-(x)) : (x)) % (1<<22))/2) * 625) / (1<<(22 -5)))/* Bitmask for what methods to try to use -- currently only PPS enabled */#define T_CBREAK 1#define T_PPS 8/* macros to test above */#define is_cbreak(x) ((x)->ttytype & T_CBREAK)#define is_pps(x) ((x)->ttytype & T_PPS)#define is_any(x) ((x)->ttytype)#define CODEREASON 20 /* reason codes *//* Data space for the unit structures. Note that we allocate these on * the fly, but never give them back. */static struct eesunit *eesunits[MAXUNITS];static u_char unitinuse[MAXUNITS];/* Keep the fudge factors separately so they can be set even * when no clock is configured. */static l_fp inherent_delay[MAXUNITS]; /* when time stamp is taken */static l_fp fudgefactor[MAXUNITS]; /* fudgetime1 */static l_fp os_delay[MAXUNITS]; /* fudgetime2 */static l_fp offset_fudge[MAXUNITS]; /* Sum of above */static u_char stratumtouse[MAXUNITS];static u_char sloppyclockflag[MAXUNITS];static int deltas[60];static l_fp acceptable_slop; /* = { 0, 1 << (FRACTION_PREC -2) }; */static l_fp onesec; /* = { 1, 0 }; */#ifndef DUMP_BUF_SIZE /* Size of buffer to be used by dump_buf */#define DUMP_BUF_SIZE 10112#endif/* ees_reset - reset the count back to zero */#define ees_reset(ees) (ees)->nsamples = 0; \(ees)->codestate = EESCS_WAIT/* ees_event - record and report an event */#define ees_event(ees, evcode) if ((ees)->status != (u_char)(evcode)) \ees_report_event((ees), (evcode)) /* Find the precision of the system clock by reading it */#define USECS 1000000#define MINSTEP 5 /* some systems increment uS on each call */#define MAXLOOPS (USECS/9)/* * Function prototypes */static int msfees_start P((int unit, struct peer *peer));static void msfees_shutdown P((int unit, struct peer *peer));static void msfees_poll P((int unit, struct peer *peer));static void msfees_init P((void));static void dump_buf P((l_fp *coffs, int from, int to, char *text));static void ees_report_event P((struct eesunit *ees, int code));static void ees_receive P((struct recvbuf *rbufp));static void ees_process P((struct eesunit *ees));#ifdef QSORT_USES_VOID_Pstatic int offcompare P((const void *va, const void *vb));#elsestatic int offcompare P((const l_fp *a, const l_fp *b));#endif /* QSORT_USES_VOID_P *//* * Transfer vector */struct refclock refclock_msfees = { msfees_start, /* start up driver */ msfees_shutdown, /* shut down driver */ msfees_poll, /* transmit poll message */ noentry, /* not used */ msfees_init, /* initialize driver */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -