' ========================================================================= ' ' File....... SECURITY_SYSTEM.BS2 ' Purpose.... Two door security system, complete with ' Author..... Amal Graafstra ' Website.... www.amal.net ' Written.... 2009/05/30 ' ' ========================================================================= ' ' {$STAMP BS2} ' {$PBASIC 2.5} ' ' ========================================================================= ' ' ' -----[ Program Description ]--------------------------------------------- ' ' This security system monitors two RFID readers, controls two door latches, ' monitors two door status sensors (open/closed), monitors two security ' override keys/buttons, and supports two way 9600 baud RS232 communication ' with a serial host. ' ' Tag IDs received from RFID reader hardware are sent to an attached serial ' host for both logging purposes as well as host based authentication. ' A limited number of "failsafe" tag IDs can be stored in memory, however ' a nearly unlimited number of tags can be supported if the serial host ' is used to determine if a tag ID should be allowed access. ' ' Serial host communications ' -------------------------- ' Approximately once every 1.5 seconds, the security system will update ' the serial host with door status sensor data. This data is followed by ' the string "CMD", which tells the host that the security system will wait ' one half second for a latch command from the host. Because the stamp ' has no built in serial buffer, host communications must be kept to a strict ' timing schedule. The security system will also output event data such as tag ' reads, latch triggers, and override keys/buttons being pushed. But the only ' time at which the security system will listen for host commands is directly ' following the string "CMD". Because the system will only process one ' command at a time, the host must queue its commands and only send one per ' "CMD" string received. ' ' Data strings sent to host vary depending on event. Approximately every 1.5 ' seconds a status string will be sent just before a command "CMD" string: ' ' D1:1,D2:1,I1:0,I2:0,GA:0,GB:0,GC:0 ' CMD ' ' This example indicates that both doors are closed and all inputs or GPIOs ' are showing LOW status. ' ' In the following example, a tag ID is read from reader 2 and the tag ID ' is sent to the host. The tag also matches an ID stored in memory and ' latch 2 is triggered: ' ' R2:,T:0103C1E821 ' L2:1 ' ' Finally, this example shows an override key being used to open door 1: ' ' K1:1 ' L1:1 ' ' Host commands are simple ASCII character byte strings: ' ' char result ' ---- --------------- ' 1 Trigger latch 1 (2.5 seconds) ' 2 Trigger latch 2 (2.5 seconds) ' A Trigger GPIO A (1/4 second) ' B Trigger GPIO B (1/4 second) ' C Trigger GPIO C (1/4 second) ' ' -----[ Constants ]------------------------------------------------------- #SELECT $STAMP #CASE BS2, BS2E, BS2PE T1200 CON 813 T2400 CON 396 T4800 CON 188 T9600 CON 84 T19K2 CON 32 TMidi CON 12 T38K4 CON 6 #CASE BS2SX, BS2P T1200 CON 2063 T2400 CON 1021 T4800 CON 500 T9600 CON 240 T19K2 CON 110 TMidi CON 60 T38K4 CON 45 #ENDSELECT #SELECT $STAMP #CASE BS2, BS2E TmAdj CON $100 ' x 1.0 (time adjust) FrAdj CON $100 ' x 1.0 (freq adjust) #CASE BS2SX TmAdj CON $280 ' x 2.5 FrAdj CON $066 ' x 0.4 #CASE BS2P TmAdj CON $3C5 ' x 3.77 FrAdj CON $044 ' x 0.265 #CASE BS2PE TmAdj CON $100 ' x 1.0 FrAdj CON $0AA ' x 0.665 #ENDSELECT #DEFINE __No_SPRAM = ($STAMP < BS2P) ' Does module have SPRAM? SevenBit CON $2000 Inverted CON $4000 Open CON $8000 Baud CON T2400 ' -----[ Variables ]------------------------------------------------------- #IF __No_SPRAM #THEN tagBuffer VAR Byte(10) ' RFID bytes buffer #ELSE chkChar VAR Byte ' tag ID character to test #ENDIF tagNum VAR Nib ' tag data from EEPROM table tagIdx VAR Byte ' tag byte index tagChar VAR Byte ' character from table ReaderID VAR Byte ' the reader number the ID ' was received from strCommand VAR Byte ' byte command from host GPIO VAR Byte ' the GPIO to trigger ' -----[ EEPROM Data ]----------------------------------------------------- ' valid tag IDs Tag1 DATA "0123456789" ' tag 1 Tag2 DATA "9998887776" ' tag 2 Tag3 DATA "1112223334" ' tag 3 LastTag CON 3 ' # of tag IDs in EEPROM ' -----[ I/O Definitions ]------------------------------------------------- RFID1 PIN 0 ' Serial from RFID reader 1 RFID2 PIN 2 ' Serial from RFID reader 2 RFID1Enable PIN 1 ' Enable RFID reader 1 RFID2Enable PIN 3 ' Enable RFID reader 2 OpenLatch1 PIN 5 ' Output HIGH to open lock 1 OpenLatch2 PIN 6 ' Output HIGH to open latch 2 Door1Status PIN 4 ' Door status (needs ext 10k P.D.) Door2Status PIN 15 ' Door status (needs ext 10k P.D.) Door1Key PIN 10 ' Door 1 key (built in 10k Pull Up) Door2Key PIN 9 ' Door 2 key (built in 10k Pull Up) Input1 PIN 8 ' In 1 (built in 10k Pull Up) Input2 PIN 7 ' In 2 (built in 10k Pull Up) PowerLED PIN 14 ' Power indicator LED GPIOA PIN 13 ' General purpose I/O A GPIOB PIN 12 ' General purpose I/O B GPIOC PIN 11 ' General purpose I/O C ' -----[ Initialization ]-------------------------------------------------- Reset: 'INIT PINS LOW OpenLatch1 ' Ensure locks are latched LOW OpenLatch2 ' Ensure locks are latched HIGH RFID1Enable ' Disable reader HIGH RFID2Enable ' Disable reader HIGH PowerLED ' Power up power LED 'Set INPUT pin directions INPUT Door1Key ' Make door 1 key pin an input INPUT Door2Key ' Make door 2 key pin an input INPUT Door1Status ' Make door 1 status an input INPUT Door2Status ' Make door 2 status an input INPUT Input1 ' Make Input1 and input INPUT Input2 ' Make Input2 and input INPUT GPIOA ' Make GPIO A an input INPUT GPIOB ' Make GPIO B an input INPUT GPIOC ' Make GPIO C an input ' -----[ Program Code ]---------------------------------------------------- Main: '============================ RFID READER CHECK =========================== 'Enable reader 1 ReaderID = 1 LOW RFID1Enable ' Enable RFID reader 1 #IF __No_SPRAM #THEN 'SERIN RFID1, T2400, [WAIT($0A), STR tagBuffer\10] SERIN RFID1, T2400, 500, CheckKey, [WAIT($0A), STR tagBuffer\10] #ELSE 'SERIN RFID1, T2400, [WAIT($0A), SPSTR 10] SERIN RFID1, T2400, 500, CheckKey, [WAIT($0A), SPSTR 10] #ENDIF 'Disable reader 1 HIGH RFID1Enable ' Disable RFID reader 1 GOTO Check_List Check_Reader_2: 'Enable reader 2 ReaderID = 2 LOW RFID2Enable #IF __No_SPRAM #THEN 'SERIN RFID, T2400, [WAIT($0A), STR tagBuffer\10] SERIN RFID2, T2400, 500, CheckKey, [WAIT($0A), STR tagBuffer\10] #ELSE 'SERIN RFID2, T2400, [WAIT($0A), SPSTR 10] SERIN RFID2, T2400, 500, CheckKey, [WAIT($0A), SPSTR 10] #ENDIF 'Disable reader HIGH RFID2Enable GOTO Check_List '========================================================================== '============================== RFID TAG CHECK ============================ Check_List: 'Send host tag data via RS232 programming/debug pin SEROUT 16, 84, 10, ["R:", DEC ReaderID, ",T:", STR tagBuffer\10, CR] FOR tagNum = 1 TO LastTag ' loop through known tag IDs FOR tagIdx = 0 TO 9 ' check bytes in tag ID READ (tagNum - 1 * 10 + tagIdx), tagChar ' get tag data from EEPROM #IF __No_SPRAM #THEN ' compare tag ID to EEPROM IF (tagChar <> tagBuffer(tagIdx)) THEN Bad_Char #ELSE GET tagIdx, chkChar ' read char from SPRAM IF (tagChar <> chkChar) THEN Bad_Char ' compare char to RAM table #ENDIF NEXT GOTO Tag_Found ' all characters match! Bad_Char: NEXT ' bad tag, check next tag GOTO Main ' all tags checked, loop again Tag_Found: IF ReaderID = 1 THEN Open_Latch_1 ' Good tag found on reader 1, open latch 1 IF ReaderID = 2 THEN Open_Latch_2 ' Good tag found on reader 2, open latch 2 GOTO Main ' Should never execute, but just in case... '========================================================================== '============================= LATCH CONTROL ============================== Open_Latch_1: SEROUT 16, 84, 10, ["L:1", CR] ' Notify host of action HIGH OpenLatch1 ' Unlock latch 1 PAUSE 2500 ' Wait 2.5 seconds for entry LOW OpenLatch1 ' Disengage (relock latch 1) GOTO Main ' Loop to Main Open_Latch_2: SEROUT 16, 84, 10, ["L:2", CR] ' Notify host of action HIGH OpenLatch2 ' Energize strike PAUSE 2500 ' Wait 2.5 seconds for entry LOW OpenLatch2 ' Lock latch GOTO Main ' Loop to Main '========================================================================== '============================= KEY CONTROL ================================ CheckKey: 'Disable reader HIGH RFID1Enable ' Disable RFID reader 1 HIGH RFID2Enable ' Disable RFID reader 2 'If Door1Key is low, consider authorized IF (Door1Key = 0) THEN SEROUT 16, 84, 10, ["K:1", CR] GOTO Open_Latch_1 ENDIF 'If Door2Key is low, consider authorized IF (Door2Key = 0) THEN SEROUT 16, 84, 10, ["K:2", CR] GOTO Open_Latch_2 ENDIF 'return if nothing found IF ReaderID = 1 THEN Check_Reader_2 GOTO Check_Command '========================================================================== '============================== HOST INTERFACE ============================ Check_Command: 'tell host we're ready for a command strCommand = 0 'clear command variable ' ping host for command, sending door open status at the same time SEROUT 16, T9600, 10, ["D1:", DEC Door1Status, ",D2:", DEC Door2Status, ",I1:", DEC Input1, ",I2:", DEC Input2, ",GA:", DEC GPIOA, ",GB:", DEC GPIOB, ",GC:", DEC GPIOC, CR, "CMD", CR] SERIN 16, T9600, 500, Main, [STR strCommand\1] ' wait for command 'check command IF strCommand = "1" THEN Open_Latch_1 IF strCommand = "2" THEN Open_Latch_2 IF strCommand = "A" THEN GPIO = 1 GOTO TriggerGPIO ENDIF IF strCommand = "B" THEN GPIO = 2 GOTO TriggerGPIO ENDIF IF strCommand = "C" THEN GPIO = 3 GOTO TriggerGPIO ENDIF GOTO Main '========================================================================== '============================== GPIO CONTROL ============================== TriggerGPIO: IF GPIO = 1 THEN ' Trigger GPIO A OUTPUT GPIOA ' Make GPIO A an output HIGH GPIOA ' Push GPIO HIGH ENDIF IF GPIO = 2 THEN ' Trigger GPIO B OUTPUT GPIOB ' Make GPIO B an output HIGH GPIOB ' Push GPIO HIGH ENDIF IF GPIO = 3 THEN ' Trigger GPIO C OUTPUT GPIOC ' Make GPIO C an output HIGH GPIOC ' Push GPIO HIGH ENDIF PAUSE 250 ' Wait for 1/4 second IF GPIO = 1 THEN LOW GPIOA ' Drop GPIO A low INPUT GPIOA ' Make GPIO A an input ENDIF IF GPIO = 2 THEN LOW GPIOB ' Drop GPIO B low INPUT GPIOB ' Make GPIO B an input ENDIF IF GPIO = 3 THEN LOW GPIOC ' Drop GPIO C low INPUT GPIOC ' Make GPIO C an input ENDIF GOTO Main ' Loop to Main '========================================================================== END ' Every program needs an end