Synergy Software Package User's Manual
GUIX Source

GUIX GX_SRC Framework Introduction

The Azure RTOS GUIX Source component (GX_SRC) is the list of properties available in GUIX to modify the RTOS components of GUIX (for example, the system timer).  See the GUIX User Guide Chapter 3: GUIX System Components for a list of GUIX components. The GUIX service calls have mutual exclusion for protection built in so that the application can use GUIX services while the GUIX 'engine' is managing the graphics.  GUIX uses ThreadX threads, timers and message queues to manage display events and render screens.

GUIX GX_SRC Framework Module Features

The GUIX GX_SRC Framework module includes the following options:

  • Disables multithread support
  • Disables UTF8 Support
  • Sets the system timer to match the hardware
gx_src_BD.png
GUIX GX_SRC Framework Module Block Diagram

GUIX GX_SRC Framework Components Overview

The number of API functions available in GUIX in the current release is over 300 and the reader is referred to the GUIX User Guide for detailed API listings and descriptions.  A list of GUIX components is discussed as follows:

GUIX Components

GUIX SYSTEM – Timers, threads and any internal objects the GUIX engine requires to run

GX_CANVAS* –  Set by gx_canvas_create.  In the simple GUIX design case, this function is called by the specification file from GUIX Studio so it is handled automatically.

GUIX CONTEXT – All the components that make up what GUIX is drawing into, that is, screen, canvas, brush and so on.

GX_DISPLAY* – All the components, including drawing functions that GUIX needs to draw on a canvas. GUIX display drivers are responsible for all interaction with the underlying physical screen. The display drivers have three basic functions: initialization, drawing and frame buffer display. Initialization is responsible for preparing the physical display hardware, informing GUIX of the properties of the physical display hardware, and for informing GUIX which specific drawing functions should be used. The main display driver initialization is called from the GUIX gx_display_create API.  This function is called from gx_studio_display_configure in applications that use the resource and specification. 

In GUIX Studio, the specification files will set up the display driver automatically.  If 16bpp is chosen in the Configure Displays dialog box in GUIX Studio, _gx_display_driver_565rgb_setup is used. If 32bpp is chosen you get _gx_display_driver_32argb_setup, and so on. 

GUIX in Synergy supports the following formats:

  • 32bpp (ARGB8888, RGB-888)
  • 16bpp (RGB565)
  • 8bpp (8bit Palette (CLUT))

The display driver function is set up in the GUIX Studio specification files if the target CPU is set to Synergy in GUIX Studio (see the IOTSG-782 module guide document for more details on setting up GUIX Studio for Synergy):

    UINT _gx_synergy_display_driver_setup(GX_DISPLAY *display)
    {
        _gx_display_driver_565rgb_setup(display, GX_NULL, _gx_dave2d_buffer_toggle);

In the user application, the gx_studio_display_configure API configures the main display including specifying the display driver.  Synergy has already tied the display driver to the SF_EL_GX instance.  The SF_EL_GX driver setup function pointer supplies the display driver:

gx_studio_display_configure (MAIN_DISPLAY,
                             g_sf_el_gx0.p_api->setup,...

GX_WIDGET* – any visible thing you place on a screen; may or may not generate events

GUIX UTILITY – essentially a tool box for utility functions

  • Defined as a struct data type in GUIX

GUIX GX_SRC Framework Module Operational Overview

Setting up GUIX in the Configurator

The GUIX Source component is optional. If not using the GUIX source, the prebuilt GUIX library with default settings is used.  If the GUIX source component is added or any of its properties modified, the developer must click on Generate Project Content in the configurator pane and rebuild the project, or the prebuilt GuiX (gx.a) library is used with none of its properties modified.

GUIX at Startup

The following steps need to be performed before rendering any GUIX images:

  • Call the gx_system_initialize API to initialize the GUIX system.
  • Initialize the GUIX driver (g_sf_el_gx.p_api->open).
  • Create and configure the display instance (gx_studio_display_configure called with g_sf_el_gx.p_api->setup as the driver input).
  • Create and initialize the canvas for the display (g_sf_el_gx.p_api->canvasInit API).
  • Prepare the display of the main screen (gx_studio_display_configure API) if using GUIX Studio specification and resource files.
  • [Optionally] create any other windows or widgets if not created (gx_widget_create).
  • Show the root window (gx_window_show API).
  • Start the GUIX engine (gx_system_start API).

In the gx_system_initialize API, GUIX creates its own thread, event queue and timer necessary for performing all drawing, timer and GUIX related tasks.  It also creates a mutex for multithreaded environments.  Application threads have access to the same resources as GUIX; for example, if GUIX is doing a refresh operation, the mutex protections prevents other threads that try to access visible widgets during the refresh of a screen.

The open, setup and canvasInit API are accessible by function pointer fields of the sf_el_gx instance.  One need only supply any other details except for the language and display screen name in the gx_studio_display_configure call.

GX_SRC Properties

GUIX Configurable Options for GX_SRC

ISDE property Default value Description
GUIX Stack Size 4096 bytes GUIX internal thread stack size in bytes.
System Timer 20 ms Used to calculate GX_SYSTEM_TIMER_TICKS. See explanation that follows. Equivalent option in Azure RTOS is GX_SYSTEM_TIMER_MS.
Disable Multithread Support No (Disabled) If not defined, ThreadX can support multiple threads by defining and using locking and unlocking functions to define critical sections. Equivalent option in Azure RTOS is GUIX_DISABLE_MULTITHREAD_SUPPORT.
Disable UTF8 Support No (Disabled) If defined, this disables UTF8 format string encoding in GUIX and allows only 8-bit ASCII character plus Latin-1 code page character encoding. Equivalent option in Azure RTOS is GX_UTF8_SUPPORT.
GUIX Event Queue Size 48 Size of GUIX Event Queue Size. Must be greater than zero or empty.
GUIX Thread Priority 16 Priority of GUIX Internal Thread. The value must be between 0 to 31.
GUIX Thread Time Slice 10 Time Slice value of GUIX Internal Thread. The value must be between 0(TX_NO_TIME_SLICE) to 0xFFFFFFFF.
Use User Data Field in GX_WIDGET Structure No(default) GUIX allows users to use gx_widget_user_data member in GX_WIDGET Structure if you say yes.
Enable partial canvas frame buffer No (Disabled) Enabling this option will define the GX_ENABLE_CANVAS_PARTIAL_FRAME_BUFFER to use the partial canvas frame buffer feature.
Enable horizontal canvas refresh direction No (Disabled) Specify the canvas refresh directions for the partial canvas frame buffer feature. By default, the canvas refreshes its dirty areas one by one. If the application requires refreshing the canvas in horizontal direction to mitigate tearing effects,this can be used.
Enable vertical canvas refresh direction No (Disabled) Specify the canvas refresh directions for the partial canvas frame buffer feature. By default, the canvas refreshes its dirty areas one by one. If the application requires refreshing the canvas in vertical direction to mitigate tearing effects,this option can be used.
Disable arc drawing support No (Disabled) If defined, removes support for the arc-drawing functions circle, arc, pie, and ellipse.
Disable software decoder support No (Disabled) If defined, reduce the GUIX library footprint when runtime decode of jpg or png files is not required.
Disable binary resource support No (Disabled) If defined, reduce your GUIX library footprint when only C source code format resource files are used.
     
Repeat button initial tics 10 This value defines how long the button waits before beginning to send repeated GX_EVENT_CLICKED events.
Maximum number of unique dirty list entries 64 This value defines the maximum number of unique dirty list entries that can be maintained by one canvas.
Maximum nesting of context 8 This value defines the maximum nesting of the drawing context stack.
Maximum input capture nesting 4 This value defines size of the stack used to maintain the list of widgets that have captures the user input.
Cursor blink interval 20 This value defines the rate at which the input cursor blinks for text input widgets.
Multi line index cache size 32 This value defines the size of the list-start index cache maintained by the multi-line text view and multi-line text input widgets.
Multi line text button maximum lines 4 This value determines the number of text pointers needed by the worst case multi-line text button.
Maximum number of polygon edges 10 This value determines the most complex polygon that can be drawn by GUIX.
Numeric scroll wheel string buffer size 16 This value determines the maximum length of the string required to display the assigned integer values.
Circular gauge animation delay 5 This value defines the number of GUIX timer ticks (50 ms) between updates of a circular gauge configured to animate the needle movement between last and current angular position.
Numeric prompt buffer size 16 This value defines the size of buffer allocated to convert an integer value assigned to the prompt to an ascii string.
Animation pool size 6 This value defines the size of animation pool from which animation information structures can be dynamically allocated and returned.
Mouse support Disabled Enables the mouse support. This definition should only be enabled when a mouse (not a touch screen) must be supported.
Hardware mouse support Disabled When enabled, the GUIX display driver utilizes hardware mouse cursor drawing support.
Font kerning support Disabled Enables font kerning support.
Maximum string length 102400 This value defines the maximum length of a string, which is used to test invalid strings.
Disable brush alpha support No (Disabled) Allows brush alpha support to be disabled. This helps eliminate runtime overhead and library footprint increase for drawing non-arc graphics, pixelmaps, and fonts with an alpha value defined by the drawing context brush while running at 16 bpp and higher color depths.
Maximum string length 102400 This value defines the maximum length of a string, which is used to test invalid strings.

GUIX Options Available in the Azure RTOS User Guide (Non-configurable in ISDE)

MACRO Default value Description
GX_SYSTEM_TIMER_TICKS 2 ticks (20 ms) GUIX timer frequency (interval on which the timer thread entry function checks for tasks (for example, periodic tasks, timeouts) that need to be executed.
GX_TICKS_SECOND 2 ticks This is only used if porting GUIX to another RTOS other than ThreadX.
GX_MAX_VIEWS 32 Number of simultaneous views.
GX_MAX_ACTIVE_TIMERS 32 Number of timers available in GUIX to be assigned to one or more widgets.
GX_DISABLE_THREADX_BINDING Not enabled If not defined, GUIX expects a ThreadX RTOS; GUIX can work with other RTOSs, but this is not supported in Synergy.
GX_DISABLE_THREADX_TIMER_SOURCE Not enabled If defined, disables ThreadX timer source to use a different timer source.

Disabling Multithread Support

The gx_system_initialize API creates the GUIX drawing and event processing thread.  That thread is started when the gx_system_start API is called. GUIX application threads may wish to invoke the GUIX API while the GUIX system thread is running.  An application thread could, for example, create a pop-up error window and display it by attaching it to the root window.  The problem is that two or more threads accessing internal GUIX resources simultaneously will cause undefined results. Therefore, in a multithreaded environment, GUIX must protect critical code sections where it updates linked lists and other internal objects. To do so, GUIX uses mutexes to guard critical code sections.  If Multithread Support property is not disabled, GUIX macros enable protection of the critical sections.  It is generally recommended that if a system is not severely constrained by resources (memory), that this option be left disabled.

If the application does not call any GUIX API, then the only thread affecting GUIX is the system thread; disabling multithreaded support will reduce the overhead of protecting critical code sections and improve performance.

GUIX System Timer

The GUIX System timer is the interval on which the GUIX timer executes and is used by GUIX for periodic processing needs inside GUIX.  The system timer It should be a multiple of the ThreadX timer, which is typically defined to be 10 ms (100 ticks/sec).  Example:

GUIX System Timer is to 10

ThreadX timer is 100

       GUIX timer tick = ((10 ms * 100 ticks per second) / 1000 ms per second) == 1 tick

This sets the GUIX timer tick to one tick. If the GUIX System timer is not a multiple of the ThreadX timer, it will be rounded down. In the example above, if it were set to 17, the GUIX timer tick would still be "1". To make the GUIX timer tick every other ThreadX timer tick, set the System timer property in GX_SRC to 20;

       GUIX timer tick = ((20 * 100) / 1000) == 2.

UTF8 Support

By default, UTF8 is enabled.  If UTF8 is disabled, GUIX is limited to ASCII type (one byte per glyph).  There is always runtime overhead associated with UTF8 support even if the application is only using ASCII. This is because GUIX has to call a function to compute the next character value in the string when using UTF8 because it cannot assume it is a one-byte character.

In lieu of disabling UTF8, the application can avoid using character values higher than 255. When UTF8 is disabled, this tells GUIX that each character is simply one byte and it does not need to call the next-character-compute function.

Display Memory Architecture

There are several display memory architectures supported by GUIX. The display memory architecture is really defined by the display driver, which is a very small hardware porting layer, and does not affect the core GUIX library code. The most common model is to provide two canvas memory areas: one the "working" buffer and one the "visible" buffer. GUIX executes drawing updates to the working canvas, then toggles the working and visible canvas buffers when a drawing sequence is completed.

Four basic memory models are described as follows:

Models 1 and 2 contain only GRAM and Frame Buffer respectively in the following diagram, and would be recommended for only very small displays as it is slow.  In Model 1, the display provides its own memory large enough to hold the pixel data. This external memory is usually called "GRAM" or Graphics Ram, and some non-random access such as SPI access is provided to the core CPU. In this model, the display driver executes all drawing operations by writing pixel data over the SPI interface.

gx_src_M1.png
Model 1
gx_src_M2.png
Model 2
gx_src_M3.png
Model 3 (Local Frame Buffer + External GRAM)

Model 3 is a combination of the first two models. In this model, sufficient local memory exists to hold one frame buffer. In addition, the display device provides an external GRAM and automatically refreshes itself using the data provided in the GRAM. This architecture benefits from improved update efficiency because the user can transfer the modified portion of the local frame buffer to the external GRAM in one block transfer, often utilizing on-board DMA channels. This model also eliminates the tearing and flicker that can be present in either of the first two models, because only completed graphics content is copied to the external GRAM.

Model 4 requires that sufficient memory is present to provide two local frame buffers. In this case, GUIX treats one frame buffer as the active frame buffer, and the other as the working frame buffer. When a display update or drawing operation is in progress, it takes place in the working buffer. When the drawing operation completes, the buffers are toggled, and the working buffer becomes the active buffer and the active buffer becomes the working buffer.  Like Model 3, this model also eliminates screen flicker and tearing that can be observed in a single buffered system.

Model 4 Ping Pong frame buffers:

gx_src_M4.png
Model 4 (Ping-Pong Frame Buffers)

Synergy (SF_EL_GX module) implements Model 4 (although Model 3 is also possible).

Receiving Events from the Hardware

Signals in GUIX

Signals are used to get information such as hardware events up to the GUIX level.  Hardware events are transduced by the hardware and message framework drivers into GX_SIGNALs by the time they reach the GUIX event queue.  The GX_SIGNAL macro is a macro that combines the ID of the widget (user defined in GUIX Studio) that generated an event with the event type the widget has generated into a unique gx_event_type identifier code.   For more details about GX_EVENT types and signals, please see the GUIX™ Synergy Port Framework Module Guide.

Drivers for the Hardware Interface

In the Synergy driver hardware, a ThreadX periodic thread task is created that continually checks for hardware events.  When an event is detected, the hardware driver transmits information about this event to the thread task. The Touch Panel V2 Framework module scans data from a touch controller and invokes the user-registered touch panel callback when a touch event occurs. If the user callback is not registered, the sf_touch_panel_v2_api_t::touchDataGet API function can be used to retrieve the data. In the example of the touchscreen, the touch panel driver would relay X and Y coordinates, and event type.

/* User callback*/
typedef struct st_sf_touchpanel_v2_callback_args
{
    sf_touch_panel_v2_payload_t     payload;       // Touch data and event provided to the user during callback
    void const                    * p_context;      // Context provided to user during callback
/* Touch data payload */
typedef struct st_sf_touch_panel_v2_payload
{
    int16_t                        x;              // X coordinate.
    int16_t                        y;              // Y coordinate.
    sf_touch_panel_v2_event_t      event_type;     // Touch event type.

The user callback must be registered to obtain touch data. The Touch Panel V2 Framework module scans data from a touch controller and invokes the user-registered callback. If the user callback is not registered, the sf_touch_panel_v2_api_t::touchDataGet API function can be used to retrieve the data. If the user callback is registered, then the framework will invoke the callback when touch events occur.

Example: (User-defined touch panel callback function)

void g_sf_touch_panel_cb(sf_touchpanel_callback_args_t * p_args)
{
    bool send_event = true;
        GX_EVENT gxe;
        switch (p_args->payload.event_type)
        {
        case SF_TOUCH_PANEL_V2_EVENT_DOWN:
            gxe.gx_event_type = GX_EVENT_PEN_DOWN;
            break;    
        case SF_TOUCH_PANEL_V2_EVENT_UP:
            gxe.gx_event_type = GX_EVENT_PEN_UP;
            break;
        case SF_TOUCH_PANEL_V2_EVENT_HOLD:
        case SF_TOUCH_PANEL_V2_EVENT_MOVE:
            gxe.gx_event_type = GX_EVENT_PEN_DRAG;
            break;
        case SF_TOUCH_PANEL_V2_EVENT_INVALID:
            send_event = false;
            break;
        default:
            break;
        }
    if (send_event)
    {
        /* Send event to GUIX */
        gxe.gx_event_sender         = GX_ID_NONE;
        gxe.gx_event_target         = 0;  /* the event to be routed to the widget that has input focus */
        gxe.gx_event_display_handle = 0;
        gxe.gx_event_payload.gx_event_pointdata.gx_point_x = p_args->payload.x;
  #if defined(BSP_BOARD_S7G2_SK)
        gxe.gx_event_payload.gx_event_pointdata.gx_point_y = (GX_VALUE)(320 - p_payload->y);
  #else
        gxe.gx_event_payload.gx_event_pointdata.gx_point_y = p_args->payload.y;
  #endif
        gx_system_event_send(&gxe);
    }
}

The user callback function can update the GX_EVENT data type and fill in the following fields as needed:

      /* Send event to GUIX */
        gxe.gx_event_sender         = GX_ID_NONE;
        gxe.gx_event_target         = 0;  /* the event to be routed to the widget that has input focus */
        gxe.gx_event_display_handle = 0;
        gxe.gx_event_payload.gx_event_pointdata.gx_point_x = p_args->payload.x;
  #if defined(BSP_BOARD_S7G2_SK)
        gxe.gx_event_payload.gx_event_pointdata.gx_point_y = (GX_VALUE)(320 - p_payload->y);
  #else
        gxe.gx_event_payload.gx_event_pointdata.gx_point_y = p_args->payload.y;
  #endif
        gx_system_event_send(&gxe);

SF_TOUCH_PANEL_V2_EVENT_DOWN, SF_TOUCH_PANEL_V2_EVENT_UP, and other touchscreen panel events are defined in the touchscreen header files.  The touchscreen driver also defines its only payload field, since it needs to communicate some value(s) to the application besides event type. For a touchscreen event, the touchscreen payload includes an x and y coordinate.  The GX_EVENT contains a union of field for payload. In this case, the GX_EVENT gx_event_payload field uses the GX_POINT gx_event_pointdata which holds two values for x and y coordinates.

Now, the application can send this event over to the GUIX event queue to let GUIX handle it by calling gx_system_event_send API. 

GUIX periodically checks the event queue, and sees the event just added to the queue.  In the case of the touchscreen panel, it uses the x,y coordinates to find the window widget currently attached to the root window, and searches all the child widgets contained by that window for the highest one (Z order) that contains this coordinate.  Then GUIX typically defers to the child widget's parent event handler for passing off further handling of the event.

Screen Management

Root and Child Windows

Each visible canvas has a root window. The root window is the container for all windows and widgets of the display.

Attaching and Detaching Screens

If the new screen is a child of the parent screen, the application must attach the new screen and detach the old screen using gx_widget_attach and gx_widget_detach (order is not important).  If moving back to a parent screen, the application does not attach the parent screen but calls gx_window_show on the parent screen. A simple algorithm for swapping out screens follows:

void ToggleScreen(GX_WIDGET *new_win, GX_WIDGET *old_win)
{
    if (!new_win->gx_widget_parent)
    {
        gx_widget_attach(root, new_win);
    }
    else
    {
        gx_widget_show(new_win);
    }
    gx_widget_hide(old_win);
}

In the following code, GUIX has detected a button widget clicked in window1, for switching from window1 to window2. It attaches the new window (window2) to the root window, and detaches the old window (window1):

UINT window1_handler(GX_WINDOW *widget, GX_EVENT *event_ptr)
{
    gx_window_event_process(widget, event_ptr);
    switch (event_ptr->gx_event_type)
    {
        case GX_SIGNAL(ID_WINDOWCHANGER, GX_EVENT_CLICKED):
        if(button_enabled)
        {
            show_window((GX_WINDOW*)&window2, (GX_WIDGET*)widget, true);
        }
        break;
       default:
        gx_window_event_process(widget, event_ptr);
        break;
    }
    return result;
}
static UINT show_window(GX_WINDOW * p_new, GX_WIDGET * p_widget, bool detach_old)
{
UINT result = gx_window_event_process(widget, event_ptr);
switch (event_ptr->gx_event_type)
{
   case GX_SIGNAL(ID_WINDOWCHANGER, GX_EVENT_CLICKED):
      if (!p_new->gx_widget_parent)
{
err = gx_widget_attach(p_window_root, p_new);
}
else
{
err = gx_widget_show(p_new);
}
gx_system_focus_claim(p_new);
GX_WIDGET * p_old = p_widget;
if (p_old && detach_old)
{
if (p_old != (GX_WIDGET*)p_new)
{
gx_widget_detach(p_old);
}
}
break;
   default:
gx_window_event_process(widget, event_ptr);
break;
}
return result;
}

Both methods are perfectly acceptable ways to move between screens, with the latter having more complexity. It does not matter which order is followed in attaching or detaching screens.  GUIX just marks the to-be visible window as dirty and re-draws that window after the application is finished modifying the tree* of visible widgets.  In other words, GUIX does not actually draw the window as part of the "attach" API call.

Note
GUIX maintains a tree structured lists of visible objects for linking child widgets (many) to their parent widget (one).   When a window is swapped out with another, the tree is modified to include the new (visible) window and remove the old (soon to be not visible) window.

Attaching and Detaching Widgets

GUIX keeps a linked list of child widgets (a window is a widget type) that belong to or are attached to a parent. Child windows are attached to the root window. When a widget is attached, it is added to the end of the list. There is a first and last child marker of this list (not a circular list). Before a child widget can be attached to a parent widget, it must not be a child of another parent. If so, it is detached from that parent first.

When it is detached, it is removed from the list. However, it is not deleted, so it is still available to be reattached without needing to be recreated. In the meantime, it cannot draw, and it has no parent, but it can still receive events and the control block for that widget is still valid.

Detaching vs Deleting Widgets

When a widget is detached, it is removed from the active list of widgets maintained by GUIX. However, it is not deleted, so it is still available to be reattached without needing to be recreated. In the meantime, it cannot draw, and it has no parent, but it can still receive events and the control block for that widget is still valid.

The gx_widget_delete API first detaches the widget if it still has a parent, then, it clears out the control block. If the control block was dynamically allocated, the memory for the control block is freed. If the gx_widget_delete API was applied to a widget, the widget will need to be re-created before it can be displayed again.

When to Create Widgets

GUIX Studio enables a developer to create screens, name widgets, set event and draw callback functions much more easily than creating them by source code in GUIX APIs.  In GUIX Studio, the developer can choose which widgets are created at start up time (default setting), or it can enable runtime creation by checking the Run Time Allocation property of a widget.  If this is enabled, the application must create the widget when it needs it. Otherwise, all the 'static' widgets are created at start up.  This requires that there be enough memory for these 'static' widgets.  If there is, there really is no reason to not create all the widgets at start time. However, in an application with a large number of screens, or limited memory, it may be necessary to create widgets as needed at runtime. 

To designate a widget for dynamic memory allocation, check the box for Runtime Allocate in GUIX Studio.  In the specification files created by GUIX Studio, the 'style flag' of the widget (and any children of the widget) sets the GX_ STYLE_DYNAMICALLY_ALLOCATED attribute.  When the application creates the widgets, it will allocate memory using the memory allocator specified in gx_system_memory_allocator_set. Note that this requires that the application set up a memory pool before starting the GUIX services.  The project for this module guide demonstrates this.

Drawing at Run Time

Some screens require drawing at run time inevitably. These would be line draw and text writing API for updating information on a screen in real time.  Dynamic string creation is accomplished using sprintf and gx_utility_ltoa functions; these are useful for printing run time values in the string. Some of the APIs used for that screen for drawing are listed below as examples:

UINT _gx_canvas_line_draw(GX_VALUE x_start, GX_VALUE y_start, GX_VALUE x_end, GX_VALUE y_end);
UINT _gx_canvas_text_draw(GX_VALUE x_start, GX_VALUE y_start, GX_CONST GX_CHAR *string, INT length);

Normally, drawing to a screen is done by a method called deferred drawing, where GUIX internally manages when a window or part of a window should be redrawn so as to improve drawing efficiency. 

However, when an application wants immediate drawing to a canvas, it must call the gx_canvas_drawing_initiate API before drawing anything.  When completed, the application calls  gx_canvas_drawing_complete to signal GUIX to let deferred drawing resume.

Run time drawing requiring memory allocation and deallocation is demonstrated in the rotation of the thermostat in the gux_gx_src_mg_ap.c file in the module guide project.

Note that in SSP 1.3.0/GUIX 5.3.3, to 'rotate' or otherwise redraw an image at run time the pixelmap data must not be compressed. If you anticipate needing to redraw an image differently, such as using rotation, make sure to uncheck the Compress Output for the pixelmap resource in GUIX Studio (v5.3.3.7 and later).  To edit a pixelmap resource, open the Pixelmaps bar by clicking on the (+**) icon -> click on **Custom -> double click on the graphic item -> Uncheck Compress Output (it is enabled by default).

Memory Allocation in GUIX Applications

Allocating Memory

Dynamic memory allocation is supported (for example, heap memory) in GUIX.  The gx_system_memory_allocator_set  API lets the application assign a memory allocation and a memory free service. This API is called at program startup, after gx_system_initialize, and before any GUIX services that require dynamic memory allocation. 

GUIX services that require a runtime memory allocation and de-allocation service include:

  • Loading binary resources from external storage into the GUIX runtime environment.
  • The software runtime jpeg image decoder.
  • The software runtime png image decoder.
  • Using text widgets with GX_STYLE_TEXT_COPY.
  • Runtime pixelmap resize and rotation utility functions.
  • Runtime screen and widget control block allocation.

Dynamic memory allocation is required for pixelmap rotation in the project for this module guide.

Dynamic allocation lets an application import resources like fonts, language, and images at runtime from non-volatile memory like a flash drive or a URL source. Most GUIX applications are small enough that this is not required. GUIX resources can be loaded and statically linked at compile time using the pixelmaps created in GUIX studio, which decode the resource from jpeg to pixelmap format. 

Widget Creation: Static vs Runtime

If you have plenty of memory and your control blocks are all statically allocated, for example, the Runtime Allocated property for the widget in GUIX Studio is not checked, then there is no reason not to create them during program startup. Creating your GUIX screens is just setting their initial parameters using the data written to the specifications file. You can always modify any of these parameters at any time after the screen has been created.

If you want your application to be more RAM efficient, set the Runtime Allocated property for some or all of your screen widgets in GUIX Studio.  In your application, set up a memory pool to use for dynamically allocating your control blocks. This is done by calling the gx_system_memory_allocator_set API, which takes as its input a memory allocate function pointer and a memory release function pointer.  These user defined functions will typically use the ThreadX tx_byte_allocate and tx_byte_release API, respectively, but other memory allocation services can be used.

Dynamic widget allocation is generally handled in the GUIX Studio specification file.  In the specification file, gx_studio_widget_create will dynamically allocate those widget control blocks assigned for dynamic allocation. In the following example, the medical screen widget is designated for dynamic allocation as indicated by the style symbol: GX_STYLE_DYNAMICALLY_ALLOCATED:

GX_CONST GX_STUDIO_WIDGET meds_screen_define =
{
    "meds_screen",
    GX_TYPE_TEMPLATE,                        /* widget type                 */
    ID_MEDS_SCREEN,                          /* widget id                   */
    GX_STYLE_BORDER_THIN|GX_STYLE_DYNAMICALLY_ALLOCATED,   /* style flags   */
    GX_STATUS_ACCEPTS_FOCUS,                 /* status flags              */

Then widget create handler in the specification file will check if a widget should be allocated dynamically:

static GX_WIDGET *gx_studio_nested_widget_create(GX_BYTE *control,
GX_CONST GX_STUDIO_WIDGET *definition, GX_WIDGET *parent)
{
    UINT status = GX_SUCCESS;
    GX_WIDGET *widget = GX_NULL;
    while(definition && status == GX_SUCCESS)
    {
                if (definition->style & GX_STYLE_DYNAMICALLY_ALLOCATED)
                {
                    status = gx_widget_allocate(&widget,
definition -> control_block_size);
                    ...

Note that the application can call gx_widget_allocate at runtime as well. 

When gx_widget_delete is called on this widget, GUIX will call the memory free function specified by the application to release the control block memory. Applications that have hundreds of screens and limited RAM would almost always be set up this way.

When a widget is dynamically allocated, the control blocks for any child widget automatically become dynamically allocated.  You cannot and are not required to set this flag for child widgets. Once you set the flag at any level in e2 studio, all children of the dynamically allocated parent also become dynamically allocated.

Multiple Canvases and Layers

GUIX in Synergy is limited to one 'simple' canvas.  A simple canvas is an off-screen drawing area used by the application. GUIX does nothing directly with a simple canvas, but the application can use a simple canvas to render complex drawing to an off-screen buffer, and then use this off-screen buffer to refresh the visible canvas when needed. Synergy does not currently support multiple canvases.  Most GUIX applications are simple enough that multiple canvases not required. The benefit of using multiple canvases is being able to assign one or more canvases to fast memory to meet performance requirements.  Multiple canvases can also be used for special effects such as fading in and fading out.

Support for multiple graphics layers (multiple overlaid frame buffers) is also not supported.

Timers

The gx_system_timer start API is called on a widget after GUIX services are initialized and running.  The input includes a timer ID for this timer (zero is not allowed) defined by the application.  To stop the timer, the gx_system_timer_stop API is called on the same widget.  If a non-zero timer ID is provided, GUIX will search for all timers attached to this widget for one matching that ID.  If a zero timer ID is provided, GUIX will stop and detach all timers for the specified widget.

On starting a timer, an available timer is allocated from GUIX's free list of timers and added to the list of active timers.  When a timer is stopped it is moved back from the active list of timers to the free list.

When a timer expires, GUIX sends the GX _EVENT_TIMEOUT for that widget (timer owner).  The event handler for that widget should handle the timeout event and perform any necessary tasks. A timer will be reset up to the number of times specified in the gx_system_timer_start API.

GUIX uses ThreadX timer for certain visual effects as well as time out expiration events. Fading out and sprite animation are two examples.

Versions in GUIX and GUIX Studio

GUIX library and Studio versions work as follows. The GUIX library has major.minor.service_pack version information. So it is always 5.3.3 or 5.4.0, three fields. The Studio version number is <GUIX_LIB_VERSION>.Studio Revision. Do not forget that Studio requires the GUIX library as part of the Studio build, this is how we render the GUIX widgets within the Studio target view panel. So the first Studio release based on 5.3.3 library is 5.3.3.0. The latest Studio release based on 5.3.3 library is 5.3.3.7. The first Studio release based on upcoming 5.4.0 library will be 5.4.0.0. So Studio release adds one field to GUIX library release.

Porting GUIX projects from SSP 1.2.0 and 1.2.1 to SSP 1.3.0

  • To port GUIX projects previously built using SSP 1.2.0 or 1.2.1, follow these steps:
    1. Install GUIX Studio 5.3.3.7.
    2. Open the gxp project file used for the GUIX project in 1.2.0/1.2.1 in GUIX Studio 5.3.3.7.
    3. Update the GUIX Library Version in the Configure Display screen (right click on the main display window) and choose 5.3.3.
    4. Generate the new specification and resource files and copy them to your project file if they do not already get written to your src folder or subfolder automatically.
    5. In the Synergy configurator, choose SSP 1.3.0, and click on Generate Project Content.
    6. Build the project.
  • If compile errors result referring to dlist_start and dlist_indirect not being defined, delete the tes and sf_tes_2d_draw folder in the synergy\ssp\src\framework folder.  Then regenerate project files by clicking on Generate Project Content and the Build project icon.
  • Compile errors result referring to the following undefined GUIX functions may result if the wrong version of GUIX is set in GUIX Studio:
    1. _gx_dave2d_glyph_8bit_draw
    2. _gx_dave2d_glyph_4bit_draw
    3. _gx_dave2d_glyph_1bit_draw

Check the headers in the specification and resource files to verify which version of GUIX Studio was used. You can check function headers in any GUIX source file (assuming you have access to it) to verify the GUIX version is 5.3.3.

GUIX GX_SRC Framework Module Important Operational Notes and Limitations

GUIX GX_SRC Framework Module Operational Notes

GUIX GX_SRC Framework Module Limitations

  • GUIX in Synergy does not support 4bpp (grayscale) or 1bpp (monochrome)
  • SF_EL_GX does not support a system with more than two frame buffers.
  • SF_EL_GX supports only one GUIX canvas system.
  • SF_EL_GX makes use of only one graphics layer in the DISPAY module.
  • Refer to the most recent SSP Release notes for additional limitations when using this module.

Including the GUIX GX_SRC Framework Module in an Application

This section describes how to include the GUIX GX_SRC Framework module in an application using the SSP configurator.

Note
It is assumed you are familiar with creating a project, adding threads, adding a stack to a thread and configuring a block within the stack. If you are unfamiliar with any of these items, refer to the first few chapters of the SSP User's Manual to learn how to manage each of these important steps in creating SSP-based applications.

To add the GUIX GX_SRC Framework module to an application, click on the Add GUIX Source block below the GUIX on gx component in the Thread Stack Panel and choose New.

GUIX GX_SRC Framework Module Selection Sequence

Resource ISDE Tab Stacks Selection Sequence
GUIX Source Threads New Stack> X-Ware> GUIX> GUIX Source

When the GUIX GX_SRC Framework module is added to the thread stack as shown in the following figure, the configurator automatically adds any needed lower‑level modules. Any modules needing additional configuration information have the box text highlighted in Red. Modules with a Gray band are individual modules that stand alone. Modules with a Blue band are shared or common; they need only be added once and can be used by multiple stacks. Modules with a Pink band can require the selection of lower-level modules; these are either optional or recommended. (This is indicated in the block with the inclusion of this text.) If the addition of lower-level modules is required, the module description include Add in the text. Clicking on any Pink banded modules brings up the New icon and displays possible choices.

gx_src_MS.png
GUIX GX_SRC Framework Module Stack

Configuring the GUIX GX_SRC Framework Module

The GUIX GX_SRC Framework module must be configured by the user for the desired operation. The SSP configuration window automatically identifies (by highlighting the block in red) any required configuration selections, such as interrupts or operating modes, which must be configured for lower-level modules for successful operation. Only properties that can be changed without causing conflicts are available for modification. Other properties are locked and not available for changes and are identified with a lock icon for the locked property in the Properties window in the ISDE. This approach simplifies the configuration process and makes it much less error-prone than previous manual approaches to configuration. The available configuration settings and defaults for all the user-accessible properties are given in the Properties tab within the SSP Configurator and are shown in the following tables for easy reference.

Note
You may want to open your ISDE, create the module and explore the property settings in parallel with looking over the following configuration table values. This helps to orient you and can be a useful hands-on approach to learning the ins and outs of developing with SSP.

Configuration Settings for the GUIX GX_SRC Framework

ISDE Property Value Description
GUIX Stack Size GUIX internal thread stack size in bytes. Must be greater than zero or empty.
GUIX System Timer (Milliseconds) GUIX system timer. Must be a multiple of TX_TIMER_TICKS_PER_SECOND or empty.
GUIX Timer Rate GUIX timer rate as a multiple of the ThreadX tick interrupt rate. Must be greater than zero or empty.
Disable Multithread Support Yes, No

Default: No
If your application has only one thread which utilizes the GUIX API services, say yes to reduce system overhead.
Disable UTF8 Support Yes, No

Default: No
GUIX disables UTF8 support if you say yes.
GUIX Event Queue Size Size of GUIX Event Queue Size. Must be greater than zero or empty.
GUIX Thread Priority 16 Priority of GUIX Internal Thread. The value must be between 0 to 31.
GUIX Thread Time Slice 10 Time Slice value of GUIX Internal Thread. The value must be between 0(TX_NO_TIME_SLICE) to 0xFFFFFFFF.
Use User Data Field in GX_WIDGET Structure Yes, No

Default: No
GUIX allows users to use gx_widget_user_data member in GX_WIDGET Structure if you say yes.
Enable partial canvas frame buffer Yes, No

Default: No
Enabling this option will define the GX_ENABLE_CANVAS_PARTIAL_FRAME_BUFFER to use the partial canvas frame buffer feature.
Enable horizontal canvas refresh direction Yes, No

Default: No
Specify the canvas refresh directions for the partial canvas frame buffer feature. By default, the canvas refreshes its dirty areas one by one. If the application requires refreshing the canvas in horizontal direction to mitigate tearing effects,this can be used.
Enable vertical canvas refresh direction Yes, No

Default: No
Specify the canvas refresh directions for the partial canvas frame buffer feature. By default, the canvas refreshes its dirty areas one by one. If the application requires refreshing the canvas in vertical direction to mitigate tearing effects,this option can be used.
Disable arc drawing support Yes, No

Default: No
Reduce the GUIX library code size and GX_DISPLAY structure size by removing support for the arc-drawing functions circle, arc, pie, and ellipse.
Disable software decoder support Yes, No

Default: No
If your application does not require runtime decode of jpg or png files, select yes to reduce the GUIX library footprint.
Disable binary resource support Yes, No

Default: No
If your application is using only C source code format resource files, select yes to reduce your GUIX library footprint.
Repeat button initial tics This value defines how long the button waits before beginning to send repeated GX_EVENT_CLICKED events.
Maximum number of unique dirty list entries This value defines the maximum number of unique dirty list entries that can be maintained by one canvas.
Maximum nesting of context This value defines the maximum nesting of the drawing context stack.
Maximum input capture nesting This value defines size of the stack used to maintain the list of widgets that have captures the user input.
Cursor blink interval This value defines the rate at which the input cursor blinks for text input widgets.
Multi line index cache size This value defines the size of the list-start index cache maintained by the multi-line text view and multi-line text input widgets.
Multi line text button maximum lines This value determines the number of text pointers needed by the worst case multi-line text button.
Maximum number of polygon edges This value determines the most complex polygon that can be drawn by GUIX.
Numeric scroll wheel string buffer size This value determines the maximum length of the string required to display the assigned integer values.
Circular gauge animation delay This value defines the number of GUIX timer ticks (50 ms) between updates of a circular gauge configured to animate the needle movement between last and current angular position.
Numeric prompt buffer size This value defines the size of buffer allocated to convert an integer value assigned to the prompt to an ascii string.
Animation pool size This value defines the size of animation pool from which animation information structures can be dynamically allocated and returned.
Mouse support Enabled, Disabled

Default: Disabled
Enables the mouse support. This definition should only be enabled when a mouse (not a touch screen) must be supported.
Hardware mouse support Enabled, Disabled

Default: Disabled
When enabled, the GUIX display driver utilizes hardware mouse cursor drawing support.
Font kerning support Enabled, Disabled

Default: Disabled
Enables font kerning support.
Maximum string length This value defines the maximum length of a string, which is used to test invalid strings.
Disable brush alpha support Yes, No

Default: No
When running at 16 bpp and higher color depths, GUIX optionally supports drawing non-arc graphics, pixelmaps, and fonts with an alpha value defined by the drawing context brush. Supporting this drawing mode introduces a small runtime overhead and library footprint increase, which can be eliminated by defining this flag if the application do not require alpha-blending drawing support. 
Show linkage warning Enabled, Disabled

Default: Enabled
Select whether or not to show linkage warning.
Note
The example settings and defaults are for a project using the S7G2 Synergy MCU Group. Other MCUs may have different default values and available configuration settings.

GUIX GX_SRC Framework Module Clock Configuration

The GUIX GX_SRC Module is a logical module and therefore does not require any hardware setting except setting the ARM Cortex-M core SysTick timer.

GUIX GX_SRC Framework Module Pin Configuration

The GUIX GX_SRC Module is a logical module and therefore does not require pin settings.

Using the GUIX GX_SRC Framework Module in an Application

The typical steps in using the GUIX Framework module in an application are (assuming the instance of the GUIX driver is g_sf_el_gx and the instance of the SPI driver for the LCD is g_rspi_lcdc):

  1. Create a memory pool for dynamic allocation in GUIX.
  2. Initialize GUIX with the gx_system_initialize function.
  3. Set the memory rotate and memory free services for GUIX to use using the gx_system_memory_allocator_set API
  4. Initialize GUIX drivers using the open API (g_sf_el_gx.p_api->open)
  5. Create and initialize the main display usingthe gx_studio_display_configure API. This uses the open function of the SF_EL_GX driver instance as one of the input parameters.
  6. Initialize the memory address of the canvas with the canvasInit API for the SF_EL_GX driver
  7. Loop through all the widgets defined in the GUIX studio resource files. Create the root window and each widget using the gx_studio_named_widget_create API.
  8. Show the root window using the gx_widget_show API.
  9. Start the GUIX system with the gx_system_start API.
  10. Open the SPI driver to initialize the LCD using the open API for the SF_EL_GX driver.
  11. Set up the LCD display with the ILI9341V_Init function.

The next steps describe the invoking of the touch panel user callback function when a touch event occurs and use GUIX services to process them and update the image display:

  1. Register a touch panel user callback in the application code to receive touch data. (Get the data using the sf_touch_panel_v2_api_t::touchDataGet API function if the user callback is not registered.)
  2. Operate on the received touch data as needed.
  3. Send the event to the GUIX engine to render an updated image using the gx_system_event_send API.

These common steps are illustrated in a typical operational flow in the following figure:

gx_src_TA.png
Flow Diagram of a Typical GUIX GX_SRC Framework Module Application

The GUIX Studio project includes a callback function for the Event Function of the main window in this project. When this callback, thermos_screen_event_handler, is invoked by GUIX, it computes how to adjust the needle on the thermostat in the image and forwards that information back to GUIX for how to render an updated image based on a user touch event:

  1. Determine event type from the event_ptr input from GUIX
  2. Get the current needle angle data from GUIX using the gx_circular_gauge_angle_get API.
  3. Send the updated information about the event to GUIX using the gx_window_event_process API.

The GUIX Studio project includes a callback function for the Draw Function of the "plus" and "minus" buttons in the main screen. When this callback, custom_pixelmap_button_draw,  is invoked by GUIX, it redraws the buttons to add the "+" or "-" depending on which button is pressed.  This does not have a great deal of functionality per se, but demonstrates how the draw function callback works with GUIX.