Demo Scrolling Menu on 4x20 LCD

westaust55

Moderator
From time to time there have been requests for code for a scrolling menu scheme using an LCD display.

Here is one possibility for a 4x20 character LCD module:

Code:
; =================================================
;   File....... Scrolling Menu
;   Purpose.... Scrolling Menu demo for 4x20 LCD dispaly
;   Author..... Westaust55
;   E-mail.....
;   Started.... 25-02-2010
;   Updated.... DD-MM-YYYY
; =================================================
;
; -----[ Program Description ]---------------------------------------------
;
; A program to demonstrate the ability for a scrolling menu on a 4x20 LCD 
; functions of the Experimenters Box. 
; 
;
; -----[ Revision History ]------------------------------------------------
;
; 
;
; -----[ I/O Definitions ]-------------------------------------------------
;
; - - - DIGITAL INPUT PINS  - - -
SYMBOL key_data = 0         ; keypad serial data input
;intrpt val_data =1         ; keypad valid data signal
;
; - - - DIGITAL OUTPUT PINS - - -
SYMBOL lcd_data = 1         ; serial pin for data to LCD display
;
;
; -----[ i2c Device Addressing ]-------------------------------------------------------
;
; 24LC256 EEPROM's
SYMBOL eeprom_0 = %10100000  ; %1010 = EPROM, 000 = Addr 0 & 0 = control bit

;
; PCF8574 8-BIT IO EXPANDERS
SYMBOL expand_0 = %01000000  ; %0100 = Chip ID, 000 = Addr 0 - For the 8 Red LED's
SYMBOL expand_1 = %01000010  ;                , 001 = Addr 1 - For Keypad Shift LED
;
;
; -----[ Constants ]-------------------------------------------------------
;
SYMBOL shiftkey = 64          ; value returned by keypad for shift key
SYMBOL NoLEDs   = 8           ; No of LEDs in the bar graph
SYMBOL divisor  = 255         ; typically divisor = 2^NoLEDs - 1
SYMBOL std_delay= 1000        ; default delay period in milliseconds
SYMBOL Scrollup = "U"
SYMBOL Scrolldown = "D"
SYMBOL Action = "A"
;
;
; 4 x 20 char LCD commands
SYMBOL lcd_bs   = $08         ; back space
SYMBOL lcd_lf   = $0A         ; line feed
SYMBOL lcd_ff   = $0C         ; form feed
SYMBOL lcd_cr   = $0D         ; carriage return
; 
SYMBOL lcdcmand = $FE         ; = 254 - send this before following commands
SYMBOL lcdclear = $01         ; clear screen and cursor to home position
SYMBOL lcdhome  = $02         ; move cursor to home position
SYMBOL lcdnocur = $0C         ; display on with no cursor
SYMBOL lcdcuron = $0E         ; display on with visible cursor
SYMBOL lcdcblnk = $0F         ; display on with blinking cursor
SYMBOL lcdline1 = $80         ; move to start of 1st line
SYMBOL lcdline2 = $C0         ; move to start of 2nd line
SYMBOL lcdline3 = $94         ; move to start of 3rd line
SYMBOL lcdline4 = $D4         ; move to start of 4th line
SYMBOL lcdlitof = $FC         ; turn backlight off
SYMBOL lcdLiton = $FD         ; turn backlight on
;
; Scrolling Menu Constants
SYMBOL Displines = 4 ; Sets the number of lines in the display
SYMBOL Charsperline = 20 ; Sets the number of characters per line
SYMBOL MaxOptions = 9 ;  Sets the total number of options in this menu set
;
;
; -----[ Variables ]-------------------------------------------------------
;
SYMBOL keypad    = b27       ; Value returned from keypad (0-63)
SYMBOL keyval    = b26       ; Add\justed value from keypad keypd+1 (1-64)
SYMBOL shflock   = b25       ; Flag to indicate if shiftlock is ON/OFF
SYMBOL keychar   = b24       ; ASCII character value for keypad key press
;
;
;Scrolling Menu Variables
SYMBOL ThisChar = b6
SYMBOL CharPtr = b5
SYMBOL Char2LCD = b4
SYMBOL LineNo = b3
SYMBOL Maxtop = b2 ; defines which is lowest menu set item that can scroll up to top display line
SYMBOL Cursor = b1 ; Defines which of the display lines the cursor is on
SYMBOL TopVisLine = b0 ; Defines which is the upper line of menu set visible on  display




