⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 dtmfasm.s55

📁 Express DSP compliant C55x DTMF detector software is proposed in two versions: one with a 5 ms frame
💻 S55
📖 第 1 页 / 共 2 页
字号:
    ac1 = ac0;
    ac1 = ac1 & #0xffff;
    ac1 = ac1 << #16;       unsigned

    ac2 = ac1 * *ar3;
    ac2 = ac2 << #-16
    ac2 = ac2 + (ac0 * *ar3);

	ac2 = ac2 + t3;						; t3 still keeps max energy
	*ar1(#(DTMF_tSc.sLoMaxFreqEn)) = ac2;
;
; -- hi band dft
;
;	ar2 =  psOut
;   ar3 = psI data
;   ar4 = psQ data
;   t1 = sSz*2-1
;   cdp = filterbank
;   t0 = 2
;   ac2 = energy, both lin and log
;
	xcdp = #_dtmf_aHi;
	xar2 = mar(*ar1(#(DTMF_tSc.asHiMainEn)));
	xar3 = mar(*ar1(#(DTMF_tSc.asHiData)));
	xar4 = mar(*ar1(#(DTMF_tSc.asHiData+1)));
    mar	(t1 = #(DTMF_HI_DFT_SZ*2-2))
    brc0 = #(4-1)

	mar	(t0 = #2);						; extra ...
    || localrepeat {
        ac0 = *(ar3+t0) * coef( *cdp+), 
		ac1 = *(ar4+t0) * coef(*cdp+);
        || repeat(#(DTMF_HI_DFT_SZ-3))
            ac0=ac0+(*(ar3+t0)*coef(*cdp+)), 
			ac1=ac1+(*(ar4+t0)*coef(*cdp+));
        ac0 = ac0+(*(ar3-t1)*coef(*cdp+)), 
		ac1 = ac1+(*(ar4-t1)*coef(*cdp+));
        || repeat(#(DTMF_HI_DFT_SZ-2))
            ac0 = ac0-(*(ar4+t0)*coef(*cdp+)), 
			ac1 = ac1+(*(ar3+t0)*coef(*cdp+));
        ac0 = ac0-(*(ar4-t1)*coef(*cdp+)), 
		ac1 = ac1+(*(ar3-t1)*coef(*cdp+));

        ac2=ac0*ac0;
        ac2=ac2+(ac1*ac1);
        macro_en2log    ac2, t2;		; [5]
        *ar2+ = ac2;
    }									; [(DFT_SZ*2+8)*4]
;
; -- sort hi frequencies ---
;
	mar	 (ar2 - #4)
    || t2   = #0
    ac3  = #0;
    || brc0 = #(4-2);    

    ac0  = *ar2+
    || localrepeat {
        ac1 = *ar2+ || ac3 = ac3 + #1;
        ac0 = max (ac1, ac0)                ; carry = 0 if ac1>ac0
        if (!CARRY) execute(D_unit)         ; 
            || t2 = ac3
    }
;
; t3 = ac0 = max of all freqs
; t2 =  max idx
    *ar1(#(DTMF_tSc.sHiFreqNo)) = t2;
    t3  = ac0;
;
    || mar  (ar2 - #4); 
    ac0	 = #-32767;

    brc0 = #(4-1);  
    
    .if 0 ; REPEAT CORRECTION OF 2002/11/20 for hi band
        
    localrepeat {
        ac1 = *ar2+ - t3;
        || bit(st0, #ST0_CARRY) = #1;
        if(ac1 != #0) execute(D_unit)
           || ac0 = max(ac1, ac0);            ; carry = 0 if ac1>ac0
        if(!CARRY) execute(D_unit)
            || ac2 = ac0;
    }
    ac2 = ac2 + t3;
    
    .else
    
    localrepeat {
        ac1 = *ar2+;
        || bit(st0, #ST0_CARRY) = #1;
        if(t2 != #0) execute(D_unit)
           || ac0 = max(ac1, ac0);            ; carry = 0 if ac1>ac0
        if(!CARRY) execute(D_unit)
            || ac2 = ac0;
        t2 = t2 - #1;
    }
    t2 = t2 + #4;
    
    .endif
    
    *ar1(#(DTMF_tSc.sHiNextEn)) = ac2;
;
; -- hi band dft for deviations
;
;   cdp = filterbank
;   t0 = 2
;   ac2 = energy, both lin and log
;
	xar2 = #__apsHiDev;
	mar	(ar2+t2);
	mar	(ar2+t2);						; long (2 w) storage for 
										; large data mem model
	xcdp = dbl(*ar2);
    brc0 = #(4-1)
	xar2 = mar(*ar1(#(DTMF_tSc.asHiDevEn)));

    localrepeat {
        ac0 = *(ar3+t0) * coef( *cdp+), 
		ac1 = *(ar4+t0) * coef(*cdp+);
        || repeat(#(DTMF_HI_DFT_SZ-3))
            ac0=ac0+(*(ar3+t0)*coef(*cdp+)), 
			ac1=ac1+(*(ar4+t0)*coef(*cdp+));
        ac0 = ac0+(*(ar3-t1)*coef(*cdp+)), 
		ac1 = ac1+(*(ar4-t1)*coef(*cdp+));
        || repeat(#(DTMF_HI_DFT_SZ-2))
            ac0 = ac0-(*(ar4+t0)*coef(*cdp+)), 
			ac1 = ac1+(*(ar3+t0)*coef(*cdp+));
        ac0 = ac0-(*(ar4-t1)*coef(*cdp+)), 
		ac1 = ac1+(*(ar3-t1)*coef(*cdp+));

        ac2=ac0*ac0;
        ac2=ac2+(ac1*ac1);
        macro_en2log    ac2, t2;		; [5]
        *ar2+ = ac2;
    }									; [(DFT_SZ*2+8)*4]
;
; --- get hi band frequency deviation
;
; ar2 = psDev
; ar3 = psDevFlt
;
	t2 = *ar1(#(DTMF_tSc.sHiFreqNo))
	mar (ar2 - #4);						; return ptr back
	xar3 = #__aasHiDevFlt;
	mar (ar3+t2);
	mar (ar3+t2);

    ac0 = *ar2(#3)
    ac0 = ac0 - *ar2; /* offset 0 */
    ac0 = ac0 + *ar2(#2)
    ac0 = ac0 - *ar2(#1)
    ac0 = ac0 << #16;
    ac0 = *ar3+ * ac0;
    
	ac1 = #(170*5) << #16;
	ac0 = min(ac1, ac0);
	ac1 = #(-170*5) << #16;
	ac0 = max(ac1, ac0);
	
    *ar1(#(DTMF_tSc.sHiFreqDev)) = HI(ac0);

    ac0 = ac0*ac0;

    ac1 = ac0;
    ac1 = ac1 & #0xffff;
    ac1 = ac1 << #16;       unsigned

    ac2 = ac1 * *ar3;
    ac2 = ac2 << #-16
    ac2 = ac2 + (ac0 * *ar3);

	ac2 = ac2 + t3;
	*ar1(#(DTMF_tSc.sHiMaxFreqEn)) = ac2;

;
; --- get new frame energy
;
	.if (IDTMF_FR_SZ == 40)
	
	xar2 = mar(*ar1(#(DTMF_tSc.as2kData)))
	ac0 = *ar2 * *ar2+;
	|| repeat (#(IDTMF_FR_SZ-2))
		ac0 = ac0 + (*ar2 * *ar2+);
	dbl(*ar1(#(DTMF_tSc.slFrameEn))) = ac0; 
	.else 
	
	xar2 = mar(*ar1(#(DTMF_tSc.as2kData)))
	ac0 = *ar2 * *ar2+;
	|| repeat (#(IDTMF_FR_SZ/2-2))
		ac0 = ac0 + (*ar2 * *ar2+);
	ac1 = *ar2 * *ar2+;
	|| repeat (#(IDTMF_FR_SZ/2-2))
		ac1 = ac1 + (*ar2 * *ar2+);
	ac0 = ac0 << #-3;
	ac1 = ac1 << #-3;
	ac0 = ac0 + ac1; 
	macro_en2log	ac0, t0
	*ar1(#(DTMF_tSc.sFrameEn)) = ac0;
	.endif
;	
;*-------------------------------------------------------------------------*/
;
; ar4 = DTMF_tCfg *pCfg
; ar0 = DTMF_tDb *ar0, 
; ar1 = DTMF_tSc *ar1
;
	xar4 = dbl(*ar0(#(DTMF_tDb.pCfg)));
	ac3 = #0;
;
; min energy thr
	ac0 = *ar1(#(DTMF_tSc.sSumEn));
	ac0 = ac0 - *ar4(#(DTMF_tCfg.sMinEnThr));
	if (ac0 < #0) execute (D_unit)
		|| ac3 = ac3 | #DTMF_MASK_MIN_EN;
;
; sum energy
	.if (IDTMF_FR_SZ == 40)
	ac0 = *ar0(#(DTMF_tDb.v.sZFrameEn));
	.else 
	ac0 = *ar1(#(DTMF_tSc.sFrameEn));
	.endif
	
	ac0 = ac0 - *ar1(#(DTMF_tSc.sSumDialEn));
	ac0 = ac0 - *ar4(#(DTMF_tCfg.sSumEnThr));
	if (ac0 > #0) execute (D_unit)
		|| ac3 = ac3 | #DTMF_MASK_SUM_EN;
;
; rising edge 
	.if (IDTMF_FR_SZ == 40)
	ac0 = *ar0(#(DTMF_tDb.v.asSumEn));
	ac1 = *ar0(#(DTMF_tDb.v.asSumEn+1));
	ac0 = min(ac1, ac0);
	ac1 = *ar0(#(DTMF_tDb.v.asSumEn+4));
	ac2 = *ar0(#(DTMF_tDb.v.asSumEn+5));
	ac1 = max(ac2, ac1);
	ac0 = ac0 - ac1;     
	.else
	ac0 = *ar0(#(DTMF_tDb.v.asSumEn));
	ac0 = ac0 - *ar0(#(DTMF_tDb.v.asSumEn+2));
	.endif
	
	ac0 = ac0 - *ar4(#(DTMF_tCfg.sNoiseThr));
	if (ac0 < #0) execute (D_unit)
		|| ac3 = ac3 | #DTMF_MASK_RS_EDGE;
;
; falling edge
	ac0 = *ar0(#(DTMF_tDb.v.Stat.sEn));
	ac0 = ac0 - *ar1(#(DTMF_tSc.sSumEn))
	ac0 = ac0 - *ar4(#(DTMF_tCfg.sNoiseThr))
	if (ac0 < #0) execute (D_unit)
		|| ac3 = ac3 | #DTMF_MASK_FL_EDGE;
;
; levels' stability
	ac0 = *ar1(#(DTMF_tSc.sLoMaxFreqEn));
	ac0 = ac0 - *ar0(#(DTMF_tDb.v.Stat.sLoEn))
	ac0 = |ac0|;
	ac0 = ac0 - *ar4(#(DTMF_tCfg.sVarThr))
	if (ac0 > #0) execute (D_unit)
		|| ac3 = ac3 | #DTMF_MASK_STABLE;
;		
	ac0 = *ar1(#(DTMF_tSc.sHiMaxFreqEn));
	ac0 = ac0 - *ar0(#(DTMF_tDb.v.Stat.sHiEn))
	ac0 = |ac0|;
	ac0 = ac0 - *ar4(#(DTMF_tCfg.sVarThr))
	if (ac0 > #0) execute (D_unit)
		|| ac3 = ac3 | #DTMF_MASK_STABLE;
;
; 2K bound
	ac0 = *ar1(#(DTMF_tSc.s2kEnDlt));
	ac0 = ac0 - *ar4(#(DTMF_tCfg.s2kUpThr))
	if (ac0 < #0) execute (D_unit)
		|| ac3 = ac3 | #DTMF_MASK_2K_BOUND
;    
; test that twists are ok
	ac0 = *ar1(#(DTMF_tSc.sHiBpEn));
	ac0 = ac0 - *ar1(#(DTMF_tSc.sLoBpEn));
	ac1 = ac0 - *ar4(#(DTMF_tCfg.sFwdTwistThr))
	ac1 = ac1 - #DTMF_FWD_TWIST_CORR;
	if (ac1 > #0) execute (D_unit)
		|| ac3 = ac3 | #DTMF_MASK_FWD_TWIST;
	ac1 = ac0 + *ar4(#(DTMF_tCfg.sRevTwistThr));
	ac1 = ac1 - #DTMF_REV_TWIST_CORR;
	if (ac1 < #0) execute (D_unit)
		|| ac3 = ac3 | #DTMF_MASK_REV_TWIST;
;
	ac0 = *ar0(#(DTMF_tDb.v.sState));
	ac0 = ac0 - #DTMF_ST_TONE;
	if (ac0 >= #0 ) goto L1;
;
;            DFT delay lines are not full. at least one frame less.
;            we shall account for wider sinc mainlobe and lower energy.
;            Noise does not have much influence on the parameters
;            in this case, so the threshold are hard coded.
;            tuning criteria was chosen the number of early-on hits 
;            on talk-off imunity test.
;            varying those thrs shall affect early detection delay
;            and talk-off immunity as well.
;
		ac0 = *ar1(#(DTMF_tSc.sLoBpEn));
		ac0 = ac0 - *ar1(#(DTMF_tSc.sLoMaxFreqEn));
		ac0 = ac0 - #(6*DTMF_1DB); 
		if (ac0 > #0) execute (D_unit)
			|| ac3 = ac3 | #DTMF_MASK_LO_PART;
;
		ac0 = *ar1(#(DTMF_tSc.sLoMaxFreqEn));
		ac0 = ac0 - *ar1(#(DTMF_tSc.sLoNextEn));
		ac0 = ac0 - #(5*DTMF_1DB); 
		if (ac0 < #0) execute (D_unit)
			|| ac3 = ac3 | #DTMF_MASK_LO_CLEAN;
;
		.if (IDTMF_FR_SZ == 40)
		ac0 = *ar1(#(DTMF_tSc.sHiBpEn));
		ac0 = ac0 - *ar1(#(DTMF_tSc.sHiMaxFreqEn));
		ac0 = ac0 - #(4*DTMF_1DB); 
		if (ac0 > #0) execute (D_unit)
			|| ac3 = ac3 | #DTMF_MASK_HI_PART;
;
		ac0 = *ar1(#(DTMF_tSc.sHiMaxFreqEn));
		ac0 = ac0 - *ar1(#(DTMF_tSc.sHiNextEn));
		ac0 = ac0 - #(7*DTMF_1DB); 
		if (ac0 < #0) execute (D_unit)
			|| ac3 = ac3 | #DTMF_MASK_HI_CLEAN;
;
		.endif
	goto	L2
L1
;
		ac0 = *ar1(#(DTMF_tSc.sLoBpEn));
		ac0 = ac0 - *ar1(#(DTMF_tSc.sLoMaxFreqEn));
		ac0 = ac0 - *ar4(#(DTMF_tCfg.sPartThr))
		if (ac0 > #0) execute (D_unit)
			|| ac3 = ac3 | #DTMF_MASK_LO_PART;
;
		ac0 = *ar1(#(DTMF_tSc.sLoMaxFreqEn));
		ac0 = ac0 - *ar1(#(DTMF_tSc.sLoNextEn));
		ac0 = ac0 - *ar4(#(DTMF_tCfg.sCleanThr)); 
		if (ac0 < #0) execute (D_unit)
			|| ac3 = ac3 | #DTMF_MASK_LO_CLEAN;
;
		.if (IDTMF_FR_SZ == 40)
		ac0 = *ar1(#(DTMF_tSc.sHiBpEn));
		ac0 = ac0 - *ar1(#(DTMF_tSc.sHiMaxFreqEn));
		ac0 = ac0 - *ar4(#(DTMF_tCfg.sPartThr)); 
		if (ac0 > #0) execute (D_unit)
			|| ac3 = ac3 | #DTMF_MASK_HI_PART;
;
		ac0 = *ar1(#(DTMF_tSc.sHiMaxFreqEn));
		ac0 = ac0 - *ar1(#(DTMF_tSc.sHiNextEn));
		ac0 = ac0 - *ar4(#(DTMF_tCfg.sCleanThr)); 
		if (ac0 < #0) execute (D_unit)
			|| ac3 = ac3 | #DTMF_MASK_HI_CLEAN;
		.endif
;
L2
;
	.if (IDTMF_FR_SZ == 80)
	
	ac0 = *ar1(#(DTMF_tSc.sHiBpEn));
	ac0 = ac0 - *ar1(#(DTMF_tSc.sHiMaxFreqEn));
	ac0 = ac0 - *ar4(#(DTMF_tCfg.sPartThr)); 
	if (ac0 > #0) execute (D_unit)
		|| ac3 = ac3 | #DTMF_MASK_HI_PART;
;
	ac0 = *ar1(#(DTMF_tSc.sHiMaxFreqEn));
	ac0 = ac0 - *ar1(#(DTMF_tSc.sHiNextEn));
	ac0 = ac0 - *ar4(#(DTMF_tCfg.sCleanThr)); 
	if (ac0 < #0) execute (D_unit)
		|| ac3 = ac3 | #DTMF_MASK_HI_CLEAN;
		
	.endif
;	
	ac0 = *ar1(#(DTMF_tSc.sLoFreqDev));
	ac0 = |ac0|;
	ac0 = ac0 - *ar4(#(DTMF_tCfg.sMaxFreqDevThr)); 
	if (ac0 > #0) execute (D_unit)
		|| ac3 = ac3 | #DTMF_MASK_LO_INRANGE;
;
	ac0 = *ar1(#(DTMF_tSc.sHiFreqDev));
	ac0 = |ac0|;
	ac0 = ac0 - *ar4(#(DTMF_tCfg.sMaxFreqDevThr)); 
	if (ac0 > #0) execute (D_unit)
		|| ac3 = ac3 | #DTMF_MASK_HI_INRANGE;
;
	ac0 = *ar1(#(DTMF_tSc.sLoFreqNo));
	ac0 = ac0 + (*ar1(#(DTMF_tSc.sHiFreqNo)) << #2);
	*ar1(#(DTMF_tSc.sDigit)) = ac0;
;
	ac0 = ac0 - *ar0(#(DTMF_tDb.v.sLastDigit));
	if (ac0 != #0) execute (D_unit)
		|| ac3 = ac3 | #DTMF_MASK_SAME_FRQ;

	*ar1(#(DTMF_tSc.sTestFailed)) = ac3;
;
; --- move scratch to db ---
;                           
	.if (IDTMF_FR_SZ == 40)
	
	ac1 = dbl(*ar1(#(DTMF_tSc.slFrameEn)))
	ac0 = ac1 + dbl(*ar0(#(DTMF_tDb.v.slFrameEn)));
	ac0 = ac0 << #-3;
	macro_en2log	ac0, t0
	*ar0(#(DTMF_tDb.v.sZFrameEn)) = ac0;
	dbl(*ar0(#(DTMF_tDb.v.slFrameEn))) = ac1;
	.else
	.endif
	
	xar2 = mar(*ar0(#(DTMF_tDb.as2kDataSav)))
	xar3 = mar(*ar1(#(DTMF_tSc.as2kData+IDTMF_FR_SZ)))
	repeat(#(DTMF_2KFLT_SZ-1))
		*ar2+ = *ar3+;
;
	xar3 = mar(*ar1(#(DTMF_tSc.asBpData+DTMF_BPFR_SZ)))
	repeat (#(DTMF_BPFLT_SZ-1))
		*ar2+ = *ar3+;
;
	xar3 = mar(*ar1(#(DTMF_tSc.asLoData+DTMF_DFR_SZ*2)))
	repeat (#(DTMF_LOSD_SZ-1))
		*ar2+ = *ar3+;
;
	.if (IDTMF_FR_SZ != 80)
	xar3 = mar(*ar1(#(DTMF_tSc.asHiData+DTMF_DFR_SZ*2)))
	repeat (#(DTMF_HISD_SZ-1))
		*ar2+ = *ar3+;   
	.endif
;
; --- restore context ---
;
	bit(ST2, #ST2_ARMS) = #1;
    .arms_on
	t3 = pop()
	t2 = pop()

	return
;-------------------------------------------------------------------------

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -