السلام عليكم ورحمة الله وبركاته
اعضاء منتدانا الغالي
تقبل الله طاعتكم جميعا ان شاء الله تعالى
اريد المساعدة في التعديل على برنامج مكتوب بلغة الاسمبلي وذلك لانه ليس لدي اي خلفيه فيه
; DTMFCTRL.ASM
; Current Version: 0.00
;
; PIC Based software DTMF decoder which controls
; 8 outputs. Command syntax: #ABCD#XY*
;
; - #ABCD# stands for a 4 digit code surrounded bij #
; - X indicates the channel (1..8)
; - Y indicates ON (1) of OFF (0)
;
; Created by Wim de Vree PE1GRL - pe1grl*amsat.org
;
; Brief overview:
; This program decodes DTMF tones using the Goertzel algorithm.
; Heavily based on the code from Radu Constantinescu
; which got the idea from David Hedly. Also thanks to
; Scott Dattalo who wrote a nice decription on the web.
; After the correct sequence is received on of the PORTB
; data lines is set or reset.
;
; Revision History
;----------------------------------------------------------------------
; 2011-01-25 0.00 Initial creation, Based on the RS232 decoder
; 2011-01-26 0.10 Completed program, removed diagnostic RS232 stuff
; 2011-01-27 0.20 Some optimalisation to fit in a 1K Flash PIC
; now using 1012 out of 1024 program words
;
; 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
;
; RA0 OUT pin 17 Interrupt Indicator ( =1 durring interrupt)
; RA2 Comparator IN pin + DTMF/FSK INPUT (Comparator)
; RA1 Comparator IN pin - Grounded
; RB 8 output channels
;
LIST P=PIC16F628A, F=INHX8M
__CONFIG _CP_OFF & _WDT_OFF & _HS_OSC & _LVP_OFF & _PWRTE_ON
; 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 <p16f628A.inc>
XTAL_FREQ EQU 20000000 ; OSC freq in Hz
#include <rxtables.asm> ; Only need the decode tables
ERRORLEVEL -302 ; disable warnings about not in bank0
CBLOCK 0x20
PCLATH_SAVE: 1 ; Interrupt save vars
STATUS_TEMP: 1
FSR_SAVE: 1
TempH: 1 ; Used in the DTMF Detector ISR for Temp Lowtemplate
TempL: 1 ; Used 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
;****************************
Flags:1 ; flags for serial comunincation
Temp:1 ; temp byte ONLY to be used locally and no calls !
;****************************
; DELAY ROUTINES VARIABLES
;****************************
TIME0: 1 ;DELAY COUNTER LSB
TIME1: 1 ;DELAY COUNTER MSB
;****************************
; DTMF DECODER ROUTINES VARIABLES
;****************************
A697SIN, A697COS:1 ; ACCUMULATOR for 697 Hz sin
A770SIN, A770COS:1 ; ACC
A852SIN, A852COS:1 ; ACC
A941SIN, A941COS:1 ; ACC
A1209SIN,A1209COS:1 ; ACC
A1336SIN,A1336COS:1 ; ACC
A1447SIN,A1447COS:1 ; ACC
A1633SIN,A1633COS:1 ; ACC
; double frequency bins
A697SIN2, A697COS2:1 ; ACCUMULATOR for 697 Hz sin
A770SIN2, A770COS2:1 ; ACC
A852SIN2, A852COS2:1 ; ACC
A941SIN2, A941COS2:1 ; ACC
A1209SIN2,A1209COS2:1 ; ACC
A1336SIN2,A1336COS2:1 ; ACC
A1447SIN2,A1447COS2:1 ; ACC
A1633SIN2,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 '-'
Uidx ; Index when hunting the unlock code
Expected ; Expected character
Channel ; Received channel
Action ; ON or OFF
ChannelMask
ENDC
; ************* Bit variable definitions ***************************
#define TIMEOUT Flags,1 ; timeout flag
#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
#define ACTION_ON Flags,2 ; =1: Turn on, else turn off
;***********************************************
;Shared Ram
;***********************************************
CBLOCK 0x78 ; variables for all the RAM pages, skip 70 for ICD
W_TEMP: 1 ; int W save/shared Ram
ENDC
;****************************
ORG 0x00
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 PORTA, 0 ; set interrupt indicator
movf PCLATH,W ; SAVE PCLATH
movwf PCLATH_SAVE
movf FSR, W
movwf FSR_SAVE
btfss PIR1,TMR2IF ; TMR2 Overflow Check ?
goto $ ; NO, hang system with led ON
;**********************
;Timer 2 ISR
;**********************
btfsc DTMF_DONE
goto T2ISR_1 ; Skip Comparator input if dtmf detect is off
clrf BYTE_DTMF ; input = 0
btfsc CMCON,C2OUT ; Output of comparator
comf BYTE_DTMF, F ; input = 1
T2ISR_1
bcf PIR1,TMR2IF ; RESET TIMER 2 INT FLAG
;**********************
; 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
skpnc
addlw 1
movwf PCLATH ; if the table will be alligned to a 256 boundary this will nor be necessary
movf TABLECOUNTER,W ; read 1X template
call LOWBAND ; read table
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
clrc ; 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
;*****************************
;
;Get the expected Highband Bits
;
;*****************************
movlw low HIGHBAND
addwf TABLECOUNTER,W
movlw high HIGHBAND
skpnc
addlw 1
movwf PCLATH
movf TABLECOUNTER,W ; read 1X template
call HIGHBAND
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
clrc
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
bnc 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
bnc SKIPHI1X
movlw LOW A1209SIN
movwf FSR ;ACCUMULATOR ADDR
movlw 8
movwf SAMPLEBIT
COMPAREBITH
rlf HIGHTEMPLATE,F
bnc 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
bnc 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
bnc 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
movlw low A1209SIN2
movwf FSR ;ACCUMULATOR ADDR
movlw .8
movwf SAMPLEBIT
COMPAREBITH2
rlf TempH,F
bnc 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
skpnz
bsf DTMF_DONE
DTMF_ISR_END
;**********************
; Delay ISR
;**********************
; TIME1:TIME0 counter will be decremented each Timer2 Tick,
; TIMEOUT flag will be set when counter reaches zero.
DELAY_ISR
btfsc TIMEOUT ; CHECK IF NOT TIMEOUT
goto DELAY_ISR_END
decf TIME0, F ; DECREMENT TIMEOUT COUNTER
bnz DELAY_ISR_END ; TIME0<>0
decf TIME1, F
skpnz
bsf TIMEOUT ; TIME1==0, SET TIMEOUT=TRUE
DELAY_ISR_END
;**********************
; Context Restore
;**********************
INT_EXIT
clrf STATUS ; ENSURE BANK0 RESTORE
movf FSR_SAVE,W
movwf FSR
movf PCLATH_SAVE,W
movwf PCLATH ; RESTORE PCLATH
bcf PORTA, 0 ; 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 Comparator input on AN1/AN2
;***************
bsf STATUS,RP0 ; Switch to Bank 1
movlw b'11111110' ; PortA: only RA0 output
movwf TRISA
bcf STATUS,RP0 ; Back to Bank 0
bcf PORTA,0 ; Led OFF
movlw b'00000101' ; One comparator used (RA1/RA2)
movwf CMCON
;***************
; 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 PORTB ; CLEAR PORTB
bsf STATUS,RP0 ; (bank 1)
clrf TRISB ; PortB all outputs
movlw B'00111111' ; 78.12Khz PWM with 20Mhz crystal
movwf PR2 ; NOTE: PWM module is OFF
bcf STATUS,RP0 ; (bank 0)
movlw B'00111000' ; set Timer2 prescaler 1/1, post scaler 1/8
movwf T2CON ; Interrupt (sample) rate is 9767Hz
; reset TMR2IF, enable interrupts
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:
; Wait for a hash which starts the scan for the lock code
WaitStartHash:
clrf Uidx ; Start of unlockcode
WaitUnLock:
movlw high GetUnLockChar
movwf PCLATH
movlw low UnlockCode
addwf Uidx,W
call GetUnLockChar
clrf PCLATH
andlw 0xFF
bz CodeReceived ; Got complete unlockcode
movwf Expected ; This is the char we expect
call GetDTMFWithTimeOut
btfsc TIMEOUT
goto WaitStartHash ; TimeOut, restart
movfw DTMF_RESULT
xorwf Expected,W
bnz WaitStartHash ; Unexpected char detected
incf Uidx,F
goto WaitUnLock ; Do Next char in unlockcode
CodeReceived: ; The unlock code was rx'd
call GetDTMFWithTimeOut ; Channel Number
btfsc TIMEOUT
goto WaitStartHash ; TimeOut, restart
movfw DTMF_RESULT
movwf Channel
call GetDTMFWithTimeOut ; Channel Status
btfsc TIMEOUT
goto WaitStartHash ; TimeOut, restart
movfw DTMF_RESULT
movwf Action
call GetDTMFWithTimeOut ; Terminator
btfsc TIMEOUT
goto WaitStartHash ; TimeOut, restart
movfw DTMF_RESULT
xorlw '*'
bnz WaitStartHash ; No Match on terminator
; Check if we have a valid CHANNEL (1..8)
movlw '1' ; Check if >= 1
subwf Channel,W
bnc WaitStartHash ; No: Invalid Channel
movlw '9' ; Check if < 8
subwf Channel,W
bc WaitStartHash ; No: Invalid Channel
movlw '0'
subwf Channel,F ; Channel now 1..8
; Check if we have a valid ACTION (0..1)
movlw '0' ; Check if >= 0
subwf Action,W
bnc WaitStartHash ; No: Invalid Action
movlw '2' ; Check if < 2
subwf Action,W
bc WaitStartHash ; No: Invalid Action
bcf ACTION_ON
movlw '0'
xorwf Action,F ; Action now 0 or 1
skpz
bsf ACTION_ON
; Get the mask for the channel
clrf ChannelMask
setc
_gm rlf ChannelMask,F
decfsz Channel,F
goto _gm
comf ChannelMask,W
andwf PORTB,W ; Channel now 0
btfsc ACTION_ON ; Turn ON ?
iorwf ChannelMask,W ; Yep
movwf PORTB ; Place DTMF command on I/O port
goto WaitStartHash ; Wait for next command
;************************************************* ***********************
;SUBROUTINES
;************************************************* ***********************
;Wait until a single DTMF character is received
;GetDTMF:
; call DETECT_DTMF ; START DTMF DETECTOR
; btfss DTMF_DETECTED
; goto GetDTMF
; return
;Wait until a single DTMF character is received
;But return after a timeout
GetDTMFWithTimeOut:
movlw .113 ; Max 3 seconds wait
movwf TIME0
movlw .114
movwf TIME1
bcf TIMEOUT ; start 3 sec delay
waitDTMF
call DETECT_DTMF ; START DTMF DETECTOR
btfsc DTMF_DETECTED
return ; Got a DTMF tone
btfss TIMEOUT
goto waitDTMF ; No time out, try again
return ; Timed Out
;************************************************* ***********************
; 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
; 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!!!
bnz TEMPXX1
; table read pointer
clrf TABLECOUNTER
clrf RESULT1 ; CLEAR RESULT DIGIT
movf FSR_SAVE_DTMF, W
movwf FSR ; RESTORE FSR
bcf DTMF_DONE ; CLEAR DONE, START DTMF ISR ROUTINE
DETECT1 btfss DTMF_DONE ; wait for the ISR part to end
goto DETECT1
; got one dtmf digit or '-'
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; DTMF DECISION ALGORITHM
; compute absolute value acc = ABS(acc)
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
bnz 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
bnz 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
bnz 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
bnz 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
bnz 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
bnz TEMPX2H
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'
bz GOTCHA1
movf RESULT,W
xorlw D'33'
bz GOTCHA2
movf RESULT,W
xorlw D'65'
bz GOTCHA3
movf RESULT,W
xorlw D'18'
bz GOTCHA4
movf RESULT,W
xorlw D'34'
bz GOTCHA5
movf RESULT,W
xorlw D'66'
bz GOTCHA6
movf RESULT,W
xorlw D'20'
bz GOTCHA7
movf RESULT,W
xorlw D'36'
bz GOTCHA8
movf RESULT,W
xorlw D'68'
bz GOTCHA9
movf RESULT,W
xorlw D'40'
bz GOTCHA0
movf RESULT,W
xorlw D'72'
bz GOTCHAPOUND
movf RESULT,W
xorlw D'24'
bz GOTCHASTAR
movf RESULT,W
xorlw B'10000001'
bz GOTCHAA
movf RESULT,W
xorlw B'10000010'
bz GOTCHAB
movf RESULT,W
xorlw B'10000100'
bz GOTCHAC
movf RESULT,W
xorlw B'10001000'
bz GOTCHAD
movlw '-' ; GOT ONLY TRASH...
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
MOVLW H'34'
GOTO SENDIT
GOTCHA5
MOVLW H'35'
GOTO SENDIT
GOTCHA6
MOVLW H'36'
GOTO SENDIT
GOTCHA7
MOVLW H'37'
GOTO SENDIT
GOTCHA8
MOVLW H'38'
GOTO SENDIT
GOTCHA9
MOVLW H'39'
GOTO SENDIT
GOTCHA0
MOVLW H'30'
GOTO SENDIT
GOTCHAA
MOVLW 'A'
GOTO SENDIT
GOTCHAB
MOVLW 'B'
GOTO SENDIT
GOTCHAC
MOVLW 'C'
GOTO SENDIT
GOTCHAD
MOVLW 'D'
GOTO SENDIT
SENDIT
movwf RESULT1 ; PLACE RECEIVED CHAR IN RESULT1
;newline
; debug print: result of every decode
; movf RESULT1, W ; result of ONE decode
; call SendChar
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; DECISION ALGORITHM : A VALUE MUST BE DETECTED AT LEAST 2 TIMES
; BEFORE IS CONSIDERED VALID
; a missing value is accepted if it was detected at lest 2 times before
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
movf RESULT1, W ; use RESULT1 ASCII result
xorwf TEMP_VAL,W ; COMPARE RESULT WITH TEMP_VAL
bz DECI1 ; ==
; RESULT1<>TEMP_VAL
decf TEMP_TIMES, F
bnz keepvalue ;<>0
; reset value
goto resetvalue
keepvalue ; keep old RESULT1 value, but temp_times=1 - this will allow 1 missing value
; reset temp times to 1
movlw 1
movwf TEMP_TIMES
bsf DTMF_RECOVER ; signal recover
; exception when temp_val='-' ==> reset to RESULT1
movlw '-'
xorwf TEMP_VAL, W ; compare '-' with result1
bnz keepvalue1 ; <>0
; reset value
resetvalue
movlw 1
movwf TEMP_TIMES
movf RESULT1, W
movwf TEMP_VAL
bcf DTMF_RECOVER ; no recover
keepvalue1
; no new digit detected
bcf DTMF_DETECTED
return
; RESULT1==TEMP_VAL
DECI1
incf TEMP_TIMES, F ; INC TEMP_TIMES
skpnz
decf TEMP_TIMES, F ; if temp_times=0 decrement to 255
; check if TEMP_VAL='-'
movlw '-'
xorwf RESULT1, W ; compare '-' with result1 - if so temp_times=1 and return
bnz DECI3 ; <>0
movlw 1
movwf TEMP_TIMES
goto keepvalue1
DECI3
movlw .2 ; NUMBER OF TIMES DETECTED BEFORE DECIDE FOR A DIGIT!
xorwf TEMP_TIMES,W
bnz keepvalue1 ; <> no new digit
; GOT ONE VALUE MORE TIMES !!!!!!!!!!!
btfss DTMF_RECOVER ; test for recover
goto DECI2 ; no recover
bcf DTMF_RECOVER ; reset recover bit and return with no new digit
goto keepvalue1 ; no new digit
DECI2 ; exit with new digit
; return result
movf RESULT1, W
movwf DTMF_RESULT
bsf DTMF_DETECTED
return
GetUnLockChar movwf PCL
UnlockCode: dt "#3479#",0 ; DTMF ACCESS CODE
UnLockCodeEnd:
IF ( (GetUnLockChar & 0x0FF) >= (UnLockCodeEnd & 0x0FF) )
MESSG "Warning - User Definded: UNLOCK CODE crosses page boundary"
ENDIF
END
البرنامج عبارة عن تحويل pic 16f628 الى شريحة dtmf ولكن الخرج يكون بكود سري #3479# وبعدها الرقم المراد تشغيلو وبعد اما 1 او 0 ليوظف هل تشغيل ام اطفاء وبعدها نجمة
البرنامج يعمل ولكن المطوب التعديل عليه هو جعل الخرج عن طريق ادخال رقم الخرج وواحد ام صفر لتحديد تشغيل ام اطفاء وبعده مثلا # فقط دون رقم سري