skip navigation

How does the ATARI 2600 keep time?


In this episode we explore how to use the various timers available for the Atari 2600, including the 1-clock (TIM1T), 8-clock (TIM8T), 64-clock (TIM64T), and 1024-clock (T1024T) timers, how to set the timing interval, reading the timer (INTIM) and how they can be used in the Vertical Blank, and Overscan area's of the CRT television screen.

July 18, 2022

Original Link:


Your support is greatly appreciated!

As we learned in a previous episode, the Atari 2600’s screen is divided into 5 sections. VERTICAL SYNC, VERTICAL BLANK, HORIZONTAL BLANK, The PLAYFIELD, and OVERSCAN.

Vertical Sync is the period when the TV’s CRT beam repositions itself after drawing a complete screen. It takes 3 full scan lines or 228 machine cycles to move the beam from the bottom right of the screen to the top left. Vertical Blank is the period when the beam is generally above the visible portion of most CRT televisions. This lasts for 37 scanlines or 2812 machine cycles.

Horizontal Blank is the period when the beam is repositioning itself from the end of one scanline on the right of the screen to the next scanline on the left. This lasts for about 23 machine cycles for each scanline. The Playfield is the visible portion of the CRT screen. This is about 53 machine cycles for each scanline

Both Horizontal Blank and the Playfield together are generally 192 scanlines in length on NTSC CRTs, for a total of 14,592 machine cycles. Overscan is the period when the beam is generally below the visible portion of most CRT televisions. This lasts for 30 scanlines or 2280 machine cycles. I’ve used the term ‘generally’ a few times because the number of scanlines you use for each section is up to you. However, the numbers we’re going to follow were recommended by atari at the time as being the most stable. on the most NTSC CRTs.

In total, we’re generating 262 scanlines per frame which will give us a nice stable screen.

So far in our videos, we’ve been using loops to count out the number of scan lines we’re generating. Particularly for the Vertical Blank and Overscan. In our loops, we’ve left them empty with the exception of a WSYNC which halts the 6507 processor until we’ve started the next scanline. If we’ve done any additional processing during Vertical Blank or Overscan, we’ve just reduced the number of cycles in the loop to compensate. But this is just wasting cycles, and it’s hard to keep track of how many cycles you still need to generate for each section.

We can make this a lot easier, by using TIMERS.

The MOS Technology 6532 Peripheral Interface Adaptor or PIA for short, provides the ATARI 2600 with its 128 bytes of RAM, the two 8-bit input/output ports, and a programmable interval timer. It’s also known as the RIOT chip, a mashup of RAM, I/O, and Timer. The chip has been used in any number of applications in the 1970s and early 1980s from pinball machines, to disk drives, to the ATARI 2600. We’ve already covered RAM and I/O in previous episodes, so let’s look into the programmable interval timer

The PIA has four timing intervals we can choose from, each one has its own address and the timer is set by writing an interval count of 1 to 255 to that address.

The four intervals available are 1 clock, 8 clocks, 64 clocks, and 1024 clocks.

If you were to write a count of 1 to the 8 clock interval address, the timer would decrement once for every interval elapsed. So after 8 clock ticks, the remaining interval count would be zero.

The PIA and the 6507 microprocessor use the same clock, so the 8 clock interval translates into exactly 8 machine cycles. 1 PIA Timer clock is equal to 1 6507 machine cycle.

Likewise, if you write a count of 4 to the 64 clock interval address then the timer would decrement the interval count every 64 machine cycles. Eventually reaching zero after exactly 256 machine cycles. The remaining clocks can be read at any time using the read address shown on the screen.

When the timer reaches 0 it will hold that count for one interval and then flip the remaining count to 255, and then begins to decrement the count once each clock cycle. This allows the programmer to determine how many clock cycles have elapsed since the timer ended.

Now that we know what a timer is, we need to figure out what it can be used for.

We know from the beginning of the episode that the Vertical Blank is 37 scan lines long, or 2812 machine cycles. Relatively speaking, that’s a large chunk of cycles in one place, In previous examples, we used up these cycles with a basic loop, and wrote to WSYNC to halt the microprocessor until the start of the next scanline. For any frame setup we were executing we would have to count the number of machine cycles and adjust the number of scanlines to use up in our loop. The more code we had, the fewer scanlines we needed to loop through to ensure the Vertical Black period totaled exactly 37.

The PIA Interval timer can help simplify this by setting a timer, doing a bunch of work, and then checking if the timer is completed. It’s a bit more involved than that, but we’ll get into the details later. What we know now is that we need a way to count down 2812 machine cycles, using one of the four available timer intervals.

We can’t use the 1 clock interval, because the maximum interval count you can set is 255. Which would only give us 255 machine cycles. We can’t use the 8-clock interval for the same reason because we would need at least 351 intervals.

However, the 64-clock interval only needs 43.9 to cover 2812 machine cycles. Now that we know what timer to use, let’s look at some code.

When it comes to timers, there’s really not too much code we need to look at, as we see here, we’re going to get a timer to handle the Verticle Blank. We’re already calculated that we need 43 intervals of 64-clocks, so we simply load 43 into a register and then store the value into the 64-clock interval timer.

From the moment you write to the timer register, it will start tracking clocks which will match up perfectly with our machine cycles.

In this bit of code, we’re setting the x position of our player graphic, calculating the pointer address to use for the graphics, and then set a few temporary variables.

That’s all we need to do for this example. After that, we read the interval timer and then branch back in a loop if the current interval count is not zero.

Way down in overscan, we’re doing the exact same thing. Just this time with 35 intervals which we check for input. After, we go into our loop until the current interval count is zero. Then we write to WSYNC to have a clean scanline and move on to the next frame.

If you found the video interesting I’d appreciate it if you’d hit that like button and share this episode to let others know.

If you haven’t already done so, please consider subscribing to the channel, and hit the bell to make sure you’re notified when a new video comes out. If you’d like to help support the development of the channel, please consider becoming a Patron. I’ll link to that in the description as well. Join us on social media. You can connect with us on Instagram, Facebook, and occasionally on Twitter.

That’s all for now, thanks for watching, and I’ll catch you later!

Back to top of page