APU Sweep: Difference between revisions
m (use the term "target period" throughout) |
(In silicon, combinational logic begins to compute the next state immediately after the current state is updated.) |
||
Line 3: | Line 3: | ||
Each sweep unit contains the following: [[APU Misc|divider]], reload flag. | Each sweep unit contains the following: [[APU Misc|divider]], reload flag. | ||
{| | {| class="tabular" | ||
| '''$4001''' || <tt>EPPP.NSSS</tt> || '''[[APU Pulse|Pulse channel 1]]''' sweep setup (write) | | '''$4001''' || <tt>EPPP.NSSS</tt> || '''[[APU Pulse|Pulse channel 1]]''' sweep setup (write) | ||
|- | |- | ||
Line 12: | Line 12: | ||
| bits 6-4 || <tt>-PPP ----</tt> || The divider's period is set to P + 1 | | bits 6-4 || <tt>-PPP ----</tt> || The divider's period is set to P + 1 | ||
|- | |- | ||
| bit 3 || <tt>---- N---</tt> || Negate flag | | bit 3 || <tt>---- N---</tt> || Negate flag<br>0: add to period, sweeping toward lower frequencies<br>1: subtract from period, sweeping toward higher frequencies | ||
|- | |- | ||
| bits 2-0 || <tt>---- -SSS</tt> || Shift count (number of bits) | | bits 2-0 || <tt>---- -SSS</tt> || Shift count (number of bits) | ||
Line 23: | Line 23: | ||
When clocked by the [[APU Frame Counter|frame counter]], the divider is ''first'' clocked and then if the reload flag is set, it is cleared and the divider is reloaded. | When clocked by the [[APU Frame Counter|frame counter]], the divider is ''first'' clocked and then if the reload flag is set, it is cleared and the divider is reloaded. | ||
The channel's 11-bit [[APU Pulse|raw timer period]] is shifted right by the shift count (using a barrel shifter), then either added to or subtracted from | The channel's 11-bit [[APU Pulse|raw timer period]] is shifted right by the shift count (using a barrel shifter), then either added to or subtracted from the channel's raw period, yielding the target period. When the channel's current period is less than 8 or the target period is greater than $7FF, the channel is silenced (0 is sent to the [[APU Mixer|mixer]]) but the channel's current period remains unchanged. Otherwise, if the enable flag is set and the shift count is non-zero, when the divider outputs a clock, the channel's period is updated. | ||
The adder computes the next target period immediately after the period is updated by $400x writes or by the frame counter. | |||
The sweep unit can silence a channel ''even when the enabled flag is clear'' and even when the sweep divider is not outputting a clock signal. To fully disable a sweep unit, write $08 to turn on the negate flag so that the target period is not greater than the channel's period and therefore not greater than $7FF. | |||
For reasons unknown, pulse channel 1 hardwires its carry input rather than using the state of the negate flag, resulting in the subtraction operation adding the '''one's complement''' instead of the expected two's complement (as pulse channel 2 does). As a result, a negative sweep on pulse channel 1 will subtract the shifted period value '''minus 1'''. | For reasons unknown, pulse channel 1 hardwires its adder's carry input rather than using the state of the negate flag, resulting in the subtraction operation adding the '''one's complement''' instead of the expected two's complement (as pulse channel 2 does). As a result, a negative sweep on pulse channel 1 will subtract the shifted period value '''minus 1'''. |
Revision as of 15:02, 18 May 2011
A NES APU sweep unit can be made to periodically adjust a pulse channel's period up or down.
Each sweep unit contains the following: divider, reload flag.
$4001 | EPPP.NSSS | Pulse channel 1 sweep setup (write) |
$4005 | EPPP.NSSS | Pulse channel 2 sweep setup (write) |
bit 7 | E--- ---- | Enabled flag |
bits 6-4 | -PPP ---- | The divider's period is set to P + 1 |
bit 3 | ---- N--- | Negate flag 0: add to period, sweeping toward lower frequencies 1: subtract from period, sweeping toward higher frequencies |
bits 2-0 | ---- -SSS | Shift count (number of bits) |
Side effects | Sets the reload flag |
NOTE: The term "target period" used in the following description is equivalent to [shift-result + current period]. That is, it does not mean the result of the right-shift alone.
When clocked by the frame counter, the divider is first clocked and then if the reload flag is set, it is cleared and the divider is reloaded.
The channel's 11-bit raw timer period is shifted right by the shift count (using a barrel shifter), then either added to or subtracted from the channel's raw period, yielding the target period. When the channel's current period is less than 8 or the target period is greater than $7FF, the channel is silenced (0 is sent to the mixer) but the channel's current period remains unchanged. Otherwise, if the enable flag is set and the shift count is non-zero, when the divider outputs a clock, the channel's period is updated.
The adder computes the next target period immediately after the period is updated by $400x writes or by the frame counter. The sweep unit can silence a channel even when the enabled flag is clear and even when the sweep divider is not outputting a clock signal. To fully disable a sweep unit, write $08 to turn on the negate flag so that the target period is not greater than the channel's period and therefore not greater than $7FF.
For reasons unknown, pulse channel 1 hardwires its adder's carry input rather than using the state of the negate flag, resulting in the subtraction operation adding the one's complement instead of the expected two's complement (as pulse channel 2 does). As a result, a negative sweep on pulse channel 1 will subtract the shifted period value minus 1.