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.

ASM > Direct Sound sample won't play

#1892 - GbaGuy - Sat Jan 25, 2003 3:22 am

I rewrote the direct sound sample code in ASM (from BeLogic.com)
and came up with this, but it doesn't appear to work (using VisualBoyAdvance):

Code:

@include dma.h
@include dirsound.h
@include timer.h
@include interrupt.h
b start
THE_WAV
@incbin wav.raw
start

ldr r4,= REG_SOUNDCNT_H
ldr r5,= 0x0B0F
strh r5,[r4]

ldr r4, =REG_SOUNDCNT_X
ldr r5, =0x0080
strh r5,[r4]

ldr r4,=REG_DMA1SAD
ldr r5,=THE_WAV
str r5,[r4]

ldr r4,=REG_DMA1DAD
ldr r5,=0x040000a0
str r5,[r4]

ldr r4,= REG_DMA1CNT
ldr r5,= 0xb600 | DMA_32NOW
strh r5,[r4]

ldr r4, = REG_TM0D
ldr r5,= 0x7098
strh r5,[r4]

ldr r4, = REG_TM0CNT
ldr r5, = 0xC4
strh r5,[r4]

ldr r4, = REG_INTADDR
ldr r5, = Handler
str r5,[r4]

ldr r4, = REG_IE
ldr r5, = 0x10
strh r5,[r4]

ldr r4, = REG_IME
ldr r5, = 0x1
strh r5,[r4]

ldr r4, = REG_TM0D
ldr r5, = 0xFBE8
strh r5,[r4]

ldr r4, = REG_TM0CNT
ldr r5, = 0x0080
strh r5,[r4]

infin
b infin

Handler:
   ldr r1,=0
   ldr r2,=REG_DMA1CNT
   str r1,[r2]
   ldr r2,=REG_TM0CNT
   str r1,[r2]

   ldr r2,=REG_IF
   str r1,[r2]



Please help.

Thanks,
- GbaGuy

#1895 - Splam - Sat Jan 25, 2003 4:30 am

Is that all the code or did you miss a bit off? ie How do you return from the interrupt? bx lr maybe?

#1896 - GbaGuy - Sat Jan 25, 2003 4:36 am

Are you sure it's bx lr ?

I'm not sure, but I had it in my head that clearing REG_IF would return
from the interrupt.

#1911 - Splam - Sat Jan 25, 2003 5:06 pm

I've just woken up so forgive me if this is wrong but,

When an interrupt occurs the BIOS catches it, vectors to its interrupt handler which then pushes r0-r3, r12 and lr, fetches the interrupt vector at 0x3007ffc and reads the contents of that into the PC which then causes the processor to run your code. When you've finished your code you then need to get back to the exit part of the bios routine which is done with bx lr, the bios then pulls those registers from the stack and sets the PC back to what it was b4 the interrupt. Clearing REG_IF is only to tell the gba that you've handled that interrupt (so another one can occur), it won't do anything about exiting the interrupt routine.

Having said that, because you're playing a sample straight from rom and not mixing it into a buffer you should at least hear the sample once, which is what you seem to be wanting anyway as the interrupt handler stops the dma and timer, so if it's playing nothing then it's something else wrong too ;) It's just hard to spot something written in asm with "magic numbers" everywhere. I'll have a look at your code some more and convert the hex ldr's so I can see what you're putting in all the dma and timer registers.

#1918 - DekuTree64 - Sat Jan 25, 2003 8:06 pm

Hmm, I don't really know what it's supposed to do, but it looks like the interrupt is to stop the sound when it's done? Looks like you set your timer up right, then set IE and IME, and then set the same timer for the sound frequency, so the interrupt is never being called.
And I'd need to see the definition of DMA_32NOW to be sure, but do you have it set to dest fixed (bit 6)? If not then you're going through all sorts of registers setting them to the sound data, which is of course not a good thing to do.

So to fix it, use a different timer for the interrupt (and Splam is right, you should have a bx lr at the end ofthe interrupt), and set bit 6 in DMA1CNT.

#1929 - GbaGuy - Sun Jan 26, 2003 3:01 am

Alright, I took out the timer stuff and the interrupt handler. Also, now
I set everything in REG_SOUNDCNT_H which should allow both FIFOs
to go if I wanted them to (only need 1).

So, by elimination, it has to be the DMA transfer.

Also, it angers me that I translated all this from the C sample code at
www.belogic.com, and it doesn't work...

Here's the new code:

Code:


@include dma.h
@include dirsound.h
@include timer.h
@include interrupt.h
b start
THE_WAV
@incbin wav.raw
start

ldr r4,= REG_SOUNDCNT_L
ldr r5,= 0             
strh r5,[r4]

ldr r4,= REG_SOUNDCNT_H 
ldr r5,= 0xFFFF
strh r5,[r4]

ldr r4, =REG_SOUNDCNT_X
ldr r5, =0x00000080
str r5,[r4]

ldr r4,=REG_DMA1SAD
ldr r5,=THE_WAV
str r5,[r4]

ldr r4,=REG_DMA1DAD
ldr r5,=0x40000a0
str r5,[r4]

ldr r4,= REG_DMA1CNT
ldr r5,= 0xb600  ; according to BeLogic, this number is :
strh r5,[r4]        ; DMA enabled+ start on FIFO+32bit+repeat

; further more, I've tried ORing 0xb600 with DMA_DEST_FIXED, but
; that didn't work either.

infin
b infin




In theory, I should atleast hear the entire sound once, right?
But I don't hear anything...

thanks for you help so far,
- GbaGuy


Last edited by GbaGuy on Sun Jan 26, 2003 8:03 pm; edited 1 time in total

#1946 - Splam - Sun Jan 26, 2003 2:16 pm

Well, having looked at the example code on the BeLogic site you seem to have made the mistake of setting up a timer for the dma and a cascade timer (the one that tells you when the sample is complete) BUT used timer0 for both of them.. Quite probably whats causing the problem if the C example works and your asm one doesn't. Hope that fixes it for you ;)

#1947 - DekuTree64 - Sun Jan 26, 2003 5:48 pm

Ok, assembly is hard to explain every little detail of how to fix, so I just made the changes myself. I haven't tested it, but try it out and see if it works. If it doesn't, then I'm just as clueless as you^_^

Code:

@include dma.h
@include dirsound.h
@include timer.h
@include interrupt.h
b start
THE_WAV
@incbin wav.raw
start

ldr r4,= REG_SOUNDCNT_H
ldr r5,= 0x0B0F ;setting this to 0xffff was setting the timer bit as well, which makes it use TM2 instead of TM1
strh r5,[r4]

ldr r4, =REG_SOUNDCNT_X
ldr r5, =0x0080
strh r5,[r4]

ldr r4,=REG_DMA1SAD
ldr r5,=THE_WAV
str r5,[r4]

ldr r4,=REG_DMA1DAD
ldr r5,=0x040000a0
str r5,[r4]

ldr r4,= REG_DMA1CNT
ldr r5,= 0xb640 ;this has dest fixed set
strh r5,[r4]

ldr r4, = REG_TM0D ;and this is for the sound frequency, so it needs to be here
ldr r5, = 0xFBE8
strh r5,[r4]

ldr r4, = REG_TM0CNT
ldr r5, = 0x0080
strh r5,[r4]

infin
b infin

#1949 - Splam - Sun Jan 26, 2003 6:16 pm

The original code posted was ok so I'd suggest using that EXCEPT it needs bx lr at the end of interrupt code AND change the TM0 to TM1. Just read the C source again and see which one..