www.pudn.com > DTMFFSK.rar > DTMFFSK.asm
;=============================================================
;An example to illustrate how to set the internal adjustable
;CID gain and receive FSK or DTMF data.
;Assume end-code of DTMF data string is "D".
;
;Step1. Initialize the CID system.
;Step2. Setting the CID gain control.
;Step3. Enable Ring detector (assume the FSK/DTMF signal comes
; between 1st and 2nd rings).
;Step4. Enable FSK and DTMF receivers when 1st ring is detected.
;Step5. Check CID interrupt resulted from FSK or DTMF receiver
; by reading CIDFG register.
;
;If FSK interrupt then refer to step5~7.
;If DTMF interrupt then refer to step8
;--FSK---
;Step5. Confirm FSK data string by counting the number of
; consecutive channel seizure.
;Step6. Continuously receive FSK data string and store it in RAM
; till receive all data or time out.
;Step7. Verify if system receives FSK data string correctly
; by comparing check-sum.
;;Jump to Step10
;--DTMF---
;Step8. Read low nibble of DTMFDR to get DTMF decoded data
;Step9. Store DTMF data in RAM.
; Repeat step8 and step9 till end-code "D" is received or time out.
;
;Step10. Process the received data according system need.
;===============================================================
;====Define the flags for FSK receiving ======================
Flag0 reg 23h ;Flag register
Channel_Seizure_Flag reg Flag0.0 ;if the number of recognition is equal to C_Ch_Seiz_Times,set flag
FSK_Data_Flag reg Flag0.1 ;if FSK data string begins, set FSK_Data_Flag
FSK_Format_Flag reg Flag0.2 ;Set when receive FSK format data
FSK_Multiple_Format_Flag reg Flag0.3 ;Set if the FSK format data is equal to 08h
FSK_Single_Format_Flag reg Flag0.4 ;Set if the FSK format data is equal to 04h
FSK_Length_Flag reg Flag0.5 ;Set when receive the FSK length data
FSK_Finish_Flag reg Flag0.6 ;Set when FSK receive data completely and correctly
;--------------------------------------------------------------
Cid_Flag1 reg 24h ;Flag register 1
Multiple_Length_Flag reg Cid_Flag1.0 ;Set when FSK receive parameter type value, clear as FSK gets parameter length
Multiple_Date_Flag reg Cid_Flag1.1 ;Set when FSK receive Data parameter, clear as FSK finish Date receiving
Multiple_Number_Flag reg Cid_Flag1.2 ;Set when FSK receive number parameter, clear as FSK finish number receiving
Multiple_Name_Flag reg Cid_Flag1.3 ;Set when FSK receive name parameter, Clear as finish name receiving
Multiple_Dummy_Flag reg Cid_Flag1.4 ;Set when FSK receiver other paramter, Clear as FSK finish dummy receiving
DTMF_Data_Flag reg Cid_Flag1.5 ;Set when DTMF decoder begins to receive DTMF data
CID_Finish_Flag reg Cid_Flag1.6 ;Set when CID receives completed data correctly
CID_Error_Flag reg Cid_Flag1.7 ;Set when CID (FSK) decoder recieves data incorrectly
;----------------------------------------------------------------
;====Register Definition================================
Cidfg_R reg 60h ;a register store cidfg
Counter1 reg 63h ;normal counter
Counter2 reg 64h ;normal counter
Data_Buffer reg 65h ;noram data buffer
Check_Sum reg 66h ;FSK check sum
Fsk_Data reg 67h ;a register to store FSKDR
DTMF_Data reg 68h ;a register to store DTMF
R0_Dp reg 69h ;save the data pointer of R0
Counter_Channel_Seizure reg 6Ah ;counter to count Channel seizure number
Data_Length reg 6Bh ;Store the FSK data length
Multiple_Parameter_Length reg 6Ch ;Store the multiple parameter length value
WDT_Counter reg 6Dh ;used in WDT interrupt to count the time-out times
Incall_Buf_Pointer_R1 reg R1 ;use R1 to be the data pointer of incall structure buffer
;-----------------------------------------------------------
;====Constant Definition===========================================
;---FSK constant-----------------------------
C_Channel_Seizure equ 055h ;Channel Seizure data
C_Ch_Seiz_Times equ 03h ;Consecutive receiving Channel seizure times
C_Single_Format equ 04h ;Single format code=04h
C_Multiple_Format equ 80h ;Multiple format code=80h
;---CID power control signal ----------
; cidprc: - - - CIDE, - FSKE, CASE, DTMFE
CAS_Enable equ 00011010b ;enable CIDE, CASE
FSK_Enable equ 00011100b ;enable CIDE, FSKE
DTMF_Enable equ 00011001b ;enable CIDE, DTMFE
C_caspt equ 15 ;CAS present time
C_casat equ 24 ;CAS absent time
C_dtmfpt equ 25 ;DTMF present time
C_dtmfat equ 25 ;DTMF absent time
;===CID gain control registers and constants definition==================
;---The Address of Internal CID Gain Control Register---------------------
CIDGD reg F9h ;CID gain control data register
CIDGA reg FAh ;CID gain control address register
C_DTMFR1_Add equ 00h ;DTMFR1 address=00h
C_DTMFR2_Add equ 01h ;DTMFR2 address=01h
C_PGAF_Add equ 02h ;Programmable Gain control Alert tone/FSK address=02h
C_PGAD_Add equ 03h ;Programmable Gain control DTMF
C_PHAD_Add equ 04h ;Programmable Hysteresis alert tone/DTMF
C_PHFL_Add equ 05h ;Programmable Hysteresis FSK/Low pass filter
;---The value of programmable gain and hysteresis ----------------
C_Gain_FD equ 09h ;set FSK/DTMF input gain=10.05dB, PGAF<3:0>
C_Gain_A equ 09h ;set Alert tone input gain=10.05dB, PGAF<7:4>
C_Gain_Row equ 07h ;set DTMF row(low) tone input gain=4.64dB, PGD<3:0>
C_Gain_Col equ 0Ah ;set DTMF column(high) tone input gain=13.53dB, PGD<7:4>
C_Hys_DTMF equ 05h ;set DTMF hysteresis=21mV, PHAD<3:0>
C_Hys_A equ 03h ;set Alert tone hysteresis=22mV, PHAD<7:4>
C_Hys_LP equ 03h ;set FSK Low Pass filter hysteresis=22mV, PHFL<3:0>
C_Hys_FSK equ 03h ;set FSK hysteresis=22mV, PHFL<7:4>
C_dtmfr1 equ 01h ;DTMF register1, row acceptable error freq:2.5%,
C_dtmfr2 equ 01h ;DTMF register2 column acceptable error freq:2.5%
C_Freq_Chg_Rst equ 01h ;1: represents DTMF PT counter will be reset by detected freq. changed
C_No_Down_Count equ 01h ;1: DTMF AT counter is up counter only, 0:is up-down counter
;-----------------------------------------------------------------
org 00h
ljmp Start
org 53h ;The address of CID interrupt vector
ljmp Cid_Int
org 70h
Start:
mov sp,#0d0h ;stack point begins at D0H
mov Counter1,#00
mov Counter2,#00
mov Counter3,#00
mov r0,#80h ;for indirect data pointer from 80H
mov R0_Dp,r0
mov Flag0,#00h
mov Cid_Flag1,#00h
call CID_Gain_Setting ;Setting the internal adjustable CID gain
call FSK_Flag_Initial_Setting ;Set the flags relative FSK to initial state
;---set CID control signals-------------
mov cidpcr,#00h ;Off all CID power
mov cidpcr,#DTMF_Enable ;-, -, -, CIDE, -, FSKE, ASE, DTMFE
orl cidpcr,#Ring_Enable ;enable ring detector
mov dtmfpt,#C_dtmfpt ;Alert Signal Present Time
mov dtmfat,#C_dtmfat ;Alert Signal Absent Time
;----clear all CID related flags--------
mov cidfg,#00h ;-, -, -, -, dtmfdf,fdrf,algof,rngf
mov exif,#00h ;clear exif.2=cidf, exif.3=divf
setb ecid ;enable CID interrupt(EIE.2)
setb ea ;enable global interrupt(IE.7)
;---Stay in a loop to wait for ring detection------------
wait_ring:
jb CID_Finish_Flag,Correct
jb CID_Error_Flag,Error
mov a,dtmfdr ;CASH,CASL,DTMFH,DTMFL,DD3,DD2,DD1,DD0
jmp wait_ring ;User can poll DTMFH/DTMFL by reading dtmfdr register.
Correct:
call CID_Correct_Procedure ;Do some procedure when data received correctly,
clr CID_Finish_Flag ;for example, show the date, time and number on LCD
call FSK_Flag_Initial_Setting ;Set the flags relative FSK to initial state
jmp wait_ring
Error:
call CID_Error_Procedure ;Do some procedure when data received with error
clr CID_Error_Flag
call FSK_Flag_Initial_Setting ;Set the flags relative FSK to initial state
jmp wait_ring
;============================================================================
; Caller ID interrupt
;1. Jump to Ring/CAS/FSK/DTMF interrupt according to CID flags(cidfg)
;2. Ring_Int:
; Enable FSK receiver power
;3. FSK_Int:
; a. Check 3 consucutive Channel_Seizure(55H) at the beginning of the FSK data string?
; If YES: setb Channel_Seizure_Flag and Disable DTMF decoder
; If NO: Clear Counter_Channel_Seizure and jump to reset counter
; and Check if DTMF_Int occurs?
; b. Check Single or Multiple format then sum up the received data:
; The first byte of FSK data string is either 04H(Single) or 80H(Multiple).
; c. Continueously store and sum up received data till the number of received bytes
; is equal to the FSK length data.
; d. Compare the check sum:
; If Correct: setb CID_Finish_Flag
; If Error: setb CID_Error_Flag
;4.DTMF_Int:
; a. Store the low nibble of DTMFDR into DTMF_Data
; b. Check Start or End code.
;============================================================================
Cid_Int:
mov Cidfg_R,cidfg ;record CIDFG register
mov a,cidfg
jb a.0,Ring_Int ;Int occurs by Ring detection
; jb a.1,CAS_Int ;Int occurs by Alert signal detection
jb a.2,FSK_Int ;Int occurs by FSK data ready
jb a.3,DTMF_Int ;Int occurs by DTMF data ready
;===Ring Detection Int=============
Ring_Int:
mov cidpcr,#FSK_Enable ;Enable the power of FSK and DTMF receivers
orl cidpcr,#DTMF_Enable
jmp End_Cid_Int
;===FSK Detection Int==============
FSK_Int:
mov Fsk_Data,fskdr ;read fsk data from fskdr
mov Data_Buffer,Fsk_Data ;put Fsk_Data in Data_Buffer
jb Channel_Seizure_Flag,Receive_FSK
;check 3 consucutive Channel Seizure (55h)
mov a,Fsk_Data
cjne a,#C_Channel_Seizure,Reset_Counter ;if not 55h initially, then reset counter and quit CID interrupt
inc Counter_Channel_Seizure ;if 55h, then inc counter
mov a,Counter_Channel_Seizure
cjne a,#C_Ch_Seiz_Times,End_Cid_Int ;check the number of recognizing channel seizure
setb Channel_Seizure_Flag ;if the number of recognition is equal to C_Ch_Seiz_Times,set flag
jmp Receive_FSK
Reset_Counter:
mov Counter_Channel_Seizure,#00h
mov a,Cidfg_R ;Not FSK data, then check if the data is DTMF format.
jb a.3,DTMF_Int ;Int occurs by DTMF data ready (DTMFDR flag)
jmp End_Cid_Int ;if not DTMF_Int, it means the FSK int is trigerred by noise.
Receive_FSK:
Check_FSK_Format:
jb FSK_Format_Flag,FSK_Length ;when receive 04H or 80H(FSK format code), then set flag
mov a,Fsk_Data
cjne a,#C_Single_Format,Check_Multiple
setb FSK_Format_Flag ;FSK format code is 04H
add a,Check_Sum ;Do Check Sum
mov Check_Sum,a
call Store_Data ;Store data in RAM
jmp End_Cid_Int
Check_Multiple:
cjne a,#C_Multiple_Format,End_Cid_Int
setb FSK_Format_Flag ;FSK format code is 80H
setb FSK_Multiple_Format_Flag
add a,Check_Sum ;Do Check Sum
mov Check_Sum,a
call Store_Data ;Store data in RAM
jmp End_Cid_Int
FSK_Length: ;receive FSK total length data
jb FSK_Length_Flag,FSK_Data_String
mov a,Fsk_Data
mov Data_Length,a
setb FSK_Length_Flag
add a,Check_Sum ;Do Check Sum
mov Check_Sum,a
call Store_Data ;Store data in RAM
jmp End_Cid_Int
FSK_Data_String: ;receiver FSK data string
mov a,Fsk_Data
add a,Check_Sum ;Do Check Sum
mov Check_Sum,a
call Store_Data ;Store data in RAM
clr c
mov a,Data_Length ;Data_Length(FSK data string length) decreases one
subb a,#01h ;when receive one bye of FSK data string
mov Data_Length,a
jnc End_Cid_Int
mov a,Check_Sum ;The last byte of FSK data string should be 2's complement of Check_Sum
jnz Receive_Error
setb CID_Finish_Flag ;set when FSK receiving is correctly completely.
mov cidpcr,#00h ;Disable CID power
jmp End_Cid_Int
Receive_Error:
setb CID_Error_Flag ;if FSK error
;---end of FSK_Int----------
;===DTMF Detection Int======
DTMF_Int:
mov cidpcr,#DTMF_Enable ;-, -, -, -, CIDE, FSKE, ASE, DTMFE (Enable DTMF only, FSK disable)
mov DTMF_Data,dtmfdr ;read fsk data from fskdr
anl DTMF_Data,#0fh ;reserve the low nibble
mov Data_Buffer,DTMF_Data ;show the DTMFDR to LCD from position1
mov a,DTMF_Data
cjne a,#0CH,Store_DTMF ;Check if End-Code ("D") is received?
setb CID_Finish_Flag
Store_DTMF:
call Store_Data ;Store data in RAM
;---end of DTMF_Int----------
End_Cid_Int:
mov cidfg,#00 ;MUST clear CID flags in every CID interrupt routine
anl exif,#11111011b ;then clear exif.2=CIDF
reti
;----End 0f CID Interrupt Routine ---------------------
;=================================================================
;An example ot tore the received data into the RAM from 80h to DFh
;=================================================================
Store_Data:
mov r0,R0_Dp
mov @r0,Data_Buffer
inc r0
mov R0_Dp,r0
cjne r0,#0d0h,Quit_Store_Data
mov r0,#080h
mov R0_Dp,r0
Quit_Store_Data:
ret
;-----------------------------------------------------------------------------
;======================================================
;The FSK flag initial Setting
;======================================================
FSK_Flag_Initial_Setting:
mov Counter_Channel_Seizure,#00h
mov Data_Length,#00h
mov Check_Sum,#00h
mov Flag0,#00h ;clear all the flags
anl Cid_Flag1,#11000000b ;reserve CID_Finish_Flag(bit6) and CID_Error_Flag(bit7)
ret
;----------------------------------------------------------------------------
;==========================================================
;Set Internal CID gain control registers
;1. Set DTMFR1
;2. Set DTMFR2
;3. FSK/DTMF input gain set. PGAF<3:0>
;4. Alert tone input gain set. PGAF<7:4>
;5. DTMF row(low) tone input gain set. PGD<3:0>
;6. DTMF column(High) tone input gain set. PGD<7:4>
;7. DTMF hysteresis set. PHAD<3:0>
;8. Alert tone input hysteresis set. PHAD<7:4>
;9. FSK Low pass filter input hysteresis set. PHFL<3:0>
;10.FSK input hysteresis set. PHFL<7:4>
;=========================================================
CID_Gain_Setting:
mov CIDGD,#00h ;initiall set Data/Address 00h
mov CIDGA,#00h
Set_DTMFR1:
mov CIDGD,#C_dtmfr1
call Latch_Data
Set_DTMFR2:
inc CIDGA ;CIDGA=01
mov CIDGD,#C_dtmfr2
call Latch_Data
PGAF_Set:
inc CIDGA ;CIDGA=02
mov a,#C_Gain_A
swap a
orl a,#C_Gain_FD ;PGAF=(C_Gain_A, C_Gain_FD)
mov CIDGD,a
call Latch_Data
PGAD_Set:
inc CIDGA ;CIDGA=03
mov a,#C_Gain_Col ;PGAD=(C_Gain_Col, C_Gain_Row)
swap a
orl a,#C_Gain_Row
mov CIDGD,a
call Latch_Data
PHAD_Set:
inc CIDGA ;CIDGA=04
mov a,#C_Hys_A ;PHAD=(C_Hys_A, C_Hys_DTMF)
swap a
orl a,#C_Hys_DTMF
mov CIDGD,a
call Latch_Data
PHFL_Set:
inc CIDGA ;CIDGA=05
mov a,#C_Hys_FSK ;PHFL=(C_Hys_FSK, C_Hys_LP)
swap a
orl a,#C_Hys_LP
mov CIDGD,a
call Latch_Data
ret
;---END OF CID GAIN SETTING--------------------------------
;===================================================
;Latch CIDGD into internal cid gain control register
;===================================================
Latch_Data:
orl CIDGA,#00001000b ;set bit3
nop
anl CIDGA,#11110111b ;clear bit3
ret
;---END OF LATCH DATA--------------------------------------
end