?? refclock_ulink.c
字號:
/* * refclock_ulink - clock driver for Ultralink WWVB receiver *//*********************************************************************** * * * Copyright (c) David L. Mills 1992-1998 * * * * Permission to use, copy, modify, and distribute this software and * * its documentation for any purpose and without fee is hereby * * granted, provided that the above copyright notice appears in all * * copies and that both the copyright notice and this permission * * notice appear in supporting documentation, and that the name * * University of Delaware not be used in advertising or publicity * * pertaining to distribution of the software without specific, * * written prior permission. The University of Delaware makes no * * representations about the suitability this software for any * * purpose. It is provided "as is" without express or implied * * warranty. * **********************************************************************/#ifdef HAVE_CONFIG_H#include <config.h>#endif#if defined(REFCLOCK) && defined(CLOCK_ULINK)#include <stdio.h>#include <ctype.h>#include "ntpd.h"#include "ntp_io.h"#include "ntp_refclock.h"#include "ntp_stdlib.h"/* This driver supports ultralink Model 320,325,330,331,332 WWVB radios * * this driver was based on the refclock_wwvb.c driver * in the ntp distribution. * * Fudge Factors * * fudge flag1 0 don't poll clock * 1 send poll character * * revision history: * 99/9/09 j.c.lang original edit's * 99/9/11 j.c.lang changed timecode parse to * match what the radio actually * sends. * 99/10/11 j.c.lang added support for continous * time code mode (dipsw2) * 99/11/26 j.c.lang added support for 320 decoder * (taken from Dave Strout's * Model 320 driver) * 99/11/29 j.c.lang added fudge flag 1 to control * clock polling * 99/12/15 j.c.lang fixed 320 quality flag * 01/02/21 s.l.smith fixed 33x quality flag * added more debugging stuff * updated 33x time code explanation * 04/01/23 frank migge added support for 325 decoder * (tested with ULM325.F) * * Questions, bugs, ideas send to: * Joseph C. Lang * tcnojl1@earthlink.net * * Dave Strout * dstrout@linuxfoundry.com * * Frank Migge * frank.migge@oracle.com * * * on the Ultralink model 33X decoder Dip switch 2 controls * polled or continous timecode * set fudge flag1 if using polled (needed for model 320 and 325) * dont set fudge flag1 if dip switch 2 is set on model 33x decoder*//* * Interface definitions */#define DEVICE "/dev/wwvb%d" /* device name and unit */#define SPEED232 B9600 /* uart speed (9600 baud) */#define PRECISION (-10) /* precision assumed (about 10 ms) */#define REFID "WWVB" /* reference ID */#define DESCRIPTION "Ultralink WWVB Receiver" /* WRU */#define LEN33X 32 /* timecode length Model 33X and 325 */#define LEN320 24 /* timecode length Model 320 */#define SIGLCHAR33x 'S' /* signal strength identifier char 325 */#define SIGLCHAR325 'R' /* signal strength identifier char 33x *//* * unit control structure */struct ulinkunit { u_char tcswitch; /* timecode switch */ l_fp laststamp; /* last receive timestamp */};/* * Function prototypes */static int ulink_start P((int, struct peer *));static void ulink_shutdown P((int, struct peer *));static void ulink_receive P((struct recvbuf *));static void ulink_poll P((int, struct peer *));/* * Transfer vector */struct refclock refclock_ulink = { ulink_start, /* start up driver */ ulink_shutdown, /* shut down driver */ ulink_poll, /* transmit poll message */ noentry, /* not used */ noentry, /* not used */ noentry, /* not used */ NOFLAGS};/* * ulink_start - open the devices and initialize data for processing */static intulink_start( int unit, struct peer *peer ){ register struct ulinkunit *up; struct refclockproc *pp; int fd; char device[20]; /* * Open serial port. Use CLK line discipline, if available. */ (void)sprintf(device, DEVICE, unit); if (!(fd = refclock_open(device, SPEED232, LDISC_CLK))) return (0); /* * Allocate and initialize unit structure */ if (!(up = (struct ulinkunit *) emalloc(sizeof(struct ulinkunit)))) { (void) close(fd); return (0); } memset((char *)up, 0, sizeof(struct ulinkunit)); pp = peer->procptr; pp->unitptr = (caddr_t)up; pp->io.clock_recv = ulink_receive; pp->io.srcclock = (caddr_t)peer; pp->io.datalen = 0; pp->io.fd = fd; if (!io_addclock(&pp->io)) { (void) close(fd); free(up); return (0); } /* * Initialize miscellaneous variables */ peer->precision = PRECISION; peer->burst = NSTAGE; pp->clockdesc = DESCRIPTION; memcpy((char *)&pp->refid, REFID, 4); return (1);}/* * ulink_shutdown - shut down the clock */static voidulink_shutdown( int unit, struct peer *peer ){ register struct ulinkunit *up; struct refclockproc *pp; pp = peer->procptr; up = (struct ulinkunit *)pp->unitptr; io_closeclock(&pp->io); free(up);}/* * ulink_receive - receive data from the serial interface */static voidulink_receive( struct recvbuf *rbufp ){ struct ulinkunit *up; struct refclockproc *pp; struct peer *peer; l_fp trtmp; /* arrival timestamp */ int quality; /* quality indicator */ int temp; /* int temp */ char syncchar; /* synchronization indicator */ char leapchar; /* leap indicator */ char modechar; /* model 320 mode flag */ char siglchar; /* model difference between 33x/325 */ char char_quality[2]; /* temp quality flag */ /* * Initialize pointers and read the timecode and timestamp */ peer = (struct peer *)rbufp->recv_srcclock; pp = peer->procptr; up = (struct ulinkunit *)pp->unitptr; temp = refclock_gtlin(rbufp, pp->a_lastcode, BMAX, &trtmp); /* * Note we get a buffer and timestamp for both a <cr> and <lf>, * but only the <cr> timestamp is retained. */ if (temp == 0) { if (up->tcswitch == 0) { up->tcswitch = 1; up->laststamp = trtmp; } else up->tcswitch = 0; return; } pp->lencode = temp; pp->lastrec = up->laststamp; up->laststamp = trtmp; up->tcswitch = 1;#ifdef DEBUG if (debug) printf("ulink: timecode %d %s\n", pp->lencode, pp->a_lastcode);#endif /* * We get down to business, check the timecode format and decode * its contents. If the timecode has invalid length or is not in * proper format, we declare bad format and exit. */ syncchar = leapchar = modechar = siglchar = ' '; switch (pp->lencode ) { case LEN33X: /* * First we check if the format is 33x or 325: * <CR><LF>S9+D 00 YYYY+DDDUTCS HH:MM:SSL+5 (33x) * <CR><LF>R5_1C00LYYYY+DDDUTCS HH:MM:SSL+5 (325) * simply by comparing if the signal level is 'S' or 'R' */ if (sscanf(pp->a_lastcode, "%c%*31c", &siglchar) == 1) { if(siglchar == SIGLCHAR325) { /* * decode for a Model 325 decoder. * Timecode format from January 23, 2004 datasheet is: * * <CR><LF>R5_1C00LYYYY+DDDUTCS HH:MM:SSL+5 * * R WWVB decodersignal readability R1 - R5 * 5 R1 is unreadable, R5 is best * space a space (0x20) * 1 Data bit 0, 1, M (pos mark), or ? (unknown). * C Reception from either (C)olorado or (H)awaii * 00 Hours since last good WWVB frame sync. Will * be 00-99 * space Space char (0x20) or (0xa5) if locked to wwvb * YYYY Current year, 2000-2099 * + Leap year indicator. '+' if a leap year, * a space (0x20) if not. * DDD Day of year, 000 - 365. * UTC Timezone (always 'UTC'). * S Daylight savings indicator * S - standard time (STD) in effect * O - during STD to DST day 0000-2400 * D - daylight savings time (DST) in effect * I - during DST to STD day 0000-2400
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -