MPLAB® Harmony Graphics Suite > Advanced Topics > Custom Event Handling and Dynamic Widget Creation
MPLAB® Harmony Graphics Suite
Custom Event Handling and Dynamic Widget Creation

This example is based on the Quick Start Guide “Adding an Event to the Aria Quickstart Demonstration” found in the Graphics Library documentation. 

This example has a target configuration for the SAM E7 Xplained Ultra Board with a 4.3” WQVGA Diaplay. For setting up these boards see the instructions for the Aria Quickstart demonstration under Graphics Demonstrations. 

This project demonstrates the following events/macros:

 

 

 

Asserting the “Make Changes. Generate. Run” button on the display changes its text to “Ouch! Ouch! Ouch!”. Pressing the board’s Switch changes the LEDs on the board as well as changing the virtual LEDs on the display. Pressing the display’s virtual S1 switch does the same. The list wheel changes the image displayed among { None | Baboon | Lena }:

 

 

The application’s events are defined in libaria_events.c:

#include "gfx/libaria/libaria_events.h"
// CUSTOM CODE - DO NOT DELETE
#include "app.h"
extern APP_DATA appData;
// END OF CUSTOM CODE

// Display_S1 - PressedEvent
void Display_S1_PressedEvent(laButtonWidget* btn)
{
  // CUSTOM CODE - DO NOT DELETE
    appData.bDisplay_S1State = true;
  // END OF CUSTOM CODE
}

// Display_S1 - ReleasedEvent
void Display_S1_ReleasedEvent(laButtonWidget* btn)
{
  // CUSTOM CODE - DO NOT DELETE
    appData.bDisplay_S1State = false;
  // END OF CUSTOM CODE
}

// SelectImage - SelectedItemChangedEvent
void SelectImage_SelectedItemChangedEvent(laListWheelWidget* whl, uint32_t idx)
{
  // CUSTOM CODE - DO NOT CHANGE
    // ChangeImage - Set Image - ImageSelected
    switch (idx)
    {
        case 0:
            appData.image_selected = APP_IMAGE_NOIMAGE;
            break;

        case 1:
            appData.image_selected = APP_IMAGE_BABOON;
            break;

        case 2:
            appData.image_selected = APP_IMAGE_LENA;
            break;
    }
  // END OF CUSTOM CODE
}

// ButtonWidget1 - PressedEvent
void ButtonWidget1_PressedEvent(laButtonWidget* btn)
{
    // ButtonDown - Set Text - ButtonWidget1
    laButtonWidget_SetText((laButtonWidget*)ButtonWidget1,
                           laString_CreateFromID(string_OuchOuchOuch));
}

// ButtonWidget1 - ReleasedEvent
void ButtonWidget1_ReleasedEvent(laButtonWidget* btn)
{
    // ButtonUp - Set Text - ButtonWidget1
    laButtonWidget_SetText((laButtonWidget*)ButtonWidget1,
                            laString_CreateFromID(string_Instructions));
}

The SelectImage list wheel selects which image is shown in the ImageSelected image by setting the variable appData.image_selected

The widget ButtonWidget1 changes its test using the laButtonWidget_SetText function. Details on how this is accomplished are discussed in the Quick Start Guide “Adding an Event to the Aria Quickstart Demonstration”. 

The Display_S1 widget just sets a Boolean semaphore appData.bDisplay_S1State

The application’s macros are defined in libaria_macros.c. They change the coloring scheme for the display’s virtual LEDs:

#include "gfx/libaria/libaria_macros.h"

void LEDsTurnOn(void)
{
    if(laContext_GetActiveScreenIndex() != default_ID)
        return;

    // TurnOnDisplayD6 - Set Scheme - SAME70_LED1
    laWidget_SetScheme((laWidget*)SAME70_LED1 &LED1_ON);
    // TurnOnDisplayD7 - Set Scheme - SAME70_LED2
    laWidget_SetScheme((laWidget*) SAME70_LED2, &LED2_ON);
}


void LEDsTurnOff(void)
{
    if(laContext_GetActiveScreenIndex() != default_ID)
        return;

    // TurnOffDisplayD6 - Set Scheme - SAME70_LED1
    laWidget_SetScheme((laWidget*)MEB2_LED_D6, &LED_OFF);
    // TurnOffDisplayD7 - Set Scheme - SAME70_LED2
    laWidget_SetScheme((laWidget*) SAME70_LED2, &LED_OFF);
}

 

The difference among the color schemes is only in the base color:

 

 

 

The macros LEDsTurnOn and LEDsTurnOff are called from the application’s main task loop, APP_Tasks. The work of controlling the LEDs is done in the APP_STATE_SERVICE_TASKS state:

void APP_Image_Tasks( void );

static bool bS1State = false;
static bool bLED_State = false;
static bool bLED_StateNow;

char *msgBuffer = "\r\nApplication created " __DATE__ " " __TIME__
                  " initialized!\r\n";

