'****************************************************************
'*  Name    : CodeLock.bas                                      *
'*  Author  : F.San                                             *
'*  Date    : 31.08.2004                                        *
'*  Version : 1.0.1                                             *
'*  Notes   : Programable Code Lock with the PIC-16F84          *
'****************************************************************

'Kilit şifresi 4x3 matrix şeklinde bağlı bir tuş takımından girilir. 
'Devre programlandığı anda kilit şifresi 1234 dür. 
'Röle çıkışını aktif hale getirmek yani kilidi açmak için 1234 tuşlanır ve 
'ardından # basılır. Eğer şifrede hata yoksa röle çeker. 

'Mevcut şifreyi değiştirmek için ise , örneğin 1961’e : 1234 * 1961#1961# gibi 
'bir tuş işlem sırası izlenmelidir. 
'Şifre değiştirme başarısızsa eski şifre geçerliliğini korur.

@ device  pic16f84, xt_osc, wdt_off, pwrt_on, protect_off

'**********************************************
RL1_ON_time con 1000 * 3  'sec. Relay ON time
Kp_TimeOut  con 1000 * 5  'sec. Timeout (reset) 
'**********************************************

OPTION_REG.7 = 0   ' PORTB Pullups.
TrisA = 0          ' PORTA, all outputs
PortA = 16         ' Turn off Buzer
TrisB = %11110000  ' PORTB.0-3 outputs, 4-7 inputs  
PortB = 0
 
LD1  var PortA.2
RL1  var PortA.3
BUZ  var portA.4
cnt  var byte
cnt2 var word

key  var byte
col  var byte
row  var byte
keycnt var byte
pwOK var bit

keybuf var byte[15]
pwbuf var byte[4]

EEPROM 0,[1,2,3,4] 'Default password 1,2,3,4 programmed at EEprom location 0..3
Read 0, pwbuf[0]   'Copy password from EEprom address 0..3 in to pwbuf[0..3]
Read 1, pwbuf[1]
Read 2, pwbuf[2]
Read 3, pwbuf[3]

pwOK = 0
keycnt = 0
cnt2 = 0

Main:
    high ld1
    if cnt2 > Kp_TimeOut then
        gosub Beep
        goto Clr_keybuf 
    endif
    goto Chk_KEYPAD
goto Main

Chk_KEYPAD:
   for row = 0 to 3 
      PORTB = (dcd row) ^ $f    
      pause 1
      if cnt2 > 0 then cnt2 = cnt2 + 1
      col = PORTB >> 4
      if (col <> $f) then ' key pressed 
         key = (row * 3) + (ncd (col ^ $f))
         goto Got_KEY
      endif
   next 
goto Main    

Got_KEY:
   cnt2 = 1
   gosub Beep
   while (PORTB >> 4) <> $f  
      pause 1
   wend
   if key = 11 then key = 0
   keybuf[keycnt] = key
   goto Chk_keycnt
goto Main

Chk_keycnt:    
   select case keycnt
      case 4
         gosub Chk_PwOK
         if pwOK then 
            if keybuf[keycnt] = 12 then Access_OK
            if keybuf[keycnt] <> 10 then Clr_keybuf
            gosub Beep
         else
            goto Clr_keybuf
         endif
      case 9
         if keybuf[keycnt] <> 12 then Clr_keybuf
         gosub Beep
      case 14
         if keybuf[keycnt] <> 12 then Clr_keybuf
         gosub Beep
         gosub Chk_NewPwOK
         if pwOK then 
            gosub Beep
            gosub Pw_Change
            gosub Beep
            goto Clr_keybuf
         else
            goto Clr_keybuf
         endif
      case else
         if keybuf[keycnt] = 12 then Clr_keybuf
   end select
   keycnt = keycnt + 1    
goto Main

Access_OK:
   High RL1
   pause RL1_ON_time
   low RL1

Clr_keybuf:
   for cnt = 0 to 14 
      keybuf[cnt] = cnt 
   next
   keycnt = 0 
   cnt2 = 0 
goto Main

Chk_PwOK: 
   PwOK = 0
   if (keybuf[0] = pwbuf[0]) and (keybuf[1] = pwbuf[1]) and _ 
      (keybuf[2] = pwbuf[2]) and (keybuf[3] = pwbuf[3]) then pwok = 1
return 

Chk_NewPwOK: 
   PwOK = 0
   if (keybuf[5] = keybuf[10]) and (keybuf[6] = keybuf[11]) and _
      (keybuf[7] = keybuf[12]) and (keybuf[8] = keybuf[13]) then pwok = 1
return 

Pw_Change:   
   pwbuf[0] = keybuf[5]
   pwbuf[1] = keybuf[6]
   pwbuf[2] = keybuf[7]
   pwbuf[3] = keybuf[8]
  
   Write 0, pwbuf[0]        'Store new password to EEprom location 0..3        
   Write 1, pwbuf[1]
   Write 2, pwbuf[2]
   Write 3, pwbuf[3]
return

Beep:
   low ld1
   low buz 
   pause 40
   high buz
return

end 
