Application development guide
There is a single commit (commit:64805071) that contains an example application that might be a good starting point to start development. I did my best to make it as simple as possible, but here you may find some additional comments.
Template (example_app.c)
NOTE: There is a slight mistake, the header file (example_app.h) is not
necessary and not used anywhere.
There are two main concepts that may help you understand the way
application works.
Events
Freewatch applications are event-driven - they receive information about
what is going on, so they have a chance to respond appropriately. An
example of action that results in event reception is a button press or
sensor interrupt. Afterwards, you may decide to redraw a part of user
interface, update internal state or save data - depending on what has
happened. Available event types are listed in sw/common/event.h.
Events are transferred from the operating system to applications via
queue. Typically, there is one main event loop that receives them and
lets you decide what should happen next. The event loop also allows you
to react if there are no events for a specified period of time.
If you expect events from sensors, you should configure them to generate
interrupts. Enabling unnecessary interrupt sources results in redundant
events and may decrease both performance and battery life. It is a good
practice to react only to events that you expect and really handle in
the code.
In the provided example there are only two types of events, but you
should expect more in the final version.
Widgets
Widgets are parts of the graphical user interface, such as buttons, checkboxes, scrollbars, etc. They have a visible representation and are expected to react to events. That is the reason why they are described by a structure (struct ui_widget) that contains:
- Drawing routine - code that describe appearance (have a look at the graphics library located in sw/common/gfx).
- Event handler - processes received events.
- Dimensions - contain the location and size of a widget.
- Surface - canvas used for drawing.
- Flags - indicate the internal state.
You may create a single widget that handles all events and then redraws everything, but it could be easier to manage more smaller widgets that have a single task to perform.
If you think that widget that you have just created could be of any use for others, please put it to folder sw/freertos/src/apps/widgets. There you may also find source code for the status bar, that is expected to be displayed by most of the applications.
Menu entry
To make your application visible in the main menu, choose the right submenu (or create a new one) and an entry in sw/freertos/apps/src/menu_struct.c:
{ APP, &example_icon, { .app = &example } },
The three fields indicate:
- APP stands for application type entry
- &example_icon is pointer to a structure containing icon data (or NULL if there is no icon); more details below
- structure dependent on entry type; for applications it stores a pointer to your application structure
Example submenu entry:
{ SUBMENU, NULL, { .submenu = &sub_menu } },
explained:
- SUBMENU is the entry type
- NULL means that there is no icon (but you can have one for submenus too)
- the last field is a structure with a pointer to the submenu (menu_list type) that should be activated
There is also a special entry that servers as the sentinel:
{ END, NULL, { NULL } }
You should have one at the end of each submenu, otherwise baaaad things will happen - I promise.
Icon (and other graphics)
To decorate an entry in menu with an icon, you need to create a 16x16
pixels bitmap (.bmp format) and put it to sw/bitmaps/ folder. Afterwards
run the bmp2rle.py script. It will convert the new bitmap to a C
structure that may be used as icon (bitmaps.{c,h} files). You can add
any graphics you would like to use in your app in the same way.
If your file is named graphic.bmp, then the created structure will be
called graphic (struct rle_bitmap type) - this is what you type in
menu entry in the icon field (prefixed by &, as in the example above).
The last small change is to add your application structure in
sw/freertos/apps/app_list.h, so it could be accessible to the menu
code.
More examples
If you seek more, then have a look at clock application (sw/freertos/apps/clock.c) or menu (sw/freertos/apps/menu.c). I recommend starting with the clock app, it is easier to follow.