; dtmfee.asm - tone decoder with relay control. ; reads output from an 8870 DTMF decoder and controls a bank of relays. ; Code sequences "*11#" through to "*18#" turn on the corresponding relay ; code sequence "*10#" turns on all relays ; Code sequences "*21#" through to "*28#" turn off the corresponding relay ; Code sequence "*20#" turns off all relays ; Codes "*?9#" through "*?D#" are ignored. ; The last relay state is stored in EEPROM. When the circuit is powered up the relays are set to this state list p=16f84a include "p16f84a.inc" __FUSES _CP_OFF & _XT_OSC & _WDT_OFF & _PWRTE_ON relays equ 10 mfcode equ 11 cntdown equ 12 timeout equ 13 slocnt1 equ 14 slocnt2 equ 15 numa equ 16 numb equ 17 numc equ 18 numd equ 19 ; EEPROM locations for data... ; EETRUE equ h'00' EECURR equ h'01' org 0000 ;tell assembler to start at 000H init goto start org 0004 ;interrupt vector rtc_interrupt decfsz slocnt1,F ;decrement 1st prescaler goto rtc_int_1 decfsz slocnt2,F ;decrement 2nd prescaler goto rtc_int_1 bcf relays,4 ;turn relay 6 off bcf PORTB,4 rtc_int_1 decfsz cntdown,F ;count down and skip next if = 0 goto counting ;still counting if not reached zero bsf timeout,0 ;set timed out bit bcf INTCON,2 ;clear interrupt flag retfie ;return counting bcf timeout,0 ;clear timed out bit bcf INTCON,2 ;clear interrupt flag retfie ;return ; subroutines wait_strobe btfsc timeout,0 ;see if timed out goto set_z ;set Z flag if timeout ocurred btfss PORTA,4 ;see if Strobe is active on RA4 goto wait_strobe ;loop until it is movfw PORTA ;retreive the code from the 8870 movwf mfcode ;store it in mfcode bcf mfcode,4 ;ensure strobe isn't seen as data bcf STATUS,2 ;return with Z=0 if tone decoded return set_z bsf STATUS,2 ;return with Z=1 if timed out waiting return wait_no_strobe btfsc PORTA,4 ;see if strobe is active on RA4 goto wait_no_strobe ;loop until it isn't return start_timer movlw H'54' ;software prescaler for 7 seconds movwf cntdown return ; Start of setup and decode routines: start movlw B'00100000' ;select register page 1 movwf STATUS clrf TRISB ;set all port B pins to output mode movlw B'00011111' ;set all port A pins to input mode movwf TRISA movlw B'10000111' movwf OPTION_REG ;sets: pull-up on port B OFF ; RTCC counts internal clock ; prescaler connected to RTCC ; prescaler divides by 256 ; (other bits unimportant) clrw ;clear the working register movwf STATUS ;switch back to register page 0 clrw call ReadEE btfss EEDATA,0 goto first movlw 1 call ReadEE goto cont2 first movlw 1 movwf EEADR movlw 1 movwf EEDATA call EEProg cont1 clrw cont2 movwf PORTB movwf relays clrf timeout movlw B'10100000' movwf INTCON ;global and RTCC interrupts enabled set_sec movlw H'01' ;put the 4 access codes into memory movwf numa ;note for a 0 the hex is H'0A' movlw H'02' movwf numb movlw H'03' movwf numc movlw H'04' movwf numd decode call wait_no_strobe ;start running when no tone present clrf timeout ;set timeout condition until later call wait_strobe ;wait for a tone to be received movlw H'0B' ;0B is the code for DTMF "*" subwf mfcode,W ;set zero flag if "*" was received btfsc STATUS,2 ;skip next if it was not a "*" goto got_star goto decode ;look for another one got_star call start_timer ;start time-out timer call wait_no_strobe ;wait for second tone call wait_strobe btfsc STATUS,2 ;abort if timed out goto decode movf numa,W subwf mfcode,W ;set zero flag if second tone was 1 btfsc STATUS,2 ;skip next if it was not a 1 goto got_A goto get_# got_A call wait_no_strobe ;wait for third tone call wait_strobe btfsc STATUS,2 ;abort if timed out goto decode movf numb,W subwf mfcode,W ;set zero flag if second tone was 1 btfsc STATUS,2 ;skip next if it was not a 1 goto got_B goto get_# got_B call wait_no_strobe ;wait for third tone call wait_strobe btfsc STATUS,2 ;abort if timed out goto decode movf numc,W subwf mfcode,W ;set zero flag if second tone was 1 btfsc STATUS,2 ;skip next if it was not a 1 goto got_C goto get_# got_C call wait_no_strobe ;wait for third tone call wait_strobe btfsc STATUS,2 ;abort if timed out goto decode movf numd,W subwf mfcode,W ;set zero flag if second tone was 1 btfsc STATUS,2 ;skip next if it was not a 1 goto got_D goto get_# got_D call wait_no_strobe ;wait for third tone call wait_strobe btfsc STATUS,2 ;abort if timed out goto decode movlw H'01' subwf mfcode,W ;set zero flag if second tone was 1 btfsc STATUS,2 ;skip next if it was not a 1 goto got_1 movlw H'02' subwf mfcode,W ;set zero flag if second tone was 0 btfsc STATUS,2 ;skip next if it was not a 0 goto got_2 goto get_# ;wait for # to end invalid sequence ; to reach here, the tone sequence "*1" has been found, now decode request ; according to the next 2 tones but don't action it until a "#" is seen. got_1 call wait_no_strobe call wait_strobe ;wait for third tone btfsc STATUS,2 ;abort if timed out goto decode call wait_no_strobe ;wait for tone to finish movf mfcode,W ;pick up keyed digit addwf PCL,F ;jump ahead to vector goto decode ;5D (mf code 0000) goto got_11 goto got_12 goto got_13 goto got_14 goto got_15 goto got_16 goto got_17 goto got_18 goto decode goto got_10 goto decode ;* goto decode ;# goto decode ;5A goto decode ;5B goto decode ;5C (mf code 1111) got_10 movlw B'11111111' ;all outputs on movwf relays goto get_# got_11 bsf relays,0 ;set output 1 on goto get_# got_12 bsf relays,1 ;set output 2 on goto get_# got_13 bsf relays,3 ;set output 3 on goto get_# got_14 bsf relays,2 ;set output 4 on goto get_# got_15 bsf relays,5 ;set output 5 on goto get_# got_16 bsf relays,4 ;set output 6 on goto get_# got_17 bsf relays,6 ;set output 7 on goto get_# got_18 bsf relays,7 ;set output 8 on goto get_# ; to reach here, the tone sequence "*2" has been found, now decode request ; according to the next 2 tones but don't action it until a "#" is seen. got_2 call wait_no_strobe call wait_strobe ;wait for sixth tone btfsc STATUS,2 ;abort if timed out goto decode call wait_no_strobe ;wait for tone to finish movf mfcode,W ;pick up keyed digit addwf PCL,F ;jump ahead to vector goto decode ;5D (mf code 0000) goto got_21 goto got_22 goto got_23 goto got_24 goto got_25 goto got_26 goto got_27 goto got_28 goto decode goto got_20 goto decode ;* goto decode ;# goto decode ;5A goto decode ;5B goto decode ;5C (mf code 1111) got_20 movlw B'0000000' movwf relays ;set all outputs off goto get_# got_21 bcf relays,0 ;set output 1 off goto get_# got_22 bcf relays,1 ;set output 2 off goto get_# got_23 bcf relays,3 ;set output 3 off goto get_# got_24 bcf relays,2 ;set output 4 off goto get_# got_25 bcf relays,5 ;set output 5 Off goto get_# got_26 bcf relays,4 ;set output 6 Off goto get_# got_27 bcf relays,6 ;set output 7 Off goto get_# got_28 bcf relays,7 ;set output 8 Off goto get_# get_# call wait_strobe ;wait for 7th tone btfsc STATUS,2 ;abort if timed out goto decode movlw H'0C' ;0C is the DTMF code for "#" subwf mfcode,W ;if # received set Z flag btfsc STATUS,2 ;skip next if not a # goto got_# call wait_no_strobe goto get_# ;only # is valid, loop until found ;or timeout got_# call wait_no_strobe ;wait for the tone to finish movfw relays ;use the "relays" variable to set RB movwf PORTB movlw 1 movwf EEADR movf relays,0 movwf EEDATA call EEProg goto decode ;all done, check for new sequence EEProg bsf STATUS,RP0 ;select bank 1 bcf INTCON,GIE ;disable interrupts bsf EECON1,WREN ;enable EEPROM write movlw h'55' movwf EECON2 ;write 55 movlw h'AA' movwf EECON2 ;write AA bsf EECON1,WR ;start write bcf EECON1,WREN ;disable write EEPLoop nop btfsc EECON1,WR ;is write cycle complete? goto EEPLoop ;wait for write to finish ret bsf INTCON,GIE ;enable interrupts bcf STATUS,RP0 ;select bank 0 return ; Read EEPROM byte ; address is supplied in W on call, data is returned in EEDATA ; ReadEE movwf EEADR ;EEADR = w bsf STATUS,RP0 ;select bank 1 bsf EECON1,RD ;read EEPROM bcf STATUS,RP0 ;select bank 0 return retlw 'v' retlw '1' retlw '.' retlw '4' retlw '.' retlw 'W' retlw 'W' retlw '2' retlw 'R' retlw ' ' retlw 'm' retlw 'a' retlw 'y' retlw '2' retlw '0' retlw '0' retlw '5' end