- [NEW] Afegits varios documents útils recopilats.
- [NEW] Afegida la rom de Combat. - [NEW] Afegit mòdul "rom" - [NEW] Ampliats stubs de "mem", "tia" i "pia"
This commit is contained in:
1 parent
421826d4b6
commit
22fd027cff
18 files changed
+3768
-1
No files matched your search
@@ -0,0 +1,107 @@
|
||||
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."
|
||||
Reference in new issue
Block a user