Knowledge Base

The first sample program above already handles one event, namely the Connect event. What happens is that when you click the Connect button on the SPLat/PC SimpleHMI screen, a special message is sent to the SPLat via the serial port. The SPLat detects this and automatically does a GoSub to your event handler. The event handler is simply a subroutine that does whatever is required in response to that event. It must exit via a Return instruction.

This event-based mechanism is carried through the whole set of HMI hash functions. Events are also generated by button clicks and by user data entry.

Events provide a lot of the power of SimpleHMI programming. Every time your SPLat program defines an event and names an event handler, a new, totally unique event code is set up in the SimpleHMI. Thus every event is unique, and unambiguously tied to its own event handler. A program may contain up to 127 event handlers. You can reference an event handler multiple times.

Consider this: SimpleHMI has a limited number of buttons, which can be re-used on different screens. On screen A button 1 may be the “Pump On” button. On screen B it may be the “Launch Missile” button. For each use you will have a separate handler subroutine. Now, it is only if screen B is actually showing that pressing that button will send back the event code for Launch_Missile. This means your program does not have to keep track of which screen it is showing in order to know how to respond to button 1.

Here’s a program that illustrates this point (You will get best value from this if you have indicator lights on outputs 0, 1, and 2 of your controller). There is a detailed description of each segment after the program. In this example I am using specific buttons to illustrate a point. Since the original writing the need to explicitly nominate buttons is all but eliminated but the point remains to be made:

(Click here for some tips for working around problems with copy and paste out of Internet Explorer and HTML-help (.chm) files)

This code was originally written to run on SimpleHMI on Windows.  However, SimpleHMI on Windows is no longer supported.  This new version of the code is written to run on an HMI430 or HMI700.  However, the controller will need to be power-cycled for the code to work.

;Demonstrate re-use of buttons, and unique event handlers for each use
;**** This example will require the HMI module to be restarted by a power cycle *******
HMIPort EQU 251 ;Define the port number we want to use.
#HMI ConnectEvent(HMI_Connect) ;Where to GoSub when the SimpleHMI connects
LaunchTask HeartBeat ;Show we are alive
RunTasksForever

;----- HeartBeat task, shows we are alive by flashing an output -----
HeartBeat:
On 0
Pause 2
Off 0
Pause 50
GoTo HeartBeat

;---- Event handler for the HMI Connected event generated by SimpleHMI -------
HMI_Connect:
GoSub HomeScreen ;Paint home screen
Return

;----- Event handler for Home button ------
HomeScreen:
#HMI Cls()
;#HMI HideAllButtons()
#HMI ButtonEvent2(id:1, y:4, x:9, h:3, w:20, t:"Pump On", ev:PumpOnEvent)
#HMI ButtonEvent2(id:2, y:9, x:9, h:3, w:20, t:"Pump Off", ev:PumpOffEvent)
#HMI ButtonEvent2(id:3, y:14, x:9, h:3, w:20, t:"Launch Screen", ev:LaunchScreen)
Return

;----- Event handler for Pump On button ------
PumpOnEvent:
On 1
Return

;----- Event handler for Pump Off button ------
PumpOffEvent:
Off 1
Return

;----- Event handler to paint Launch Screen ------
LaunchScreen:
#HMI SetColors(b:'HFF000000) Cls() ButtonEvent2(id:1, y:12, x:9, h:10, w:20, t:"Launch Missile", ev:Launch_Missile)
#HMI ButtonEvent2(id:2, y:21, x:0, h:3, w:8, t:"Home", ev:HomeScreen)
Return

****** Launch the missile *********
Launch_Missile:
LaunchTask MissileLaunch ;A new MultiTrack task
GoSub HomeScreen ;Display the home screen
Return
;==================================================================
;A separate MultiTrack task to create a "spectacular" launch display
bCount defBYTE
MissileLaunch:
SetMem bCount,150 ;150 flashes
#HMI ButtonEvent2(id:5, x:30, y:15, w:4, h:2, t:b(*bCount), m:"d1m1", ev:Return)
FLoop:
#HMI ButtonEvent2(id:5, t:b(*bCount) )
On 2
Pause 10
Off 2
Pause 90
DMGNZ bCount,Floop
Killtask

Return:
Return

Here’s a blow by blow description of each segment of the program:

Startup code

Defines the handler for the HMI ConnectEvent, launches the heartbeat task and gets MultiTrack running.

Heartbeat task

Trivial. I use this because it’s helpful to know during development that my program is actually running, especially as there’s a 10 second delay when initialising a serial protocol.

Connect event handler

Just calls the subroutine that paints the home screen. This is also called from elsewhere.

Handler for Home button

Cls() clears the screen to the current background colour (more on that later). HideAllButtons() … I’ll let you work that out!

Once the screen is returned to a blank state, we position and label buttons 1, 2, and 3, and define their event handler names.

Pump handlers

Trivial, but notice how little effort it has taken to tie the buttons to the physical actions.

Launch screen

This is the program’s second screen. It sets the background colour to red before clearing the screen. Then it defines a large, impressive “Launch Missile” button and a more modest Home button. Notice we are using button 1, which on the home screen is the Pump On button.

Launch button handler

This handler launches a fresh MultiTrack task whose job it is to manage the missile launch sequence.

MissileLaunch task

Creates a light and sound show (minus sound!) consisting of 150 rapid flashes of an output, then kills itself.

But there’s a problem, Housten!

When you test the program you will discover that on returning to the home screen from the launch screen, the red background colour persists. That was not the intention.

Exercise: Study the program and fix it.

A subtle hazard

I have positioned the Launch Screen button on the home screen, and the Launch Missile button on the launch screen, deliberately overlapping each other. If you click very rapidly on the overlapping buttons, you will be able to crash the program. The reason is that every time you launch the missile you also launch another copy of the MissileLaunch task. When you get to the limit of 32 running tasks, the controller crashes.

Exercise: Find a solution.

Hint: Use a semaphore that is set when the launch missile task is launched, and reset when it completes. Use that semaphore to prevent it from being launched a second time when it is already running.

This effect does not occur in Android, because Android and Windows have different way of rendering overlapping buttons. This example is intended only for the Windows versions of SimpleHMI.

Note: It took me longer to write this page than to write the sample program.

Exercise: Modify the program so it is impossible to launch while the pump is on.