home *** CD-ROM | disk | FTP | other *** search
- /*---------------------------------------------------------------------------
- * filename - delay.cas
- *
- * function(s)
- * delay - wait for specified period.
- *--------------------------------------------------------------------------*/
-
- /*
- * C/C++ Run Time Library - Version 5.0
- *
- * Copyright (c) 1987, 1992 by Borland International
- * All Rights Reserved.
- *
- */
-
-
- #pragma inline
- #include <asmrules.h>
- #include <dos.h>
-
- static unsigned long multiplier = 1193*2L;
-
- static void near dummy (void) {}
-
- /*--------------------------------------------------------------------------*
-
- Name readtimer - read the complemented value of timer 0
-
- Usage unsigned readtimer (void);
-
- Prototype in local
-
- Description Obtain the complement of the value in timer 0. The
- complement is used so that the timer will appear to
- count up rather than down. The value returned will
- range from 0 to 0xffff.
-
- Return value The complement of the value in timer 0.
-
- *---------------------------------------------------------------------------*/
-
- static unsigned near readtimer (void)
- {
- asm pushf /* Save interrupt flag */
- asm cli /* Disable interrupts */
- asm mov al,0h /* Latch timer 0 */
- asm out 43h,al
- dummy(); /* Waste some time */
- asm in al,40h /* Counter --> bx */
- asm mov bl,al /* LSB in BL */
- dummy(); /* Waste some time */
- asm in al,40h
- asm mov bh,al /* MSB in BH */
- asm not bx /* Need ascending counter */
- asm popf /* Restore interrupt flag */
- return( _BX );
- }
-
- /*--------------------------------------------------------------------------*
-
- Name timer_init - initialize multiplier for delay function
-
- Usage void timer_init (void);
-
- Prototype in local
-
- Description Determine the multiplier required to convert milliseconds
- to an equivalent interval timer value. Interval timer 0
- is normally programmed in mode 3 (square wave), where
- the timer is decremented by two every 840 nanoseconds;
- in this case the multiplier is 2386. However, some
- programs and device drivers reprogram the timer in mode 2,
- where the timer is decremented by one every 840 ns; in this
- case the multiplier is halved, i.e. 1193.
-
- When the timer is in mode 3, it will never have an odd value.
- In mode 2, the timer can have both odd and even values.
- Therefore, if we read the timer 100 times and never
- see an odd value, it's a pretty safe assumption that
- it's in mode 3. This is the method used in timer_init.
-
- Return value None
-
- *---------------------------------------------------------------------------*/
-
- static void timer_init(void)
- {
- int i;
-
- for (i = 0; i < 100; i++)
- if ((readtimer() & 1) == 0) /* readtimer() returns complement */
- {
- multiplier = 1193L;
- return;
- }
- }
-
- #pragma startup timer_init 16
-
- /*--------------------------------------------------------------------------*
-
- Name delay - wait for specified period.
-
- Usage void delay(unsigned milliseconds);
-
- Prototype in dos.h
-
- Description The current thread of execution is suspended for the specified
- number of milliseconds.
-
- Return value None
- *---------------------------------------------------------------------------*/
-
- void _CType delay( unsigned milliseconds )
- {
- unsigned long stop;
- unsigned cur, prev;
-
- stop = (prev = readtimer()) + (milliseconds * multiplier);
-
- while ((cur = readtimer()) < stop)
- {
- if (cur < prev) /* Check for timer wraparound */
- {
- if (stop < 0x10000L)
- break;
- stop -= 0x10000L;
- }
- prev = cur;
- }
- }
-