How to jump back to an original state? - PIC programming

Thread Starter

draeberg

Joined Apr 24, 2008
7
I have made a well functioning electronic combination lock, with a lot of help from Nigel's page: http://www.winpicprog.co.uk/. Well, the thing is, that I made it work perfectly until one thing, that seems to annoy me.

To simulate an unlock/lock stage I "make" the PIC jump from one place in the code to another place.

What happens is that when you start the PIC, it will start up with a text displaying that says "Enter Code" in english (I know it is not what says in the text, but it is in Danish). I enter the code and it works all well. Then I make it jump and it says "Locked: Enter code". You will therefore have to enter the code once again to unlock (or the right word should be jump) the pic and it should jump back and display "Enter code". It all works well, except that when it says "Locked...." you have to enter any 4 bit code, but the right code to unlock it, and if you enter the right code it keeps on jumping back. So you see it works quite well, except that it should work the other round, so when you enter the wrong code it keeps on looping and says "Locked: Enter code" and when the right code is entered it will jump And say "Enter code:"....

I make it jump by writing:
Rich (BB code):
Correct_Wait call Delay255
  call Delay255
  call Delay255
  call Delay255
  goto Init2
Where init2 is the locked stage, it is actually an exact copy of the init, and does the same thing. Except that when wrong code is entered it should jump back to init2 and when correct it should jump to init.

Why does it not work?
Where did I go wrong?
You can see what I have done in the code given below:

Rich (BB code):
 LIST p=16F628  ;Her fortælles til assembler hvilken chip der bruges
 include "P16F628.inc" ;Her defineres hvad der skal inkluderes til chippen
        ;hvilket er nogle standarder som programmet kan gå ud fra
        ;når chippen skal programmeres
 ERRORLEVEL 0, -302 ;suppress bank selection messages
 __config 0x3D18
 
  cblock 0x20   ;start of general purpose registers
   count   ;used in looping routines
   count1   ;used in delay routine
   counta   ;used in delay routine
   countb   ;used in delay routine
   tmp1   ;temporary storage
   tmp2
   templcd   ;temp store for 4 bit mode
   templcd2
   key   ;which key was pressed
   rows   ;counter for number of rows
   code1   ;registers for secret code
   code2
   code3
   code4
   key1   ;registers for keyed attempts
   key2
   key3
   key4
  endc
LCD_PORT Equ PORTA
LCD_TRIS Equ TRISA
LCD_RS  Equ 0x04   ;LCD handshake lines
LCD_RW  Equ 0x06
LCD_E  Equ 0x07
KEY_PORT Equ PORTB   ;keypad port
KEY_TRIS Equ TRISB
Col1  Equ 0   ;pins used for keypad inputs
Col2  Equ 1
Col3  Equ 2
Col4  Equ 3
  org 0x0000
  goto Start
Key_Table   ADDWF   PCL       , f ;translation table for keypad
             RETLW   0x31 ;1
             RETLW   0x34 ;4
             RETLW   0x37 ;7
             RETLW   0x2a ;*
             RETLW   0x32 ;2
             RETLW   0x35 ;5
             RETLW   0x38 ;8
             RETLW   0x30 ;0
             RETLW   0x33 ;3
             RETLW   0x36 ;6
             RETLW   0x39 ;9
             RETLW   0x23 ;#
             RETLW   0x43 ;C
             RETLW   0x44 ;D
             RETLW   0x45 ;E
             RETLW   0x46 ;F
 
HEX_Table   ADDWF   PCL       , f  ;hex table for LCD routines
             RETLW   0x30
             RETLW   0x31
             RETLW   0x32
             RETLW   0x33
             RETLW   0x34
             RETLW   0x35
             RETLW   0x36
             RETLW   0x37
             RETLW   0x38
             RETLW   0x39
             RETLW   0x41
             RETLW   0x42
             RETLW   0x43
             RETLW   0x44
             RETLW   0x45
             RETLW   0x46
 
Text  addwf PCL, f
  retlw 'S'
  retlw 'k'
  retlw 'r'
  retlw 'i'
  retlw 'v'
  retlw ' '
  retlw 'k'
  retlw 'o'
  retlw 'd'
  retlw 'e'
  retlw ':'
  retlw 0x00
Text2  addwf PCL, f
  retlw 'L'
  retlw 'a'
  retlw 'a'
  retlw 's'
  retlw 't'
  retlw ':'
  retlw ' '
  retlw 'S'
  retlw 'k'
  retlw 'r'
  retlw 'i'
  retlw 'v'
  retlw 0x00
