gbadev.org forum archive

This is a read-only mirror of the content originally found on forum.gbadev.org (now offline), salvaged from Wayback machine copies. A new forum can be found here.

Audio > DMA Timing

#15756 - animension - Thu Jan 29, 2004 5:31 am

Ok, I just spent hours pulling my hair out trying to figure something out. Some info about what I'm doing with a sound renderer:

1) Set up a sound buffer of 128 bytes x 2 = 256 bytes, and initialize all to 0
2) Set up an active buffer flag, initialized to 0
3) Set up Timer 0 to (0xFFFF - 1024) // 16384 Hz
4) Set up Timer 1 to increment on Timer 0 overflow, initial count (0xFFFF - 128) + Enable IRQ
5) Set up Timer 1 IRQ handler to do the following in ARM ASM in roughly 35 cycles:
- Store REG_IE state into stack, clear VBL bit, and overwrite REG_IE to disable VBL
- Toggle active buffer
- If switching to second half, don't reset DMA -- it'll start reading second half on its own
- else: disable DMA, reset address to buffer start, enableDMA
- Restore REG_IE state from stack, and overwrite REG_IE with previous state
- return

What I've been banging my head against my desk for the last 2-3 hours is this, taken from the logging function of VBA(Win32) for my DMA transfers

Quote:

256 byte sound buffer starts at 0x03000bd8

DMA2: s=03000bd8 d=040000a4 c=b600 count=00000010
DMA2: s=03000be8 d=040000a4 c=b600 count=00000010
DMA2: s=03000bf8 d=040000a4 c=b600 count=00000010
DMA2: s=03000c08 d=040000a4 c=b600 count=00000010
DMA2: s=03000c18 d=040000a4 c=b600 count=00000010
DMA2: s=03000c28 d=040000a4 c=b600 count=00000010
DMA2: s=03000c38 d=040000a4 c=b600 count=00000010
DMA2: s=03000c48 d=040000a4 c=b600 count=00000010
DMA2: s=03000c58 d=040000a4 c=b600 count=00000010
DMA2: s=03000c68 d=040000a4 c=b600 count=00000010
DMA2: s=03000c78 d=040000a4 c=b600 count=00000010
DMA2: s=03000c88 d=040000a4 c=b600 count=00000010
DMA2: s=03000c98 d=040000a4 c=b600 count=00000010
DMA2: s=03000ca8 d=040000a4 c=b600 count=00000010
DMA2: s=03000cb8 d=040000a4 c=b600 count=00000010
DMA2: s=03000cc8 d=040000a4 c=b600 count=00000010
DMA2: s=03000cd8 d=040000a4 c=b600 count=00000010
DMA2: s=03000bd8 d=040000a4 c=b600 count=00000010
DMA2: s=03000be8 d=040000a4 c=b600 count=00000010
DMA2: s=03000bf8 d=040000a4 c=b600 count=00000010
DMA2: s=03000c08 d=040000a4 c=b600 count=00000010
DMA2: s=03000c18 d=040000a4 c=b600 count=00000010
DMA2: s=03000c28 d=040000a4 c=b600 count=00000010
DMA2: s=03000c38 d=040000a4 c=b600 count=00000010
DMA2: s=03000c48 d=040000a4 c=b600 count=00000010
DMA2: s=03000c58 d=040000a4 c=b600 count=00000010
DMA2: s=03000c68 d=040000a4 c=b600 count=00000010
DMA2: s=03000c78 d=040000a4 c=b600 count=00000010
DMA2: s=03000c88 d=040000a4 c=b600 count=00000010
DMA2: s=03000c98 d=040000a4 c=b600 count=00000010
DMA2: s=03000ca8 d=040000a4 c=b600 count=00000010
DMA2: s=03000cb8 d=040000a4 c=b600 count=00000010
DMA2: s=03000cc8 d=040000a4 c=b600 count=00000010
DMA2: s=03000bd8 d=040000a4 c=b600 count=00000010
DMA2: s=03000be8 d=040000a4 c=b600 count=00000010
DMA2: s=03000bf8 d=040000a4 c=b600 count=00000010
DMA2: s=03000c08 d=040000a4 c=b600 count=00000010
DMA2: s=03000c18 d=040000a4 c=b600 count=00000010
DMA2: s=03000c28 d=040000a4 c=b600 count=00000010
DMA2: s=03000c38 d=040000a4 c=b600 count=00000010
DMA2: s=03000c48 d=040000a4 c=b600 count=00000010
DMA2: s=03000c58 d=040000a4 c=b600 count=00000010
DMA2: s=03000c68 d=040000a4 c=b600 count=00000010
DMA2: s=03000c78 d=040000a4 c=b600 count=00000010
DMA2: s=03000c88 d=040000a4 c=b600 count=00000010
DMA2: s=03000c98 d=040000a4 c=b600 count=00000010
DMA2: s=03000ca8 d=040000a4 c=b600 count=00000010
DMA2: s=03000cb8 d=040000a4 c=b600 count=00000010
DMA2: s=03000cc8 d=040000a4 c=b600 count=00000010
DMA2: s=03000cd8 d=040000a4 c=b600 count=00000010
DMA2: s=03000bd8 d=040000a4 c=b600 count=00000010
DMA2: s=03000be8 d=040000a4 c=b600 count=00000010


Where the lines are bold is where VBA is telling me that the DMA is transferring 16 bytes of data past my buffer onto the FIFO! The problem is that it's not consistently doing it, but VBA does show that it *is* doing it. This is causing some noise to be sent to the FIFO and is extremely annoyying, considering the timer 1 IRQ handler is stopping the DMA within ~15 cycles after the IRQ handler is called when the DMA controller needs to wrap back to the beginning of the buffer. I even changed it so that the controller is stopped first thing (within 4 cycles of entering IRQ handler) and it made no noticable difference. Any suggestions would be most welcome.
_________________
"Beer is proof that God loves us and wants us to be happy."
-- Benjamin Franklin

#15760 - poslundc - Thu Jan 29, 2004 3:07 pm

This might be a silly question, but are you remembering to set REG_IF at the end of your ISR?

As for what's causing your extra-DMA problem, I'm pretty sure you should be setting your Timer 1's initial count to (0xFFFF - 127), not (0xFFFF - 128). The latter will take 129 sound-chip-cycles to overflow, which may be causing your extra DMA problem.

For that matter, you should be setting Timer0 to (0xFFFF - 1023) for greatest accuracy. (Or do what I did and just set it to 0xFFFF and set the timer's frequency to 16 KHz instead of full clock speed.)

Hope this helps,

Dan.

#15761 - Lord Graga - Thu Jan 29, 2004 4:09 pm

proslundc: Wouldn't it be the other way around? :P
As in:
(0xFFFF - 129)

I don't know much about sound though, sorry if I am wrong :P

#15763 - poslundc - Thu Jan 29, 2004 5:20 pm

Lord Graga wrote:
proslundc: Wouldn't it be the other way around? :P
As in:
(0xFFFF - 129)


That would make the interrupt fire every 130 timer-cycles. Remember, the timer value counts up and it triggers on overflow.

Dan.

#15766 - Lord Graga - Thu Jan 29, 2004 6:16 pm

heh, that's right, poslundc ;)

Thanks for pointing it out :)

#15772 - animension - Thu Jan 29, 2004 7:47 pm

Oh no... my first "off by one" bug... Something so simple that I should have seen it. That did the trick. Thanks!
_________________
"Beer is proof that God loves us and wants us to be happy."
-- Benjamin Franklin