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

Revision 10832, 24.4 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_datum - clock driver for the Datum Programmable Time Server
3**
4** Important note: This driver assumes that you have termios. If you have
5** a system that does not have termios, you will have to modify this driver.
6**
7** Sorry, I have only tested this driver on SUN and HP platforms.
8*/
9
10#ifdef HAVE_CONFIG_H
11#include <config.h>
12#endif
13
14#if defined(REFCLOCK) && defined(DATUM)
15
16/*
17** Include Files
18*/
19
20#include <stdio.h>
21#include <ctype.h>
22#include <sys/time.h>
23#include <sys/errno.h>
24
25#include "ntpd.h"
26#include "ntp_io.h"
27#include "ntp_refclock.h"
28#include "ntp_unixtime.h"
29
30#if defined(HAVE_BSD_TTYS)
31#include <sgtty.h>
32#endif /* HAVE_BSD_TTYS */
33
34#if defined(HAVE_SYSV_TTYS)
35#include <termio.h>
36#endif /* HAVE_SYSV_TTYS */
37
38#if defined(HAVE_TERMIOS)
39#include <termios.h>
40#endif
41#if defined(STREAM)
42#include <stropts.h>
43#if defined(WWVBCLK)
44#include <sys/clkdefs.h>
45#endif /* WWVBCLK */
46#endif /* STREAM */
47
48#if defined (WWVBPPS)
49#include <sys/ppsclock.h>
50#endif /* WWVBPPS */
51
52#include "ntp_stdlib.h"
53
54/*
55** This driver supports the Datum Programmable Time System (PTS) clock.
56** The clock works in very straight forward manner. When it receives a
57** time code request (e.g., the ascii string "//k/mn"), it responds with
58** a seven byte BCD time code. This clock only responds with a
59** time code after it first receives the "//k/mn" message. It does not
60** periodically send time codes back at some rate once it is started.
61** the returned time code can be broken down into the following fields.
62**
63**            _______________________________
64** Bit Index | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
65**            ===============================
66** byte 0:   | -   -   -   - |      H D      |
67**            ===============================
68** byte 1:   |      T D      |      U D      |
69**            ===============================
70** byte 2:   | -   - |  T H  |      U H      |
71**            ===============================
72** byte 3:   | - |    T M    |      U M      |
73**            ===============================
74** byte 4:   | - |    T S    |      U S      |
75**            ===============================
76** byte 5:   |      t S      |      h S      |
77**            ===============================
78** byte 6:   |      m S      | -   -   -   - |
79**            ===============================
80**
81** In the table above:
82**
83**      "-" means don't care
84**      "H D", "T D", and "U D" means Hundreds, Tens, and Units of Days
85**      "T H", and "UH" means Tens and Units of Hours
86**      "T M", and "U M" means Tens and Units of Minutes
87**      "T S", and "U S" means Tens and Units of Seconds
88**      "t S", "h S", and "m S" means tenths, hundredths, and thousandths
89**                              of seconds
90**
91** The Datum PTS communicates throught the RS232 port on your machine.
92** Right now, it assumes that you have termios. This driver has been tested
93** on SUN and HP workstations. The Datum PTS supports various IRIG and
94** NASA input codes. This driver assumes that the name of the device is
95** /dev/datum. You will need to make a soft link to your RS232 device or
96** create a new driver to use this refclock.
97*/
98
99/*
100** Datum PTS defines
101*/
102
103/*
104** Note that if GMT is defined, then the Datum PTS must use Greenwich
105** time. Otherwise, this driver allows the Datum PTS to use the current
106** wall clock for its time. It determines the time zone offset by minimizing
107** the error after trying several time zone offsets. If the Datum PTS
108** time is Greenwich time and GMT is not defined, everything should still
109** work since the time zone will be found to be 0. What this really means
110** is that your system time (at least to start with) must be within the
111** correct time by less than +- 30 minutes. The default is for GMT to not
112** defined. If you really want to force GMT without the funny +- 30 minute
113** stuff then you must define (uncomment) GMT below.
114*/
115
116/*
117#define GMT
118#define DEBUG_DATUM_PTC
119#define LOG_TIME_ERRORS
120*/
121
122
123#define PTSPRECISION    (-10)           /* precision assumed 1/1024 ms */
124#define DATMREFID "DATM"                /* reference id */
125#define DATUM_DISPERSION 0              /* fixed dispersion = 0 ms */
126#define DATUM_MAX_ERROR 0.100           /* limits on sigma squared */
127
128#define DATUM_MAX_ERROR2 (DATUM_MAX_ERROR*DATUM_MAX_ERROR)
129
130/*
131** External Variables
132*/
133
134extern u_long current_time;     /* current time (s) - not really  used */
135extern int debug;               /* global debug flag - not relly used */
136
137/*
138** The Datum PTS structure
139*/
140
141/*
142** I don't use a fixed array of MAXUNITS like everyone else just because
143** I don't like to program that way. Sorry if this bothers anyone. I assume
144** that you can use any id for your unit and I will search for it in a
145** dynamic array of units until I find it. I was worried that users might
146** enter a bad id in their configuration file (larger than MAXUNITS) and
147** besides, it is just cleaner not to have to assume that you have a fixed
148** number of anything in a program.
149*/
150
151struct datum_pts_unit {
152  struct peer *peer;            /* peer used by xntp */
153  struct refclockio io;         /* io structure used by xntp */
154  int PTS_fd;                   /* file descriptor for PTS */
155  u_int unit;                   /* id for unit */
156  u_long timestarted;           /* time started */
157  l_fp lastrec;                 /* time tag for the receive time (system) */
158  l_fp lastref;                 /* reference time (Datum time) */
159  u_long yearstart;             /* the year that this clock started */
160  int coderecv;                 /* number of time codes received */
161  int day;                      /* day */
162  int hour;                     /* hour */
163  int minute;                   /* minutes */
164  int second;                   /* seconds */
165  int msec;                     /* miliseconds */
166  int usec;                     /* miliseconds */
167  u_char leap;                  /* funny leap character code */
168  char retbuf[8];               /* returned time from the datum pts */
169  char nbytes;                  /* number of bytes received from datum pts */
170  double sigma2;                /* average squared error (roughly) */
171  int tzoff;                    /* time zone offest from GMT */
172};
173
174/*
175** PTS static constant variables for internal use
176*/
177
178static char TIME_REQUEST[6];    /* request message sent to datum for time */
179static int nunits;              /* number of active units */
180static struct datum_pts_unit
181        **datum_pts_unit;       /* dynamic array of datum PTS structures */
182
183/*
184** Callback function prototypes that xntpd needs to know about.
185*/
186
187static  int     datum_pts_start         P((int, struct peer *));
188static  void    datum_pts_shutdown      P((int, struct peer *));
189static  void    datum_pts_poll          P((int, struct peer *));
190static  void    datum_pts_control       P((int, struct refclockstat *,
191                                                  struct refclockstat *));
192static  void    datum_pts_init          P((void));
193static  void    datum_pts_buginfo       P((int, struct refclockbug *));
194
195/*
196** This is the call back function structure that xntpd actually uses for
197** this refclock.
198*/
199
200struct  refclock refclock_datum = {
201  datum_pts_start,              /* start up a new Datum refclock */
202  datum_pts_shutdown,           /* shutdown a Datum refclock */
203  datum_pts_poll,               /* sends out the time request */
204  datum_pts_control,            /* not used */
205  datum_pts_init,               /* initialization (called first) */
206  datum_pts_buginfo,            /* not used */
207  NOFLAGS                       /* we are not setting any special flags */
208};
209
210/*
211** The datum_pts_receive callback function is handled differently from the
212** rest. It is passed to the xntpd io data structure. Basically, every
213** 64 seconds, the datum_pts_poll() routine is called. It sends out the time
214** request message to the Datum Programmable Time System. Then, xntpd
215** waits on a select() call to receive data back. The datum_pts_receive()
216** function is called as data comes back. We expect a seven byte time
217** code to be returned but the datum_pts_receive() function may only get
218** a few bytes passed to it at a time. In other words, this routine may
219** get called by the io stuff in xntpd a few times before we get all seven
220** bytes. Once the last byte is received, we process it and then pass the
221** new time measurement to xntpd for updating the system time. For now,
222** there is no 3 state filtering done on the time measurements. The
223** jitter may be a little high but at least for its current use, it is not
224** a problem. We have tried to keep things as simple as possible. This
225** clock should not jitter more than 1 or 2 mseconds at the most once
226** things settle down. It is important to get the right drift calibrated
227** in the xntpd.drift file as well as getting the right tick set up right
228** using tickadj for SUNs. Tickadj is not used for the HP but you need to
229** remember to bring up the adjtime daemon because HP does not support
230** the adjtime() call.
231*/
232
233static  void    datum_pts_receive       P((struct recvbuf *));
234
235/*......................................................................*/
236/*      datum_pts_start - start up the datum PTS. This means open the   */
237/*      RS232 device and set up the data structure for my unit.         */
238/*......................................................................*/
239
240static int datum_pts_start(unit, peer)
241  int unit;
242  struct peer *peer;
243{
244  struct datum_pts_unit **temp_datum_pts_unit;
245  struct datum_pts_unit *datum_pts;
246
247#ifdef HAVE_TERMIOS
248  struct termios arg;
249#endif
250
251#ifdef DEBUG_DATUM_PTC
252  if (debug)
253    printf("Starting Datum PTS unit %d\n", unit);
254#endif
255
256/*
257** Create the memory for the new unit
258*/
259
260  temp_datum_pts_unit = (struct datum_pts_unit **)
261                malloc((nunits+1)*sizeof(struct datum_pts_unit *));
262  if (nunits > 0) memcpy(temp_datum_pts_unit, datum_pts_unit,
263                nunits*sizeof(struct datum_pts_unit *));
264  free(datum_pts_unit);
265  datum_pts_unit = temp_datum_pts_unit;
266  datum_pts_unit[nunits] = (struct datum_pts_unit *)
267                                malloc(sizeof(struct datum_pts_unit));
268  datum_pts = datum_pts_unit[nunits];
269
270  datum_pts->unit = unit;       /* set my unit id */
271  datum_pts->yearstart = 0;     /* initialize the yearstart to 0 */
272  datum_pts->sigma2 = 0.0;      /* initialize the sigma2 to 0 */
273
274/*
275** Open the Datum PTS device
276*/
277
278  datum_pts->PTS_fd = open("/dev/datum",O_RDWR);
279
280  fcntl(datum_pts->PTS_fd, F_SETFL, 0); /* clear the descriptor flags */
281
282#ifdef DEBUG_DATUM_PTC
283  if (debug)
284    printf("Opening RS232 port with file descriptor %d\n",
285        datum_pts->PTS_fd);
286#endif
287
288/*
289** Set up the RS232 terminal device information. Note that we assume that
290** we have termios. This code has only been tested on SUNs and HPs. If your
291** machine does not have termios this driver cannot be initialized. You can change this
292** if you want by editing this source. Please give the changes back to the
293** xntp folks so that it can become part of their regular distribution.
294*/
295
296#ifdef HAVE_TERMIOS
297
298  arg.c_iflag = IGNBRK;
299  arg.c_oflag = 0;
300  arg.c_cflag = B9600 | CS8 | CREAD | PARENB | CLOCAL;
301  arg.c_lflag = 0;
302  arg.c_cc[VMIN] = 0;           /* start timeout timer right away (not used) */
303  arg.c_cc[VTIME] = 30;         /* 3 second timout on reads (not used) */
304
305  tcsetattr(datum_pts->PTS_fd, TCSANOW, &arg);
306
307#else
308
309  msyslog(LOG_ERR, "Datum_PTS: Termios not supported in this driver");
310 (void)close(datum_pts->PTS_fd);
311
312  return 0;
313
314#endif
315
316/*
317** Initialize the xntpd IO structure
318*/
319
320  datum_pts->peer = peer;
321  datum_pts->timestarted = current_time;
322
323  datum_pts->io.clock_recv = datum_pts_receive;
324  datum_pts->io.srcclock = (caddr_t)datum_pts;
325  datum_pts->io.datalen = 0;
326  datum_pts->io.fd = datum_pts->PTS_fd;
327
328  if (!io_addclock(&(datum_pts->io))) {
329
330#ifdef DEBUG_DATUM_PTC
331    if (debug)
332      printf("Problem adding clock\n");
333#endif
334
335    msyslog(LOG_ERR, "Datum_PTS: Problem adding clock");
336    (void)close(datum_pts->PTS_fd);
337
338    return 0;
339  }
340
341  peer->precision = PTSPRECISION;
342  peer->rootdelay = 0;
343  peer->rootdispersion = 0;
344  peer->stratum = 0;
345  memcpy((char *)&peer->refid, DATMREFID, 4);
346
347/*
348** Now add one to the number of units and return a successful code
349*/
350
351  nunits++;
352  return 1;
353
354}
355
356
357/*......................................................................*/
358/*      datum_pts_shutdown - this routine shuts doen the device and     */
359/*      removes the memory for the unit.                                */
360/*......................................................................*/
361
362static void datum_pts_shutdown(unit, peer)
363  int unit;
364  struct peer *peer;
365{
366  int i,j;
367  struct datum_pts_unit **temp_datum_pts_unit;
368
369#ifdef DEBUG_DATUM_PTC
370  if (debug)
371    printf("Shutdown Datum PTS\n");
372#endif
373
374  msyslog(LOG_ERR, "Datum_PTS: Shutdown Datum PTS");
375
376/*
377** First we have to find the right unit (i.e., the one with the same id).
378** We do this by looping through the dynamic array of units intil we find
379** it. Note, that I don't simply use an array with a maximimum number of
380** Datum PTS units. Everything is completely dynamic.
381*/
382
383  for (i=0; i<nunits; i++) {
384    if (datum_pts_unit[i]->unit == unit) {
385
386/*
387** We found the unit so close the file descriptor and free up the memory used
388** by the structure.
389*/
390
391      io_closeclock(&datum_pts_unit[i]->io);
392      close(datum_pts_unit[i]->PTS_fd);
393      free(datum_pts_unit[i]);
394
395/*
396** Now clean up the datum_pts_unit dynamic array so that there are no holes.
397** This may mean moving pointers around, etc., to keep things compact.
398*/
399
400      if (nunits > 1) {
401
402        temp_datum_pts_unit = (struct datum_pts_unit **)
403                malloc((nunits-1)*sizeof(struct datum_pts_unit *));
404        if (i!= 0) memcpy(temp_datum_pts_unit, datum_pts_unit,
405                i*sizeof(struct datum_pts_unit *));
406
407        for (j=i+1; j<nunits; j++) {
408          temp_datum_pts_unit[j-1] = datum_pts_unit[j];
409        }
410
411        free(datum_pts_unit);
412        datum_pts_unit = temp_datum_pts_unit;
413
414      }else{
415
416        free(datum_pts_unit);
417        datum_pts_unit = NULL;
418
419      }
420
421      return;
422
423    }
424  }
425
426#ifdef DEBUG_DATUM_PTC
427  if (debug)
428    printf("Error, could not shut down unit %d\n",unit);
429#endif
430
431  msyslog(LOG_ERR, "Datum_PTS: Could not shut down Datum PTS unit %d",unit);
432
433}
434
435/*......................................................................*/
436/*      datum_pts_poll - this routine sends out the time request to the */
437/*      Datum PTS device. The time will be passed back in the           */
438/*      datum_pts_receive() routine.                                    */
439/*......................................................................*/
440
441static void datum_pts_poll(unit, peer)
442  int unit;
443  struct peer *peer;
444{
445  int i;
446  int index;
447  int error_code;
448  struct datum_pts_unit *datum_pts;
449
450#ifdef DEBUG_DATUM_PTC
451  if (debug)
452    printf("Poll Datum PTS\n");
453#endif
454
455/*
456** Find the right unit and send out a time request once it is found.
457*/
458
459  index = -1;
460  for (i=0; i<nunits; i++) {
461    if (datum_pts_unit[i]->unit == unit) {
462      index = i;
463      datum_pts = datum_pts_unit[i];
464      error_code = write(datum_pts->PTS_fd, TIME_REQUEST, 6);
465      if (error_code != 6) perror("TIME_REQUEST");
466      datum_pts->nbytes = 0;
467      break;
468    }
469  }
470
471/*
472** Print out an error message if we could not find the right unit.
473*/
474
475  if (index == -1) {
476
477#ifdef DEBUG_DATUM_PTC
478    if (debug)
479      printf("Error, could not poll unit %d\n",unit);
480#endif
481
482    msyslog(LOG_ERR, "Datum_PTS: Could not poll unit %d",unit);
483    return;
484
485  }
486
487}
488
489
490/*......................................................................*/
491/*      datum_pts_control - not used                                    */
492/*......................................................................*/
493
494static void datum_pts_control(unit, in, out)
495  int unit;
496  struct refclockstat *in;
497  struct refclockstat *out;
498{
499
500#ifdef DEBUG_DATUM_PTC
501  if (debug)
502    printf("Control Datum PTS\n");
503#endif
504
505}
506
507
508/*......................................................................*/
509/*      datum_pts_init - initializes things for all possible Datum      */
510/*      time code generators that might be used. In practice, this is   */
511/*      only called once at the beginning before anything else is       */
512/*      called.                                                         */
513/*......................................................................*/
514
515static void datum_pts_init()
516{
517
518/*                                                                      */
519/*...... open up the log file if we are debugging ......................*/
520/*                                                                      */
521
522/*
523** Open up the log file if we are debugging. For now, send data out to the
524** screen (stdout).
525*/
526
527#ifdef DEBUG_DATUM_PTC
528  if (debug)
529    printf("Init Datum PTS\n");
530#endif
531
532/*
533** Initialize the time request command string. This is the only message
534** that we ever have to send to the Datum PTS (although others are defined).
535*/
536
537  memcpy(TIME_REQUEST, "//k/mn",6);
538
539/*
540** Initialize the number of units to 0 and set the dynamic array of units to
541** NULL since there are no units defined yet.
542*/
543
544  datum_pts_unit = NULL;
545  nunits = 0;
546
547}
548
549
550/*......................................................................*/
551/*      datum_pts_buginfo - not used                                    */
552/*......................................................................*/
553
554static void datum_pts_buginfo(unit, bug)
555  int unit;
556  register struct refclockbug *bug;
557{
558
559#ifdef DEBUG_DATUM_PTC
560  if (debug)
561    printf("Buginfo Datum PTS\n");
562#endif
563
564}
565
566
567/*......................................................................*/
568/*      datum_pts_receive - receive the time buffer that was read in    */
569/*      by the xntpd io handling routines. When 7 bytes have been       */
570/*      received (it may take several tries before all 7 bytes are      */
571/*      received), then the time code must be unpacked and sent to      */
572/*      the xntpd clock_receive() routine which causes the systems      */
573/*      clock to be updated (several layers down).                      */
574/*......................................................................*/
575
576static void datum_pts_receive(rbufp)
577  struct recvbuf *rbufp;
578{
579  int i;
580  l_fp tstmp;
581  struct datum_pts_unit *datum_pts;
582  char *dpt;
583  int dpend;
584  int tzoff;
585  int timerr;
586  double ftimerr, abserr;
587  u_fp dispersion;
588  int goodtime;
589
590/*
591** Get the time code (maybe partial) message out of the rbufp buffer.
592*/
593
594  datum_pts = (struct datum_pts_unit *)rbufp->recv_srcclock;
595  dpt = (char *)&rbufp->recv_space;
596  dpend = rbufp->recv_length;
597
598#ifdef DEBUG_DATUM_PTC
599  if (debug)
600    printf("Receive Datum PTS: %d bytes\n", dpend);
601#endif
602
603/*                                                                      */
604/*...... save the ntp system time when the first byte is received ......*/
605/*                                                                      */
606
607/*
608** Save the ntp system time when the first byte is received. Note that
609** because it may take several calls to this routine before all seven
610** bytes of our return message are finally received by the io handlers in
611** xntpd, we really do want to use the time tag when the first byte is
612** received to reduce the jitter.
613*/
614
615  if (datum_pts->nbytes == 0) {
616    datum_pts->lastrec = rbufp->recv_time;
617  }
618
619/*
620** Increment our count to the number of bytes received so far. Return if we
621** haven't gotten all seven bytes yet.
622*/
623
624  for (i=0; i<dpend; i++) {
625    datum_pts->retbuf[datum_pts->nbytes+i] = dpt[i];
626  }
627
628  datum_pts->nbytes += dpend;
629
630  if (datum_pts->nbytes != 7) {
631    return;
632  }
633
634/*
635** Convert the seven bytes received in our time buffer to day, hour, minute,
636** second, and msecond values. The usec value is not used for anything
637** currently. It is just the fractional part of the time stored in units
638** of microseconds.
639*/
640
641  datum_pts->day =      100*(datum_pts->retbuf[0] & 0x0f) +
642                                10*((datum_pts->retbuf[1] & 0xf0)>>4) +
643                                (datum_pts->retbuf[1] & 0x0f);
644
645  datum_pts->hour =     10*((datum_pts->retbuf[2] & 0x30)>>4) +
646                                (datum_pts->retbuf[2] & 0x0f);
647
648  datum_pts->minute =   10*((datum_pts->retbuf[3] & 0x70)>>4) +
649                                (datum_pts->retbuf[3] & 0x0f);
650
651  datum_pts->second =   10*((datum_pts->retbuf[4] & 0x70)>>4) +
652                                (datum_pts->retbuf[4] & 0x0f);
653
654  datum_pts->msec =     100*((datum_pts->retbuf[5] & 0xf0) >> 4) +
655                                10*(datum_pts->retbuf[5] & 0x0f) +
656                                ((datum_pts->retbuf[6] & 0xf0)>>4);
657
658  datum_pts->usec =     1000*datum_pts->msec;
659
660#ifdef DEBUG_DATUM_PTC
661  if (debug)
662    printf("day %d, hour %d, minute %d, second %d, msec %d\n",
663        datum_pts->day,
664        datum_pts->hour,
665        datum_pts->minute,
666        datum_pts->second,
667        datum_pts->msec);
668#endif
669
670/*
671** Get the GMT time zone offset. Note that GMT should be zero if the Datum
672** reference time is using GMT as its time base. Otherwise we have to
673** determine the offset if the Datum PTS is using time of day as its time
674** base.
675*/
676
677  goodtime = 0;         /* We are not sure about the time and offset yet */
678
679#ifdef GMT
680
681/*
682** This is the case where the Datum PTS is using GMT so there is no time
683** zone offset.
684*/
685
686  tzoff = 0;            /* set time zone offset to 0 */
687
688#else
689
690/*
691** This is the case where the Datum PTS is using regular time of day for its
692** time so we must compute the time zone offset. The way we do it is kind of
693** funny but it works. We loop through different time zones (0 to 24) and
694** pick the one that gives the smallest error (+- one half hour). The time
695** zone offset is stored in the datum_pts structure for future use. Normally,
696** the clocktime() routine is only called once (unless the time zone offset
697** changes due to daylight savings) since the goodtime flag is set when a
698** good time is found (with a good offset). Note that even if the Datum
699** PTS is using GMT, this mechanism will still work since it should come up
700** with a value for tzoff = 0 (assuming that your system clock is within
701** a half hour of the Datum time (even with time zone differences).
702*/
703
704  for (tzoff=0; tzoff<24; tzoff++) {
705    if (clocktime( datum_pts->day,
706                  datum_pts->hour,
707                  datum_pts->minute,
708                  datum_pts->second,
709                  (tzoff + datum_pts->tzoff) % 24,
710                  datum_pts->lastrec.l_ui,
711                  &datum_pts->yearstart,
712                  &datum_pts->lastref.l_ui) ) {
713
714      error = datum_pts->lastref.l_ui - datum_pts->lastrec.l_ui;
715
716#ifdef DEBUG_DATUM_PTC
717      printf("Time Zone (clocktime method) = %d, error = %d\n", tzoff, error);
718#endif
719
720      if ((error < 1799) && (error > -1799)) {
721        tzoff = (tzoff + datum_pts->tzoff) % 24;
722        datum_pts->tzoff = tzoff;
723        goodtime = 1;
724
725#ifdef DEBUG_DATUM_PTC
726        printf("Time Zone found (clocktime method) = %d\n",tzoff);
727#endif
728
729        break;
730      }
731
732    }
733  }
734
735#endif
736
737/*
738** Make sure that we have a good time from the Datum PTS. Clocktime() also
739** sets yearstart and lastref.l_ui. We will have to set astref.l_uf (i.e.,
740** the fraction of a second) stuff later.
741*/
742
743  if (!goodtime) {
744
745    if (!clocktime( datum_pts->day,
746                  datum_pts->hour,
747                  datum_pts->minute,
748                  datum_pts->second,
749                  tzoff,
750                  datum_pts->lastrec.l_ui,
751                  &datum_pts->yearstart,
752                  &datum_pts->lastref.l_ui) ) {
753
754#ifdef DEBUG_DATUM_PTC
755      if (debug)
756        {
757          printf("Error: bad clocktime\n");
758          printf("GMT %d, lastrec %d, yearstart %d, lastref %d\n",
759                  tzoff,
760                  datum_pts->lastrec.l_ui,
761                  datum_pts->yearstart,
762                  datum_pts->lastref.l_ui);
763        }
764#endif
765
766      msyslog(LOG_ERR, "Datum_PTS: Bad clocktime");
767
768      return;
769
770    }else{
771
772#ifdef DEBUG_DATUM_PTC
773      if (debug)
774        printf("Good clocktime\n");
775#endif
776
777    }
778
779  }
780
781/*
782** We have datum_pts->lastref.l_ui set (which is the integer part of the
783** time. Now set the microseconds field.
784*/
785
786  TVUTOTSF(datum_pts->usec, datum_pts->lastref.l_uf);
787
788/*
789** Compute the time correction as the difference between the reference
790** time (i.e., the Datum time) minus the receive time (system time).
791*/
792
793  tstmp = datum_pts->lastref;           /* tstmp is the datum ntp time */
794  L_SUB(&tstmp, &datum_pts->lastrec);   /* tstmp is now the correction */
795  datum_pts->coderecv++;                /* increment a counter */
796
797  dispersion = DATUM_DISPERSION;        /* set the dispersion to 0 */
798
799#ifdef DEBUG_DATUM_PTC
800  ftimerr = dispersion;
801  ftimerr /= (1024.0 * 64.0);
802  if (debug)
803    printf("dispersion = %d, %f\n", dispersion, ftimerr);
804#endif
805
806/*
807** Pass the new time to xntpd through the refclock_receive function. Note
808** that we are not trying to make any corrections due to the time it takes
809** for the Datum PTS to send the message back. I am (erroneously) assuming
810** that the time for the Datum PTS to send the time back to us is negligable.
811** I suspect that this time delay may be as much as 15 ms or so (but probably
812** less). For our needs at JPL, this kind of error is ok so it is not
813** necessary to use fudge factors in the ntp.conf file. Maybe later we will.
814*/
815
816  refclock_receive(     datum_pts->peer,
817                        &tstmp,
818                        tzoff,
819                        dispersion,
820                        &datum_pts->lastrec,
821                        &datum_pts->lastrec,
822                        datum_pts->leap );
823
824/*
825** Compute sigma squared (not used currently). Maybe later, this could be
826** used for the dispersion estimate. The problem is that xntpd does not link
827** in the math library so sqrt() is not available. Anyway, this is useful
828** for debugging. Maybe later I will just use absolute values for the time
829** error to come up with my dispersion estimate. Anyway, for now my dispersion
830** is set to 0.
831*/
832
833  timerr = tstmp.l_ui<<20;
834  timerr |= (tstmp.l_uf>>12) & 0x000fffff;
835  ftimerr = timerr;
836  ftimerr /= 1024*1024;
837  abserr = ftimerr;
838  if (ftimerr < 0.0) abserr = -ftimerr;
839
840  if (datum_pts->sigma2 == 0.0) {
841    if (abserr < DATUM_MAX_ERROR) {
842      datum_pts->sigma2 = abserr*abserr;
843    }else{
844      datum_pts->sigma2 = DATUM_MAX_ERROR2;
845    }
846  }else{
847    if (abserr < DATUM_MAX_ERROR) {
848      datum_pts->sigma2 = 0.95*datum_pts->sigma2 + 0.05*abserr*abserr;
849    }else{
850      datum_pts->sigma2 = 0.95*datum_pts->sigma2 + 0.05*DATUM_MAX_ERROR2;
851    }
852  }
853
854#ifdef DEBUG_DATUM_PTC
855  if (debug)
856    printf("Time error = %f seconds\n", ftimerr);
857#endif
858
859#if defined(DEBUG_DATUM_PTC) || defined(LOG_TIME_ERRORS)
860  if (debug)
861    printf("PTS: day %d, hour %d, minute %d, second %d, msec %d, Time Error %f\n",
862        datum_pts->day,
863        datum_pts->hour,
864        datum_pts->minute,
865        datum_pts->second,
866        datum_pts->msec,
867        ftimerr);
868#endif
869
870}
871#endif
Note: See TracBrowser for help on using the repository browser.