?? clearview007.asm
字號:
; DTMF PWM GENERATOR v1.0
; (c) 2004 Radu Constantinescu
; constantinescuradu at yahoo.com
; Free for Noncomercial use.
;
;
; DTMF SOFTWARE DECODER v2.0
; (c) 2003-2004 Radu Constantinescu
; constantinescuradu at yahoo.com
; based on a David Hedley idea
;
; SERIAL ROUTINES with Buffer
; modified by Radu Constantinescu - eliminate calls in order to save stack space
; UART routines with TX and RX buffers By Tony K黚ek 2000-06-22 free for use
;
; PWM SIGNAL GENERATOR
; timer 2 used to generate interupts at 9765.625hz
; PWM1 output at 78.12hz
;
; SOFTWARE DTMF DECODER
; modified Goertzel algorithm
; timer 2 used to generate interupts at 9765.625hz
; with 1X and 2X frequency bins
;
;
;
;
; FOR 16F88 / 20 Mhz
; F sample = 5000000/512 hz = 9765. 625 hz
;
; RB3 OUT pin 9 PWM1 DTMF OUT - connect to a low pass filter
; RA0 analog IN pin 17 DTMF/FSK INPUT (A/D) - RA0 Signal source must ve impedance lower thah 2K5
; as per Microchip specifications and must have Vcc/2 bias.;
;
; RB2 IN pin 8 Serial Rx
; RB5 OUT pin 11 Serial Tx
;
; RB1 OUT pin 7 Interrupt Indicator ( =1 durring interrupt)
; RB4 OUT pin 10 FSK DCD - ACTIVE LOW
; RB0 OUT pin 6 FSK DATA
;
;
; started JAN 31 2004
;
;
;config bits
;2007 2762
;2008 3ffc
; define treshods for the dtmf decoder
#define treshold1XL .240/4 ; for 1X frequencies DTMF detector / 240 samples
#define treshold1XH .240/5 ; for 1X frequencies DTMF detector / 240 samples
#define treshold2XL .113/3 ; for 2X frequencies DTMF detector / 113 samples
#define treshold2XH .113/3 ; for 2X frequencies DTMF detector / 113 samples
; 50 40 2
; 40 40 3 < best OF 126 - GOOD EXCEPT *
; 35 35 3
RADIX DEC
#include <p16f88.inc>
#include <macro.asm>
; base frequency
XTAL_FREQ EQU 20000000 ; OSC freq in Hz
#include <serial.asm>
#include <tables.asm>
CBLOCK 0x20
;****************************
; Bank0 Int Save
;****************************
PCLATH_SAVE: 1
STATUS_TEMP: 1
FSR_SAVE: 1
;****************************
; DTMF GENERATOR VARIALBLES
;****************************
PWMVAL: 1 ; intermediate PWM Value (another temp register for interrupts can be used)
AccHH: 1 ; Accumulator High High Frequency
AccLH: 1 ; Accumulator Lo High Fequency
AccHL: 1 ; Accumulator High Low Frequency
AccLL: 1 ; Accumulator Lo Low Fequency
XAddHH: 1 ; Acc Add High High Frequency
XAddLH: 1 ; Acc Add Lo High frequency
XAddHL: 1 ; Acc Add High Low Frequency
XAddLL: 1 ; Acc Add Lo Low frequency
TempH: 1 ; ISR Temp PWM value for High Frequency, reused in the DTMF Detector ISR for Temp Lowtemplate
TempL: 1 ; ISR Temp PWM value for Low Frequency, reused in the DTMF Detector ISR for Temp Highemplate
; Freq AddH AddL Error(%)
; 1000 26 55 0.001692772
; 697 18 69 -0.01042912
; 770 20 47 -0.007402742
; 852 22 86 0.005680407
; 941 24 171 0.000885164
; 1209 31 177 -0.00569002
; 1336 35 6 0.002852743
; 1477 38 184 0.000209718
; 1633 42 207 0.001117896
;Frequency 1209 1336 1477 1633
;697 1 2 3 A
;770 4 5 6 B
;852 7 8 9 C
;941 * 0 # D
;****************************
; SERIAL ROUTINES VARIABLES
;****************************
; serial buffer RX and TX pointers, buffers located in bank1
RX_Buffer_InPtr:1 ; where to put next incomming byte
RX_Buffer_OutPtr:1 ; where to get next ( first ) byte
RX_Buffer_Count:1 ; how many we have in buffer
TX_Buffer_InPtr:1 ; where to put next outgoing byte
TX_Buffer_OutPtr:1 ; whre to get next byte
TX_Buffer_Count:1 ; how many we have in buffer
TX_Temp:1 ; temporary reg used while sending
Flags:1 ; flags for serial comunincation
EE_Byte:1 ; Temp var for EEProm Routines
Temp:1 ; temp byte ONLY to be used locally and no calls !
FSRSAVE:1
;****************************
; DELAY ROUTINES VARIABLES
;****************************
TIME0: 1 ;DELAY COUNTER LSB
TIME1: 1 ;DELAY COUNTER MSB
;****************************
; DTMF DECODER ROUTINES VARIABLES
;****************************
A697SIN:1
A697COS:1 ; ACCUMULATOR for 697 Hz sin
A770SIN:1
A770COS:1 ; ACC
A852SIN:1
A852COS:1 ; ACC
A941SIN:1
A941COS:1 ; ACC
A1209SIN:1
A1209COS:1 ;ACC
A1336SIN:1
A1336COS:1 ;ACC
A1447SIN:1
A1447COS:1 ;ACC
A1633SIN:1
A1633COS:1 ;ACC
; double frequency bins
A697SIN2:1
A697COS2:1 ; ACCUMULATOR for 697 Hz sin
A770SIN2:1
A770COS2:1 ; ACC
A852SIN2:1
A852COS2:1 ; ACC
A941SIN2:1
A941COS2:1 ; ACC
A1209SIN2:1
A1209COS2:1 ;ACC
A1336SIN2:1
A1336COS2:1 ;ACC
A1447SIN2:1
A1447COS2:1 ;ACC
A1633SIN2:1
A1633COS2:1 ;ACC
SAMPLEBIT:1
TABLECOUNTER:1
LOWTEMPLATE:1 ; USED BY DTMF DETECTOR ISR - temp val for Lowfreq Table Value
HIGHTEMPLATE:1 ; USED BY DTMF DETECTOR ISR - temp val for Highfreq Table Value
BYTE_DTMF:1
RESULT1:1 ; DECODED DIGIT OR 0
RESULT:1 ; USED BY DTMF DETECTOR ISR - result bits for 1X BINS
RESULT2X:1 ; USED BY DTMF DETECTOR ISR - result bits for 2X BINS
FSR_SAVE_DTMF:1 ; DTMF ISR ROUTINE TEMP Variable
TEMP_VAL:1
TEMP_TIMES:1
DTMF_RESULT:1 ; LAST detected DTMF digit or '-'
LASTBIT:1 ; 0 OR 1(FF)
BITCHANGES:1 ; COUNT THE NUMBER OF BIT CHANGES, INCREMENT AT EACH INPUT BIT CHANGE
ENDC
; ************* Bit variable definitions ***************************
#define _BufferOverrun Flags,0 ; Serial RX buffer overrun
#define TIMEOUT Flags,1 ; timeout flag
#define DTMF_GEN_ON Flags,2 ; DTMF GENERATOR ON/OFF
#define GOT_ONE Flags,3 ; GOT_ONE is set when at least a char is in the RxBuffer
#define DTMF_DONE Flags,4 ; 1 DTMF detector off / 0 - DTMF detector on
#define DTMF_DETECTED Flags, 5 ; one DTMF digit detected in DTMF_RESULT
#define DTMF_RECOVER Flags,6 ; =1 do not send the next digit - just recover (used by the decision alg.)
#define Temp_Flag Flags,7
; *** Bank1 *** 80 bytes, 64 used for Serial Buffers
CBLOCK 0x0A0
RX_Buffer:RX_BUFFER_SIZE ; buffer for rx - A0
TX_Buffer:TX_BUFFER_SIZE ; buffer for tx - C0
ENDC
;***********************************************
;Shared Ram
;***********************************************
CBLOCK 0x71 ; variables for all the RAM pages, skip 70 for ICD
W_TEMP: 1 ; int W save/shared Ram
XcomA: 1
XcomB: 1
XcomC: 1
temp1: 1 ; temp value 1
ENDC
;***********************************************
;EEprom Variables
;***********************************************
;ORG h'2100' ;EEPROM INITIAL VALUES
;DE 0,0,0,0,0,0,0,0
;DE "1234567890"
;****************************
ORG 0X00
NOP
CLRF PCLATH ; Page 0
CLRF STATUS ; BANK 0
GOTO START
INTERRUPT_VECTOR
ORG 0X04
;****************************
;
; CONTEXT SAVE
;
;****************************
C_SAVE MOVWF W_TEMP
SWAPF STATUS,W
CLRF STATUS ;ENSURE BANK0 SAVE
MOVWF STATUS_TEMP
BSF PORTB, 1 ; set interrupt indicator
MOVF PCLATH,W ; SAVE PCLATH
MOVWF PCLATH_SAVE
MOVF FSR, W
MOVWF FSR_SAVE
BTFSS PIR1,TMR2IF ; TMR2 Overflow Check
GOTO INT_TEST_RX_IRQ ; ; if not timer 2 then goto serial
;**********************
;Timer 2 ISR
;**********************
BTFSC DTMF_DONE
GOTO T2ISR_1 ; Skip A/D input if dtmf detect is off
CLRF BYTE_DTMF ; input = 0
BTFSC ADRESH,7 ; MSB bit of A/D
COMF BYTE_DTMF, F ; input = 1
BSF ADCON0, GO ; start a new conversion
; clrw
; xorwf BYTE_DTMF, W
; btfsC STATUS, Z
; BCF PORTB, 0
; MOVLW .255
; xorwf BYTE_DTMF, W
; btfsC STATUS, Z
; BSF PORTB, 0
; COMPARE input AND lastbit
; MOVF LASTBIT, W
; XORWF BYTE_DTMF,W
; BTFSC STATUS, Z
; GOTO LASTBITEND
; ; IF input <> lastbit
; INCF BITCHANGES, F ; INCREMENT THE NUMBER OF BITCHANGES
; ; LASTBIT = INPUT
; MOVF BYTE_DTMF, W
; MOVWF LASTBIT
LASTBITEND
T2ISR_1
BCF PIR1,TMR2IF ; RESET TIMER 2 INT FLAG
BTFSS DTMF_GEN_ON ; dtmf generator is on?
GOTO DTMF_DETECT ; no, skip to DTMF detect ISR
;**********************
; DTMF GENERATOR ISR
;**********************
; Update High Frequency Generator Accumulator
MOVF XAddLH,W ; Low constant High Frequency
ADDWF AccLH,F ; Add to the low accumulator byte, High Frequency
MOVF XAddHH,W ; High constant High Frequency
BTFSC STATUS,C
ADDLW 1 ; ADD carry
ADDWF AccHH,F ; Add to the high accumulator byte, High Frequency
; Update Low Frequency Generator Accumulator
MOVF XAddLL,W ; Low constant Low Frequency
ADDWF AccLL,F ; Add to the low accumulator byte, Low Frequency
MOVF XAddHL,W ; High constant Low Frequency
BTFSC STATUS,C
ADDLW 1 ; ADD carry
ADDWF AccHL,F ; Add to the high accumulator byte, Low Frequency
GetSinVal: ; Read the Value from a 128 entries sin table
;necessary only if table is not alligned
;MOVLW LOW GetSinTab
;ADDWF ACCH,W ; just set carry
MOVLW HIGH GetSinTab
;BTFSC STATUS,C
;ADDLW 1
MOVWF PCLATH
MOVF AccHH,W ; get index
ANDLW B'01111111' ; mask upper bit 0-127 only
CALL GetSinTab
; add sign
BTFSS AccHH,7 ; 2's coplement 256-value if <0
GOTO DTMFISR1
CLRF TempH
SUBWF TempH,W
DTMFISR1:
MOVWF TempH ; Store temp pwm val for high freq
MOVF AccHL,W ; get index
ANDLW B'01111111' ; mask upper bit 0-127 only
CALL GetSinTab
MOVWF TempL ; Store temp pwm val for low freq
BCF STATUS, C ; Clear Carry
RRF TempL,F ; TempL=TempL/2
BCF STATUS, C ; Clear Carry
RRF TempL,W ; TempL=TempL/2, result in W
ADDWF TempL,W ; TempL = 0.75 TempL --> Low frequency amplitude should be 3dB (0.707) lower than high frequency amplitude, resul in W
; add sign
BTFSS AccHL,7 ; 2's coplement 256-value if <0
GOTO DTMFISR2
CLRF TempL
SUBWF TempL,W
DTMFISR2:
;MOVWF TempL ; Store temp pwm val for low freq
ADDWF TempH,W ; XcomBined PWM Value in W
ADDLW 128 ; 128+w --> value=128+PWM value
; +50 = 128+50
; -50 --> hCE+h80=H14e, h4e=78 = 128-50
; index was 128-255 --> value=128-table read
CLRF PCLATH
SetPWMVal: ; set PWM val to W, PWMVAL=CCPR1L<5,0>,CCP1CON<5,4>
MOVWF PWMVAL ; temporary
BCF CCP1CON,4 ; clear CCP1CON<5,4>
BCF CCP1CON,5
RRF PWMVAL,F ; rotate right with carry
BTFSC STATUS,C
BSF CCP1CON,4 ; store carry in CCP1Con<4>
RRF PWMVAL,W
BTFSC STATUS,C
BSF CCP1CON,5 ; store carry in CCP1Con<5>
ANDLW B'00111111'
MOVWF CCPR1L ; store 6 MSB bits in CCPR1L<5,0>
; continue to Dtmf Detector ISR
;**********************
; DTMF DETECTOR ISR
;**********************
DTMF_DETECT
BTFSC DTMF_DONE
GOTO DTMF_ISR_END ; Skip dtmf detect isr if done=1, goto delay ISR
; input value in DTMF_BYTE = 00 or FF
;*****************************
;
;Get the expected Lowband Bits
;
;*****************************
MOVLW LOW LOWBAND
ADDWF TABLECOUNTER,W ; add low lowband + tablecounter with carry
MOVLW HIGH LOWBAND ; to pclath
BTFSC STATUS,C
ADDLW 1
MOVWF PCLATH ; if the table will be alligned to a 256 boundary this will nor be necessary
; read 1X template
MOVF TABLECOUNTER,W
CALL LOWBAND ; read table
;CLRF PCLATH
MOVWF LOWTEMPLATE
MOVF BYTE_DTMF,W
XORWF LOWTEMPLATE, F ; APPLY INPUT OVER MASK
; read 2X template - must use TABLECOUNTER X 2 as pointer
MOVF TABLECOUNTER,W
;clear carry
bcf STATUS, C ; Carry=0
rlf TABLECOUNTER,W ; TABLECOUNTER X 2 > W
CALL LOWBAND ; read table
MOVWF TempL
MOVF BYTE_DTMF,W
XORWF TempL, F ; APPLY INPUT OVER MASK
;CLRF PCLATH ; clear pclath before any GOTO
;*****************************
;
;Get the expected Highband Bits
;
;*****************************
MOVLW LOW HIGHBAND
ADDWF TABLECOUNTER,W
MOVLW HIGH HIGHBAND
BTFSC STATUS,C
ADDLW 1
MOVWF PCLATH
; read 1X template
MOVF TABLECOUNTER,W
CALL HIGHBAND
;CLRF PCLATH
MOVWF HIGHTEMPLATE
MOVF BYTE_DTMF,W
XORWF HIGHTEMPLATE, F ; APPLY INPUT OVER MASK
; read 2X template - must use TABLECOUNTER X 2 as pointer
MOVF TABLECOUNTER,W
;clear carry
bcf STATUS, C ; Carry=0
rlf TABLECOUNTER,W ; TABLECOUNTER X 2 > W
CALL HIGHBAND ; read table
MOVWF TempH
MOVF BYTE_DTMF,W
XORWF TempH, F ; APPLY 2X frequencies Mask over the 1X frequencies result
CLRF PCLATH ; clear pclath before any GOTO.......
;*******************************
;
; LOWTEMPLATE AND HIGHTEMPLATE
; CONTAIN THE EXPECTED VALUES
; FOR THE INCOMING BIT
;
;*******************************
; do it for the 1Xfreq bins
MOVLW LOW A697SIN
MOVWF FSR ;ACCUMULATOR ADDR in pointer FSR
MOVLW 8
MOVWF SAMPLEBIT ; samplebit is the number of the bit being tested
COMPAREBITL
RLF LOWTEMPLATE,F
BTFSS STATUS,C
GOTO MATCHL
DECF INDF,F ; decrement accumulator
GOTO CONTINL
MATCHL
INCF INDF,F
CONTINL
INCF FSR,F ; increment pointer - next accumulator
DECFSZ SAMPLEBIT,F ; next bit
GOTO COMPAREBITL ;FINISH THE BYTE
; MOVF TABLECOUNTER,W
; SUBLW .66-1 ; 0-65=66 SAMPLES This is the number of samples to test against (max 127)
; this will go from 0 to 125 and stop at 126, a total of 126 samples
;treshold-w--> W, carry=0 on borrow,
; W=31 carry=0, W=30 carry=1, W=29 carry=1!
; therefore C is 0 for W > treshold
BTFSS STATUS,C
GOTO SKIPHI1X
MOVLW LOW A1209SIN
MOVWF FSR ;ACCUMULATOR ADDR
MOVLW 8
MOVWF SAMPLEBIT
COMPAREBITH
RLF HIGHTEMPLATE,F
BTFSS STATUS,C
GOTO MATCHH
DECF INDF,F
GOTO CONTINH
MATCHH
INCF INDF,F
CONTINH
INCF FSR,F
DECFSZ SAMPLEBIT,F
GOTO COMPAREBITH ;FINISH THE BYTE
SKIPHI1X
; do it again for the 2Xfreq bins
; SKIP 2X IF TABLECOUNTER>113
MOVF TABLECOUNTER,W
SUBLW .113-1 ;This is the number of samples to test against (max 127)
; this will go from 0 to 125 and stop at 126, a total of 126 samples
;treshold-w--> W, carry=0 on borrow,
; W=31 carry=0, W=30 carry=1, W=29 carry=1!
; therefore C is 0 for W > treshold
BTFSS STATUS,C
GOTO SKIPHI2X
MOVLW LOW A697SIN2
MOVWF FSR ;ACCUMULATOR ADDR in pointer FSR
MOVLW 8
MOVWF SAMPLEBIT ; samplebit is the number of the bit being tested
COMPAREBITL2
RLF TempL,F
BTFSS STATUS,C
GOTO MATCHL2
DECF INDF,F ; decrement accumulator
GOTO CONTINL2
MATCHL2
INCF INDF,F
CONTINL2
INCF FSR,F ; increment pointer - next accumulator
DECFSZ SAMPLEBIT,F ; next bit
GOTO COMPAREBITL2 ;FINISH THE BYTE
; MOVF TABLECOUNTER,W
; SUBLW .66-1 ;This is the number of samples to test against (max 127)
; this will go from 0 to 125 and stop at 126, a total of 126 samples
;treshold-w--> W, carry=0 on borrow,
; W=31 carry=0, W=30 carry=1, W=29 carry=1!
; therefore C is 0 for W > treshold
; BTFSS STATUS,C
; GOTO SKIPHI2X
MOVLW LOW A1209SIN2
MOVWF FSR ;ACCUMULATOR ADDR
MOVLW 8
MOVWF SAMPLEBIT
COMPAREBITH2
RLF TempH,F
BTFSS STATUS,C
GOTO MATCHH2
DECF INDF,F
GOTO CONTINH2
MATCHH2
INCF INDF,F
CONTINH2
INCF FSR,F
DECFSZ SAMPLEBIT,F
GOTO COMPAREBITH2 ;FINISH THE BYTE
SKIPHI2X
;********************************
;
; Increment Tablecounter 0..255
;
;********************************
INCF TABLECOUNTER,F
MOVF TABLECOUNTER,W
XORLW .240 ;This is the number of samples to test against (max 127)
; this will go from 0 to 125 and stop at 126, a total of 126 samples
BTFSS STATUS,Z
GOTO DTMF_ISR_END
BSF DTMF_DONE
DTMF_ISR_END
;**********************
; Delay ISR
;**********************
; TIME1:TIME0 counter will be decremented each Timer2 Tick,
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -