Advice on reducing programme size for a code newbie.

Blazemaguire

Senior Member
Hi,

This is my most ambitious programe yet (for me at least, go easy!) - I'm trying to make a simple keypad activated lock, but also with a 'set code' mode where the 4 digit pin can be set from within the programe.

I had the structure working fine when it was just looking for a code that was set in the original programe, but now I've added functionality to allow setting of the code whilst in operation, i've exceeded my memory by 547 bytes.

As a code novice, I do not know any shortcuts for reducing the size of the programe without reducing the functionality. - Could someone have a look and give me some pointers that I could try to reduce the size? - I'm using an 18m2 chip. - I'd rather not have to use one of the bigger memory versions.

I've started to comment the front of the programme, but the rest is repetition.

Code:
init:
symbol codepos1=140 'for determining where to display the character on the LCD
symbol codepos2=141 'for determining where to display the character on the LC
symbol codepos3=142 'for determining where to display the character on the LC
symbol codepos4=143 'for determining where to display the character on the LC
symbol scancode1=b1 'reading the code part 1
symbol scancode2=b2 'reading code part 2
symbol scancode3=b3 'reading code part 3
symbol scancode4=b4 'reading code part 4
symbol setcode1=b5  	'storage of programmed code part 1
symbol setcode2=b6 	'storage of programmed code part 2
symbol setcode3=b7	'storage of programmed code part 3
symbol setcode4=b8	'storage of programmed code part 4
symbol delaycode=250	'how long to display a character before moving on to next
symbol programmemode=b9 'to keep track of being in setcode mode, or scancode mode.
symbol yes=1	
symbol no=0			
symbol timetounlock=w9
setcode1=0   'set default code to 0000
setcode2=0
setcode3=0
setcode4=0

main:
serout b.3,N2400,(254,1) ' clear display
pause 200
if programmemode=no then
serout b.3,N2400,(254,128,"Enter Code: ") 'display enter code on LCD if in non programme mode
else if programmemode=yes then
serout b.3,N2400,(254,128,"Set Code: ") 'display set code on LCD if in setcode mode.
endif
low b.0,b.1 'turn of both status LEDS (red and green LED for locked / unlocked status attached to these outputs)
pause 1000
timetounlock=0 'reset the time unlocked variable


'read button press 1 code or setting
scan1:

'scan row 1

high b.4 low b.5,b.6,b.7  'set row 1 high and the others lows

if pinc.2=1 then 'read column 1
	serout b.3,N2400,(254,codepos1,"1")
	if programmemode=no then: scancode1=1: pause delaycode
	elseif programmemode=yes then: setcode1=1: programmemode=no else: endif
	serout b.3,N2400,(254,codepos1,"*"): pause delaycode
	
	goto scan2

elseif pinc.1=1 then 'read column 2
	serout b.3,N2400,(254,codepos1,"2")
	if programmemode=no then: scancode1=2: pause delaycode
	elseif programmemode=yes then: setcode1=2:programmemode=no else: endif
	serout b.3,N2400,(254,codepos1,"*"): pause delaycode
	
	goto scan2

elseif pinc.0=1 then 'read column 3
	serout b.3,N2400,(254,codepos1,"3")
	if programmemode=no then: scancode1=1: pause delaycode
	elseif programmemode=yes then: setcode1=2:programmemode=no else: endif
	serout b.3,N2400,(254,codepos1,"*"): pause delaycode
	
	goto scan2

else
	endif

'scan row 2

high b.5 low b.4,b.6,b.7
if pinc.2=1 then
	serout b.3,N2400,(254,codepos1,"3")
	if programmemode=no then: scancode1=3: pause delaycode
	elseif programmemode=yes then: setcode1=3: programmemode=no else: endif
	serout b.3,N2400,(254,codepos1,"*"): pause delaycode
	
	goto scan2

elseif pinc.1=1 then
	serout b.3,N2400,(254,codepos1,"4")
	if programmemode=no then: scancode1=4: pause delaycode
	elseif programmemode=yes then: setcode1=4:programmemode=no else: endif
	serout b.3,N2400,(254,codepos1,"*"): pause delaycode
	
	goto scan2

