- [NEW] Afegida la rom de Combat. - [NEW] Afegit mòdul "rom" - [NEW] Ampliats stubs de "mem", "tia" i "pia"
108 lines
5.7 KiB
Plaintext
108 lines
5.7 KiB
Plaintext
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."
|