APU Triangle

From NESdev Wiki
Jump to navigationJump to search

The NES APU triangle channel generates a pseudo-triangle wave. It has no volume control; the waveform is either cycling or suspended. It includes a linear counter, an extra duration timer of higher accuracy than the length counter.

The triangle channel contains the following: timer, length counter, linear counter, linear counter reload flag, control flag, sequencer.

      Linear Counter   Length Counter
            |                |
            v                v
Timer ---> Gate ----------> Gate ---> Sequencer ---> (to mixer)
$4008 CRRR.RRRR Linear counter setup (write)
bit 7 C---.---- Control flag (this bit is also the length counter halt flag)
bits 6-0 -RRR RRRR Counter reload value
 
$400A LLLL.LLLL Timer low (write)
bits 7-0 LLLL LLLL Timer low 8 bits
 
$400B llll.lHHH Length counter load and timer high (write)
bits 2-0 ---- -HHH Timer high 3 bits
Side effects Sets the linear counter reload flag

The sequencer is clocked by a timer whose period is the 11-bit value (%HHH.LLLLLLLL) formed by timer high and timer low, plus one. Given t = HHHLLLLLLLL, 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, this timer 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, meaning frequencies up to fCPU/32 (about 55.9 kHz for NTSC) are possible - far above the audible range. Some games, e.g. Mega Man 2, "silence" the triangle channel by setting the timer to zero, which produces a popping sound when an audible frequency is resumed, easily heard e.g. in Crash Man's stage. At the expense of accuracy, these can be eliminated in an emulator e.g. by halting the triangle channel when an ultrasonic frequency is set (a timer value less than 2).

Other games, e.g. Zombie Nation and Bullet-Proof Software's Tetris, "silence" the triangle channel by setting the timer to $7FF, which produces a deep rumble and quiet whine.

When the frame counter generates a linear counter clock, the following actions occur in order:

  1. If the linear counter reload flag is set, the linear counter is reloaded with the counter reload value, otherwise if the linear counter is non-zero, it is decremented.
  2. If the control flag is clear, the linear counter reload flag is cleared.

Note that the reload flag is not cleared unless the control flag is also clear, so when both are already set a value written to $4008 will be reloaded at the next linear counter clock.

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 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

Within the mixer, the DMC level has a noticeable effect on the triangle's level.

The triangle channel can be silenced by several methods:

  1. Write $80 to $4008, which will halt and reload the linear counter with 0 at the next frame sequence tick. This can be simply resumed by writing $FF to $4008. (When using this method the control flag and reload flag should be permanently set.)
    • Optionally: a write to $4017 after the write to $4008 can trigger an immediate frame sequence tick, if the 1/4 frame delay of the frame sequence is undesirable. This has all the other consequences of the frame sequence tick, however.
  2. 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.
    • When using DPCM samples, it is difficult to manipulate a single bit in $4015 without risking conflict with the DPCM control.
  3. Write a period value of 0 or 1 to $400A/$400B, causing a very high frequency. Due to the averaging effect of the lowpass filter, the resulting value is halfway between 7 and 8.
    • This sudden jump to "7.5" causes a harder popping noise than other triangle silencing methods, which will instead halt it in whatever its current output position is.
    • Mega Man 1 and 2 use this technique.
  4. 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.