elseif pinc.0=1 then
	serout b.3,N2400,(254,codepos1,"5")
	if programmemode=no then: scancode1=5: pause delaycode
	elseif programmemode=yes then: setcode1=5:programmemode=no else: endif
	serout b.3,N2400,(254,codepos1,"*"): pause delaycode
	
	goto scan2

else
	endif


'scan row 3

high b.6 low b.4,b.5,b.7
if pinc.2=1 then
	serout b.3,N2400,(254,codepos1,"7")
	if programmemode=no then: scancode1=7: pause delaycode
	elseif programmemode=yes then: setcode1=7: programmemode=no else: endif
	serout b.3,N2400,(254,codepos1,"*"): pause delaycode
	
	goto scan2

elseif pinc.1=1 then
	serout b.3,N2400,(254,codepos1,"8")
	if programmemode=no then: scancode1=8: pause delaycode
	elseif programmemode=yes then: setcode1=8:programmemode=no else: endif
	serout b.3,N2400,(254,codepos1,"*"): pause delaycode
	
	goto scan2

elseif pinc.0=1 then
	serout b.3,N2400,(254,codepos1,"9")
	if programmemode=no then: scancode1=9: pause delaycode
	elseif programmemode=yes then: setcode1=9:programmemode=no else: endif
	serout b.3,N2400,(254,codepos1,"*"): pause delaycode
	
	goto scan2

else
	endif
	
'scan row 4
	
high b.7 low b.4,b.5,b.6
if pinc.2=1 then
	serout b.3,N2400,(254,codepos1,"*")
	if programmemode=no then: scancode1=10: pause delaycode
	elseif programmemode=yes then: setcode1=10: programmemode=no else: endif
	serout b.3,N2400,(254,codepos1,"*"): pause delaycode
	
	goto scan2

elseif pinc.1=1 then
	serout b.3,N2400,(254,codepos1,"0")
	if programmemode=no then: scancode1=0: pause delaycode
	elseif programmemode=yes then: setcode1=0:programmemode=no else: endif
	serout b.3,N2400,(254,codepos1,"*"): pause delaycode
	
	goto scan2

elseif pinc.0=1 then
	serout b.3,N2400,(254,codepos1,"#")
	if programmemode=no then: scancode1=11: pause delaycode
	elseif programmemode=yes then: setcode1=11:programmemode=no else: endif
	serout b.3,N2400,(254,codepos1,"*"): pause delaycode
	
	goto scan2

else
	endif

goto scan1

'2nd and third code read should happen here
'---------------------------------------------------------------------------------------------------------------------

'read 4th button into memory
scan4:

'scan row 1

high b.4 low b.5,b.6,b.7

if pinc.2=1 then
	serout b.3,N2400,(254,codepos1,"1")
	if programmemode=no then: scancode4=1: pause delaycode
	elseif programmemode=yes then: setcode4=1: programmemode=no else: endif
	serout b.3,N2400,(254,codepos1,"*"): pause delaycode
	
	goto checkcode

elseif pinc.1=1 then
	serout b.3,N2400,(254,codepos1,"2")
	if programmemode=no then: scancode4=2: pause delaycode
	elseif programmemode=yes then: setcode4=2:programmemode=no else: endif
	serout b.3,N2400,(254,codepos1,"*"): pause delaycode
	
	goto checkcode

elseif pinc.0=1 then
	serout b.3,N2400,(254,codepos1,"3")
	if programmemode=no then: scancode4=1: pause delaycode
	elseif programmemode=yes then: setcode4=2:programmemode=no else: endif
	serout b.3,N2400,(254,codepos1,"*"): pause delaycode
	
	goto checkcode

else
	endif

'scan row 2

high b.5 low b.4,b.6,b.7
if pinc.2=1 then
	serout b.3,N2400,(254,codepos1,"3")
	if programmemode=no then: scancode4=3: pause delaycode
	elseif programmemode=yes then: setcode4=3: programmemode=no else: endif
	serout b.3,N2400,(254,codepos1,"*"): pause delaycode
	
	goto checkcode

elseif pinc.1=1 then
	serout b.3,N2400,(254,codepos1,"4")
	if programmemode=no then: scancode4=4: pause delaycode
	elseif programmemode=yes then: setcode4=4:programmemode=no else: endif
	serout b.3,N2400,(254,codepos1,"*"): pause delaycode
	
	goto checkcode

