I am writing mixer, using stereo DMA1/2 transfer, drived by timer0.
I am using double buffering that means my buffer have samples for two
VBLANK periods (DMA restart is every second vblank). Mixer frequency
is 22075 hz.
so timer0 counter value is 0xffff-(2^24 / 22075) ~= 0xfd08
and buffer size = 22075/60 ~= 368
my routine is unstable, that means it generates click not every
buffer restart (30 a second) but at lower frequency.
I have written two routines, one to init mixer (dma, sound output)
and second to restart DMA.
I tried everything (except the thing that would help :-)
(enlarging buffer, slightly changing timer frequency, resetting timer
every second vblank with DMA reset, starting timer in init routine
synchronized to 160 vline).
Maybe I am using not valid frequency.
I tested it on software VisualBoyAdvance and hardware with flash
linker.
I cannot get rid of strange clicks and sounds in my samples. I fight
with that for few days and going out of my nerves. Here is my code,
please please help!!!
(Maybe someone will support me with such working routine.)
... mixer.s
SAMPLES_PER_VBLANK = 368
SOUND_BUFFERS = 2
SOUND_CONTROL_LOW = 0x0080
SOUND_CONTROL_HIGH = 0x0082
SOUND_CONTROL = 0x0084
SOUND_FIFO_A = 0x00A0
SOUND_FIFO_B = 0x00A4
SOUND_FIFO_A_RATIO_HALF = 0x0000
SOUND_FIFO_A_RATIO_FULL = 0x0004
SOUND_FIFO_B_RATIO_HALF = 0x0000
SOUND_FIFO_B_RATIO_FULL = 0x0008
SOUND_FIFO_A_OUTPUT_R = 0x0100
SOUND_FIFO_A_OUTPUT_L = 0x0200
SOUND_FIFO_A_TIMER_0 = 0x0000
SOUND_FIFO_A_TIMER_1 = 0x0400
SOUND_FIFO_A_RESET = 0x0800
SOUND_FIFO_B_OUTPUT_R = 0x1000
SOUND_FIFO_B_OUTPUT_L = 0x2000
SOUND_FIFO_B_TIMER_0 = 0x0000
SOUND_FIFO_B_TIMER_1 = 0x4000
SOUND_FIFO_B_RESET = 0x8000
SOUND_CIRCUIT_ENABLE = 0x0080
DMA1_SOURCE_ADDRESS = 0x00BC
DMA1_DESTINATION_ADDRESS = 0x00C0
DMA1_WORD_COUNT = 0x00C4
DMA1_CONTROL = 0x00C6
DMA2_SOURCE_ADDRESS = 0x00C8
DMA2_DESTINATION_ADDRESS = 0x00CC
DMA2_WORD_COUNT = 0x00D0
DMA2_CONTROL = 0x00D2
DMA_ENABLE_FLAG = 0x8000
DMA_START_ON_SOUND_FIFO = 0x3000
DMA_TRANSFER_32BIT = 0x0400
DMA_REPEAT = 0x0200
DMA_SOURCE_INCREMENT = 0x0000
DMA_DESTINATION_FIXED = 0x0040
TIMER0_SETTING = 0x00
TIMER0_CONTROL = 0x02
TIMER_START_TIMER = 0x0080
TIMER_PRESCALE_1 = 0x0000
.section .iwram
.balign 4
left_channel: .space SOUND_BUFFERS*SAMPLES_PER_VBLANK
right_channel: .space SOUND_BUFFERS*SAMPLES_PER_VBLANK
first_vbl: .word 0
second_vbl: .word 0
timer0_mix_freq: .word 0xfd08
left_channel_address: .word left_channel
right_channel_address: .word right_channel
first_vbl_address: .word first_vbl
second_vbl_address: .word second_vbl
mixer_init:
stmfd sp!, {r0, r1, lr}
mov r0, #0
ldr r1, first_vbl_address
str r0, [r1]
ldr r1, second_vbl_address
str r0, [r1]
mov r1, #0x04000000
@ set DMA source
ldr r2, left_channel_address
str r2, [r1, #DMA1_SOURCE_ADDRESS]
ldr r2, right_channel_address
str r2, [r1, #DMA2_SOURCE_ADDRESS]
@ set DMA dest
mov r0, r1
add r0, r0, #SOUND_FIFO_A
str r0, [r1, #DMA1_DESTINATION_ADDRESS]
mov r0, r1
add r0, r0, #SOUND_FIFO_B
str r0, [r1, #DMA2_DESTINATION_ADDRESS]
@enable DMA
mov r0, #DMA_ENABLE_FLAG |
DMA_START_ON_SOUND_FIFO | DMA_TRANSFER_32BIT | DMA_REPEAT
orr r0, r0, #DMA_SOURCE_INCREMENT |
DMA_DESTINATION_FIXED
strh r0, [r1, #DMA1_CONTROL]
strh r0, [r1, #DMA2_CONTROL]
@ setup Direct Sound Volume & Output
mov r0, #SOUND_FIFO_A_RESET |
SOUND_FIFO_B_RESET | SOUND_FIFO_A_TIMER_0 | SOUND_FIFO_B_TIMER_0
orr r0, r0, #SOUND_FIFO_A_RATIO_FULL |
SOUND_FIFO_B_RATIO_FULL
orr r0, r0, #SOUND_FIFO_A_OUTPUT_L |
SOUND_FIFO_B_OUTPUT_R
strh r0, [r1, #SOUND_CONTROL_HIGH]
mov r0, #SOUND_CIRCUIT_ENABLE
strh r0, [r1, #SOUND_CONTROL]
ldmfd sp!, {r0, r1, lr}
mov pc, lr
VBLANK:
stmfd sp!, {r0-r2, lr}
bl mixer_dma
mov r1, #0x04000000
orr r1, r1, #0x200
mov r0, #1
str r0, [r1, #2]
ldmfd sp!, {r0-r2, lr}
mov pc, lr
mixer_dma:
stmfd sp!, {r0-r2}
@ flip buffers (r0 = current buffer)
ldr r1, second_vbl_address
ldr r0, [r1]
add r0, r0, #1
cmp r0, #3
blt mixer_dma_not_reset
@ reset DMA
mov r1, #0x04000000
mov r0, #0
strh r0, [r1, #DMA1_CONTROL]
strh r0, [r1, #DMA2_CONTROL]
@ set DMA source
ldr r2, left_channel_address
str r2, [r1, #DMA1_SOURCE_ADDRESS]
ldr r2, right_channel_address
str r2, [r1, #DMA2_SOURCE_ADDRESS]
@enable DMA
mov r0, #DMA_ENABLE_FLAG |
DMA_START_ON_SOUND_FIFO | DMA_TRANSFER_32BIT | DMA_REPEAT
orr r0, r0, #DMA_SOURCE_INCREMENT |
DMA_DESTINATION_FIXED
strh r0, [r1, #DMA1_CONTROL]
strh r0, [r1, #DMA2_CONTROL]
mov r0, #0
mixer_dma_not_reset:
ldr r1, second_vbl_address
str r0, [r1]
ldr r1, first_vbl_address
ldr r0, [r1]
cmp r0, #0
bne mixer_dma_second_vbl
mov r0, #1
str r0, [r1]
@ setup Timer0 frequency & enable it
mov r1, #0x04000000
add r1, r1, #0x0100
ldr r0, timer0_mix_freq
strh r0, [r1, #TIMER0_SETTING]
mov r0, #TIMER_START_TIMER | TIMER_PRESCALE_1
strh r0, [r1, #TIMER0_CONTROL]
mixer_dma_second_vbl:
ldmfd sp!, {r0-r2}
mov pc, lr
Thanks in advance
Tristan Rybak
rybak@...