Menu selection and number input without a keypad

skeldro

New Member
In a proposed project for an intelligent battery charger/ discharger, I require a menu and number input.

To avoid the extra expense and space required by a keypad I wrote the code below, which requires the 2x16 LCD module connected to an output pin – to one of the Darlington outputs here – and three switches connected to three of the input pins.

Article Pic.jpg


The menu sub displays the menu options on the second line and the cursor on the top line. The cursor can be moved left and right with the push switches. Using OK selects the cursor option.

The maximum number of options is determined by optCount*optLength <= 16 ,remembering to count the option delimiter as a character, eg Op1 Op2 Op3 Op4 with optLength=4 and optCount=4

You must set optLength and optCount constants in the code and
the menu string in the menu sub – it would better in EEPROM at the start of the program.

The getNumber sub displays the digits 012..9 on the second line with a ‘control’ symbol after the 9
The sub works in a similar way to the menu one with two additions:

The compiled integer is shown at the right of line1;
The ‘control’ character after 9 allows for last digit deletion or final OK.
In this position <- moves left as usual, OK confirms the number but -> deletes the last digit entered.
The symbol helps to remind what buttons to use – you get used to it after a time!

The number is checked for maximum length but not magnitude.


Code:
'Menu chooser and number input by using three pins
'skeldro – Oct 2011. Use at your own risk.
'Menu of optCount optLength char options
'LCD routines for 8MHz -----

'In xtick box (after the 9)
'	left moves the cursor left
' 	right deletes the last digit of the number
' 	OK	exits the procedure with num

'--------- sub-routines ----------------
'init	- the lcd
'menu - displays menu and returns option
'getNumber	- allows word number input and returns num

'------ constants and variables--------
'address 0 of the scratchpad is used by getNumber

symbol optLength 	= 3 'Character length of each option-set to suit *****************
symbol optCount 	= 4 'Number of options -set to suit ******************************

symbol lcdPort 	= 6 'reserved	for LCD serial link
symbol serPort		= 7 'reserved for serial link to PC but not used here

symbol leftPin		= pin0	'the cursor switches, set to suit
symbol rightPin	= pin1
symbol OKpin		= pin2

'w0 to w8 available for user - use reserved ones with care
 
symbol wCal		= w9
symbol num		= w10
'b22 spare
symbol tmp		= b23
symbol dCur		= b24	'1-9 for left and 11-19 for right
symbol cur		= b25	'reserved for cur logical position, 0,1,2 etc
symbol option 	= b26	'reserved for cur LCD position, eg 0,3,6
symbol cal		= b27	'reserved for calculations

'-------------------------
setFreq m8
gosub initLCD
serout LCDport,T2400_8, (254,64,36,36,36,36,36,53,46,36) 'preload cursor
'		use serout LCDport,T2400_8,(8) to display
serout LCDport, T2400_8, (254,72,35,35,40,63,40,33,42,36) 'preload xtick 
'		use ...(9)

'========================main loop==========
do
	gosub menu
	on option gosub number,other,quit			'sample subs
loop until option = 2

end

'========= Sub-routines go here =============

'--------------Sample  Option----------------
number:
	gosub getNumber
	serout lcdPort,T2400_8,(254,192)				'Start of line 2
	serout lcdPort,T2400_8,(#num," Press OK...")
	gosub waitForOK
return

'----------------Sample Option----------------
other:
	serout lcdPort,T2400_8,("Other..Press OK...")
	gosub waitForOK 
return

'--------------------------------------------
quit:
	serout lcdPort,T2400_8,("Finished")
return

'======================================================
menu:
	gosub clearr
	cur = 0
	serout LCDport,T2400_8,(8) 			'the cursor
	serout lcdPort,T2400_8,(254,192)			'line 2, pos 1
	serout lcdPort,T2400_8,("Vo Ch Di Qu ")	'the menu
	
	option = 0	'none chosen

		do
			if leftPin=1 then 				'go left
				if cur >= optLength then
					dCur = optLength
					gosub moveCursor					
				end if
				do loop until leftPin=0
			
			else if rightPin=1 then				'go right				
				cal = optCount-1
				cal = optLength*cal									
				
				if cur < cal then
					dCur = optLength+10
					gosub moveCursor	
				end if
				do loop until rightPin=0
				
			elseif OKpin=1 then				'select option
				cal = cur/optLength
				option = cal + 1
				do loop until OKpin=0
			end if
		
			
		loop until option <> 0
		
		gosub clearr
	option = option - 1					'for on gosub
return
		
'----------------------------------------
getNumber:
	gosub clearr
	serout LCDport,T2400_8,(8) 			'the cursor
	serout lcdPort,T2400_8,(254,192)			'line 2, pos 1
	serout lcdPort,T2400_8,("O123456789")		'012...9
	serout lcdPort,T2400_8,(9)				'xtick symbol
	cur = 11
	gosub moveTo
	serout lcdPort,T2400_8,("0")			'the number
	num = 0	
	cur = 0
	put 0,0								'number digits
	
	do
		if leftPin=1 then					'go lleft
			if cur > 0 then									
				dCur = 1
				gosub moveCursor				
			end if			
			do loop until leftPin=0
		
		elseif rightPin=1 then				'go right
			if cur < 10 then				'go right
				dCur = 11
				gosub moveCursor
			else						'delete digit	
				get 0,cal				'number digits from scratchpad
				if cal>0 then				'something to delete
					num = num/10
					cal=cal-1
					put 0,cal				'store new length
					
					cur = 11				'update display and
					gosub moveTo
					serout lcdPort,T2400_8,("     ")
					cur = 11				'update display and
					gosub moveTo
					serout lcdPort,T2400_8,(#num)
					cur=10
					dCur = 1				'move cursor out off xtick
					gosub moveCursor
				end if
			end if
			do loop until rightPin=0

		
		elseif OKpin=1 then
			if cur <> 10 then
				get 0,cal					'number digits
				
				if cal < 5	then	
					num = 10*num
					num = num+cur													
					cal = cal+1
					put 0,cal
					tmp=cur					'save it
					cur = 11
					gosub moveTo
					cur=tmp					'restore cursor
					serout lcdPort,T2400_8,(#num)
				end if								
			else
				option = 1					'set exit flag
			end if
			
			do loop until OKpin=0
		end if
		
	loop until option <> 0
		
	gosub clearr
return

'-----------------------------------------
waitForOK:
	do loop until OKpin=1
	do loop until OKpin=0
return

'------------------------------------------
moveTo:									'cur position on line 1
	cal = 128+cur
	serout LCDport,T2400_8,(254,cal)
return

'-----------------------------------------

moveCursor:								'from cur by dCur
	gosub moveTo
	serout lcdPort,T2400_8,(" ")			'delete cursor
	
	if dCur < 10 then					'move left
		cur = cur-dCur
	else										'move right
		cal = dCur-10
		cur = cur+cal
	end if
	
	gosub moveTo						'cursor placed
	serout lcdPort,T2400_8,(8)
return

'------------------------------------------
clearr:
	serout lcdPort,T2400_8,(254,1)	
	pause 30
return


'-------------------------------------------
initLCD:
	pause 500							'to let LCD settle
	serout lcdPort,T2400_8,(254,14)			'cursor on
	pause 30
	serout lcdPort,T2400_8,(254,1)			'clear
	pause 30
return
 

westaust55

Moderator
Well done and thank you for posting your LCD menu code.
As a topic this requirement for an LCD based menu arises from time to time, so your code gives future enquirers something to find and work from.
 
Top