elseif pinc.0=1 then
	serout b.3,N2400,(254,codepos1,"5")
	if programmemode=no then: scancode4=5: pause delaycode
	elseif programmemode=yes then: setcode4=5:programmemode=no else: endif
	serout b.3,N2400,(254,codepos1,"*"): pause delaycode
	
	goto checkcode

else
	endif


'scan row 3

high b.6 low b.4,b.5,b.7
if pinc.2=1 then
	serout b.3,N2400,(254,codepos1,"7")
	if programmemode=no then: scancode4=7: pause delaycode
	elseif programmemode=yes then: setcode4=7: programmemode=no else: endif
	serout b.3,N2400,(254,codepos1,"*"): pause delaycode
	
	goto checkcode

elseif pinc.1=1 then
	serout b.3,N2400,(254,codepos1,"8")
	if programmemode=no then: scancode4=8: pause delaycode
	elseif programmemode=yes then: setcode4=8:programmemode=no else: endif
	serout b.3,N2400,(254,codepos1,"*"): pause delaycode
	
	goto checkcode

elseif pinc.0=1 then
	serout b.3,N2400,(254,codepos1,"9")
	if programmemode=no then: scancode4=9: pause delaycode
	elseif programmemode=yes then: setcode4=9:programmemode=no else: endif
	serout b.3,N2400,(254,codepos1,"*"): pause delaycode
	
	goto checkcode

else
	endif
	
'scan row 4
	
high b.7 low b.4,b.5,b.6
if pinc.2=1 then
	serout b.3,N2400,(254,codepos1,"*")
	if programmemode=no then: scancode4=10: pause delaycode
	elseif programmemode=yes then: setcode4=10: programmemode=no else: endif
	serout b.3,N2400,(254,codepos1,"*"): pause delaycode
	
	goto checkcode

elseif pinc.1=1 then
	serout b.3,N2400,(254,codepos1,"0")
	if programmemode=no then: scancode4=0: pause delaycode
	elseif programmemode=yes then: setcode4=0:programmemode=no else: endif
	serout b.3,N2400,(254,codepos1,"*"): pause delaycode
	
	goto checkcode

elseif pinc.0=1 then
	serout b.3,N2400,(254,codepos1,"#")
	if programmemode=no then: scancode4=11: pause delaycode
	elseif programmemode=yes then: setcode4=11:programmemode=no else: endif
	serout b.3,N2400,(254,codepos1,"*"): pause delaycode
	
	goto checkcode

else
	endif

goto scan4


checkcode:



if scancode1=setcode1 and scancode2=setcode2 and scancode3=setcode3 and scancode4=setcode4 then

serout b.3,N2400,(254,128,"Code Correct      ")


'check for enter code programming mode
do
high B.7
high b.1

inc w9
if pinC.0 = 1 then 
programmemode=yes
loop while timetounlock < 2000


goto main

else

serout b.3,N2400,(254,128,"Code Incorrect      ")

high b.0

pause 3000

goto main


endif
endif
 

bfgstew

Senior Member
Therre does seem a lot of repetition.

Give this keypad code snippet a go, Nick kindly donated it to me and works like a dream, may save a lot of space?

Code:
GetKeyPress:
 	 Do
    		Gosub GetTheKeyPressed			' Wait until no key pressed
  			Loop Until key_value = 0
 	 Do
   		 Gosub GetTheKeyPressed			' Wait until key pressed
  			Loop Until key_value <> 0
  			If key_value = 11 Then
    			key_value = 0
    			endif
    			if key_value => 0 then high key_LED
    			pause 30
    			low key_LED
  		End If
  	Return		
GetTheKeyPressed:	;Keypad scan coding
		key_pos = 0
		key_value = 0
	 	High ROW1 : gosub ScanCol : low ROW1
	 	High ROW2 : gosub ScanCol : low ROW2
	 	High ROW3 : gosub ScanCol : low ROW3 
	 	High ROW4 : gosub ScanCol : low ROW4
	 	Return	 	
	 	ScanCol:
	 		if COL1 = 1 then : key_value = key_pos + 1 : endif
	 		if COL2 = 1 then : key_value = key_pos + 2 : endif
	 		if COL3 = 1 then : key_value = key_pos + 3 : endif
	 		key_pos = key_pos + 3   
   		return
