Code:
'******************************************************************
'* Name : CODELOCK.BAS *
'* Author : [LB] *
'* Notice : Copyright (c) 2024 [14 April 2024] *
'* : All Rights Reserved *
'* Date : 14-Apr-24 *
'* Version : 1.0 *
'* Notes : This is a codelock based on the following components *
'* : PIC18F26K22 @ 64Mhz *
'* : 4D Systems Pixxi LCD 25P4 *
' ======= Key Mapping (last 4 bytes of response codes) =======
'NUM_KEYS CON 12
' Hex Codes & Corresponding Key Values
'keyCodes DATA $313A, 1 ' Number 1 "07 0D 01 00 31 3A"
'keyCodes DATA $3239, 2 ' Number 2 "07 0D 01 00 32 39"
'keyCodes DATA $3338, 3 ' Number 3 "07 0D 01 00 33 38"
'keyCodes DATA $343F, 4 ' Number 4 "07 0D 01 00 34 3F"
'keyCodes DATA $353E, 5 ' Number 5 "07 0D 01 00 35 3E"
'keyCodes DATA $363D, 6 ' Number 6 "07 0D 01 00 36 3D"
'keyCodes DATA $373C, 7 ' Number 7 "07 0D 01 00 37 3C"
'keyCodes DATA $3833, 8 ' Number 8 "07 0D 01 00 38 33"
'keyCodes DATA $3932, 9 ' Number 9 "07 0D 01 00 39 32"
'keyCodes DATA $2A21, 10 ' Number * "07 0D 01 00 2A 21" (unused)
'keyCodes DATA $303B, 0 ' Number 0 "07 0D 01 00 30 3B"
'keyCodes DATA $0803, 11 ' Go # "07 0D 01 00 08 03"
'*********************************************************************************
' *
#IF __PROCESSOR__ = "18F26k22"
@ ERRORLEVEL -306 ; this command prevents the compiler to give you a notice of *
; crossing page boundary - make sure bits are set *
'*********************************************************************************
; *
#CONFIG ; The PBP configuration for the PIC18F26K22 is: *
; *
;*********************************************************************************
CONFIG FOSC=INTIO67, PLLCFG=ON, PRICLKEN=OFF, FCMEN=OFF, IESO=OFF
CONFIG PWRTEN=OFF, BOREN=SBORDIS, BORV=190, WDTEN=ON, WDTPS=32768
CONFIG CCP2MX=PORTC1, PBADEN=OFF, CCP3MX=PORTB5, HFOFST=ON, T3CMX=PORTC0
CONFIG P2BMX=PORTB5, MCLRE=EXTMCLR, STVREN=ON, LVP=OFF, XINST=OFF, DEBUG=OFF
CONFIG CP0=OFF, CP1=OFF, CP2=OFF, CP3=OFF, CPB=OFF, CPD=OFF, WRT0=OFF
CONFIG WRT1=OFF, WRT2=OFF, WRT3=OFF, WRTC=OFF, WRTB=OFF, WRTD=OFF, EBTR0=OFF
CONFIG EBTR1=OFF, EBTR2=OFF, EBTR3=OFF, EBTRB=OFF
#ENDCONFIG
#ELSE
#MSG "Wrong Processor selected!"
#ENDIF
define OSC 64
INCLUDE "modedefs.bas"
INCLUDE "ALLDIGITAL.pbp"
OSCCON = %01110000 ; 16Mhz
OSCTUNE.6 = 1 ; Enable 4x PLL
'*-----------------------------------------------------------------------------|
'* | --------------------- | |
'*----------------------- | EUART 2 Configuration | --------------------------|
'* | --------------------- | |
'*-----------------------------------------------------------------------------|
' for debuging PLL if it is ready or not
' EUART 1 is configured later in the code
DEFINE HSER2_RCSTA 90h ' Enable serial port & continuous receive
DEFINE HSER2_TXSTA 24h ' Enable transmit, BRGH = 1
DEFINE HSER2_CLROERR 1 ' Clear overflow automatically
DEFINE HSER2_SPBRG 160 ' 38400 Baud @ 64MHz, -0.08%
SPBRGH2 = 1
BAUDCON2.3 = 1 ' Enable 16 bit baudrate generator
' Debug loop to check PLLRDY status
WHILE !OSCCON2.7 ' Wait until PLL is stable
pause 500
HSEROUT2 ["PLL not ready...", 13, 10] ' Send message to terminal
PAUSE 500 ' Wait 500ms before checking again
WEND
pause 500
HSEROUT2 ["PLL is ready!", 13, 10] ' Confirm PLL is stable
'------------------------------------------------------------------------------|
' INITIALIZE RAM |
'------------------------------------------------------------------------------|
initialize:
CLEAR
'------------------------------------------------------------------------------|
'-------------------------------------------------------------------------------------------------------------------------------------------------------------
TRISA = %00000000 'use TRISA to specify which pin is (1 = input) and which (0 = output) (ALL pins are output)
TRISB = %10000000 'use TRISB to specify which pin is (1 = input) and which (0 = output) (RB7 PORTB.7 is the RX input pin of the EUART, the rest are output)
TRISC = %10000000 'use TRISC to specify which pin is (1 = input) and which (0 = output) (RC7 PORTC.7 is the RX input pin of the EUART, the rest are output)
'in PORTC the RC3 attached is an LED.
'------------------------------------------------------------------------|
'--------------------------- TRIS A B C ---------------------------------|
'------------------------------------------------------------------------|
' PORTA.7 PORTA.6 PORTA.5 PORTA.4 PORTA.3 PORTA.2 PORTA.1 PORTA.0 |
' bit7 bit6 bit5 bit4 bit3 bit2 bit1 bit0 |
' 1 0 0 0 0 0 0 0 |
'------------------------------------------------------------------------|
'------------------------------------------------------------------------|
' PORTB.7 PORTB.6 PORTB.5 PORTB.4 PORTB.3 PORTB.2 PORTB.1 PORTB.0 |
' bit7 bit6 bit5 bit4 bit3 bit2 bit1 bit0 |
' 0 0 0 0 0 0 0 0 |
'------------------------------------------------------------------------|
'------------------------------------------------------------------------|
' PORTC.7 PORTC.6 PORTC.5 PORTC.4 PORTC.3 PORTC.2 PORTC.1 PORTC.0 |
' bit7 bit6 bit5 bit4 bit3 bit2 bit1 bit0 |
' 1 0 0 0 0 0 0 0 |
'------------------------------------------------------------------------|
'------------------------------------------------------------------------|
'----------------------- At start all PORTS LOW -------------------------|
'------------------------------------------------------------------------|
PORTA = 0 'make low all ports at A range |
PORTB = 0 'make low all ports at B range |
PORTC = 0 'make low all ports at C range |
'------------------------------------------------------------------------|
'------------------------------------------------------------------------|
'-------------------------- COMPARATORS OFF -----------------------------|
'------------------------------------------------------------------------|
CM1CON0.7 = 0 'Disable comparator1 |
CM2CON0.7 = 0 'Disable comparator2 |
'------------------------------------------------------------------------|
'*-----------------------------------------------------------------------------|
'* | --------------------- | |
'*----------------------- | EUART 1 Configuration | --------------------------|
'* | --------------------- | |
'*-----------------------------------------------------------------------------|
DEFINE HSER_RCSTA 90h ' Enable serial port & continuous receive
DEFINE HSER_TXSTA 24h ' Enable transmit, BRGH = 1
DEFINE HSER_CLROERR 1 ' Clear overflow automatically
DEFINE HSER_SPBRG 160 ' 38400 Baud @ 64MHz, -0.08%
SPBRGH = 1
BAUDCON.3 = 1 ' Enable 16 bit baudrate generator
'*-----------------------------------------------------------------------------|
'*-----------------------------------------------------------------------------|
Red var LATC.3
Blue var LATA.2
Green var LATC.1
' ======= Buffers and Variables =======
passcode VAR BYTE[4] ' Stores the correct passcode
inputCode VAR BYTE[4] ' Stores user input
passIndex VAR BYTE ' Index for passcode entry
receivedByte VAR BYTE[6] ' Array to store received bytes from LCD
keyCode VAR BYTE ' Stores the decoded key value
keyCodeHigh VAR BYTE ' High byte of the key code
keyCodeLow VAR BYTE ' Low byte of the key code
keyCodeCombined VAR WORD ' Combined 16-bit key code
i VAR BYTE ' Loop counter
' Initialize Variables
passIndex = 0 ' Initialize passcode index
keyCode = $FF ' Initialize keyCode as undefined
failCount VAR BYTE ' Tracks failed attempts
MAX_FAILS CON 5 ' Maximum allowed failed attempts before lockout
Timeout VAR WORD ' Timeout counter for automatic reset
CurrentIndex VAR BYTE
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
' VAR for Contrast '
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
command var byte
contrast var byte
CS var byte
'================================================================================================
NUM_KEYS CON 5
' Corrected Key Mapping
keyCodes VAR WORD[NUM_KEYS] ' Store received hex codes
keyValues VAR BYTE[NUM_KEYS] ' Corresponding key values
' Initialize keyCodes and keyValues arrays
FOR i = 0 TO NUM_KEYS - 1
READ keyCodes[i], keyValues[i]
NEXT i
' Manually define keys (matching Pixxi LCD response)
keyCodes[0] = $3239 ' Number 2
keyValues[0] = "2"
keyCodes[1] = $373C ' Number 7
keyValues[1] = "7"
keyCodes[2] = $3833 ' Number 8
keyValues[2] = "8"
keyCodes[3] = $343F ' Number 4
keyValues[3] = "4"
keyCodes[4] = $0803 ' Go button
keyValues[4] = "G"
' ==== Set Correct Passcode ====
passcode[0] = "2" ' Passcode digit 2
passcode[1] = "7" ' Passcode digit 7
passcode[2] = "8" ' Passcode digit 8
passcode[3] = "4" ' Passcode digit 4
' Debugging: Print the contents of keyCodes and keyValues arrays
FOR i = 0 TO NUM_KEYS - 1
hserout2 ["Key Code ", DEC i, ": ", HEX keyCodes[i], " | Key Value: ", keyValues[i], 13,10]
NEXT i
'checking the LEDs.
high red
pause 500
low RED
high Green
hserout2 ["Red LED flashes once", 13,10]
hserout2 ["Green LED shows that PIC is powered up", 13,10]
pause 3000 ' wait for the LCD to power up.
'=========================== CONTRAST checksum commands=====================
'===========================================================================
gosub checksum
hserout [command,contrast,CS] ' Contrast settings
hserin [wait(6)]
pause 100
'*********************************************************************************
' Main Program
'*********************************************************************************
' ==== Main Program ====
START:
LOW Blue
LOW Red
GOSUB ReadKey ' Read key pressed
hserout2 ["Key Read Complete", 13, 10] ' debug serial out on 2 via PICKIT2
IF keyCode <> "G" THEN ' this operator <> checks If not equal to the Go button
IF passIndex < 4 THEN
inputCode[passIndex] = keyCode ' Store key in inputCode
passIndex = passIndex + 1 ' Increment index
ENDIF
ELSE
' If "Go" button pressed, check passcode
IF passIndex = 4 THEN
GOSUB CheckPasscode
ENDIF
ENDIF
GOTO START
' ==== Read Key ====
ReadKey:
' Ensure buffer is cleared before receiving new data
FOR i = 0 TO 5
receivedByte[i] = 0
NEXT i
HSERIN [receivedByte[0], receivedByte[1], receivedByte[2], receivedByte[3], receivedByte[4], receivedByte[5]]
'debug serial out on 2 via PICKIT2
hserout2 ["Packet: ", HEX receivedByte[0], " ", HEX receivedByte[1], " ", HEX receivedByte[2], " ", HEX receivedByte[3], " ", HEX receivedByte[4], " ", HEX receivedByte[5],13,10]
' Extract the key code (last 2 bytes from the received data)
keyCodeHigh = receivedByte[4] ' Get the high byte of the key code from the received data
keyCodeLow = receivedByte[5] ' Get the low byte of the key code from the received data
' Combine the high and low bytes into a single 16-bit value
keyCodeCombined = (keyCodeHigh << 8) | keyCodeLow
' (keyCodeHigh << 8)Shift the high byte 8 bits to the left making room for the lowbyte and (| keyCodeLow) perform a bitwise OR with the low byte.
' This forms a 16-bit value where keyCodeHigh is the upper 8 bits and keyCodeLow is the lower 8 bits.
' Debugging: Print the combined key code
hserout2 ["Combined Key Code: ", HEX keyCodeCombined, 13, 10]
' Look up the combined key code in the keyCodes table
keyCode = "?" ' Default to undefined keycode for debugging
' Debugging: Output the keycodes and compare
FOR i = 0 TO NUM_KEYS - 1
hserout2 ["Checking: ", HEX keyCodeCombined, " against ", HEX keyCodes[i], 13, 10]
IF keyCodeCombined = keyCodes[i] THEN
keyCode = keyValues[i] 'Retrieve corresponding key value
hserout2 ["Match Found: ", keyCode, 13, 10]
EXIT
ENDIF
NEXT i
' Debugging: Output the detected key value
hserout2 ["Key Value: ", keyCode, 13, 10]
RETURN
' ==== Check Passcode ====
CheckPasscode:
'debug serial out on 2 via PICKIT2: Print the inputCode array
hserout2 ["Input Code: ", inputCode[0], inputCode[1], inputCode[2], inputCode[3], 13, 10]
FOR i = 0 TO 3
IF inputCode[i] <> passcode[i] THEN
'debug serial out on 2 via PICKIT2
hserout2 ["Passcode Mismatch at Index ", DEC i, 13, 10] ' Debugging mismatch
GOSUB Fail
RETURN
ENDIF
NEXT i
' If all characters match, passcode is correct
'debug serial out on 2 via PICKIT2
hserout2 ["Passcode is Correct open the door ", 13, 10]
GOSUB Unlocked
RETURN
' ======= Passcode Unlocked =======
Unlocked:
' Reset failed attempts counter
failCount = 0
' Blink Blue LED to indicate success
FOR i = 1 TO 3
HIGH Blue
PAUSE 100
LOW Blue
PAUSE 50
NEXT i
GOSUB ResetInputCode ; Reset input code
RETURN
' ======= Passcode Failed =======
Fail:
failCount = failCount + 1
'debug serial out on 2 via PICKIT2
hserout2 ["Incorrect code. Attempts: ", DEC failCount, 13, 10]
' Lockout check
IF failCount >= MAX_FAILS THEN
'debug serial out on 2 via PICKIT2
hserout2 ["LOCKED OUT! Too many failed attempts.", 13, 10]
GOSUB Lockout
RETURN
ENDIF
' Blink Red LED
HIGH Red
PAUSE 100
LOW Red
PAUSE 50
GOSUB ResetInputCode
RETURN
' ======= System Lockout =======
Lockout:
FOR i = 1 TO 10
HIGH Red
HIGH Blue
PAUSE 50
LOW Red
LOW Blue
PAUSE 50
NEXT i
' Disable Serial Reception
RCSTA.4 = 0 ' Disable continuous receive
'debug serial out on 2 via PICKIT2
hserout2 ["System Serial port is disabled.", 13, 10]
hserout2 ["System in Lockout Mode. Auto-reset in 60 seconds.", 13, 10]
' Automatic timeout reset (wait 60s)
FOR Timeout = 1 TO 60
PAUSE 1000
NEXT Timeout
' Reset failed attempts counter
failCount = 0
' Clear the entered code buffer
FOR i = 0 TO 3
InputCode[i] = 0
NEXT i
' Reset input index
CurrentIndex = 0
' Enable Serial Reception again
RCSTA.4 = 1 ' Re-enable continuous receive
'debug serial out on 2 via PICKIT2
hserout2 ["System Serial port is enabled.", 13, 10]
hserout2 ["Lockout reset. You may try again.", 13, 10]
RETURN
' ======= Reset Input Code =======
ResetInputCode:
FOR i = 0 TO 3
inputCode[i] = 0 ; Reset input code array
NEXT i
passIndex = 0 ; Reset passIndex
keyCode = $FF ; Reset keyCode
RETURN
'========== Contrast Checksum commmands ============
checksum:
command = $04
contrast = $01
cs = 0
cs = cs ^command ^ contrast
return
' ======= End of Program =======
END
Bookmarks