This is an old revision of the document!
−Table of Contents
Audio controller
The gamepad has a simple audio controller that presumably just streams raw PCM16 to the speakers/headphone jack.
Register map:
Address | Desc. |
---|---|
0xF0005400 | Output - control register |
0xF0005404 | Output - ?? |
0xF0005408 | Output - buffer start address |
0xF000540C | Output - buffer end address |
0xF0005410 | Output - playback end address |
0xF0005414 | Output - current playback address |
0xF0005418 | ???? |
0xF000541C | ?? |
0xF0005420 | Output - playback control of sorts |
0xF0005424 | Output - count for alert IRQ |
0xF0005428 | Output - remaining playback count |
0xF000542C | Output - IRQ enable |
0xF0005430 | Output - IRQ status |
0xF0005434 | Output - ?? (IRQ related) |
0xF0005438 | Output - current even sample (left) |
0xF000543C | Output - current odd sample (right) |
0xF0005440 | counter of sorts? |
0xF0005444 | Input control (?) |
0xF0005448 | ??? |
0xF00054A0 | Input - buffer start address? |
0xF00054A4 | Input - buffer end address? |
0xF00054A8 | Input - current buffer address? |
0xF00054B0 | ?? |
0xF00054B4 | Input related?? |
0xF00054C0 | Input - IRQ flags? |
0xF00054C4 | Input - IRQ enable? |
0xF00054C8 | Input - IRQ ack? |
Related IRQs:
IRQ | Desc. |
---|---|
0x17 | Audio output event |
0x18 | Presumably audio capture event |
0x1E | Periodic IRQ |
IRQ 0x17 is used to signal certain events related to audio playback, such as start or end of playback.
IRQ 0x1E is used by the stock firmware for certain non-audio tasks such as input polling. It seems to always trigger periodically no matter what. I measured the period to be ~5547 microseconds (~600000 cycles), no idea what this represents.
Not yet known:
- if it is possible to play a looping sound (TODO check F0005420 bit0)
- how to set the sample rate (prolly directly on the amplifier)
Audio controller registers
0xF0005400
Controls low level aspects of how sound data is parsed and transmitted to the amplifier.
Bits | Desc. |
---|---|
0 | ?? Enable? |
1 | ??? |
2 | ?? |
3 | ?? |
4 | ?? |
5 | Channel order; 0=L/R, 1=R/L |
6-10 | Offset of sound data relative to sample clock |
11-15 | Bit width of sound data |
16 | ??? |
17 | ??? |
18 | ?? |
19 | ?? 1=disable sound output but not always?? |
20 | ?? |
21 | ?? |
22 | Sample rate; 0=48KHz, 1=24KHz |
23 | Sound format; 0=PCM16, 1=PCM8 |
24 | Encoding for PCM8; 0=µ-law, 1=A-law |
The initial value for this register is 0x00008000.
When bit 19 is set, no sound data is sent to the audio amplifier. It effectively functions as a mute bit, even though muting is done at the amplifier level – maybe it serves to make extra sure no sound will come out? TODO figure out what the fuck is going on with bit 19
Sound data is transmitted to the amplifier over an I2S interface. The sample clock and bit clock are generated by the amplifier, at speeds of 48 KHz and 3.08 MHz respectively.
Bits 6-10 control when a sample starts relative to the sample clock edges. The default setting is 1.
Bits 11-15 seem to control the bit width of samples. 0 seems to be interpreted as 32. In practice, values 16 and above act the same. The default setting is 0.
0xF0005404
Controls aspects of playback?
This register is 16 bits wide.
Setting bit 7 causes each sample to be output to both left and right channels, essentially acting as mono.
0xF0005408
Output buffer start address.
Stock firmware ensures it is aligned to a 16-byte boundary.
0xF000540C
Output buffer end address.
0xF0005410
Playback end address.
Writing to this register starts playback. This register is not updated by hardware.
This register is actually the address at which playback will end. If it is set to the beginning of the buffer, the entire buffer will be played once. If it is set to the end of the buffer, or anywhere outside of the buffer, the entire buffer will be played repeatedly.
Bits 3-27 are writable. It seems that the playback address has a resolution of 16 bytes (atleast with settings: 48KHz stereo 16bit), ie. setting bit 3 will cause the buffer to be played repeatedly.
Writing to this register while playback is in progress has no effect. TODO: not yet known how to cleanly stop playback.
0xF0005414
Current playback address. This register is updated by hardware during playback. After playback is finished, it points back to the buffer start.
0xF0005420
Unknown.
Bits | Desc. |
---|---|
0 | Mute? |
1 | Mute but weird? |
2 | Stop playback |
4 | ??? |
8 | ??? |
Bit 0 seems to mute sound output? but not always (ie. if F0005400 bit19 is cleared, sometimes it doesn't mute). Setting bit 0 also triggers IRQ 0 immediately. Clearing bit 0 causes IRQ 4 to be triggered as soon as sound is playing.
Bit 1 functions identically to bit 0, but a bit weird. Setting bit 1 triggers IRQ 1 immediately. Clearing bit 1 causes IRQ 5 to be triggered as soon as sound is playing.
Setting bit 2 stops playback. IRQ 2 is fired when playback is stopped, and bit 2 is automatically cleared.
Bit 4 can only be set when no sound is playing. It seems to be forced to zero when sound is playing. Not known what the effect is.
Bit 8 can be set or cleared at any time. Not known what the effect is.
0xF0005424
This register controls when IRQ 3 should fire. It can be used to trigger an interrupt at a specific point within the buffer.
It is expressed in units of 8 bytes. For example, setting it to 8 causes the IRQ to fire 64 bytes before the end of the buffer is reached.
This likely just works by comparing 0xF0005428 against this register.
(TODO word less awkwardly)
0xF0005428
Remaining amount of audio data to be played, expressed in 8-byte units.
It is simply the difference between the requested playback end address (accounting for wraparound) and the current address.
This register is not reloaded when reaching the end of the buffer and looping back to the start, which causes it to wrap around to a very large value. If one desires repeated alert IRQs, 0xF0005424 needs to be adjusted upon each alert IRQ (by subtracting the buffer size from it).
0xF000542C
IRQ enable flags.
Bits | Desc. |
---|---|
0 | Mute (0xF0005420 bit 0) |
1 | Mute (0xF0005420 bit 1) |
2 | Playback stop |
3 | Position alert (0xF0005424) |
4 | Unmute (0xF0005420 bit 0) |
5 | Unmute (0xF0005420 bit 1) |
0xF0005430
IRQ status flags. Writing a 1 to a flag clears it.
Same format as register 0xF000542C.
IRQ status flags seem to only get set if the corresponding enable flags are set.
Failure to properly clear these flags will result in IRQs being triggered again and again, effectively freezing the main program.
Headphones detection
Neither the audio controller nor the audio amplifier are aware of whether headphones are connected. The UIC is responsible for this.
The headphone status can be found in the input data buffer (returned by UIC command 0x07): power status byte, bit 5.
The stock firmware checks for when this bit changes, and reconfigures the audio amplifier as needed. (TODO: document this)