To call it just use gosub GetKeyPress..............
 

bfgstew

Senior Member
Another to help reduce repetition........

Code:
Get4DigitNumberIntoW6: ;Coding to change the pause time via keypad
			
		For b7 = 1 to 4				
  			Gosub GetKeyPress 
  			w6 = w6 * 10 + b1
  			serout C.7,N2400,(254,161,#w6,"ms")
  			pause 30
  			next b7
 		Return
Uses a word variable so you can have 4 digits in one go, nice and simple.
 

bfgstew

Senior Member
Try this, it may need tweaking slightly to suit your set up.

Code:
#picaxe18m2
symbol key_pos = b0
symbol key_value = b1
symbol COL1 = pin0 ; keypad scan config
symbol COL2 = pin1 ; change these to suit your set up
symbol COL3 = pin2 ; 
symbol ROW1 = B.0  ;
symbol ROW2 = B.1  ;
symbol ROW3 = B.2  ;
symbol ROW4 = B.3  ;
let w7 = 0
let w8 = 1234

main:
	serout C.7,N2400,(254,1)
		pause 30
		serout C.7,N2400,(254,134,"CODE",254,137,#w7)
		pause 30
			gosub Get4DigitNumberIntow7
			pause 1000
			if w7 = w8 then goto OPENit
			if w7 <> w8 then goto main
			
OPENit:
	;Opens lock
	
			
Get4DigitNumberIntow7: ;Coding to change the code via keypad
			
		For b7 = 1 to 4				
  			Gosub GetKeyPress 
  			w7 = w7 * 10 + b1
  			serout C.7,N2400,(254,137,#w7,"ms")
  			pause 30
  			next b7
 		Return
			
GetKeyPress:
 	 Do
    		Gosub GetTheKeyPressed			' Wait until no key pressed
  			Loop Until key_value = 0
 	 Do
   		 Gosub GetTheKeyPressed			' Wait until key pressed
  			Loop Until key_value <> 0
  			If key_value = 11 Then
    			key_value = 0
    			endif
  	Return		
GetTheKeyPressed:	;Keypad scan coding
		key_pos = 0
		key_value = 0
	 	High ROW1 : gosub ScanCol : low ROW1
	 	High ROW2 : gosub ScanCol : low ROW2
	 	High ROW3 : gosub ScanCol : low ROW3 
	 	High ROW4 : gosub ScanCol : low ROW4
	 	Return	 	
	 	ScanCol:
	 		if COL1 = 1 then : key_value = key_pos + 1 : endif
	 		if COL2 = 1 then : key_value = key_pos + 2 : endif
	 		if COL3 = 1 then : key_value = key_pos + 3 : endif
	 		key_pos = key_pos + 3   
   		return
 

Blazemaguire

Senior Member
thanks for your help.

After the first suggestion, I've written this code (if it helps someone else) - It provides reprogramming of the PIN from within the code, and saves the pin to the eeprom so it is preserved even after power off.

Down to 1370 ish bytes now! - Not sure it's the most efficient thing out there, but hey. it works! - And i'm learning.

Code:
symbol row1=b.4
symbol row2=b.5
symbol row3=b.6
symbol row4=b.7
symbol incorrectLED=b.0
symbol correctLED=b.1
symbol col1=pinc.2
symbol col2=pinc.1
symbol col3=pinc.0
symbol key_value=b1
symbol keyvalue1=b2
symbol keyvalue2=b3
symbol keyvalue3=b4
symbol keyvalue4=b5
symbol keyset1=b8
symbol keyset2=b9
symbol keyset3=b10
symbol keyset4=b11
symbol key_pos=b6
symbol displaypos=b0
symbol keytrack=b7
symbol delaycode=300






init:
displaypos=140
keytrack=0
read b12,b8
read b13,b9
read b14,b10
read b15,b11

if b8=0 and b9=0 and b10=0 and b11=0 then
keytrack=0: displaypos=142

gosub setcode

else 

endif

serout b.3,N2400,(254,1)
pause delaycode
serout b.3,N2400,(254,128,"Enter Code:")
pause 50
goto main

init2:
read b12,b8
read b13,b9
read b14,b10
read b15,b11

displaypos=140
serout b.3,N2400,(254,1)
pause delaycode
serout b.3,N2400,(254,128,"Enter Code:")
pause 50


main:
if keytrack>=4 then
goto codecheck
else 
endif

gosub getkeypress


if key_value=10 then: serout b.3,N2400,(254,displaypos,"* ")
high correctLED
pause delaycode
serout b.3,N2400,(254,displaypos,"* ")
low correctLED
inc displaypos: inc keytrack: goto main
elseif key_value=12 then: serout b.3,N2400,(254,displaypos,"# ")
high correctLED
pause delaycode
serout b.3,N2400,(254,displaypos,"* ")
low correctLED
inc displaypos: inc keytrack: goto main
else 
endif

serout b.3,N2400,(254,displaypos,#key_Value)
high correctLED
pause delaycode
serout b.3,N2400,(254,displaypos,"*")
low correctLED
key_value=0 :inc displaypos: inc keytrack:

 goto main


codecheck:
read b12,b8
read b13,b9
read b14,b10
read b15,b11
if keyset1=keyvalue1 and keyset2=keyvalue2 and keyset3=keyvalue3 and keyset4=keyvalue4 then
serout b.3,N2400,(254,128,"Code Correct!       ")
write b12,b8
write b13,b9
write b14,b10
write b15,b11
high correctLED
pause 2000
low correctLED
keytrack=0: displaypos=140
goto init2

else
serout b.3,N2400,(254,128,"Code incorrect!     ")
keytrack=0: displaypos=140
high incorrectLED
pause 2000
low incorrectLED
goto init2
endif

goto init2



GetKeyPress:

 	 Do
    		Gosub GetTheKeyPressed			' Wait until no key pressed
  			Loop Until key_value = 0
 	 Do
   		 Gosub GetTheKeyPressed			' Wait until key pressed
  			Loop Until key_value <> 0
  			If key_value = 11 Then
    			key_value = 0
    			endif
    			if key_value => 0 then 
  		End If
  		
if 	 keytrack=0 then: keyvalue1=key_value:	
elseif keytrack=1 then: keyvalue2=key_value:	 
elseif keytrack=2 then: keyvalue3=key_value:	 
elseif keytrack=3 then: keyvalue4=key_value:	
else


endif


  	Return		
  	
GetTheKeyPressed:	;Keypad scan coding
		key_pos = 0
		key_value = 0
	 	High ROW1 : gosub ScanCol : low ROW1
	 	High ROW2 : gosub ScanCol : low ROW2
	 	High ROW3 : gosub ScanCol : low ROW3 
	 	High ROW4 : gosub ScanCol : low ROW4
	 	Return	 	
	 	ScanCol:
	 		if COL1 = 1 then : key_value = key_pos + 1 : else endif
	 		if COL2 = 1 then : key_value = key_pos + 2 : else endif
	 		if COL3 = 1 then : key_value = key_pos + 3 : else endif
	 		if COL1 =1 and col3=1 then   'check for entering new code set mode
	 		keyvalue=0: keytrack=0: displaypos=144
	 		serout b.3,N2400,(254,128," ==RESET CODE MODE==  ")
	 		pause 1000
	 		serout b.3,N2400,(254,128,"Enter Old Code:          ")
	 		pause delaycode
	 		
	 		 gosub setcodecheckpin: else endif
	 		key_pos = key_pos + 3   
	 		
   		return
   		
   		
setcodecheckpin:
if keytrack>=4 then
goto oldcodecheck
else 
endif

gosub getkeypress
serout b.3,N2400,(254,128,"Enter Old Code:")
pause delaycode
if key_value=10 then: serout b.3,N2400,(254,displaypos,"* ")
high correctLED
pause delaycode
serout b.3,N2400,(254,displaypos,"* ")
low correctLED
inc displaypos: inc keytrack: goto setcodecheckpin
elseif key_value=12 then: serout b.3,N2400,(254,displaypos,"# ")
high correctLED
pause delaycode
serout b.3,N2400,(254,displaypos,"* ")
low correctLED
inc displaypos: inc keytrack: goto setcodecheckpin
else 
endif

serout b.3,N2400,(254,displaypos,#key_Value)
high correctLED
pause delaycode
serout b.3,N2400,(254,displaypos,"*")
low correctLED
key_value=0 :inc displaypos: inc keytrack:

 goto setcodecheckpin


oldcodecheck:
read b12,b8
read b13,b9
read b14,b10
read b15,b11
if keyset1=keyvalue1 and keyset2=keyvalue2 and keyset3=keyvalue3 and keyset4=keyvalue4 then
serout b.3,N2400,(254,128,"Code Correct!          ")
write b12,b8
write b13,b9
write b14,b10
write b15,b11
pause 1000
serout b.3,N2400,(254,128,"Set New Code:")
pause delaycode
keytrack=0: displaypos=142
goto setcode

else
serout b.3,N2400,(254,128,"Code incorrect!        ")
keytrack=0: displaypos=140
high incorrectLED
pause 2000
low incorrectLED
goto init2
endif

goto init2









setcode:
if keytrack>=4 then: keytrack=0 

serout b.3,N2400,(254,128,"New Code Set")
write b12,b8
write b13,b9
write b14,b10
write b15,b11
pause 1000
goto init2

else 
serout b.3,N2400,(254,128,"Set New Code:")
endif

gosub getkeypressforsetting
if key_value=10 then: serout b.3,N2400,(254,displaypos,"* ")
high correctLED
pause delaycode
serout b.3,N2400,(254,displaypos,"* ")
low correctLED
inc displaypos: inc keytrack: goto setcode
elseif key_value=12 then: serout b.3,N2400,(254,displaypos,"# ")
high correctLED
pause delaycode
serout b.3,N2400,(254,displaypos,"* ")
low correctLED
inc displaypos: inc keytrack: goto setcode
else 
endif

serout b.3,N2400,(254,displaypos,#key_Value)
high correctLED
pause delaycode
serout b.3,N2400,(254,displaypos,"*")
low correctLED
key_value=0 :inc displaypos: inc keytrack:

 goto setcode









GetKeyPressforsetting:

 	 Do
    		Gosub GetTheKeyPressedforsetting			' Wait until no key pressed
  			Loop Until key_value = 0
 	 Do
   		 Gosub GetTheKeyPressedforsetting			' Wait until key pressed
  			Loop Until key_value <> 0
  			If key_value = 11 Then
    			key_value = 0
    			endif
    			if key_value => 0 then 
  		End If
  		
if 	 keytrack=0 then: keyset1=key_value:	
elseif keytrack=1 then: keyset2=key_value:	 
elseif keytrack=2 then: keyset3=key_value:	 
elseif keytrack=3 then: keyset4=key_value:	
else


endif


  	Return		
  	
GetTheKeyPressedforsetting:	;Keypad scan coding
		key_pos = 0
		key_value = 0
	 	High ROW1 : gosub ScanColset : low ROW1
	 	High ROW2 : gosub ScanColset : low ROW2
	 	High ROW3 : gosub ScanColset : low ROW3 
	 	High ROW4 : gosub ScanColset : low ROW4
	 	Return	 	
	 	ScanColset:
	 		if COL1 = 1 then : key_value = key_pos + 1 : else endif
	 		if COL2 = 1 then : key_value = key_pos + 2 : else endif
	 		if COL3 = 1 then : key_value = key_pos + 3 : else endif
	 		if COL1 =1 and col3=1 then: keyvalue=0: Keytrack=0: Displaypos=146
	 		gosub setcode: else endif
	 		key_pos = key_pos + 3   
	 	
	 		
   		return
 

bfgstew

Senior Member
To alter the security code just add another subroutine, this time for w8. This will need another tweak in 'main' so you can access this but I am not on my PC as am work so no PE available to do it for you.

Get4DigitNumberIntow8: ;Coding to change the code via keypad

For b7 = 1 to 4
Gosub GetKeyPress
w8 = w8 * 10 + b1
serout C.7,N2400,(254,137,#w8) ; alter the numbers to suit were you want on LCD
pause 30
next b7
Return
Add LED high and low as necessary and screen displays.
 

Blazemaguire

Senior Member
That's a handy thread! - - Not sure I'm bright enough to implement all of those tricks just yet, but that's a great resource still! thanks all, - Helpful as ever.
 
Top