list P=16F84
include P16F84.INC
; Define the direction bit types
f equ 1
w equ 0
; Define the data storage locations
; These locations must NOT be modified!
entered_pass_code equ 0x20 ; the entered passcode - last four keys pressed
num_pass_codes equ 0x21 ; the number of passcodes stored
success equ 0x40 ; grant or deny access
history equ 0x41 ; history of passcodes entered
supervisor_mode equ 0x42 ; supervisor code entered -> adding new pass code to list
status_temp equ 0x4A ; temp storage of STATUS reg during subroutines
w_temp equ 0x4B ; temp storage of W during subroutines
last_key_press equ 0x4F ; last key pressed
new_num_passcodes equ 0x50
counter equ 0x10
temp_passcode equ 0x11
new_loc equ 0x12
org 0x30
passcodes res 16 ; location of the passcodes
; Define the control code for adding new users
control_code equ 0x1B
; start defining the program
; interrupts, so start at 0x30
org 0x00
goto start
; Interrupt Service Routine
org 0x04
movwf w_temp ; store the value of W
movf STATUS, w
movwf status_temp ; store the STATUS register
movf PORTA, w ; get the key pressed
movwf last_key_press; move the captured key press to reg
bcf INTCON, INTF ; clear interrupt flag
movf status_temp, w ; restore the status register's value
movwf STATUS
movf w_temp, w ; restore the W register's value
retfie
; Success or Failure Subroutine
grant_deny
movwf w_temp ; store the value of W
movf STATUS, w
movwf status_temp ; store the STATUS register
btfss success, 0
goto update_history
open_door
movlw 0x8 ; send open door signal -> RA3
movwf PORTA
movlw 0x0
movwf PORTA
update_history
bcf STATUS, 0 ; clear the carry bit to allow for shift thru carry
rlf history, f
movf success, w
addwf history, f
clrf entered_pass_code ; clear last attempt's pass code
clrf success ; clear success flag
movf status_temp, w ; restore the STATUS register
movwf STATUS
movf w_temp, w ; restore the W register
return
; Sleep subroutine
sleep_now
sleep
; nop needed after sleep command for correct interrupt handling
nop
return
; start main program
org 0x30
start
; Set-up Interrupt on RB0
bsf INTCON, GIE ; enable global interrupts
bsf INTCON, INTE ; enable RB0 interrupts
; Set-up Inputs
bsf STATUS, RP0 ; select bank 1
movlw 0x07 ; configure first 3 bits as inputs
; The following instruction generates a MESSAGE[302] warning from MPLAB - this is expected.
movwf TRISA ; load configuration into RA port
bcf STATUS, RP0 ; select bank 0
clrf history ; zero out history of successes
clrf PORTA ; clear the output on PORTA
clrf num_pass_codes ; start out with an empty authorized pass codes list
clrf supervisor_mode
; This is the main program loop that calls your subroutines.
endless_loop
call sleep_now
btfsc last_key_press, 2 ; test for Enter press
goto enter_pressed
call update_pass_code ; update the entered pass code if Enter not pressed
goto endless_loop
enter_pressed
call compare_pass_code
goto endless_loop
; Place your subroutines (compare_code & update_code) here:
update_pass_code:
movf entered_pass_code,w ; move entered passcode into w
movwf temp_passcode ; move entered passcode into new location so it won't be modified
bcf STATUS,C
rlf temp_passcode,f
bcf STATUS,C
rlf temp_passcode,f
;
movf entered_pass_code,w ; move the original entered_pass_code into w
addwf temp_passcode,w ; add to new temp_passcode, gets you the new format
call compare_pass_code
return
compare_pass_code:
movf supervisor_mode,f
btfss STATUS,Z ;check to see if supervisor_mode is 0 or 1
goto not_super
goto super
not_super
movf entered_pass_code,w
sublw 0x1B,f ; subtract entered_pass_code from supervisor's code(0x1B
btfss STATUS,Z ; check to see if they are equal(0 as answer)
call supermode
call compare_to_list
super ;store the new passcode in list
movf passcodes,w
movwf FSR
;
movf entered_pass_code,w
movwf INDF
;
incf num_pass_codes,f
clrf supervisor_mode
;
return
supermode:
movwf supervisor_mode
movlw 0x01 ;insert 1 into supervisor_mode, since the enter_pass_code matched
return
no_match
incf counter,f
incf new_num_passcodes,w
subwf num_pass_codes,f
btfss STATUS,Z
call compare_to_list
call grant_deny
compare_to_list
movlw passcodes ; set passcodes to the value in 0x30
addwf counter,w ; place passcodes into counter
movwf FSR
movf INDF,w ; get the passcode to place in temp register
movwf new_loc ; move into new location
subwf entered_pass_code,f ; compare the entered code to the list
btfss STATUS,Z ; check to see if answer equals 0
call grant_deny
goto no_match
return