Continue to Site

Welcome to our site!

Electro Tech is an online community (with over 170,000 members) who enjoy talking about and building electronic circuits, projects and gadgets. To participate you need to register. Registration is free. Click here to register now.

  • Welcome to our site! Electro Tech is an online community (with over 170,000 members) who enjoy talking about and building electronic circuits, projects and gadgets. To participate you need to register. Registration is free. Click here to register now.

LCD+keypad interface -> menu structure. Concepts sought. Assembly. PIC.

Status
Not open for further replies.

astronomerroyal

New Member
Hi, I have a numeric keypad + LCD interface for my PIC project. Currently it only displays the value of the key you've pressed, and stores its face value in a register. That alone is a minor miracle, mostly thanks to Wilmshurst's book and Ilett's document.

I want to now add a useful and basic menu system. The user enters a value (for now just a one digit number) and presses ENTER. They may then go to a sub-menu and so on ... setting the flags and entering parameters that define the subsequent flow of the program.

I believe this is called a 'hierarchical menu system' and I was hoping to find a well thought out framework, upon which I would expand. I don't know C yet, so I want to do it in assembly.

What I would like to see is a descriptive overview, pseudo-code, or a pointer to a book or website that addresses this topic.

I realize there are many types of menu, so am mostly interested in seeing a cross-section of the methods used.

Some issues:
1) linear code vs. subroutines.
2) Many unique menus vs. single menu template that uses indirect addressing to send the data to the right register.
3) What are the factors that affect choice of design (e.g number of menu levels)?
4) How best to store the menu descriptions (e.g. individual characters in a 'computed goto' look-up table?)
5) What to do when user must enter multiple digit decimal numbers.

Many thanks in advance for your thoughts, and for reading this far,
AR.
 
Last edited:
4) How best to store the menu descriptions (e.g. individual characters in a 'computed goto' look-up table?)
With assembly language programs I find that storing string tables in-line with your code provides a more intuitive structure, much like a high-level language;

Mike

Code:
;
;  main menu
;
menu.a
        PutStr  "\x1b[2J"       ; home cursor, clear screen
        PutStr  " Menu\r\n\n"
        PutStr  " 1 - set azimuth\r\n"
        PutStr  " 2 - set elevation\r\n"
        call    Get232          ; get rs-232 input
        xorlw   '2'             ; a '2'?
        beq     menu.2          ; yes, branch, else
        xorlw   '1'^'2'         ; a '1'?
        bnz     menu.a          ; no, branch, else
menu.1
 
Hi,

Was interested to see your post on menu structures, an area I had been looking at for a while, without much success, perhaps some good ideas may now come forward.

My existing pic assembler / 2x16 lcd menu system is done by pressing a switch to invoke the main menu and pressing the key again to advance to the next menu function, - very simple but effective although a little cumbersome.
You can also use a press and hold main menu, where holding down a key cycles the lcd through all the menu options -release the key to enter that function .. etc etc..

Your idea of initially entering a number seems a little bit of a retrograde step, certainly not a method new users would find easy without a printed list of codes.

There must be many possible ways of creating menus, but the limitation will always be the lcd, typically a 2x16 unit. A 4x16 will give more freedom but basically the same constraints.

Probably something you may have looked at but discounted, is the use of glcd units.
They can be used a simple text screen, giving an equivalent display of 8 rows of 16 + characters, or with large character images as shown in the attached picture.


They are cost effective and practicable with simple assembler code, as can be seen in my recent post ( sorry the opening message photos deleted by mistake, but they are in the attached pdf)

https://www.electro-tech-online.com/threads/glcds-with-pic-18f-assembler.40676/

With a glcd there is so much scope for more information / options on the screen for the user to choose /select.

This also introduces the option of a touch screen as a practical reality for diyers - attached are pics of my current, very early, touch screen work.
The touch screen overlay and fdc connector costs under GB £10

