APU Triangle
The NES APU triangle channel generates a pseudo-triangle wave. It has no volume control; the waveform is only either cycling or suspended.
Linear Counter Length Counter
| |
v v
Timer ---> Gate ----------> Gate ---> Sequencer ---> (to mixer)
7 bit 0
---- ----
CRRR RRRR
|||| ||||
|+++-++++- Linear counter reload value
+--------- Linear counter control flag and length counter halt flag
The linear counter is an extra hardware duration timer that provides higher accuracy than the length counter. It works completely seperately from length counter.
When the APU Frame Counter generates the quarter frame clock, these actions occur in order:
- If the linear counter reload flag is set, the counter is reloaded with the counter reload value, otherwise, if the counter is non-zero, it is decremented.
- If the counter control flag (
Cbit) is clear, the reload flag is cleared.
Note that the counter reload flag is not cleared unless the control flag (C bit) is also clear, so when both are already set a value written to $4008 will be reloaded at the next linear counter clock. It’s impossible to disable the linear counter alone and clearing the control flag (C bit) resumes both length counter and linear counter at the same time. Consequently this means longer length counter values are unusable in practice because the maximum duration that the linear counter allows is shorter.
7 bit 0
---- ----
TTTT TTTT
|||| ||||
++++-++++- Lower 8 bits of timer period value
7 bit 0
---- ----
LLLL LTTT
|||| ||||
|||| |+++- Upper 3 bits of timer period value
++++-+---- Length counter load value
Writing to this register sets linear counter reload flag too.
The sequencer is clocked by a timer where the period is the 11-bit value (from $400A and $400B) plus one. Given “t” as the timer value, the timer counts t, t-1, ..., 0, t, t-1, ..., clocking the waveform generator when it goes from 0 to t.
Unlike the pulse channels, the timer of the triangle channel ticks at the rate of the CPU clock rather than the APU (CPU/2) clock. So given the following:
- fCPU = the clock rate of the CPU
- tval = the value written to the timer high and low registers
- f = the frequency of the wave generated by this channel
The following relationships hold:
- f = fCPU ÷ (32 × (tval + 1))
- tval = fCPU ÷ (32 × f) - 1
Unlike the pulse channels, the triangle channel supports frequencies up to the maximum frequency the timer will allow and can generate ultrasonic frequency (fCPU/32 = 55.9 kHz in NTSC). Due to external filtering, ultrasonic frequencies are averaged into constant output at roughly half amplitude. A few games “silence” the channel by setting the triangle period to 0, creating a sharp audible pop over the transition.
The sequencer is clocked by the timer as long as both the linear counter and the length counter are nonzero.
The sequencer sends the following looping 32-step sequence of 4-bit values to the mixer:
15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15
The triangle channel stops the sequencer only when either the length counter or the linear counter is zero.
- Write $80 to $4008, which will halt and reload the linear counter with 0 (which will halt the sequencer because the counter is 0) at the next frame sequence tick. It can be simply resumed by writing $FF to $4008. Note that when using this method, the linear counter control flag and reload flag should be permanently set.
- Use $4015 to turn off the channel, which will clear its length counter. To resume, turn it back on via $4015, then write to $400B to reload the length counter.
- Either the length counter or linear counter can be used to automatically halt the triangle after a period of time.
- Unfortunately this is limited to very short durations because the linear counter can only go as high as 127 quarter frames.
| V | | |
|---|---|
| Concepts | Registers | Basics | Period table |
| Channels | Pulse 1 and Pulse 2 | Triangle | Noise | DMC |
| Components | Envelope | Sweep | Frame Counter | Length Counter | DMA | Mixer |
| Expansion audio | 2C33 (Disk System) | MMC5 | VRC6 | VRC7 | Namco 163 | Sunsoft 5B | µPD7756 |