;----------------------------------------------------------------------; ; COMBO4M.ASM A combination lock 4 Mhz ; ;----------------------------------------------------------------------; ; Hold both buttons down when power applied to enter code set routine ; A total of 8 button presses makes up the combination. If the correct ; combination is entered, all four LEDs will flash 6 times else once. ; .-----------. ; -|RA2 RA1|- V+ = 4.5 or 5V ; -|RA3 RA0|- X = 4 MHz cer. res. ; -|RA4 OSC1|--|X|___ gnd ; -{r}- = 470 ohm V+ ---|MCLR OSC2|--|X| ; -|<- = LED gnd ---|Vss Vdd|--- V+ ; gnd ---|<--{r}--|RB0 RB7|- ; gnd ---|<--{r}--|RB1 RB6|- ; gnd ---|<--{r}--|RB2 RB5|---[PB]--- gnd ; gnd ---|<--{r}--|RB3 RB4|---[PB]--- gnd ; '-----------' ; PIC16F84 -[PB]- pushbutton LIST P=16F84 ; tells which processor is used INCLUDE "p16f84.inc" ; defines various registers etc. Look ERRORLEVEL -224 ; supress annoying message from tris ERRORLEVEL -302 ; " " " page change __CONFIG _PWRTE_ON & _XT_OSC & _WDT_OFF ; config.switches #define PB1 PORTB, 4 ; Pushbutton #1, generates a '0' bit #define PB2 PORTB, 5 ; Pushbutton #2, generates a '1' bit #define LED1 PORTB, 3 ; LED #1 #define LED2 PORTB, 0 ; LED #2 ; register usage: CBLOCK H'C' combo ; holds combination count ; general count register codevalue ; holds code value cntmsec ; used to count milliseconds ENDC ORG 0 ; start a program memory location zero goto main ; jump over the interrupt routine ;----------------------------------------------------------------------; ; Initialize the ports etc. ; ;----------------------------------------------------------------------; init: movlw B'00000000' ; all bits low in W tris PORTA ; contents of W copied to PORT A ... movlw B'00110000' ; Rb4,RB5 inputs, all other output tris PORTB ; into PORT B clrf PORTB ; LEDs blanked movlw 0 option ; Port B pullups enabled return ;----------------------------------------------------------------------; ; Read a byte from the data EEPROM at address given in W ; ;----------------------------------------------------------------------; readee movwf EEADR ; set up eeprom address from W bsf STATUS,RP0 ; change to page 1 bsf EECON1,RD ; set the read bit bcf STATUS,RP0 ; back to page 0 movf EEDATA,W ; return value in W return ;----------------------------------------------------------------------; ; This routine writes a byte to data EEPROM ; ; set up EEADR and EEDATA before entry ; ;----------------------------------------------------------------------; writee: bsf STATUS,RP0 ; enter page 1 clrf EECON1 bsf EECON1,WREN ; enable write movlw H'55' ; magic sequence movwf EECON2 movlw H'AA' movwf EECON2 bsf EECON1,WR eeloop: btfsc EECON1,WR ; wait for WR to go low goto eeloop ; not yet bsf EECON1,WREN bcf EECON1,EEIF ; clear the interrupt flag bcf STATUS,RP0 ; return to page 0 movlw D'10' ; delay to 'burn' in call nmsec return ;----------------------------------------------------------------------; ; Enter Code ; ;----------------------------------------------------------------------; entercode: movlw 1 ; flash once call flashleds movlw 8 ; set up to count 8 presses movwf count waitboth: btfss PB1 ; wait until pushbutton 1 up goto waitboth btfss PB2 ; and pushbutton 2 up goto waitboth call msec20 ; bypass any bouncing bcf LED1 bcf LED2 eitherbutton: ; wait until either button pressed comf PORTB, W ; compliment of Port B in W andlw B'00110000' ; look at buttons, ( 0's if up) btfsc STATUS, Z ; skip if either pressed goto eitherbutton ; try again call msec20 ; debounce press (not in 32 kHz ver) bcf STATUS, C ; clear carry btfss PB1 ; if one pressed leave carry clear goto PB1pressed bsf STATUS, C ; else set carry goto $ + 3 ; skip over PB1pressed bsf LED1 ; turn LED1 on goto $ + 2 ; skip over bsf LED2 ; turn LED2 on rrf combo, f ; roll result into combo high bit decfsz count, f ; more presses necessary goto waitboth ; next press movf combo, W ; transfer result to W return ;----------------------------------------------------------------------; ; time delay routines ; ;----------------------------------------------------------------------; micro4 addlw H'FF' ; subtract 1 from 'W' btfss STATUS,Z ; skip when you reach zero goto micro4 ; more loops return onesecond: ; a subroutine that delays for 1 sec call msec250 call msec250 call msec250 call msec250 return msec20 movlw D'20' ; 20 msec delay entry point goto nmsec msec250: ; a subroutine to delay 250 msec movlw D'250' ;*** N millisecond delay routine *** nmsec: movwf cntmsec ; delay for N (in W) millisec msecloop: movlw D'248' ; 1 usec for load call micro4 ; this instruction is 995 usec nop ; 1 usec decfsz cntmsec,f ; 1 usec, (2 if skip taken) goto msecloop ; 2 usec, loop = 995+5 = 1 msec return ;----------------------------------------------------------------------; ; Flash the LEDs, number of flashes in W on entry ; ;----------------------------------------------------------------------; flashleds: movwf count flashloop: movlw H'F' movwf PORTB call onesecond + 2 ; 1/2 sec on movlw 0 movwf PORTB call onesecond + 2 ; 1/2 sec off decfsz count, f goto flashloop return ;----------------------------------------------------------------------; ; Get combo value and place it in EEPROM location 0 ; ;----------------------------------------------------------------------; setcombo: call entercode ; get desired press combination movwf EEDATA ; set up data and address movlw 0 movwf EEADR call writee ; save combo in EEPROM movlw 2 ; flash leds 2 times call flashleds ; (one additional when entering main) return ;----------------------------------------------------------------------; ; The Main routine ; ;----------------------------------------------------------------------; main: call init ; initialize registers etc. movf PORTB, W ; check both buttons pressed on pwr-up andlw B'00110000' ; look at buttons, (0's if down) btfsc STATUS, Z ; skip if both not presssed call setcombo ; if both press set the combination movlw 0 ; get combo from EEPROM address 0 call readee movwf codevalue ; save it mainloop: call entercode subwf codevalue, W ; is it same as code? btfss STATUS, Z ; zero set if yes goto mainloop movlw 5 ; sucess, unlocking procedure would ... call flashleds ; be placed here. goto mainloop org 2100 ; this is location of EEPROM data dw H'33' ; the initial value of location 0 ... ; is set to B'00110011' end ; end of program