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

📄 clearview007.asm

📁 DTMF decoder using pic16f
💻 ASM
📖 第 1 页 / 共 3 页
字号:
;	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 + -