; 
; -----[ EEPROM Data ]-----------------------------------------------------
;
EEPROM 0,   ("Set The Time      ")
EEPROM 20,  ("Show the Time     ")
EEPROM 40,  ("Show Temperature  ")
EEPROM 60,  ("Show Mag Field Str")
EEPROM 80,  ("Show Pot Voltage  ")
EEPROM 100, ("Show the Distance ")
EEPROM 120, ("Show the Heading  ")
EEPROM 140, ("Show Light Level  ")
EEPROM 160, ("Hex to Dec & Bin  ")
EEPROM 180, ("Say Text String   ")
EEPROM 200, ("Play a Tune       ")
;
;
; -----[ Initialization ]--------------------------------------------------
;
Init:  
       PAUSE 1000            ; wait for LCD to initialise
       SEROUT lcd_data, N2400, (lcdcmand,lcdclear)
       pause 10
       
; Scrolling LCD Menu variables       
      TopVisLine = 1
	Cursor = 1
	Maxtop = MaxOptions - Displines

;

	GOSUB DispMenu
      SETINT %00000000, %00000010  ; set polled interrupt to act on a change to 0 on input 1 
;
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
;  
Main:

Cont:  DO
         PAUSE 10
       LOOP WHILE keyval =0  
;  Serin 1, N2400, keypad

IF keychar = scrollup THEN
  Cursor = Cursor -1
  IF Cursor = 0 THEN
    Cursor = 1
    TopVisLine = TopVisLine - 1 MIN 1
  ENDIF
    GOSUB DispMenu

ENDIF

IF keychar = scrolldown THEN
  Cursor = Cursor + 1
  IF Cursor = 5 THEN
    Cursor = 4
    TopVisLine = TopVisLine + 1 MAX MaxTop
  ENDIF
    GOSUB DispMenu

ENDIF
 IF keychar = action THEN
   GOSUB DoAction
   GOSUB DispMenu
 ENDIF
 keyval =0
GOTO Main
;
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
;
DispMenu:
  SEROUT lcd_data, N2400, (lcdcmand,lcdclear)
  pause 10
  For LineNo = 1 to Displines 
  LOOKUP LineNo, (0,lcdline1,lcdline2,lcdline3,lcdline4), Char2LCD
  SEROUT lcd_data, N2400, (lcdcmand,Char2LCD) 
  PAUSE 10
  
  For CharPtr = 1 to Charsperline
 
    IF CharPtr = 1 THEN
      IF Cursor = LineNo THEN
        SEROUT lcd_data, N2400, (">")
      ELSE
        SEROUT lcd_data, N2400, (" ")
      ENDIF
    ELSEIF CharPtr = 2 THEN
      SEROUT lcd_data, N2400, (" ")
    ELSE
      ThisChar = TopVisLine -1 + LineNo - 1 * Charsperline  + CharPtr - 3;
      READ ThisChar, Char2LCD
      SEROUT lcd_data, N2400, (Char2LCD)
    ENDIF
  NEXT CharPtr
NEXT LineNo
RETURN
;
;
DoAction:
       SEROUT lcd_data, N2400, (lcdcmand,lcdclear)
       pause 10
       SEROUT lcd_data, N2400, ("Here we would do the"); Do the action here
       SEROUT lcd_data, N2400, ("selected action")
       PAUSE 5000 ; give time to see message
RETURN
;
;
Shlok2led: ; Subroutine to togggle the keypad "SHIFT" LED
           HI2CSETUP i2cmaster, expand_1, i2cslow, i2cbyte
           IF shflock = 0 THEN
             HI2COUT (0)
           ELSE
             HI2COUT (1)
           ENDIF
           RETURN
