APU basics: Difference between revisions

From NESdev Wiki
Jump to navigationJump to search
(How to use a period table)
(An octave down)
Line 78: Line 78:
The article [[APU period table]] has a lookup table from semitone numbers. For example, to play a middle C:
The article [[APU period table]] has a lookup table from semitone numbers. For example, to play a middle C:


  ldx #27    ; middle C, because 0 is an octave above the lowest A on the piano
  ldy #27    ; middle C, because 0 is an octave above the lowest A on the piano
 
  lda periodTableLo,x
  lda periodTableLo,y
  sta $4002
  sta $4002
  lda periodTableHi,x
  lda periodTableHi,y
  sta $4003
  sta $4003
 
  lda #%10111111
  lda #%10111111
  sta $4000
  sta $4000
Line 125: Line 125:
|}
|}


To determine the raw period for a given frequency in Hz, use this formula:
For any given period, the triangle channel's frequency is half that of the pulse channel, or a pitch one octave lower. To determine the raw period for a given frequency in Hz, use this formula:


:raw period = round(55930.4/frequency) - 1
:raw period = round(55930.4/frequency) - 1
Line 142: Line 142:
  sta $400B
  sta $400B


To silence the wave, write %10000000 to $4008. Note that writes to $4008 can take up to 1/240 second before affecting the triangle channel. Writing a raw period of 0 also silences the wave, but produces a pop, so it's not the preferred method.
To silence the wave, write %10000000 to $4008. Note that writes to $4008 can take up to 1/240 second before affecting the triangle channel, but the listener likely won't notice. Writing a raw period of 0 also silences the wave, but produces a pop, so it's not the preferred method.


The raw period can be changed while the channel is playing.
The raw period can be changed while the channel is playing.

Revision as of 13:14, 29 July 2010

This article covers basic usage of the APU's four waveform channels. It does not cover the DMC, or more advanced usage. Any registers unrelated to basic operation are not even mentioned here.

Channels

The APU has five channels: two square waves, triangle wave, noise, and DMC (sample playback). Only the first four are covered here.

The channel registers begin at $4000, and each channel has four registers devoted to it. All but the triangle wave have 4-bit volume control (the triangle just has an un-mute flag).

$4000-$4003 First square
$4004-$4007 Second square
$4008-$400B Triangle
$400C-$400F Noise

In register descriptions below, bits listed as - can have any value written to them, while bits listed as 1 must have a 1 written, otherwise other APU features will be enabled, causing the registers to behave differently than described here.

Register initialization

Before using the APU, first initialize all the registers to known values that silence all channels.

init_apu:
        lda #$0F
        sta $4015
        
        ldy #0
@loop:  lda @regs,y
        sta $4000,y
        iny
        cpy #$18
        bne @loop
        
        rts
@regs:
        .byte $30,$08,$00,$00  ; constant volume = 0, sweep = off
        .byte $30,$08,$00,$00  ; constant volume = 0, sweep = off
        .byte $80,$00,$00,$00  ; linear counter = 0
        .byte $30,$00,$00,$00  ; constant volume = 0
        .byte $00,$00,$00,$00
        .byte $00,$0F,$00,$40

This writes values that are most useful for basic use of the channels. It's not important exactly what they do, just that they establish a known state.

Square wave channels

Main article: APU Pulse

There are two square wave channels, each with pitch, volume, and timbre controls.

$4000 $4004 %DD11VVVV Duty cycle and volume

DD: 00=12.5% 01=25% 10=50% 11=75%
VVVV: 0000=silence 1111=maximum

$4002 $4006 %LLLLLLLL Low 8 bits of raw period
$4003 $4007 %-----HHH High 3 bits of raw period

To determine the raw period for a given frequency in Hz, use this formula:

raw period = round(111860.8/frequency) - 1

The following code plays a 400 Hz square wave (50% duty) at maximum volume:

jsr init_apu

lda #<279
sta $4002

lda #>279
sta $4003

lda #%10111111
sta $4000

The article APU period table has a lookup table from semitone numbers. For example, to play a middle C:

ldy #27     ; middle C, because 0 is an octave above the lowest A on the piano

lda periodTableLo,y
sta $4002
lda periodTableHi,y
sta $4003

lda #%10111111
sta $4000

All parameters can be changed while the tone is playing. To fade a note out, for example, write to $4000 or $4004 with the lower 4 bits decreasing every few frames. Note that writing to $4003 and $4007 resets the phase, which causes a slight pop. This is an issue when doing vibrato, for example, and beyond the scope of this article.

Noise channel

Main article: APU Noise

The noise channel allows control over frequency, volume, and timbre.

$400C %--11VVVV Volume

VVVV: 0000=silence 1111=maximum

$400E %T---PPPP Tone mode enable, Period

The following code plays a tone-like noise at maximum volume:

jsr init_apu

lda #%10000101
sta $400E

lda #%00111111
sta $400C

All parameters can be changed while the noise is playing.

Triangle channel

Main article: APU Triangle

The triangle channel allows control over frequency and muting.

$4008 %1U------ Un-mute
$400A %LLLLLLLL Low 8 bits of raw period
$400B %-----HHH High 3 bits of raw period

For any given period, the triangle channel's frequency is half that of the pulse channel, or a pitch one octave lower. To determine the raw period for a given frequency in Hz, use this formula:

raw period = round(55930.4/frequency) - 1

The following code plays a 400 Hz triangle wave:

jsr init_apu

lda #%11000000
sta $4008

lda #<139
sta $400A

lda #>139
sta $400B

To silence the wave, write %10000000 to $4008. Note that writes to $4008 can take up to 1/240 second before affecting the triangle channel, but the listener likely won't notice. Writing a raw period of 0 also silences the wave, but produces a pop, so it's not the preferred method.

The raw period can be changed while the channel is playing.