📄 pcm_pcm.s
字号:
/************************************************************************/
; (c)1996 Copyright M-Pact, Inc. All rights reserved
;
; Revision 1.0
;
;
; Module: PCM_OUT (PCM output routine)
;
; Initial version: Jinshi Huang 3/17/97
;
; Calling : none
; Called by: top level
; Return: r27, LBPCM_flag
; Param in:
; Temp reg:
; AGR reg:
; Local buffer:
;************************************************************************
.nolist
#include "regdef2.h"
#ifndef EFFECT
#include "ac3_com.h"
#endif //EFFECT
#include "user2.h"
#include "memory2.h"
#ifdef EFFECT
#include "stereo_user.h"
#include "memory.h"
#endif //EFFECT
#ifdef MSW_ADD_QSOUND
#include "qx.h"
#endif // MSW_ADD_QSOUND
.data
.list
.extern PCM_Config_Word
#ifdef MSW_ADD_QSOUND
.extern SUB_QSurround
.extern QSOUND_CMD_BUF
#endif // MSW_ADD_QSOUND
.globl SUB_pcm_pcm
SUB_pcm_pcm:
#ifndef EFFECT
movb r1, LBFIFO_flag
movb r4, LBblknum
#ifdef EXECTIVE
subi r4,1 // block count already increment
#endif
tsti r1, 0
beq no_checking_FIFO
#endif //EFFECT
dlw r10, FIFO_BLK_PTR
movi r8, PCM_FIFO_0_START ; beginning of FIFO_0
movi r9, PCM_FIFO_0_END ; to the end of FIFO being read
tsti r10, PCM_FIFO_0_START
beq toggle_ref_ptr
movi r8, PCM_FIFO_1_START ; beginning of FIFO_1
movi r9, PCM_FIFO_1_END ; end of FIFO_1
toggle_ref_ptr:
;; read location of read fifo
pcmout_wait:
#ifdef FILE_OUT
dlw r1,PCM_Rd_Ptr ; read current pointer assigned by host
nop
#else
1:
rlwi r1, PCM_Rd_Ptr ; read current pointer register (28c)
rlwi r3, PCM_Rd_Ptr ; read current pointer register (28c)
tst r1,r3
bne 1b
#endif
#ifdef STREAM_SIM
shr r1, 16 ; make it just the current address portion
#else
andi r1,0xffff
#endif
tst r1, r8
blt write_to_FIFO
tst r1, r9 ;
// blte pcm_not_out ; if begin <= ptr <= end, wait
// j write_to_FIFO
bgt write_to_FIFO
delay_loop_start:
loop 64,delay_loop
nop
nop
nop
nop
delay_loop:
rlwi r1, PCM_Rd_Ptr ; read current pointer register (28c)
rlwi r3, PCM_Rd_Ptr ; read current pointer register (28c)
tst r1,r3
bne delay_loop
sub r3,r9,r1
tsti r3,24 // 3 dWords/sample
bgt delay_loop_start
j pcm_not_out
/**********************************************************************/
// this code should be moved to the kernel later !!!!!
// write to the FIFO
;====write 256 words to main memory. pcmptr2 += offset
;this is modified to write 16-bit format of 6 channels to
;0 - 0x3000 of the DRAM which is the PCM output FIFO.
no_checking_FIFO:
tsti r4, 0
bne second_FIFO_block
;;; set the size of the PCM output FIFO for 2 blocks
movi r1, PCM_FIFO_SIZE ; size of PCM output FIFO
#ifdef STREAM_SIM
; 28c is PCM FIFO end address in real chip
; and should contain full address,seg+offset
; will be set by host for the time being.
rswi r1, 0x28c ; write to register
#endif
movi r10, PCM_FIFO_0_START
j write_to_FIFO
second_FIFO_block:
movi r1, 1
movb LBFIFO_flag,r1
movi r10, PCM_FIFO_1_START
write_to_FIFO:
#ifndef EFFECT
tsti r4,0
bne Lskip_PTS
movh r28,LIfrmsize
shl r28,1
movw r1,LWbytecount
add r1,r28
movw LWbytecount,r1
jsr r28,SUB_check_PTS
Lskip_PTS:
#endif
#ifdef EFFECT
// copy data to local buffer
movi StartAddrHigh,DataSeg //to second segment
movi DMASize,31
movi r12,local_FApcm_buf_word
movi r11,keyshift_context
shr r11,2
loop 8, get_keyshift_output ;total of 8*32 words
mov LocalAddr, r12
dmarr r11
Lwait3: bdb Lwait3
addi r12, 32 ;32 words each block
addi r11, 32
get_keyshift_output:
movi StartAddrHigh,MEM_SEG //back to first segment
#endif //EFFECT
//tchou
#if 0 //testing
//ZhangWei:MIC balance between normal playing and not playing
dlw r0,USER_ICFG
nop
andi r0,ICFG_MIC_EXIST_MASK ;bit15 stands for ufone hardware
tsti r0,ICFG_MIC_EXIST_MASK
bz skip_ufon_only ;skip if non-existence
movh r0,LIstatus
andi r0,RUN_STOP_MASK // check if process stopped
tsti r0,STATUS_STOP
beq Lend_of_gain_loop //only for ufone
skip_ufon_only:
#endif
// get the gain value by combining stream gain with user gain
movw r4, LWpcmscale //gain from user
movw r0,LWFrameCount
tsti r0,40 // 18
bgte Lgain_setting_done
movi r4,0 // set gain to 0
Lgain_setting_done:
movi DMASize, 31 ;32 words each block
#ifdef EFFECT
movi BlockSkip, 5 ;2
#else //EFFECT
movi BlockSkip, 0
#endif //EFFECT
movi BlockSize, 0 ;block size = 1.
// apply the gain to the samples
movi r0, 0xffff //lower 16-bit mask
mupi r1, 0xffff //upper 16-bit mask
movi AGRAdr0, local_FApcm_buf_byte
dlw r3,KARAOKE_0
movi TrapReg,0
andi r3,0x3
tsti r3,3 // check KARAOKE_0
beq Lswap_lr // R=melody, L=vocal
tsti r3,2
beq Ll_to_lr // R=vocal, L=vocal
tsti r3,1
beq Lr_to_lr // R=melody, L=melody
// default: R=vocal, L=melody
#ifdef EFFECT
loop 8, Lpcm_gain_outer_lr2lr
#else // EFFECT
loop 24, Lpcm_gain_outer_lr2lr
#endif // EFFECT
loop 32, Lpcm_gain_inner_lr2lr
mulhf r6,r4,a0(2) // r6=r4*L
mulhf r8,r4,a0(-2) // r8=r4*R
shl r6,1
shl r8,1
rndhf a0(2),r6
rndhf a0(2),r8
Lpcm_gain_inner_lr2lr:
Lpcm_gain_outer_lr2lr:
j Lend_of_gain_loop
Lswap_lr:
#ifdef EFFECT
loop 8, Lpcm_gain_outer_slr
#else // EFFECT
loop 24, Lpcm_gain_outer_slr
#endif // EFFECT
loop 32, Lpcm_gain_inner_slr
mulhf r6,r4,a0(2) // r6=r4*L
mulhf r8,r4,a0(0) // r8=r4*R
shl r6,1
shl r8,1
rndhf a0(-2),r6
rndhf a0(4),r8
Lpcm_gain_inner_slr:
Lpcm_gain_outer_slr:
j Lend_of_gain_loop
Ll_to_lr:
#ifdef EFFECT
loop 8, Lpcm_gain_outer_l2lr
#else // EFFECT
loop 24, Lpcm_gain_outer_l2lr
#endif // EFFECT
loop 32, Lpcm_gain_inner_l2lr
mulhf r6,r4,a0(2) // r6=r4*L
mulhf r8,r4,a0(-2) // r8=r4*R
shl r6,1
shl r8,1
rndhf a0(2),r6
rndhf a0(2),r6
Lpcm_gain_inner_l2lr:
Lpcm_gain_outer_l2lr:
j Lend_of_gain_loop
Lr_to_lr:
#ifdef EFFECT
loop 8, Lpcm_gain_outer_r2lr
#else // EFFECT
loop 24, Lpcm_gain_outer_r2lr
#endif // EFFECT
loop 32, Lpcm_gain_inner_r2lr
mulhf r6,r4,a0(2) // r6=r4*L
mulhf r8,r4,a0(-2) // r8=r4*R
shl r6,1
shl r8,1
rndhf a0(2),r8
rndhf a0(2),r8
Lpcm_gain_inner_r2lr:
Lpcm_gain_outer_r2lr:
Lend_of_gain_loop:
#ifdef MSW_ADD_QSOUND
;; EFFECT must be defined so that we get 256 words of LR Stereo data.
;; Each word contains a stereo pair (the order is R|L).
;; The first thing to do is go to the end of the buffer and repack the
;; data so that it is in the same format as we would get the ac3 6 channels.
;; We start at the ends so that we does not trash any samples.
;; I could just add it into the previous volume loop stuff. But keep
;; it completely seperate now for simplicity reasons
// dlh r0,COMMAND1
dlh r0,QSOUND_CMD_BUF
nop
tsti r0,CMD1_QSOUND_A
beq foundPCMQSound
tsti r0,CMD1_QSOUND
bne noPCMQSound
foundPCMQSound:
movi AGRSiz0, 0xffff
movi AGRSiz1, 0xffff
#ifdef MSW_SAVE_LOCAL
;; saved local memory I use in dram 32 words each of buffer, data
;; and coeff - I do not actually use all 32 words of each component
;; but it makes it a lot easier to save (can ignore whether three
;; stage and/or highpass...).
movi r0, olddmaStuff
shr r0, 2 ; convert to word address
movi SizeSkip, (31 << 11 | 31 << 6 | 0)
movi r1, (local_buf>>2); convert to word
mov LocalAddr, r1
dmawr r0
qswaita:bdb qswaita
addi r0,32
movi r1, (local_coeffs>>2); convert to word
mov LocalAddr, r1
dmawr r0
qswaitb:bdb qswaitb
addi r0,32
movi r1, (local_data>>2); convert to word
mov LocalAddr, r1
dmawr r0
qswaitc:bdb qswaitc
#endif // MSW_SAVE_LOCAL
;; stash r10 as we are going to destroy it.
dsw r10,dramlocalr10
;; call qxpander
jsr r27, SUB_QXpander
;; restore r10
dlw r10,dramlocalr10
#ifdef MSW_SAVE_LOCAL
;; restore the locations that I used...
movi r0, olddmaStuff
shr r0, 2 ; convert to word address
movi SizeSkip, (31 << 11 | 31 << 6 | 0)
movi r1, (local_buf>>2); convert to word
mov LocalAddr,r1
dmarr r0
qswaitd:bdb qswaitd
addi r0,32
movi r1, (local_coeffs>>2); convert to word
mov LocalAddr, r1
dmarr r0
qswaite:bdb qswaite
addi r0,32
movi r1, (local_data>>2); convert to word
mov LocalAddr, r1
dmawr r0
qswaitf:bdb qswaitf
#endif // MSW_SAVE_LOCAL
;; restore default dma stuff prior to my call
movi DMASize, 31 ;32 words each block
#ifdef EFFECT
; movi BlockSkip, 5 ;2
#else //EFFECT
; movi BlockSkip, 0
#endif //EFFECT
; movi BlockSize, 0 ;block size = 1.
noPCMQSound:
#endif // MSW_ADD_QSOUND
#if !LS388
movi TrapReg,1<<2
#endif // !LS388
movi r3, local_FApcm_buf_word ; word addr
movi AGRAdr1, local_FApcm_buf_byte
shr r9, r10, 2 ; to word addr
#if !LS388
dlw r2,SPDIF_SET_FLAG
#endif // !LS388
#ifdef EFFECT
movi StartAddrHigh,DataSeg
#endif //EFFECT
#if !LS388
movi TrapReg,0
nop
nop
tsti r2,1
bne skip_data_manipulation
#endif // !LS388
#if 0 // -------------------------------------------
movi BlockSkip, 4
movi BlockSize, 1 ;block size = 2
movi AGRAdr0,SP_draft_before_dram_byte - 4
movi AGRAdr1, local_FApcm_buf_byte + 1020 ; 255 * 4 =1020
; movi AGRSiz0,0xffff
movi AGRSiz1,0xffff
loop 256,spdif_raw_data
shr r1,a1(0),8
mov a0(-4),r1
movhf r2,a1(-4)
mov a0(-4),r2
spdif_raw_data:
addi r9,4
loop 16, write_spdif_pcm_buf ;total of 256*2 words
mov LocalAddr, r3
dmawr r9 ;r10=FPApcmbufptr[outchan]=pcmptr2(init)
wait_dma_spdif_21:
mov r2,StatusPort
tsti r2,DmaDoneBit
bz wait_dma_spdif_21 ;wait for dma done
addi r3, 32 ;32 words each block
addi r9, 16 * 6 ;32*3
write_spdif_pcm_buf:
j merge_pcm_spdif
skip_data_manipulation:
#ifdef EFFECT
loop 8, write_pcm_buf ;total of 256 words
#else //EFFECT
loop 24, write_pcm_buf ;total of 256*3 words
#endif //EFFECT
mov LocalAddr, r3
dmawr r9 ;r10=FPApcmbufptr[outchan]=pcmptr2(init)
wait_dma_21:
mov r2,StatusPort
tsti r2,DmaDoneBit
bz wait_dma_21 ;wait for dma done
addi r3, 32 ;32 words each block
#ifdef EFFECT
addi r9, 32*6 ;32*3
#else //EFFECT
addi r9, 32
#endif //EFFECT
write_pcm_buf:
movi r3, local_FApcm_buf_word ; word addr
shr r9, r10, 2 ; to word addr
addi r9,1
loop 256,pcm_local_data_shift
shr r2,a1(0),16
mov a1(1*4),r2
pcm_local_data_shift:
#ifdef EFFECT
loop 8, write_pcm_hi_buf ;total of 256 words
#else //EFFECT
loop 24, write_pcm_hi_buf ;total of 256*3 words
#endif //EFFECT
mov LocalAddr, r3
dmawr r9 ;r10=FPApcmbufptr[outchan]=pcmptr2(init)
wait_dma_hi_21:
mov r2,StatusPort
tsti r2,DmaDoneBit
bz wait_dma_hi_21 ;wait for dma done
addi r3, 32 ;32 words each block
#ifdef EFFECT
addi r9, 32*6 ;32*3
#else //EFFECT
addi r9, 32
#endif //EFFECT
write_pcm_hi_buf:
#else // -------------------------------------------
movi BlockSkip, 4
movi BlockSize, 1 ;block size = 2
movi AGRAdr0,SP_draft_before_dram_byte - 4
movi AGRAdr1, local_FApcm_buf_byte + 1020 ; 255 * 4 =1020
movi AGRSiz1,0xffff
//*****************************************
// Modified especially for Esona I2S D/A
//*****************************************
rlwi r1,PCM_Out_Ctrl
andi r1,0x0030
tsti r1,0
bne do_mpg_center_justified ; for non i2s
loop 256,spdif_16bits_pcm_data
#if 0
shr r1,a1(0),16
mov a0(-4),r1
mov r2,a1(-4)
mov a0(-4),r2
#else
mov r1,a1(0)
mov a0(-4),r1
shr r2,a1(-4),16
mov a0(-4),r2
#endif
spdif_16bits_pcm_data:
j spdif_raw_data
do_mpg_center_justified:
/////////////////////////////////////////////////
loop 256,spdif_raw_data
#if 0
shr r1,a1(0),16
shl r2,a1(0),16
nop
nop
or a1(0),r2,r1
nop
nop
shr r1,a1(0),8
mov a0(-4),r1
movhf r2,a1(-4)
mov a0(-4),r2
#else
shl r1,a1(0),8
mov a0(-4),r1
// shr r2,a1(0),8
shr r2,a1(-4),8
mov a0(-4),r2
#endif
spdif_raw_data:
addi r9,4
loop 16, write_spdif_pcm_buf ;total of 256*2 words
mov LocalAddr, r3
dmawr r9 ;r10=FPApcmbufptr[outchan]=pcmptr2(init)
WaitDma
addi r3, 32 ;32 words each block
addi r9, 16 * 6 ;32*3
write_spdif_pcm_buf:
subi r9,(16*16*6+4)
subi r3,(32*16)
movi BlockSkip, 4
movi BlockSize, 1 ;block size = 2
movi AGRAdr1,SP_draft_before_dram_byte - 4
//*****************************************
// Modified especially for Esona I2S D/A
//*****************************************
rlwi r1,PCM_Out_Ctrl
andi r1,0x0030
tsti r1,0
beq i2s_analog ; for non i2s
from_mpg_center_justified:
/////////////////////////////////////tanchou/////
loop 256,spdif_to_pcm
#if 0
shr r1,a1(0),8
mov a1(-4),r1
shr r1,a1(0),8
mov a1(-4),r1
#else
shr r1,a1(-4),8
shr r2,a1(4),8
mov a1(-4),r2
mov a1(-4),r1
#endif
spdif_to_pcm:
j do_analog_pcm
i2s_analog:
loop 256,swap_analog_pcm_data
mov r1,a1(-4)
mov r2,a1(4)
mov a1(-4),r2
mov a1(-4),r1
swap_analog_pcm_data:
do_analog_pcm:
loop 16, write_pcm_buf ;total of 256*2 words
mov LocalAddr, r3
dmawr r9 ;r10=FPApcmbufptr[outchan]=pcmptr2(init)
WaitDma
addi r3, 32 ;32 words each block
addi r9, 16 * 6 ;32*3
write_pcm_buf:
#endif // -------------------------------------------
#if ENABLE_PSM
nop
jsr r25,disp_spectrum
nop
#endif /* ENABLE_PSM */
merge_pcm_spdif:
movi TrapReg,1<<2
#ifdef EFFECT
movi StartAddrHigh,MEM_SEG
#endif //EFFECT
movi BlockSkip, 0
movi BlockSize, 0
;; Make sure PCMOUT is enabled. This is only necessary for the
;; first time.
// dlw r1, PCM_Config_Word
// nop ;pipeline
// rswi r1, PCM_Out_Ctrl ; write to register
dlw r0,MUTE_FLAG
#ifdef LS388
movi r1,0x31
#else //LS388
movi r1, 0x1 ; enable PCM output
#endif //LS388
tsti r0,1
beq Lalready_on
#ifndef R3K_PCM_OUT_CTRL
rswi r1, PCM_Run_Halt ; write to register
#endif // R3K_PCM_OUT_CTRL
dsw r1,MUTE_FLAG
Lalready_on:
movi r9, PCM_FIFO_1_START
tsti r10, PCM_FIFO_0_START
beq toggle_FIFO_ptr
movi r9, PCM_FIFO_0_START
toggle_FIFO_ptr:
dsw r9, FIFO_BLK_PTR ;toggle block ptr
movi r1, 1
movb LBPCM_flag, r1 ;set the flag
#ifndef EFFECT
rlwi r0,STC
movw LWStartPTS,r0
#endif
#ifdef LS240_PM
j Lnot_sleep
pcm_not_out:
#ifndef R3K_PCM_OUT_CTRL
rlwi r0,HOST_CTRL
mupi r1,0xffff
ori r1,0xffef ; DSP colck turned off
+ and r0,r1
rswi r1,HOST_CTRL
#endif // R3K_PCM_OUT_CTRL
Lnot_sleep:
#else
pcm_not_out:
#endif
#ifdef EFFECT
j r31
#else //EFFECT
j r27
#endif //EFFECT
#ifdef MSW_ADD_QSOUND
#ifdef MSW_SAVE_LOCAL
.data
.align 2
olddmaStuff:
.fill 96,4,0 ; to hold what ever exists in my local memory spaces
#endif // MSW_SAVE_LOCAL
dramlocalr10:
.data
.align 2
.word 0
#endif // MSW_ADD_QSOUND
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -