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

📄 clearview007.asm

📁 DTMF decoder using pic16f
💻 ASM
📖 第 1 页 / 共 3 页
字号:
; TIMEOUT flag will be set when counter reaches zero.
DELAY_ISR
	BTFSC	TIMEOUT		; CHECK IF NOT TIMEOUT
	GOTO DELAY_ISR_END
	; DECREMENT TIMEOUT COUNTER
	DECF	TIME0, F
	BTFSS	STATUS, Z
	GOTO	DELAY_ISR_END		; TIME0<>0
	DECF	TIME1, F
	BTFSS	STATUS, Z
	GOTO 	DELAY_ISR_END		; TIME1<>0
	BSF	TIMEOUT		; SET TIMEOUT=TRUE
DELAY_ISR_END
	; continue to Serial ISR	


	goto INT_EXIT	; skip serial


;**********************
; Serial ISR
;**********************
INT_TEST_RX_IRQ
	BTFSS	PIR1,RCIF	; test if serial recive irq
	GOTO	INT_TEST_TX_IRQ ; nope check next
; ***********************************************************************
;  RX_INT_HANDLER - handles the received commands on serial com 
RX_INT_HANDLER
	BTFSS	RCSTA,OERR	; test for overrun error
	GOTO	RX_CHECK_FRAMING
	; when overrun, uart will stop receving the continous 
	; recevive bit must then be reset
	BCF	RCSTA,CREN	; clear continous receve bit
	BSF	RCSTA,CREN	; and set it again
RX_CHECK_FRAMING
	BTFSS	RCSTA,FERR	; check from framing errors
	GOTO	RX_CHECK_BUFFER 
	; framing error do not store this byte
	; read rx reg and discard byte
	GOTO	RX_DISCARD_BYTE 
RX_CHECK_BUFFER	
	MOVF	RX_Buffer_Count,W	; test for space
	XORLW	RX_BUFFER_SIZE
	BTFSC	STATUS,Z
	GOTO	RX_BUFFER_FULL
	; Place the new char in the RxBuffer
	MOVF	RX_Buffer_InPtr,W	; get adress for indirect dressing
	MOVWF	FSR		; setup fsr
	MOVF	RCREG,W		; get received byte
	MOVWF	INDF		; and store it in buffer
	INCF	RX_Buffer_Count,F ; inc buffer counter
	; update pointers
	INC_BUFFER	RX_Buffer_InPtr,RX_Buffer,RX_BUFFER_SIZE
	BSF	GOT_ONE	; set flag 
	GOTO	INT_RX_END
RX_BUFFER_FULL
	; no room for more bytes, set overrun flag
	BSF	_BufferOverrun
	; and clear the last byte ( no room to store it ! )
RX_DISCARD_BYTE
	; optional an error flag could be set to indicate comm error.
	MOVF	RCREG,W		; read byte and discard
; END RX INT HANDLER
INT_RX_END
	BCF	PIR1,RCIF	; clear rx int flag
INT_TEST_TX_IRQ
	BTFSS	PIR1,TXIF	; test if serial transmit irq
	GOTO	INT_TEST_NXT
; ***********************************************************************
;  TX_INT_HANDLER - handles the tramission of bytes on serial com 
;
TX_INT_HANDLER
	MOVF	TX_Buffer_Count,W ; get number of bytes
	BTFSC	STATUS,Z	; buffer empty ?
	GOTO	TX_BUFFER_EMPTY
	
	MOVF	TX_Buffer_OutPtr,W ; get adress for indirect adressing
	MOVWF	FSR		; setup fsr
	MOVF	INDF,W		; get byte
	MOVWF	TXREG		; and put it in tx reg
	DECF	TX_Buffer_Count,F	; decrement buffer counter
	
	; update pointers
	INC_BUFFER	TX_Buffer_OutPtr,TX_Buffer,TX_BUFFER_SIZE
	GOTO	INT_TX_END
TX_BUFFER_EMPTY
	; no more bytes to send disable TX irq
	; code is to avoid bank switching ( using FSR )
	MOVLW	PIE1	; get adress for tx irq enable
	MOVWF	FSR	; setup fsr
	BCF	INDF,TXIE ; and disable tx irq
INT_TX_END
	BCF	PIR1,TXIF	; clear tx int flag
INT_TEST_NXT
	; test whatever left :-)


;**********************
; Context Restore
;**********************
INT_EXIT

	CLRF	STATUS		;ENSURE BANK0 RESTORE
	MOVF	FSR_SAVE,W
	MOVWF	FSR

	MOVF	PCLATH_SAVE,W
	MOVWF	PCLATH		; RESTORE PCLATH

	BCF	PORTB, 1	; reset interrupt indicator

	SWAPF	STATUS_TEMP,W
	MOVWF	STATUS
	SWAPF	W_TEMP,F
	SWAPF	W_TEMP,W

	RETFIE

;**********************************************************
; Main Program
;**********************************************************



START

INIT	; INIT ROUTINE	
;***************	
; setup delay
;***************
	BCF		TIMEOUT		; KEEP DELAY COUNTER STOPPED
	CLRF	TIME0		; INIT DELAY COUNTER
	CLRF	TIME1
			
;***************	
; setup uart
;***************
	CALL	INIT_UART
	; initialize buffers/pointers	
	CALL	INIT_BUFFERS

;***************	
; setup A/D
;***************
	Bank1
	CLRF	ANSEL		; configure Port A as digital I/O
	BSF	ANSEL,0		; RA0 = analog input
	bsf	TRISA,0		; PORTA0 = input, AN0
	movlw	B'01000000'	; ADFM=0 left justified, ADCS2=1 divide clock by 2,VCFG=00 - VDD VSS reference, XXXX  
	movwf	ADCON1
	Bank0
	movlw	B'10000001'	; ADCS=10=fosc/64(ADCS2=1), CHS=000=RA0, GO=0, X, ADON=1 A/D ON
	movwf	ADCON0

;***************	
; setup DTMF generator
;***************
	BCF DTMF_GEN_ON		; stop dtmf generator

;***************	
; setup DTMF DETECTOR
;***************
	BSF	DTMF_DONE	; STOP DTMF detector
	movlw	'-'
	movwf	TEMP_VAL
	movlw	1
	movwf	TEMP_TIMES
	bcf		DTMF_RECOVER

;*************************
; setup timer2 and PWM and PORTB
;*************************
	CLRF	AccLH
	CLRF	AccHH	; CLEAR High Freq Generator accumulator
	CLRF	AccLL
	CLRF	AccHL	; CLEAR Low Freq Generator accumulator

	BANKSEL PR2	;(bank 1)
	MOVLW	B'00111111'
	MOVWF	PR2	; 78.12Khz PWM with 20Mhz oscillator

	BANKSEL	CCPR1L	;(bank 0)
	MOvLw	B'00100000'
	MOVLW	CCPR1L	; initial PWM value = 128
	BCF CCP1CON,5
	BCF CCP1CON,4
	
	clrf PORTB		; CLEAR PORTB
	; 1=in, 0=out
	movlw	B'11000100'	;port B 7,6 in, 5TxOUT,4 out,  3  OUT,2RxIN, 1out, 0 out
	BANKSEL TRISB	;(bank 1)
	movwf	TRISB

	BANKSEL T2CON	;(bank 0)	
	MOVLW	B'00111000'	; set Timer2 prescaler 1/1, post scaler 1/8
	MOVWF	T2CON

	;BANKSEL CCP1CON	;(bank 0)
	; configure CCP1CON for PWM
	MOVLW	B'00001111'
	IORWF	CCP1CON,F	; set last four bits

	; reset TMR2IF, enable interrupts
	;BANKSEL PIR1	;(bank 0)
	BCF PIR1, TMR2IF
	BANKSEL	PIE1	;(bank 1)	
	BSF	PIE1, TMR2IE
	BANKSEL INTCON	;(bank 0)

; Start the interrupts
	BSF	INTCON,GIE	; global int
	BSF	INTCON,PEIE	; Peripherals int
	
	BSF	T2CON,TMR2ON	; start Timer2, bank0



;*********************************
; MAIN LOOP	
;*********************************
MAIN:


	; send a wellcome string to the serial port
	movlw	LOW linie1                          
	movwf	XcomA                          
	movlw	HIGH linie1                          
	movwf	XcomB                         
	call	ser_rom  ;send str to serial

	MOVLW	"+"
	Call	DTMF_digit ; 1000hz bip

	movlw	LOW linie2                          
	movwf	XcomC                          
	movlw	HIGH linie2                          
	movwf	XcomB                         
	call	DTMF_rom  ;send string linie2 to DTMF



ECHO_SERIAL
	; echo chars received to the serial port
	CALL RX_GET_BUFFER
	BTFSC	STATUS, Z	; or test for zero on return
	GOTO	ECHO_1
	movwf	temp1
	CALL TX_ADD_BUFFER	; SEND CHAR TO SERIAL

	movf	temp1,W		; send char to dtmf generator
	CALL 	DTMF_digit

ECHO_1
	CALL	DETECT_DTMF	; START DTMF DETECTOR
	btfss	DTMF_DETECTED
	goto nonewdigit

	
; new digit detected

		; 5 sec timer
		;DISABLE_IRQ
		MOVLW	.188
		MOVWF	TIME0
		MOVLW	.190
		MOVWF	TIME1
		BCF	TIMEOUT	; start 5 sec delay
		;ENABLE_IRQ
	bsf	Temp_Flag

	; print last digit
	movf	DTMF_RESULT, W
	call	TX_ADD_BUFFER

	goto ECHO_SERIAL


nonewdigit	; no new dtmf digit detected
	;check timeout
	
	btfss	Temp_Flag
	GOTO DTMF_digit_timeout	; wait for Temp_Flag=1
	BTFSS	TIMEOUT
	GOTO DTMF_digit_timeout	; wait for TIMEOUT=1
	; print CRLF
	bcf	Temp_Flag
	movlw	0x0d
	call	TX_ADD_BUFFER
	movlw	0x0a
	call	TX_ADD_BUFFER	
DTMF_digit_timeout
	goto ECHO_SERIAL	; no new dtmf digit detected


;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;; Send W hex to serial port + 1 space, uses XcomB, XcomC
PRINTWHEX
	; high nibble, low nibble, space
	MOVWF	XcomB	; save w

	swapf	XcomB, W
	ANDLW	0x0F
	movwf	XcomC
	sublw	9		; test if char = ABCDEF
	movf	XcomC, W
	btfss	STATUS, C	; skip if 0-9
	addlw	.7 ;('A'-'0')-10
	addlw	'0'
	call	TX_ADD_BUFFER ; print high nibble

	movf	XcomB,W
	ANDLW	0x0F
	movwf	XcomC
	sublw	9		; test if char = ABCDEF
	movf	XcomC, W
	btfss	STATUS, C	; skip if 0-9
	addlw	.7	;('A'-'0')-10
	addlw	'0'
	call	TX_ADD_BUFFER ; print low nibble

	movlw	' '
	call	TX_ADD_BUFFER ; print space
	Return			
;************************************************************************
;SUBROUTINES
;************************************************************************

;************************************************************************

; TO START DTMF DETECTOR - CALL DETECT_DTMF - this will return in ~130 timer cycles
; if DTMF_DETECTED=1 on return one NEW DTMF digit was detected in DTMF_RESULT or '-' for pause
;************************************************************************
;START DTMF DECODER
DETECT_DTMF
	;BSF	DTMF_DONE		; STOP DTMF INT ROUTINE

; clear the dtmf detector values
	MOVF	FSR,W
	MOVWF	FSR_SAVE_DTMF		; SAVE FSR
	MOVLW	(Low A697SIN)-1		; start -1
	MOVWF	FSR
