Many embedded applications need to present status and allow users to manage settings. TcMenu provides first class support for both presenting status and managing configuration/settings using menu items. It is possible to use with and without a local user interface. All menu item types can be accessed remotely, and we have a remote API, UI solutions, and connectors to commercial IoT endpoints for that.
Each menu item is part of a tree, if you are unfamiliar with trees, there’s a little terminology worth learning. We refer to elements that hold other items as the parent of those items. Conversely, each of the items in the sub menu are children of subMenu. Let’s take a look at an example:
Root menu (parent of Item1, Item2, SubMenu)
+- Item 1 (child of root)
+- Item 2 (child of root)
+- SubMenu (child of root, parent of subItem1, subItem2)
+- SubItem1 (child of subMenu)
+- SubItem2 (child of subMenu)
On the device, we store menu items in a linked list structure where the getNext()
of a menu item points to the next item in the list, each submenu holds an additional linked list, of child items access using getChild()
. We must terminate every list with NULL. Let’s express the above list in this format:
Item1 -> Item2 -> SubMenu -> NULL
-> SubItem1 -> SubItem2 -> NULL
Each item has a type that defines what kind of data it can hold, for example an analog item can hold fixed point numeric information stored as an integer. Whereas a sub menu item does not have any “data” of its own, but holds child items that appear below it. Every menu item you create can be accessed in code using its variable name. File yourProjectName_menu.h
has all the definitions ready exported. Let’s say we have an item called Brightness
in the Settings
Sub Menu, then the variable name would be as below:
This guide is designed to be read in conjunction with the tcMenu reference documentation.
TcMenu can handle many menu item data types with each one extending MenuItem, so you can rely on some features always being available. Later on this page we’ll provide links to each menu item type, but first let’s look at properties common to all:
On the designer you edit these parameters by selecting the menu item from the tree, the properties area will show something similar to below:
When an item changes, the manager can call you back to let your code take appropriate action, if you provide a function name in the designer, it will be generated in your sketch only if it doesn’t already exist.
When no callback is required you either leave the field blank, or set it to NoCallback
. Either of these indicate there is no callback for this item.
This is a simple example showing how we would control a PWM channel based on the value of a menu Item. In this example we have an AnalogMenuItem
called menuExample
, that has the same range of values as the PWM channel.
void CALLBACK_FUNCTION onExampleChanged(int id) {
analogWrite(somePwmPin, menuExample.getCurrentValue());
}
For advanced users you can click the “edit” button shown to the right of the callback, where you can select from one of the options in the callback type combo:
@myCallback
. Doing this will result in myCallback
being declared but not implemented. An example implementation will be provided in the “Code definition if needed”, and you should put this into a CPP file somewhere.NOTE about definition only mode: You will then need to implement the function somewhere yourself or there will be a linker error.
To get the ID of any menu item
int id = menuItem.getId();
To get the item name into a character array
copyNameToBuffer(char* buffer, int bufferSize);
To get the sub class type of the MenuItem, useful before casting it:
MenuType type = menuItem.getMenuType();
To get the EEPROM storage address
uint16_t position = menuItem.getEeepromPosition();
To get the maximum value for any item
int maxVal = menuItem.getMaximumValue();
Checking if an item has changed or marking it as changed is handled using the changed methods, Note there’s also several remote-change flags, remote changed means that the actual value needs to be remotely communicated. Unless you use the silent version of the set… method, the changed and remote flag will be set automatically.
// set the item changed locally
menuItem.setChanged(changed);
// indicate that the item also needs to be sent remotely
menuItem.setSendRemoteNeededAll();
// check if the menu item is changed
bool b = menuItem.isChanged(newState);
Menu items can be made read only and therefore cannot be edited, default is false (editable):
menuItem.setReadOnly(newState);
bool b = menuItem.isReadOnly();
Menu items that are not visible will not be displayed, default is true (visible).
menuItem.setVisible(isVisible);
bool b = menuItem.isVisible();
Menu items that are local only will never be sent to any remote, default is false (not local):
menuItem.setLocalOnly(bool localOnly);
bool b = menuItem.isLocalOnly();
Core menu item types that others extend from
Menu item types that you can generate