APU DMC
The NES APU’s delta modulation channel (DMC) provides automatic 1-bit delta-encoded sample playback unit that can fetch a sample byte from the same CPU memory area by its own, or the 7-bit counter (final output level) can be directly loaded, allowing flexible manual sample playback via CPU.
Timer Direct Load
| |
v v
Reader ---> Buffer ---> Shifter ---> 7-bit Counter ---> (to mixer)
7 bit 0
---- ----
IL.. RRRR
|| ||||
|| ++++- Playback rate index
|+-------- Sample loop flag
+--------- Enable DMC sample-end interrupt (hereinafter "DMC IRQ")
The rate (R bits) determines for how many CPU cycles happen between changes in the output level during automatic sample playback.
Setting the loop flag (L bit) inhibits DMC IRQ pending flag from being set.
Periods in this table are in CPU cycles.
| NTSC | PAL | |||||||||||
| $4010.0-3 | Period | Frequency | Note (raw) | Note (1-byte loop) | Note (17-byte loop) | Note (33-byte loop) | Period | Frequency | Note (raw) | Note (1-byte loop) | Note (17-byte loop) | Note (33-byte loop) |
| $0 | 428 | 4181.71 Hz | C-8 -2c | C-5 -2c | B-0 -7c | infrasound | 398 | 4177.40 Hz | C-8 -4c | C-5 -4c | B-0 -9c | infrasound |
| $1 | 380 | 4709.93 Hz | D-8 +4c | D-5 +4c | C#1 -1c | infrasound | 354 | 4696.63 Hz | D-8 -1c | D-5 -1c | C#1 -6c | infrasound |
| $2 | 340 | 5264.04 Hz | E-8 -3c | E-5 -3c | Eb1 -8c | infrasound | 316 | 5261.41 Hz | E-8 -4c | E-5 -4c | Eb1 -9c | infrasound |
| $3 | 320 | 5593.04 Hz | F-8 +2c | F-5 +2c | E-1 -3c | E-0 +48c | 298 | 5579.22 Hz | F-8 -3c | F-5 -3c | E-1 -8c | E-0 +44c |
| $4 | 286 | 6257.95 Hz | G-8 -4c | G-5 -4c | F#1 -9c | F#0 +43c | 276 | 6023.94 Hz | G-8 -70c | G-5 -70c | F#1 -75c | F#0 -23c |
| $5 | 254 | 7046.35 Hz | A-8 +2c | A-5 +2c | Ab1 -3c | Ab0 +48c | 236 | 7044.94 Hz | A-8 +1c | A-5 +1c | Ab1 -4c | Ab0 +48c |
| $6 | 226 | 7919.35 Hz | B-8 +4c | B-5 +4c | Bb1 -1c | Bb0 +50c | 210 | 7917.18 Hz | B-8 +3c | B-5 +3c | Bb1 -2c | Bb0 +50c |
| $7 | 214 | 8363.42 Hz | C-9 -2c | C-6 -2c | B-1 -7c | B-0 +45c | 198 | 8397.01 Hz | C-9 +5c | C-6 +5c | B-1 +0c | B-0 +52c |
| $8 | 190 | 9419.86 Hz | D-9 +4c | D-6 +4c | C#2 -1c | C#1 +51c | 176 | 9446.63 Hz | D-9 +9c | D-9 +9c | C#2 +4c | C#1 +56c |
| $9 | 160 | 11186.1 Hz | F-9 +2c | F-6 +2c | E-2 -3c | E-1 +48c | 148 | 11233.8 Hz | F-9 +9c | F-6 +9c | E-2 +4c | E-1 +56c |
| $A | 142 | 12604.0 Hz | G-9 +8c | G-6 +8c | F#2 +3c | F#1 +55c | 132 | 12595.5 Hz | G-9 +7c | G-6 +7c | F#2 -2c | G-1 +54c |
| $B | 128 | 13982.6 Hz | A-9 -12c | A-6 -12c | Ab2 -17c | Ab1 +35c | 118 | 14089.9 Hz | A-9 +1c | A-6 +1c | Ab2 -4c | Ab1 +48c |
| $C | 106 | 16884.6 Hz | C-10 +14c | C-7 +14c | B-2 +10c | B-1 +61c | 98 | 16965.4 Hz | C-10 +23c | C-7 +23c | B-2 +18c | B-1 +69c |
| $D | 84 | 21306.8 Hz | E-10 +17c | E-7 +17c | Eb3 +12c | Eb2 +64c | 78 | 21315.5 Hz | E-10 +18c | E-7 +18c | Eb3 +13c | Eb2 +65c |
| $E | 72 | 24858.0 Hz | G-10 -16c | G-7 -16c | F#3 -21c | F#2 +31c | 66 | 25191.0 Hz | G-10 +7c | G-7 +7c | F#3 +2c | F#2 +54c |
| $F | 54 | 33143.9 Hz | C-11 -18c | C-8 -18c | B-3 -23c | B-2 +29c | 50 | 33252.1 Hz | C-11 -12c | C-8 -12c | B-3 -17c | B-2 +34c |
(Deviation from note is given in cents, which are defined as 1/100th of a semitone.)
On RP2A07, the pitches at $4 and $C appear to be incorrect with respect to their intended A-440 tuning scheme. [1]
All “Dendy timing” clone CPUs are known to use NTSC period table.
7 bit 0
---- ----
.DDD DDDD
||| ||||
+++-++++- Unsigned 7-bit counter value
Writing to this register directly sets the counter value (final output level). If the automatic DMC playback unit clocks the counter at the same time, the output level is occasionally not changed properly. [2]
The change still occurs even when the automatic DMC playback unit is deactivated.
7 bit 0
---- ----
AAAA AAAA
|||| ||||
++++-++++- Sample address = $C000 + (A * 64)
This register sets reload value. Retrigerring the sample playback reloads the value back from this register.
7 bit 0
---- ----
LLLL LLLL
|||| ||||
++++-++++- Sample length = (L * 16) + 1 bytes
This register sets reload value. Retrigerring the sample playback reloads the value back from this register.
7 bit 0 (read)
---- ----
IF.D NT21
| |
| +------ Sample is on playback flag
+--------- DMC IRQ asserted
The D bit returns 1 when the bytes-remaining counter is not zero.
7 bit 0 (write)
---- ----
...D NT21
|
+------ Start / Stop DMC sample playback
When writing to this register with the D bit clear, the bytes-remaining counter is set to 0, consequently finishes the playback before the next sample byte is fetched. When the write is done with the bit set and if the bytes-remaining counter is 0, the sample playback is restarted, by reloading the address counter and bytes-remaining counter based on $4012 and $4013.
Writing to this register also clears DMC IRQ pending flag.
For descriptions for other bits, see APU#Status.
The output level, or the current output of the 7-bit counter is sent to the mixer regardless the channel is enabled or not. It can be updated via $4011 writes and the automatic delta-encoded sample playback unit.
The automatic sample playback unit consists of two seperate units that operate in parallel, a memory reader and an output unit.
The output unit take the sample byte from the sample buffer (filled by memory reader) and update the output level accordingly. It includes an 8-bit shift register that is loaded with the content from sample buffer, shifted as the clocking happens.
The output unit runs regardless the sample playback is happening or not. When timer generates clock, following occur:
- The least significant bit of the shift register detemines whether to up or down count the output level:
- If it is 0 and the current output level is higher than 1, decrement the output level by 2.
- If it is 1 and the current output level is below 126, increment the output level by 2.
- Notice that the difference per a sample bit is 2 and not 1.
- The shift register shifts the bits to right.
- If all eight bits in the shift register is spent, whether the sample buffer is empty or not determines if the new byte cycle starts or the output unit is inactive for the next eight timer clocks.
- If the sample buffer is empty: do not update the output level for the next eight timer clocks.
- Otherwise if the sample buffer is filled: The shift register is filled with the content of the sample buffer, sample buffer becomes empty state and the byte cycle repeats.
- Emptying the sample buffer essentially means the memory reader will immediately fill the sample buffer back if the current sample isn’t finished.
The memory reader includes a DMA device that reads the target sample byte from the CPU memory area by its own.
With these internal components:
- An address counter that points at the CPU address of the sample byte to read.
- A bytes-remaining counter that counts the number of bytes that are left to read.
- An 8-bit sample buffer that either temporary holds the current sample byte read with the DMA or is in empty state.
(Re)starting a sample reloads the address counter and the bytes-remaining counter based on $4012 and $4013.
The sample byte fetching process occurs whenever the sample buffer is empty and the bytes-remaining counter isn’t 0. Which only means it occurs when one of following happens:
- The playback has started with $4015 write when sample buffer was empty.
- The playback has restarted because of the loop flag (
Lbit). - The output unit emptied the sample buffer to fill the shift register and the sample hasn’t finished yet.
When the conditions are met, following happen:
- DMC DMA halts the CPU for 1-4 cycles to read the target byte, and fill the sample buffer with the byte read.
- The address counter is incremented. If it exceeds $FFFF, it is wrapped around $8000.
- The bytes-remaining counter is decremented. If it reaches 0-
- and if the loop flag (
Lbit) is set, the sample is restarted. (reloads the address counter and the bytes-remaining counter based on $4012 and $4013) - Otherwise if it reaches 0 and if the sample-end interrupt (
Ibit) is enabled, DMC IRQ pending flag is set.- At any time, if the interrupt flag is set, the CPU’s IRQ line is continuously asserted until the interrupt flag is cleared. It can be clared by writing any value to $4015 or by clearing the sample-end interrupt flag (
Ibit) in $4010.
- At any time, if the interrupt flag is set, the CPU’s IRQ line is continuously asserted until the interrupt flag is cleared. It can be clared by writing any value to $4015 or by clearing the sample-end interrupt flag (
- and if the loop flag (
On the 2A03 CPU used in the NTSC NES and Famicom, if a new sample byte is fetched from memory at the same time the program is reading a register that has read side effects (such as controllers via $4016 or $4017, PPUDATA ($2007), or the Vblank flag in PPUSTATUS ($2002), that register will see multiple extra reads that result in data loss or corruption. This is mostly a problem for controllers, and special controller reading code is necessary to work around this.
This problem is fixed on the 2A07 series of PAL CPUs by forcing DMA to halt on the first cycle of an instruction, which fetches an instruction opcode and thus isn’t normally reading from registers.
See DMA#DMC DMA for a thorough explanation of how DMA works and how it conflicts with register reads.
The DMC can generate CPU interrupt when it loaded the last sample byte to the sample buffer, and can play short enough sample that is shorter than a video frame. Using this, the DMC channel can be used to perform mid-frame video stuffs that usually required sprite zero hit flag, sprite overflow flag or external mapper timer IRQ.
The basic concept is about essentially playing a short silent sample at the fixed point of the screen (like at the very beginning of the PPU NMI, however because how the playback unit works, the sample playback does not begin immediately after you toggle the bit in $4015, and it can take maximum of 8 timer clocks until the shift register is ready.
The easiest and straightfoward way to work around of the issue is to measure the CPU cycles until it actually begins the playback and use that to cancel out the variable delay inside the generated IRQ.
At a fixed point in video rendering, a dummy single-byte sample at rate $F is started. Due to a hardware quirk†, the sample needs to be started three times in a row like this:
sei
lda #$10
sta $4015
sta $4015
sta $4015
cli
- The amount of cycles before a DMC IRQ happens is then measured (either using an actual IRQ, or by polling $4015).
- At rate $F, there are 54 CPU cycles between clocks, so there are 432 CPU cycles between boundaries.
- The main sample that will be used for the timing is then started (please refer to the table below to have sample lengths for various waiting times)
- When the main IRQ happens, the measurement from before is retrieved, and a timing loop with variable delay is used. In order to synchronize with Vblank, after a DMC IRQ we should wait 432 CPU cycles minus the time we measured.
†Note: The hardware quirk mentioned above deals with how DMC IRQs are generated. Basically, the IRQ is generated when the last byte of the sample is read, not when the last sample of the sample plays. The sample buffer sometimes has enough time to empty itself between writes to $4015, meaning your next write to $4015 will trigger an immediate IRQ. Fortunately, writing to $4015 three times will avoid this issue.
Still using Vblank as an example, the measurement tells how far into the 8-clock boundary Vblank occurred, and by delaying after a DMC IRQ, we perform a raster effect at the same point within the 8-clock boundary, aligning it with Vblank. By performing this same method each frame, the raster effect will have a reasonably stable timing to it. As a bonus, since mostly using IRQs are being used, the CPU is free to do something else, instead of waiting in a timed loop.
It’s possible to use more than one IRQ per frame - but the measurement part needs to be done at the same time within each frame, before the usage of any IRQ.
Only a single split-point per IRQ is possible, with the shortest IRQ being 3.8 scanlines. For split points closer than this amount, timed code has to be used.
In order to remain silent, samples should be made up of all $00 or $FF bytes, and $00 or $7F should have been previously written to $4011. Otherwise, audio will unintentionally be created. This is a sound channel, after all.
This table converts sample length in scanline length (all values are rounded to the higher integer).
NTSC Rate
Length $0 $1 $2 $3 $4 $5 $6 $7 $8 $9 $a $b $c $d $e $f
----------------------------------------------------------------------------------------------------
1-byte (8 bits) 31 27 24 23 21 18 16 16 14 12 10 10 8 6 6 4
17-byte (136 bits) ** ** ** ** ** ** ** ** 228 192 170 154 127 101 87 65
33-byte (264 bits) ** ** ** ** ** ** ** ** ** ** ** ** ** 196 168 126
49-byte (392 bits) ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** 187
PAL Rate
Length $0 $1 $2 $3 $4 $5 $6 $7 $8 $9 $a $b $c $d $e $f
----------------------------------------------------------------------------------------------------
1-byte (8 bits) 30 27 24 23 21 18 16 15 14 12 10 9 8 6 5 4
17-byte (136 bits) ** ** ** ** ** ** ** ** 225 189 169 151 126 100 85 64
33-byte (264 bits) ** ** ** ** ** ** ** ** ** ** ** ** ** 194 164 124
49-byte (392 bits) ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** 184
This table gives the best sample length and frequency combinations for all possible scanlines interval to wait. They are best because they are where the CPU will have to kill the least time. However, it’s still possible to use options to wait for fewer lines and kill more time during the interrupt before the video effect.
Because a PAL interrupt will always happen about the same time or a bit sooner than a NTSC interrupt, the NTSC table will be used to set the “best” setting here :
Scanlines Best opt. for IRQ
1-3 Timed code
4-5 Length $0, rate $f
6-7 Length $0, rate $d
8-9 Length $0, rate $c
10-11 Length $0, rate $a
12-13 Length $0, rate $9
14-15 Length $0, rate $8
16-17 Length $0, rate $6
18-20 Length $0, rate $5
21-22 Length $0, rate $4
23 Length $0, rate $3
24-26 Length $0, rate $2
27-30 Length $0, rate $1
31-64 Length $0, rate $0
65-86 Length $1, rate $f
87-100 Length $1, rate $e
101-125 Length $1, rate $d
126 Length $2, rate $f
127-153 Length $1, rate $c
154-167 Length $1, rate $b
168-169 Length $2, rate $e
170-186 Length $1, rate $a
187-191 Length $3, rate $f
192-195 Length $1, rate $9
196-227 Length $2, rate $d
228-239 Length $1, rate $8
| V | | |
|---|---|
| Concepts | Registers | Basics | Period table |
| Channels | Pulse 1 and Pulse 2 | Triangle | Noise | DMC |
| Components | Envelope | Sweep | Frame Counter | Length Counter | DMA | Mixer |
| Expansion audio | 2C33 (Disk System) | MMC5 | VRC6 | VRC7 | Namco 163 | Sunsoft 5B | µPD7756 |