TEMPXX1
	INCF	FSR,F
	CLRF	INDF
	MOVF	FSR,W
	XORLW	LOW A1633COS2		; CLEAR RAM FROM A697SIN-A1633COS2!!!
	BTFSS	STATUS,Z
	GOTO	TEMPXX1
		; table read pointer
	CLRF	TABLECOUNTER
	CLRF	RESULT1		; CLEAR RESULT DIGIT
	MOVF	FSR_SAVE_DTMF, W
	MOVWF	FSR		; RESTORE FSR
	;BCF		DTMF_RECOVER	;
	
	CLRF	BITCHANGES	; CLEAR THE COUNTER
	BCF		DTMF_DONE		; CLEAR DONE, START DTMF ISR ROUTINE
	
DETECT1
	;wait for the ISR part to end
	btfss 	DTMF_DONE
	goto	DETECT1
	;got one dtmf digit or '-'
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; DTMF DECISION ALGORITHM
; compute absolute value  acc = ABS(acc)
	
; FIRST LOOK AT THE BITCHANGES COUNTER > 10
;	MOVF	BITCHANGES,W
;	SUBLW	5	; treshold-w--> W, carry=0 on borrow,
						; W=31 carry=0, W=30 carry=1, W=29 carry=1!
						; therefore the bit is 0 in RESULT for W > treshold
;	BTFSS	STATUS, C
;	GOTO	STARTTEST
	; GOT A QUAIET FRAME - JUST SKIP THE REST
;	MOVLW	'Q'
;	GOTO	SENDIT

STARTTEST
	MOVLW	LOW A697SIN	
	MOVWF	FSR
TESTFORNEG
	BTFSC	INDF,7
	GOTO	NEG
	GOTO	NEXT
NEG
;	SUBTRACT F FROM 0

	MOVF	INDF,W
	SUBLW	0
	MOVWF	INDF
NEXT
	INCF	FSR,F
	MOVF	FSR,W
	XORLW	LOW A1633COS2+1	; for 1X and 2X bins the end is A1633COS2
	BTFSS	STATUS,Z
	GOTO	TESTFORNEG

; add acumulator results for sin and cos,  results in cos , sin=0

	MOVLW	LOW A697SIN	
	MOVWF	FSR
MORERESULTS
	MOVF	INDF,W
	CLRF	INDF
	INCF	FSR,F
	ADDWF	INDF,F
	MOVF	FSR,W
	INCF	FSR,F
	XORLW	LOW A1633COS2 ; for 1X and 2X bins the end is A1633COS2
	BTFSS	STATUS,Z
	GOTO	MORERESULTS

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; compare acc with treshold1X
; for 1X bins

	MOVLW	LOW A697COS	; first result
	MOVWF	FSR
TEMPX1L
	MOVF	INDF,W
	SUBLW	treshold1XL	; treshold-w--> W, carry=0 on borrow,
						; W=31 carry=0, W=30 carry=1, W=29 carry=1!
						; therefore the bit is 0 in RESULT for W > treshold
	RRF		RESULT,F
	INCF	FSR,F
	INCF	FSR,F
	MOVF	FSR,W
	XORLW	LOW A941COS+2
	BTFSS	STATUS,Z
	GOTO 	TEMPX1L		
	
	MOVLW	LOW A1209COS	; first result
	MOVWF	FSR
TEMPX1H
	MOVF	INDF,W
	SUBLW	treshold1XH	; treshold-w--> W, carry=0 on borrow,
						; W=31 carry=0, W=30 carry=1, W=29 carry=1!
						; therefore the bit is 0 in RESULT for W > treshold
	RRF		RESULT,F
	INCF	FSR,F
	INCF	FSR,F
	MOVF	FSR,W
	XORLW	LOW A1633COS+2
	BTFSS	STATUS,Z
	GOTO 	TEMPX1H		

	COMF	RESULT,F	; complement result>> bit is set if A...COS > TRESHOLD

; RESULT bits are   1633/1477/1336/1209/941/852/770/697 FOR VALUE>Treshold


;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; compare acc with treshold2X
; for 2X bins

	MOVLW	LOW A697COS2	; first result
	MOVWF	FSR
TEMPX2L
	MOVF	INDF,W
	SUBLW	treshold2XL	; treshold-w--> W, carry=0 on borrow,
						; W=31 carry=0, W=30 carry=1, W=29 carry=1!
						; therefore the bit is 0 in RESULT for W > treshold
	RRF		RESULT2X,F
	INCF	FSR,F
	INCF	FSR,F
	MOVF	FSR,W
	XORLW	LOW A941COS2+2
	BTFSS	STATUS,Z
	GOTO 	TEMPX2L


	MOVLW	LOW A1209COS2	; first result
	MOVWF	FSR
