129 lines
4.4 KiB
Plaintext
129 lines
4.4 KiB
Plaintext
|
How To Waste Time
|
|||
|
* Copyright 1988 Commodore-Amiga, Inc.
|
|||
|
*
|
|||
|
* Executables based on this information may be used in software
|
|||
|
* for Commodore Amiga computers. All other rights reserved.
|
|||
|
* This information is provided "as is"; no warranties are made. All
|
|||
|
* use is at your own risk. No liability or responsibility is assumed.
|
|||
|
|
|||
|
|
|||
|
The worst way to insert a delay in an Amiga program is this:
|
|||
|
|
|||
|
move.w #2000,d0
|
|||
|
loop dbra loop,d0
|
|||
|
|
|||
|
This loop, or anything like it is *unacceptable*.
|
|||
|
|
|||
|
If running under the multitasking operating system, the
|
|||
|
timer.device can provide delay that still lets other tasks run.
|
|||
|
If taking over the machine, a loop like this is far better:
|
|||
|
|
|||
|
loop btst.b #0,$bfed01
|
|||
|
beq.s loop
|
|||
|
|
|||
|
This uses one of the high speed timer chips. As included example
|
|||
|
shows, the timers are very easy to use. This method is superior
|
|||
|
for a large number of reasons:
|
|||
|
|
|||
|
<EFBFBD> The timer chip loop is more accurate.
|
|||
|
|
|||
|
<EFBFBD> The software loop method fails to produce accurate timing under
|
|||
|
a large number of 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, in what relation to vertical
|
|||
|
blank the code executes in, what the blitter is doing, what
|
|||
|
interrupts are enabled and more other factors than you want to
|
|||
|
think about.
|
|||
|
|
|||
|
<EFBFBD> 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 is counting.
|
|||
|
|
|||
|
<EFBFBD> The timer can produce an interrupt when it is finished, or it
|
|||
|
can set a bit you can examine at any time.
|
|||
|
|
|||
|
<EFBFBD> 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 milisecond (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 perloop. The loop
|
|||
|
above will thus waste about (2000 * 1.5 = 3000)
|
|||
|
microseconds (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.318181 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
|
|||
|
|