( this 5x3 switch touch panel is the simple 'digital switch' type that is connected directly to the pic without a special controller chip)


Clearly this opens the way to a totally different menu system, but it should provide the user with the best possible information.


hth

Richard
 

Attachments

  • 2008-07-24 003.JPG
    2008-07-24 003.JPG
    259.6 KB · Views: 943
  • 2008-07-08 003.JPG
    2008-07-08 003.JPG
    65.5 KB · Views: 927
Your idea of initially entering a number seems a little bit of a retrograde step, certainly not a method new users would find easy without a printed list of codes.
Hi Richard,

I think you may have missed the point of my post. Please note the quote and my description.

I posted an example of how I store string tables in-line with my code to produce code which seems more intuitive (to me). That example was for a Hyperterminal menu system where you have the benefit of the PC keyboard for input.

Mike
 
Last edited:
hi,
A common simple method for multi item menus, using just 4 push buttons.

I use 4 n/o push buttons., with primary names 'Menu', 'Inc', 'Dec' and 'Accept'
and secondary functions as 'Escape', 'Opt#1, 'Opt#2', 'Enter'

Pressing the 'Menu' key steps thru all the available options, one push at a time, the option is displayed on the LCD, press the 'Menu' key again for the next menu option and so on.

If the menu option I want is displayed, I press the 'Accept' key.
This displays on the LCD, the parameter value for that menu option.

If the 'Inc' or 'Dec' key is pressed the selection parameter is inc/dec, pressing the 'Accept' key move the LCD cursor to the next parameter value.... if at the end of the inc/dec's I want to save and use the values just entered I press the 'Enter' key, if I want to discard the new values I press the 'Escape' key and move onto the next Menu item.

At the end of the setup sequence, the 'Enter' puts the LCD back to displaying as per the running program..

Example: say the LCD displays the 'real time' as a normal function, pressing the 'Opt1' key would show the Date on the LCD and pressing the 'Opt2' would display the Temperature.

Pressing the 'menu' key would display 'Set Date', pressing 'Accept' would display the Date with cursor under the 'days' value, [inc/dec as required] press 'Accept' again the cursor would move to the 'months' value and so on.
 
Inline strings.

With assembly language programs I find that storing string tables in-line with your code provides a more intuitive structure, much like a high-level language;

I get the idea, although I don't recognize this type of coding. I think this link also expresses this (very sensible) notion in the assembly that I understand,

https://www.phanderson.com/PIC/16C84/mult_string.html

I'll definitely use this. And Mike, thanks.

I think the 'retrograde notion' was a reference to my menu idea. True enough, but that's why I'm here - to emerge from my own dark ages.
 
Last edited:
Like Eric, I also normally use four push buttons on my interactive projects. Also like Eric, those four push buttons behave differently depending on where you are in the program and what you're doing on the LCD screen.

The instructions you see that don't look familiar are macros. I'll show you the PutStr macro in a subsequent post.