;
; -----[ Interrupt Routines (if used) ]-------------------------------------
;
Interrupt: SERIN key_data, T2400, keypad            ; here when a key is pressed
           keyval = keypad +1                       ; change 0 to 63 to 1 to 64 (easier for maths)
	     
           IF keyval = shiftkey THEN                ; If it was shift key Then . . .
	        shflock = shflock ^ keyval            ; exclusive OR to toggle state of shift lock flag
              GOSUB Shlok2led                       ; update the SHIFT LED
	     ENDIF

	     keyval = keyval + shflock                ; 1 to 63 for lower, 65 to 127 for upper/shifted
           
           HI2CSETUP i2cmaster, EEPROM_0, i2cslow, i2cword
           HI2CIN keyval, (keychar)                 ; fetch the equivalent character from EEPROM table
	     
	     SETINT %00000000, %00000010              ; restore the interrupt scheme and return to main program
	     RETURN 
;          
; =================================================
;      THE END
; =================================================

In this program, I do have some extra bits such as the interrupt routine to read my EDE-1188 based 48-key keypad based home brew keyboard (and using an eternal EEPROM for keyboard ASCII code lookup).
Plus moree SYMBOL statements than are specifically required for the scrolling menu.
Other than scroll up and down a menu with the U and D keys and give a message if the A key is pressed it is just a working demo for others to extrract code form.
 

Johnmb

Member
I will find it very helpful, but...

Please post a schematic. Which PICAXE can be used? I have a PICAXE08M. Will that do?
John
 

westaust55

Moderator
Hi John,

The first lines in the program listing indicate the PICAXE inputs and Outputs utilised.
Namely:
Code:
; -----[ I/O Definitions ]-------------------------------------------------
;
; - - - DIGITAL INPUT PINS  - - -
SYMBOL key_data = 0         ; keypad serial data input
;intrpt val_data =1         ; keypad valid data signal
;
; - - - DIGITAL OUTPUT PINS - - -
SYMBOL lcd_data = 1         ; serial pin for data to LCD display
;
If you do wish to see my schematics for the LCD connection and keypad circuit, please have a look at the second pdf file in post 5 here:
http://www.picaxeforum.co.uk/showthread.php?t=10576
Easier to point you there rather than post the same data agin here)
The first pdf has more schematics for my PICAXE experimenters box.

Most would not be trying to emulate my keypad/keyboard for their projects. You could easily just alter the program to use say 3 buttons/switches onto separate inputs to scroll up, down or action the command on selected line.

The LCD is a 1-wire serial interface much the same as the Rev Ed AXE033 but with a 4x20 LCD display instead of a 2x16 display

I doubt that you will be able to use an 08M, as the text for the menus consumes quite a lot of the memory space (all of the “M” series PICAXE chips only have 256 bytes for program and EEPROM functions)

I had the code in a 40X1.
Any X (eg 18X), X1 or X2 chip will have sufficient memory to run the scrolling menu approach with sufficient program space remaining to actually hold the code to action the selected commands.

I guess it may be possible to have a very small menu program in an 08M and just send a byte of data to another PICAXE to perform the desired action but the question is then – why not just move the project to a PICAXE chip with more memory to hold the entire program (for example an 18X).
 

Johnmb

Member
I was too late.

When I realized the information was in the program, I signed on to the thread and found your reply. Thank you very much. The responders on this forum are very gentle with lazy types like me. I appreciate it.
John
 

ValueAdd

Senior Member
When I realized the information was in the program, I signed on to the thread and found your reply. Thank you very much.
I guess that is the sign of someone who documents their projects well.
Just a case that the rest of us need to read those descriptions thoroughly



The responders on this forum are very gentle with lazy types like me. I appreciate it.
John
Others have made the same comments here in the past suggesting other forums are more “aggressive”.
I too find that while there is the occasional joking/banter and suggestion to “RTFM”, in the vast majority of cases, the responses here are very pleasant.
 

fernando_g

Senior Member
"I too find that while there is the occasional joking/banter and suggestion to “RTFM”, in the vast majority of cases, the responses here are very pleasant."

You bet...forum members here are quite civil and polite, compared to other forum jungles I sometimes browse.....
 
Top