Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix the behavior of the direct audio channels #1847

Closed
Gericom opened this issue Aug 8, 2020 · 0 comments
Closed

Fix the behavior of the direct audio channels #1847

Gericom opened this issue Aug 8, 2020 · 0 comments

Comments

@Gericom
Copy link

@Gericom Gericom commented Aug 8, 2020

After having performed various tests on real hardware I found out that the direct audio channels behave slightly different from what is generally believed. (I hope I didn't forget anything)

The fifo's of the two channels work as follows:

  • They are made from a 7 (!) 32-bit word ring buffer
  • Internally there's a separate 32-bit word for each of the two channels that is used as the current playing buffer
  • When the timer overflows:
    (1) if there are 4 or more empty words in the fifo, then a dma request is issued
    (2) if the current playing buffer is empty, and the fifo has at least one word available, it is transferred to the buffer. Note that this means that two dma requests will never happen without an extra timer overflow in-between, since there is simply no place in the buffer yet! If both the fifo and the current playing word are empty, I guess it will keep playing the last played sample. It definitely won't loop on the current play buffer, so I suppose the samples are shifted out of there or so.
  • Writing to the fifo using the cpu will always perform a modification on the 32 bit word in the fifo that is currently to be written and then move the write pointer to the next word. 32 bit writes obviously work as expected and write 4 new samples. On 16 and 8 bit writes, it will also result in 4 new samples, but 2 respectively 3 samples will be left over from the old value on that place in the ring buffer. Which depends on what part of the fifo register you write.
    For example say that the current fifo write location contained 0xAABBCCDD previously and you do *(vu8*)0x040000A0 = 8;. This results in the value 0xAABBCC08 to be written to the fifo. Similarly if you write to other parts, only the addressed part will be replaced. So *(vu8*)0x040000A3 = 2; results in 0x02BBCCDD. This works similar for 16 bit, but then either the upper or lower 16 bits will be replaced.
  • It seems that when the fifo overflows, it is reset to an empty state (similar to writing the fifo reset bit in SOUNDCNT_H).
  • Sound fifo dma is forced to 32 bit, but the destination address is not forced to be the sound fifo. As such it is possible to generate interrupts whenever there is enough space for 16 samples in the fifo by setting the destination to 0x00000000 or something and doing cpu writes in the dma interrupt.

This test rom will help checking if the dma request timings are correct.
directaudiotest.zip
Expected output is as follows (ran on a dslite in gba mode):
image
The numbers are the number of cycles between iterations of the loop in this function:
image

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Linked pull requests

Successfully merging a pull request may close this issue.

None yet
2 participants