Wrong_Text addwf PCL, f
  retlw 'F'
  retlw 'o'
  retlw 'r'
  retlw 'k'
  retlw 'e'
  retlw 'r'
  retlw 't'
  retlw ' '
  retlw 'k'
  retlw 'o'
  retlw 'd'
  retlw 'e'
  retlw 0x00
Correct_Text addwf PCL, f
  retlw 'K'
  retlw 'o'
  retlw 'r'
  retlw 'r'
  retlw 'e'
  retlw 'k'
  retlw 't'
  retlw ' '
  retlw 'k'
  retlw 'o'
  retlw 'd'
  retlw 'e'
  retlw 0x00
Start  movlw 0x07
  movwf CMCON   ;turn comparators off (make it like a 16F84)
Initialise movlw '0'   ;set 4 digit secret code
  movwf code1
  movlw '0'
  movwf code2
  movlw '0'
  movwf code3
  movlw '0'
  movwf code4
 
SetPorts bsf  STATUS,  RP0 ;select bank 1
  movlw 0x00   ;make all pins outputs
  movwf LCD_TRIS
  movlw 0x0F   ;set keypad pins
  movwf KEY_TRIS  ;half in, half out
  movwf TRISB
  bcf  STATUS,  RP0 ;select bank 0
Init  call LCD_Init  ;setup LCD
 
  clrf count   ;set counter register to zero
Message  movf count, w  ;put counter value in W
  call Text   ;get a character from the text table
  xorlw 0x00   ;is it a zero?
  btfsc STATUS, Z
  goto Main
  call LCD_Char
  incf count, f
  goto Message
Wrong  call LCD_Clr
  clrf count   ;set counter register to zero
Message1 movf count, w  ;put counter value in W
  call Wrong_Text  ;get a character from the text table
  xorlw 0x00   ;is it a zero?
  btfsc STATUS, Z
  goto Wrong_Wait
  call LCD_Char
  incf count, f
  goto Message1
Wrong_Wait call Delay255
  call Delay255
  call Delay255
  call Delay255
  goto Init
Correct  call LCD_Clr
  clrf count   ;set counter register to zero
Message2 movf count, w  ;put counter value in W
  call Correct_Text  ;get a character from the text table
  xorlw 0x00   ;is it a zero?
  btfsc STATUS, Z
  goto Correct_Wait
  call LCD_Char
  incf count, f
  goto Message2
Correct_Wait call Delay255
  call Delay255
  call Delay255
  call Delay255
  goto Init2
Init2  call LCD_Init  ;setup LCD
 
  clrf count   ;set counter register to zero
Messagelaas movf count, w  ;put counter value in W
  call Text2   ;get a character from the text table
  xorlw 0x00   ;is it a zero?
  btfsc STATUS, Z
  goto Main
  call LCD_Char
  incf count, f
  goto Messagelaas
Wrong2  call LCD_Clr
  clrf count   ;set counter register to zero
Messagelaas1 movf count, w  ;put counter value in W
  call Wrong_Text  ;get a character from the text table
  xorlw 0x00   ;is it a zero?
  btfsc STATUS, Z
  goto Wrong_Wait2
  call LCD_Char
  incf count, f
  goto Messagelaas1
Wrong_Wait2 call Delay255
  call Delay255
  call Delay255
  call Delay255
  goto Init
Correct2 call LCD_Clr
  clrf count   ;set counter register to zero
Messagelaas2 movf count, w  ;put counter value in W
  call Correct_Text  ;get a character from the text table
  xorlw 0x00   ;is it a zero?
  btfsc STATUS, Z
  goto Correct_Wait2
  call LCD_Char
  incf count, f
  goto Messagelaas2
Correct_Wait2 call Delay255
  call Delay255
  call Delay255
  call Delay255
  goto Init2
Main  movlw d'1'
  call LCD_Line2W  ;move to 2nd row, 2nd column
  call LCD_CurOn
  call Chk_Keys  ;wait for key
  movwf key1   ;store first digit
  call LCD_Char
  call Chk_Keys  ;wait for key
  movwf key2   ;store second digit
  call LCD_Char
  call Chk_Keys  ;wait for key
  movwf key3   ;store third digit
  call LCD_Char
  call Chk_Keys  ;wait for key
  movwf key4   ;store fourth digit
  call LCD_Char
  call LCD_CurOff
 
