home *** CD-ROM | disk | FTP | other *** search
/ Liren Large Software Subsidy 7 / 07.iso / c / c082_122 / 5.ddi / CLIBSRC2.ZIP / DELAY.CAS < prev    next >
Encoding:
Text File  |  1992-06-10  |  4.3 KB  |  132 lines

  1. /*---------------------------------------------------------------------------
  2.  * filename - delay.cas
  3.  *
  4.  * function(s)
  5.  *        delay - wait for specified period.
  6.  *--------------------------------------------------------------------------*/
  7.  
  8. /*
  9.  *      C/C++ Run Time Library - Version 5.0
  10.  *
  11.  *      Copyright (c) 1987, 1992 by Borland International
  12.  *      All Rights Reserved.
  13.  *
  14.  */
  15.  
  16.  
  17. #pragma inline
  18. #include <asmrules.h>
  19. #include <dos.h>
  20.  
  21. static unsigned long multiplier = 1193*2L;
  22.  
  23. static void near dummy (void) {}
  24.  
  25. /*--------------------------------------------------------------------------*
  26.  
  27. Name            readtimer - read the complemented value of timer 0
  28.  
  29. Usage           unsigned readtimer (void);
  30.  
  31. Prototype in    local
  32.  
  33. Description     Obtain the complement of the value in timer 0.  The
  34.                 complement is used so that the timer will appear to
  35.                 count up rather than down.  The value returned will
  36.                 range from 0 to 0xffff.
  37.  
  38. Return value    The complement of the value in timer 0.
  39.  
  40. *---------------------------------------------------------------------------*/
  41.  
  42. static unsigned near readtimer (void)
  43. {
  44.   asm pushf                    /* Save interrupt flag                       */
  45.   asm cli                      /* Disable interrupts                        */
  46.   asm mov  al,0h               /* Latch timer 0                             */
  47.   asm out  43h,al
  48.       dummy();                 /* Waste some time */
  49.   asm in   al,40h              /* Counter --> bx                            */
  50.   asm mov  bl,al               /* LSB in BL                                 */
  51.       dummy();                 /* Waste some time */
  52.   asm in   al,40h
  53.   asm mov  bh,al               /* MSB in BH                                 */
  54.   asm not  bx                  /* Need ascending counter                    */
  55.   asm popf                     /* Restore interrupt flag                    */
  56.   return( _BX );
  57. }
  58.  
  59. /*--------------------------------------------------------------------------*
  60.  
  61. Name            timer_init - initialize multiplier for delay function
  62.  
  63. Usage           void timer_init (void);
  64.  
  65. Prototype in    local
  66.  
  67. Description     Determine the multiplier required to convert milliseconds
  68.                 to an equivalent interval timer value.  Interval timer 0
  69.                 is normally programmed in mode 3 (square wave), where
  70.                 the timer is decremented by two every 840 nanoseconds;
  71.                 in this case the multiplier is 2386.  However, some
  72.                 programs and device drivers reprogram the timer in mode 2,
  73.                 where the timer is decremented by one every 840 ns; in this
  74.                 case the multiplier is halved, i.e. 1193.
  75.  
  76.                 When the timer is in mode 3, it will never have an odd value.
  77.                 In mode 2, the timer can have both odd and even values.
  78.                 Therefore, if we read the timer 100 times and never
  79.                 see an odd value, it's a pretty safe assumption that
  80.                 it's in mode 3.  This is the method used in timer_init.
  81.  
  82. Return value    None
  83.  
  84. *---------------------------------------------------------------------------*/
  85.  
  86. static void timer_init(void)
  87. {
  88.     int i;
  89.  
  90.     for (i = 0; i < 100; i++)
  91.         if ((readtimer() & 1) == 0)     /* readtimer() returns complement */
  92.             {
  93.             multiplier = 1193L;
  94.             return;
  95.             }
  96. }
  97.  
  98. #pragma startup timer_init 16
  99.  
  100. /*--------------------------------------------------------------------------*
  101.  
  102. Name            delay - wait for specified period.
  103.  
  104. Usage           void delay(unsigned milliseconds);
  105.  
  106. Prototype in    dos.h
  107.  
  108. Description     The current thread of execution is suspended for the specified
  109.                 number of milliseconds.
  110.  
  111. Return value    None
  112. *---------------------------------------------------------------------------*/
  113.  
  114. void _CType delay( unsigned milliseconds )
  115. {
  116.     unsigned long stop;
  117.     unsigned cur, prev;
  118.  
  119.     stop = (prev = readtimer()) + (milliseconds * multiplier);
  120.  
  121.     while ((cur = readtimer()) < stop)
  122.         {
  123.         if (cur < prev)     /* Check for timer wraparound */
  124.             {
  125.             if (stop < 0x10000L)
  126.                 break;
  127.             stop -= 0x10000L;
  128.             }
  129.         prev = cur;
  130.         }
  131. }
  132.