(c)  Copyright 1989 Commodore-Amiga, Inc.   All rights reserved.
The information contained herein is subject to change without notice, and 
is provided "as is" without warranty of any kind, either expressed or implied.  
The entire risk as to the use of this information is assumed by the user.



                       How To Waste Time

                        by Bryce Nesbitt
        


The worst way to insert a delay in an Amiga program is with a busy-loop
like this:

         move.w #2000,d0
    loop dbra   loop,d0


If you are running under the multitasking operating system, the timer.device 
can provide a delay that still lets other tasks run.  If you are taking over 
the machine, then a loop like this is far better:

    loop btst.b #0,$bfed01
         beq.s  loop

This uses one of the high speed timer chips to provide the delay.  A complete 
example is shown below.  As you can see, the timers are easy to use - it only
takes a few lines of code to run them.  This is a better way to delay for
several reasons:

o  The software loop method fails to produce accurate timings under
   many circumstances.  The speed depends on what CPU is installed 
   in the system, what video mode is selected, what type of memory 
   the program is in, the position of the vertical blank at run
   time, what the blitter is doing, what interrupts are enabled and 
   more other factors than you want to think about.

o  The timer chip can be "set and forgotten".  The chip does the
   counting.  Your code can continue to get other things done while
   the chip timer runs.

o   The timer can produce an interrupt when it is finished, or it
    can set a bit you can examine at any time.

o   The timer can be set to automatically reload the count and
    start again.  This gives even pulses, even if your software can't
    respond to them immediately.


Calculating the Time
--------------------


First some definitions:

    1 millisecond  (ms)  = 1/1,000 second
    1 microsecond (us)  = 1/1,000,000 second
    1 nanosecond  (ns)  = 1/1,000,000,000 second

On a stock 68000 based Amiga with no extra memory, the "DBRA"
instruction listed above will take about 1.5 microseconds per
loop.  So the loop above will waste about 3000 microseconds 
(2000 * 1.5 = 3000)  This is the same as 3 miliseconds, or .003
seconds.

Each 8520 chip has two 16 bit timers counting down at .715909
Mhz, or 1.3968255 microseconds per tick.  To get the same 3
milisecond delay with the 8520, we need to divide the desired
time by the rate;  3000 / 1.3968255 = 2148.


A Complete Example


;
; A complete 8520 timing example.  This blinks the power light at
; (exactly) 3 milisecond intervals.  It takes over the machine,
; so watch out!
;
;
; The base Amiga crytal frequecies are:
;	    NTSC    28.63636  Mhz
;	    PAL     28.37516  Mhz
;
;
;
; The two 16 bit timers on the 8520 chips each count down at 1/10
; the CPU clock, or .715909 Mhz.  That works out to 1.3968255
; microseconds per count.  Under PAL the countdown is a hair
; slower, .709379 Mhz.
;
; To wait 1/100 second would require waiting 10,000 microseconds.
; The timer register would be set to (10,000 / 1.3968255 =
; 7159).
;
; To wait 3 miliseconds would require waiting 3000 microsecsonds.
; The register would be set to (3000 / 1.3968255 = 2148).
;
; See the hardware manual for more information on the 8520 chips.
;
ciaatalo	EQU $bfe401	;Timer A low
ciaatahi	EQU $bfe501	;Timer A high
ciaaicr 	EQU $bfed01	;Interrupt control register
ciaacra 	EQU $bfee01	;Timer A control

		move.w	#$7fff,$dff09a	    ;Kill all custom chip interrupts

;----Setup, only do once
;----This sets timer A to one-shot mode.
		move.b	ciaacra,d0	    ;Set control register A on CIAA
		and.b	#%11000000,d0	    ;Don't trash the 60/50Hz flag
		or.b	#%00001000,d0	    ;or serial direction bits
		move.b	d0,ciaacra
		move.b	#%01111111,ciaaicr  ;Clear all 8520 interrupts

;----Set time (low byte THEN high byte)
;----And the low order with $ff
;----Shift the high order by 8
		move.b	#(2148&255),ciaatalo
		move.b	#(2148>>8),ciaatahi

;----Wait for the timer to count down
busy_wait:
		btst.b	#0,ciaaicr	    ;Wait for timer expired flag
		beq.s	busy_wait
		bchg.b	#1,$bfe001	    ;Blink light
		bset.b	#0,ciaacra	    ;Restart timer
		bra.s	busy_wait

         END


