;************************************************************************** ; FILE: elock.asm * ; CONTENTS: Touch Tone electronic combination lock * ; COPYRIGHT: MadLab Ltd. 2004 * ; AUTHOR: James Hutchby * ; UPDATED: 06/05/04 * ;************************************************************************** list p=12F629 #include "p12f629.inc" ; __config _INTRC_OSC_NOCLKOUT & _WDT_ON & _MCLRE_OFF & _PWRTE_ON & _BODEN_ON & _CP_OFF & _CPD_OFF __config _INTRC_OSC_NOCLKOUT & _WDT_ON & _MCLRE_OFF & _PWRTE_ON & _BODEN_ON & _CP_ON & _CPD_ON __idlocs h'EA10' errorlevel -207,-302,-305,-306 ;************************************************************************** ; * ; Specification * ; * ;************************************************************************** ; power-up self-test - LED flashes twice ; setup mode for 10s after power up ; setup mode allows relay activation period and user combination to be changed ; '**1' ... '**9', '**0' sets relay activation period in s (1 to 10) ; LED flashes 4 times when relay period changed ; current combination must be entered before user combination can be changed ; new combination must be verified by entering it again ; LED flashes 4 times after combination entered and verified ; maximum combination length = 10 (including star) ; failsafe combination update ; LED flashes briefly every few seconds while waiting for tone (after setup mode) ; valid tone indicated by short LED flash ; hashes are ignored, precede all combinations with hash(es) ; combinations always terminated with star ; LED flashes 4 times when correct combination entered ; relay activated and LED lit when correct combination entered ; default user combination is '1234*' ; master combination is 'XXXXXXXX*' (can't be changed, not made public) ;************************************************************************** ; * ; Port assignments * ; * ;************************************************************************** GPIO_IO equ b'001110' ; port I/O status D0 equ 0 ; DTMF data D1 equ 1 D2 equ 2 D3 equ 3 DV equ 4 ; DTMF data valid PWDN equ 5 ; DTMF power down LED equ 4 ; status LED RELAY equ 0 ; relay ;************************************************************************** ; * ; Constants and timings * ; * ;************************************************************************** CLOCK equ d'4000000' ; processor clock frequency in Hz MAX_CODE equ d'10' ; maximum code length (including star) SETUP_PERIOD equ d'10' ; setup mode period in s POLL_DELAY equ d'10' ; poll delay in ms VALID_DELAY equ d'150' ; flash delay in ms CORRECT_DELAY equ d'100' ; correct delay in ms RELAY_PERIOD equ d'5' ; default relay period in s TIMEOUT_PERIOD equ d'10' ; timeout period in s ; DTMF codes DTMF_1 equ b'0001' ; 1 DTMF_2 equ b'0010' ; 2 DTMF_3 equ b'0011' ; 3 DTMF_4 equ b'0100' ; 4 DTMF_5 equ b'0101' ; 5 DTMF_6 equ b'0110' ; 6 DTMF_7 equ b'0111' ; 7 DTMF_8 equ b'1000' ; 8 DTMF_9 equ b'1001' ; 9 DTMF_0 equ b'1010' ; 0 DTMF_STAR equ b'1011' ; * DTMF_HASH equ b'1100' ; # DTMF_A equ b'1101' ; A DTMF_B equ b'1110' ; B DTMF_C equ b'1111' ; C DTMF_D equ b'0000' ; D ;************************************************************************** ; * ; File register usage * ; * ;************************************************************************** RAM equ h'20' cblock RAM flags ; various flags buffer:MAX_CODE+1 ; code buffer ndx ; EEPROM index loop, count ; loop counters timeout:2 ; timeout timer setup:2 ; setup mode timer timer ; timer work1, work2, work3 ; work registers endc ; flags VERIFY equ 0 ; set if verifying combination ACTIVE equ 1 ; set if relay active LIT equ 2 ; set if LED lit ;************************************************************************** ; * ; Macros * ; * ;************************************************************************** routine macro label ; routine label endm table macro label ; define lookup table label addwf PCL endm entry macro value ; define table entry retlw value endm index macro label ; index lookup table call label endm jump macro label ; jump through table goto label endm tstw macro ; test w register iorlw 0 endm movff macro f1,f2 ; move file to file movfw f1 movwf f2 endm movlf macro n,f ; move literal to file movlw n movwf f endm set16 macro n,f movlf high (n),(f)+0 movlf low (n),(f)+1 endm tst16 macro f movfw (f)+0 iorwf (f)+1,w endm inc16 macro f incf (f)+1 skpnz incf (f)+0 endm dec16 macro f tstf (f)+1 skpnz decf (f)+0 decf (f)+1 endm tris_ macro t movlw t bsf STATUS,RP0 movwf TRISIO bcf STATUS,RP0 endm ;-------------------------------------------------------------------------- ; reset vector ;-------------------------------------------------------------------------- org 0 bsf STATUS,RP0 call h'3ff' movwf OSCCAL bcf STATUS,RP0 goto main_entry ;************************************************************************** ; * ; Procedures * ; * ;************************************************************************** ;-------------------------------------------------------------------------- ; waits for the number of milliseconds in w reg ;-------------------------------------------------------------------------- routine wait_ms movwf work1 wait1 movlf CLOCK/(d'1000'*d'20'),work2 wait2 nop ; [4] nop ; [4] decfsz work2 ; [4/8] goto wait2 ; [8/0] clrwdt ; [0/4] decfsz work1 goto wait1 return ;-------------------------------------------------------------------------- ; waits for the number of seconds in w reg ;-------------------------------------------------------------------------- routine wait_s movwf loop wait3 movlw d'250' call wait_ms movlw d'250' call wait_ms movlw d'250' call wait_ms movlw d'250' call wait_ms decfsz loop goto wait3 return ;-------------------------------------------------------------------------- ; writes the EEPROM with w reg ;-------------------------------------------------------------------------- routine write_EEPROM bsf STATUS,RP0 movwf EEDATA movff ndx,EEADR bcf EEADR,6 ; protect master combination bsf EECON1,WREN movlf h'55',EECON2 movlf h'aa',EECON2 bsf EECON1,WR write1 clrwdt btfsc EECON1,WR goto write1 bcf EECON1,WREN bcf STATUS,RP0 return ;-------------------------------------------------------------------------- ; reads the EEPROM into w reg ;-------------------------------------------------------------------------- routine read_EEPROM bsf STATUS,RP0 movff ndx,EEADR bsf EECON1,RD movfw EEDATA bcf STATUS,RP0 return ;-------------------------------------------------------------------------- ; tests whether valid DTMF data is present, returns NZ flag set if true ;-------------------------------------------------------------------------- routine test_DTMF bcf GPIO,DV tris_ GPIO_IO|(1< 0 movff buffer+i-1,buffer+i i -= 1 endw movff work1,buffer+0 gett1 bsf GPIO,LED ; acknowledge tone movlw VALID_DELAY call wait_ms bcf GPIO,LED gett2 call test_DTMF ; wait for end of valid pulse bz gett3 movlw POLL_DELAY call wait_ms goto gett2 gett3 return ;-------------------------------------------------------------------------- ; flashes the LED, fed with the repeat count in w reg ;-------------------------------------------------------------------------- routine flash movwf count movlw VALID_DELAY call wait_ms flash1 movlw CORRECT_DELAY call wait_ms bsf GPIO,LED movlw CORRECT_DELAY call wait_ms bcf GPIO,LED decfsz count goto flash1 return ;-------------------------------------------------------------------------- ; tests a code, fed with a combination address in w reg, returns Z flag ; set if code matches combination, and C flag set if code is same length ; as combination ;-------------------------------------------------------------------------- routine test_code movwf ndx movlf buffer,FSR test1 call read_EEPROM ; get tone xorlw -1 ; end of combination ? bz test3 ; branch if yes xorlw -1 ; code matches combination ? subwf 0,w bnz test2 ; branch if not incf ndx incf FSR goto test1 test2 clrz ; signal no match return test3 clrc ; determine if equal length incf 0,w skpnz setc setz ; signal match return ;-------------------------------------------------------------------------- ; stores a code, fed with a combination address in w reg, returns Z flag ; set if error ;-------------------------------------------------------------------------- routine store_code movwf ndx movlf buffer,FSR movlf MAX_CODE,count stor1 movfw 0 ; store tone call write_EEPROM call read_EEPROM ; test read xorwf 0,w bnz stor2 ; branch if error incf ndx incf FSR decfsz count goto stor1 movlw -1 ; end marker call write_EEPROM clrz ; signal success return stor2 setz ; signal error return ;-------------------------------------------------------------------------- ; gets a user combination ;-------------------------------------------------------------------------- routine get_combination bcf flags,VERIFY getc1 movlw -1 ; clear code buffer variable i = 0 while i < MAX_CODE+1 movwf buffer+i i += 1 endw PERIOD set (SETUP_PERIOD*d'1000')/POLL_DELAY getc2 set16 PERIOD,timeout ; initialise timeout timer getc3 call test_DTMF ; wait for valid DTMF data bnz getc4 movlw POLL_DELAY call wait_ms dec16 timeout ; decrement timeout timer tst16 timeout ; timeout ? bnz getc3 ; loop if not goto getc6 getc4 bcf flags,ACTIVE bcf flags,LIT call get_tone ; get the tone btfsc flags,VERIFY ; verifying combination ? goto getc5 ; branch if yes movlw DTMF_STAR ; combination terminated with star xorwf buffer+0,w bnz getc2 incf buffer+1,w ; reject null combinations bz getc6 movlf combination,ndx ; store in unused user combination call read_EEPROM xorlw 1 movlw user_combination1 skpnz movlw user_combination2 call store_code bz getc6 ; branch if error movlw d'4' ; signal user combination entered call flash bsf flags,VERIFY ; verify combination goto getc1 getc5 movlf combination,ndx ; compare the user combination call read_EEPROM xorlw 1 movlw user_combination1 skpnz movlw user_combination2 call test_code bnz getc2 bnc getc6 ; branch if different movlf combination,ndx ; toggle current user combination call read_EEPROM xorlw b'11' call write_EEPROM movlw d'4' ; signal user combination updated call flash clrf timer getc6 goto main_loop ;-------------------------------------------------------------------------- ; sleep state ;-------------------------------------------------------------------------- routine sleep_state bcf GPIO,LED ; LED off movfw timer ; DTMF decoder on periodically andlw b'11' skpnz bcf GPIO,PWDN skpz bsf GPIO,PWDN bsf STATUS,RP0 ; prescale WDT 1:2 movlw b'10001001' movwf OPTION_REG bcf STATUS,RP0 clrwdt sleep ; standby mode nop ; goto main_entry ;-------------------------------------------------------------------------- ; main entry point ;-------------------------------------------------------------------------- routine main_entry clrf GPIO ; initialise port tris_ GPIO_IO bsf STATUS,RP0 ; prescale WDT 1:128, movlw b'10001111' ; weak pull-ups disabled movwf OPTION_REG clrf WPU bcf STATUS,RP0 clrf INTCON ; interrupts off movlf b'111',CMCON clrf PCLATH movfw STATUS ; wake-up from sleep ? andlw (1<