Menu systems aren't that difficult. Here's a simple 3 item LCD menu example (for 16F' devices) that uses <up>, <dn>, and <rt> arrow push buttons (yes, it uses macros). I've omitted the PCLATH code in the jump tables for clarity (caveat);

Mike

Code:
Menu
        clrf    Item            ; Item = 0                        |B0
        goto    PutItem         ; put item string on LCD          |B0
Menu.a
        swtest (uparrow)        ; if <up> arrow key               |B0
        goto    DecItem         ; branch, else                    |B0
        swtest (dnarrow)        ; if <dn> arrow key               |B0
        goto    IncItem         ; branch, else                    |B0
        swtest (rtarrow)        ; if <rt> arrow key               |B0
        goto    SelItem         ; branch, select item, else       |B0
        swtest (setsw)          ; if <set> switch pressed         |B0
        goto    SetMode         ; branch, else                    |B0
        goto    Menu.a          ; start over                      |B0
DecItem
        movf    Item,W          ; Item > 0?                       |B0
        bz      Menu.a          ; no, branch, else                |B0
        decf    Item,F          ; dec menu item number            |B0
        goto    PutItem         ; put item string on LCD          |B0
IncItem
        movf    Item,W          ; Item 0..2                       |B0
        xorlw   2               ; last item?                      |B0
        bz      Menu.a          ; yes, branch, else               |B0
        incf    Item,F          ; inc menu item number            |B0
        goto    PutItem         ; put item string on LCD          |B0
SelItem
        movf    Item,W          ; Item 0..2                       |B0
        addwf   PCL,F           ;                                 |B0
        goto    Item0           ; branch to item 0 code           |B0
        goto    Item1           ; branch to item 1 code           |B0
        goto    Item2           ; branch to item 2 code           |B0
PutItem
        PutLCD  cmd,line2+4     ; line 2, htab 4                  |B0
        movf    Item,W          ; Item 0..2                       |B0
        addwf   PCL,F           ;                                 |B0
        goto    Istr0           ; print item string 0             |B0
        goto    Istr1           ; print item string 1             |B0
        goto    Istr2           ; print item string 2             |B0
;
Istr0   PutStr  " menu item 0    "
        goto    Menu.a          ;                                 |B0
Istr1   PutStr  " menu item 1    "
        goto    Menu.a          ;                                 |B0
Istr2   PutStr  " menu item 2    "
        goto    Menu.a          ;                                 |B0
;
;  Item code modules
;
Item0   nop                     ;                                 |B0
        ........
Item1   nop                     ;                                 |B0
        ........
Item2   nop                     ;                                 |B0
        ........
 
Last edited:
My existing pic assembler / 2x16 lcd menu system is done by pressing a switch to invoke the main menu and pressing the key again to advance to the next menu function, - very simple but effective although a little cumbersome.

...

Your idea of initially entering a number seems a little bit of a retrograde step, certainly not a method new users would find easy without a printed list of codes.

There must be many possible ways of creating menus, but the limitation will always be the lcd, typically a 2x16 unit. A 4x16 will give more freedom but basically the same constraints.

Probably something you may have looked at but discounted, is the use of glcd units.
They can be used a simple text screen, giving an equivalent display of 8 rows of 16 + characters, or with large character images as shown in the attached picture.


They are cost effective and practicable with simple assembler code, as can be seen in my recent post ( sorry the opening message photos deleted by mistake, but they are in the attached pdf)

https://www.electro-tech-online.com/threads/glcds-with-pic-18f-assembler.40676/

...

This also introduces the option of a touch screen as a practical reality for diyers - attached are pics of my current, very early, touch screen work.
The touch screen overlay and fdc connector costs under GB £10

( this 5x3 switch touch panel is the simple 'digital switch' type that is connected directly to the pic without a special controller chip)

...

Good stuff. The link to the GLCD code was particularly interesting. It looks (on the 18F PICs) like a straightforward business, even in assembly. Currently I'm still on 16F PICs + MPASM, but will definitely consider GLCDs once I've got through all the other acronyms.

Your 2x16 menu, is that code you would be prepared to share or describe?

I'm surprised I couldn't find explicit menu designs on piclist.com.
 

Quote:-

Your 2x16 menu, is that code you would be prepared to share or describe?



Its a 2 line and 16 row lcd , the menu started as simple 10 level affair, which over the years has outgrown itself to nearly 30 consecutive levels -hence my earlier looking around for a better system.

Think one of the best methods is to put your menu ideas onto a flowchart, it soon becomes apparent which is the easier way for your system.


I assume you existing code will handle a 2x16 display ok ? - my menu code is, I'm afraid its so intertwined with all my other code it would not make much sense as an example for you. A good lesson in how not to code - keep things in separate routines wherever possible

Mine was also just a two key system, as I was trying to save on I/O ports, which I now regret.
I think a 4 key system like Eric has just mentioned to be a much more practicable way.

Richard
 
Richard,

Your comments are perplexing. When you're dedicating six or more pins to drive a character LCD you only need a single additional pin to read 1 to 5 push button switches by multiplexing some of the LCD lines.

Mike
 
Menu systems aren't that difficult. Here's a simple 3 item LCD menu example (for 16F' devices) that uses <up>, <dn>, and <rt> arrow push buttons (yes, it uses macros). I've omitted the PCLATH code in the jump tables for clarity (caveat);

Mike

Good stuff, Eric's also. Definitely a main menu design to consider for small 2x16 LCD displays. This is much better than asking the user to enter a menu-index number.

I began to write a long reply about the potential for reducing the menu system down to a few of generic subroutines, using indexes to keep track of where one is in the hierarchy tree, and indirect addressing to move the relevant data around. I then realised this complexity is only profitable for very large, deeply embedded, degenerate menu systems. In reality it seems individual (sub)menus are rather unique and the entire menusystem broadly irreducible.

Although I have potentially up to nine items in mind for my particular main_menu (i.e I have Item0 to Item8), the subsequent submenu system is only one submenu deep (i.e. user is prompted to enter a number and returns to main_menu). In this case it seems that writing every submenu out explicitly is not only the simplest approach, but is also an acceptably efficient use of program memory.

This has helped me a lot, especially seeing some actual code. For now I'll adopt Mike/Eric's approach. The future -> touchscreen glcds.

Mike, you wouldn't happen to be in Ann Arbor, would you? I work at UofM.
 
Richard,

Your comments are perplexing. When you're dedicating six or more pins to drive a character LCD you only need a single additional pin to read 1 to 5 push button switches by multiplexing some of the LCD lines.

Mike

Hi Mike,

Yes I do know that now, but when I started coding it was way beyond me, and didn't then know of helpful sites like Electro Tech etc.

Also, guys like Astro, just starting may get overwhelmed by too many options, so I didn't want to complicate things at this stage.



Richard
 
Astronomer',

As promised, here's the PutStr sub-system for 16F' devices in a nut-shell. It's very similar in function the the PH Anderson examples you cited.

You would want to replace the call Put232 instruction with a call to your PutLCD subroutine. The return (\r) and newline (\n) characters probably don't serve any function in most character LCD applications. A similar sub-system for 18F' devices is much smaller, tighter, cleaner.

Have fun. Mike

Code:
;******************************************************************
;
;  example macro usage
;
        PutStr  "Bill's Particle Accelerator Demo\r\n\n"
        PutStr  "Main Menu\r\n"
;
;******************************************************************
Code:
;******************************************************************
;
;  PutStr macro - print a string to the RS-232 port
;
PutStr  macro   str             ;
        local   String, Print
        movlw   low String      ;
        movwf   PTRL            ;
        movlw   high String     ;
        movwf   PTRH            ;
        goto    Print           ;
String  dt      str,0
Print   call    PutString       ; print string
        endm

;******************************************************************
Code:
;******************************************************************
;
;  PutString Subroutine
;
;         - setup PTRL and PTRH to string address before entry
;         - string must be terminated with a 0 byte
;
PutString
        call    GetTable        ; get a table character            |B0
        andlw   b'11111111'     ;                                  |B0
        btfsc   STATUS,Z        ; a 00 byte, last character?       |B0
        return                  ; yes, return, else                |B0
        [COLOR=Red]call    Put232[/COLOR]          ; output character                 |B0
        incfsz  PTRL,F          ; increment pointer                |B0
        goto    PutString       ;                                  |B0
        incf    PTRH,F          ;                                  |B0
        goto    PutString       ;                                  |B0
;
GetTable
        movf    PTRH,W          ;                                  |B0
        movwf   PCLATH          ;                                  |B0
        movf    PTRL,W          ;                                  |B0
        movwf   PCL             ;                                  |B0

;******************************************************************
 
Last edited:
hi,
This is a very simple example of the 4 pb menu.

Code:
example only, in Basic expanded format.

main:
do while menukey = 1
..... normal operating code here
wend

do while menukey =0 ' finger off pb, test
wend

do while menukey =1
wend
'
do while menukey =0 
menu1:
lcdout "[B]Set Date[/B]"
if acceptkey = 1 then
goto set_date
endif

do while menukey =1 ' finger off pb test
wend
'
do while menukey =0 
menu2:
lcdout "[B]Set Time[/B]"
if acceptkey = 1 then
goto set_time
endif

set_date:
lcdout "[B]dd mm yy[/B]" ' actual date, [dd is underlined by LCD cursor]
'
set_day:
if Inckey= 1 then
..... inc the days
endif

if deckey= 1 then
..... dec the days
endif

if acceptkey= 1 then
goto set_month
endif

if  escapekey= 1 then
goto quit
endif
goto set_day
'
set_month:
lcdout "[B]dd mm yy[/B]" ' actual date, [mm is underlined by LCD cursor]
......................................................


Its easy to change the number of menu items and internal routines for the pb's.

Important point is that, the menu's are in plain English text and can be displayed on the bottom line of the LCD,
just above the push buttons.
 
Last edited:
As promised, here's the PutStr sub-system for 16F' devices in a nut-shell.

Very kind of you to share this. I see now that the macro is a useful modular way to develop textual menus in assembly code. I'll try and implement some of this tonight.

The azimuth, elevation reference did not go unnoticed.

Eric; thanks for the program flow. This does seem like a good project for something more readable, like basic.
 
Last edited:
Nothing to do with astronomy, really. The azimuth, elevation reference did not go unnoticed.
I worked a few Ham radio operators several years ago through the LEO (low earth orbit) Russian RS-12/RS-13 satellite. I kept a program on my PC up to date with Keplerian data and the program provided accurate AOS and LOS and it also controlled both of the VFO's on my cross-band transceiver (transmitter uplink and receiver downlink) to automatically correct for Doppler shift once I acquired the satellites beacon. It was a wonderful and exciting experience.

Mike
 
Last edited:
Astronomer',

As promised, here's the PutStr sub-system for 16F' devices in a nut-shell.

I'm pleased to report that your code worked like a charm, on the first try. Hadn't seen 'low' and 'high' before - somehow I had entirely missed the MPASM User's guide...
 
Astronomer',

As promised, here's the PutStr sub-system for 16F' devices in a nut-shell. It's very similar in function the the PH Anderson examples you cited.

A similar sub-system for 18F' devices is much smaller, tighter, cleaner.

Eventually I built a fairly sophisticated menu system to interface and send toggles, 16bit variables, reset commands, and so on, to my 16F887 project. the menu system - written in assembly - turned out to be by far the largest part of the code. Very enjoyable and successful experience, until a few days ago.

Solid days of debugging revealed inexplicable behaviours that defied my understanding of PICs. There came a point when the mere addition of lines of code would cause bizarre failures - and it didn't matter what code you added. I though it might be paging issues, but I was on Page0, no data tables crossed 'xxFF' addresses, etc. A futile nightmare to simulate. I considered asking for help, but instead I'd like to ask a different question. Is a menu system better implemented in C?

Sadly Hitech's C compiler for 16F devices simply kills my MPLAB (v8.10), so I was thinking of investigating the 18Fs (i have a couple of 18F4550) - presumably using microchip's C18 compiler. Mike's comment above, suggests this might indeed be a good idea.

So, how does one achieve a 'smaller, tighter, cleaner' menu system on the 18F compared to the 16F? Just by using C, or does the 18F have something particularly special?
 
Status
Not open for further replies.

Latest threads

New Articles From Microcontroller Tips

Back
Top