📄 dtmfsub.asm
字号:
sth B,*AR4+ ; store result E[k] into energy data block
goer4 ;}
;------------------------------------------------------------------------
; Initialize Filter Taps to zero for next round
;
;------------------------------------------------------------------------
ld *AR5(1),A
stlm A,AR2 ;AR2 points to beginning of filter taps
ld #0,A
rpt #(20-1) ;for(i=0;i<20;i++)
stl A,*AR2+ ; initialize filter taps for next round
goer5 popm AR7
popm AR6
popm AR1
popm ST1
popm ST0
ret
**************************************************************************
* SUBROUTINE: dtmf_checks (approx 1544 cycles)
*
* Input: ptr to DTMFDECOBJ
* Output: none
* Uses:
*
* Description:
* - maximum search
* - DTMF status check
* - signal strength check
* - twist check
* - relative peak check
* - 2nd harmonic check
* conditional computation of 2nd harmonics energies
* - digit validation
*
**************************************************************************
_dtmfchecks:
nop
pshm ST0
pshm ST1
pshm AR1
pshm AR6
pshm AR7
nop
frame #0 ;---- local variables -----
; none
;---- arguments -----------
; (A) = ptr to dtmfchannel struct
ssbx FRCT
stlm A,AR5 ;AR5 is used as ptr to dtmfchannel struct
; *AR5(0) = ptr to data
; *AR5(1) = ptr to taps
; *AR5(2) = ptr to energy template
; *AR5(3) = digitptr
; *AR5(4) = digitlast
; *AR5(5) = detectstat
; *AR5(6) = err_flags
;------------------------------------------------------------------------
; Alternative Maximum search
; result: AR3 points to max row energy ROWMAX
; AR4 points to max col energy COLMAX
;------------------------------------------------------------------------
max_search:
ld *AR5(2),A
stlm A,AR2 ;AR2 points to ENERGY table (row energies)
mvmm AR2,AR3 ;AR3 points to ENERGY table
stm #(4-1),BRC
rptb max1-1 ;for(k=0;k<4;k++)
ld *AR3,A ; (A)=oldmax
sub *AR2,A ; (A)=oldmax-E[k]
bc max11,AGT ; if(oldmax < E[k])
mvmm AR2,AR3 ; AR3 points to newmax
max11 mar *AR2+ ; increment pointer
max1 ;result: AR3 points to ROWMAX
; AR2 points to column energies
mvmm AR2,AR4 ;AR4 points to ENERGY table (column energies)
stm #(4-1),BRC
rptb max2-1 ;for(k=0;k<4;k++)
ld *AR4,A ; (A)=oldmax
sub *AR2,A ; (A)=oldmax-E[k]
bc max21,AGT ; if(oldmax < E[k])
mvmm AR2,AR4 ; AR4 points to newmax
max21 mar *AR2+ ; increment pointer
max2 ;result: AR4 points to COLMAX
; AR2 points to column energies
;----------------------------------------------------------------------
; DTMF Status Check:
; if(detectstat == 0)
; if( max(ROWMAX,COLMAX) < THR_PAU )
; detectstat = 1, detector enabled
; terminate all checks
; else
; continue
;
; AR3 points to ROWMAX
; AR4 points to COLMAX
;----------------------------------------------------------------------
stat_check
andm #0080h,*AR5(6) ;clear error flags, except OVA
bitf *AR5(5),#0001h ;
bc stat1,NTC ;if(detectstat == 1)
ld *AR5(5),A ; load detectstat
and #0F00h,A ; mask out duration bits
sftl A,1 ; shift duration bits
andm #0001h,*AR5(5) ; retain only detect status bit
or *AR5(5),A ; or in duration bits
stl A,*AR5(5) ; write back to detectstat
b sig_check ; continue with sig_check
stat1 ld *AR3,A ;else
ld *AR4,B ;
max A ; (A)=max(ROWMAX,COLMAX)
sub #THR_PAU,A ; (A)=max(ROWMAX,COLMAX) - THR_PAU
bc stat2,ageq ; if((A)<0)
st #0001h,*AR5(5) ; detectstat = 1
stat2 b ende ; terminate all checks
;----------------------------------------------------------------------
; Signal strength check:
; if(ROWMAX+COLMAX > THR_SIG) continue
; else terminate all checks
;
; AR3 points to ROWMAX
; AR4 points to COLMAX
;----------------------------------------------------------------------
sig_check:
ld *AR3,A
add *AR4,A ;(A) = ROWMAX+COLMAX
sub #THR_SIG1,A,B ;
bc ende,BLEQ ;if(ROWMAX+COLMAX <= THR_SIG1)
; signal is not possible tone
; terminate checks
sub #THR_SIG2,A,B ;
bc err_sig,BLEQ ;if(ROWMAX+COLMAX <= THR_SIG2)
; signal is possible tone
; however does not meet THR_SIG2
; branch to err_sig
b twist_check
err_sig: ;**** record signal strength error ****
orm #0001h,*AR5(6) ; set signal strength error flag (b0)
b ende ; terminate checks
;----------------------------------------------------------------------
; Twist check:
; if(ROWMAX > COLMAX)
; check reverse twist:
; if((COLMAX/ROWMAX) > THR_REVTWI) continue
; else terminate all checks
; else
; check standard twist:
; if((ROWMAX/COLMAX) > THR_STDTWI) continue
; else terminate all check
;
; AR3 points to ROWMAX
; AR4 points to COLMAX
;----------------------------------------------------------------------
twist_check:
ld *AR3,A
sub *AR4,A
bc twist2,ALEQ ;if(ROWMAX > COLMAX)
twist1 ld *AR4,16,A ; (AH)=COLMAX
rpt #(16-1) ;
subc *AR3,A ; compute (COLMAX/ROWMAX)
and #0ffffh,A ; retain quotient (AL), mask remainder
sfta A,15 ; shift quotient into AH
sub #THR_REVTWI,16,A;
bc err_revtwi,ALEQ ; if((COLMAX/ROWMAX) <= THR_REVTWI)
; branch to err_revtwi
b rel_check
;else
twist2 ld *AR3,16,A ; (AH)=ROWMAX
rpt #(16-1) ;
subc *AR4,A ; compute (ROWMAX/COLMAX)
and #0ffffh,A ; retain quotient (AL), mask remainder
sfta A,15 ; shift quotient into AH
sub #THR_STDTWI,16,A;
bc err_stdtwi,ALEQ ; if((COLMAX/ROWMAX) <= THR_STDTWI)
; branch to err_stdtwi
b rel_check
err_revtwi: ;**** record reverse twist error ****
orm #0002h,*AR5(6) ; set reverse twist error flag (b1)
b ende ; terminate checks
err_stdtwi: ;**** record standard twist error ****
orm #0004h,*AR5(6) ; set standard twist error flag (b2)
b ende ; terminate checks
;----------------------------------------------------------------------
; Relative peak check:
;
; find rel row peak --> RELPEAK
; if(RELPEAK/ROWMAX < THR_ROWREL) continue
; else terminate all checks
;
; find rel col peak --> RELPEAK
; if(RELPEAK/COLMAX < THR_ROWREL) continue
; else terminate all checks
;
; AR3 points to ROWMAX
; AR4 points to COLMAX
;----------------------------------------------------------------------
rel_check: ;------ relative row peak ratio check -------
ld *AR5(2),A ;
stlm A,AR0 ;AR0 points to ENERGY table (row frequencies)
ld #0,B ;(BH)=0
stm #(4-1),BRC ;
rptb rel12-1 ;for(k=0;k<4;k++)
ld *AR0,16,A ; (AH)=E[k]
cmpr 0,AR3 ;
bc rel11,TC ; if(AR0==AR3)
max B ; (B)=newmax=max(oldmax,E[k])
rel11 mar *AR0+ ;
rel12 rpt #(16-1) ;
subc *AR3,B ;compute (RELPEAK/ROWMAX)
and #0ffffh,B ;retain quotient (BL), mask remainder
sfta B,15 ;shift quotient into BH
sub #THR_ROWREL,16,B;
bc err_rowrel,BGEQ ;if((RELPEAK/ROWMAX) >= THR_ROWREL)
; branch to err_rowrel
;------ relative column peak ratio check ----
rel2 ld #0,B ;(BH)=0
stm #(4-1),BRC ;
rptb rel22-1 ;for(k=4;k<8;k++)
ld *AR0,16,A ; (AH)=E[k]
cmpr 0,AR4 ;
bc rel21,TC ; if(AR0==AR4)
max B ; (B)=newmax=max(oldmax,E[k])
rel21 mar *AR0+ ;
rel22 rpt #(16-1) ;
subc *AR4,B ;compute (RELPEAK/COLMAX)
and #0ffffh,B ;retain quotient (BL), mask remainder
sfta B,15 ;shift quotient into BH
sub #THR_COLREL,16,B;
bc err_colrel,BGEQ ;if((RELPEAK/COLMAX) >= THR_COLREL)
; branch to err_colrel
b sec_check
err_rowrel: ;**** record row's rel peak error ****
orm #0008h,*AR5(6) ; set row's rel peak error flag (b3)
b ende ; terminate checks
err_colrel ;**** record col's rel peak error ****
orm #0010h,*AR5(6) ; set col's rel peak error flag (b4)
b ende ; terminate checks
;----------------------------------------------------------------------
; Second Harmonics check
; if( (ROW2nd/ROWMAX) < THR_ROW2nd ) continue
; else terminate all checks
;
; if( (COL2nd/COLMAX) < THR_COL2nd ) continue
; else terminate all checks
;
; AR3 points to ROWMAX
; AR4 points to COLMAX
;----------------------------------------------------------------------
sec_check:
mvmm AR3,AR6 ;backup AR3
mvmm AR4,AR7 ;backup AR4
;=========== 2nd harmonics check for rows ===========
;----- define ptr to coeff tbl (AR3) -----
ld *AR5(2),A ;load pointer to coeffs from struct
stlm A,AR0 ;AR0 points to energy template
nop
nop ;pipeline latencies
mar *AR3-0 ;AR3 contains displacement in energy template
mvmm AR3,AR1 ;save displacement in AR1
stm #COEF2nd,AR0 ;AR0 points to 2nd harm coefficients
mar *AR3+0 ;AR3 points to desired coefficient
;----- define ptr to taps array (AR4) -----
ld *AR5(1),A ;load pointer to taps from struct
add #3,A ;
stlm A,AR4 ;AR4 points to row's 2nd harm tap
;----- define ptr to energy (AR1) ------
ld *AR5(2),A ;
add #8,A ;
stlm A,AR1 ;AR1 points to row's 2nd harm in energy template
;----- compute goertzel filter -----
ld #0,ASM ;ASM=0
ld *AR5(0),A ;
stlm A,AR2 ;AR2 points to data
stm #(N-1),BRC ;
ld *AR2+,16,A ;(AH) = x(n)
rptb sec1-1 ;for(n=0;n<N;n++) {
sub *AR4-,16,A,B ; (B) = -vk(n-2) + x(n)
mac *AR4,*AR3,B ; (B) = coef*vk(n-1) - vk(n-2) + x(n)
mac *AR4,*AR3,B ; (B) = 2*coef*vk(n-1) - vk(n-2) + x(n)
delay *AR4 ; vk(n-1) ---> vk(n-2)
st B,*AR4+ ; (B) ---> vk(n-1)
|| ld *AR2+,A ; (AH) = x(n)
sec1 ;}
;----- compute energy --------------
ld *AR4,16,A ; (A) = vk(N-1), A(32:16) loaded
mpya *AR4- ; (B) = vk(N-1)*vk(N-1), (T) = vk(N-1)
mpy *AR4,A ; (A) = vk(N)*vk(N-1)
ld *AR3+,T ; (T) = coef
mpya A ; (A) = coef*vk(N)*vk(N-1)
sub A,1,B ; (B) = -2*coef*vk(N)*vk(N-1) + vk(N-1)*vk(N-1)
ld *AR4,T ; (T) = vk(N)
mac *AR4,B ; (B) = vk(N)*vk(N) - 2*coef*vk(N)*vk(N-1) + vk(N-1)*vk(N-1)
sth B,*AR1 ; store result E[k] into energy template
;----- check threshold condition ------
ld *AR1,16,A ;(AH)=ROW2nd
sub *AR6,16,A,B ;(BH)=ROW2nd-ROWMAX
bc err_row2nd,BGEQ ;if(ROW2nd<ROWMAX)
rpt #(16-1) ;
subc *AR6,A ; compute (ROW2nd/ROWMAX)
and #0ffffh,A ; retain quotient (AL), mask remainder
sfta A,15 ; shift quotient into AH
sub #THR_ROW2nd,16,A;
bc err_row2nd,AGEQ ; if((ROW2nd/ROWMAX) >= THR_ROW2nd)
; branch to err_row2nd
;=========== 2nd harmonics check for columns ===========
;----- define ptr to coeff tbl (AR3) -----
mvmm AR7,AR3 ;AR3 points to COLMAX
ld *AR5(2),A ;load pointer to coeffs from struct
stlm A,AR0 ;AR0 points to energy template
nop
nop ;pipeline latencies
mar *AR3-0 ;AR3 contains displacement in energy template
mvmm AR3,AR1 ;save displacement in AR1
stm #COEF2nd,AR0 ;AR0 points to 2nd harm coefficients
mar *AR3+0 ;AR3 points to desired coefficient
;----- define ptr to taps array (AR4) -----
ld *AR5(1),A ;load pointer to taps from struct
add #1,A ;
stlm A,AR4 ;AR4 points to column's 2nd harm tap
;----- define ptr to energy (AR1) ------
ld *AR5(2),A ;
add #9,A ;
stlm A,AR1 ;AR1 points to column's 2nd harm in energy template
;----- compute goertzel filter -----
ld #0,ASM ;ASM=0
ld *AR5(0),A ;
stlm A,AR2 ;AR2 points to data
stm #(N-1),BRC ;
ld *AR2+,16,A ;(AH) = x(n)
rptb sec2-1 ;for(n=0;n<N;n++) {
sub *AR4-,16,A,B ; (B) = -vk(n-2) + x(n)
mac *AR4,*AR3,B ; (B) = coef*vk(n-1) - vk(n-2) + x(n)
mac *AR4,*AR3,B ; (B) = 2*coef*vk(n-1) - vk(n-2) + x(n)
delay *AR4 ; vk(n-1) ---> vk(n-2)
st B,*AR4+ ; (B) ---> vk(n-1)
|| ld *AR2+,A ; (AH) = x(n)
sec2 ;}
;----- compute energy --------------
ld *AR4,16,A ; (A) = vk(N-1), A(32:16) loaded
mpya *AR4- ; (B) = vk(N-1)*vk(N-1), (T) = vk(N-1)
mpy *AR4,A ; (A) = vk(N)*vk(N-1)
ld *AR3+,T ; (T) = coef
mpya A ; (A) = coef*vk(N)*vk(N-1)
sub A,1,B ; (B) = -2*coef*vk(N)*vk(N-1) + vk(N-1)*vk(N-1)
ld *AR4,T ; (T) = vk(N)
mac *AR4,B ; (B) = vk(N)*vk(N) - 2*coef*vk(N)*vk(N-1) + vk(N-1)*vk(N-1)
sth B,*AR1 ; store result E[k] into energy template
;----- check threshold condition ------
ld *AR1,16,A ;(AH)=COL2nd
sub *AR7,16,A,B ;(BH)=COL2nd-COLMAX
bc err_col2nd,BGEQ ;if(COL2nd<COLMAX)
rpt #(16-1) ;
subc *AR7,A ; compute (COL2nd/COLMAX)
and #0ffffh,A ; retain quotient (AL), mask remainder
sfta A,15 ; shift quotient into AH
sub #THR_COL2nd,16,A;
bc err_col2nd,AGEQ ; if((COL2nd/COLMAX) >= THR_COL2nd)
; branch to err_col2nd
mvmm AR6,AR3 ;restore AR3
mvmm AR7,AR4 ;restore AR4
b digit_map
err_row2nd: ;**** record row's 2nd harm error ****
orm #0020h,*AR5(6) ; set row's 2nd harm error flag (b5)
b ende ; terminate checks
err_col2nd: ;**** record col's 2nd harm error ****
orm #0040h,*AR5(6) ; set col's 2nd harm error flag (b6)
b ende ; terminate checks
;----------------------------------------------------------------------
; Map detected tone pair to digit
;
; AR3 points to ROWMAX
; AR4 points to COLMAX
;----------------------------------------------------------------------
digit_map:
;---------- find row and col numbers ----------------------------
ld *AR5(2),A
stlm A,AR0 ;load offset
nop
nop
mar *AR3-0 ;AR3 contains row#
mar *+AR0(4)
mar *AR4-0 ;AR4 contains col#
;---------- map row and column numbers to actual digit -------------
ld *(AR3),8,A ;load row nbr in upper byte of AL
add *(AR4),A ;load column nbr in lower byte of AL
stm #KEYS,AR2 ;AR2 points to key mapping table
stm #0,AR3 ;AR3 is used as counter
stm #(16-1),BRC
rptb digit3-1 ;for(k=0;k<16;k++) {
sub *AR2+,A,B
bc digit31,bneq ; if(A == KEYS[k]) insert delay
b digit4 ; branch to ende
digit31 mar *AR3+ ; increment counter
digit3 ;}
;------------------------------------------------------------------------
; Validate digit from previous digit
;
;------------------------------------------------------------------------
digit4 nop ;now AR3 contains decoded digit
ld *AR5(3),A ;
stlm A,AR4 ;AR4 used as digitptr
orm #0100h,*AR5(5) ;set bit "duration counter"
ldm AR3,A ;load current digit
sub *AR5(4),A,B ;compare with last digit
bc digit5,bneq ;if current digit and last digit are the same
stl A,*AR4+ ; store VALID DIGIT into DIGITS
ldm AR4,A ;
stl A,*AR5(3) ; update pointer
st #0,*AR5(5) ; disable detector and wait for pause
st #-1,*AR5(4) ; reset last digit
b ende ;else
digit5 ldm AR3,A ; store decoded digit
stl A,*AR5(4) ; into digitlast
ende bitf *AR5(5),#0400h ;test "duration counter"
bc end1,NTC ;if(bit set)
st #0,*AR5(5) ; disable detector and wait for pause
st #-1,*AR5(4) ; reset last digit
end1 frame #0
popm AR7
popm AR6
popm AR1
popm ST1
popm ST0
nop
ret
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -