Proton BASIC Compiler - A Real Time Operating System for the PIC – Part 3

  • Pic® Basic

  • BRTOS: Basic Real Time Operating System for PIC® micro – Part 3

    By John Barrat

    This section describes interfacing to a general purpose menu system which can be operated with a 2 line LCD and 4 key, keypad.
    First, an explanation of the menu basics – when no buttons have been pressed the display will be showing its default display (in the case of the demo application the time and date on the top row of the display). Four buttons beneath the display have the following Functions:
    Menu – this invokes the interacting menus, successive presses of the menu button will cycle round all the menus.
    Inc/Dec – these 2 buttons can be used to either move between items within a menu or adjust the value of items.
    Set – this button is used to accept the change. It might be used to take the user on to another item in the data entry sequence or may return to the top menu item for that sequence.
    In all cases, if buttons have not been pressed within a set period, the display will revert to its default mode. Holding a button down for a default period will invoke key repeat.
    Menus can have Sub Menus and the top level menu is called the Main Menu. Pressing the Menu button moves between Main Menus, depending on context the Inc/Dec or Set buttons can be used to move between sub menus.
    In the default mode the Set, Inc and Dec buttons have no direct function. The system however lets you assign specific functions to these buttons if you wish. The Menu button will always have to retain the fixed Menu function.
    The system supports more than one default display. How the default display is selected is up to the application. I generally use the default Set button to move around the default display options.
    Operation of the Demo program - In the demo program the Inc and Dec buttons have been used to adjust the LCD contrast when in Default Display mode. The menu button will invoke the Set Clock menu item. (As it is only a clock there are no other menus in the demo). The table below shows how the menu works for the Demo program.
    Default Display Contrast Contrast Main Set Clock
    Main Set Clock (DS) Next Toggle Toggle Main Set Clock
    Sub Set Hours Enter/Next Dec Hours Inc Hour Main Set Clock
    Sub Set Mins Enter/Next Dec Minutes Inc Minutes Main Set Clock
    Sub Set Day Enter/Next Dec Day Inc Day Main Set Clock
    Sub Set Month Enter/Next Dec Month Inc Month Main Set Clock
    Sub Set Year Update Clock
    Main Set Clock
    Dec Year Inc Year Main Set Clock
    If there were additional menu items, pressing the menu button would take the user to the next main menu item. As there is only one menu in the demo it returns to that menu.
    The system supports an additional Config Mode of operation which can force the system into a different set of menus. In this mode there is no timeout back to a default display and there has to be a specific menu action to leave this mode. This facility would normally be used in setting up specific parameters in the system.

    Interfacing to the Menu System

    Having explained the basic operation of the system lets see how the application can hook into the code to tailor the menus to the requirements of the application.
    This module probably has the most interaction of all the modules with the application program as it is essentially the user interface. It has no function on its own without the application code; however what it does provide is a standardised method of calling functions which move between menus and for controlling the display.
    The menu system is essentially a state machine with the current state of the menu held in a byte variable called MenuAct. This variable holds the MainMenu number in its high nibble and the SubMenu number in its lower nibble. Thus in theory it would be possible to support at maximum of 15 Main menus each with 15 sub menus. When no menu is active (i.e. Default Display mode) the MenuAct value is zero. The table below shows this diagrammatically:
    Menu Timeout
    Default Display
    Main Menu
    Sub Menu
    Sub Menu
    Sub Menu
    Sub Menu
    In this example there are 5 Main menu items, Main menu 1 has 4 sub menus, 2, has 1 sub menu, 3 and 4 have 2 submenus and 5 has no sub menus.
    The number of Menu items is defined by the constants MnuMTNum and MnuMCNum for the Main Menu and the Config menu respectively. Submenu sizes are set in code as they can vary from menu to menu.
    When the menu button is pressed from the Default Display mode the Menu code will call a routine in the application code called RemoveDefaultDisp. This routine allows the application to clear up any tasks before entering the Menu mode. The Menu code will then call ProcMainMenu in the application code. (MenuAct will hold the value $10 indicating the first Main menu item).
    ProcMainMenu is a jump table to application code for each menu indexed by ActPtr. (ActPtr is simply the MS nibble of MenuAct - 1 so that the jump can be 0 based). Successive pressings of Menu will increment MenuAct (and hence ActPtr) up to the maximum number of menus set in the application code. Similarly, when in the Menu mode, pressing any of the other buttons will call a similar jump table for that button.
    See the code snippets below.
    On ActPtr GoToL Menu_Clock, Menu_Next, etc...
    GoSub ActionFail [10]

    On ActPtr GoToL Set_Clock, Set_Next, etc...
    GoSub ActionFail [20]

    On ActPtr GoToL IncDec_Clock, IncDec_Next, etc...
    GoSub ActionFail [30]

    Once in Menu mode, before calling ProcMainMenu to move to the next Main menu item the Menu code will call CancelMainMenu. This is another jump table which allows code to be added to clear up any of the existing menu before moving out of the current menu an onto the next menu item. See code snippet below:
    On ActPtr GoToL Can_Menu_Clock, Can_Menu_Next, etc...

    (Where action is not required in any of the above jump tables Can_Menu_Def should be placed in place of the expected jump label).
    Three calls allow the Main Application code to move between submenus within the defined range for the current menu.
    IncDecSubMenu – will move the submenu number up or down depending on whether Inc or Dec button pressed.
    DecSubMenu will decrement the Submenu number
    IncSubMenu will increment the Submenu number.
    These routines have to be called specifically from the relevant code in the application.
    When no key has been depressed for the set menu timeout period, the Menu code will call Cancel_Main_Menu for the current menu, clear MenuAct to zero and call RestoreDefaultDisp which will set up the display to return to the current Default.
    The application can, where appropriate, disable specific buttons when in a specific menu. Setting any of the three variables MenuHold, SetHold, IncDecHold will cause the Menu code to ignore the respective button.
    Look at the Demo program in MainTest to see how the clock application uses the menu functions.
    Default Display Mode – When the system is in Default Display mode, the menu will call DefltSet, DefltInc and DefltDec routines whenever the Set, Inc and Dec buttons are pressed. These can be used to provide certain fixed functions outside the menu. I usually use Set to cycle around alternative default displays. In the case of the demo program I have used Inc and Dec to adjust the contrast of the LCD display.
    As mentioned earlier, there is a ConfigMode which can be invoked from the keypad which will force the system to use a different set of menus. The ConfigMode is reached by depressing more than one of the keys at the same time. The ConfigMode key combination is defined in the constant ForceConfig.
    ConfigMode – In ConfigMode the menu will call an alternative set of routines which you can use for setting up the application etc. Before entering ConfigMode the screen prompts the user to confirm. The first item in the Config Menu is used for this purpose. In the demo only “No” is permitted when ask to confirm entry into ConfigMode The code snippets below show the config code used in the demo – as there are no configuration menus each routine returns simply calls Can_Menu_Def.
    On ActPtr GoToL Menu_Cfg_Chk, Can_Menu_Def
    Cls : GoSub ActionFail [11]

    On ActPtr GoToL Set_Cfg_Chk, Can_Menu_Def
    Cls : GoSub ActionFail [21]

    On ActPtr GoToL IncDec_Cfg_Chk, Can_Menu_Def
    Cls : GoSub ActionFail [31]

    In configuration mode there is no menu timeout function. You must explicitly add code under one of your menus to return to normal mode. The simplest route here is to execute a software RESET once all the configuration changes have been saved.

    Underneath the Covers

    The menu code supports interrupt driven or polled scanning of the keys. The interrupt driven approach consumes much less processor resource although it does require a little more code. It also uses TMR1 set to 50Hz (20mS) in the PIC® to manage de-bounce and repeat delays. However, as it runs continuously it could also be used for other timing activities with a little modification.
    I will discuss the details of this part of the code further in the article covering Interrupts and Serial Communications interfacing.

    Attached Code:

    MainCTest.Bas The main application code The Menu code.

    Further Reading

    The next article, written by JohnB, will describe the interrupt routines I have used in BRTOS to support the serial communications and keypad.

    About the Proton Compiler

    Crownhill's Proton Plus Compiler is a part of the Proton Development Suite - A suite of British-developed applications enabling fast development of PIC® micro's using the PIC® BASIC Language.
    For more information on the Proton Development Suite, please visit