source: trunk/third/xntp/xntpd/refclock_tpro.c @ 10832

Revision 10832, 5.3 KB checked in by brlewis, 27 years ago (diff)
This commit was generated by cvs2svn to compensate for changes in r10831, which included commits to RCS files with non-trunk default branches.
Line 
1/*
2 * refclock_tpro - clock driver for the KSI/Odetics TPRO-S IRIG-B reader
3 */
4
5#ifdef HAVE_CONFIG_H
6#include <config.h>
7#endif
8
9#if defined(REFCLOCK) && defined(TPRO)
10
11#include <stdio.h>
12#include <ctype.h>
13#include <sys/time.h>
14
15#include "ntpd.h"
16#include "ntp_io.h"
17#include "ntp_refclock.h"
18#include "ntp_unixtime.h"
19#include "sys/tpro.h"
20#include "ntp_stdlib.h"
21
22/*
23 * This driver supports the KSI/Odetecs TPRO-S IRIG-B reader and TPRO-
24 * SAT GPS receiver for the Sun Microsystems SBus. It requires that the
25 * tpro.o device driver be installed and loaded.
26 */
27
28/*
29 * TPRO interface definitions
30 */
31#define DEVICE           "/dev/tpro%d" /* device name and unit */
32#define PRECISION       (-20)   /* precision assumed (1 us) */
33#define REFID           "IRIG"  /* reference ID */
34#define DESCRIPTION     "KSI/Odetics TPRO/S IRIG Interface" /* WRU */
35
36#define NSAMPLES        3       /* stages of median filter */
37
38/*
39 * Imported from ntp_timer module
40 */
41extern u_long current_time;     /* current time (s) */
42
43/*
44 * Imported from ntpd module
45 */
46extern int debug;               /* global debug flag */
47
48/*
49 * Unit control structure
50 */
51struct tprounit {
52        struct  tproval tprodata; /* data returned from tpro read */
53};
54
55/*
56 * Function prototypes
57 */
58static  int     tpro_start      P((int, struct peer *));
59static  void    tpro_shutdown   P((int, struct peer *));
60static  void    tpro_poll       P((int unit, struct peer *));
61
62/*
63 * Transfer vector
64 */
65struct  refclock refclock_tpro = {
66        tpro_start,             /* start up driver */
67        tpro_shutdown,          /* shut down driver */
68        tpro_poll,              /* transmit poll message */
69        noentry,                /* not used (old tpro_control) */
70        noentry,                /* initialize driver (not used) */
71        noentry,                /* not used (old tpro_buginfo) */
72        NOFLAGS                 /* not used */
73};
74
75
76/*
77 * tpro_start - open the TPRO device and initialize data for processing
78 */
79static int
80tpro_start(unit, peer)
81        int unit;
82        struct peer *peer;
83{
84        register struct tprounit *up;
85        struct refclockproc *pp;
86        char device[20];
87        int fd;
88
89        /*
90         * Open TPRO device
91         */
92        (void)sprintf(device, DEVICE, unit);
93        fd = open(device, O_RDONLY | O_NDELAY, 0777);
94        if (fd == -1) {
95                msyslog(LOG_ERR, "tpro_start: open of %s: %m", device);
96                return (0);
97        }
98
99        /*
100         * Allocate and initialize unit structure
101         */
102        if (!(up = (struct tprounit *)
103            emalloc(sizeof(struct tprounit)))) {
104                (void) close(fd);
105                return (0);
106        }
107        memset((char *)up, 0, sizeof(struct tprounit));
108        pp = peer->procptr;
109        pp->io.clock_recv = noentry;
110        pp->io.srcclock = (caddr_t)peer;
111        pp->io.datalen = 0;
112        pp->io.fd = fd;
113        pp->unitptr = (caddr_t)up;
114
115        /*
116         * Initialize miscellaneous peer variables
117         */
118        peer->precision = PRECISION;
119        pp->clockdesc = DESCRIPTION;
120        memcpy((char *)&pp->refid, REFID, 4);
121        return (1);
122}
123
124
125/*
126 * tpro_shutdown - shut down the clock
127 */
128static void
129tpro_shutdown(unit, peer)
130        int unit;
131        struct peer *peer;
132{
133        register struct tprounit *up;
134        struct refclockproc *pp;
135
136        pp = peer->procptr;
137        up = (struct tprounit *)pp->unitptr;
138        io_closeclock(&pp->io);
139        free(up);
140}
141
142
143/*
144 * tpro_poll - called by the transmit procedure
145 */
146static void
147tpro_poll(unit, peer)
148        int unit;
149        struct peer *peer;
150{
151        register struct tprounit *up;
152        struct refclockproc *pp;
153        struct tproval *tp;
154
155        /*
156         * This is the main routine. It snatches the time from the TPRO
157         * board and tacks on a local timestamp.
158         */
159        pp = peer->procptr;
160        up = (struct tprounit *)pp->unitptr;
161
162        tp = &up->tprodata;
163        if (read(pp->io.fd, (char *)tp, sizeof(struct tproval)) < 0) {
164                refclock_report(peer, CEVNT_FAULT);
165                return;
166        }
167        get_systime(&pp->lastrec);
168        pp->lasttime = current_time;
169        pp->polls++;
170
171        /*
172         * We get down to business, check the timecode format and decode
173         * its contents. If the timecode has invalid length or is not in
174         * proper format, we declare bad format and exit. Note: we
175         * can't use the sec/usec conversion produced by the driver,
176         * since the year may be suspect. All format error checking is
177         * done by the sprintf() and sscanf() routines.
178         */
179        sprintf(pp->a_lastcode,
180            "%1x%1x%1x %1x%1x:%1x%1x:%1x%1x.%1x%1x%1x%1x%1x%1x %1x",
181            tp->day100, tp->day10, tp->day1, tp->hour10, tp->hour1,
182            tp->min10, tp->min1, tp->sec10, tp->sec1, tp->ms100,
183            tp->ms10, tp->ms1, tp->usec100, tp->usec10, tp->usec1,
184            tp->status);
185        pp->lencode = strlen(pp->a_lastcode);
186
187#ifdef DEBUG
188        if (debug)
189                printf("tpro: time %s timecode %d %s\n",
190                    ulfptoa(&pp->lastrec, 6), pp->lencode,
191                    pp->a_lastcode);
192#endif
193        record_clock_stats(&peer->srcadr, pp->a_lastcode);
194        if (sscanf(pp->a_lastcode, "%3d %2d:%2d:%2d.%6ld", &pp->day,
195            &pp->hour, &pp->minute, &pp->second, &pp->usec)
196            != 5) {
197                refclock_report(peer, CEVNT_BADTIME);
198                return;
199        }
200        if (!tp->status & 0x3) {
201                pp->leap = LEAP_NOTINSYNC;
202                refclock_report(peer, CEVNT_FAULT);
203                return;
204        } else {
205                pp->leap = 0;
206                pp->lasttime = current_time;
207        }
208
209        /*
210         * Process the new sample in the median filter and determine the
211         * reference clock offset and dispersion. We use lastrec as both
212         * the reference time and receive time in order to avoid being
213         * cute, like setting the reference time later than the receive
214         * time, which may cause a paranoid protocol module to chuck out
215         * the data.
216         */
217        if (!refclock_process(pp, NSAMPLES, NSAMPLES)) {
218                refclock_report(peer, CEVNT_BADTIME);
219                return;
220        }
221        refclock_receive(peer, &pp->offset, 0, pp->dispersion,
222            &pp->lastrec, &pp->lastrec, pp->leap);
223}
224
225#else /* not (REFCLOCK && TPRO) */
226int refclock_tpro_bs;
227#endif /* not (REFCLOCK && TPRO) */
228
Note: See TracBrowser for help on using the repository browser.