From: https://forums.atariage.com/topic/133686-please-explain-riot-timmers/#comment-1617207


        NOTE about timer initial state from
        (https://forums.atariage.com/topic/256802-two-questions-about-the-pia/):
        - the increment seem to be always set to 1024T (unless you just played
          a game and swap it with the testrom leaving the console unpowered for
          a very short time)
        - the actual timer value is random
        - the interrupt flag is also random


The documentation for the 6532 "RIOT" chip calls it the "interrupt flag register."
The VCS.H file calls it "TIMINT" (for "timer interrupt"). It's located at address
$5 of the RIOT chip. On the Atari 2600, the RIOT chip addresses begin at address
$280, so that means the TIMINT register is at address $285 (and its many mirrors).

This register holds two RIOT interrupt flags-- the timer interrupt flag (bit 7)
and the PA7 edge-detect interrupt flag (bit 6). These flags will trigger IRQ
interrupts, but they have no "real" effect on an Atari 2600, because the Atari
2600 uses a 6507 CPU, and the 6507 chip doesn't have an IRQ line, therefore the
Atari 2600 doesn't have IRQ interrupts.

I don't know if the PA7 edge-detect interrupt flag has any significance for
Atari 2600 programming, so I won't try to explain it. But the timer interrupt
flag can be used to tell if the timer has counted down past 0.

Whenever you set the interval timer by writing a value to TIM1T, TIM8T, TIM64T,
or T1024T, the timer interrupt flag will be cleared automatically. The timer
then counts down to 0, starting from the value you've set it to. The first
decrement occurs right after you set the timer (i.e., 1 cycle later), but the
subsequent decrements occur at the interval you've selected (i.e., after every
1 cycle, 8 cycles, 64 cycles, or 1024 cycles). When the timer reaches 0, it
will stay 0 for the indicated interval, and will then wrap around to 255. The
moment it wraps around from 0 to 255, the timer interrupt flag will be set.
Once the timer has wrapped around and the timer interrupt flag has been set,
the timer will decrement every 1 cycle.

Whenever you read the timer or the timer interrupt flag, the timer interrupt
flag will be cleared. However, the flag will *not* be cleared if you read it
(or the timer) at the same moment that the flag is set.

Anyway, let's suppose you write a value of 5 to TIM8T, which will cause the
timer to count down from 5 to 0 at an interval of 8 cycles. The timer and the
timer interrupt flag will contain the following values:

    Instruction: | Cycle:	  | Timer:	     | Flag:
    -------------|------------|--------------|-------------
    LDA #5	     | 00, 01	  | ???, ???	 | ???, ???
    STA TIM8T	 | 02, ... 05 | ???, ... 005 | ???, ... 000
    		     | 06, ... 13 | 004, ... 004 | 000, ... 000
    		     | 14, ... 21 | 003, ... 003 | 000, ... 000
    		     | 22, ... 29 | 002, ... 002 | 000, ... 000
    		     | 30, ... 37 | 001, ... 001 | 000, ... 000
    		     | 38, ... 45 | 000, ... 000 | 000, ... 000
    		     | 46		  | 255		     | 128
    		     | 47		  | 254		     | 128
    		     | 48		  | 253		     | 128
    		     | etc.	      | etc.		 | etc.

In other words, "LDA #5" takes 2 cycles, and we don't know what the timer or
the flag are set to. "STA TIM8T" takes 4 cycles. On the last cycle of that
instruction, the timer will be set to 5, and the flag will be cleared. On the
very next cycle, the timer will decrement from 5 to 4, but the flag will still
be 0. The timer will stay at 4 for 8 cycles, then it will decrement to 3 and
stay at 3 for 8 cycles, etc. When the timer reaches 0, it will stay at 0 for
8 cycles.

Then the timer will decrement from 0 to 255, and the flag will be set. The
timer flag is bit 7, so it has a value of 128. The timer will continue
decrementing, but it will decrement once each cycle, rather than every 8 cycles
as before.

One way to check when the timer has finished counting down is to read the timer
(or INTIM), which tells us what value is in the timer at that moment. We could
then test the value of the timer to see if it's equal to 0, not equal to 0,
plus/positive (0 to 127), or minus/negative (128 to 255). But that method can
present problems, depending on what value we set the timer to, and how we're
testing its value. For example, if you set the timer to 255, and then test
whether its value is minus, then it will be minus right away. Or if you set the
timer to 64, and then test whether its value is plus, then it will be plus
right away. A more generic test would be to see if its 0 yet-- but that would
mean you aren't waiting until it's counted *past* 0.

Another way to check when the timer has finished counting down is to read the
timer flag (or TIMINT). As long as TIMINT is still 0, the timer hasn't finished
counting down yet. But if TIMINT is 128, then the timer has finished counting
down. If you aren't worried about the PA7 edge-detect interrupt flag (bit 6 of
TIMINT), then you can just use "not equal 0."

So let's say you want to wait for 20 scan lines before doing something. A scan
line is 76 cycles long, so 20 scan lines would be 1520 cycles. Dividing that by
64, we get 23.75. So we could do the following:

        LDA #23
        STA TIM64T
    ; do some stuff here, then start checking the timer flag
    LOOP
        LDA TIMINT
        BEQ LOOP; this will keep looping as long as the flag isn't set yet
        STA WSYNC; finish off the scan line so we resume at the beginning of a scan line
    ; now we've waited 20 scan lines

Note that it takes time to set the timer, and it takes time to read the timer,
so that needs to be factored into the amount of time we set the timer for. You
might need to adjust the number you set the timer to in order to get the desired
result. For example, we might need to use "LDA #22" instead of "LDA #23."
