Yup, there's Tons of different ways.
But first, why doesn't Joe's program work...
- There's no way out of the Start: loop. It never makes it to combo:
- There are too many nested gosubs. It'll overflow the stack before it gets a full combination entered. You only get 4 levels.
- Spaghetti code like that needs Marinara, not Picante sauce.

So here's one of those other ways. It has 2 security levels, timeouts, and an easy to set Code in EEPROM.
Code:
@MyConfig = _HS_OSC & _WDT_OFF & _PWRTE_ON & _LVP_OFF
@MyConfig = MyConfig & _BODEN_OFF
@ __config MyConfig
'@ __CONFIG _HS_OSC & _WDT_ON & _PWRTE_ON & _LVP_OFF & _CP_OFF
CLEAR
;________________________User Configurable Settings___________________________
DEFINE HIGH_SECURITY 1 ; For HIGH_SECURITY, the user is required to enter
; the exact number of digits, Followed by the # sign
MaxTime CON 5000 ; Timeout if no keypress, in ms
Data @0, 5, "78A5D" ; Length of, and The Combination
; Since it's in EEPROM, it can be changed later.
;_____________________________________________________________________________
Define PIC16F877A
@ errorlevel -230
CMCON = 7
ADCON1 = 7
define OSC 20
TrisD = %00000000
DEFINE LCD_DREG PORTA
DEFINE LCD_DBIT 0
DEFINE LCD_RSREG PORTA
DEFINE LCD_RSBIT 5
DEFINE LCD_EREG PORTA
DEFINE LCD_EBIT 4
DEFINE LCD_BITS 4
DEFINE LCD_LINES 4
disable debug
include "keypad.bas"
enable debug
DEFINE KEYPAD_ROW 4 ' 4 ROW keypad
DEFINE KEYPAD_ROW_PORT PORTB ' ROW port = PORTB
DEFINE KEYPAD_ROW_BIT 4 ' ROW0 = PORTB.4
DEFINE KEYPAD_COL 4 ' 3 COL keypad
DEFINE KEYPAD_COL_PORT PORTB ' COL port = PORTB
DEFINE KEYPAD_COL_BIT 0 ' COL0 = PORTB.1
DEFINE KEYPAD_DEBOUNCEMS 50 ' debounce delay = 50 mSec
DEFINE SCAN_ONCE 1
ByteA var byte
ComboLength VAR BYTE
ComboPtr VAR BYTE
Timeout VAR WORD
Failed VAR BIT
ReStart VAR BIT
OPTION_REG.7=0 ' Enable the Excellent internal PORTB pull-ups :D
TRISB = %11110000 ' Set Keypad I/O
PORTB = 0 ' Set columns LOW
INTCON = %10001000 ' Enable global interrupt, and PORTB change
on interrupt goto KeypadInt ; ON INTERRUPT ???? :)
Init:
ReStart = 0
lcdout $FE,1
pause 500
Failed = 0
Read 0, ComboLength
lcdout $FE,1,"Press any Key"
Start:
pause 1
Timeout = Timeout - 1
if (ComboPtr > 0) and (Timeout = 0) then Gosub Reset
if ReStart then Init
goto Start
;_____________________________________________________________________________
disable
@ ifndef HIGH_SECURITY
@ #define HIGH_SECURITY 0 ; default to Low security
@ endif
KeypadINT:
@ READKEYPAD _ByteA ; Get the keypress
TRISB=%11110000 ; Reset I/O's
PORTB=0 ; Set all columns LOW
INTCON.0=0 ; Clear RBIF
Timeout = MaxTime ; Reset the Timeout
lookup ByteA,[0,"123A456B789C*0#D"],Key ; convert keypress
ComboPtr = ComboPtr + 1 ; point to next digit
@ if HIGH_SECURITY == 1
LCDOUT $FE, $C4 + ComboPtr, "*" ; print a Mask character
if Key = "*" then Reset
if Key = "#" then Finish
@ endif
if ComboPtr <= ComboLength then
Read ComboPtr, ByteA ; Get the digit from EEPROM
if Key = ByteA then ; is it the same ?
Read 0, ByteA ; Get the length of the combo
@ if HIGH_SECURITY == 0
LCDOUT $FE, $C4 + ComboPtr, "*" ; print a Mask character
if ComboPtr = ByteA then AccessGranted ; Done?, Grant Access
@ endif
else
@ if HIGH_SECURITY == 0
ComboPtr = 0 ; Wrong digit
goto AccessDenied ; terminate entry
@ else ; -HIGH_SECURITY-
Failed = 1 ; let them keep entering
@ endif ; makes it harder to figure
Endif ; the combination
endif
resume ; must end with # sign
AccessGranted:
ComboPtr = 0
lcdout $FE,1," Gate Opening"
PortD.2 = 1
pause 30000
lcdout $FE,1,$FE,$C0," Gate Closing"
pause 30000
ReStart = 1
resume
AccessDenied:
ComboPtr = 0
LCDOUT $FE, 1, " Access Denied"
; Zapp them with 5000v to the kaypad :)
pause 2000
ReStart = 1
resume
Reset:
ComboPtr = 0
LCDOUT $FE, 1, " Entry Reset"
pause 2000
ReStart = 1
resume
Finish:
if (Failed = 0) and (ComboPtr = ComboLength + 1) then
goto AccessGranted
else
goto AccessDenied
endif
enable
Bookmarks