APU Pulse: Difference between revisions
mNo edit summary |
No edit summary |
||
Line 1: | Line 1: | ||
[[Category:APU]] | [[Category:APU]] | ||
Each of the two [[APU|NES APU]] pulse (square) wave channels generate a pulse wave with variable duty. | Each of the two [[APU|NES APU]] pulse (square) wave channels generate a pulse wave with variable duty. | ||
Each pulse channel contains the following: | Each pulse channel contains the following: | ||
Line 21: | Line 22: | ||
Envelope -------> Gate -----> Gate -------> Gate --->(to mixer) | Envelope -------> Gate -----> Gate -------> Gate --->(to mixer) | ||
</pre> | </pre> | ||
'''Note''': the addresses below are ''write-only!'' | '''Note''': the addresses below are ''write-only!'' | ||
Line 53: | Line 55: | ||
|colspan=2| Side effects || The sequencer is immediately restarted at the first value of the current sequence. The [[APU Envelope|envelope]] is also restarted. The period divider is ''not'' reset.[//forums.nesdev.org/viewtopic.php?p=186129#p186129] | |colspan=2| Side effects || The sequencer is immediately restarted at the first value of the current sequence. The [[APU Envelope|envelope]] is also restarted. The period divider is ''not'' reset.[//forums.nesdev.org/viewtopic.php?p=186129#p186129] | ||
|} | |} | ||
'''Duty Cycle Sequences''' | '''Duty Cycle Sequences''' | ||
Line 66: | Line 69: | ||
| 3 || <samp>1 0 0 1 1 1 1 1</samp> (25% negated) | | 3 || <samp>1 0 0 1 1 1 1 1</samp> (25% negated) | ||
|} | |} | ||
Notice that a few Famiclone units have swapped APU duty cycles, as 12.5 [0], 50 [1], 25 [2] and 25 negated [3] instead. | |||
'''Sequencer behavior''' | |||
The sequencer is clocked by an 11-bit [[APU Misc|timer]]. Given the timer value ''t = HHHLLLLLLLL'' formed by timer high and timer low, | The sequencer is clocked by an 11-bit [[APU Misc|timer]]. Given the timer value ''t = HHHLLLLLLLL'' formed by timer high and timer low, | ||
Line 77: | Line 85: | ||
* t = f<sub>CPU</sub>/(16*f<sub>pulse</sub>) - 1 | * t = f<sub>CPU</sub>/(16*f<sub>pulse</sub>) - 1 | ||
A period of ''t < 8'', either set explicitly or via a sweep period update, silences the corresponding pulse channel. The highest frequency a pulse channel can output is hence about 12.4 kHz for NTSC. ('''TODO:''' PAL behavior?) | |||
'''Note:''' A period of ''t < 8'', either set explicitly or via a sweep period update, '''silences the corresponding pulse channel'''. The highest frequency a pulse channel can output is hence about 12.4 kHz for NTSC. ('''TODO:''' PAL behavior?) | |||
'''Pulse channel output to mixer''' | |||
The [[APU Mixer|mixer]] receives the current [[APU Envelope|envelope volume]] except when | The [[APU Mixer|mixer]] receives the current [[APU Envelope|envelope volume]] except when | ||
Line 84: | Line 96: | ||
* the [[APU Length Counter|length counter]] is zero, or | * the [[APU Length Counter|length counter]] is zero, or | ||
* the timer has a value less than eight. | * the timer has a value less than eight. | ||
'''Pulse channel 1 vs Pulse channel 2 behavior''' | |||
The behavior of the two pulse channels differs only in the effect of the negate mode of their [[APU Sweep|sweep units]]. | The behavior of the two pulse channels differs only in the effect of the negate mode of their [[APU Sweep|sweep units]]. | ||
== Implementation details == | == Implementation details == |
Revision as of 17:52, 10 June 2022
Each of the two NES APU pulse (square) wave channels generate a pulse wave with variable duty.
Each pulse channel contains the following:
Sweep -----> Timer | | | | | v | Sequencer Length Counter | | | | | | v v v Envelope -------> Gate -----> Gate -------> Gate --->(to mixer)
Note: the addresses below are write-only!
Address | Bitfield | Description |
---|---|---|
$4000 | DDlc.vvvv | Pulse 1 Duty cycle, length counter halt, constant volume/envelope flag, and volume/envelope divider period |
$4004 | DDlc.vvvv | Pulse 2 Duty cycle, length counter halt, constant volume/envelope flag, and volume/envelope divider period |
Side effects | The duty cycle is changed (see table below), but the sequencer's current position isn't affected. | |
$4001 | EPPP.NSSS | See APU Sweep |
$4005 | EPPP.NSSS | See APU Sweep |
$4002 | LLLL.LLLL | Pulse 1 timer Low 8 bits |
$4006 | LLLL.LLLL | Pulse 2 timer Low 8 bits |
$4003 | llll.lHHH | Pulse 1 length counter load and timer High 3 bits |
$4007 | llll.lHHH | Pulse 2 length counter load and timer High 3 bits |
Side effects | The sequencer is immediately restarted at the first value of the current sequence. The envelope is also restarted. The period divider is not reset.[1] |
Duty Cycle Sequences
Duty | Output waveform |
---|---|
0 | 0 1 0 0 0 0 0 0 (12.5%) |
1 | 0 1 1 0 0 0 0 0 (25%) |
2 | 0 1 1 1 1 0 0 0 (50%) |
3 | 1 0 0 1 1 1 1 1 (25% negated) |
Notice that a few Famiclone units have swapped APU duty cycles, as 12.5 [0], 50 [1], 25 [2] and 25 negated [3] instead.
Sequencer behavior
The sequencer is clocked by an 11-bit timer. Given the timer value t = HHHLLLLLLLL formed by timer high and timer low, this timer is updated every APU cycle (i.e., every second CPU cycle), and counts t, t-1, ..., 0, t, t-1, ..., clocking the waveform generator when it goes from 0 to t. Since the period of the timer is t+1 APU cycles and the sequencer has 8 steps, the period of the waveform is 8*(t+1) APU cycles, or equivalently 16*(t+1) CPU cycles.
Hence
- fpulse = fCPU/(16*(t+1)) (where fCPU is 1.789773 MHz for NTSC, 1.662607 MHz for PAL, and 1.773448 MHz for Dendy)
- t = fCPU/(16*fpulse) - 1
Note: A period of t < 8, either set explicitly or via a sweep period update, silences the corresponding pulse channel. The highest frequency a pulse channel can output is hence about 12.4 kHz for NTSC. (TODO: PAL behavior?)
Pulse channel output to mixer
The mixer receives the current envelope volume except when
- The sequencer output is zero, or
- overflow from the sweep unit's adder is silencing the channel, or
- the length counter is zero, or
- the timer has a value less than eight.
Pulse channel 1 vs Pulse channel 2 behavior
The behavior of the two pulse channels differs only in the effect of the negate mode of their sweep units.
Implementation details
The reason for the odd output from the sequencer is that the counter is initialized to zero but counts downward rather than upward. Thus it reads the sequence lookup table in the order 0, 7, 6, 5, 4, 3, 2, 1.
Duty | Sequence lookup table | Output waveform |
---|---|---|
0 | 0 0 0 0 0 0 0 1 |
0 1 0 0 0 0 0 0 (12.5%) |
1 | 0 0 0 0 0 0 1 1 |
0 1 1 0 0 0 0 0 (25%) |
2 | 0 0 0 0 1 1 1 1 |
0 1 1 1 1 0 0 0 (50%) |
3 | 1 1 1 1 1 1 0 0 |
1 0 0 1 1 1 1 1 (25% negated) |