How-To: Use Input System Service for Idle Timeout
Introduction
The Input System Service (ISS) allows other tasks to register as listeners for input events. One such task is the Microchip Graphics Suite (MGS) Harmony Task, which listens to input events through this service.
In some cases, user application code may also need to register as a listener for input events. For instance, monitoring touchscreen activity can help determine if the system has been idle for a certain period and may need to enter low-power mode. Another example is detecting and processing touch gestures at the application level, such as swiping to change screens.
This guide demonstrates how to utilize the Input System Service (ISS) to monitor touch input and manage user inactivity effectively.
MGS Example Project
Refer to the project in GitHub for the example mentioned in this guide.
MGS Simulator Output
The application shows a counter that counts down from 30 seconds when no user input is detected on the screen. When touch input is detected anywhere on the screen, the counter will reset back to 30 seconds.
When the counter expires to zero, a locked screen dialog box is shown. The screen is unlocked when the unlock button is pressed.
MGS Harmony Composer Design
Here is what the design looks like in MGS Harmony Composer.
Selecting the widgets in the Screen Tree window will show the widget in the Screen Designer.
The hidden panel widget pnlLock contains the dialog pop-up box that will show up when the timer expires. This can be shown in MGS Composer by unselecting the Hidden property of pnlLock.
Application Code
There are two types of application code used in this example: the main and the screen application codes.
Main Application Code
The main application code in app.c registers as a listener to the ISS.
First, it declares the ISS listener object and handle.
static SYS_INP_InputListener APP_inputListener;
/* input system service listener id */
static int32_t APP_inputListenerId;
It also defines the ISS event handler functions for touch down, up, and move events. These functions call the screen Application Programming Interface (API) for resetting the timeout counter value.
static void app_touchDownHandler(const SYS_INP_TouchStateEvent* const evt)
{
/* Touch Detected reset counter */
App_Screen0_ResetTimer();
}
/* input system service touch up callback */
static void app_touchUpHandler(const SYS_INP_TouchStateEvent* const evt)
{
/* Touch Detected reset counter */
App_Screen0_ResetTimer();
}
/* input system service touch move callback */
static void app_touchMoveHandler(const SYS_INP_TouchMoveEvent* const evt)
{
/* Touch Detected reset counter */
App_Screen0_ResetTimer();
}
Then it calls the ISS API to register as a listener to ISS events.
APP_inputListener.handleTouchUp = &app_touchUpHandler;
APP_inputListener.handleTouchMove = &app_touchMoveHandler;
APP_inputListenerId = SYS_INP_AddListener(&APP_inputListener);
if (APP_inputListenerId >= 0)
{
appData.state = APP_STATE_SERVICE_TASKS;
}
Since the callbacks are registered in the main application code, these callbacks take effect system-wide and are active regardless of the screen being shown.
Screen Application Code
In the screen application code in app_screen0.c, the screen event callback functions for the screen show/hide/update and unlock button press/release events are defined.
Screen OnShow and OnHide
When the screen is first shown, the Screen0_OnShow() screen callback function creates a 1-second periodic timer using the Harmony Timer System Service. This periodic timer calls Timer_callback to increment the tickSecs counter.
{
/* Initialize counters */
tickSecs = 0;
lastTickSec = 0;
/* Showing screen, register 1s timer */
screenTimer = SYS_TIME_CallbackRegisterMS(Timer_Callback,
1,
SCREEN_TIMER_PERIOD_MS,
SYS_TIME_PERIODIC);
/* Hide lock dialog box at init */
Screen0_pnlLock->fn->setVisible(Screen0_pnlLock, LE_FALSE);
//Allocate dynamic string object, must be freed with leString_Delete
screenCounterString = leDynamicString_New();
screenCounterString->fn->setFont(screenCounterString, (leFont*) &Font0);
}
This timer is destroyed in Screen0_OnHide when the screen is hidden during a screen transition.
void Screen0_OnHide(void)
{
/* Hiding screen, destroy timer */
SYS_TIME_TimerDestroy(screenTimer);
/* Free Dynamic string allocations */
leString_Delete((leString *) screenCounterString);
}
Screen OnUpdate
The Screen0_OnUpdate() function is periodically called by the GFX library. This event callback function is used to monitor the value of tickSecs to show the counter value using the lblCounter label and show the locked screen dialog box when the counter expires.
void Screen0_OnUpdate(void) {...}
{
if (lastTickSec != tickSecs)
{
char cStrBuff[16];
/* Update the counter value label */
snprintf(cStrBuff, 16, "%d\nsecs", tickSecs);
//Set string data from C-string
screenCounterString->fn->setFromCStr(screenCounterString, cStrBuff);
//Update label widget string
Screen0_lblCounter->fn->setString(Screen0_lblCounter, (leString *) screenCounterString);
/* Check if counter has expired */
if (tickSecs == 0)
{
/* Stop Timer */
SYS_TIME_TimerStart(screenTimer);
/* Show lock dialog box */
Screen0_pnlLock->fn->setVisible(Screen0_pnlLock, LE_TRUE);
}
lastTickSec = tickSecs;
}
}
Summary
The example shows how the Input System Service can be used to listen for and receive touch events in the application and process these events to perform application-specific functions.