APU Length Counter
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 | ssHe.eeee | Pulse channel 1 duty cycle, length counter halt, and envelope (write) |
$4004 | ssHe.eeee | Pulse channel 2 duty cycle, length counter halt, and envelope (write) |
$400C | --He.eeee | Noise channel length counter halt and 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 halt 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
Precise length counter period
In the actual APU, the length counter silences the channel when clocked while already zero (provided the length counter halt flag isn't set). Hence an implementation that silences the channel when the length counter becomes zero will do so one frame counter clock early (though that most likely won't be audible). To simulate this in the disable-when-zero model of the length counter presented here, just add one to each entry in the table.
The triangle's linear counter works differently, and does silence the channel when it reaches zero.