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