home *** CD-ROM | disk | FTP | other *** search
- /*********************************************************************
- * HRTIMER2.C - This program uses the function HRTimer2() as shown in *
- * Figure E of the article "Designing a high-resolution timer" in *
- * the May 1991 issue of Inside Microsoft C. It demonstrates some *
- * of the problems associated with this function. *
- *********************************************************************/
-
- #include <stdio.h> /* puts() */
- #include <conio.h> /* outp(), inp(), kbhit() */
- #include <dos.h> /* disable(), enable() */
-
- #define MAX_LAG_CYCLES 64
- #define COUNTS_PER_uSEC (double)1.19318
-
- void HRMode2( void );
- void HRMode3( void );
- void InitHRTimer( void );
- unsigned long HRTimer2( void );
-
- unsigned long StartTicker; /* Holds starting ticker value at init */
-
- /*********************************************************************
- * HRMode2 - Switch counter 0 to mode 2 and load initial value 65536 *
- *********************************************************************/
- void HRMode2( void )
- {
- _disable(); /* Disable interrupts */
- outp(0x43, 0x34); /* Counter 0, Mode 2, LSB/MSB */
- outp(0x40, 0x00); /* Load low word of valu */
- outp(0x40, 0x00); /* Load high word of value */
- _enable(); /* Re-enable interrupts */
- }
-
- /*********************************************************************
- * HRMode3 - Switch counter 0 to mode 3 and load initial value 65536 *
- *********************************************************************/
- void HRMode3( void )
- {
- _disable(); /* Disable interrupts */
- outp(0x43, 0x36); /* Counter 0, Mode 3, LSB/MSB */
- outp(0x40, 0x00); /* Load low word of value */
- outp(0x40, 0x00); /* Load high word of value */
- _enable(); /* Re-enable interrupts */
- }
-
- /*********************************************************************
- * InitHRTimer - Get StartTicker value from master clock count. *
- *********************************************************************/
- void InitHRTimer( void )
- {
- unsigned int far * BiosTicker =
- (unsigned int far *)0x0040006cL;
-
- StartTicker = *BiosTicker;
- }
-
- /*********************************************************************
- * HRTimer2 - as shown in Figure E. *
- *********************************************************************/
- unsigned long HRTimer2( void )
- {
- unsigned int far * BiosTicker =
- (unsigned int far *)0x0040006cL;
- union {
- unsigned long l;
- struct { unsigned int l, h; } i;
- struct { unsigned char l, h; } c;
- } A, B, Ticker;
-
- _disable(); /* Turn off interrupts */
- outp(0x43, 0x00); /* Latch PIT counter 0 */
- A.c.l = inp(0x40); /* Read low byte of counter 0 */
- A.c.h = inp(0x40); /* Read high byte of counter 0 */
- Ticker.l = *BiosTicker; /* Get BIOS's master clock count */
- _enable(); /* Turn interrupts back on */
- A.i.l = 65535 - (--A.i.l); /* Normalize counter value */
-
- B.i.l = A.i.l; /* Copy initial value to B.i.l */
-
- while ( B.i.l < MAX_LAG_CYCLES ) /* If new cycle, wait a while */
- { /* to ensure MCC has been updated */
- _disable(); /* Turn off interrupts */
- outp(0x43, 0x00); /* Latch PIT counter 0 */
- B.c.l = inp(0x40); /* Read low byte of counter 0 */
- B.c.h = inp(0x40); /* Read high byte of counter 0 */
- Ticker.l = *BiosTicker; /* Get BIOS's master clock count */
- _enable(); /* Turn interrupts back on */
- B.i.l = 65535 - (--B.i.l);/* Normalize counter value */
- }
-
- Ticker.l -= StartTicker; /* Subtract start ticker value */
- A.i.h = Ticker.i.l; /* Move difference to A.i.h */
-
- return( A.l );
- }
-
- /*********************************************************************
- * main - Test loop for HRTimer2(). *
- *********************************************************************/
- void main( void )
- {
- unsigned long time1, time2;
- unsigned long iterations=0;
- unsigned long min=0xffff, max=0;
-
- HRMode2();
- InitHRTimer();
-
- printf( "Testing 32k iterations of HRTimer2(). "
- " Press any key to quit ... \n" );
-
- while ( !kbhit() && iterations < 32768 )
- {
- time1 = HRTimer2();
- time2 = HRTimer2();
- ++iterations;
- if ( time2 < time1 )
- puts( "HRTimer2 error" );
- else
- {
- if ( time2 - time1 > max )
- {
- max = time2 - time1;
- printf( "New max: %lu\n", max );
- }
- else if ( time2 - time1 < min )
- {
- min = time2 - time1;
- printf( "New min: %lu\n", min );
- }
- }
- }
-
- if ( iterations >= 16384 )
- printf( "HRTimer2 is accurate to approximately ± %f uSecs.\n",
- (double)(max - min) / COUNTS_PER_uSEC / 2.0 );
- else
- puts( "Not enough iterations to estimate HRTimer2() accuracy" );
-
- HRMode3();
- }