User Tools

Site Tools


audio_controller

This is an old revision of the document!


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)

audio_controller.1742477655.txt.gz · Last modified: 2025/03/20 13:34 by arisotura

Donate Powered by PHP Valid HTML5 Valid CSS Driven by DokuWiki