Classic Computer Magazine Archive ANTIC VOL. 4, NO. 5 / SEPTEMBER 1985

Power Programming


Machine language timing power


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
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.

Listing 1: TIMER1.BAS Download

Listing 2: TIMER2.ASM Download / View

Listing 3: TIMER3.BAS Download

Listing 4: TIMER4.ASM Download / View

Listing 5: TIMER5.BAS Download