home *** CD-ROM | disk | FTP | other *** search
/ Power-Programmierung / CD1.mdf / magazine / ins_msc / imc9106 / hrtimer2.c < prev    next >
Text File  |  1991-05-01  |  6KB  |  142 lines

  1. /*********************************************************************
  2. * HRTIMER2.C - This program uses the function HRTimer2() as shown in *
  3. *   Figure E of the article "Designing a high-resolution timer" in   *
  4. *   the May 1991 issue of Inside Microsoft C. It demonstrates some   *
  5. *   of the problems associated with this function.                   *
  6. *********************************************************************/
  7.  
  8. #include <stdio.h>      /* puts()                                   */
  9. #include <conio.h>      /* outp(), inp(), kbhit()                   */
  10. #include <dos.h>        /* disable(), enable()                      */
  11.  
  12. #define MAX_LAG_CYCLES 64
  13. #define COUNTS_PER_uSEC (double)1.19318
  14.  
  15. void HRMode2( void );
  16. void HRMode3( void );
  17. void InitHRTimer( void );
  18. unsigned long HRTimer2( void );
  19.  
  20. unsigned long StartTicker;   /* Holds starting ticker value at init */
  21.  
  22. /*********************************************************************
  23. * HRMode2 - Switch counter 0 to mode 2 and load initial value 65536  *
  24. *********************************************************************/
  25. void HRMode2( void )
  26.     {
  27.     _disable();                   /* Disable interrupts             */
  28.     outp(0x43, 0x34);             /* Counter 0, Mode 2, LSB/MSB     */
  29.     outp(0x40, 0x00);             /* Load low word of valu          */
  30.     outp(0x40, 0x00);             /* Load high word of value        */
  31.     _enable();                    /* Re-enable interrupts           */
  32.     }
  33.  
  34. /*********************************************************************
  35. * HRMode3 - Switch counter 0 to mode 3 and load initial value 65536  *
  36. *********************************************************************/
  37. void HRMode3( void )
  38.     {
  39.     _disable();                   /* Disable interrupts             */
  40.     outp(0x43, 0x36);             /* Counter 0, Mode 3, LSB/MSB     */
  41.     outp(0x40, 0x00);             /* Load low word of value         */
  42.     outp(0x40, 0x00);             /* Load high word of value        */
  43.     _enable();                    /* Re-enable interrupts           */
  44.     }
  45.  
  46. /*********************************************************************
  47. * InitHRTimer - Get StartTicker value from master clock count.       *
  48. *********************************************************************/
  49. void InitHRTimer( void )
  50.     {
  51.     unsigned int far * BiosTicker =
  52.         (unsigned int far *)0x0040006cL;
  53.  
  54.     StartTicker = *BiosTicker;    
  55.     }
  56.  
  57. /*********************************************************************
  58. * HRTimer2 - as shown in Figure E.                                   *
  59. *********************************************************************/
  60. unsigned long HRTimer2( void )
  61.     {
  62.     unsigned int far * BiosTicker =
  63.         (unsigned int far *)0x0040006cL;
  64.     union {
  65.         unsigned long l;
  66.         struct { unsigned int l, h; } i;
  67.         struct { unsigned char l, h; } c;
  68.         } A, B, Ticker;
  69.  
  70.     _disable();                   /* Turn off interrupts            */
  71.     outp(0x43, 0x00);             /* Latch PIT counter 0            */
  72.     A.c.l = inp(0x40);            /* Read low byte of counter 0     */
  73.     A.c.h = inp(0x40);            /* Read high byte of counter 0    */
  74.     Ticker.l = *BiosTicker;       /* Get BIOS's master clock count  */
  75.     _enable();                    /* Turn interrupts back on        */
  76.     A.i.l = 65535 - (--A.i.l);    /* Normalize counter value        */
  77.  
  78.     B.i.l = A.i.l;                /* Copy initial value to B.i.l    */
  79.  
  80.     while ( B.i.l < MAX_LAG_CYCLES )  /* If new cycle, wait a while */
  81.         {                         /* to ensure MCC has been updated */
  82.         _disable();               /* Turn off interrupts            */
  83.         outp(0x43, 0x00);         /* Latch PIT counter 0            */
  84.         B.c.l = inp(0x40);        /* Read low byte of counter 0     */
  85.         B.c.h = inp(0x40);        /* Read high byte of counter 0    */
  86.         Ticker.l = *BiosTicker;   /* Get BIOS's master clock count  */
  87.         _enable();                /* Turn interrupts back on        */
  88.         B.i.l = 65535 - (--B.i.l);/* Normalize counter value        */
  89.         }
  90.  
  91.     Ticker.l -= StartTicker;      /* Subtract start ticker value    */
  92.     A.i.h = Ticker.i.l;           /* Move difference to A.i.h       */
  93.  
  94.     return( A.l );
  95.     }
  96.  
  97. /*********************************************************************
  98. * main - Test loop for HRTimer2().                                   *
  99. *********************************************************************/
  100. void main( void )
  101.     {
  102.     unsigned long time1, time2;
  103.     unsigned long iterations=0;
  104.     unsigned long min=0xffff, max=0;
  105.  
  106.     HRMode2();
  107.     InitHRTimer();
  108.  
  109.     printf( "Testing 32k iterations of HRTimer2(). "
  110.             " Press any key to quit ... \n" );
  111.  
  112.     while ( !kbhit() && iterations < 32768 )
  113.         {
  114.         time1 = HRTimer2();
  115.         time2 = HRTimer2();
  116.         ++iterations;
  117.         if ( time2 < time1 )
  118.             puts( "HRTimer2 error" );
  119.         else
  120.             {
  121.             if ( time2 - time1 > max )
  122.                 {
  123.                 max = time2 - time1;
  124.                 printf( "New max: %lu\n", max );
  125.                 }
  126.             else if ( time2 - time1 < min )
  127.                 {
  128.                     min = time2 - time1;
  129.                     printf( "New min: %lu\n", min );
  130.                 }
  131.             }
  132.         }
  133.  
  134.     if ( iterations >= 16384 )
  135.         printf( "HRTimer2 is accurate to approximately ± %f uSecs.\n",
  136.                 (double)(max - min) / COUNTS_PER_uSEC / 2.0 );
  137.     else
  138.         puts( "Not enough iterations to estimate HRTimer2() accuracy" );
  139.  
  140.     HRMode3();
  141.     }
  142.