APU Frame Counter: Difference between revisions
(Also specify reg) |
mNo edit summary |
||
(7 intermediate revisions by 6 users not shown) | |||
Line 5: | Line 5: | ||
The frame counter contains the following: [[APU Misc|divider]], looping clock [[APU Misc|sequencer]], frame interrupt flag. | The frame counter contains the following: [[APU Misc|divider]], looping clock [[APU Misc|sequencer]], frame interrupt flag. | ||
The sequencer is clocked on every other CPU cycle, so 2 CPU cycles = 1 APU cycle. The sequencer keeps track of how many APU cycles have elapsed in total, and each step of the sequence will occur once that total has reached the indicated amount. Once the last step has executed, the count resets to 0 on the next APU cycle. | The sequencer is clocked on every other CPU cycle, so 2 CPU cycles = 1 APU cycle. The sequencer keeps track of how many APU cycles have elapsed in total, and each step of the sequence will occur once that total has reached the indicated amount (with an additional delay of one CPU cycle for the quarter and half frame signals). Once the last step has executed, the count resets to 0 on the next APU cycle. | ||
{| class="tabular" | {| class="tabular" | ||
Line 16: | Line 16: | ||
| Bit 6 || <tt>-I-- ----</tt> || Interrupt inhibit flag. If set, the frame interrupt flag is cleared, otherwise it is unaffected. | | Bit 6 || <tt>-I-- ----</tt> || Interrupt inhibit flag. If set, the frame interrupt flag is cleared, otherwise it is unaffected. | ||
|- | |- | ||
|colspan=2| Side effects || After | |colspan=2| Side effects || After 3 or 4 CPU clock cycles*, the timer is reset.<br>If the mode flag is set, then both "quarter frame" and "half frame" signals are also generated. | ||
|} | |} | ||
<nowiki>*</nowiki> If the write occurs ''during'' an APU cycle, the effects occur | <nowiki>*</nowiki> If the write occurs ''during'' an APU cycle, the effects occur 3 CPU cycles after the '''$4017''' write cycle, and if the write occurs ''between'' APU cycles, the effects occurs 4 CPU cycles after the write cycle. | ||
PAL behavior is currently assumed to be the same. | |||
The frame interrupt flag is connected to the [[CPU]]'s IRQ line. It is set at a particular point in the 4-step sequence (see below) provided the interrupt inhibit flag in $4017 is clear, and can be cleared either by reading $4015 (which also returns its old status) or by setting the interrupt inhibit flag. | The frame interrupt flag is connected to the [[CPU]]'s IRQ line. It is set at a particular point in the 4-step sequence (see below) provided the interrupt inhibit flag in $4017 is clear, and can be cleared either by reading $4015 (which also returns its old status) or by setting the interrupt inhibit flag. | ||
Line 26: | Line 26: | ||
=== Mode 0: 4-Step Sequence (bit 7 of $4017 clear) === | === Mode 0: 4-Step Sequence (bit 7 of $4017 clear) === | ||
{| class="tabular" | {| class="tabular" | ||
| Step | ! rowspan=2 | Step | ||
! colspan=2 | APU cycles | |||
! rowspan=2 | [[APU Envelope|Envelopes]] & [[APU Triangle|triangle's linear counter]]<br/>(Quarter frame) | |||
! rowspan=2 | [[APU Length Counter|Length counters]] & [[APU Sweep|sweep units]]<br/>(Half frame) | |||
! rowspan=2 | Frame interrupt flag | |||
|- | |- | ||
| | ! NTSC || PAL | ||
|- | |- | ||
| | | 1 || 3728.5 || 4156.5 || Clock || || | ||
|- | |- | ||
| | | 2 || 7456.5 || 8313.5 || Clock || Clock || | ||
|- | |- | ||
| | | 3 || 11185.5 || 12469.5 || Clock || || | ||
|- | |- | ||
| | | rowspan=3 | 4 || 14914 || 16626 || || || Set if interrupt inhibit is clear | ||
|- | |- | ||
| | | 14914.5 || 16626.5 || Clock || Clock || Set if interrupt inhibit is clear | ||
|- | |- | ||
| || || ''240 Hz (approx.)'' || ''120 Hz (approx.)'' || ''60 Hz (approx.)'' | | 0 (14915) || 0 (16627) || || || Set if interrupt inhibit is clear | ||
|- | |||
| || colspan=2 | || NTSC: ''240 Hz (approx.)''<br/>PAL: ''200 Hz (approx)'' || NTSC: ''120 Hz (approx.)''<br/>PAL: ''100 Hz (approx)'' || NTSC: ''60 Hz (approx.)''<br/>PAL: ''50 Hz (approx)'' | |||
|} | |} | ||
In this mode, the interrupt flag is set every 29830 CPU cycles, which is slightly slower than the 29780.5 CPU cycles per NTSC PPU frame. | In this mode, the interrupt flag is set every 29830 CPU cycles, which is slightly (0.166%) slower than the 29780.5 CPU cycles per NTSC PPU frame. | ||
Some Nintendo arcade boards, even those not directly based on the NES, use the 2A03 CPU as a sound processor. | On the PAL RP2A07, this is every 33254 CPU cycles, still slower than the 33247.5 CPU cycles per PAL PPU frame but much closer (only off by 0.0196%). | ||
This IRQ allows the CPU to keep time even if no PPU is connected to the bus. | Some Nintendo arcade boards, even those not directly based on the NES, use the 2A03 CPU as a sound processor. Examples include ''[[wikipedia:Punch-Out!! (arcade game)|Punch-Out!!]]'' and ''[[wikipedia:Donkey Kong 3|Donkey Kong 3]]''. This IRQ allows the CPU to keep time even if no PPU is connected to the bus. | ||
=== Mode 1: 5-Step Sequence (bit 7 of $4017 set) === | === Mode 1: 5-Step Sequence (bit 7 of $4017 set) === | ||
{| class="tabular" | {| class="tabular" | ||
| Step | ! rowspan=2 | Step | ||
! colspan=2 | APU cycles | |||
! rowspan=2 | [[APU Envelope|Envelopes]] & [[APU Triangle|triangle's linear counter]]<br/>(Quarter frame) | |||
! rowspan=2 | [[APU Length Counter|Length counters]] & [[APU Sweep|sweep units]]<br/>(Half frame) | |||
|- | |||
! NTSC || PAL | |||
|- | |- | ||
| 1 || 3728 || Clock || | | 1 || 3728.5 || 4156.5 || Clock || | ||
|- | |- | ||
| 2 || 7456 || Clock || Clock | | 2 || 7456.5 || 8313.5 || Clock || Clock | ||
|- | |- | ||
| 3 || 11185 || Clock || | | 3 || 11185.5 || 12469.5 || Clock || | ||
|- | |- | ||
| 4 || 14914 || || | | 4 || 14914.5 || 16626.5 || || | ||
|- | |- | ||
| 5 || 18640 || Clock || Clock | | rowspan=2 | 5 || 18640.5 || 20782.5 || Clock || Clock | ||
|- | |- | ||
| | | 0 (18641) || 0 (20783) || || | ||
|- | |- | ||
| || || ''192 Hz (approx.), uneven timing'' || ''96 Hz (approx.), uneven timing'' | | || colspan=2 | || NTSC: ''192 Hz (approx.), uneven timing''<br/>PAL: ''160 Hz (approx.), uneven timing'' || NTSC: ''96 Hz (approx.), uneven timing''<br/>PAL: ''80 Hz (approx.), uneven timing'' | ||
|} | |} | ||
In this mode, the frame interrupt flag is never set.<br> | In this mode, the frame interrupt flag is never set.<br> | ||
Latest revision as of 18:00, 2 July 2022
The NES APU frame counter (or frame sequencer) generates low-frequency clocks for the channels and an optional 60 Hz interrupt. The name "frame counter" might be slightly misleading because the clocks have nothing to do with the video signal.
The frame counter contains the following: divider, looping clock sequencer, frame interrupt flag.
The sequencer is clocked on every other CPU cycle, so 2 CPU cycles = 1 APU cycle. The sequencer keeps track of how many APU cycles have elapsed in total, and each step of the sequence will occur once that total has reached the indicated amount (with an additional delay of one CPU cycle for the quarter and half frame signals). Once the last step has executed, the count resets to 0 on the next APU cycle.
Address | Bitfield | Description |
$4017 | MI--.---- | Set mode and interrupt (write) |
Bit 7 | M--- ---- | Sequencer mode: 0 selects 4-step sequence, 1 selects 5-step sequence |
Bit 6 | -I-- ---- | Interrupt inhibit flag. If set, the frame interrupt flag is cleared, otherwise it is unaffected. |
Side effects | After 3 or 4 CPU clock cycles*, the timer is reset. If the mode flag is set, then both "quarter frame" and "half frame" signals are also generated. |
* If the write occurs during an APU cycle, the effects occur 3 CPU cycles after the $4017 write cycle, and if the write occurs between APU cycles, the effects occurs 4 CPU cycles after the write cycle.
PAL behavior is currently assumed to be the same.
The frame interrupt flag is connected to the CPU's IRQ line. It is set at a particular point in the 4-step sequence (see below) provided the interrupt inhibit flag in $4017 is clear, and can be cleared either by reading $4015 (which also returns its old status) or by setting the interrupt inhibit flag.
Mode 0: 4-Step Sequence (bit 7 of $4017 clear)
Step | APU cycles | Envelopes & triangle's linear counter (Quarter frame) |
Length counters & sweep units (Half frame) |
Frame interrupt flag | |
---|---|---|---|---|---|
NTSC | PAL | ||||
1 | 3728.5 | 4156.5 | Clock | ||
2 | 7456.5 | 8313.5 | Clock | Clock | |
3 | 11185.5 | 12469.5 | Clock | ||
4 | 14914 | 16626 | Set if interrupt inhibit is clear | ||
14914.5 | 16626.5 | Clock | Clock | Set if interrupt inhibit is clear | |
0 (14915) | 0 (16627) | Set if interrupt inhibit is clear | |||
NTSC: 240 Hz (approx.) PAL: 200 Hz (approx) |
NTSC: 120 Hz (approx.) PAL: 100 Hz (approx) |
NTSC: 60 Hz (approx.) PAL: 50 Hz (approx) |
In this mode, the interrupt flag is set every 29830 CPU cycles, which is slightly (0.166%) slower than the 29780.5 CPU cycles per NTSC PPU frame.
On the PAL RP2A07, this is every 33254 CPU cycles, still slower than the 33247.5 CPU cycles per PAL PPU frame but much closer (only off by 0.0196%).
Some Nintendo arcade boards, even those not directly based on the NES, use the 2A03 CPU as a sound processor. Examples include Punch-Out!! and Donkey Kong 3. This IRQ allows the CPU to keep time even if no PPU is connected to the bus.
Mode 1: 5-Step Sequence (bit 7 of $4017 set)
Step | APU cycles | Envelopes & triangle's linear counter (Quarter frame) |
Length counters & sweep units (Half frame) | |
---|---|---|---|---|
NTSC | PAL | |||
1 | 3728.5 | 4156.5 | Clock | |
2 | 7456.5 | 8313.5 | Clock | Clock |
3 | 11185.5 | 12469.5 | Clock | |
4 | 14914.5 | 16626.5 | ||
5 | 18640.5 | 20782.5 | Clock | Clock |
0 (18641) | 0 (20783) | |||
NTSC: 192 Hz (approx.), uneven timing PAL: 160 Hz (approx.), uneven timing |
NTSC: 96 Hz (approx.), uneven timing PAL: 80 Hz (approx.), uneven timing |
In this mode, the frame interrupt flag is never set.