'===========================================================================
' Subject: Milli-second Delay                 Date: 10-19-03 (  :  )       
'  Author: Michael Webster                    Code: XPB!BASIC              
'  Origin: mfwebster@pdq.net                Packet: DATETIME.ABC
'===========================================================================
' DELAY.BAS

DECLARE SUB SyncTimer ()
DECLARE SUB Delay (millisecond%)

' This program contains a millisecond delay procedure
' that should work reliably under Windows XP, along
' with a support procedure and some test code.
'
' Running under Windows, the actual delay interval
' is somewhat variable, but typically within ~4% of
' the specified interval.

' Calibrate the delay loop count.
Delay 0
' Wait for disk activity to subside.
Delay 2000

SyncTimer

' This test should require 2.00 seconds.
s! = TIMER
FOR i% = 1 TO 200
    Delay 10
NEXT
f! = TIMER
PRINT USING "#.##"; f! - s!

SUB Delay (milliseconds%) STATIC
    ' Delays for <milliseconds%> ms before returning.
    '
    ' Calibrates the delay loop count on first call.

    IF fRun% THEN
        loops& = milliseconds% * loopsPerMs&
        FOR i& = 1 TO loops&
            x! = x! ^ 2
        NEXT
    ELSE
        loops& = 100
        SyncTimer
        DO
            s! = TIMER
            FOR i& = 1 TO loops&
                x! = x! ^ 2
            NEXT
            f! = TIMER
            IF f! > s! + 1 THEN
                fRun% = -1
                EXIT DO
            END IF
            loops& = loops& * 2
        LOOP
        loopsPerMs& = loops& / (f! - s!) / 1000
    END IF
END SUB

SUB SyncTimer
    ' Waits for the next system timer tick before
    ' returning.
    '
    ' The value of the TIMER function changes in
    ' increments of ~55ms, corresponding to the
    ' period of the system timer tick that it is
    ' derived from. Because the timing of an
    ' interval requires two calls to the TIMER
    ' function, the uncertainty in the interval
    ' is ~110ms. Synchronizing with the timer
    ' tick will reduce the uncertainty to ~55ms.
   
    s! = TIMER
    DO
    LOOP UNTIL s! <> TIMER

END SUB

