;----------------------------------------------------------------------;
; 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