home *** CD-ROM | disk | FTP | other *** search
/ nisttime.carsoncity.k12.mi.us / nisttime.carsoncity.k12.mi.us.tar / nisttime.carsoncity.k12.mi.us / pub / lockclock / getdif.c < prev    next >
C/C++ Source or Header  |  1996-11-18  |  9KB  |  283 lines

  1. #include "sizint.h"
  2. int cmadr;
  3. int cmport;        /*define the global comport number*/
  4. int getdif(daym,fdaym,delta,xsigma,lsflag,sigmam)
  5. LONG  *daym;        /*MJD of time comparsion*/
  6. LONG  *fdaym;        /*time of comparison in seconds after midnight*/
  7. double *delta;        /*time difference, local-remote*/
  8. double xsigma;        /*tolerance for consecutive differences*/
  9. int *lsflag;        /*leap second flag set on received time */
  10. double *sigmam;        /*noise in current measurements */
  11. {
  12. /*
  13.     this subroutine measures the difference between ACTS and
  14.     the local clock.  it is a stripped-down version of NISTIME
  15.     without most of the flexibility of that program.  the
  16.     configuration file of that program is not used here --
  17.     the corresponding variables are set via include files
  18.     on the assumption that they will not change once the
  19.     program is built.
  20. */
  21. #include <stdio.h>
  22. #include "getdif.h"
  23. #ifdef IBMPC
  24. #include <dos.h>
  25. #endif
  26. char buf[280];
  27. void wrtbuf(),inilin_l(),hangup();
  28. void putmsg(char *);
  29. char msgbuf[80];
  30. int diftim();
  31. int rdbuf();
  32. int dial(int);
  33. int j;
  34. int len;
  35. int lim;
  36. int tmo  = 0;
  37. char ie1 = '*';
  38. char ie2 = '#';
  39. char ie3 = -120;
  40. char ie3a= '>';    /* changed to allow titles to terminate with > after OTM */
  41. LONG mjd[3];            /*MJD of time difference from diftim*/
  42. LONG  fday[3];        /*time of time difference from diftim*/
  43. double diff[3];        /*time difference from diftim*/
  44. int ls[3];        /*leap second flag read from transmissions*/
  45. int kbig,kmid,ksml;    /*largest, middle, smallest difference*/
  46. int conserr;        /*consecutive errors from diftim*/
  47. int alt_num;        /*force dialing of alternate number if 1 */
  48. int dialstat;        /*status returned from dial subroutine */
  49. int difstat;        /*pass dialstat back through difstat*/
  50. int difretry;        /*retry count on time-out */
  51. /*
  52.         following constant sets timeout value for read.
  53.         this version (7 jan 92) uses a time-out value that is
  54.         specified directly in ticks and is not scaled by
  55.         the cpu speed for the PC version.  the value is
  56.         therefore independent of BIOS/non-BIOS access and
  57.         machine speed.
  58. */
  59. #ifdef IBMPC
  60. int ttmo = -72;        /*72 ticks is about 4 seconds */
  61. #endif
  62. #ifdef SUN
  63. int ttmo = -20;
  64. #endif
  65. /*
  66.         initialize serial line. subroutine is variant
  67.     of inilin version used in ACTS.
  68. */
  69.         inilin_l();
  70. /*
  71.         following code sets number of times first loop is done.
  72.         previous versions had a different limit for 300 bits/s, but
  73.         there is no difference in this version since the time can
  74.         now be set at either speed.
  75. */
  76.         lim=8;
  77.     alt_num = 0;    /*start out with standard ACTS number*/
  78.     difstat = 0;    /*normal return status*/
  79.     difretry = 3;    /*allow 3 retries on a time-out*/
  80. /*
  81.         now dial number -- continue if dial status shows connect.
  82.     if dial subroutine cannot connect then return dialer
  83.     status to caller.  this will be a negative integer from
  84.     -1 to -5 if there is a modem error and 
  85.     0 if there is no answer or the line is busy.
  86.  
  87.     if the connection is lost while data are being received,
  88.     then the subroutine returns a status of -6 (if the loss
  89.     is in the first 6 lines) and -7 after that.
  90.  
  91.     A status return of +1 is okay, +2 is okay but one value
  92.     does not agree with the others and +3 means that none
  93.     of the values agree with each other.
  94. */
  95. redial:        /*come here to redial on alternate number*/
  96.         if( (dialstat=dial(alt_num) ) < 1) 
  97.        {
  98.        sprintf(msgbuf,"\n getdif-1, dialstat= %d alt_num= %d difstat=%d",
  99.         dialstat,alt_num,difstat);
  100.        putmsg(msgbuf);
  101.        hangup();        /*be sure modem has hung-up*/
  102.        if(alt_num++ == 0) 
  103.         {
  104.         difstat = 10;
  105.         goto redial;
  106.        }
  107.        close(cmport);
  108.        return(dialstat);
  109.     }
  110. /*
  111.         now start reading from line
  112.         note that 6 lines will be read followed by a time set.
  113.         time-set. note that this version does not distinguish between
  114.         300 and 1200.
  115. */
  116.         for(j=0; j<lim; j++)
  117.            {
  118.            len=rdbuf(buf,ie1,ie2,ie3a,ttmo);
  119.            if( (len > 0) && (buf[0] > 0) )
  120.               wrtbuf(&buf[len-1]);    /* echo terminating character */
  121.            else 
  122.         {
  123.         hangup();
  124.         sprintf(msgbuf,"\n getdif -2, timeout, difstat=%d retry=%d",
  125.             difstat,difretry);
  126.         putmsg(msgbuf);
  127.         if(difretry-- > 0) goto redial;  /*just try again*/
  128.         if(alt_num++ == 0)   /*try again on other number*/
  129.         {
  130.         difstat= 10;
  131.         difretry = 3;
  132.         goto redial;    /*try again on alternate*/
  133.         }
  134.         close(cmport);
  135.         return(-6);    /*time out error */
  136.       }
  137.          }
  138.      if(dialstat == 11) difstat = 10;    /*alternate number*/
  139.  /*
  140.         now read next lines and then check the time for each
  141.     one
  142. */
  143.     j=0;            /*loop counter */
  144.     conserr=3;        /*consecutive error counter*/
  145.     while(j < 3)
  146.           {
  147.           len=rdbuf(buf,ie1,ie2,ie3,ttmo);
  148.           if( (len > 0) && (buf[0] > 0) )
  149.             {
  150.             wrtbuf(&buf[len-1]);
  151. /*
  152.         if diftim returns okay status then advance counter
  153.         and go around again.  otherwise do not count this
  154.         line and try again.  give up if too many consecutive
  155.         errors
  156. */
  157.             if(diftim(buf,&mjd[j],&fday[j],&diff[j],&ls[j]) == 0) j++;
  158.         else    conserr--;        /*decrement consecutive errors*/
  159.  
  160. /*
  161.         return error status if terminator was not # or if there
  162.         were too many consecutive errors
  163. */
  164.         if( (buf[len-1] != ie2) || (conserr < 0) )
  165.         {
  166.         hangup();
  167.             close(cmport);
  168.         return(-8);    /*line delay is not being measured*/
  169.         }
  170.           }
  171.           else 
  172.         {
  173.         hangup();
  174.         close(cmport);
  175.         return(-7);        /*connection was lost */
  176.       }
  177.         }
  178.         hangup();
  179.     close(cmport);
  180. /*
  181.     if all leap second flags are the same then return leap
  182.     second status.  if leap-second flags are not the same
  183.     on all three tries, then we have a problem.  It is possible
  184.     that the day rolled over between transmissions and that
  185.     ls changed at that time.  In that case, report lsflag=-1
  186.     and wait for next time.  The negative signal indicates to
  187.     the caller that the current round should not be used.
  188. */
  189.     if( (ls[0] == ls[1]) && (ls[0] == ls[2]) ) *lsflag=ls[0];
  190.     else *lsflag= -1;
  191. /*
  192.     sort differences into largest, smallest and 
  193.     remaining one which is in between.
  194.     first find largest and smallest differences.
  195. */
  196.     kbig=ksml=0;
  197.     for(j=1; j<3; j++)
  198.        {
  199.        if(diff[j] > diff[kbig]) kbig=j;    /*this is larger*/
  200.        if(diff[j] < diff[ksml]) ksml=j;    /*this is smaller*/
  201.     }
  202.     switch(kbig+ksml)
  203.        {
  204.        case 1:        /*kbig,ksml = 0,1 or 1,0*/
  205.          kmid=2;
  206.          break;
  207.        case 2:        /*kbig,ksml = 0,2 or 2,0*/
  208.          kmid=1;
  209.          break;
  210.        case 3:        /*kbig,ksml = 1,2 or 2,1*/
  211.          kmid=0;
  212.          break;
  213.     }
  214. /*
  215.     if all values differ by less than tolerance,
  216.     then report average. estimate sigmam as equal to
  217.     the p-p scatter. The true RMS value would be 0.35
  218.     of this value if things are really white PM and 
  219.     these values are representative (one-half of 0.7).
  220.     otherwise discard single outlier if possible
  221.     otherwise report failure due to too much noise
  222.  
  223.     it is also possible that the failures are because
  224.     sigma has gotten too small.  The tolerance here
  225.     is actually 3 sigma in the main program, so set
  226.     sigmam to be 0.5 of sigma, which is 1.5X
  227.     the sigma in the main program.
  228.  
  229.     in all cases, report time of mid-point calibration
  230. */
  231.     *daym=mjd[1];
  232.     *fdaym=fday[1];
  233.     if( (diff[kbig] - diff[ksml]) < xsigma)
  234.        {
  235.        *delta=(diff[0] + diff[1] + diff[2])/3;
  236.        *sigmam= diff[kbig] - diff[ksml];
  237.        return(1+difstat);  /*add 10 if from alternate number*/
  238.     }
  239. /*
  240.     we have some kind of trouble -- the values differ
  241.     by more than expected value.
  242.  
  243.     test to see if diff[ksml] is the outlier
  244. */
  245.     if( ( (diff[kbig] - diff[kmid]) <  xsigma)  &&
  246.         ( (diff[kmid] - diff[ksml]) >= xsigma)  )
  247.        {
  248.        *delta=(diff[kbig] + diff[kmid])/2;
  249.        *sigmam=0.5*xsigma;
  250. /*
  251.        show one point dropped
  252. */
  253.        return(2+difstat);
  254.     }
  255. /*
  256.     test to see if diff[kbig] is the outlier
  257. */
  258.     if( ( (diff[kbig] - diff[kmid]) >= xsigma)  &&
  259.         ( (diff[kmid] - diff[ksml]) <  xsigma)  )
  260.        {
  261.        *delta=(diff[kmid] + diff[ksml])/2;
  262.        *sigmam=0.5*xsigma;
  263.        return(2+difstat);
  264.     }
  265. /*
  266.     if we get here then there are two remaining possibilities:
  267.  
  268.     either both differences are <~ sigma so that 
  269.     diff[kbig]-diff[ksml] is of order 2 sigma but neither
  270.     kbig nor ksml is an outlier because both differences
  271.     are about the same or 
  272.     all of them differ from each other by more sigma
  273.     report average but show noisy status.  a return
  274.     value of 4 means that either this cycle is unusually
  275.     noise or sigma is a bit too small.  a return value
  276.     of 3 probably means that something is wrong.
  277. */
  278.     *delta=(diff[0] + diff[1] + diff[2])/3;
  279.     *sigmam=0.5*xsigma;
  280.     if( (diff[kbig] - diff[ksml]) <= 2*xsigma) return(4+difstat);
  281.     else return(3+difstat);
  282. }
  283.