'----------------------------------------------- ' PASSWORD.BAS ' ' AUTHOR TIM BOX ' NOV 03 ' ' FOR THE PROTON+ COMPILER (BY LES JOHNSON) ' ' COMMENTS: ' SET THE DEFAULT PASSOWORDS AT THE BOTTOM ' IN THE EDATA STATEMENTS ' AND THE NUMBER OF KEY PRESSES REQUIRED ' IN MAX_NO_NOS ' ' COPYRIGHT? WOULD YOU TAKE ANY NOTICE ' IF I CLAIMED ANY? ' THOUGHT NOT. HAVE FUN! '----------------------------------------------- DEVICE 16F628 ALL_DIGITAL = TRUE DIM TRUE AS 1 ' DECLARE MY STANDARD MODIFIERS DIM FALSE AS 0 DIM ON AS 1 DIM OFF AS 0 '---- TIMER RELATED DIMS -------- DIM INPUT_TMR AS WORD ' KEY INPUT TIMER DIM INPUT_TMR_RUNNING AS BIT ' KEY INPUT TIMER CONTROL FLAG DIM LED_TMR AS BYTE ' LED TIMER DIM LED_TOGGLE_STATE AS BIT ' TOGGLE STATE FLAG DIM LED_FORCED_OFF AS BIT ' USED TO FORCE OF THE LED DIM LED_ON AS BYTE ' RELOAD STORES FOR LED TMRS DIM LED_OFF AS BYTE '---- LED FLASH TIMER VALUES ---- ' PASSWORD ENTRY LED FLASH RATE DIM P_ENTRY_ON_TIME AS 60 ' 100'S SECOND THAT LED IS ON FOR DIM P_ENTRY_OFF_TIME AS 60 ' 100'S SECOND THAT LED IS OFF FOR ' NEW PASSWORD ENTRY LED FLASH RATE DIM N_P_ENTRY_ON_TIME AS 10 ' 100'S SECOND THAT LED IS ON FOR DIM N_P_ENTRY_OFF_TIME AS 10 ' 100'S SECOND THAT LED IS OFF FOR DIM INPUT_TMR_VALUE AS 300 ' 100'S OF A SECOND BETWEEN NUMBER ENTRYS '---- KEYBOARD RELATED DIMS ----- DIM KEY AS BYTE ' HOLDS THE CURRENT KEY PRESS DIM LAST_KEY AS BYTE ' KEY VALUE FROM LAST SCAN DIM KEY_STATUS AS BIT ' SET WHEN KEY CHECK IS TRUE DIM NEW_KEY AS BIT ' SET WHEN A NEW KEY IS READ DIM NO_KEY AS 255 ' VALUE TO INDICATE NO KEY '---- EEPROM READ/WRITE DIMS ----- DIM EEPASSWORD_ADDRESS AS BYTE ' EEPROM ADDRESS DIM EEPASSWORD_DATA AS BYTE ' TRANSFER BYTE DIM OFFSET AS BYTE ' OFFSET '---- PASSWORD, MODE DIMS AND ALIAS'S -- DIM MODE AS BYTE ' CURRENT MODE DIM NO_PASSWORDS AS 2 DIM MAX_NO_NOS AS 6 ' NUMBER OF CHRS IN PASSWORD DIM PASSWORD_POINTER AS BYTE ' POINTER TO NEXT CHR IN PASSWORD DIM PASSWORD AS BYTE ' PASSWORD STATUS RETURNED IN THIS DIM PASSWORD_STR[MAX_NO_NOS] AS BYTE ' PASSWORD COLLECTOR STRING DIM PASSWORD_OK AS BIT ' FLAG TO INDICATE IF PASSWORD MATCHED DIM PASSWORD_ENTERED AS BIT ' INDICATES WHEN THE FULL PASSWORD HAS BEEB ENTERED DIM STANDARD_PASSWORD_ADDRESS AS MAX_NO_NOS ' THE START ADDRESS OF THE STANDARD PASSWORD DIM STANDBY AS 255 ' STANDBY MODE DIM PASSWORD_ENTRY AS 254 ' PASSWORD ENTRY MODE DIM NEW_PASSWORD_ENTRY AS 0 ' NEW PASSWORD ENTRY MODE DIM NORMAL_ENTRY AS 1 ' PASSWORD VALUE RETURNED IF MATCH IS MADE WITH NORMAL PASSWORD DIM MASTER_PASSWORD AS 0 ' PASSWORD VALUE RETURNED IF MATCH IS MADE WITH MASTER PASSWORD '---- HARDWARE PORT ALIAS'S -------------- DIM LED AS PORTA.0 DIM RELAY AS PORTA.1 DIM RELAY_ON_TIME AS 10000 '---- INTERRUPT CONTROL DIMS ------------- DIM GIE AS INTCON.7 DIM TIMER1REG AS TMR1L.WORD SYMBOL FUDGE_FACTOR = 7 SYMBOL TMR1_VAL =((65536)-(XTAL*2500))+FUDGE_FACTOR ' CALCULATE OSC OFFSET VALUES FOR 100HZ INTERRUPT ON_INTERRUPT INTERRUPT_ROUTINE ' WHERE TO GO ON AN INTERRUPT GOTO START ' JUMP OVER ALL SUBS '----------------------------------------------- ' INTERRUPT ROUTINE TO SERVICE THE TIMERS AND ' LED FLASHES ' '----------------------------------------------- INTERRUPT_ROUTINE: CLEAR T1CON.0 ' STOP TMR1 TIMER1REG = TIMER1REG + TMR1_VAL ' LOAD TMR1 SET T1CON.0 ' START TMR1 IF INPUT_TMR_RUNNING = TRUE THEN ' IS THIS TIMER RUNNING DEC INPUT_TMR ' DEC THE TIMER IF INPUT_TMR = 0 THEN INPUT_TMR_RUNNING = FALSE ' IF WE ARE AT ZERO INDICATE SO ENDIF DEC LED_TMR ' DEC THE TIMER IF LED_TMR = 0 THEN ' IF ZERO IF LED_TOGGLE_STATE = TRUE THEN ' TOGGLE THE STATE IF LED_FORCED_OFF = FALSE THEN LED = ON LED_TMR = LED_ON ' LOAD THE TIMER LED_TOGGLE_STATE = FALSE ' TOGGLE STATE ELSE LED = OFF LED_TMR = LED_OFF ' LOAD THE TIMER LED_TOGGLE_STATE = TRUE ' TOGGLE STATE ENDIF ENDIF CLEAR PIR1.0 ' CLEAR TMR1 INTERRUPT FLAG CONTEXT RESTORE ' END OF INTERRUPT ROUTINE '----------------------------------------------- ' SCAN THE KEYBOARD AND CHECK FOR SET KEY PRESSES ' '----------------------------------------------- KEY_SCAN: KEY = INKEY ' SCAN THE KEYPAD KEY = LOOKUP KEY, [1,2,3,255,4,5,6,NO_KEY,7,8,9,NO_KEY,"*",0,"#",NO_KEY,NO_KEY] IF KEY = NO_KEY THEN NEW_KEY = TRUE GOTO KEY_EXIT ' NEW KEY IS ONLY CLEARED BY A NO_KEY BEING SEEN ENDIF IF NEW_KEY = TRUE THEN ' IF THIS IS THE FIRST TIME WE HAVE SEEN IF KEY <> LAST_KEY THEN DELAYMS 50 ' THIS KEY, DE-BOUNCE ENDIF KEY_EXIT: LAST_KEY = KEY ' SAVE THE KEY VALUE RETURN CHK_KEY_0_9: KEY_STATUS = FALSE ' PRECONDITION THE RESULT IF NEW_KEY = TRUE THEN ' IF THIS PRESS IS NEW TO US IF KEY >= 0 THEN ' IF WE ARE IN THE RANGE 0 - 9 IF KEY <= 9 THEN KEY_STATUS = TRUE ' RESULT IS TRUE NEW_KEY = FALSE ' LATCH THE KEY AS BEING READ RETURN ENDIF ENDIF ENDIF RETURN CHK_KEY_CANCEL: KEY_STATUS = FALSE ' PRECONDITION THE RESULT IF NEW_KEY = TRUE THEN ' IF THIS PRESS IS NEW TO US IF KEY = "#" THEN ' IF WE SEE THE "#" KEY KEY_STATUS = TRUE ' RESULT IS TRUE NEW_KEY = FALSE ' LATCH THE KEY AS BEING READ RETURN ENDIF ENDIF RETURN '----------------------------------------------- ' LOAD THE PASSWORD ARRAY AND RESET WHEN INKEY TIMER ' TIMES OUT ' ALSO RE-LOADS INKEY TIMER ON EVERY VALID KEY PRESS '----------------------------------------------- PASSWORD_ACCUMULATOR: GOSUB CHK_KEY_0_9 ' CHECK FOR KEYS 0 - 9 IF KEY_STATUS = TRUE THEN ' DID WE SEE ONE? GOSUB LOAD_INPUT_TIMER ' YES SO RELOAD INPUT TIMER PASSWORD_STR[PASSWORD_POINTER] = KEY ' SAVE THE ENTERED NUMBER IN THE ARRAY INC PASSWORD_POINTER ' UP THE POINTER IF PASSWORD_POINTER > MAX_NO_NOS-1 THEN ' HAVE WE EXCEEDED THE MAXIMUM NUMBER OF CHARS PASSWORD_ENTERED = TRUE ' YES SO THATS A WHOLE PASSWORD ENDIF ENDIF ' NO SO BACK TO STANDBY MODE RETURN ' ALL DONE SO RETURN '----------------------------------------------- ' COMPARES THE ENTERED PASSWORD WITH THAT IN EEPROM ' INDICATES RESULT WITH FLAG AND IF A MATCH IS FOUND ' GENERATES A VALUE TO INDICATE WHICH PASSWORD '----------------------------------------------- PASSWORD_COMPARE: EEPASSWORD_ADDRESS = 0 REPEAT ' CHECK ALL THE PASSWORDS STORED PASSWORD_OK = TRUE ' WE NEED TO PRE LOAD THIS FLAG FOR THE ROUTINE TO WORK CLEAR OFFSET REPEAT ' LOOP THROUGH ALL THE CHARS OF THE NUMBER EEPASSWORD_DATA = EREAD EEPASSWORD_ADDRESS + OFFSET ' FIRST READ IN THE EEPROM STORE PASSWORD IF PASSWORD_STR[OFFSET] <> EEPASSWORD_DATA THEN ' THEN COMPARE IT AGAINST THE ONE ON OFFER PASSWORD_OK = FALSE ' THIS CHAR DOES NOT MATCH SO CHECK AGAINST NEXT ONE ENDIF INC OFFSET UNTIL OFFSET = MAX_NO_NOS IF PASSWORD_OK = TRUE THEN ' A MATCH HAS BEEN FOUND! PASSWORD = EEPASSWORD_ADDRESS / MAX_NO_NOS ' WORK OUT A NUMBER VALUE FOR WHICH PASSWORD PASSED I.E. MASTER OR USER RETURN ENDIF EEPASSWORD_ADDRESS = EEPASSWORD_ADDRESS + MAX_NO_NOS UNTIL EEPASSWORD_ADDRESS = MAX_NO_NOS * NO_PASSWORDS RETURN ' IF WE GET TO HERE THERE WAS NO MATCH MATCHED '----------------------------------------------- ' PERFORMS AN UPDATE ON TIMERS FLAGS ETC REQUIRED ' WHEN EVER A MODE CHANGE IS REQUIRED ' '----------------------------------------------- MODE_CONTROL: GIE = 0 ' TURN OFF GLOBAL INTERRUPTS WHILE GIE = 1 : GIE = 0 : WEND ' AND MAKE SURE THEY ARE OFF IF MODE = PASSWORD_ENTRY THEN LED_FORCED_OFF = FALSE ' ENABLE THE LED TO LIGHT LED_ON = P_ENTRY_ON_TIME ' LOAD THE RELOAD VARS WITH THE LED_OFF = P_ENTRY_OFF_TIME ' PASSWORD ENTRY LED FLASH TIMES LED_TMR = 1 ' FORCE A RELOAD NEXT INTERRUPT LED_TOGGLE_STATE = 1 ENDIF IF MODE = NEW_PASSWORD_ENTRY THEN LED_ON = N_P_ENTRY_ON_TIME ' LOAD THE RELOAD VARS WITH THE LED_OFF = N_P_ENTRY_OFF_TIME ' NEW PASSWORD ENTRY LED FLASH TIMES LED_TMR = 1 ' FORCE A RELOAD NEXT INTERRUPT LED_TOGGLE_STATE = 1 ' FORCE THE LED ON STRAIGHT AWAY ENDIF IF MODE = STANDBY THEN LED_FORCED_OFF = TRUE LED_ON = 1 ' LOAD THE RELOAD VARS WITH THE LED_OFF = 1 ' STANDBY LED FLASH TIMES LED_TMR = 1 ' FORCE A RELOAD NEXT INTERRUPT INPUT_TMR_RUNNING = FALSE ENDIF GIE = 1 ' TURN ON GLOBAL INTERRUPTS AGAIN GOSUB CLEAR_PASSWORD_BUFFER ' ALWAYS SEEMS TO BE NEEDED RETURN '----------------------------------------------- ' SUB TO RESET TO STANDBY AS USED MOST OFTEN ' ' '----------------------------------------------- SETMODE_STANDBY: MODE = STANDBY GOSUB MODE_CONTROL RETURN '----------------------------------------------- ' LOAD THE INPUT TIMER WITH IT'S TIME OUT VALUE ' ' '----------------------------------------------- LOAD_INPUT_TIMER: GIE = 0 'TURN OFF GLOBAL INTERRUPTS WHILE GIE = 1 : GIE = 0 : WEND ' AND MAKE SURE THEY ARE OFF INPUT_TMR = INPUT_TMR_VALUE ' RELOAD THE INPUT TIMER INPUT_TMR_RUNNING = TRUE ' MAKE SURE IT IS RUNNING GIE = 1 ' TURN THE INTERRUPTS BACK ON RETURN '----------------------------------------------- ' CLEAR THE PASSWORD BUFFER AND RESET POINTER ' ' '----------------------------------------------- CLEAR_PASSWORD_BUFFER: FOR PASSWORD_POINTER = 0 TO MAX_NO_NOS ' ROUTINE TO CLEAR THE PASSWORD ARRAY CLEAR PASSWORD_STR[PASSWORD_POINTER] ' CLEAR THE PASSWORD BUFFER NEXT CLEAR PASSWORD_POINTER ' RESET THE POINTER RETURN '----------------------------------------------- ' THIS ROUTINE IS JUMPED TO WHEN A NORMAL PASSWORD ' IS ENTERED. CONTROL LOCK OR WHAT EVER YOU WANTED ' THE UNIT FOR IN HERE '----------------------------------------------- NORMAL_ENTRY_ROUTINE: GOSUB SETMODE_STANDBY ' WE WILL USE STANDBY MODE RELAY = ON ' AS THAT LEAVES THE LED OFF DELAYMS RELAY_ON_TIME ' OPEN THE DOOR LOCK OR WHATEVER FOR THIS LONG RELAY = OFF PASSWORD_OK = FALSE GOTO MAIN_LOOP '----------------------------------------------- ' WHEN MASTER MODE PASSWORD IS ENTERED YOU ENABLE ' THE NORMAL PASSWORD TO BE CHANGED ' '----------------------------------------------- NEW_PASSWORD_ENTRY_ROUTINE: MODE = NEW_PASSWORD_ENTRY ' INDICATE YOU ARE IN THIS MODE BY THE GOSUB MODE_CONTROL ' LED FLASH RATE GOSUB LOAD_INPUT_TIMER ' HAVE TO LOAD THE INPUT TIMER NEW_PASSWORD_ENTRY_LOOP: GOSUB KEY_SCAN ' IMPORTANT TO SCAN THE KEYBOARD GOSUB PASSWORD_ACCUMULATOR ' GET THE PASSWORD IF INPUT_TMR_RUNNING = FALSE THEN ' HAS THE INPUT TIMER TIMED OUT GOSUB SETMODE_STANDBY ' YES SO RETURN TO STANDBY MODE GOTO MAIN_LOOP ' AND BACK TO NORMAL RUNNING ENDIF IF PASSWORD_ENTERED = TRUE THEN ' HAS ALL THE NUMBERS BEEN ENTERED GOSUB PASSWORD_COMPARE ' YES SO COMPARE THE PASSWORD PASSWORD_ENTERED = FALSE ' CLEAR THE FLAG IF PASSWORD_OK = FALSE THEN ' ONLY PROCCED IF ITS A NEW PASSWORD CLEAR OFFSET REPEAT ' WRITE THE NEW PASSWORD IN EWRITE STANDARD_PASSWORD_ADDRESS + OFFSET,[PASSWORD_STR[OFFSET]] INC OFFSET UNTIL OFFSET = MAX_NO_NOS ENDIF GOSUB SETMODE_STANDBY ' WHAT EVER HAPPENS BACK TO STANDBY MODE GOTO MAIN_LOOP ' AND RUN AS NORMAL ENDIF GOTO NEW_PASSWORD_ENTRY_LOOP ' ROUND THE LOOP AGAIN '----------------------------------------------- ' INITALISATION COMMANDS '----------------------------------------------- START: T1CON = %00000000 ' Set up Tmr1 to have 1:1 prescaler and act as a timer PIR1.0 = 0 ' Clear Tmr1 interrupt flag INTCON = %11000000 ' Global and Peripheral interrupts on PIE1.0 = 1 ' Enable Tmr1 as peripheral interrupt source T1CON.0 = 1 CLEAR trisa = %11111100 GOSUB SETMODE_STANDBY '----------------------------------------------- ' MAIN LOOP ' CALLS THE KEYBOARD TO BE SCANNED ' WAITS FOR A KEY PRESS BEFORE INITIATING ' THE PASSWORD TO BE COLLECTED ' WHEN THE WHOLE PASSWORD IS ENTERED ' CHECKS FOR CORRECT RESULT AND DECIDES WHAT TO DO ' ALSO ENABLES THE CANCELATION OF THE PASSWORD ' CURRENTLY BEING ENTERED '----------------------------------------------- MAIN_LOOP: GOSUB KEY_SCAN IF MODE = STANDBY THEN ' IF WE ARE IN STANDBY MODE GOSUB CHK_KEY_0_9 ' HAS A KEY BEEN PRESSED IF KEY_STATUS = TRUE THEN ' YES SO WE ENTER PASSWORD ENTRY MODE MODE = PASSWORD_ENTRY ' GOSUB MODE_CONTROL NEW_KEY = TRUE ' SET THE NEW KEY FLAG SO THE GOSUB LOAD_INPUT_TIMER ' HAVE TO LOAD THE INPUT TIMER TO START WITH GOSUB PASSWORD_ACCUMULATOR ' PASSWORD ACCUMULATOR ADDS KEY PRESS'S STRAIGHT AWAY ENDIF ELSE ' WE ARE NOT IN STANDBY SO ADD SOME KEY PRESSES IF INPUT_TMR_RUNNING = FALSE THEN ' HAS THE INPUT TIMER TIMED OUT GOSUB SETMODE_STANDBY ' YES SO RETURN TO STANDBY MODE GOTO MAIN_LOOP ' AND BACK TO NORMAL RUNNING ENDIF GOSUB PASSWORD_ACCUMULATOR ENDIF IF PASSWORD_ENTERED = TRUE THEN ' HAVE ALL THE NUMBERS BEEN ENTERED GOSUB PASSWORD_COMPARE ' YES SO COMPARE PASSWORD PASSWORD_ENTERED = FALSE ' CLEAR THE FLAG IF PASSWORD_OK = TRUE THEN ' DID IT MATCH? GOSUB MODE_CONTROL ' YES SO CONFIGURE SYSTEM TO THIS NEW PASSWORD LEVEL GOSUB CLEAR_PASSWORD_BUFFER ' THEN JUMP TO APPROPRIATE ROUTINE IF PASSWORD = NORMAL_ENTRY THEN GOTO NORMAL_ENTRY_ROUTINE ' NORMAL ENTRY ROUTINE IF PASSWORD = NEW_PASSWORD_ENTRY THEN GOTO NEW_PASSWORD_ENTRY_ROUTINE ELSE GOSUB SETMODE_STANDBY ' PASSWORD FAILED SO BACK TO STANDBY MODE ENDIF ENDIF GOSUB CHK_KEY_CANCEL IF KEY_STATUS = TRUE THEN ' IF THE CANCEL KEY IS PRESSED GOSUB SETMODE_STANDBY ' RESET MODE TO STANDBY ENDIF GOTO MAIN_LOOP ' ROUND AND ROUND WE GO END '--------------------------------------------------- ' PROGRAM TIME PASSWORD SETTINGS ' '--------------------------------------------------- EDATA 1,2,3,4,5,6 ' DEFAULT MASTER PASSWORD EDATA 2,3,4,5,6,7 ' DEFAULT NORMAL PASSWORD