void APP_Tasks ( void )
{
    /* Check the application's current state. */
    switch ( appData.state )
    {
        /* Application's initial state. */
        case APP_STATE_INIT:
        {
            bool appInitialized = true;
            /* Show Hyperterminal is working using available output functions */
            SYS_CONSOLE_Write(SYS_CONSOLE_INDEX_0, STDOUT_FILENO,
                              msgBuffer, strlen(msgBuffer));
            if (appInitialized)
            {
                appData.state = APP_STATE_SERVICE_TASKS;
            }
            break;
        }

        case APP_STATE_SERVICE_TASKS:
        {
            APP_Image_Tasks(); // Handle images
            bS1State = !SW1_Get(); // Closed --> grounded
            bLED_StateNow = bS1State || appData.bDisplay_S1State; // S1 and virtual S1
            if ( bLED_State != bLED_StateNow )
            {// LED state has changed
                if ( bLED_StateNow )
                {
                    LED1_On();  // LED1 On
                    LED2_On();  // LED2 On
                    LEDsTurnOn();   // Turn display LEDs off; // Turn display LEDs on
                }
                else
                {
                    LED1_Off(); // LED1 Off
                    LED2_Off(); // LED2 Off
                    LEDsTurnOff();   // Turn display LEDs off
                }//end if ( bMEB2_S1State || bDisplay_S1State )
                bLED_State = bLED_StateNow; // Remember new state
            }
            break;
        }

        default:
        { /* The default state should never be executed. */
           #define UNKNOWN_APP_STATE 0
            assert(UNKNOWN_APP_STATE);
            break;
        }

    }//end switch ( appData.state )

}//end APP_Tasks

 

The image widget is managed in APP_Image_Tasks. This state machine is responsible for the dynamic changing of the image displayed based on the list wheel Select_Image.

void APP_Image_Tasks( void )
{
    static APP_IMAGE_SELECTED image_selected_old = APP_IMAGE_NOIMAGE;

    if ( laContext_IsDrawing() )
    { // Don't do anything.  Wait until all drawing is done.
        return;
    }

    switch ( appData.image_selected )
    {
        case APP_IMAGE_NOIMAGE:
            if ( appData.bImageDrawn )
            { // If image is visible, hide it
                laWidget_SetVisible((laWidget *)ImageSelected,LA_FALSE);
                appData.bImageDrawn = false;
            }
            image_selected_old = APP_IMAGE_NOIMAGE;
            break;

        case APP_IMAGE_BABOON:
            if ( !appData.bImageCreated )
            { // Create image for the first time
                _APP_Image_Create();
                appData.bImageCreated = true;
                appData.bImageDrawn   = true;
            }
            if ( !appData.bImageDrawn )
            { // Image hidden, make it visible
                laWidget_SetVisible((laWidget *)ImageSelected,LA_TRUE);
                appData.bImageDrawn = true;
            }
            if ( image_selected_old != APP_IMAGE_BABOON )
            { // Select Baboon as the image displayed
                laImageWidget_SetImage((laImageWidget*)ImageSelected,
                                       &Baboon_quartersized);
                image_selected_old = APP_IMAGE_BABOON;
            }
            break;

        case APP_IMAGE_LENA:
            if ( !appData.bImageCreated )
            { // Create image for the first time
                _APP_Image_Create();
                appData.bImageCreated = true;
                appData.bImageDrawn   = true;
            }
            if ( !appData.bImageDrawn )
            { // Image hidden, make it visible
                laWidget_SetVisible((laWidget *)ImageSelected,LA_TRUE);
                appData.bImageDrawn = true;
            }
            if ( image_selected_old != APP_IMAGE_LENA )
            { // Select Lena as the image displayed
                laImageWidget_SetImage((laImageWidget*)ImageSelected,
                                       &Lena_quartersized);
                image_selected_old = APP_IMAGE_LENA;
            }
            break;

        default:
           #define UNKNOWN_IMAGE_TASK_STATE 0
            assert(UNKNOWN_IMAGE_TASK_STATE);
            break;

    }//end switch ( appData.image_state )

}//end APP_Image_Tasks( void )

 

At boot-up the widget ImageSelected has not been created. Only when the image is changed from None to Baboon or Lena is the image created for the first time. Then if the image is changed back to None the APP_Image_Tasks hides the image by making it invisible.

static void _APP_Image_Create( void )
{ // Create the image widget for the first time.
    while ( laContext_IsDrawing() )
    { // Don't do anything.  Wait until all drawing is done.
    }

    ImageSelected = laImageWidget_New();
    laWidget_SetPosition((laWidget*)ImageSelected, 6, 66);
    laWidget_SetSize((laWidget*)ImageSelected, 128, 128);
    laWidget_SetBackgroundType((laWidget*)ImageSelected, LA_WIDGET_BACKGROUND_NONE);
    laWidget_SetBorderType((laWidget*)ImageSelected, LA_WIDGET_BORDER_NONE);
    laWidget_AddChild((laWidget*)Images, (laWidget*)ImageSelected);

}//end APP_Image_Create

 

If laContect_IsDrawing returns true, then neither APP_Image_Tasks or _APP_Image_Create runs. This is to prevent conflicts in the redraws by the graphics library.

MPLAB® Harmony Graphics Suite