home *** CD-ROM | disk | FTP | other *** search
/ Power-Programmierung / CD1.mdf / magazine / drdobbs / 1991 / 06 / clock_c.asc next >
Text File  |  1991-05-02  |  22KB  |  668 lines

  1. _USING THE REAL-TIME CLOCK_
  2. by Kenneth Roach
  3.  
  4. [TURBO C VERSION]
  5.  
  6.  
  7. [TIME_C.C]
  8.  
  9. /*
  10. ** TIME_C
  11. ** (C) Copyright 1990 by Kenneth Roach
  12. ** Version date: 3 November, 1990
  13. **
  14. ** This program uses the time and date functions provided by the Turbo-C
  15. ** compiler, as well as similar functions contained in the module TIMELIB.C.
  16. ** TIME_C calls each function for five seconds, counting the number of
  17. ** times the function in question was called.  It then compares the number
  18. ** of times each function was called and displays the results.  Following
  19. ** this, it displays the current date and time obtained from the
  20. ** get_rtc_time function, and as reported and converted by the rtc_time
  21. ** and ctime2 functions.
  22. */
  23.  
  24. #include <stdio.h>
  25. #include <dos.h>
  26. #include <time.h>
  27. #include "timelib.h"
  28.  
  29. long   grt_count = 0L;              /* counter for get_rtc_time() calls */
  30. long   grd_count = 0L;              /* counter for get_rtc_date() calls */
  31. long   rt_count  = 0L;                  /* counter for rtc_time() calls */
  32. long   gt_count  = 0L;                   /* counter for gettime() calls */
  33. long   gd_count  = 0L;                   /* counter for getdate() calls */
  34. long   t_count   = 0L;                      /* counter for time() calls */
  35. long   t2_count  = 0L;                     /* counter for time2() calls */
  36. long   ct2_count = 0L;                    /* counter for ctime2() calls */
  37. long   ct_count  = 0L;                     /* counter for ctime() calls */
  38. struct time t;              /* used in testing of gettime, get_rtc_time */
  39. struct date d;              /* used in testing of getdate, get_rtc_date */
  40. char   *str;                           /* used in testing ctime, ctime2 */
  41. time_t timer;                  /* used in testing time, time2, rtc_time */
  42. long   temp;
  43.  
  44. #define TEST_TIME 5120L              /* 5 seconds * 1024 interrupts per */
  45.  
  46. /*
  47. **  test performance of real time clock based time functions
  48. */
  49.  
  50. void test_rtc()
  51. {
  52.    printf("\nTesting get_rtc_time...");
  53.    temp = rtc_clock();
  54.    do {
  55.       get_rtc_time(&t);
  56.       ++grt_count;
  57.    } while(rtc_clock() - temp < TEST_TIME);      /* count for 5 seconds */
  58.  
  59.    printf("\nTesting get_rtc_date...");
  60.    temp = rtc_clock();
  61.    do {
  62.       get_rtc_date(&d);
  63.       ++grd_count;
  64.    } while(rtc_clock() - temp < TEST_TIME);      /* count for 5 seconds */
  65.  
  66.    printf("\nTesting rtc_time...");
  67.    temp = rtc_clock();
  68.    do {
  69.       rtc_time(&timer);
  70.       ++rt_count;
  71.    } while(rtc_clock() - temp < TEST_TIME);      /* count for 5 seconds */
  72.  
  73.    printf("\nTesting ctime2...");
  74.    temp = rtc_clock();
  75.    do {
  76.       str = ctime2(&timer);
  77.       ++ct2_count;
  78.    } while(rtc_clock() - temp < TEST_TIME);      /* count for 5 seconds */
  79. }
  80.  
  81. /*
  82. **  test performance of C's DOS based time functions
  83. */
  84.  
  85. void test_c()
  86. {
  87.  
  88.    printf("\nTesting gettime...");
  89.    temp = rtc_clock();
  90.    do {
  91.       gettime(&t);
  92.       ++gt_count;
  93.    } while(rtc_clock() - temp < TEST_TIME);      /* count for 5 seconds */
  94.  
  95.    printf("\nTesting getdate...");
  96.    temp = rtc_clock();
  97.    do {
  98.       getdate(&d);
  99.       ++gd_count;
  100.    } while(rtc_clock() - temp < TEST_TIME);      /* count for 5 seconds */
  101.  
  102.    printf("\nTesting time...");
  103.    temp = rtc_clock();
  104.    do {
  105.       time(&timer);
  106.       ++t_count;
  107.    } while(rtc_clock() - temp < TEST_TIME);      /* count for 5 seconds */
  108.  
  109.    printf("\nTesting time2...");
  110.    temp = rtc_clock();
  111.    do {
  112.       time2(&timer);
  113.       ++t2_count;
  114.    } while(rtc_clock() - temp < TEST_TIME);      /* count for 5 seconds */
  115.  
  116.    printf("\nTesting ctime...");
  117.    temp = rtc_clock();
  118.    do {
  119.       str = ctime(&timer);
  120.       ++ct_count;
  121.    } while(rtc_clock() - temp < TEST_TIME);      /* count for 5 seconds */
  122. }
  123.  
  124. /*
  125. ** determine percentage one value represents of another
  126. */
  127.  
  128. long percent(long count1,long count2)
  129. {
  130.    long temp;
  131.    temp = (count1 * 100L) / count2;
  132.    if(((count1 * 100L) % count2) >= 50L)
  133.       ++temp;
  134.    return(temp);
  135. }
  136.  
  137. /*
  138. ** show results of timing tests
  139. */
  140.  
  141. void display_results()
  142. {
  143.    printf("\nTest Summary:\n");
  144.    printf("\ngettime()      called %6ld times\n",gt_count);
  145.    printf("get_rtc_time() called %6ld times\n",grt_count);
  146.    if(grt_count > gt_count)
  147.       printf("get_rtc_time() was %02ld%% the speed of gettime()\n",
  148.                              percent(grt_count,gt_count));
  149.    else
  150.       printf("gettime()      was %02ld%% the speed of get_rtc_time()\n",
  151.                              percent(gt_count,grt_count));
  152.  
  153.    printf("\ngetdate()      called %6ld times\n",gd_count);
  154.    printf("get_rtc_date() called %6ld times\n",grd_count);
  155.    if(grd_count > gd_count)
  156.       printf("get_rtc_date() was %02ld%% the speed of getdate()\n",
  157.                              percent(grd_count,gd_count));
  158.    else
  159.       printf("getdate()      was %02ld%% the speed of get_rtc_date()\n",
  160.                              percent(gd_count,grd_count));
  161.  
  162.    printf("\ntime()         called %6ld times\n",t_count);
  163.    printf("time2()        called %6ld times\n",t2_count);
  164.    printf("rtc_time()     called %6ld times\n",rt_count);
  165.    if(rt_count > t_count)
  166.       printf("rtc_time()     was %02ld%% the speed of time()\n",
  167.                              percent(rt_count,t_count));
  168.    else
  169.       printf("time()         was %02ld%% the speed of rtc_time()\n",
  170.                              percent(t_count,rt_count));
  171.  
  172.    printf("\nctime()        called %6ld times\n",ct_count);
  173.    printf("ctime2()       called %6ld times\n",ct2_count);
  174.    if(ct2_count > ct_count)
  175.       printf("ctime2()       was %02ld%% the speed of ctime()\n",
  176.                              percent(ct2_count,ct_count));
  177.    else
  178.       printf("ctime()        was %02ld%% the speed of ctime2()\n",
  179.                              percent(ct_count,ct2_count));
  180. }
  181.  
  182. void main()
  183. {
  184.    enable_rtc_ints();
  185.  
  186.    clrscr();
  187.  
  188.    test_rtc();          /* test the functions using the real time clock */
  189.    test_c();              /* test the normal C/DOS based time functions */
  190.  
  191.    display_results();
  192.  
  193.    printf("\nEnd of test.\nStart time display.\nDepress any key to stop\n\n");
  194.  
  195.    while(!kbhit())
  196.    {
  197.       get_rtc_time(&t);
  198.       rtc_time(&timer);
  199.       printf("\r%02.2d:%02.2d:%02.2d.%02.2d       %-24.24s",
  200.              t.ti_hour,t.ti_min,t.ti_sec,t.ti_hund,ctime(&timer));
  201.    }
  202.  
  203.    disable_rtc_ints();
  204. }
  205.  
  206.  
  207.  
  208. [TIMELIB.C}
  209.  
  210.  
  211. /*
  212. ** TIMELIB.C
  213. ** (C) Copyright 1990 by Kenneth Roach
  214. ** Version date: 3 November, 1990
  215. **
  216. ** This module contains functions similar to ANSI C's time(), gettime() and
  217. ** getdate(), and clock() functions, but which are based on use of the AT
  218. ** class of system's real time clock.  Additionally, functions are provided
  219. ** to enable and disable periodic interrupts from the real time clock along
  220. ** with an intterupt handler for same.  Interrupts from the real time clock
  221. ** are provided at a rate of 1024 per second, and a function is provided to
  222. ** return the number of interrupts received in the current second.  Also
  223. ** provided is a replacement for the C language's ctime() function which is
  224. ** modestly faster.
  225. */
  226.  
  227. #pragma inline
  228.  
  229. #include <stdio.h>
  230. #include <dos.h>
  231. #include <time.h>
  232. #include "timelib.h"
  233.  
  234. #define  CMOSFLAG       0x70
  235. #define  CMOSDATA       0x71
  236. #define  SECONDS_REQ    0x00
  237. #define  MINUTES_REQ    0x02
  238. #define  HOURS_REQ      0x04
  239. #define  STATUSA        0x0a
  240. #define  STATUSB        0x0b
  241. #define  STATUSC        0x0c
  242. #define  DATE_REQ       0x07
  243. #define  MONTH_REQ      0x08
  244. #define  YEAR_REQ       0x09
  245. #define  CENTURY_REQ    0x32
  246. #define  UPDATE         0x80
  247. #define  BCD            0x04
  248. #define  MASK_24        0x02
  249. #define  HINIBBLE       0xf0
  250. #define  LONIBBLE       0x0f
  251.  
  252. #define  APRIL          4
  253. #define  JUNE           6
  254. #define  SEPTEMBER      9
  255. #define  NOVEMBER       11
  256. #define  FEBRUARY       2
  257.  
  258. #define  RTC_VEC        0x70
  259. #define  IMR2           0xa1
  260. #define  CMD1           0x20
  261. #define  CMD2           0xa0
  262. #define  EOI            0x20
  263. #define  RTC_MASK       0xfe
  264. #define  RTC_FLAG       0x40
  265.  
  266. #define  SECS_PER_DAY   86400L
  267. #define  SECS_PER_YEAR  31536000L
  268. #define  BIAS_10_YEARS  315532800L   /* difference between 1970 and 1980 */
  269. #define  BASE_YEAR      1980
  270. #define  SECS_PER_MIN   60
  271. #define  SECS_PER_HOUR  3600
  272. #define  MINS_PER_HOUR  60
  273. #define  DAYS_PER_YEAR  365
  274. #define  DAYS_PER_WEEK  7
  275. #define  TUESDAY        3                    /* day of week for 1-1-1980 */
  276.  
  277. #define bcd_bin(x)     (bcd) ? ((((x & HINIBBLE) >> 4)\
  278. * 10) + (x & LONIBBLE)) : (x)
  279.  
  280. char months[12][4] = {"Jan","Feb","Mar","Apr","May","Jun",
  281.                       "Jul","Aug","Sep","Oct","Nov","Dec"};
  282. char days[7][4]    = {"Sun","Mon","Tue","Wed","Thu","Fri","Sat"};
  283.  
  284. extern   long timezone;
  285.  
  286. volatile int  rtc_count  = 0;
  287. volatile long tick_count = 0L;
  288.  
  289. void interrupt (*old_rtc_vec)();
  290.  
  291. int func_init = 0;
  292. int bcd  = 0;
  293. int dst  = 0;
  294. unsigned int old_mask;
  295. char time_str[26];
  296.  
  297. /*
  298. ** replacement for the Turbo-C clock() function.  rtc_clock returns
  299. ** a value corresponding to the number of periodic interrupts which
  300. ** have occurred since interrupts from the real time clock were
  301. ** enabled. The value will remain positive for some 24 days from
  302. ** initialization.
  303. */
  304.  
  305. clock_t rtc_clock()
  306. {
  307.    return(tick_count);
  308. }
  309.  
  310. /*
  311. ** millicount returns the real time clock periodic interrupt count for
  312. ** the current second.  Range of value is 0 to 1023.
  313. */
  314.  
  315. int milli_count()
  316. {
  317.    return(rtc_count);
  318. }
  319.  
  320. /*
  321. ** real time clock interrupt handler
  322. */
  323.  
  324. void interrupt rtc()
  325. {
  326.    asm cli;
  327.    outportb(CMOSFLAG,STATUSC); /* get interrupt register identification */
  328.    if((inportb(CMOSDATA) & 0x40) != 0)     /* if a "periodic" interrupt */
  329.    {
  330.       if(++rtc_count == 1024)   /* update nbr times ISR called this sec */
  331.          rtc_count = 0;      /* if start of new second, reset rtc_count */
  332.       else
  333.       {
  334.          outportb(CMOSFLAG,STATUSA);     /* check it again for accuracy */
  335.          if(inportb(CMOSDATA) & UPDATE)
  336.             rtc_count = 0;
  337.       }
  338.       ++tick_count;              /* update total number of times called */
  339.       outportb(CMD1,EOI);    /* signal end of interrupt to primary 8259 */
  340.       outportb(CMD2,EOI);    /* signal end of interrupt to chained 8259 */
  341.    }
  342.    else
  343.       (*old_rtc_vec)();
  344.    asm sti;
  345. }
  346.  
  347. /*
  348. ** turn on interrupts from the real time clock
  349. */
  350.  
  351. void enable_rtc_ints()
  352. {
  353.    rtc_count   = 0;
  354.    tick_count  = 0L;
  355.    old_rtc_vec = getvect(RTC_VEC);
  356.    setvect(RTC_VEC,rtc);                  /* point to interrupt handler */
  357.    outportb(IMR2,inportb(IMR2) & RTC_MASK);   /* enable clock interrupt */
  358.    outportb(CMOSFLAG,STATUSB);
  359.    old_mask = inportb(CMOSDATA);              /* get rtc mask register  */
  360.    outportb(CMOSFLAG,STATUSB);
  361.    outportb(CMOSDATA,old_mask | RTC_FLAG);    /* enable 1k interrupts   */
  362. }
  363.  
  364. /*
  365. ** turn off interrupts from the real time clock
  366. */
  367.  
  368. void disable_rtc_ints()
  369. {
  370.    outportb(CMOSFLAG,STATUSB);
  371.    outportb(CMOSDATA,old_mask);         /* turn off periodic interrupts */
  372.    outportb(IMR2,inportb(IMR2) & ~RTC_MASK);   /* diable RTC interrupts */
  373.    setvect(RTC_VEC,old_rtc_vec);        /* restore old interrupt vector */
  374. }
  375.  
  376. /*
  377. ** replacement for the C language's ctime() function
  378. */
  379.  
  380. char *ctime2(time_t *t)
  381. {
  382.    unsigned int hr,mn,sc;
  383.    unsigned int yr,mo,dy;
  384.    unsigned int bias,dw;
  385.    int    junk,s,tp;
  386.    long   temp;
  387.    time_t time;
  388.  
  389.    time = *t - BIAS_10_YEARS;
  390.    if(dst)
  391.       time -= 3600L;                 /* compensate for daylight savings */
  392.    time -= timezone;
  393.    temp = time % SECS_PER_DAY;         /* get seconds left for this day */
  394.    hr   = temp / SECS_PER_HOUR;             /* determine hours this day */
  395.    temp %=       SECS_PER_HOUR;                  /* lose hours this day */
  396.    mn   = temp / MINS_PER_HOUR;          /* determine minutes this hour */
  397.    sc   = temp % SECS_PER_MIN;         /* determine seconds this minute */
  398.  
  399.    asm cli;
  400.    do                            /* following code duplicated for speed */
  401.       outportb(CMOSFLAG,STATUSA);     /* wait until not in update cycle */
  402.    while(inportb(CMOSDATA) & UPDATE);
  403.    outportb(CMOSFLAG,CENTURY_REQ); s = inportb(CMOSDATA); tp   = bcd_bin(s);
  404.    outportb(CMOSFLAG,YEAR_REQ);    s = inportb(CMOSDATA); bias = bcd_bin(s);
  405.    outportb(CMOSFLAG,MONTH_REQ);   s = inportb(CMOSDATA); mo   = bcd_bin(s);
  406.    outportb(CMOSFLAG,DATE_REQ);    s = inportb(CMOSDATA); dy   = bcd_bin(s);
  407.    asm sti;
  408.  
  409.    bias = bias + tp * 100 - BASE_YEAR;
  410.    temp = time / SECS_PER_DAY;     /* get number of days for this value */
  411.    yr   = temp / DAYS_PER_YEAR;              /* now convert it to years */
  412.    bias >>= 2;                          /* get leap year days for value */
  413.    dy   = temp - yr * DAYS_PER_YEAR - bias;     /* get unprocessed days */
  414.    yr  += BASE_YEAR;                  /* now add in the 1980 start date */
  415.    dw   = time / SECS_PER_DAY + TUESDAY;        /* 1-1-80 was a Tuesday */
  416.    dw  %= DAYS_PER_WEEK;                           /* determine weekday */
  417.    --dw;
  418.    s  = 1;                            /* now determine the month's name */
  419.    mo = 0;
  420.    while(s)                    /* process total remaining days for year */
  421.    {
  422.       junk = 0;
  423.       switch(s)
  424.       {
  425.          case APRIL:                    /* first do months with 30 days */
  426.          case JUNE:
  427.          case SEPTEMBER:
  428.          case NOVEMBER: if(dy  >= 30)
  429.                            junk = 30;     break;
  430.          case FEBRUARY: if((yr >> 2) == 0)     /* special case february */
  431.                            if(dy  >= 29)
  432.                               junk = 29;           /* process leap year */
  433.                            else
  434.                               ;
  435.                         else if(dy >= 28)            /* not a leap year */
  436.                            junk = 28;     break;
  437.          default:       if(dy  >= 31)
  438.                            junk = 31;         /* else month has 31 days */
  439.       }
  440.       if(junk)
  441.       {
  442.          ++mo;                      /* account for month just processed */
  443.          ++s;                                        /* bump case index */
  444.          dy -= junk;                    /* subtract days just processed */
  445.       }
  446.       else
  447.          s = 0;             /* Dy is less than 1 month, clear while var */
  448.    }
  449.  
  450.    time_str[0]  = days[dw][0];    /* now convert all values to a string */
  451.    time_str[1]  = days[dw][1];       /* avoid call to sprintf for speed */
  452.    time_str[2]  = days[dw][2];
  453.    time_str[4]  = months[mo][0];
  454.    time_str[5]  = months[mo][1];
  455.    time_str[6]  = months[mo][2];
  456.    time_str[8]  = dy /   10 + '0';
  457.    time_str[9]  = dy %   10 + '0';
  458.    time_str[11] = hr /   10 + '0';
  459.    time_str[12] = hr %   10 + '0';
  460.    time_str[14] = mn /   10 + '0';
  461.    time_str[15] = mn %   10 + '0';
  462.    time_str[17] = sc /   10 + '0';
  463.    time_str[18] = sc %   10 + '0';
  464.    time_str[20] = yr / 1000 + '0';  yr %= 1000;
  465.    time_str[21] = yr /  100 + '0';  yr %= 100;
  466.    time_str[22] = yr /   10 + '0';
  467.    time_str[23] = yr %   10 + '0';
  468.    time_str[24] = '\n';
  469.    time_str[25] = 0;
  470.    time_str[3]  = time_str[7]  = time_str[10] = time_str[19] = ' ';
  471.    time_str[13] = time_str[16] = ':';
  472.    return(time_str);
  473. }
  474.  
  475. /*
  476. ** replacement for Turbo-C's gettime() function
  477. */
  478.  
  479. void get_rtc_time(struct time *timep)
  480. {
  481.    int h,m,s;
  482.    if(!func_init)
  483.       init_time();                       /* assure we have info we need */
  484.    asm cli;
  485.    do
  486.       outportb(CMOSFLAG,STATUSA);     /* wait until not in update cycle */
  487.    while(inportb(CMOSDATA) & UPDATE);
  488.  
  489.    outportb(CMOSFLAG,HOURS_REQ);                         /* get hours   */
  490.    h = inportb(CMOSDATA); timep->ti_hour = bcd_bin(h);
  491.    outportb(CMOSFLAG,MINUTES_REQ);                       /* get minutes */
  492.    m = inportb(CMOSDATA); timep->ti_min  = bcd_bin(m);
  493.    outportb(CMOSFLAG,SECONDS_REQ);                       /* get seconds */
  494.    s = inportb(CMOSDATA);    timep->ti_sec  = bcd_bin(s);
  495.    asm sti;
  496.    s = rtc_count / 10;                        /* rtc_count goes to 1024 */
  497.    if(s > 75)                  /* correct for values to 102 each second */
  498.       s -= 3;
  499.    else if(s > 50)
  500.       s -= 2;
  501.    else if(s > 25)
  502.       --s;
  503.    timep->ti_hund = s;
  504. }
  505.  
  506. /*
  507. ** replacement for Turbo-C's getdate() function
  508. */
  509.  
  510. void get_rtc_date(struct date *datep)
  511. {
  512.    int d,m,y,t,s;
  513.    if(!func_init)
  514.       init_time();                       /* assure we have info we need */
  515.    asm cli;
  516.    do
  517.       outportb(CMOSFLAG,STATUSA);     /* wait until not in update cycle */
  518.    while(inportb(CMOSDATA) & UPDATE);
  519.  
  520.    outportb(CMOSFLAG,CENTURY_REQ);                       /* get century */
  521.    s  = inportb(CMOSDATA);   t              = bcd_bin(s);
  522.    outportb(CMOSFLAG,YEAR_REQ);                          /* get year    */
  523.    y = inportb(CMOSDATA);    datep->da_year = bcd_bin(y);
  524.    outportb(CMOSFLAG,MONTH_REQ);                         /* get month   */
  525.    m = inportb(CMOSDATA);    datep->da_mon  = bcd_bin(m);
  526.    outportb(CMOSFLAG,DATE_REQ);                          /* get day     */
  527.    d = inportb(CMOSDATA);    datep->da_day  = bcd_bin(d);
  528.    asm sti;
  529.    datep->da_year = datep->da_year + t * 100;         /* add in century */
  530. }
  531.  
  532. /*
  533. ** replacement for Turbo-C's time() function
  534. */
  535.  
  536. time_t rtc_time(time_t *result)
  537. {
  538.    time_t   hr;
  539.    unsigned s,b,yr,sc,mn,mo,dy;
  540.    if(!func_init)
  541.       init_time();                       /* assure we have info we need */
  542.    asm cli;                   /* following code is duplicated for speed */
  543.    do
  544.       outportb(CMOSFLAG,STATUSA);        /* wait until not update cycle */
  545.    while(inportb(CMOSDATA) & UPDATE);
  546.  
  547.    outportb(CMOSFLAG,SECONDS_REQ);                       /* get seconds */
  548.    s  = inportb(CMOSDATA);   sc = bcd_bin(s);
  549.    outportb(CMOSFLAG,MINUTES_REQ);                       /* get minutes */
  550.    s  = inportb(CMOSDATA);   mn = bcd_bin(s);
  551.    outportb(CMOSFLAG,HOURS_REQ);                         /* get hours   */
  552.    s  = inportb(CMOSDATA);   hr = bcd_bin(s);
  553.  
  554.    outportb(CMOSFLAG,YEAR_REQ);                          /* get year    */
  555.    s  = inportb(CMOSDATA);   yr = bcd_bin(s);
  556.    outportb(CMOSFLAG,CENTURY_REQ);                       /* get century */
  557.    s  = inportb(CMOSDATA);   b  = bcd_bin(s);
  558.    outportb(CMOSFLAG,MONTH_REQ);                         /* get month   */
  559.    s  = inportb(CMOSDATA);   mo = bcd_bin(s);
  560.    outportb(CMOSFLAG,DATE_REQ);                          /* get day     */
  561.    s  = inportb(CMOSDATA);   dy = bcd_bin(s);
  562.    asm sti;
  563.  
  564.    mn = mn * 60 + sc;                     /* convert minutes to seconds */
  565.    hr = hr * 3600 + mn + timezone;          /* convert hours to seconds */
  566.    yr = yr + b * 100 - 1980;                    /* get years since 1980 */
  567.    dy = dy + (yr >> 2);                  /* correct days for leap years */
  568.    s  = 1;
  569.    while(s < mo)                              /* add days for this year */
  570.       switch(s++)
  571.       {
  572.          case APRIL:                             /* months with 30 days */
  573.          case JUNE:
  574.          case SEPTEMBER:
  575.          case NOVEMBER:   dy += 30L;                              break;
  576.          case FEBRUARY:   dy += ((yr >> 2) == 0)  ?  29L  :  28L; break;
  577.          default:         dy += 31L;          /* else month has 31 days */
  578.       }
  579.    if(dst)
  580.       hr -= 3600L;                   /* compensate for daylight savings */
  581.    return(*result = (yr * SECS_PER_YEAR +         /* return final value */
  582.                      dy * SECS_PER_DAY  +
  583.                      hr + BIAS_10_YEARS)); /* 10 yr bias for difference */
  584.                                         /* between 1970 and 1980 (secs) */
  585. }
  586.  
  587. /*
  588. ** replacement for Turbo-C's time() function
  589. */
  590.  
  591. time_t time2(time_t *result)
  592. {
  593.    time_t   hr;
  594.    unsigned s,yr,mn,mo,dy;
  595.    struct date d;
  596.    struct time t;
  597.    asm cli;
  598.  
  599.    getdate(&d);
  600.    gettime(&t);
  601.    mn = t.ti_min * 60 + t.ti_sec;         /* convert minutes to seconds */
  602.    hr = t.ti_hour * 3600 + mn + timezone;   /* convert hours to seconds */
  603.    yr = d.da_year - 1980;                       /* get years since 1980 */
  604.    dy = d.da_day + (yr >> 2);            /* correct days for leap years */
  605.    s  = 1;
  606.    mo = d.da_mon;
  607.    while(s < mo)                              /* add days for this year */
  608.       switch(s++)
  609.       {
  610.          case APRIL:                             /* months with 30 days */
  611.          case JUNE:
  612.          case SEPTEMBER:
  613.          case NOVEMBER:   dy += 30L;                              break;
  614.          case FEBRUARY:   dy += ((yr >> 2) == 0)  ?  29L  :  28L; break;
  615.          default:         dy += 31L;          /* else month has 31 days */
  616.       }
  617.    if(dst)
  618.       hr -= 3600L;                   /* compensate for daylight savings */
  619.    asm sti;
  620.    return(*result = (yr * SECS_PER_YEAR +         /* return final value */
  621.                      dy * SECS_PER_DAY  +
  622.                      hr + BIAS_10_YEARS)); /* 10 yr bias for difference */
  623.                                         /* between 1970 and 1980 (secs) */
  624. }
  625. /*
  626. ** initialize variables for rtc time and date functions
  627. */
  628.  
  629. void init_time()
  630. {
  631.    struct tm *cur_time;
  632.    time_t timer;
  633.    time(&timer);                           /* kick start TC's time code */
  634.    cur_time = localtime(&timer);     /* check for daylight savings time */
  635.    dst      = cur_time->tm_isdst;
  636.    outportb(CMOSFLAG,STATUSB);              /* get mode the clock is in */
  637.    bcd      = (inportb(CMOSDATA) & BCD) == 0;    /*   (binary or BCD)   */
  638.    outportb(CMOSFLAG,STATUSB);
  639.    outportb(CMOSDATA,inportb(CMOSDATA) | MASK_24);/* force 24 hour mode */
  640.    func_init = 1;
  641. }
  642.  
  643.  
  644.  
  645. [TIMELIB.H]
  646.  
  647.  
  648. /*
  649. ** TIMELIB.H
  650. **
  651. ** prototype declarations for TIMELIB.C
  652. */
  653.  
  654.  
  655. clock_t rtc_clock();
  656. int     milli_count();
  657. void    enable_rtc_ints();
  658. void    disable_rtc_ints();
  659. void    get_rtc_time(struct time *timep);
  660. void    get_rtc_date(struct date *datep);
  661. time_t  rtc_time(time_t *result);
  662. time_t  time2(time_t *result);
  663. void    init_time();
  664. char    *ctime2();
  665.  
  666.  
  667.  
  668.