pcmaudio: bugfix corrupted audio, loop mode, adjust examples
This commit is contained in:
parent
79baf3cef5
commit
11814cd24f
5 changed files with 363 additions and 46 deletions
101
lib/pcmaudio.s
101
lib/pcmaudio.s
|
|
@ -1,25 +1,25 @@
|
|||
.EQU AUDIO_BASE $A00
|
||||
.EQU IRQC_REG $980
|
||||
.EQU IRQC_EN $80
|
||||
.EQU CPU_FREQ 77000000
|
||||
|
||||
; args: sample rate
|
||||
START_PCMAUDIO:
|
||||
; calculate clock divider
|
||||
LOADCP 77000000
|
||||
LOADCP CPU_FREQ
|
||||
SWAP
|
||||
LOADCP _DIV
|
||||
CALL
|
||||
|
||||
LOADC AUDIO_BASE + 1
|
||||
SWAP ; put clock divider on ToS
|
||||
; LOADCP 4812 ; clock divider for 16KHz sample rate
|
||||
; LOADCP 2406 ; clock divider for 32KHz sample rate
|
||||
STOREI 1
|
||||
LOADCP 32768 ; set amplitude to biased 0
|
||||
STOREI
|
||||
DROP
|
||||
|
||||
LOADC AUDIO_BASE
|
||||
LOADC 17 ; enable channel, enable interrupt
|
||||
LOADC 1 ; enable channel
|
||||
STOREI
|
||||
DROP
|
||||
RET
|
||||
|
|
@ -101,18 +101,14 @@ PLAY1_L0:
|
|||
DROP
|
||||
RET
|
||||
|
||||
; start interrupt-driven sample playback
|
||||
; args: pointer to pascal string, sample rate
|
||||
SAMPLEQSTART:
|
||||
LOADCP START_PCMAUDIO
|
||||
CALL
|
||||
|
||||
; set sample queue count and pointer from string header
|
||||
; args: pointer to string/SndBufPtr
|
||||
_STR2SMPLQPTR:
|
||||
LOADCP SMPLQ_COUNT
|
||||
OVER
|
||||
LOADI ; get string size from header
|
||||
SHR ; divide by 4 to get word count
|
||||
SHR
|
||||
|
||||
STOREI
|
||||
DROP
|
||||
|
||||
|
|
@ -121,6 +117,38 @@ SAMPLEQSTART:
|
|||
INC 8 ; skip rest of header
|
||||
STOREI ; store sample data pointer
|
||||
DROP
|
||||
RET
|
||||
|
||||
; start interrupt-driven sample playback
|
||||
; args: pointer to pascal string, loop flag, sample rate
|
||||
SAMPLEQSTART:
|
||||
LOADCP START_PCMAUDIO ; sample rate is on ToS as arg to subroutine
|
||||
CALL
|
||||
|
||||
SWAP ; swap loop flag and buf ptr
|
||||
|
||||
LOADCP _STR2SMPLQPTR
|
||||
CALL
|
||||
|
||||
; loop flag is now on ToS
|
||||
CBRANCH.Z SQ_S_1
|
||||
; if nonzero, set loop ptr
|
||||
LOADCP SMPLQ_PTR
|
||||
LOADI
|
||||
DEC 8 ; subtract offset for string header again
|
||||
BRANCH SQ_S_0
|
||||
SQ_S_1:
|
||||
LOADC 0
|
||||
SQ_S_0:
|
||||
LOADCP SMPLQ_NEXT
|
||||
SWAP
|
||||
STOREI
|
||||
DROP
|
||||
|
||||
LOADC AUDIO_BASE
|
||||
LOADC 17 ; enable channel, enable interrupt
|
||||
STOREI
|
||||
DROP
|
||||
|
||||
LOADCP SMPLQ_ISR ; set interrupt handler
|
||||
STOREREG IV
|
||||
|
|
@ -154,6 +182,7 @@ SAMPLEQSIZE:
|
|||
|
||||
SMPLQ_PTR: .WORD 0
|
||||
SMPLQ_COUNT: .WORD 0
|
||||
SMPLQ_NEXT: .WORD 0
|
||||
|
||||
SMPLQ_ISR:
|
||||
LOADC IRQC_REG
|
||||
|
|
@ -170,7 +199,7 @@ SMPLQ_I_L:
|
|||
DROP
|
||||
BRANCH SMPLQ_I_XT ; if null, end interrupt routine
|
||||
SMPLQ_I_B:
|
||||
LOADI ; load next word
|
||||
LOADI ; load next word which contains two samples
|
||||
DUP
|
||||
|
||||
BROT ; get high half-word
|
||||
|
|
@ -205,23 +234,42 @@ SMPLQ_I_B:
|
|||
STOREI
|
||||
DROP
|
||||
|
||||
; check if fifo is full
|
||||
LOADC AUDIO_BASE
|
||||
LOADI
|
||||
LOADC 8 ; fifo_full
|
||||
; put up to 16 samples into the sample queue
|
||||
LOADCP SMPLQ_COUNT
|
||||
LOADI ; load word counter again
|
||||
LOADC 7 ; check if count modulo 7 = 0
|
||||
AND
|
||||
CBRANCH.Z SMPLQ_I_L ; next sample if not full
|
||||
CBRANCH.NZ SMPLQ_I_L ; if not, next two samples
|
||||
|
||||
LOADC AUDIO_BASE
|
||||
LOADC 17 ; re-enable channel interrupt
|
||||
STOREI
|
||||
; check if fifo is full
|
||||
; does not work reliably when running in DRAM,
|
||||
; maybe because at least one sample has already played
|
||||
; since start of ISR?
|
||||
; LOADC AUDIO_BASE
|
||||
; LOADI
|
||||
; LOADC 8 ; fifo_full
|
||||
; AND
|
||||
; CBRANCH.Z SMPLQ_I_L ; next sample if not full
|
||||
|
||||
BRANCH SMPLQ_I_XT
|
||||
|
||||
; end of sample buffer, check for next
|
||||
SMPLQ_I_END:
|
||||
DROP
|
||||
DROP
|
||||
|
||||
LOADCP SMPLQ_NEXT ; skip to end
|
||||
LOADI ; if NEXT ptr is zero
|
||||
DUP
|
||||
CBRANCH.Z SMPLQ_I_END1
|
||||
|
||||
LOADCP _STR2SMPLQPTR
|
||||
CALL
|
||||
|
||||
BRANCH SMPLQ_I_XT
|
||||
|
||||
; end playback, set ptr and counter to zero
|
||||
SMPLQ_I_END:
|
||||
DROP
|
||||
SMPLQ_I_END1:
|
||||
DROP
|
||||
LOADCP SMPLQ_PTR
|
||||
LOADC 0
|
||||
|
|
@ -238,7 +286,16 @@ SMPLQ_I_END:
|
|||
STOREI
|
||||
DROP
|
||||
|
||||
; exit without enabling interrupts for this channel
|
||||
BRANCH SMPLQ_I_XT2
|
||||
|
||||
SMPLQ_I_XT:
|
||||
LOADC AUDIO_BASE
|
||||
LOADC 17 ; re-enable channel interrupt
|
||||
STOREI
|
||||
DROP
|
||||
|
||||
SMPLQ_I_XT2:
|
||||
LOADC IRQC_REG ; re-enable interrupts
|
||||
LOADC IRQC_EN
|
||||
STOREI
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue