APU Pulse

From NESdev Wiki
Revision as of 16:37, 14 May 2011 by Quietust (talk | contribs) (The duty cycle counter actually counts downward (since it's triggered by frequency counter underflow), but it's initialized to 000 rather than 111, which explains the waveform sequences)
Jump to navigationJump to search

Each of the two NES APU pulse (square) wave channels generate a pulse wave with variable duty.

Each pulse channel contains the following: envelope generator, sweep unit, timer, 8-step sequencer, length counter.

    Timer ---> Sequencer    Sweep   Length Counter
                   |          |           |
                   |          |           |
                   v          v           v
Envelope -------> Gate-----> Gate -----> Gate ---> (to mixer)
Address Bitfield Description
$4000 DDle.eeee Pulse 1 duty, length counter halt, and envelope (write)
$4004 DDle.eeee Pulse 2 duty, length counter halt, and envelope (write)
bits 7-6 DD-- ---- The duty cycle is set (see table below). The sequencer's current position is not changed.
 
$4002 LLLL.LLLL Pulse 1 timer low (write)
$4006 LLLL.LLLL Pulse 2 timer low (write)
bits 7-0 LLLL LLLL Timer low 8 bits
 
$4003 llll.lHHH Pulse 1 length counter load and timer high (write)
$4007 llll.lHHH Pulse 2 length counter load and timer high (write)
bits 2-0 ---- -HHH Timer high 3 bits
Side effects The sequencer is restarted at the first value of the current sequence. The envelope is also restarted.

Duty Cycle Sequences

Duty Waveform sequence
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)
The reason for these odd sequences is that the sequence counter is initialized to zero but counts downward rather than upward

The sequencer is clocked by a timer whose period is the 12-bit value (%HHHL.LLLLLLL0, incorporating a left shift) formed by timer high and timer low, plus two. It further divides the timer's output by 8 to produce the audio frequency. So given the following:

  • fCPU = the clock rate of the CPU
  • tval = the 11-bit value that the program writes to the timer high and low registers
  • f = the frequency of the wave generated by this channel

The following relationships hold:

  • f = fCPU/(16*(tval + 1))
  • tval = fCPU/(16*f) - 1

The mixer receives the current envelope volume except when

  • The sequencer output is zero, or
  • The sweep unit is silencing the channel, or
  • The length counter is zero

The behavior of the two pulse channels differs only in the effect of the negate mode of their sweep units.