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 / diftim_l.c < prev    next >
C/C++ Source or Header  |  1996-11-18  |  8KB  |  295 lines

  1. #include "sizint.h"
  2. int diftim(buf,mjd,fday,difp,ls)
  3. char buf[280];        /*time string received from ACTS*/
  4. LONG *mjd;        /*MJD of calibration */
  5. LONG *fday;        /*time of calibration in seconds */
  6. double *difp;        /*time difference, local-ACTS*/
  7. int *ls;        /*leap second flag read from received data*/
  8. {
  9. #include "getdif.h"
  10. #include <stdio.h>
  11. #ifdef IBMPC
  12. #include <dos.h>
  13. #endif
  14. char c;
  15. float xx,interp();                /* holds tick fraction */
  16. LONG cvt2jd();            /*converts yr,mo,day to MJD */
  17. int j,yr,mo,day,hr,min,sec,dst;   /* holds parsed NIST time */
  18. int yribm,moibm,dayibm,hribm,minibm,secibm,hunibm; /* holds computer time */
  19. #ifdef IBMPC
  20. int yrat,moat,dayat,hrat,minat,secat;/* holds CMOS time for AT*/
  21. #endif
  22. int iterr = 0;
  23. #ifdef IBMPC
  24. int lday[13] = {0,31,28,31,30,31,30,31,31,30,31,30,31}; /*last day of month*/
  25. #endif
  26. static int tday[13] = {0,0,31,59,90,120,151,181,212,243,273,304,334};
  27. int done = 0;         /* flag to show when comparison is complete */
  28. #ifdef IBMPC
  29. int dsdone=0;                /* flag to show conversion for daylight sav.*/
  30. int ks;                /*value to be transmitted to interp*/
  31. #endif
  32. #ifdef SUN
  33. #include <sys/time.h>
  34. struct timeval tvv,*tp;
  35. struct tm gvv,*gv;
  36. LONG  kin;            /*value to be transmitted to interp*/
  37. #endif
  38. double diff;            /*local copy of time difference*/
  39. LONG  itdiff;            /*integer version of diff*/
  40. /*
  41.         this subroutine receives a time string in character
  42.         array buf.  it is parsed and compared with the system
  43.         clock.  the origin of the parser is the - character between
  44.         the year and the month so that leading stuff will simply be
  45.         ignored.
  46.  
  47.     the IBMPC version performs the comparison using local time
  48.         this subroutine uses global variables dsflag to check for
  49.         daylight savings time and utcdif to convert from UTC to local
  50.         time
  51.  
  52.     the SUN version performs the comparison using UTC directly
  53.     since that is available from the system
  54.  
  55.     this version differs from the version used for ACTS in that
  56.     it does not print the time difference on the screen but
  57.     rather returns it to the caller
  58.  
  59.  
  60.     the subroutine normally returns a status of 0, and it
  61.     will return a status of -1 if there is a syntax error
  62.     on the input time string.
  63.         begin by getting computer time now.
  64. */
  65. #ifdef IBMPC
  66.     _AH=0;
  67.     geninterrupt(0x1a);    /*get time as number of ticks*/
  68.     ks=_DX;            /*save low half to send to interp*/
  69.         _AH=0x2c;
  70.         geninterrupt(0x21);
  71.         hribm=_CH;
  72.         minibm=_CL;
  73.         secibm=_DH;
  74.         hunibm=_DL;
  75. /*
  76.     also get tick fraction now for interpolating later
  77. */
  78. #if INTERP
  79.     xx=interp((LONG)ks);
  80. #endif
  81.         _AH=0x2a;
  82.         geninterrupt(0x21);
  83.         yribm=_CX;
  84.         moibm=_DH;
  85.         dayibm=_DL;
  86.         yribm -= 1900;
  87. /*
  88.         if this is an at-type machine, read CMOS clock too
  89. */
  90.         if(atflag != 0)
  91.         {
  92.         _AH=2;
  93.         geninterrupt(0x1a);
  94.         hrat=_CH;
  95.         minat=_CL;
  96.         secat=_DH;
  97.         _AH=4;
  98.         geninterrupt(0x1a);
  99.         yrat=_CL;
  100.         moat=_DH;
  101.         dayat=_DL;
  102.         }
  103. #endif
  104. #ifdef SUN
  105.     tp= &tvv;
  106.     gv= &gvv;
  107.     gettimeofday(tp,0);
  108.     kin=tp->tv_usec;
  109. /*
  110.     get tick fraction from interp.  send current microsecond
  111.     value in case value changes while call transfer is in
  112.     progress.
  113. */
  114. #if INTERP
  115.     xx=interp(kin);
  116. #endif
  117.     gv=gmtime(tp);
  118.     yribm=gv->tm_year;
  119.     moibm=gv->tm_mon + 1;
  120.     dayibm=gv->tm_mday;
  121.     hribm=gv->tm_hour;
  122.     minibm=gv->tm_min;
  123.     secibm=gv->tm_sec;
  124.     hunibm=tp->tv_usec/10000;
  125. #endif
  126. /*
  127.         now parse line from NIST transmission
  128. */
  129.         for(j=0; (buf[j] != 0) && (buf[j] != '-') ; j++) ;
  130.         sscanf(&buf[j-2],"%2d-%2d-%2d %2d:%2d:%2d %d %d",&yr,&mo,&day,
  131.         &hr,&min,&sec,&dst,ls);
  132. /*
  133.     check for obvious transmission errors
  134. */
  135.     if( (mo < 1) || (mo > 12) || (day < 1) ||
  136.         (day>31) || (hr < 0 ) || (hr  >23) ||
  137.         (min< 0) || (min> 59) || (sec < 0) ||
  138.         (sec>59) || (dst< 0 ) || (dst > 99)||
  139.         (*ls< 0) || (*ls> 2 )  ) return (-1); 
  140. /*
  141.     if the leap second flag is set then see if the 
  142.     leap second is due today.  if yes, return 10x ls.
  143.     the leap seconds can occur only at the end of
  144.     the months of june or december
  145. */
  146.     if(*ls != 0)        /* if leap second due*/
  147.        {
  148.        if( ( (mo == 6) && (day == 30) ) ||
  149.            ( (mo ==12) && (day == 31) )  ) *ls *= 10;
  150.     }
  151. /*
  152.     for IBMPC version, convert to local time and
  153.     daylight savings time if necessary
  154.  
  155.      note that this conversion is not necessary for the
  156.     SUN which performs the comparison directly on UTC
  157. */
  158. #ifdef IBMPC
  159. /*
  160.         make standard-time portion of dst flag contiguous
  161. */
  162.         if(dst == 0) dst = 100;
  163. /*
  164.         convert from utc to local time. note that minute and second
  165.         are already correct.
  166.         daylight savings time flag must also be updated
  167.         if conversion to local time changes the day
  168.  
  169. */
  170.         if( (yr & 3) == 0 ) lday[2]=29;  /* 29 days for Feb in leap year */
  171.         hr += utcdif;                    /* convert hour to local time */
  172. /*
  173.         also do first part of conversion to daylight savings time
  174.         see parset and arcdif where same problem is dealt with
  175. */
  176.         if( (dsflag != 0) && (dst <= 50) && (dst > 1) )
  177.         {
  178.         hr++;
  179.         dsdone=1;
  180.         }
  181.         if(hr < 0)
  182.         {
  183.         hr += 24;
  184.         day--;
  185.         dst++;         /* update daylight savings flag for change of day*/
  186.         if(day < 1)
  187.            {
  188.            mo--;
  189.            if(mo < 1)
  190.               {
  191.               mo=12;
  192.               yr--;
  193.               }
  194.            day=lday[mo];
  195.            }
  196.         }
  197.         if(hr > 23)
  198.         {
  199.         hr -= 24;
  200.         day++;
  201.         dst--;        /* update daylight saving flag for change of day */
  202.         if(day > lday[mo])
  203.            {
  204.            day=1;
  205.            mo++;
  206.            if(mo > 12)
  207.               {
  208.               mo=1;
  209.               yr++;
  210.               }
  211.            }
  212.         }
  213. /*
  214.         now finish up daylight savings time if enabled
  215. */
  216.         if( (dsflag != 0) && (dsdone == 0) )
  217.         {
  218.            if( (dst == 51) && (hr >= 2) ) hr++;
  219.            if( (dst ==  1) && (hr <  2) ) hr++;
  220.         }
  221. #endif
  222. /*
  223.     save time of calibration in input parameters mjd and
  224.     fday
  225. */
  226.     *mjd=cvt2jd(yr,mo,day);
  227.     *fday=3600*hr + 60*min + sec;
  228. /*
  229.         ready to begin comparing the clocks
  230.     first see if the days are the same
  231. */
  232.         itdiff=365*(yribm - yr) + tday[moibm] - tday[mo] + dayibm - day;
  233.         if( ( (yribm & 3) == 0)  && (moibm > 2) ) itdiff++;
  234.         if( ( (yr    & 3) == 0)  && (mo    > 2) ) itdiff--;
  235.         if( (itdiff > 1) || (itdiff < -1) ) 
  236.            {
  237.        diff = itdiff;
  238.            diff *= 86400;    /*convert days to seconds */
  239.            done=1;
  240.         }
  241.         if(done == 0)
  242.            {
  243.            itdiff= 24*itdiff + hribm - hr;
  244.            if( (itdiff > 2) || (itdiff < -2) )
  245.              {
  246.          diff=itdiff;
  247.              diff *= 3600;    /*convert hours to seconds */
  248.              done=1;
  249.            }
  250.         }
  251.         if(done == 0)
  252.         {
  253.            itdiff=60*itdiff + minibm - min;
  254.            if( (itdiff > 40) || (itdiff < -40) )
  255.              {
  256.          diff=itdiff;
  257.              diff *= 60;    /*convert minutes to seconds */
  258.              done=1;
  259.            }
  260.         }
  261.         if(done == 0)
  262.        {
  263.            diff=60*itdiff + secibm - sec;
  264. #ifdef IBMPC
  265.        diff +=  0.01*(float)hunibm;
  266. #endif
  267. #ifdef SUN
  268.        diff += (double)kin*1e-6;
  269. #endif
  270. /*
  271.     Add the fraction of a tick computed by interp.  this value
  272.         tends to make the local clock later, since this value must be
  273.         added to the integer values read from the system.
  274.         If this is a SUN system, the interval between ticks is defined 
  275.     in the header file nistime.h.  It is typically 20 msec on a Sun, 
  276.     10 msec on a VAX and 3906 usec on a DEC RISC machine.  This number
  277.     is always given in microseconds and is converted to seconds
  278.         here.  Note that the value in paretheses is a tick fraction
  279.         expressed as a percent.  All MS DOS machines uses the same clock
  280.     rate of roughly 18.2 ticks/second or about 55 msec betweek
  281.     ticks.
  282. */
  283. #if INTERP
  284. #ifdef IBMPC
  285.        diff +=  0.000549*(100-xx);
  286. #endif
  287. #ifdef SUN
  288.            diff += ( (double) tickus) *(100-xx)*1e-8;
  289. #endif
  290. #endif
  291.     }
  292.     *difp=diff;
  293.     return(0);        /*return status okay*/
  294. }
  295.