TEMPX2H
	MOVF	INDF,W
	SUBLW	treshold2XH	; treshold-w--> W, carry=0 on borrow,
						; W=31 carry=0, W=30 carry=1, W=29 carry=1!
						; therefore the bit is 0 in RESULT for W > treshold
	RRF		RESULT2X,F
	INCF	FSR,F
	INCF	FSR,F
	MOVF	FSR,W
	XORLW	LOW A1633COS2+2
	BTFSS	STATUS,Z
	GOTO 	TEMPX2H
		
	;COMF	RESULT2X,F	; complement result>> bit is set if A...COS > TRESHOLD

	movf	RESULT2X, W	; 2X frequencies mask is 0 for 2X freq bin > treshold
	andwf	RESULT, F	; apply 2X frequencies mask over 1X RESULT

; RESULT2 bits are for 2X frequencies  1633/1477/1336/1209/941/852/770/697 FOR VALUE>Treshold

; 	translate to ASCII
;**********************************************
; GOT ONE CHARACTER, CONVERT IT TO ASCII....
;**********************************************
	MOVF	RESULT,W	
	XORLW	B'00010001'
	BTFSC	STATUS,Z
	GOTO	GOTCHA1
	MOVF	RESULT,W
	XORLW	D'33'
	BTFSC	STATUS,Z
	GOTO	GOTCHA2
	MOVF	RESULT,W
	XORLW	D'65'
	BTFSC	STATUS,Z
	GOTO	GOTCHA3
	MOVF	RESULT,W
	XORLW	D'18'
	BTFSC	STATUS,Z
	GOTO	GOTCHA4
	MOVF	RESULT,W
	XORLW	D'34'
	BTFSC	STATUS,Z
	GOTO	GOTCHA5
	MOVF	RESULT,W
	XORLW	D'66'
	BTFSC	STATUS,Z
	GOTO	GOTCHA6
	MOVF	RESULT,W
	XORLW	D'20'
	BTFSC	STATUS,Z
	GOTO	GOTCHA7
	MOVF	RESULT,W
	XORLW	D'36'
	BTFSC	STATUS,Z
	GOTO	GOTCHA8
	MOVF	RESULT,W
	XORLW	D'68'
	BTFSC	STATUS,Z
	GOTO	GOTCHA9
	MOVF	RESULT,W
	XORLW	D'40'
	BTFSC	STATUS,Z
	GOTO	GOTCHA0
	MOVF	RESULT,W
	XORLW	D'72'
	BTFSC	STATUS,Z
	GOTO	GOTCHAPOUND
	MOVF	RESULT,W
	XORLW	D'24'
	BTFSC	STATUS,Z
	GOTO	GOTCHASTAR
	MOVF	RESULT,W	
	XORLW	B'10000001'
	BTFSC	STATUS,Z
	GOTO	GOTCHAA
	MOVF	RESULT,W	
	XORLW	B'10000010'
	BTFSC	STATUS,Z
	GOTO	GOTCHAB
	MOVF	RESULT,W	
	XORLW	B'10000100'
	BTFSC	STATUS,Z
	GOTO	GOTCHAC
	MOVF	RESULT,W	
	XORLW	B'10001000'
	BTFSC	STATUS,Z
	GOTO	GOTCHAD
; GOT ONLY TRASH...
	MOVLW	'-'
	GOTO	SENDIT
; CONVERT ASCII	
	
GOTCHAPOUND
	MOVLW	H'23'
	GOTO	SENDIT
GOTCHASTAR
	MOVLW	H'2A'
	GOTO	SENDIT
GOTCHA1
	MOVLW	H'31'
	GOTO	SENDIT
GOTCHA2
	MOVLW	H'32'
	GOTO	SENDIT
GOTCHA3
	MOVLW	H'33'
	GOTO	SENDIT
GOTCHA4

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -