Programming the Graphical User Interface
Programming interactive user interfaces for your Handheld instrument
The Graphical User Interface (GUI) Toolkit is a suite of programming tools that gives you the ability to build an informative and interactive graphical user interface to monitor and control your handheld instrument. This chapter:
- Introduces the structure of the GUI Toolkit;
- Takes you on a step-by-step guide to building your interactive application; and,
- Provides you with detailed descriptions of each component of the GUI Toolkit.
The Structure Of The GUI Toolkit
A graphical user interface is created from building blocks such as bit-mapped images and ASCII strings. These building blocks, or data, must be organized in an intuitive way so users can easily run your instrument. Object oriented concepts are the key to organizing this data and make it easy for you to design and implement your user interface. Object oriented programming allows you to organize data hierarchically based on objects and manipulate the data using methods. With the GUI Toolkit, it is simple to create elementary objects such as graphics that contain bitmapped image data and textboxes that contain ASCII string data. You can load those objects into other objects such as screens so that they can be shown on the display. You can create yet another type of object, a control, which can execute functions that acquire data from a user or actuate hardware when a user touches the keypad.
Object oriented programming
The two concepts of object oriented programming essential to modern programs with user interfaces are "Objects" and "Events". An object is an association of properties and methods, and may respond to events. An event is an external action that prompts an object into action. GUI Toolkit objects that can respond to events are called controls.
GUI object properties
Properties describe an object’s physical attributes like its size, location, or image. Objects contain a data structure that holds its properties. Properties generally don’t do anything by themselves; they are more like read/write variables. However, properties may qualify the object’s behavior when the object does do something or has something done to it.
Some properties may be read only while others may be read/write. GUI Toolkit properties are always 32-bit numbers and are accessed or modified by calling the methods Get_Property
or Set_Property
. Set_Property
requires a reference to an object, its property, and the new value, while Get_Property
requires a reference to an object and its property as parameters and returns the property value.
GUI object methods
Methods are actions the object can do or have done to it. Many methods, like Load
, are overloaded; that is, they are applicable to several different types of objects. For example, you can load graphics and textboxes into a screen. Overloaded methods allow you to use a single simple syntax with respect to many different objects.
GUI object properties
Events are external actions that an object responds to by executing a user defined function called an event procedure. Objects automatically recognize a predefined set of events, it is up to you to decide if and how they respond to those events. You specify the event procedure called when the event happens (or fires) by storing your function into the appropriate property using Set_Property
. Event procedures are written, for example, to specify the program actions that occur in response to the press of a key.
GUI toolkit objects
The following table lists the objects in the GUI Toolkit.
Object | Description |
---|---|
GUI_TOOLKIT | The central object that contains properties relevant to all other objects. |
GUI_DISPLAY | The object tied to the physical display. |
GUI_SCREEN0 to GUI_SCREEN3 | An object that contains a collection of other functionally related objects such as graphics, textboxes, and plots. |
GUI_KEYPAD0 to GUI_KEYPAD3 | An object tied to the physical keypad for each GUI screen. |
GUI_BATTERY | The object tied to the rechargeable batteries. |
GUI_TIMER | An object that repeatedly calls event procedures. |
GUI_ERROR | An object that contains the most recent GUI Toolkit error. |
GUI_PEN | A tool object that is used in conjunction with the Draw method to draw lines and geometrical figures onto screens. |
GUI_BUZZER | The object tied to the physical buzzer. |
GUI_FONT | A custom proportional font, 10 pixels tall, that is used to render strings in textboxes. |
GRAPHIC | An object that contains a single image as a property. |
FONT | An object that contains a single image composed of the 255 images of each character of a font that is used to render strings in textboxes. |
TEXTBOX | An object that uses a font object to render strings onto a screen. |
DATA_ENTRY_KEY | An object associated with a key on the keypad that adds a character to a textbox. |
ACTION_KEY | An object associated with a key on the keypad that responds to a user’s touch by calling an associated event procedure. |
SHIFT_KEY | An object associated with a key on the keypad that changes the shift state. |
PLOT | An object used to render numerical data into graphical form onto a screen. |
Some of these objects are created when you initialize the GUI Toolkit while others are created by functions that you write. All GUI objects reside in their own task with their own heap and some respond to events. In the next section, we’ll show you how to create your user interface and then how to write your application using the GUI Toolkit.
Building an interactive application
In this section, we’ll explore the GUI Toolkit in the order in which you would typically build your application. We’ll show you how to:
- Design and create your user interface on a PC;
- Transfer the images that you created for your user interface from the PC to the Handheld Controller;
- Write your application using the demo program as a reference guide;
- Handle errors; and,
- Expand the capabilities of the GUI Toolkit.
The demo program shows you how to build a multitasking application with five simple screens. The first screen combines a welcome message with an alphanumeric keypad example that allows you to enter text and show it on the display. The second screen (accessed by pressing shift-up then the "Display" key) allows you to adjust the contrast and brightness of the display. The third screen (accessed by pressing shift-down then the "Sound" key) allows you to change the length of each beep that is sounded when you press a key. The fourth screen (accessed by pressing the F1 key) displays a textbox using a custom font of 8 point Comic Sans. The fifth screen (accessed by pressing the F4 key) displays the state of the battery charger. As we describe each part of the GUI Toolkit, we’ll use the alphanumeric keypad screen of the demo to illustrate the important concepts.
Designing your user interface
Before you start coding your application, it’s a good idea to sketch out how you want your user interface to look. Figure 1 shows a rough sketch of the first screen of the demo program. Sketching out your user interface before you start programming will help you to think about how you want your application to be organized and how you want to present information to your user.
Drawing your screens
Once you’ve sketched out and designed your user interface, you need to create bitmapped images of your interface using an image-editing program. Images may be created using Microsoft Paint, which is included with all versions of Windows. You can also use other image-editing programs such as Corel Draw, Photoshop, and Paint Shop Pro. In this section and throughout this chapter, we provide step-by-step instructions for creating and manipulating images using Photoshop. However, all of the image-editing programs have similar tools and functionality. For example, the pencil tool in Photoshop is simply called the pencil in Paint and the line tool in Photoshop is called the line in Paint. Thus, the steps listed in the examples, although specific to Photoshop, apply to all image-editing programs.
To create an image of a screen from your sketch using Photoshop:
- Create a new file with a width of 128 pixels and a height of 128 pixels, a resolution of 72 pixels per inch, and using the bitmap image mode. 128x128 is the size of the display and the size of a screen. The resolution is not important because it refers to the number of pixels per inch for the monitor. However, the image mode is important and must be set to bitmap if you are using a monochrome display. This configures the image to have one bit per pixel.
- Draw all lines using the pencil tool with a brush size of one pixel. The line tool, paint brush tool, and airbrush tool are also useful in drawing shapes and patterns.
- Draw text using the type tool.
- Save the image as a windows bitmap. A dialog box may appear informing you that some image data, such as printer settings, cannot be saved with this format. This does not affect the image so you can just click on OK.
The image that we created based on the sketch in Figure 1 is shown in Figure 2.
Creating your images
Once you have created the screens for your user interface, you need to ungroup them. Ungrouping the screens into smaller images will allow you to save space in Flash memory since you don’t want to store images with a lot of white space. To ungroup an image using Photoshop:
- Select the marquee tool;
- Left click on the upper left corner of an image you want to ungroup and drag the mouse pointer to the lower right corner of the image. This will create a box with a moving dashed line around the image;
- Note the location of the upper left corner of the image; this location will be needed when you want to load a graphic containing the image onto a screen;
- Under the Edit Menu, select the cut option to move the image to the clipboard. The image will disappear from the screen;
- Under the File Menu, select the create new file option;
- Name the file, based on the image. The height and width will automatically be set to the height and width of the image that is in the clipboard;
- Under the Edit Menu; select paste; and,
- Save the ungrouped image in the Windows bitmap format.
The width of an image must be a multiple of 8 pixels and the image must be positioned on an 8 pixel horizontal grid in a screen. Finer horizontal pixel placement and image widths would require bit shifting of each byte of the image every time it is drawn, significantly slowing performance of the GUI Toolkit. There are no limitations on the placement of an image in the vertical direction. The size of an image is limited by its placement and the size of the display. For example, an image placed in the upper left corner (at coordinates 0,0) can be up to 128 pixels wide by 128 pixels tall. However, if the image is moved 8 pixels to the right and 12 pixels down (to coordinates 8,12), the maximum size the image can be is 120 pixels wide by 116 pixels tall.
Transferring images to the Handheld controller
Once you have ungrouped all the images for your user interface, assemble them into a single directory. Images must be processed before you can use them with the GUI Toolkit; Mosaic’s Image Conversion Program concatenates images into a single text file called an Image Data File. The Image Data File is stored in the same directory as your images and when it is transferred to the Handheld Controller, it stores your image data in RAM and then copies it into Flash. You must transfer the Image Data File using Mosaic’s Terminal Program, to the Handheld Controller before you transfer your application code. For more information, see the subsection describing the Image Conversion Program in the "Graphic Object" section below.
The image header file
An Image Header File is also created with the Image Conversion Program and stored in the same directory as your images. The Image Header File associates the names of your images with the location of their image data in Flash. The Image Header File must be included in your application in order for you to create graphic objects.
The following shows the first few lines of the Image Header File used by the demo. The Image Header File defines a few constants, named after the image files display_screen.bmp, sound_screen_bmp, and welcome.bmp shown in the following listing. The constants contain the addresses of the image data in Flash memory on the Handheld Controller. For more information on the memory map of the Handheld Controller see Chapter 4: Making Effective Use of Memory.
//Listing 8-1 The first few lines of the Image Header File.// #define DISPLAY_SCREEN_BMP 0x7101F36 #define SOUND_SCREEN_BMP 0x102756 . . . #define WELCOME_BMP 0x103497
Coding your application
Once you have designed and built the user interface for your application and you have transferred the images to the Handheld Controller, you can start writing the code to animate your instrument. All GUI applications need the following components:
- The pre-loaded GUI Toolkit driver software;
- The Image Data and Image Header Files from the Image Conversion Program;
- An initialization routine that initializes the GUI Toolkit and sets up a task to run your application’s user interface.
- Routines that create and configure objects;
- Event procedures that animate controls;
- Routines that load objects onto screens; and,
- An endless loop that executes event procedures
Each of these components are described in the following sections.
The GUI Toolkit driver software
The GUI Toolkit driver software is pre-installed on your Handheld Controller. However, you will need to copy the library files (which define constants, structures, and headers for the GUI Toolkit methods) to the same directory as your source code as described below.
The GUI Toolkit driver software is provided as a pre-coded modular runtime library, known as a "kernel extension" because it enhances the on-board kernel's capabilities. The library functions are accessible from C and Forth.
The kernel extension for the GUI Toolkit is available from Mosaic Industries on the Installation CD. Look in the Demos and Drivers directory, in the subdirectory corresponding to your hardware, in the GUI Toolkit folder.
The kernel extension is shipped as a "zipped" file named "packages.zip". Unzipping it (using, for example, winzip or pkzip) extracts the following files:
- readme.txt - Provides summary documentation about the library.
- install.txt - The installation file, to be loaded to COLD-started controller.
- library.4th - Forth name headers and utilities; prepend to Forth programs.
- library.c - C callers for all functions in library; #include in C code.
- library.h - C prototypes for all functions; #include in extra C files.
Library.c and library.h are only needed if you are programming in C. Library.4th is only needed if you are programming in Forth. The uses of all of these files are explained below.
We recommend that you move the relevant files to the same directory that contains your application source code; the references to the library files in the demo assume the library files are in the same directory as the source code.
Using the Driver Code with C
Move the library.c and library.h files into the same directory as your other C source code files and use the following directives in your highest level source code file:
#include “library.h” #include “library.c”
The library.h contains the prototypes and constants of the GUI Toolkit while library.c contains the code to call the various GUI Toolkit methods. You should include library.c only once in your highest level source code file but include library.h in every additional source file that uses GUI Toolkit constants or functions.
Note that all of the functions in the kernel extension are of the _forth type. While they are fully callable from C, there are two important restrictions. First, _forth functions may not be called as part of a parameter list of another _forth function. Second, _forth functions may not be called from within an interrupt service routine unless the instructions found in the file named
\fabius\qedcode\forthirq.c
are followed.
qlink.bat
and qmlink.bat
in your /fabius/bin
directory on your installation before using the kernel extension. You can download a zip file of new versions from
http://www.mosaic-industries.com/Download/new_qlink.zip
The two new files should be placed in c:\Fabius\bin
. This upgrade only has to be done once for a given installation of the C compiler.
Using the image data and image header files
Before writing your application code, be sure to transfer the Image Data File, created with the Image Conversion Program, to the Handheld Controller. Then, be sure to include the Image Header File in your application as shown below:
Listing 8-3 The first few lines of the demo program.
#include <\mosaic\allqed.h> // Include all of the Mosaic utilities. #include “library.h” // Define prototypes and constants of the GUI Toolkit. #include “library.c” // Code used to call the GUI Toolkit functions. #include “image_header.h” // Include constants that define location of your images
Writing your application’s initialization routine
The initialization routine of your application needs to initialize the GUI Toolkit and setup a task to control the GUI Toolkit before any GUI Methods are called.
Initialize_GUI
must be called before any other GUI method!
To initialize the GUI Toolkit, call Initialize_GUI, passing it a heap start address and a heap end address as shown in the demo.
Listing 8-5 Initializing the GUI Toolkit
#define GUI_HEAP_START 0x0F3000L #define GUI_HEAP_END 0x0F6FFFL . . void main( void ) { Initialize_GUI ( GUI_HEAP_START, GUI_HEAP_END ); . . }
Initialize_GUI
performs several actions: it sets up a heap memory structure for the GUI Toolkit; it sets up and activates a task for the GUI Toolkit; it initializes and starts the timeslicer; and it configures several critical objects, called the GUI Toolkit’s pre-instantiated objects.
All GUI objects and their associated properties are stored in a heap accessed only by the GUI Toolkit. This GUI Heap can be located in any contiguous block of RAM (i.e. it may span consecutive pages of RAM) but it is typically placed on page 0x0F from 0x3000 to 0x6FFF as shown in the example above. The size of the heap that is needed by the GUI Toolkit depends on your application. As a benchmark, the demo program uses approximately 8k of heap space. Because all objects are stored in the GUI Heap, it is easy to add, modify, or resize objects without worrying about the specifics of their memory allocation.
The GUI Toolkit runs in a stand-alone task called the GUI Task. The GUI Task executes an endless loop that:
- checks to see if new objects need to be created or existing objects need to be modified;
- polls the keypad looking for events;
- checks to see if a user defined event procedure needs to be called (as part of the GUI Timer); and,
- calls
Pause
.
Servicing GUI Events
When an action key is pressed, the GUI Task sends a message indicating that the event procedure should be executed. Service_GUI_Events
listens for messages from the GUI Task and executes the appropriate event procedure when commanded. Service_GUI_Events
must be included in the infinite loop of a task that you create (separate from the GUI Toolkit’s Task) as shown in the following example. This task should also be in charge of creating, initializing and updating the objects for your application.
Listing 8-7 Servicing GUI Events
TASK taskbase; . . void GUI_Monitor ( void ) { Initialize_GUI ( GUI_HEAP_START, GUI_HEAP_END); . while(1) { . . Service_GUI_Events(); Pause(); } } void main( void ) { . BUILD_C_TASK(0, 0, &taskbase); // build task ACTIVATE( GUI_Monitor,&taskbase); // activate task StartTimeslicer(); // starts elapse time clock, enables interrupts Pause(); // start next task immediately }
The GUI Toolkit is a single resource, access to which must be controlled in a multitasking application. The simplest method is to use only one task for all interactions with the GUI toolkit, so that there are no concerns about concurrent access. This requires performing all updates to the GUI within the same loop that is calling Service_GUI_Events. However, if multiple tasks in your application need to use the GUI Toolkit, you must use the resource variable GUI_resource to assure that only one task accesses the GUI Toolkit at a time. In this case, you must call GET( GUI_resource )
before any GUI Toolkit operations, and RELEASE( GUI_resource )
afterward. It is a good idea to also call Pause()
after releasing GUI_resource to limit the amount of time other tasks wait for it to be available. For more information on using resource variables see the C language glossary entry for RESOURCE .
The GUI Task should have an opportunity to run approximately once every 50 milliseconds. Calling the GUI Task more frequently will not improve performance because the GUI Task polls the timeslicer to assure it is not called more than once every 50 milliseconds. Calling the GUI Task less frequently will not cause any errors but may result in sluggish performance. Because the GUI Toolkit polls the timeslicer, the timeslicer must be running or the GUI Toolkit will freeze. The GUI Task takes approximately one millisecond to execute if no events occur, no new object needs to be created, and no existing object needs to be modified. When an event fires, the time the GUI Task takes to execute is proportional to the number of items that are loaded onto the visible screen. For a screen with 15 objects, it will take approximately 5 milliseconds to pass the event to the responsible control. Additional time is required if the responsible control has an image that has to be redrawn.
The GUI Toolkit’s pre-instantiated objects
The GUI Toolkit has a set of special objects that are created and configured only when you initialize the GUI Toolkit. These special objects are called the pre-instantiated objects because they are instantiated or created before the GUI Toolkit starts its task. These objects include the GUI Toolkit itself, display, four predefined screens, four predefined keypads, battery, timer, pen, buzzer, and default font. You can not create additional instances of these objects because they are tied to a specific piece of hardware or unique function of the GUI Toolkit.
The GUI Toolkit is itself an object with properties that influence the operation of the GUI Task and all other objects. The GUI Toolkit Object is called the GUI_TOOLKIT
and has properties that determine how objects such as graphics and controls are loaded into screens, whether events are serviced, and the behavior of the GUI Task when an error occurs.
The Display Object is called the GUI_DISPLAY
, and is tied to the physical display. Properties of the GUI_DISPLAY
control the behavior of the display such as adjusting the contrast or controlling the backlight. The GUI_DISPLAY
contains four pre-instantiated screens called GUI_SCREEN0
to GUI_SCREEN3
. A property of GUI Screens is their VISIBLE
property. Only one of the GUI Screens may be made visible at a time. When it is made visible, the other GUI Screens are automatically made not visible and the display suddenly shows the visible screen’s objects. GUI Screens are the only objects that are shown on the physical display. To show an object like a graphic on the display, the object must be loaded into the visible GUI Screen. The visible screen after Initialize_GUI
is called is GUI_SCREEN0
.
Each GUI Screen has an associated keypad named GUI_KEYPAD0
to GUI_KEYPAD3
. A keypad is a collection of keys; the possible types of keys are action keys, data entry keys, and shift keys. Action keys generate events when a user presses the key (press event), holds down the key (hold event), and releases the key (release event). Data entry keys are used to enter numbers, letters, or symbols into textboxes. You can overload data entry keys so that the same key can be used to enter multiple numbers, letters, or symbols. For example, in the demo, the number 9 data entry key is used to enter the number "9" as well as the letters "W", "X", "Y", "Z", "w", "x", "y", or "z". Shift keys are used to change the shift state to enable the overloading of data entry keys.
The Battery Object is called the GUI_BATTERY
, and it is tied to the physical rechargeable batteries. Properties of the GUI_BATTERY
include the battery voltage, battery current usage, battery state, and whether the charger is on or off.
The Timer Object is called the GUI_TIMER
, and it is used to repetitively call user defined event procedures. The GUI_TIMER
is useful for calling routines that need to be called every so often to perform tasks like reading the battery.
The Pen Object is called the GUI_PEN
. This useful tool generates geometric shapes and line drawings on a screen. The GUI_PEN
has properties that control how the points and lines are drawn so you don’t have to pass all the optional parameters to the drawing method each time it is called.
The Buzzer Object is called the GUI_BUZZER
and it is associated with the piezo electric beeper. Properties of the GUI_BUZZER
control the length of time of a beep and turn the buzzer on and off.
The Default Font Object is called the GUI_FONT
and is associated with a custom proportional font that is10-pixels tall. The default font is used to render string data from a textbox onto a screen where it can be shown.
Creating new objects
The GUI Toolkit also has other objects, like graphics and textboxes, that you can create using the New_Object
method. New_Object requires one input parameter that specifies the type of object you want to create; GRAPHIC
, FONT
, TEXTBOX
, ACTION_KEY
, DATA_ENTRY_KEY
, SHIFT_KEY
, SCREEN
, and PLOT
are all valid object types. New_Object
returns an integer that you store into a variable. This variable (which we call an object reference because it contains a reference to the object) is used to set properties of the object and perform actions on the object like loading the object onto a screen.
The following code from the demo creates a new graphic object and stores its object reference into a variable named graphicWelcome
. Later, we’ll set the image of the graphic and then load it into a screen.
Listing 8 9 Creating a New Graphic.
int graphicWelcome; . . . void Initialize_Screen0 ( void ) { graphicWelcome = New_Object ( GRAPHIC ); . . . }
Objects can be created but not destroyed. Because objects are stored in the heap, you can only create a finite number of them. Different objects use different amounts of heap space. For example, graphics and fonts only use a few bytes of heap space while plots use hundreds of bytes depending on the size of its buffer.
Setting object properties
All objects have their properties set to default values when they are created so that you need to set as few properties as possible to have a fully functional object. However, certain objects like graphics require you to set its image before the graphic can be loaded onto a screen.
In the demo, Initialize_Screen0
creates a graphic and then sets its image property using a constant defined in the Image Header File.
Listing 8-11 Setting the Property of a Graphic.
int graphicWelcome; . . . void Initialize_Screen0 ( void ) { graphicWelcome = New_Object ( GRAPHIC ); Set_Property ( graphicWelcome, IMAGE, WELCOME_BMP ); . . . }
Creating and initializing controls
Now that you’re familiar with creating graphic objects, we’ll show you how to create an action key. To create an action key:
- Use the
New_Object
method to create an action key and store the object reference to the action key into a variable. By default, the action key will beep when it receives a press event. You can change this behavior by setting theKEYPAD_BEEP
property of the keypad containing the action key (GUI_KEYPAD0
in this case) toGUI_FALSE
. - Initialize any required action key properties such as
BLOCK_ON_HOLD
. The next section discusses when to use blocking in your application. - Define the
PRESS_EVENT_PROCEDURE
for the action key. Writing event procedures is covered after the next section on blocking. - Associate the event procedure with the action key using the
Set_Property
method. - Insert the action key into a keypad using the
Insert_Key
method. Inserting a key into a keypad associates the key with a screen. When the associated screen becomes visible, the key becomes active (i.e. the key will responded to presses). The key positions are shown in the following table:
Table 8-1 The key positions for a keypad.
0 | 4 | 8 | 12 |
1 | 5 | 9 | 13 |
2 | 6 | 10 | 14 |
3 | 7 | 11 | 15 |
20 | 24 | 28 | 32 |
21 | 25 | 29 | 33 |
22 | 26 | 30 | 34 |
23 | 27 | 31 | On / Off |
The on / off key is tied to power circuitry so it can not be moved or assigned to different function.
The following code shows the Initialize_Screen0
function from the demo that illustrates how to create an action key that, when pressed, will beep, and execute an event procedure.
Listing 8 13 Creating and Initializing a Control.
int actionkeyFunction1; . . . void Initialize_Screen0 ( void ) { . . . actionkeyFunction1 = New_Object( ACTION_KEY ); Set_Property(actionkeyFunction1, BLOCK_ON_PRESS, GUI_TRUE); Set_Property(actionkeyFunction1, PRESS_EVENT_PROCEDURE, (long) Function1_event_procedure_ptr); // Position the function 1 key to be in the upper left corner of the keypad. Insert_Key ( GUI_KEYPAD0, actionkeyFunction1, 0 ); . . . }
Defining and initializing other controls like data entry keys and shift keys are handled in the same way. Examples of how to define and initialize data entry keys and shift keys are shown in the demo.
When to block events
Turning off the service events property of the GUI Toolkit (also called blocking) disables the keypad and keys from changing GUI Toolkit properties. Blocking is required when the state of the GUI Toolkit must remain unchanged for a short time period. Blocking is usually associated with action keys with event procedures that need to read, write, or change properties or calls GUI Toolkit methods. As shown in the previous listing, the block on press property of the action key is set because its event procedure (as shown in the next listing) changes the visible property of a screen. Thus once the action key is pressed, no other keys will be able to change GUI Toolkit properties (so another key that is simultaneously pressed can’t make another screen visible causing a conflict). If you configure an action key to block, it is your responsibility to re-enable the servicing of events in the event procedure. Typically, the re-enabling of events is the last thing you do in an event procedure before exiting.
Writing event procedures
Event procedures are functions that you write to animate your controls. Event procedures cannot take any parameters or return any values, but they can set variables and call other GUI methods like Clear
and Refresh
. In the demo, the event procedure for the Function 1 Action Key changes the visible screen. The following listing shows the code for the action key’s event procedure.
Listing 8 15 Writing the Event Procedure.
void Function1_Event_Procedure ( void ) { // Set GUI Screen 3 to be the visible screen. Set_Property ( GUI_SCREEN3, VISIBLE, GUI_TRUE ) ; // The action key associated with this event procedure must be configured to // block on press since the event procedure must change the visible property // of a screen. Re-enable the servicing of events here at the end of the // event procedure. Set_Property ( GUI_TOOLKIT, SERVICE_EVENTS, GUI_TRUE ); } // We need to store the address of the event procedure into a function pointer which // will be used to associate the event procedure with the action key. #include “begin_event_procedure_pointers.h” . . . xaddr (*function1_event_procedure_ptr)(void) = Function1_Event_Procedure; . . . #include “end_event_procedure_pointers.h”
Loading objects into screens
The final step in creating a GUI application is loading the objects onto the screen. To load an object onto a screen, use the Load
method. The following code initializes a graphic for GUI_SCREEN0
and then loads it into the screen.
Listing 8-17 Loading a Control into a Screen.
void Initialize_Screen0 ( void ) { graphicWelcome = New_Object ( GRAPHIC ); Set_Property ( graphicWelcome, IMAGE, WELCOME_BMP ); Load ( GUI_SCREEN0, graphicWelcome, 0, 0 ); . . . }
We've now shown you how to design and build your user interface, initialize the GUI Toolkit, create and initialize objects, write event procedures, and load objects onto screens. This final section covers how to handle errors that may occur during your application.
Error handling
The GUI Toolkit has extensive error handling and reporting abilities. When an error occurs, an error code is logged and an attempt is made to recover from the error. For example, if you try to load a graphic that contains an image which is 24 pixels wide to the coordinates (112,0), 8 pixels of the image will hang off the edge of the screen (since the width of a screen is 128 pixels). This will generate an X_OUT_OF_RANGE
error, and the graphic will instead be loaded to the right-most position on the screen at (104,0). You can read the error code by using the Read_Error
method of the GUI Toolkit object. Because only the last error is recorded, you must call Clear_Error after you read the error to prevent servicing the same error more than once. The following code shows how to create a custom error handling and reporting routine:
Listing 8-19 Handling Errors.
void Print_Error ( void ) { switch (Read_Error()) { case HEAP_FULL: printf(“Can’t create any more new objects.\n”); break; case X_OUT_OF_RANGE: printf(“X coordinate is out of range.\n”); break; // You would put other error codes and error messages here. } Clear_Error(); // Be sure to clear the error after we read it; // we don’t want to respond to the same error more than once. }
Multiple errors can occur for each GUI Toolkit method but only one can occur at a time. It is up to you to decide if and when you should check for errors.
A useful debugging tool that comes with the GUI Toolkit is the property ABORT_ON_ERROR
. If true, an error causes the controller to disable interrupts, stop multitasking, and send a descriptive error message to the primary serial port, Serial 1. The error message identifies the calling method and parameters that triggered the error. ABORT_ON_ERROR
helps you to quickly identify the source of the error; this is especially useful when developing a complex application. This property should be set to GUI_FALSE
for the production version of your application.
Expanding the GUI Toolkit’s objects and methods
We understand that each GUI application you write has unique requirements. Although it is possible for you to implement many things like custom plotting routines or drawing geometrical shapes by writing high level code, there maybe a significant performance advantage in our providing pre-packaged objects to you that perform the desired function. Please contact Mosaic Industries about adding additional objects, properties, and methods to the GUI Toolkit. We are planning to add many features to the toolkit to enhance its capabilities; the features you are looking for may already exist.
GUI objects in detail
There are many kinds of GUI objects. Some are tied tightly to particular hardware (the GUI_BATTERY
and GUI_DISPLAY
), some collect other objects together (GUI Screens), some respond to events (controls), some are tools (the GUI_PEN
), and some simply contain data for display (graphics and textboxes). Several of the GUI objects are created and configured when Initialize_GUI
is called. These objects include the GUI_DISPLAY
, GUI_BATTERY
, GUI_BUZZER
, GUI_FONT
, GUI Screens, GUI Keypads, and GUI_PEN
. You can not create more of these object types. For other object such as graphics, textboxes, keys, screens, and plots, you can create as many as you like. All of the GUI Toolkit objects, their 32-bit properties, associated methods, and possible errors are described below. More detailed descriptions of each method, property, and value is available in the GUI Toolkit Glossary.
GUI_TOOLKIT
The GUI Toolkit is itself an object that contains properties that affect all other objects. The GUI Toolkit Object is called GUI_TOOLKIT
. These are its properties, methods, and possible errors:
Properties
Table 8-2 Properties of the GUI_TOOLKIT
.
Property | Values | Meaning |
---|---|---|
ABORT_ON_ERROR | GUI_TRUE , GUI_FALSE | If true, disables interrupts, stops multitasking, and sends a detailed message to serial 1 when an error occurs. |
AVAILABLE_HEAP_SPACE | Unsigned Long | Read only. Contains the number of bytes remaining in the GUI Heap. |
CURRENT_SCREEN | GUI_SCREEN0 to GUI_SCREEN3 | Contains the current visible screen. |
SERVICE_EVENTS | GUI_TRUE , GUI_FALSE | If false, events are not serviced. All events generated by pressed keys are ignored. |
STANDARD_FONT | GUI_FONT or custom font object | Contains the reference to the font object used to render string data in textboxes. At initialization, STANDARD_FONT is set to GUI_FONT which is a proportional font with a height of 10 pixels. You can set this property to your own custom font, if desired. |
HORIZONTAL_SNAP_TO_GRID | GUI_TRUE | Read only. Causes all objects loaded onto a screen to be located on the nearest 8-pixel horizontal boundary. This property is always true for speed. |
VERICAL_SNAP_TO_GRID | GUI_TRUE , GUI_FALSE | If true, causes all objects loaded on to a screen to be located on the nearest 8-pixel vertical boundary. |
Methods
Table 8-3 Methods of the GUI_TOOLKIT
.
Method | Parameters | Return Value | Action |
---|---|---|---|
Initialize_GUI | Start of the GUI Heap, End of the GUI Heap | None | Initializes the GUI_TOOLKIT , GUI_DISPLAY , GUI_BATTERY , GUI_PEN , GUI_FONT , GUI_BUZZER , GUI Screens, and GUI Keypads. Sets up and activates a task in common memory. Initializes and starts the timeslicer. Calling any other GUI Toolkit method before calling Initialize_GUI will crash the controller. |
Service_GUI_Events | None | None | Executes the event procedures of controls. This method must be included in a task as part of your infinite loop to service events generated from the GUI Task. |
Read_Error | None | Error code | Reads the last reported error. |
Clear_Error | None | None | Clears the last reported error. |
New_Object | Object Type | Object Reference | Create a new object and return an object reference which is stored in an object variable for later use. |
Set_Property | Object Reference, Property, Value | None | Set an object’s property as a 32-bit value. |
Get_Property | Object Reference, Property | Value | Get an object’s property as a 32-bit value. |
Errors
Table 8-4 Errors of the GUI_TOOLKIT
.
Error | Associated Method | Meaning |
---|---|---|
HEAP_FULL | Initialize_GUI , New_Object | Heap is full. There is no room to create the GUI Toolkit, create new objects, or resize existing objects. |
GUI_EXISTS | Initialize_GUI | The GUI Task has already been activated. Do not call Initialize_GUI more than once! |
DISPLAY_INITIALIZATION_FAILURE | Initialize_GUI | There was a problem initializing the display. This error occurs if there was a hardware communications problem talking to the display controller. If the problem persists, contact Mosaic Industries. |
INVALID_OBJECT | New_Object , Set_Property , Get_Property | The object reference is not valid. |
INVALID_PROPERTY | Get_Property , Set_Property | The property is not valid. |
INVALID_IMAGE | Set_Property | There is no valid image at the specified address. This error is returned after attempting to set the IMAGE property of a graphic or a font. |
INVALID_FONT | Set_Property | The object reference is not a font when setting the STANDARD_FONT property of the GUI Toolkit or setting the TEXTBOX_FONT property of a textbox. |
BUFFER_SIZE_OUT_OF_RANGE | Set_Property | The size of the plot object buffer must be greater than or equal to the width of the plot in pixels |
WIDTH_OUT_OF_RANGE | Set_Property | The width will create a plot or textbox that is wider than the width of the screen. |
HEIGHT_OUT_OF_RANGE | Set_Property | The height will create a plot or textbox that is taller than the height of the screen. |
GUI_DISPLAY
The GUI_DISPLAY
corresponds to the physical display. Properties of the GUI_DISPLAY
and all other GUI objects are accessed or modified using the GUI_TOOLKIT
methods Set_Property
and Get_Property
.
Properties
Table 8-5 Properties of the GUI_DISPLAY
.
Property | Values | Meaning |
---|---|---|
WIDTH_IN_PIXELS | 128 pixels | Read only. Contains the width of the display in pixels. |
HEIGHT_IN_PIXELS | 128 pixels | Read only. Contains the height of the display in pixels. |
CONTRAST | 0 to 31 | Changes the contrast voltage of the monochrome display. Saturates at 0 or 31. Initialized to 16. |
BACKLIGHT_ON | GUI_TRUE , GUI_FALSE | If true, turns the backlight on for monochrome displays. Initialized to GUI_TRUE . |
BRIGHT_BACKLIGHT | GUI_TRUE , GUI_FALSE | If true and the backlight is on, supplies more current to the backlight to increase the brightness. Initialized to GUI_FALSE . |
GUI screens
A screen is a collection of functionally related objects, including textboxes, plots, and graphics that are presented together on the display. Screens are fixed in size to 128 pixels wide by 128 pixels tall. For speed, objects loaded into screens are aligned on 8 pixel horizontal grid. A property of the GUI Toolkit, called VERTICAL_SNAP_TO_GRID
, allows you to align objects vertically as well. The coordinate system for specifying the location of objects and drawing to a screen is in pixels and the origin is the upper left corner of a screen. The x coordinate represents a displacement from the origin in the horizontal direction and the y coordinate represents a displacement from the origin in the vertical direction. An increase in x moves the coordinate to the right and an increase in y moves the coordinate down.
Screens whose object images are stored in the display’s memory are called GUI Screens. GUI screens have a visible property that when set, causes the selected screen to be shown on the display and makes all other GUI Screens invisible. Only one GUI Screen can be made visible at a time. GUI Screens are the only objects that are shown on the physical display. To show an object like a graphic on the display, the object must first be loaded into a GUI Screen. The visible screen after Initialize_GUI
is called is GUI_SCREEN0
.
You can also create additional screens that reside in the heap. Heap screens, unlike GUI Screens, can not be made visible. Heap screens allow you to build many different screens when you are initializing your application and then quickly switch them into GUI Screens at run time using the Copy_Screen
method. Heap screens are described in detail in a later section.
Properties
Table 8-6 Properties of GUI Screens.
Property | Values | Meaning |
---|---|---|
WIDTH_IN_PIXELS | 128 pixels | Read only. Contains the width of the screen in pixels. |
HEIGHT_IN_PIXELS | 128 pixels | Read only. Contains the height of the screen in pixels. |
VISIBLE | GUI_TRUE , GUI_FALSE | If true, makes the screen visible and sets the last visible screen’s property to false. |
NUM_OBJECTS | Unsigned Long | Read only. Contains the number of objects contained in the screen. |
IN_DISPLAY | GUI_TRUE , GUI_FALSE | Read only. TRUE if the screen is in the display memory, FALSE otherwise. All GUI screens have this property set to GUI_TRUE . |
SCREEN_ADDRESS | Extended Address | Read only. Contains the address of the rendered image of the screen and its objects in the display. |
Methods
Table 8-7 Methods of GUI Screens.
Method | Parameters | Return Value | Meaning |
---|---|---|---|
Load | Screen Reference, Object Reference, X Coordinate, Y Coordinate | None | Load an object into a screen at the specified x and y coordinates. |
Un_Load | Screen Reference, Object Reference, X Coordinate, Y Coordinate | None | Unload an object from a screen at the specified x and y coordinates. |
Copy_Screen | Source Screen Reference, Destination Screen Reference | None | Copies the contents of the source screen into the destination screen. The contents of the destination screen are over written. |
Clear | Screen Reference | None | Unloads all objects from the screen and erases the screen. |
Refresh | Screen Reference | None | Re-renders graphics, textboxes and plots in the screen that have their refresh flags set to true. Sets the refresh flags to false once the objects have been refreshed. |
Redraw | Screen Reference | None | Re-draws all objects contained in the screen. |
Errors
Table 8-8 Errors of GUI Screens.
Error | Associated Method | Meaning |
---|---|---|
HEAP_FULL | Load | Heap is full. There is no room to load an object into a GUI Screen. |
INVALID_OBJECT | Load , Un_Load | The object reference cannot be loaded into a GUI Screen. |
INVALID_SCREEN | Load , Un_Load , Clear , Redraw , Refresh, Copy_Screen | The object reference is not a GUI Screen. |
X_OUT_OF_RANGE | Load , Un_Load | The x coordinate plus the width of the object is greater than the width of the GUI Screen. |
Y_OUT_OF_RANGE | Load , Un_Load | The y coordinate plus the height of the object is greater than the height of the GUI Screen. |
GUI keypads
Each GUI Screen has a corresponding keypad that holds the keys that animate the screen. GUI_SCREEN0
is associated with GUI_KEYPAD0
, GUI_SCREEN1
is associated with GUI_KEYPAD1
, GUI_SCREEN2
is associated with GUI_KEYPAD2
, and GUI_SCREEN3
is associated with GUI_KEYPAD3
. GUI Keypads can contain three different types of keys - action keys, data entry keys, and shift keys. Each type of key is covered in a later section. Only the keypad of the visible screen is active (i.e. responds to key presses).
Properties
Table 8-9 Properties of the GUI Keypads
.
Property | Values | Meaning |
---|---|---|
DATA_ENTRY_EVENT_PROCEDURE | Extended Address | Execute this user defined event procedure when a non-overloaded data entry key is pressed or an overloaded data entry key is pressed and a timeout has been reached. If zero, no event procedure is executed. |
INT_DATA_ENTRY_EVENT_PROCEDURE | Extended Address | Execute this user defined event procedure when an overloaded data entry key is pressed and a timeout has not been reached. If zero, no event procedure is executed. |
SHIFT_EVENT_PROCEDURE | Extended Address | Execute this user defined event procedure when any shift key is pressed. If zero, no event procedure is executed. |
DATA_ENTRY_TEXTBOX | Textbox object | The textbox that contains the keycodes of pressed data entry keys. |
SHIFT_STATE_TEXTBOX | Textbox Object | The textbox that contains a string corresponding to the shift state. |
KEYPAD_BEEP | GUI_TRUE, GUI_FALSE | If true, sounds the buzzer when a key is pressed. |
KEYPAD_BEEP_DURATION | Unsigned Integer | Controls the length of time (in 5 ms intervals) the piezo electric buzzer is on when a key is pressed. The default value is 1, corresponding to 5 milliseconds. |
KEY_CODE | 1 – 255 | Read only. Contains the key code of the last pressed data entry key. See the following section on Data Entry Keys for more information on Key Codes. |
PRIOR_KEY_CODE | 1 – 255 | Read only. Contains the key code of the data entry key that was pressed before the last data entry key. |
KEY_EVENT | PRESS_EVENT, HOLD_EVENT, RELEASE_EVENT, NO_EVENT | Read only. Contains the last event. |
PRIOR_KEY_EVENT | PRESS_EVENT, HOLD_EVENT, RELEASE_EVENT, NO_EVENT | Read only. Contains the event that occurred before the last event. |
KEY_POSITION | 0 – 15 or 20 – 34 | Read only. Contains the key position of the last key. See Table 8 1 for the key positions on the keypad. |
PRIOR_KEY_POS | 0 – 15 or 20 – 34 | Read only. Contains the key position of the key pressed before the last key. |
KEY_TYPE | ACTION_KEY, DATA_ENTRY_KEY, SHIFT_KEY, NO_KEY | Read only. Contains the type of key that was last pressed. |
PRIOR_KEY_TYPE | ACTION_KEY, DATA_ENTRY_KEY, SHIFT_KEY, NO_KEY | Read only. Contains the type of key that was pressed before the last key. |
PRESS_NUMBER | Unsigned Integer | Read only. Contains the number of times the last data entry key was pressed before a timeout expired. |
SHIFT_STATE | SHIFT_UP, SHIFT_NEUTRAL, SHIFT_DOWN | Contains the current shift state. |
Methods
Table 8-10 Methods of the GUI Keypads
.
Method | Inputs | Outputs | Meaning |
---|---|---|---|
Insert_Key | Keypad Reference, Key Reference, and Key Position | None | Inserts a key object into the specified keypad object at the specified position. Valid positions are shown in Table 8 1. |
Errors
Table 8-11 Errors of the GUI Keypads
.
Error | Associated Method | Meaning |
---|---|---|
INVALID_KEY | Insert_Key | The specified object reference is not a valid key. |
INVALID_KEYPAD | Insert_Key | The specified object reference is not a valid keypad. |
KEY_POS_OUT_OF_RANGE | Insert_Key | The specified key position is not between 0 and 15 or 20 and 34. |
GUI_PEN
The GUI_PEN
is a tool used to draw points, lines, and shapes on a screen. You use its Draw
method to draw to the screen, and its properties control how points or lines are rendered so you don’t have to pass all the optional parameters to the Draw
method.
Properties
Table 8-12 Properties of the GUI_PEN
.
Property | Values | Meaning |
---|---|---|
PEN_TYPE | SET , UNSET | Determines whether the pen draws or erases from the screen. |
SHAPE | POINT , LINE | Determines the shape that is drawn or erased from the screen. |
TARGET_SCREEN | Screen Reference | Contains the screen the pen is rendering to. |
LAST_COORDS | Unsigned Long | Contains the last coordinates passed to the Draw method. The y coordinate is located in the 16 most significant bits and the x coordinate is located in the 16 least significant bits. |
Methods
Table 8-13 Methods of the GUI_PEN
.
Method | Inputs | Outputs | Meaning |
---|---|---|---|
Draw | X Coordinate, Y Coordinate | None | Draw or erase a point or a line onto a screen. If drawing a line, draws from the last coordinate to the coordinates passed to Draw . To draw a line from an arbitrary point rather than the last coordinate, place the new coordinate into LAST_COORDS . |
Errors
Table 8-14 Errors of the GUI_PEN
.
Error | Associated Method | Meaning |
---|---|---|
X_OUT_OF_RANGE | Draw | The x coordinate is outside of the width of the screen. |
Y_OUT_OF_RANGE | Draw | The y coordinate is outside of the height of the screen. |
GUI_BUZZER
The GUI_BUZZER
corresponds to the piezo electric beeper and controls the length of the beep when the Buzz
method is called. The GUI_BUZZER
is useful for alarms and system notifications.
Properties
Table 8-15 Properties of the GUI_BUZZER
.
Property | Values | Meaning |
---|---|---|
BEEP_TIME | Unsigned Long | Controls the length of time the piezo electric buzzer is on during a call to the Buzz method. Only the 16 least significant bits are used. The units of BEEP_TIME are in TCNTs or 2 microsecond intervals. The default value is 1000, corresponding to 2 milliseconds. |
BEEPER_ON | GUI_TRUE , GUI_FALSE | If true, turns the piezo electric buzzer on. |
Methods
Table 8-16 Methods of the GUI_BUZZER
.
Method | Inputs | Outputs | Meaning |
---|---|---|---|
Buzz | None | None | Turns the piezo electric buzzer on for BEEP_TIME . |
GUI_BATTERY
The GUI_BATTERY
contains properties corresponding to the 6 AA rechargeable Nickle Metal Hydride batteries. The GUI_BATTERY
is used to monitor the state of the batteries. For more information about the lifetime, replacement, and charging of the batteries, see the chapter on Powering Your Handheld.
If reading the battery voltage, current draw, battery state, and charger state, be sure to install jumpers J3 and J4 on the Motherboard to connect the A/D inputs to the battery. Before you read any properties of the battery, be sure to call Read_Battery
to update the battery properties. If all 8 Port E lines are required by your application, don’t install the jumpers on the Motherboard and don’t call Read_Battery
. To monitor the battery and use the remaining Port E lines as digital or analog inputs, you must GET
the 8 bit A/D resource before reading the other Port E lines and then RELEASE
the resource when finished.
Properties
Table 8-17 Properties of the GUI_BATTERY
.
Property | Values | Meaning |
---|---|---|
BATTERY_STATE | FULL_BATTERY, MEDIUM_BATTERY, LOW_BATTERY, NO_BATTERY | Read only. Contains the current state of the battery. |
BATTERY_VOLTAGE | Unsigned Long | Read only. In the 16 least significant bits, contains the current battery voltage in millivolts. |
BATTERY_CURRENT | Unsigned Long | Read only. In the 16 least significant bits, contains the current draw of the Handheld in milliamps. |
CHARGER_STATE | GUI_TRUE , GUI_FALSE | Read only. If true, the battery charger is on. |
Methods
Table 8-18 Methods of the GUI_BATTERY
.
Method | Inputs | Outputs | Meaning |
---|---|---|---|
Initialize_Battery | None | None | Turns on the 8-bit A/D circuitry of the processor which is used to read the battery voltage, current usage, battery state, and charger state. |
Read_Battery | None | None | Reads the battery voltage, current usage, battery state, and charger state and stores it into the appropriate properties. |
GUI_TIMER
The GUI_TIMER
allows you to repetitively call non-critical event procedures during a specified interval. The GUI_TIMER
is useful for calling routines every so often – like reading the battery once a minute and showing the voltage on the display. In case the repetitively called event procedure reads, writes, or changes any GUI Toolkit property or calls a GUI Toolkit method, before the event procedure is called the GUI Toolkit by default disables the servicing of events. Consequently, in the last line of the event procedure you must re-enable the servicing of events. See the demo program for an example. The GUI_TIMER
should only be used for non-critical event scheduling because events may be delayed by interrupt service routines and other tasks. For critical event timing, you may still need to use an interrupt service routine.
Methods
Table 8-19 Methods of the GUI_TIMER
.
Method | Inputs | Outputs | Meaning |
---|---|---|---|
Schedule_Event | Extended Address, Interval, Start Time, End Time | None | Schedules an event procedure to be repetitively called. The interval, start, and stop time are specified in 5 ms increments. If 0 is specified for the Start Time, the event procedure is called immediately. If 0 is specified for the End Time, the event procedure is repetitively called forever or until the event procedure is removed by Remove_Event . No error checking is performed. |
Remove_Event | Extended Address | None | Removes an event procedure from being called by the GUI_TIMER . No error checking is performed. |
Graphic object
A graphic object contains a single image as a property. Images are typically created on a PC but need to be converted and transferred to the Handheld Controller before they can be loaded into a graphic. Images are converted using Mosaic’s Image Conversion Program. The Image Conversion Program creates two files, an Image Data File and an Image Header File. The Image Data File contains the converted image data, and the Image Header File associates the location of the image data on the Handheld Controller with a constant named after the file name of the image. Before the GUI Toolkit is initialized and graphics are created, the Image Data File must be transferred to the Controller using Mosaic’s Terminal Program. After the Image Data File is transferred and the GUI Toolkit is initialized, a new graphic is created using the New_Object
method and its image set using the Set_Property
method. The width and height of the graphic object are automatically set when the IMAGE
property of the graphic is set to a valid image. Error checking is performed to assure the image is valid.
For the optimal performance of the GUI Toolkit, the width of an image must be a multiple of 8 pixels, and graphics must be loaded onto an 8 pixel horizontal grid in a screen. Finer horizontal pixel placement and image widths would require bit shifting of each byte of the image every time it is drawn, significantly slowing performance of the GUI Toolkit. To enforce the alignment there are two properties of the GUI Toolkit that globally affect the placement of objects, HORIZONTAL_SNAP_TO_GRID
and VERTICAL_SNAP_TO_GRID
. HORIZONTAL_SNAP_TO_GRID
is read-only and is always true where as VERTICAL_SANP_TO_GRID
may be set to either true or false. Images whose width does not fall on 8 pixel boundaries will not be converted with the Image Conversion Program. The images must be cropped or stretched appropriately using an image-editing program before the Image Conversion Program is used.
Properties
Table 8-20 Properties of Graphic Objects.
Property | Values | Meaning |
---|---|---|
WIDTH_IN_PIXELS | 8 to 128 pixels | Read only. Contains the width of the image in pixels. |
HEIGHT_IN_PIXELS | 1 to 128 pixels. | Read only. Contains the height of the image in pixels. |
IMAGE | Extended Address | Contains a pointer to the image contained in the graphic. |
Image conversion program
Mosaic’s Image Conversion Program allows you to easily transfer images created on a PC to your Handheld Controller for use with the GUI Toolkit. The image conversion program takes all of the images in a selected directory and concatenates them into a single text file called an Image Data File. The Image Data File is stored in the selected directory and is sent to the Controller using Mosaic’s Terminal Program, the terminal program provided by Mosaic Industries. The Image Data File, by default, puts the converted image data into RAM on page 0x01 and then transfers the data into Flash at page 0x10. For more information about the memory map of the Handheld Controller, see Chapter 4: Making Effective Use of Memory.
Another file, called an Image Header File, is created to associate the names of the images (which is just the filename of the image) with their location in memory on the Controller. The Image Header File contains constants named after the file names of the images and must be included in your program to tell the GUI Toolkit where the images are stored. Supported image formats are monochrome bitmap (*.bmp) and PCX (*.pcx) files. The following sections describe the user interface and the error messages returned by the Image Conversion Program.
Image conversion program interface
The user interface for Mosaic’s Image Conversion Program has a main screen, an advanced options screen, a font selection screen, and a help screen. On the main screen there are controls that select the directory that contain your image files, specify the type of image file (PCX or BMP) to convert, and select the type of controller you are using. A button labeled "Convert Files Now" starts the conversion process. In the advanced options screen there are controls that select your programming language, desired target memory location for the image data, and filenames for the Image Data and Image Header files. All of the advanced options are set to default values that will work for most applications. In the font selection screen there are controls that allow you to preview and select fonts to use with the GUI Toolkit. Once a font is selected, a bitmap image is made of all of the characters of the font and a data file is created that contains the width of each character. The bitmap file and the data file are then stored into the currently selected directory. The Image Conversion program will then add the font bitmap file and the character width data file along with your images into the Image Data File and the Image Header File. Be sure to select your working directory before selecting a font and be sure to select the BMP image format to convert your selected fonts. The help screen provides additional information for each of the options and controls.
Image conversion program errors
Mosaic’s Image Conversion Program detects and reports the following error conditions:
- "Error changing to the specified directory". The directory does not exist, it was moved, or deleted. A new directory has to be specified.
- "Error opening an image file, Image Data File, or Image Header File".
- "Not a valid bitmap file (no valid file identifier) or pcx file (no valid manufacturer or encoding)".
- "Bit depth of the image file does not match the specified value".
- "Image width does not fall on an 8-pixel boundary". All images must have a width that is a multiple of eight pixels. This is required to quickly draw the images onto screens. Please crop or stretch the image using any photo or image editing program such as Photoshop or Paint.
Font object
A font object renders string data into images that can be displayed on a screen in a textbox. A font object is like a graphic object in that it contains a single bitmap image of all 255 characters joined together along with a data file that contains the widths of each character. Fonts are created on the PC using the Image Conversion Program (see the previous section for more information). The GUI Toolkit provides a custom proportional font that is 10 pixels tall called the GUI_FONT
. The demo program uses a Comic Sans font to demonstrate how to create and use font objects. While you can’t create another instance of the GUI_FONT
, you can create your own custom fonts as described in the previous section.
Properties
Table 8-21 Properties of the Font Object.
Property | Values | Meaning |
---|---|---|
HEIGHT_IN_PIXELS | 10 – 128 pixels. | Read only. Contains the height of a single character in pixels. |
IMAGE | Extended Address | Contains a pointer to the image of the characters contained in the font. |
IMAGE_WIDTH_DATA | Extended Address | Contains a pointer to the array that contains the width in pixels of each character contained in the font. |
Textbox object
Textboxes are used in conjunction with fonts to render string data on a screen so it can be shown on the display. Textboxes are useful for displaying information that constantly changes, like the status of a process or the state of an instrument.
When textboxes are created, the font referenced by the STANDARD_FONT
property of the GUI Toolkit, is stored into the TEXTBOX_FONT
property of the textbox. If you did not store a custom font into the STANDARD_FONT
property of the GUI Toolkit, the GUI_FONT
is stored into the TEXTBOX_FONT
property of the textbox. The GUI_FONT
is a 10 pixel tall, proportional font; each character has a different width depending on the glyph or symbol of the character. If you want to change the font of a textbox, you must change it before you set the size of the textbox. Once you have set the size of a textbox, the font can not be changed.
The size of a textbox is uninitialized when it is instantiated. The size of the textbox must be set (using the Set_Property
method along with the HEIGHT_IN_PIXELS
and WIDTH_IN_PIXELS
properties) before a character or string is written into the textbox. Once the size of a textbox is set, it cannot be changed. When the size of a textbox is initialized, a block of memory in the heap is allocated for the textbox to render its string into. The string in a textbox must be rendered before it can be shown on the display. The RENDER
property controls whether or not the string in a textbox is rendered. The RENDER
property is set to GUI_TRUE
when a textbox is instantiated. Turning this property off is useful when a string in a textbox needs to be changed or modified frequently but does not need to be shown on the display.
Properties
Table 8-22 Properties of the Textbox Object.
Property | Values | Meaning |
---|---|---|
WIDTH_IN_PIXELS | 8 to 128 pixels | Write once. Contains the width of the textbox in pixels. |
HEIGHT_IN_PIXELS | 10 to 128 pixels | Write once. Contains the height of the textbox in pixels. |
TEXTBOX_ROWS | Unsigned Long | Read only. The 16 least significant bits contain the number of rows of the textbox. Equals to the textbox height divided by the font height. |
STRING_LINES | Unsigned Long | Read only. The 16 least significant bits contain the number of lines the string in the textbox occupies when rendered. Based on the number of characters in the string and the textbox width. |
FIRST_VISIBLE_LINE | Unsigned Long | The 16 least significant bits contain the line number of the string that is written to the first row of the textbox. Typically used for scrolling long strings in textboxes. See the demo for an example. |
STRING_LENGTH | Unsigned Long | Read only. The 16 least significant bits contain the length of the string in the textbox. |
TEXTBOX_FONT | Font reference | Contains a reference to the font object used to render the string in the textbox. This property can only be set before the size of the textbox is set. |
RENDER | GUI_TRUE, GUI_FALSE | If true, immediately renders changes to the textbox string. |
INVERT | GUI_TRUE, GUI_FALSE | If true, inverts the background and rendered string. If using this property, be sure to set this property to the desired value before writing to the textbox. |
BORDER | GUI_TRUE , GUI_FALSE | If true, draws a one-pixel border around the textbox. |
Methods
Table 8-23 Methods of the Textbox Object.
Method | Inputs | Outputs | Meaning |
---|---|---|---|
Add_Character | Textbox Reference, Character | None | Adds a character to the end of the string in a textbox. |
Delete_Character | Textbox Reference | None | Deletes a character from the end of the sting in a textbox. |
STRING_TO_TEXTBOX | Textbox Reference, String | None | Writes a string up to 255 characters into a textbox. Overwrites any existing string. |
Textbox_To_String | Textbox Reference | String | Reads the first 255 characters of the string in a textbox. |
Clear | Textbox Reference | None | Sets all of the characters in the textbox to ASCII space. |
Errors
Table 8-24 Errors of the Textbox Object.
Error | Associated Method | Meaning |
---|---|---|
INVALID_OBJECT | Clear | The object reference is not a textbox. |
INVALID_TEXTBOX | Add_Character, Delete_Character, Textbox_To_String, STRING_TO_TEXTBOX | The object reference is not a textbox. |
HEIGHT_OUT_OF_RANGE | Set_Property | The height is greater than the height of the display or less than the height of the textbox font. |
WIDTH_OUT_OF_RANGE | Set_Property | The width is greater than the width of the display or less than the width of the widest character of the textbox font. |
Controls
Controls are objects that respond to keypad events such as key presses and releases. The GUI Toolkit has three types of controls for data entry and instrument control – Action Keys, Data Entry Keys, and Shift Keys; each are described in the following sections.
Action key object
Action keys are used to invoke custom program actions such as turning on a motor, changing the contrast level of the display, or starting a process. The custom program actions are performed using event procedures or functions that you write that can be assigned to run when an action key is pressed, held, or released. Event procedures cannot receive or return values but they can modify global variables. If you need to write an event procedure that needs to read, write, or modify GUI Toolkit properties, the servicing of events must be disabled using BLOCK_ON_PRESS
, BLOCK_ON_HOLD
, and BLOCK_ON_RELEASE
to prevent data corruption. If using BLOCK_ON_PRESS
, BLOCK_ON_HOLD
, and BLOCK_ON_RELEASE
, remember to re-enable the servicing of events (by setting the GUI_TOOLKIT
property, SERVICE_EVENTS
to GUI_TRUE
) prior to leaving the event procedure. When an Action Key object is instantiated, all of its properties are initialized to 0.
Properties
Table 8-25 Properties of the Action Key Object.
Property | Values | Meaning |
---|---|---|
PRESS_EVENT_PROCEDURE | Extended Address | Execute this user defined event procedure when the key is pressed. If zero, no event procedure is executed. |
HOLD_EVENT_PROCEDURE | Extended Address | Execute this user defined event procedure when the key is held. If zero, no event procedure is executed. |
RELEASE_EVENT_PROCEDURE | Extended Address | Execute this user defined event procedure when the key is released. If zero, no event procedure is executed. |
BLOCK_ON_PRESS | GUI_TRUE, GUI_FALSE | If true, disables the servicing of events when the key is pressed. |
BLOCK_ON_HOLD | GUI_TRUE, GUI_FALSE | If true, disables the servicing of events when the key is held. |
BLOCK_ON_RELEASE | GUI_TRUE, GUI_FALSE | If true, disables the servicing of events when the key is released. |
Data entry key object
Data entry keys are used to enter alphanumeric characters and symbols into the DATA_ENTRY_TEXTBOX
of a keypad. Data entry keys may be overloaded; that is the same key can be used to enter many different characters or symbols. The alphanumeric characters and symbols are stored as key codes in the Data Entry Key object. Key codes are numbers from 1 to 255 that refer to the images of the characters of a font that are copied to a textbox when a string is rendered. Key codes are stored into the Data Entry Key object by using the Set_Property
method. When a Data Entry Key object is instantiated, all of its properties are initialized to 0; be sure to initialize the Data Entry Key object (by storing key codes into the properties) before you use it.
Properties
Table 8-26 Properties of the Data Entry Key Object.
Property | Values | Meaning |
---|---|---|
SHIFT_NEUTRAL_VALUE | 1 to 255 | The key code that is added to the Data Entry Textbox when the data entry key is pressed and the shift state is shift neutral. |
NUM_SHIFT_UP_VALUES | 0 to 5 | Contains the number of shift up values in the Data Entry Key. |
SHIFT_UP_VALUE0 | 1 to 255 | The key code that is added to the Data Entry Textbox when the data entry key is first pressed and the shift state equals to shift up. |
SHIFT_UP_VALUE1 | 1 to 255 | The key code that is added to the Data Entry Textbox when the data entry key is pressed twice and the shift state equals to shift up. |
SHIFT_UP_VALUE2 | 1 to 255 | The key code that is added to the Data Entry Textbox when the data entry key is pressed three times and the shift state equals to shift up. |
SHIFT_UP_VALUE3 | 1 to 255 | The key code that is added to the Data Entry Textbox when the data entry key is pressed four times and the shift state equals to shift up. |
SHIFT_UP_VALUE4 | 1 to 255 | The key code that is added to the Data Entry Textbox when the data entry key is pressed five times and the shift state equals to shift up. |
NUM_SHIFT_DOWN_VALUES | 0 to 5 | Contains the number of shift down values in the Data Entry Key. |
SHIFT_DOWN_VALUE0 | 1 to 255 | The key code that is added to the Data Entry Textbox when the data entry key is first pressed and the shift state equals to shift down. |
SHIFT_DOWN_VALUE1 | 1 to 255 | The key code that is added to the Data Entry Textbox when the data entry key is pressed twice and the shift state equals to shift down. |
SHIFT_DOWN_VALUE2 | 1 to 255 | The key code that is added to the Data Entry Textbox when the data entry key is pressed three times and the shift state equals to shift down. |
SHIFT_DOWN_VALUE3 | 1 to 255 | The key code that is added to the Data Entry Textbox when the data entry key is pressed four times and the shift state equals to shift down. |
SHIFT_DOWN_VALUE4 | 1 to 255 | The key code that is added to the Data Entry Textbox when the data entry key is pressed five times and the shift state equals to shift down. |
Shift key object
Shift keys are used to set the Shift State of the keypad. Changing the Shift State allows Data Entry Keys to be overloaded. When a Shift Key object is instantiated, the Shift Type is set to SHIFT_NEUTRAL
, and SHIFT_TOGGLE
is set to GUI_FALSE
.
Properties
Table 8-27 Properties of the Shift Key Object.
Property | Values | Meaning |
---|---|---|
SHIFT_TYPE | SHIFT_UP, SHIFT_NEUTRAL, SHIFT_DOWN | Contains the shift type of shift key. |
SHIFT_TOGGLE | GUI_TRUE, GUI_FALSE | If true, causes the shift key when pressed, to toggle between the SHIFT_NEUTRAL state and value in the SHIFT_TYPE property. |
Plot object
Plot objects are used to render data (such as temperature, voltage, or pressure) into a graphical form onto a screen. Plot objects contain a one-dimensional circular byte array, called the plot buffer, that holds the data. The initial size of a plot is 120 pixels wide by 120 pixels tall, with a 240-byte buffer. The size of the plot buffer is limited by the size of the GUI Heap and must be greater than or equal to the width of the plot in pixels. The data in the plot buffer specifies the y coordinate, as the vertical distance in pixels, measured from the top edge of the plot object. Data is added into the plot buffer sequentially; the position of the data in the plot buffer represents the x coordinate and sequential points are connected by lines. For example, if we enter the two data values 4 and 57 into a new plot object and the plot’s upper left corner is at (8,10), a line would be drawn from point (8,14) to (9,67). When the plot buffer is the same size as the plot width and you get to the end of the buffer, the next data point you add will be written into the first position of the buffer and the data will be plotted to the left-edge of the plot (over-writing the previous point on the screen and data in the buffer). When the buffer is larger than the plot width and you get to the end of the plot, the next data point that you add will be written to the next position of the buffer and the data will be plotted to the left-edge of the plot (over-writing only the previous point on the screen). This provides plots that look like oscilloscope traces.
The Add_Data
method adds a single data value into a plot object. The Refresh
method must be called after data is added to re-render the plot on the screen. The plot is rendered from left to right. For example, the following code creates a new plot, loads it into GUI_SCREEN0
, and then repeatedly adds a random data value from 0 to 119 into the plot buffer and refreshes the plot on the screen.
Listing 8-21 Using the Plot Object.
int plotRandom; void Example_Plot( void ) { int random_num; // Create a new plot object. plotRandom = New_Object( PLOT ); // Center plot object on the screen. Plot size is 240 x 120 pixels. Load(GUI_SCREEN0, plotRandom, 0, 0); random_num = Random(); Add_Data(plotRandom, (random_num % 119)); while(1) { random_num = Random (); Add_Data(plotRandom, (random_num % 119)); Refresh(GUI_SCREEN0); Pause(); } }
Properties
Table 8-28 Properties of the Plot Object.
Property | Values | Meaning |
---|---|---|
WIDTH_IN_PIXELS | 8 to 128 pixels | Contains the width of the plot in pixels. |
HEIGHT_IN_PIXELS | 1 to 128 pixels | Contains the height of the plot in pixels. |
BUFFER_SIZE | Unsigned Long | Sets the size of the circular plot buffer. The plot buffer must be greater than or equal to the width of the plot in pixels. |
BORDER | GUI_TRUE , GUI_FALSE | If true, draws a one pixel border around the plot |
Methods
Table 8-29 Methods of the Plot Object.
Method | Inputs | Outputs | Meaning |
---|---|---|---|
Add_Data | Plot Reference, Data | None | Adds a single data value into a plot object. Data is added to the next position in the circular plot buffer. The data value represents the distance in pixels as measured from the top edge of the plot. |
Errors
Table 8-30 Errors of the Plot Object.
Error | Associated Method | Meaning |
---|---|---|
DATA_OUT_OF_RANGE | Add_Data | The data value is larger than the height of the plot in pixels. |
INVALID_PLOT | Add_Data | The object reference is not a plot. |
Screen object
Screens that are created using the New_Object
method reside in the heap. Screens that reside in the heap can not be made visible - the only difference between heap screens and GUI Screens. Heap screens are useful for applications with many different screens. All screens can be instantiated and loaded when the application first starts up. Then, during run time, the screens that are needed can be quickly copied to the GUI Screens for viewing.
Properties
Table 8-31 Properties of Screen Objects.
Property | Values | Meaning |
---|---|---|
WIDTH_IN_PIXELS | 128 pixels | Read only. Contains the width of the screen in pixels. |
HEIGHT_IN_PIXELS | 128 pixels | Read only. Contains the height of the screen in pixels. |
VISIBLE | GUI_FALSE | Read only. All non GUI screens have this property set to GUI_FALSE since they can not be made visible. |
NUM_OBJECTS | Unsigned Long | Read only. Contains the number of objects contained in the screen. |
IN_DISPLAY | GUI_FALSE | Read only. All non GUI screens have this property set to GUI_FALSE since they reside in the heap |
SCREEN_ADDRESS | Extended Address | Read only. Contains the heap handle to the address of the rendered image of the screen. |
Methods
Table 8-32 Methods of Screen Objects.
Method | Parameters | Return Value | Meaning |
---|---|---|---|
Load | Screen Reference, Object Reference, X Coordinate, Y Coordinate | None | Load an object into a screen at the specified x and y coordinates. |
Un_Load | Screen Reference, Object Reference, X Coordinate, X Coordinate | None | Unload an object from a screen at the specified x and y coordinates. |
Copy_Screen | Source Screen Reference, Destination Screen Reference | None | Copies the contents of the source screen into the destination screen. The contents of the destination screen are over written. |
Clear | Screen Reference | None | Unloads all objects from the screen and erases the screen. |
Refresh | Screen Reference | None | Re-renders graphics, textboxes and plots in the screen that have their refresh flags set to true. Sets the refresh flags to false once the objects have been refreshed. |
Redraw | Screen Reference | None | Re-draws all objects contained in the screen. |
Errors
Table 8-33 Errors of Screen Objects.
Error | Associated Method | Meaning |
---|---|---|
HEAP_FULL | Load | Heap is full. There is no room to load an object into a screen. |
INVALID_OBJECT | Load , Un_Load | The object reference cannot be loaded into a screen. |
INVALID_SCREEN | Load , Un_Load , Clear , Redraw , Refresh, Copy_Screen | The object reference is not a screen. |
X_OUT_OF_RANGE | Load , Un_Load | The x coordinate plus the width of the object is greater than the width of the screen. |
Y_OUT_OF_RANGE | Load , Un_Load | The y coordinate plus the height of the object is greater than the height of the screen. |
Customizing the keypad overlay
You can customize the "look and feel" of your instrument by creating your own graphic to be used over your keypad. Figure 3 shows an example graphic.
The keypad includes a clear plastic overlay that forms a pocket into which you can place a paper graphic. When shipped from the factory, the keypad is loosely attached with tape to the enclosure; the adhesive on the back of the keypad is not used to securely fasten the keypad to the enclosure. This allows you to pull up the keypad and install your own custom graphic. Once you have finalized your keypad design, you can remove the backing on the keypad (exposing the adhesive) and permanently attach the keypad to the enclosure. You can also remove the clear plastic overlay and instead use an adhesived plastic sheet with your own graphic.
Figure 3 provides the dimensions of the keypad, showing the precise placement of the buttons. Note that they are not arrayed perfectly evenly; your graphic design should take into account their precise placement. The figure also shows an example overlay design including alphanumeric entry keys, shift and menu keys, navigation keys, and function keys.
One key is special: The bottom right corner key is used to turn the handheld on and off. It is directly wired to the handheld’s power circuitry and it is not scanned with the other keypad keys by the keypad driver routines. Your graphic should show this dedicated key as the on/off button.
Using the keypad pocket
You can print a graphic image on ordinary photo paper and insert it into the keypad pocket. We’ve had the best success printing on "Epsom Photo Quality Ink Jet Paper (Matte Finish)" Part Number S041062, or equivalent: 27 lb, ISO 90 brightness (or greater), 4.9 mil, coated paper. Using a thin paper will not interfere with the buttons’ tactile feedback, while much thicker paper stock may. After printing, the image can be cut to size to fit within the pocket, i.e., to 2.350 x 5.050 in., and carefully slid into the pocket. You can also achieve a better finished look if the image is inserted into the keypad pocket slightly underlapping the black border of the keypad’s top clear plastic layer. If so, cut the image slightly larger. To insert it you will need to peel back the pocket’s top clear plastic layer. Peel it back starting at the top – it is pressure-sensitive-adhesived at the side and bottom edges only. Then place the overlay onto the keypad, carefully centering it so that its edges slightly underlap the black borders of the top plastic layer, and carefully aligning its top edge with the top edge of the keypad. Then place the top layer back on, and reseal the pocket by running a finger around the bottom and side edges to reattach the pressure sensitive adhesive.
Printing on a plastic overlay
Alternatively you can print directly on plastic sheets and use them in place of the top layer on the existing keypad. For use as a top layer, the cropped size of your graphic should be 2.630 by 5.180 in.