APU Triangle: Difference between revisions

From NESdev Wiki
Jump to navigationJump to search
(The triangle period timer ticks at the rate of the CPU clock)
(mention the other misuse of the triangle channel)
 
(15 intermediate revisions by 4 users not shown)
Line 2: Line 2:
The [[APU|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 [[APU Length Counter|length counter]].
The [[APU|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 [[APU Length Counter|length counter]].


The triangle channel contains the following: [[APU Misc|timer]], linear counter, [[APU Length Counter|length counter]], halt flag, [[APU Misc|sequencer]]. The linear counter contains an internal halt flag and counter.
The triangle channel contains the following: [[APU Misc|timer]], [[APU Length Counter|length counter]], linear counter, linear counter reload flag, control flag, [[APU Misc|sequencer]].
 
<pre>
<pre>
       Linear Counter  Length Counter
       Linear Counter  Length Counter
Line 29: Line 30:
| bits 2-0 || <tt>---- -HHH</tt> || Timer high 3 bits
| bits 2-0 || <tt>---- -HHH</tt> || Timer high 3 bits
|-
|-
|colspan=2| Side effects || Sets the halt flag
|colspan=2| Side effects || Sets the linear counter reload flag
|}
|}


The sequencer is clocked by a [[APU Misc|timer]] whose period is the 11-bit value (<tt>%HHH.LLLLLLLL</tt>) formed by timer high and timer low, ''plus one''.
The sequencer is clocked by a [[APU Misc|timer]] whose period is the 11-bit value (<tt>%HHH.LLLLLLLL</tt>) 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 [[APU Pulse|pulse]] channels, this timer ticks at the rate of the CPU clock rather than the APU (CPU/2) clock.
Unlike the [[APU Pulse|pulse]] channels, this timer ticks at the rate of the CPU clock rather than the APU (CPU/2) clock.
So given the following:
So given the following:
*f<sub>CPU</sub> = the [[clock rate]] of the CPU
*f<sub>CPU</sub> = the [[Cycle_reference_chart#Clock_rates|clock rate]] of the CPU
*tval = the value written to the timer high and low registers
*tval = the value written to the timer high and low registers
*f = the frequency of the wave generated by this channel
*f = the frequency of the wave generated by this channel
Line 41: Line 43:
*f = f<sub>CPU</sub>/(32*(tval + 1))
*f = f<sub>CPU</sub>/(32*(tval + 1))
*tval = f<sub>CPU</sub>/(32*f) - 1
*tval = f<sub>CPU</sub>/(32*f) - 1
Unlike the [[APU Pulse|pulse]] channels, the triangle channel supports frequencies up to the maximum frequency the timer will allow, meaning frequencies up to f<sub>CPU</sub>/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 [[APU Frame Counter|frame counter]] generates a linear counter clock, the following actions occur in order:
When the [[APU Frame Counter|frame counter]] generates a linear counter clock, the following actions occur in order:
# If the halt flag is set, the linear counter is reloaded with the counter reload value, otherwise if the linear counter is non-zero, it is decremented.
# 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.
# If the control flag is clear, the halt flag is cleared.
# 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 [[APU Length Counter|length counter]] are nonzero.
The sequencer is clocked by the timer as long as both the linear counter and the [[APU Length Counter|length counter]] are nonzero.
Line 53: Line 62:
  0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14, 15
  0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14, 15
</pre>
</pre>
Within the mixer, the DMC level has a noticeable effect on the triangle's level.


At the lowest two [[APU Misc|timer]] periods ($400B = 0 and $400A = 0 or 1), the resulting frequency is so high (over 20 kHz) that the [[APU Mixer|mixer]] effectively receives a value half way between 7 and 8.<br>
The triangle channel can be silenced by several methods:
'''Note:''' If you're using this to silence the triangle channel, be aware that this makes a popping noise, because the triangle output is basically jumping to "7.5", from wherever it was before (could be 0 or 15). Mega Man 1 and 2 do this.
# 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.
If that's undesirable, then there are three other ways to silence the triangle channel:
# 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.
* Use the linear counter to control the length of the note. This may be a bit limiting, because the linear counter doesn't allow for super-long notes.
#* When using DPCM samples, it is difficult to manipulate a single bit in $4015 without risking conflict with the DPCM control.
* Use $4015 to turn off the triangle channel when it needs to be silent (don't forget to turn it back on). However, writing to $4015 may cause problems if you're using the DMC.
# 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.  
* Use the following writes when you want to silence the triangle channel:
#* 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.
*# Write $00 to $4008. This sets the linear counter to 0.
#* Mega Man 1 and 2 use this technique.
*# Write to $400B. This is to reload the linear counter with that 0. Be careful, because this register contains 3 bits of the triangle channel's period. You'd either need to rewrite the same value to this register, or write $07 to change the period to something low pitched and unnoticable.
# Either the length counter or linear counter can be used to automatically halt the triangle after a period of time.
*# Write to $4017 with bit 7 set. This will immediately clock the linear counter, reloading it, and silencing the triangle channel. This step is optional, but if you don't do this, there will be a random delay before the triangle channel is actually silenced, which is why it's important to pay attention to what you write to $400B in the previous step.
#* Unfortunately this is limited to very short durations because the linear counter can only go as high as 127 quarter frames.
*#* If you want to use the things that depend on the frame counter, you can simply write to $4017 every frame at the end of your music routine, instead of compulsively writing to $4017 only when you want to silence the triangle channel. This will keep the frame counter's sequencer consistent.

Latest revision as of 01:20, 19 December 2021

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.