Chk_Code movf code1, w  ;test first digit
  subwf key1, w
  btfss STATUS, Z
  goto Wrong
  movf code2, w  ;test second digit
  subwf key2, w
  btfss STATUS, Z
  goto Wrong
  movf code3, w  ;test third digit
  subwf key3, w
  btfss STATUS, Z
  goto Wrong
  movf code4, w  ;test fourth digit
  subwf key4, w
  btfss STATUS, Z
  goto Wrong
  goto Correct
 

Caveman

Joined Apr 15, 2008
471
If I read this right, you are just absolutely going from init to init2. This isn't right. The way your state machine should work is like this:
2 states: LOCKED and UNLOCKED.
If code is wrong, state stays the same.
If code is right, state toggles.

Here's the pseudocode:
Rich (BB code):
Start:
  Initialize STATE = UNLOCKED.
RunLoop:
  if STATE = LOCKED
      Print "Locked: Enter code"
  else
      Print "Unlocked: Enter code"
  Get Code Entry
  If entry is correct
      Print "Correct"
      Toggle State
  Else entry is incorrect
      Print "Wrong"
  Delay so statement can be read.
  Goto RunLoop
Once you understand the pseudocode, then you can flesh it out with the details.
 

Caveman

Joined Apr 15, 2008
471
Rich (BB code):
Start:
  Initialize STATE = UNLOCKED.
RunLoop:
  if STATE = LOCKED
      Print "Locked: Enter code"
  else
      Print "Unlocked: Enter code"
  Get Code Entry
  If entry is correct
      Print "Correct"
      Toggle State
  Else entry is incorrect
      Print "Wrong"
  Delay so statement can be read.
  Goto RunLoop
Which step do you not understand how to translate to assembly? You already have coded almost all of the steps.
 

Thread Starter

draeberg

Joined Apr 24, 2008
7
Well, I do not now know how to write the beginning of the runloop.
I already wrote some of the code...?

As shown below, I thought I was doing something like the example you given.

The only thing I want is to make it jump back when to the first state when the code is entered correct, when in "locked" stage, and when wrong it should keep looping there. And everytime you start the system it should be reset as if it was unlocked. And I understand the pseudocode, but I can not find the way how to simulate it.

I was thinking of something like what I have already written.

Rich (BB code):
Init  call LCD_Init  ;setup LCD

  clrf count   ;set counter register to zero
Message  movf count, w  ;put counter value in W
  call Text   ;get a character from the text table
  xorlw 0x00   ;is it a zero?
  btfsc STATUS, Z
  goto Main
  call LCD_Char
  incf count, f
  goto Message
Wrong  call LCD_Clr
  clrf count   ;set counter register to zero
Message1 movf count, w  ;put counter value in W
  call Wrong_Text  ;get a character from the text table
  xorlw 0x00   ;is it a zero?
  btfsc STATUS, Z
  goto Wrong_Wait
  call LCD_Char
  incf count, f
  goto Message1
Wrong_Wait call Delay255
  call Delay255
  call Delay255
  call Delay255
  goto Init
Correct  call LCD_Clr
  clrf count   ;set counter register to zero
Message2 movf count, w  ;put counter value in W
  call Correct_Text  ;get a character from the text table
  xorlw 0x00   ;is it a zero?
  btfsc STATUS, Z
  goto Correct_Wait
  call LCD_Char
  incf count, f
  goto Message2
Correct_Wait call Delay255
  call Delay255
  call Delay255
  call Delay255
  goto Init2
 

Caveman

Joined Apr 15, 2008
471
Create a variable called "state" in your list of registers. If state is 0, we will call it UNLOCKED, if 1 it is LOCKED

Rich (BB code):
Start:
  clrf state        ; Initialize STATE = UNLOCKED.
RunLoop:
  btfss state, 0   ; if state = LOCKED, skip the next line.
  goto UL1          ; not locked, so go to the unlocked code.
  call ShowLockedQuery  ; Print "Locked: Enter code"
  goto ML1
UL1:
  call ShowUnlockedQuery ; Print "Unlocked: Enter code"
ML1:
  ; Get Code Entry in the same method as before.
  ;If entry is correct
  ;    Print "Correct"
  ;    Toggle State
  ;Else entry is incorrect
  ;    Print "Wrong"
  ;Delay so statement can be read.
goto RunLoop
Does this make sense?
 
Top