Shop OBEX P1 Docs P2 Docs Learn Events
Flexible menu system for spin? — Parallax Forums

Flexible menu system for spin?

RavenkallenRavenkallen Posts: 1,057
edited 2010-06-01 06:36 in Propeller 1
Very recently i have found out that the current menu system that i am using will not work do to a ton of recursive method calls. I asked about different types of alternative menu systems and i got back varied results. I was just wondering if anybody knows anything about a better menu system in a GOTO-Less spin structure. I thank the people who have already helped me and i am·glad to find such a friendly forum.

Comments

  • JonnyMacJonnyMac Posts: 9,208
    edited 2010-05-31 02:20
    A menu system is generally optimized for a hardware UI -- what kind of display and input are you using?

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    Jon McPhalen
    Hollywood, CA
  • RavenkallenRavenkallen Posts: 1,057
    edited 2010-05-31 03:04
    I am using a character 20x2 lcd with a serial protocol and a parallax ps/2 keyboard. All i need is something simple.
  • bill190bill190 Posts: 769
    edited 2010-05-31 03:32
    How about using a separate object for each menu,·along with·cognew and cogstop (to kill off the old menus)?

    You make·menu selections going down and it starts new objects along the way and kills off the menus it is leaving behind.

    Then opposite going back up.

    Would this use·up stack space? (I don't know???)
  • RavenkallenRavenkallen Posts: 1,057
    edited 2010-05-31 03:49
    Hey, bill190. That sounds like an idea. I just might try that out. UGGHH, it is has been so difficult trying to figure out what to do.
  • T ChapT Chap Posts: 4,223
    edited 2010-05-31 05:00
    I am not sure if this offers any help to your problem, but here is what I do for a menu system on a 2x16 LCD with several buttons to navigate. The buttons are < > for navigating through each item in the menu. Then -NO and +YES buttons to increment/dec the values of that menus parameter(s). Then ENTER for various menu functions. Last, the SETUP button which enters the menu list from the main loop running elsewhere. I use a PCF8574 I2C device to read the 6 button states.

    There are two main parts of the menu, the MAINMENU and the List of Case Statements. Then, create the methods as needed, each method requires the section to trap the buttons as they are pressed. Then there are the individual methods for changing the values as needed. Maybe you can at least get some ideas from this system.


    
    PUB MainMenu | n
        n := UpdateIndex     'updateindex is stored in eeprom so each time entering menu, you are at the same item as last visited.
        CLS    'clear LCD
        go(0,0)
        ser.str(3, string("Main Menu"))
        go(1,0)
        ser.str(3, string("< > View Options"))
        repeat while ina[noparse][[/noparse]setupkey] == 1     'trap here till button released to start menu
        Repeat
         ReadSetupKeys
         If setupkeys == leftbut
            n := n - 1  #>  1       
            cls
            spk.beep(19, 3500, 100)
            UpdateIndex := n
            WriteUpdateIndex   'update the menu position in eeprom for future use.  
         elseIf setupkeys == rightbut
            n := n + 1  <# 28      '<<<<<<always update this value based on number of menu items
            cls
            spk.beep(19, 3500, 100)
            UpdateIndex := n
            WriteUpdateIndex
         trap := on
         Option(n)
         If setupkeys == setupbut
            spk.beep(19, 3500, 100)
            setupled := on    'led = of
            SetPcbLED_PinState
            CLS    'clear screen
            return  1
    
    
    PUB Option(N)   'examples
        Case N
             1:  if Method1  == stop   
                   return
             2:  if Method2  == stop  
                   return
             3:  if Method3  == stop  
                   return
    
    
    PUB IDSet    'example   set the ID for this device
       cls
       go(0, 0)
       ser.str(3, string("Set ID"))
       go(1, 0)
       ser.decf(3, ID, 6)
       repeat
         ReadSetupKeys    'reads I2C device to check button states
         if setupkeys == yesbut
            ID := ID + 1    <# 127
            go(1, 0)
            ser.decf(3, ID, 6)
            spk.beep(19, 2500, 200)
         if setupkeys == nobut
            ID := ID - 1  #> 0   ' limit min
            go(1, 0)
            ser.decf(3, ID, 6)
            spk.beep(19, 2500, 200)
         if setupkeys == enterbut
            WriteID    'write the value to eeprom
            WriteIndicator
    
         repeat while (setupkeys == yesbut) or  (setupkeys == nobut)
              ReadSetupKeys   'reads I2C device to check button states
         if trap
            if setupkeys == leftbut or  setupkeys == rightbut     ' test
               repeat scrolldelay      ' delay x if is still held from initial entry press   test
         ReadSetupKeys       'reads I2C device to check button states
         if  (setupkeys == leftbut) or  (setupkeys == rightbut) or (setupkeys == setupbut)  'get out of here if < or >
            WriteID
            return stop
         trap~   'remove initial trap state
    
    

    Post Edited (Todd Chapman) : 5/31/2010 5:05:27 AM GMT
  • heaterheater Posts: 3,370
    edited 2010-05-31 05:55
    Ravenkallen: At this point in your studies I might make a humble suggestion.

    Get yourself set up with a BASIC that supports functions and procedures on your PC. Try to create what you want in a menu system using that. Make the rule that you will not use GOTOs in your code.

    You can simulate your LCD with a couple of lines of screen output and use stub functions for the actions that the menu selections will ultimately trigger.

    It will be much easier to write, test, debug your menu system on the PC and in a language you are somewhat familiar with.

    When you have that working you will see how you can write the same thing in Spin.

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    For me, the past is not over yet.
  • MagIO2MagIO2 Posts: 2,243
    edited 2010-05-31 06:33
    Here's a thread about a LCD menu:

    http://forums.parallax.com/showthread.php?p=872190


    Here's another one, 3rd post contains a MenuDemo.spin. It's meant for a TV driver, but it should be easy to change it and at least gives you an idea how it can be done:
    http://forums.parallax.com/showthread.php?p=848636

    Post Edited (MagIO2) : 5/31/2010 6:44:06 AM GMT
  • RavenkallenRavenkallen Posts: 1,057
    edited 2010-05-31 21:21
    Thanks guys. I was kind of asking about menu systems in theory. Like an explanation on how to go about making one of them, like a tutorial of sorts. I googled various menu types and i didn't find any important info.
  • MagIO2MagIO2 Posts: 2,243
    edited 2010-06-01 06:36
    Well .. what's the theory behind a menu system?

    It's like any tree .. you have a root (the main menu) and then the root has nodes ( menu entries ) which can be a branch ( submenu-entry ) or a leaf ( let's call it the action entry because it really starts some code ).

    So, first of all you have to think about a data-structure which allows to define this tree-structure.
    Just as an example, you could have a structure that describes the (sub)menu: pointer to (sub)menu-name, number of entries (NOE)
    followed by·a structure that describes a menu entry: type ( branch or leaf ), pointer to name, pointer to submenu ( in case of a leaf it's used·to·store a function number )

    Next thing is a piece of code which can handle this data-structure according to the given user input.
    With up/down the previous/next menu entry is getting the focus within the range of 1 to number of entries (NOE)·of the actual menu description.
    With enter the focused entry is selected. If it's a leaf the function number of the menu entry is passed to the code that executes the functions. ( return value or global variable ).
    If the selected entry is a branch, the code switches to the submenu.
    With ESC the menu-system returns to the parent menu.

    [noparse][[/noparse]·By the way ... recently there was a thread about recursive function calls ... here a recursive function call can help to keep the menu-handler easy.
    You start with menuHandler( @rootmenu ) and each submenu is doing a recursive call menuHandler( pointer to submenu ). Hitting ESC is then as easy as RETURN - you should only prevent that the first menuHandler should not allow an ESC ]

    The third thing needed is a presentation layer. This is needed to print the menu on the device you have. It's a good idea to keep the menu-handler separated from the code that prints the menu. Because then it's easy to use the same data-structure and menu-handler for different systems (text LCD, TV, graphical LCD).
    You can do that by defining an interface to the presentation part, for example just one function that's used by the menu-handler like
    printMenu( pointer to actual menu, number of entry having the focus)


    Then you need the code that uses the menu-system. There you have 2 possibilities:
    1. the using code simply starts the menu-system (in it's own COG)·which then runs independend. Selected menu entries (function number of the leaf) will be communicated via a communication buffer.
    2. the menu is the main-program and calls a function handler. The function handler is a case statement which contains the right function call per function number

    The difference? 1 needs an additional COG but it will always react on user-input. Maybe code to sync with the functionHandler is needed, as some functions might want to finish the job before the next selection can be done.
    2 is running the menu in the initial SPIN-COG. If a function want's to run in parallel the functionHandler can also do a COGNEW.

    So from a functional point of view there is no real difference except that in 1 the menu output device is always blocked by the menu-system, in 2 the function can delete the menu and do it's own output.

    Hope that helped ;o)



    PS: Practice is better than talking, so start writing your own menu-system and you'll very soon face the first problems (or not) and we can go on with discussing ;o)
Sign In or Register to comment.