ATARI TIME MACHINE
Machine language timing powerby FRED PINHO
Timer displays are important in many different kinds of programs. For example, game designers couldn't live without timers. Now this article teaches you how to harness the power of Atari's timer registers for your own programs. (To get the most out of this information, you should understand the essentials of machine language programming or be an intermediate BASIC programmer). Demonstration listings are given in both machine language and BASIC. They work on all Atari computers of any memory size, with disk or cassette.
This tutorial explores the electronic gears of the Atari time-piece. Many types of programs are enhanced by timer displays. The Atari has several timer registers which can be programmed in BASIC, but the most accurate timers are written in machine language.
BASIC programmers are probably most familiar with the real-time clock. This is a three-byte count-up timer at locations 18-20 ($12-$14) in memory. The least significant of the three bytes is stored in location 20. Every sixtieth of a second (called a "jiffy") the Atari Operating System (OS) increments this byte. When the value "overflows" (counts past 255) it is reset to zero and the value in location 19 is increased by 1.
Similarly, when the value in 19 overflows, it returns to zero and the value in 18 is incremented. The value in 18 overflows approximately once every 78 hours and all three registers are returned to zero. The three-byte, real-time clock timer can be represented by the following table:
Memory location 18 19 20 Seconds per count 1094 4.272 0.0167
To use this timer in your BASIC program, you must first calculate the total number of jiffies to be timed:
JIFFIES=PEEK(20)+ PEEK(19)* 256+ PEEK(18)*65536
Now, convert jiffies into minutes and seconds:
The biggest problem with using these registers in a BASIC program is that complex BASIC programs, such as games, tend to slow down BASIC timers. The slowdown can be avoided by using machine language timers.
The OS maintains five two-byte countdown timers which count backward from a given number to zero at an approximate rate of 60 times per second. When the timer reaches zero, either a flag byte is set, or a user-defined machine language subroutine is executed. These timers are explained in Figure 1. You must know machine language for timers one or two because the subroutines they call must be written in machine language. The remaining timers may be used from BASIC, but will have the same limitations as the real-time clock.
FIGURE 1 Count Flag Down Located Action on Address of byte Comments Timer at Reaching Subroutine Located Number Zero Stored at at 1 536,537 Calls Subroutine 550,551 - Reserved for OS 2 538,539 Calls Subroutine 552,553 - 3 540,541 Zeros Flag byte - 554 Used by cassette 4 542,543 Zeros Flag Byte - 556 5 544,545 Zeros Flag Byte - 558
The timing routines we will demonstrate use the vertical blank interrupt (VBI) which occurs approximately every sixtieth of a second while the video electron gun is turned off and re-aimed at the top of the screen. Since the VBI actually occurs 59.92334 times per second, our calculations will contain an error of 0.13 percent, or one-third of a second every 255 seconds. This is still accurate enough for our purposes.
Listings 1 and 3 are BASIC programs which demonstrate timers through the use of assembly language routines. The source code for these routines is in Listings 2 and 4. Listing 5 is an example of an all-BASIC timer for comparison.
Type in the BASIC listings, checking them with TYPO II and SAVEing copies. The assembly listings are for instruction and do not need to be typed.
To properly enable the countdown timers, the Atari OS has a machine language routine called SETVBV located in ROM at 58460 ($E45C). To use SETVBV, first store the address of your machine language subroutine (for timers one and two) or set the flag byte to a positive value (for timers three, four, and five). Next, store the countdown time, in jiffies, in the X (high-byte) and Y (low-byte) registers. Finally, store the timer number in the accumulator and code a JSR SETVBV.
First, POKE a 1 into memory location 66 ($42). This allows a routine called CRITIC to temporarily suspend the updating of timers and various other functions. Next, load the countdown time (in jiffies) into your timer routines and set the flag byte. Finally, reset CRITIC to zero. To keep your timers accurate, you must always reset CRITIC to zero as quickly as possible.
Lines 120-220 are the machine language routine which is stored in Page Six of memory. Also used are seven bytes of the cassette buffer (1021-1026, 1028) and two Page Zero bytes (208,209). These bytes function as shown in Figure 2.
The BASIC program first asks for the initial value of the countdown timer, which can be up to 250 seconds. The total number of jiffies is calculated at line 40. This value is changed into low-byte/high-byte format and POKEd into locations 1025 and 1026. The timer active flag is also set to zero. When the program is RUN, the time will be displayed in the lower right corner of the text window. At lines 50 and 60, the position of the text window is determined and the address of the MINUTES display is POKEd into locations 208-209. The timer routine automatically enables timer five in line 70. Here, the timer routine is linked to the vertical blank interrupt.
Finally, location 558, the flag byte, is monitored for a zero value in line 90. This is the signal that timer five has run out. Before checking the flag byte, a short delay is used in line 80 to allow the OS to set up and enable the timer.
FIGURE 2 Memory Locations Function 208-209 Contains the desired starting location of the timer display in lo-byte/hi-byte format. Set by Basic. 1021 Timer active flag. BASIC initializes it to zero to indicate that the timer must be enabled. Enabling is done automatically by the routine. 1022-1024 Used internally by the timer routine. 1025-1026 BASIC stores the total countdown time (in jiffies) here. The value is stored in lo-byte/hi-byte format. 1028 A delay counter. Used internally by the timer routine.
Listing 3 uses the real-time clock at locations 18-20. In this case, the lowest two bytes (19, 20) are used, which limits the timer to 4 minutes, 15 seconds.
Again, the routine is stored in Page Six. Location 1027 holds the task done flag. Initially set to zero, BASIC stores a positive number here when the task is completed, signaling the timer routine which is monitoring this location for a positive number.
A modified display list is used to insert a Graphics 2 text line between the Graphics 7 lines and the text window. Calculations in lines 30 and 40 place the timer display in the middle of the Graphics 2 line. By storing the starting address of the timer display in locations 208-209, the programmer can point the display to any text line on the display list.
The program is designed to monitor the time required to plot the function R = COS(4 * Q) in Graphics 7. This is to demonstrate that BASIC is not significantly slowed by machine language timers. Listing 5 lets BASIC perform all of the timer functions without the help of machine language. RUN the two programs and compare results. Here are some sample results:
Time In Seconds No Timer 168 Machine Language Timer 168 BASIC Timer 218
As you can see, the machine language timer ran significantly faster; and ran less than a second slower than the same program without a timer.
Although these routines are running every sixtieth of a second during the VBI, to increase efficiency the calculation and printing of time is done only every sixth of a second. Since the minimum time increment displayed is one second, there is no need to update the display more frequently.
A delay counter at location 1028 is used to track our display update. A 10 is initially stored there and every VBI decreases the contents of this location by one. The time is calculated and printed only when the delay counter reaches zero.
To change the printing frequency, replace the 10 with your own number in line 160 of listing 1 and line 140 in listing 3.
Fred Pinho of Valley Cottage, New York is a biochemical research engineer a part-time tennis pro and a regular contributor to Antic.