APU Length Counter: Difference between revisions

From NESdev Wiki
Jump to navigationJump to search
(The triangle halt flag was renamed to linear counter reload flag)
(Constant volume flag was missing, making it look like the volume/envelope field is 5 bits long. Also make consistent with main page by using 'v' instead of 'e'.)
Line 9: Line 9:
|colspan=3|  
|colspan=3|  
|-
|-
| '''$4000''' || <tt>ssHe.eeee</tt> || '''[[APU Pulse|Pulse channel 1]] duty cycle, length counter halt, and [[APU Envelope|envelope]]''' (write)
| '''$4000''' || <tt>ssHc.vvvv</tt> || '''[[APU Pulse|Pulse channel 1]] duty cycle, length counter halt, constant volume flag, and volume/[[APU Envelope|envelope]]''' (write)
|-
|-
| '''$4004''' || <tt>ssHe.eeee</tt> || '''[[APU Pulse|Pulse channel 2]] duty cycle, length counter halt, and [[APU Envelope|envelope]]''' (write)
| '''$4004''' || <tt>ssHc.vvvv</tt> || '''[[APU Pulse|Pulse channel 2]] duty cycle, length counter halt, constant volume flag, and volume/[[APU Envelope|envelope]]''' (write)
|-
|-
| '''$400C''' || <tt>--He.eeee</tt> || '''[[APU Noise|Noise channel]] length counter halt and [[APU Envelope|envelope]]''' (write)
| '''$400C''' || <tt>--Hc.vvvv</tt> || '''[[APU Noise|Noise channel]] length counter halt, constant volume flag, and volume/[[APU Envelope|envelope]]''' (write)
|-
|-
| bit 5 || <tt>--H- ----</tt> || Halt length counter (this bit is also the [[APU Envelope|envelope's loop flag]])
| bit 5 || <tt>--H- ----</tt> || Halt length counter (this bit is also the [[APU Envelope|envelope's loop flag]])

Revision as of 09:09, 6 May 2013

The length counter provides automatic duration control for the NES APU waveform channels. Once loaded with a value, it can optionally count down (when the length counter halt flag is clear). Once it reaches zero, the corresponding channel is silenced.

Address Bitfield Description
$4015 ---d.nt21 DMC control and length counter enabled flags (write)
 
$4000 ssHc.vvvv Pulse channel 1 duty cycle, length counter halt, constant volume flag, and volume/envelope (write)
$4004 ssHc.vvvv Pulse channel 2 duty cycle, length counter halt, constant volume flag, and volume/envelope (write)
$400C --Hc.vvvv Noise channel length counter halt, constant volume flag, and volume/envelope (write)
bit 5 --H- ---- Halt length counter (this bit is also the envelope's loop flag)
 
$4008 Hlll.llll Triangle channel length counter halt and linear counter load (write)
bit 7 H--- ---- Halt length counter (this bit is also the linear counter's control flag)
 
$4003 LLLL.Lttt Pulse channel 1 length counter load and timer (write)
$4007 LLLL.Lttt Pulse channel 2 length counter load and timer (write)
$400B LLLL.Lttt Triangle channel length counter load and timer (write)
$400F LLLL.L--- Noise channel length counter load (write)
bits 7-3 LLLL L--- If the enabled flag is set, the length counter is loaded with entry L of the length table:
     |  0   1   2   3   4   5   6   7    8   9   A   B   C   D   E   F
-----+----------------------------------------------------------------
00-0F  10,254, 20,  2, 40,  4, 80,  6, 160,  8, 60, 10, 14, 12, 26, 14,
10-1F  12, 16, 24, 18, 48, 20, 96, 22, 192, 24, 72, 26, 16, 28, 32, 30
Side effects The envelope is restarted, for pulse channels phase is reset, for triangle the linear counter reload flag is set.

Clocking

When the enabled bit is cleared (via $4015), the length counter is forced to 0 and cannot be changed until enabled is set again (the length counter's previous value is lost). There is no immediate effect when enabled is set.

When clocked by the frame counter, the length counter is decremented except when:

  • The length counter is 0, or
  • The halt flag is set

Length counter internals

In the actual APU, the length counter silences the channel when clocked while already zero (provided the length counter halt flag isn't set). The values in the above table are the actual values the length counter gets loaded with plus one, to allow us to use a model where the channel is silenced when the length counter becomes zero.

The triangle's linear counter works differently, and does silence the channel when it reaches zero.