0% found this document useful (0 votes)
103 views36 pages

Design XPress Home Theater Version Advanced Programmers Guide 0332716

AMX DISCLAIMS ALL OTHER WARRANTIES, EITHER EXPRESS or IMPLIED, WITH REGARD TO THE AMX SOFTWARE. NO LIABILITY FOR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OF OR INABILITY TO USE THIS AMX PRODUCT. IN NO EVENT SHALL AMX BE LIABLE FOR ANY DAMAGES WHATSOEVER (INCLUDING, WITHOUT LIMITATION, DAMAGES for LOSS of BUSINESS PROFIT

Uploaded by

cwar0021
Copyright
© Attribution Non-Commercial (BY-NC)
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
103 views36 pages

Design XPress Home Theater Version Advanced Programmers Guide 0332716

AMX DISCLAIMS ALL OTHER WARRANTIES, EITHER EXPRESS or IMPLIED, WITH REGARD TO THE AMX SOFTWARE. NO LIABILITY FOR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OF OR INABILITY TO USE THIS AMX PRODUCT. IN NO EVENT SHALL AMX BE LIABLE FOR ANY DAMAGES WHATSOEVER (INCLUDING, WITHOUT LIMITATION, DAMAGES for LOSS of BUSINESS PROFIT

Uploaded by

cwar0021
Copyright
© Attribution Non-Commercial (BY-NC)
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 36

instruction manual

Design XPress -
Home Theater
version 1.2

Advanced Programmer’s Guide

So ftw are
Software Warranty Agreement
PRE-RELEASE CODE.
Portions of the AMX Software may, from time to time, as identified in the AMX Software, include PRE-RELEASE CODE
and such code may not be at the level of performance, compatibility and functionality of the final code. The PRE-
RELEASE CODE may not operate correctly and may be substantially modified prior to final release or certain features
may not be generally released. AMX is not obligated to make or support any PRE-RELEASE CODE. ALL PRE-
RELEASE CODE IS PROVIDED “AS IS” WITH NO WARRANTIES.

LIMITED WARRANTY.
AMX warrants that the AMX Software will perform substantially in accordance with the accompanying written materials
for a period of 30 days from the date of receipt. AMX DISCLAIMS ALL OTHER WARRANTIES, EITHER EXPRESS OR
IMPLIED, INCLUDING, BUT NOT LIMITED TO IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE, WITH REGARD TO THE AMX SOFTWARE. THIS LIMITED WARRANTY GIVES YOU
SPECIFIC LEGAL RIGHTS.

LICENSEE REMEDIES.
AMX's entire liability and your exclusive remedy shall be repair or replacement of the AMX Software that does not meet
AMX's Limited Warranty and which is returned to AMX. This Limited Warranty is void if failure of the AMX Software has
resulted from accident, abuse, or misapplication. Any replacement AMX Software will be warranted for the remainder
of the original warranty period or 30 days, whichever is longer. Outside the United States, these remedies may not
available.

NO LIABILITY FOR CONSEQUENTIAL DAMAGES. IN NO EVENT SHALL AMX BE LIABLE FOR ANY DAMAGES
WHATSOEVER (INCLUDING, WITHOUT LIMITATION, DAMAGES FOR LOSS OF BUSINESS PROFITS, BUSINESS
INTERRUPTION, LOSS OF BUSINESS INFORMATION, OR ANY OTHER PECUNIARY LOSS) ARISING OUT OF
THE USE OF OR INABILITY TO USE THIS AMX PRODUCT, EVEN IF AMX HAS BEEN ADVISED OF THE POSSI-
BILITY OF SUCH DAMAGES. BECAUSE SOME STATES/COUNTRIES DO NOT ALLOW THE EXCLUSION OR LIMI-
TATION OF LIABILITY FOR CONSEQUENTIAL OR INCIDENTAL DAMAGES, THE ABOVE LIMITATION MAY NOT
APPLY TO YOU.

If you acquired this product in the United States, this Agreement is governed by the laws of the State of Texas.
Should you have any questions concerning this Agreement, or if you desire to contact AMX for any reason, please
write: AMX Corporation, 3000 Research Drive, Richardson, TX 75082.
Table of Contents

Table of Contents
Architectural Overview ............................................................................................1
The GUI Tier...................................................................................................................... 1
BUTTON_EVENT - Cable.axi .................................................................................................. 1
BUTTON_EVENT - CD.axi ...................................................................................................... 1
BUTTON_EVENT - Display.axi................................................................................................ 1
BUTTON_EVENT - DSS.axi .................................................................................................... 1
BUTTON_EVENT - DVD.axi .................................................................................................... 1
BUTTON_EVENT - Environment.axi ....................................................................................... 1
BUTTON_EVENT - Global.axi ................................................................................................. 1
BUTTON_EVENT - Main Menu.axi.......................................................................................... 1
BUTTON_EVENT - MP3.axi .................................................................................................... 1
BUTTON_EVENT - PVR.axi .................................................................................................... 1
BUTTON_EVENT - Receiver.axi ............................................................................................. 2
BUTTON_EVENT - VCR.axi .................................................................................................... 2
Main Menu.axi.......................................................................................................................... 2
TP.axi ....................................................................................................................................... 2
The Application (Logic) Tier .............................................................................................. 3
Define Constant.axi.................................................................................................................. 3
Define Event.axi ....................................................................................................................... 3
Define Start.axi......................................................................................................................... 3
Define Structure.axi.................................................................................................................. 3
Define Variable.axi ................................................................................................................... 3
Control.axi ................................................................................................................................ 3
ControlLogics.axi...................................................................................................................... 3
Custom.axi ............................................................................................................................... 4
Custom Macro Functions.axi.................................................................................................... 4
Debug.axi ................................................................................................................................. 4
Globals.axi ............................................................................................................................... 4
Macro Engine.axi ..................................................................................................................... 4
Macro Engine Handlers.axi ...................................................................................................... 4
The Data Tier .................................................................................................................... 4
Config.axi ................................................................................................................................. 4
CD List Management.axi.......................................................................................................... 4
DB Access.axi .......................................................................................................................... 4
Anatomy Of a Handler ..............................................................................................5
Overview ........................................................................................................................... 5
DBInitHandler .................................................................................................................... 7

DXP-HT v1.2 - Advanced Programmer’s Guide i


Table of Contents

Duties accomplished by DBInitHandler.................................................................................... 8


Additional notes........................................................................................................................ 9
ControlSourceDevice / ControlDisplayDevice................................................................... 9
Custom Programming ............................................................................................ 11
Guidelines ....................................................................................................................... 11
Method 1 ................................................................................................................................ 11
Method 2 ................................................................................................................................ 11
Advanced Customization ...................................................................................... 15
NetLinx Database Manipulation ...................................................................................... 15
How to create a custom event handler................................................................................... 15
How to take advantage of the custom macro functions. ........................................................ 17
How to create a custom macro sequence within a handler or custom function. .................... 18
How to add a button to the scrolling main menu. ................................................................... 20
How to manually add a source to the NetLinx database........................................................ 21
How to create a custom Control Logic. .................................................................................. 24
Control Logic parameters....................................................................................................... 24
Feedback ............................................................................................................................... 27
TPFdbkON (INTEGER nBtnSet, INTEGER nChan) .............................................................. 27
TPFdbkOFF (INTEGER nBtnSet, INTEGER nChan)............................................................. 27
TPFdbk (INTEGER nBtnSet, INTEGER nChan, INTEGER bState) ...................................... 28
Debugging and Diagnostics .................................................................................. 29
Glossary .................................................................................................................. 31

ii DXP-HT v1.2 - Advanced Programmer’s Guide


Architectural Overview

Architectural Overview
Design XPress Home Theater (DXP-HT) NetLinx code is best viewed as a traditional "3-Tier"
application - the Graphical User Interface (GUI) Tier, the Application (or Logic) Tier, and the Data
Tier.

The GUI Tier


All TPD files should be considered part of the GUI tier.

BUTTON_EVENT - Cable.axi
Handles touch panel interface commands that apply to cable set-top units. While all handlers for the
entire cable receiver command-set are found within this file, the actual logic of what action(s) to
take as a result of each command is contained within Control.axi and ControlLogics.axi. The
handlers themselves are virtually identical except that each one passes the appropriate unique
command identifier into Control.axi. This is true for all BUTTON_EVENT - { Type } files, with the
exception of BUTTON_EVENT - Display.axi, which calls into ControlDisplayDevice instead
of ControlSourceDevice (both ControlSourceDevice and ControlDisplayDevice are
defined within Control.axi).

BUTTON_EVENT - CD.axi
Handles touch panel interface commands that apply to CD players.

BUTTON_EVENT - Display.axi
Handles touch panel interface commands that apply to display devices.

BUTTON_EVENT - DSS.axi
Handles touch panel interface commands that apply to Digital Satellite Systems.

BUTTON_EVENT - DVD.axi
Handles touch panel interface commands that apply to DVD players.

BUTTON_EVENT - Environment.axi
Handles touch panel interface commands that apply to environmental control.

BUTTON_EVENT - Global.axi
Handles global touch panel interface commands.

BUTTON_EVENT - Main Menu.axi


Handles touch panel interface commands that apply to the DXP-HT main menu.

BUTTON_EVENT - MP3.axi
Handles touch panel interface commands that apply to MP3 players.

BUTTON_EVENT - PVR.axi
Handles touch panel interface commands that apply to personal video recorders (PVRs).

DXP-HT v1.2 - Advanced Programmer’s Guide 1


Architectural Overview

BUTTON_EVENT - Receiver.axi
Handles touch panel interface commands that apply to A/V receivers.

BUTTON_EVENT - VCR.axi
Handles touch panel interface commands that apply VCRs.

Main Menu.axi
Governs population and handling of the main menu. Two menu types are available in DXP-HT:

! Scrolling - The structure of the main menu is gleaned dynamically from the database
using the same set of buttons to select any device that is available to the user. The
categories (or families) of devices are defined by the v_rstDevType table and the
members of those categories are defined within the v_rstDisplay and v_rstSource
tables. Note that the prefix "rst" may be read, "Array of Structures". FIG. 1 shows an
example of the Scrolling main menu style:

FIG. 1 Scrolling main menu style

! Static - Up to six parent categories are available at all times: Display, Sources, Lights,
Relays, Macros, About. With the exception of the Sources button, selecting any category
will send the user to the proper popup. If the user selects the Sources category then s/he
will be presented with a popup of static buttons with source names as their labels.
Pressing any of those buttons will send the user to the proper popup and activate the
selected device. Because these buttons are static, they may be copied and pasted
anywhere in the interface (TPD) file. This means that custom pages or popups may be
built with buttons used to activate sources. FIG. 2 shows an example of the Static main
menu style:

FIG. 2 Static main menu style

TP.axi
Functions related to interface feedback and behaviors.

2 DXP-HT v1.2 - Advanced Programmer’s Guide


Architectural Overview

The Application (Logic) Tier


Define Constant.axi
Defines all global constants, which are preceded with c_, followed by appropriate Hungarian
Notation.

Define Event.axi
Handles interface, I/O device, and MP3 Player events (ONLINE, STRING, etc).

Define Start.axi
Miscellaneous startup initializations. The most important steps that occur during startup are the
database queries that define all properties of the system (source count, source properties, number of
interfaces, display device properties, macros, etc).

Define Structure.axi
Defines all structures that are used in DXP-HT. Most of the structures pertain to the database,
which is really just several arrays of structures (all global structures are preceded with "v_rst," to
indicate that they are arrays of structures). The three main structures that constitute the bulk of the
database are v_rstSource, v_rstDisplay, and v_rstInterface. Note that the structures are
defined within this file but they are not actually declared here -- that is a function of _Define
Variable.axi. Refer to The Data Tier section on page 4 for more information regarding the database
structures.

Define Variable.axi
Defines all global variables, which are preceded with "v_," followed by appropriate Hungarian
Notation.

Control.axi
The central point from which all commands are interpreted and acted upon. Almost all handlers
will call into this include file (either ControlSourceDevice or ControlDisplayDevice,
depending on which handler has executed). This include file will determine whether or not a
Control Logic is defined for the device in question, then it will either call the appropriate Control
Logic or else it will determine which IR code to pulse in order to cause the desired behavior. When
determining the correct IR code the IR Map will be referenced, which is a structure containing
unique commands and their corresponding IR codes. All display devices and sources have an IR
map associated with them, although it may not be referenced if the device utilizes a Control Logic.

ControlLogics.axi
Contains all intrinsic DXP-HT Control Logics. A Control Logic is a block of code built to control a
specific device. For example, the behaviors, properties, and protocols of a specific device will be
known by the Control Logic. Control Logics may be modules, SYSTEM_CALLs, or simple NetLinx
code. See How to create a custom Control Logic. section on page 24 for detailed information
regarding Control Logics.

DXP-HT v1.2 - Advanced Programmer’s Guide 3


Architectural Overview

Custom.axi
This file contains no code. It is intended for use by the dealer when customizing the system.

Custom Macro Functions.axi


This file contains 32 "stubbed-off" macro functions. These may be used by the dealer when
customizing the system, in conjunction with the Macro Engine. See the How to take advantage of
the custom macro functions. section on page 17 for information regarding the Macro Engine.

Debug.axi
Strictly for debugging via Telnet or HyperTerminal. Prints debugging and diagnostics for use when
troubleshooting the system. Refer to the Debugging and Diagnostics section on page 29 for more
information.

Globals.axi
"Catch all" for all functions that are not easily categorized into one of the existing include files.
This include file handles those commands that apply to multiple categories (such as the discrete
channel list which may apply to both the display device and the VCR).

Macro Engine.axi
The core code that drives the Macro Engine. The Macro Engine allows sequences of unique
commands to execute on a timeline while retaining namespace for all required parameters.

Macro Engine Handlers.axi


A "sub-include" of Macro Engine.axi. In this file are all the handlers that should execute whenever
a macro item is ready to launch. See the How to create a custom macro sequence within a handler
or custom function. section on page 18 for more information.

The Data Tier


Config.axi
The NetLinx "database" that defines the system properties and behaviors. Config.axi defines
properties for sources, display devices, interfaces, macros, and discrete channel presets. This is one
of two files (the other being Main.AXS) that the DXP-HT Wizard generates upon project
completion.

CD List Management.axi
Reads the CD List from the D.O.C. and displays it for the user. Also handles many functions of the
CD List such as sorting, scrolling, Add, Edit, Delete, etc.

DB Access.axi
Functions regarding database access (i.e., the arrays of structures that are initialized in Config.axi).
This file serves as a level of abstraction between the "Application Tier" and the "Data Tier." For the
most part, a NetLinx programmer need understand only a few of the functions that are available
within this file in order to gain access to any part of the database.

4 DXP-HT v1.2 - Advanced Programmer’s Guide


Anatomy Of a Handler

Anatomy Of a Handler
Overview
The mechanism by which all interface button pushes are handled is the NetLinx BUTTON_EVENT
handler. No PUSHes or RELEASEs are handled via Mainline.
Each button will have a corresponding BUTTON_EVENT in a related file. The channel names will
typically be indicative of the button's nature. For example, the DVD Player "Play" button can be
found within the file BUTTON_EVENT - DVD.axi.
The handler is: BUTTON_EVENT[dvTP, c_btnDVDPlay].
Some handlers include stacked BUTTON_EVENTs of related functionality, such as transport
control. This is also evident with the DVD "Play" button handler, which looks like this:
BUTTON_EVENT[dvTP, c_btnDVDPlay]
BUTTON_EVENT[dvTP, c_btnDVDStop]
BUTTON_EVENT[dvTP, c_btnDVDPause]
BUTTON_EVENT[dvTP, c_btnDVDFF]
BUTTON_EVENT[dvTP, c_btnDVDRew]
BUTTON_EVENT[dvTP, c_btnDVDSkipRev]
BUTTON_EVENT[dvTP, c_btnDVDSkipFwd]
{
...body of handler...
}
The body of most handlers is almost identical, with the exception of some parameters that are
passed into the functions that query the database and act upon the devices. The exceptions are the
"Power" handlers, which are similar to all other handlers except that they call into a different
function in order to act upon the device. This is due to the special needs of the power management
capability.
Following is an example of a simple handler:
// Handle DVD ENTER command:
BUTTON_EVENT[dvTP, c_btnDVDEnter]
{
PUSH :
{
STACK_VAR INTEGER nSrcIdx // Index into source table
STACK_VAR INTEGER nTPDBIdx // Index into interface table

// Acquire interface and active source properties:


IF (DBInitHandler (nSrcIdx,
nTPDBIdx,
c_nDVD,
c_nPush,
c_nHandleFdbk))
{
// Now control the active source, if applicable:
ControlSourceDevice (nSrcIdx,
nTPDBIdx,
c_nEnter,
v_stR, // Empty route placeholder
v_stP, // Empty param placeholder
c_nPush)

DXP-HT v1.2 - Advanced Programmer’s Guide 5


Anatomy Of a Handler

}
}
RELEASE :
{
STACK_VAR INTEGER nSrcIdx // Index into source table
STACK_VAR INTEGER nTPDBIdx // Index into interface table

// Acquire interface and active source properties:


IF (DBInitHandler (nSrcIdx,
nTPDBIdx,
c_nDVD,
c_nRelease,
c_nHandleFdbk))
{
// Now control the active source, if applicable:
ControlSourceDevice (nSrcIdx,
nTPDBIdx,
c_nEnter,
v_stR, // Empty route placeholder
v_stP, // Empty param placeholder
c_nRelease)
}
}
}
The process whereby an event is received and acted upon can seem somewhat mysterious at first
glance. How is it that two function calls, DBInitHandler and ControlSourceDevice, can drive
almost all of the functionality within the system?

! The first function call, DBInitHandler (found in DB Access.axi), queries the NetLinx
database (found in Config.axi) to determine which source is currently active to the
interface from which the event was received. This query also acquires the pertinent
properties of the device. The DBInitHandler function is described in greater detail in the
DBInitHandler section on page 7.

! The second function call, ControlSourceDevice (or ControlDisplayDevice, depending on


the event type), determines how the active device should be controlled, then acts upon it
via the proper mechanism (IR, string, command, or relay ON/OFF).
ControlSourceDevice is described in greater detail in the ControlSourceDevice /
ControlDisplayDevice section on page 9.
One might also ask, "Why is DXP-HT architected in this manner? Why not simply pulse the proper
IR channel from within the handler itself?"

! In order to employ a consistent mechanism for control of all device types, DXP-HT does
not typically act directly upon a device from within the handler. This is because the goal
is to allow you leverage to choose your own devices, rather than dictating which devices
DXP-HT will support. If we were to build DXP-HT around specific make and models
then we could act directly upon them within the handlers. However, as we do not
necessarily know the control mechanism required to control your selected set of devices,
we instead save all necessary device properties within the NetLinx database (Config.axi)
and acquire those properties when the handlers are executed. This allows us to determine
how to control a device and potentially employs special logic that may be required to
control your devices.

6 DXP-HT v1.2 - Advanced Programmer’s Guide


Anatomy Of a Handler

! Another reason for the database-driven architecture is to allow you to use your IR files
without worrying about the channel locations for the various functions. Instead of forcing
you to place functions in particular slots within the IR files, we allow you to tell us how
your files are mapped. Support of this functionality requires that your IR mappings be
saved in a database and looked up by the handlers.

! While it would be possible to simplify the handlers by only looking up IR mappings and
then pulsing the proper IR code directly from within the handler, that would not suffice
for RS-232 controlled devices. So the argument could be made, why not simply pulse IR
or send strings directly from within the handlers? While this may seem simpler, it would
greatly complicate the handlers since we would have to embed all of the logic to
determine what strings to send, what special logic may be required, etc. Instead of
attempting to handle the endless permutations that inevitably surface in custom home
theaters, we have built a standard mechanism that is employed by almost all handlers. In
our model, the "nuts and bolts" of acting upon the devices are then driven by two
centralized functions: ControlSourceDevice and ControlDisplayDevice (found in
Control.axi).

! ControlSourceDevice and ControlDisplayDevice may reference the IR Map and control


the device accordingly, or they may pass the functions into a Control Logic. See the How
to create a custom Control Logic. section on page 24 for more information regarding
Control Logics.

! Building all handlers in a consistent manner allows us to determine which events apply to
which devices by altering the database instead of the source code. For example, if a user
presses a button with channel code 1 on touch panel device 128, it may cause two
handlers to execute. One may query the database and find that [128:1:0,1] does not apply
to it, since the "Device Used" level does not apply to it. However, another handler may
perform the same query and discover that the event does apply to it, and it can then
proceed with the handler. This allows consistency across handlers for all device types and
it allows us to simply reference the one master interface DevSet, dvTP, which is written
out by the Wizard in Main.axs, rather than attempting to maintain several different
DevSets for each device type.

DBInitHandler
Following is a list of the parameters received by DBInitHandler:

INTEGER nIdx An INTEGER STACK_VAR passed by reference. This param-


eter is zero when it is passed in. If applicable, the nIdx param-
eter will be initialized to the index into the Source or Display
table to which the event applies. This will cause the value of
the variable that was passed in to change within the handler
itself. If the "Device Used" level from which the event was
received does not correlate to the device type that was
passed in (see section 2.2.1.3), then this parameter will not
be initialized within DBInitHandler.

DXP-HT v1.2 - Advanced Programmer’s Guide 7


Anatomy Of a Handler

INTEGER nTPDBIdx An INTEGER STACK_VAR passed by reference. This parame-


ter is zero when it is passed in. If applicable, the nTPDBIdx
parameter will be initialized to the index into the Interface
table that corresponds to the touch panel that sent the event.
This will cause the value of the variable that was passed in to
change within the handler itself. If the "Device Used" level
from which the event was received does not correlate to the
device type that was passed in (see section 2.2.1.3), then this
parameter will not be initialized within DBInitHandler.
INTEGER nType A unique identifier that indicates the nature of the handler that
has executed. This parameter will be set equal to one of the
following constants: c_nDVD, c_nVCR, c_nCD, c_nMP3,
c_nRELAY, c_nPVR, c_nDSS, c_nCABLE, c_nLIGHT,
c_nTUNER, c_nRCVR, or c_nVolume.
INTEGER bPush A non-zero value will be passed in for this parameter on the
PUSH event. A zero value will be passed in for this parameter
on the RELEASE event. DBInitHandler will utilize this to
determine whether feedback should be turned ON or OFF, if
applicable.
INTEGER bFdbk This parameter will always be set to one of the following con-
stants: c_nHandleFdbk or c_nNoFdbk. If the parameter is
set to c_nHandleFdbk, DBInitHandler will call into
TPHandleFdbk (found in TP.axi), which will, in turn, emulate
momentary feedback, unless feedback capabilities have been
overridden for the device in question. If the parameter is set to
c_nNoFdbk, DBInitHandler will not even attempt to han-
dle feedback.

Duties accomplished by DBInitHandler

! Queries the database to determine whether the "Device Used" level for the device type in
question is equal to the "Device Used" level from which the event was received.

! Outputs debugging and diagnostics to the Telnet or Terminal client (see the Debugging
and Diagnostics section on page 29).

! Determines which device is currently "active". In other words, determines which device
the user previously selected from the main menu, so that we will be sure to control the
device that the user intends to control.

! Ensures that the interface is not locked. Some actions require a short time-out during
which interface events should be ignored. DBInitHandler provides this capability since
all standard handlers call into it.

! Automatically handles feedback for the event, if applicable (see the


DBInitHandler section on page 7).

! Determines whether the calling handler should fall through (i.e., do nothing) or rather
control the active device to which the handler applies. If the button channel code is found
to be on the same "Device Used" level as the device type parameter that was passed in
(parameter #3 - nType), and if nIdx and nTPDBIdx are properly initialized (see the
DBInitHandler section on page 7), DBInitHandler will return a non-zero value.
Otherwise, it will return zero and the handler will fall through. For example, if the button
"Device Used" level is 2, and if the third parameter passed into DBInitHandler is
c_nDVD, the handler will return a non-zero value, because c_nDVDSetIdx is 2 in
_Define Constant.axi. On the other hand, if the third parameter was c_nCD, which

8 DXP-HT v1.2 - Advanced Programmer’s Guide


Anatomy Of a Handler

utilizes buttons on "Device Used" level 3 of the touch panel, DBInitHandler would
return 0.

Additional notes

! The "Device Used" levels for all device types are stored in the Device Types table in
Config.axi (v_rstDevType). DBInitHandler calls into DBGetDeviceTypeIndex and
passes in the unique identifier from the handler (c_nDVD, c_nVCR, etc.).
DBGetDeviceTypeIndex returns the index into the v_rstDevType table that
corresponds to the device type. We are then able to determine what the "Device Used"
level is, and consequently we can know whether the event applies to the handler or not.

! The centralized DBInitHandler function allows handling of feedback according to the


properties of the device to be controlled. Some devices may only utilize momentary
feedback (PUSH ON; RELEASE OFF) while others may echo the true state of the device.
Also, some devices may emulate feedback. By default, DBInitHandler takes care of
momentary feedback for most devices. However, feedback may be overridden and
handled within the BUTTON_EVENT or by the Control Logic. See the How to create a
custom Control Logic. section on page 24 for more information regarding the handling of
feedback.

ControlSourceDevice / ControlDisplayDevice
ControlSourceDevice and ControlDisplayDevice are very similar in nature. The parameters that
they receive vary only slightly. The main difference between these two functions is that one queries
against the Source table and the other queries against the Display table in Config.axi.
The following table lists the parameters received by ControlSourceDevice:

INTEGER nSrcDBIdx Index into the Source table that applies to the device in ques-
tion.
INTEGER nTPDBIdx Index into the Interface table that applies to the interface that
sent the control event.
INTEGER nFunc A unique identifier corresponding to the selected function.
stRoute stXPoints An stRoute structure containing crosspoint information. For
any device other than receivers or routers this value will
always contain zeroes for all members (passed as
v_stBlankRoute). It may or may not contain non-zero values
for receivers. It must contain non-zero values for switchers.
See the Define Structure.axi section on page 3 for a list of the
members contained within it.
stPmtrs stParams A "generic" structure that can be used to pass parameters
into this function. See the Define Structure.axi section on
page 3 for a list of the members contained within it.
INTEGER bPush Indicates whether the function has been invoked as the result
of a PUSH or RELEASE. If true then it applies to a PUSH; if
false then it is a RELEASE.
INTEGER nTVDBIdx Index into the Display table that applies to the device in ques-
tion.
INTEGER nTPDBIdx Index into the Interface table that applies to the interface that
sent the control event.
INTEGER nFunc A unique identifier corresponding to the selected function.

DXP-HT v1.2 - Advanced Programmer’s Guide 9


Anatomy Of a Handler

stPmtrs stParams A "generic" structure that can be used to pass parameters


into this function. See the definition of this structure in _Define
Structure.axi for a list of the members contained within it.
INTEGER bPush Indicates whether the function has been invoked as the result
of a PUSH or RELEASE. If true then it applies to a PUSH; if
false then it is a RELEASE.

The following table lists the parameters received by ControlDisplayDevice:

INTEGER nTVDBIdx Index into the Display table that applies to the device in ques-
tion.
INTEGER nTPDBIdx Index into the Interface table that applies to the interface that
sent the control event.
INTEGER nFunc A unique identifier corresponding to the selected function.
stPmtrs stParams A "generic" structure that can be used to pass parameters
into this function. See the Define Structure.axi section on
page 3 for a list of the members contained within it.
INTEGER bPush Indicates whether the function has been invoked as the result
of a PUSH or RELEASE. If true then it applies to a PUSH; if
false then it is a RELEASE.

The duties accomplished by ControlSourceDevice and ControlDisplayDevice include:

! Determines whether or not the device to be controlled has a Control Logic associated
with it (as determined by its nCtrlLogic member that is initialized within Config.axi). If
so, calls into the proper Control Logic. Otherwise, proceeds with the following...

! Provides special handling for tuning of discrete channel presets.

! Provides special handling for tuning of Surround Sound presets.

! Provides special handling for power management.

! Queries the IR Map and sends IR to sources, if applicable.

10 DXP-HT v1.2 - Advanced Programmer’s Guide


Custom Programming

Custom Programming
Guidelines
Modification of any file other than Custom.axi or Custom Macro Functions.axi is highly
discouraged because DXP-HT will overwrite all other files when the project is regenerated. For
advanced users that choose to modify the core NetLinx engine, the preferred method is to build the
project to the extent that it can be completed via the Wizard. Then, after generating code, copy the
interfaces and the source code from the project directory to another directory that is not utilized by
the DXP-HT Project Wizard. Thereafter, implement all modifications using the new working
directory.
If possible, all customization should be accomplished within the files Custom.axi or Custom Macro
Functions.axi. The DXP-HT Wizard will not overwrite these files during project generation. Any
site-specific customization that cannot be accomplished within Custom.axi should be developed
using the method described above.
The importance of careful attention to the location of your source code cannot be overstated. If you
generate a project and then use the DXP-HT working directory as the location for your custom
modifications (other than those implemented within Custom.axi or Custom Macro Functions.axi),
you run the risk of accidentally overwriting your hard work whenever the project is regenerated.
This principle also applies to the touch panel interface files (TPDs).
The easiest and most familiar way to add customization to a facility is via traditional NetLinx code,
or via the customization tools that DXP-HT provides.

Method 1
Manually create a button, preferably on Device #4 of the touch panel interface. Then create a
handler for that button in Custom.axi (the handler must be preceded with a DEFINE_EVENT section
identifier). For example, if you create a button on Device #4 having channel ID 100, and you want
that button to pulse IR slot 5 on NetLinx card 10 at port 2, the handler might look like this (the
following assumes the facility utilizes three interfaces starting at AMX Device ID 128):
BUTTON_EVENT [131:1:0, 100] // Button on "Device Used" 4
BUTTON_EVENT [135:1:0, 100] // Button on "Device Used" 4
BUTTON_EVENT [139:1:0, 100] // Button on "Device Used" 4
{
PUSH :
{
PULSE [10:2:0, 5]
}
}

Method 2
Create a PULSE macro via the Wizard and assign it to a button on the Macros page. Then, using
TPDesign3 or TPDesing4, copy that button from the macros page and paste it onto the appropriate
page. See the How to take advantage of the custom macro functions. section on page 17 for more
information regarding the Macro Engine.
Adding NetLinx handler functionality while maintaining the integrity of the architecture is
somewhat more complicated. However, in the example from Method 1, the difficulty is not extreme.

DXP-HT v1.2 - Advanced Programmer’s Guide 11


Custom Programming

Following are the steps of how one would accomplish the same goal without abandoning the
database-driven architecture of DXP-HT:

! Open the file that controls the device for which you are adding a button. Let's assume
we're adding a button to the DVD control page. We would open the file BUTTON_EVENT
- DVD.axi.

! Find an existing handler. Note that some handlers include stacked events with
SELECT…CASE statements within them. Such handlers would not be desirable for this
example. The "Enter" command is a good example of a simple command handler.
Following is the code snippet for the "Enter" handler:
// Handle DVD ENTER command:
BUTTON_EVENT[dvTP, c_btnDVDEnter]
{
PUSH :
{
STACK_VAR INTEGER nSrcIdx
STACK_VAR INTEGER nTPDBIdx

// Acquire interface and active source properties:


IF (DBInitHandler (nSrcIdx,
nTPDBIdx,
c_nDVD,
c_nPush,
c_nHandleFdbk))
{
// Now control the active source, if applicable:
ControlSourceDevice (nSrcIdx,
nTPDBIdx,
c_nEnter,
v_stR,
v_stP,
c_nPush)
}
}
RELEASE :
{
STACK_VAR INTEGER nSrcIdx
STACK_VAR INTEGER nTPDBIdx

// Acquire interface and active source properties:


IF (DBInitHandler (nSrcIdx,
nTPDBIdx,
c_nDVD,
c_nPush,
c_nHandleFdbk))
{
// Now control the active source, if applicable:
ControlSourceDevice (nSrcIdx,
nTPDBIdx,
c_nEnter,
v_stR,
v_stP,
c_nRelease)
}
}

12 DXP-HT v1.2 - Advanced Programmer’s Guide


Custom Programming

! Copy the above handler and paste it into Custom.axi, immediately after the
DEFINE_EVENT section identifier (which must be added manually).

! Change the channel (c_btnDVDEnter) to the channel ID that you need to handle. You
may hard code it or you may create a constant in Main.AXS (or _Define Constants.axi).

! In the body of the handler, replace the unique command ID (c_nEnter) with your own
unique command ID. This must be done in both the PUSH and RELEASE sections of the
handler.

! If your command is not already defined in _Define Constants.axi then you will need to
create a new one. The value of the command ID is irrelevant except that it must be
unique. Therefore, if you create your own command ID, it is recommended that it be
initialized at 1000 or larger, to ensure that it is out of range of the unique command
identifiers that are used by DXP-HT.

! If your command is already defined, and if your DVD player is IR controlled, you are
done. The handler will call into ControlSourceDevice and pass the unique ID, which will
be referenced against the IR Map. Assuming the IR code has been properly mapped via
the Wizard, IR will be pulsed when the event is received.
If you created a new command ID (such as c_nAspect, for example), and if your device is
controlled via IR, then you will need to add that handler to the IR map. This may be accomplished
by adding a new member to the stIRMap structure within _Define Structure.axi, then initializing
that member within the DEFINE_START section of Custom.axi. If your device is controlled via
RS-232, Ethernet, or Relay, then you will need to add handling of your unique ID to the device's
Control Logic, or create a new Control Logic geared towards your device. See the How to create a
custom Control Logic. section on page 24 for instructions on creating new Control Logics.

DXP-HT v1.2 - Advanced Programmer’s Guide 13


Custom Programming

14 DXP-HT v1.2 - Advanced Programmer’s Guide


Advanced Customization

Advanced Customization
NetLinx Database Manipulation
For advanced programmers, more complex customization may be accomplished while remaining
true to the architecture of DXP-HT NetLinx. Because all source code that is generated by the
Wizard is open for modifications, careful study of the overall architecture and a full understanding
of the database-driven model can unlock the true power of the DXP-HT application.
Properties for all interfaces are stored in the Interface table (v_rstInterface). Note that the
prefix "rst" should be read, "Array of Structures". Some members of the interface structure are
initialized in Config.axi by the Wizard. Others are internal to NetLinx. Custom members may be
added to the interface database by defining them within the stInterface structure within
_Define Structure.axi.
Properties for all sources are stored in the Source table (v_rstSource). Much like the Interface
table, some members of the source structure are initialized in Config.axi by the Wizard while others
are internal to NetLinx. Adding members to the Source database may be accomplished by defining
them within the stSource structure within _Define Structure.axi.
Properties for all display devices are stored in the Display table (v_rstDisplay). Just as with
interfaces and sources, some members of the display device structure are initialized in Config.axi
by the Wizard while others are internal to NetLinx. Adding members to the Display database may
be accomplished by defining them within the stDisplay structure within _Define Structure.axi.
The device categories (or families) are stored in the Device Types table (v_rstDevType). Most
members of this table are written by the Wizard but a few are defined during startup as the facility
configuration is gleaned from the Display and Source databases. New device categories may be
added to DXP-HT by adding them to this database. For example, if a facility called for the inclusion
of a Laser Disc Player, which is not supported by default, a new record could be added to this table
to define the category, then a Laser Disc Player could be added to the source table as a member of
the new category. See the How to manually add a source to the NetLinx database. section on
page 21 for step-by-step instructions on adding unsupported devices.
Macros are stored in the Macros database (v_rstMacroSeq). See the How to create a custom event
handler. section on page 15 for step-by-step instructions regarding manual macro creation.

How to create a custom event handler.


The simplest way to create a simple PUSH & PULSE handler is by creating a 1-step macro in the
Wizard. This method will require no custom NetLinx code. Accomplishing this via the Wizard is a
simple matter. However, you may also create your 1-step macro via manual manipulation of the
NetLinx database (Config.axi).
If you choose to create your macro manually via NetLinx database manipulation, follow these steps
(don't forget that Config.axi will be overwritten if you regenerate your project; it is important to do
this in a safe directory that is untouched by DXP-HT). The following instructions are geared
towards a hypothetical situation whereby the need is to create a custom macro that will pulse IR to
a device:

DXP-HT v1.2 - Advanced Programmer’s Guide 15


Advanced Customization

If the Source database in Config.axi (v_rstSource) does not contain a source of type c_nMacro
then you must create one. If a source of type c_nMacro already exists, skip to step 4. Otherwise,
follow these steps to create a new Macro "source":
1. First, locate the About "source," which should be the last index of the Source database.
Immediately before the section pertaining to the About source, paste the following three lines
of source code:
// Macro "source"
v_rstSource[20].strName = "'Macros'"
v_rstSource[20].nSourceType = c_nMacro
Ensure that the subscript is the next in line. For instance, make the Macro "source" subscript
(20 in this example) the subscript of the About "source," then increment the About source's
subscript by one (since it should always be the last "source").
2. Next, increase the CfgDefineSources() return value by one. The RETURN statement
immediately follows the initialization of the About "source." The subscript on the About
"source" and the return value should be identical.
3. Finally, in Main.AXS, increase the value of c_nMaxSources by one. You have now created a
new "macro source" that will appear on the main menu of the touch panel.
4. Now you are ready to create your macro. In the function cfgDefineMacros(), increase the
return value by one. Then paste the following block into the function immediately above the
RETURN statement:
v_rstMacroSeq[x].stStep[1].dvID = y:y:y
v_rstMacroSeq[x].stStep[1].nActionID = c_qPulse
v_rstMacroSeq[x].stStep[1].stParam.nParam1 = z
…where…

! x = the next available index (will be 1 if no other macros exist), and

! y:y:y = the D:P:S device ID of the card that should pulse, and

! z = the channel to pulse.


5. Now, you should go back into Main.AXS to add or alter two constants: c_nMaxMacros and
c_nMaxMacroSteps. If these constants have already been created, you will need to increase
c_nMaxMacros by one. Also, make c_nMaxMacroSteps equal to the largest subscript of
your macro step (stStep). If neither c_nMaxMacros nor c_nMaxMacroSteps have been
created, you will need to create them in the DEFINE_CONSTANT section. Set c_nMaxMacros
equal to the number of macros you created (the largest subscript of v_rstMacroSeq) and set
c_nMaxMacroSteps equal to the longest macro you created (the largest subscript of stStep)
6. Create a button in the TPD file to launch your macro. The macro button ranges are from 220
through 251 on Touch Panel device 2. The Wizard will delete any unused buttons. Therefore,
on the "Macros" or "Macros2" page of the touch panel, determine the ID of the last button on
the page, then create a new button and assign it the next incremental channel code. If you find
that all 32 macro buttons exist in the panel file, create a new button and assign an unused
channel code to it (be sure to keep your new button on Device Used 2). Then, add that new
button to c_btnMacroSet in _Define Constant.axi.
7. Note that the unique Action ID for the custom step (c_qPulse) that we've created is already
defined in the core NetLinx code. You may also create your own Action IDs that are outside

16 DXP-HT v1.2 - Advanced Programmer’s Guide


Advanced Customization

the range of those already defined within _Define Constant.axi. It is recommended that the
naming convention be followed where "c_" indicates that the value is a constant and "q"
indicates it is a "Queue Action ID." Be sure to define your custom constant outside the range of
those that exist in the core NetLinx code. After creating your custom Action ID, it must be
handled in Macro Engine Handlers.axi. Be careful to save any modifications to Macro Engine
Handlers.axi within a separate working directory, as DXP-HT will overwrite this file any time
you regenerate your project. See the NetLinx Database Manipulation section on page 15 for
more information regarding Action IDs.

How to take advantage of the custom macro functions.


DXP-HT includes 32 "stubbed off" macro functions in the file Custom Macro Fuctions.axi. This
file will remain untouched by DXP-HT after the initial install, much like Custom.axi. Therefore,
you may place any custom code within the 32 custom macro functions that is necessary to drive the
special needs of the facility that you are targeting.
After placing code within your custom macro handlers, macro steps must be created via the Wizard
that call into the custom handlers, as follows:

Custom macro handler #1

Custom macro handler #2

FIG. 3 Creating Macro Steps in the DXP-HT Wizard

The example macro shown in FIG. 3 will be assigned to one of the 32 custom macro buttons on the
interface. Upon project generation, the Wizard will name the button "Movie Mode". When the user
presses the "Movie Mode" button, the Macro Engine will immediately execute the first step, which
is to lower the screen. Immediately after lowering the screen, your custom code within
CustomMacroFunction01 (), which is in the file Custom Macro Handlers.axi, will execute.
Next, the display device will turn ON, then a 5-second wait will transpire. Then, your custom code
within CustomMacroFunction02 () will execute. The Macro Engine will proceed to complete
steps 6, 7, and 8.

DXP-HT v1.2 - Advanced Programmer’s Guide 17


Advanced Customization

It should be noted that each of the 32 custom macro functions can call other custom functions that
you develop. Also, if need be, nested macros may be included within the custom macro functions.
See the following section for more information regarding programmatic use of the Macro Engine.

How to create a custom macro sequence within a handler or custom function.


The mechanism used by the Wizard to execute macros can also be implemented manually via
NetLinx code. Manual creation of a macro sequence requires a unique Action ID, handling of the
Action ID within Macro Engine Handlers.axi, and "instantiation" of the macro in your custom
handler or function. Note that you may programmatically create a macro either by manipulating the
Macros table in Config.axi (see the How to create a custom event handler. section on page 15) or by
calling into the Macro Engine directly from within your handler or function. The steps to
programmatically utilize the Macro Engine are described in detail below:
1. Create a unique Action ID.

! The Action ID is a unique identifier used by the Macro Engine to determine which block
of code to execute. The value of the Action ID is irrelevant, but it must be unique.

! By convention, Action IDs are prefixed with "c_q". The "c_" indicates that the value is a
constant and the "q" indicates that it is a Queue Action ID.

! Several Action IDs exist already within _Define Constants.axi. Be sure to define your
Action ID such that it does not conflict with any existing Action IDs. It is recommended
that your custom Action IDs start at 500+. To see those Action IDs that exist within the
core NetLinx code, open _Define Constants.axi and search on "c_q".

! It is recommended that your custom Action IDs be defined within the


DEFINE_CONSTANT section of Custom.axi. If you choose to define your custom Action
IDs within _Define Constant.axi, be sure to make your changes in a safe working
directory (i.e., one that is unused by the Wizard). Otherwise, the Wizard will overwrite
your customization whenever your project is regenerated.
2. Handle the unique Action ID within Macro Engine Handlers.axi.

! Macro Engine Handlers.axi contains a SWITCH...CASE statement with handlers for all
Queue Action IDs. You will need to create your own branch of the SWITCH...CASE. Note
that Macro Engine Handlers.axi is another core DXP-HT file that will be overwritten any
time you regenerate your project. Therefore, any modifications to this file imply that your
code must be saved to a working directory that is untouched by the Wizard.

! The parameters for the Macro Engine include a "generic" structure that can be used to
pass in values to be retrieved when the Action ID is handled. Retrieval of any value from
the parameter list implies a contact between the caller and the handler. For example, if we
retrieve any value from the parameter list then we must also ensure that we have passed
that value in when we "instantiated" the macro. Passing parameters into the Macro
Engine is described further in the next section.
The following table lists the parameters that may be retrieved when the Action ID is handled within
Macro Engine Handlers.axi:

• ? v_rstQ[v_lSeqPtr].stParam.nIdx The index into the Source or Display tables


to which the Action ID applies.

18 DXP-HT v1.2 - Advanced Programmer’s Guide


Advanced Customization

• ? v_rstQ[v_lSeqPtr].stParam.nType A unique identifier that indicates whether


we should de-reference the Source or Dis-
play table. This value should always be ini-
tialized to either c_nSource or
c_nDisplay.
• ? v_rstQ[v_lSeqPtr].stParam.nParam1 An integer value for general use.
• ? v_rstQ[v_lSeqPtr].stParam.nParam2 An integer value for general use.
• ? v_rstQ[v_lSeqPtr].stParam.nParam3 An integer value for general use.
• ? v_rstQ[v_lSeqPtr].stParam.nParam4 An integer value for general use.
• ? v_rstQ[v_lSeqPtr].stParam.strString A string value for general use.

Additional parameters for general use may be added to the Macro Engine via
additions to the stMacroParam structure in _Define Structure.axi.

3. Create the macro sequence.

! Any macro sequence requires creation of an Instance with as many steps as necessary (up
to c_nMaxMacroSteps).

! A macro instance is initiated via the c_nBeginInstance constant and it is terminated


via the c_nEndInstance constant.

! Following is an example of creation of a 1-step macro that will simply pulse an IR code
(note that c_qPulse is predefined in the turnkey DXP-HT NetLinx code):
STACK_VAR stMacroParam stMP // Macro parameters

AddMacroItem (0:0:0, // N/A for BeginInstance


0, // N/A for BeginInstance
0, // Wait time
c_qBeginInstance, // Initiate instance
v_stMP) // Empty placeholder

v_stMP.nParam1 = 5 // Channel to PULSE

AddMacroItem (5001:1:0, // Device to PULSE


c_qPulse, // Action ID
0, // Wait time
c_qBeginInstance, // Initiate instance
stMP) // Incl. channel to PULSE

AddMacroItem (0:0:0, // N/A for EndInstance


0, // N/A for EndInstance
0, // Wait time
c_qEndInstance, // End instance
v_stMP) // Empty placeholder
The example shown above will simply pulse an IR code. While it will work fine, it does
include some unnecessary code, because the Action ID could have been combined with
the initial instance creation. If we expand our needs to send three pulses with waits in
between, and combine the instance initializations with the Action IDs, the macro calls
would look like this instead:
STACK_VAR stMacroParam stMP // Macro parameters

DXP-HT v1.2 - Advanced Programmer’s Guide 19


Advanced Customization

v_stMP.nParam1 = 5 // 1st Channel to PULSE

AddMacroItem (5001:1:0, // Device to PULSE


c_qPulse, // Action ID
10, // Wait time of 1 second
c_qBeginInstance, // Initiate instance
stMP) // Incl. channel to PULSE

v_stMP.nParam1 = 10 // 2nd Channel to PULSE

AddMacroItem (5001:1:0, // Device to PULSE


c_qPulse, // Action ID
20, // Wait time of 2 seconds
c_qBeginInstance, // Initiate instance
stMP) // Incl. channel to PULSE

v_stMP.nParam1 = 15 // 3rd Channel to PULSE

AddMacroItem (5001:1:0, // Device to PULSE


c_qPulse, // Action ID
0, // Wait time (none)
c_qEndInstance, // End instance
v_stMP) // Empty placeholder

How to add a button to the scrolling main menu.


The scrolling main menu buttons that are available to the users are gleaned from two tables: the
Device Types table (v_rstDevType) and the Sources table (v_rstSource). Both of these tables
can be found in Config.axi.
The Device Types table constitutes the list of device categories (or families). It could be considered
a "parent" to the Source table. For any category to be available on the scrolling main menu, it must
first be defined within the Device Types table and it must have at least one member from the Source
table.
By default, DXP-HT supports the following device types:

• Two Display Devices


• One Receiver
• One AM/FM Tuner
• Multiple DSS Receivers
• Multiple DVD Players
• Multiple Video Cassette Recorders (VCRs)
• Multiple CD Players
• Multiple MP3 Servers
• Multiple Personal Video Recorders (PVRs)
• Multiple set-top Cable Receivers
• Three relay controlled devices

Additional device categories may be added by duplicating an existing type and incrementing the
index:
1. Copy an existing set from the Device Types table (v_rstDevType) and paste it to the end of
the CfgDefineDeviceTypes() function.

20 DXP-HT v1.2 - Advanced Programmer’s Guide


Advanced Customization

2. Increment each index of the new section by one.


3. Increment the function return value by one.
4. In Main.AXS, increment the constant c_nMaxDeviceTypes by one.
Populate each member of the new section according to the member definitions described below:

strName (CHAR[ ]) The device description (ex: "DVD Player").


strLabel (CHAR[ ]) The device label that should be displayed on the main menu
(ex: "DVD").
nIconID (INT) The device type category icon ID from the TPD file (1-255).
strBitmap (CHAR[ ] ) The device type category bitmap from the TPD file. This is the
bitmap that will display on the Active Device Button whenever
the device type category is selected from the main menu (ex:
"dvd.bmp").
strPopup (CHAR[ ] ) The name of the popup that controls this device type (ex:
"DVD"), if applicable.
strPage (CHAR[ ] ) The name of the page that controls this device type (ex:
"HELP-ABOUT"), if applicable.
nType(INT) A unique identifier that indicates whether the device type
applies to a display device or a source. Available constants
are c_nDisplay and c_nSource.
nTypeID (INT) A unique identifier that indicates the device type family. Avail-
able constants are: c_nDVD, c_nVCR, c_nCD, c_nMP3,
c_nRelay, c_nPVR, c_nDSS, c_nCable, c_nLIGHT,
c_nTuner, c_nRcvr, c_nVolume, c_nAbout,
c_nMacro, and c_nTV.
nDeviceUsed(INT) The "Device Used" level of the buttons that correspond to this
device type. Available constants are: c_nRCVRSetIdx,
c_nTUNRSetIdx, c_nDVDSetIdx, c_nVCRSetIdx,
c_nMP3SetIdx, c_nTVSetIdx, c_nTV2SetIdx,
c_nCDSetIdx, c_nENVIRSetIdx, c_nRELAYSetIdx,
c_nMENUSetIdx, c_nPVRSetIdx, c_nDSSSetIdx,
c_nCableSetIdx, c_nLightSetIdx,
c_nDebugSetIdx, c_nMacroSetIdx.
stPwr.nPwrChan (INT) The interface power button channel number for this device.

5. After following the steps above, you must create a source or display device that falls within the
new device type category. See the following section for instructions on manually adding
sources to the NetLinx database.

How to manually add a source to the NetLinx database.


Before adding a source, ensure that it falls within a category that DXP-HT supports. By default,
DXP-HT supports the following device types::

• Two Display Devices


• One Receiver
• One AM/FM Tuner
• Multiple DSS Receivers
• Multiple DVD Players
• Multiple Video Cassette Recorders (VCRs)
• Multiple CD Players
• Multiple MP3 Servers

DXP-HT v1.2 - Advanced Programmer’s Guide 21


Advanced Customization

• Multiple Personal Video Recorders (PVRs)


• Multiple set-top Cable Receivers
• Three relay controlled devices

If your source does not fall within this category, refer to section 4.5 for instructions about creating
your own device category (or family).
Assuming the source that you are adding falls into an existing or newly created category, follow
these steps to add it to the NetLinx database:
1. In Config.axi, find the CfgDefineSources() function. Scroll down to the end of the function
until you reach the About "source." Increase the index of the About "source" by one (i.e., if it
exists at v_rstSource[15] then increment all indexes in that section such that they read
v_rstSource[16]).
2. Increase the return value of the CfgDefineSources() function by one.
3. In Main.AXS, increase the value of c_nMaxSources by one.
4. In Config.axi, copy an existing source initialization. Do not copy any irMap or rstPreset
blocks. Paste the block towards the end of the CfgDefineSources() function, immediately
before the About "source."
5. Increment all indexes on the copied block so that they immediately precede the indexes of the
About section. Note that all indexes within a section should be identical. For example, if your
new source falls at v_rstSource[15] then all indexes within the block should be 15.
6. Initialize the members according to the following member descriptions:

dvID (DEV) D:P:S device ID of the source.


dvVirtualID (DEV) D:P:S device ID of the Virtual Device (if applicable).
strName (CHAR[ ] ) Name of source (e.g., "Toshiba DVD XL1000").
Unique identifier of source type; available constants are:
c_nDVD, c_nVCR, c_nLDP, c_nRCVR, c_nMP3,
nSourceType (INT) c_nCD, c_nPVR, c_nCass, c_nCable, c_nLIGHT,
c_nCustom, and c_nMacro (
Note: only one c_nMacro source type is allowed.
The means by which we control this device. Available con-
nCtrlMethod (INT)
stants: c_nIR, c_nRS232, and c_nTCPIP.
Control Logic for this source (omit if none); available Control
Logics are:
c_nDVD01…c_nDVD10
nCtrlLogic (INT) c_nVCR01…c_nVCR10
c_nLDP01…c_nLDP10
c_nRCVR01…c_nRCVR10
c_nMP301…c_nMP310
stRouter (STRUCT) See definition of stRoute struct.
irMap (STRUCT) The IR Map structure.
stParam (STRUCT) A generic parameter structure.
strFileName (CHAR[ ] ) Disc List file name, if applicable.
nChanCount (INT) The total number of preset channels for this source.
rstSurround[ ].strName A Surround Sound mode name.
(CHAR[ ] )

22 DXP-HT v1.2 - Advanced Programmer’s Guide


Advanced Customization

An IR Code or unique identifier that corresponds to the Sur-


rstSurround[ ].nCode round Sound mode (applicable only to those sources without
(INT)
an associated Control Logic)
A unique identifier that indicates whether the receiver input to
which this source connects supports Audio and Video or just
Audio or Video. Available constants are: c_nBoth,
stRcvr.nType (INT)
c_nAudio, c_nVideo. Note that this field should not be pop-
ulated for the receiver but rather the source that connects to
the receiver.
stRcvr.nTunerIndex (INT) A "pointer" to the built in tuner, if applicable.
A sequential number that increments once for each CD
nCDIdx (INT) Changer. i.e., the first CD Changer will set nCDIdx to 1, the
second to two, and so-forth.
A "pointer" to another source that may be used as a tuner, if
applicable. i.e., if the VCR sits on Line Input 1 and uses the
DSS as it's tuner, then this member should point to the DSS
index in the Source database. DXP-HT supports only one
nTunerIdx (INT)
level of indirection. i.e., if the VCR points to a different VCR
and that VCR points to the DSS, only the first de-reference
would apply, which means the first VCR would use the second
VCR as its tuner, not the DSS.
Number of CDs that a CD Changer can hold (1 for single-disc
nCDChangerSize (INT)
units)
rstPreset[ ].strName A generic preset name field, used for discrete channels, light-
(CHAR[ ]) ing, etc.
rstPreset[ ].strParam1 A generic preset string field, used for discrete channels, light-
(CHAR[ ]) ing, etc.
rstPreset[ ].nParam1 A generic preset INTEGER field, used for discrete channels,
(INT) lighting, etc.
For AM/FM RS-232 receivers, this value must equal the
parameter that should be sent to the module with the
?
'PRESET=[x]' command (i.e., x = nParam1). AM/FM IR
receivers are handled via the irStack array.
? For RF tunable devices, this should be the channel to tune to.
An array of ones and zeroes that correspond to the discrete
channel preset categories that should include this preset. The
maximum number of categories is defined via
rstPreset[ c_nMaxCategories (overridable). The flags are set left-to-
].strCategories (CHAR[ right so that a 1 as the first byte corresponds to the first chan-
]) nel preset category (should always be "All"), the second byte
corresponds to the second category, etc. Channel preset cat-
egories are stored in the global array, v_rCategories,
which is initialized in CfgDefinePresetCategories ( ).
For IR controlled tuners only: An array of size
c_nMaxPresetStack in which IR codes can be stored. If
only one pulse is required to select a preset then only popu-
late rstPreset[ ].irStack[1].
stPwr.bDiscretePower (INT) - Non-zero (true) indi-
rstPreset[ ].irStack[ ] cates the source supports discrete power; zero (false) indi-
(INT) cates the source does not. If this member is set to false,
NetLinx will pulse irPowerToggle whenever power is
turned ON or OFF. Otherwise, NetLinx will pulse irPowerOn
or irPowerOff, unless stPwr.nPwrCtrl = c_nNetLinx,
in which case NetLinx will emulate PON/POF (we never send
the PON/POF commands).
Non-zero (true) indicates DXP-HT should govern power state;
stPwr.bPwrCtrl (INT)
zero (false) indicates DXP-HT should not govern power state.

DXP-HT v1.2 - Advanced Programmer’s Guide 23


Advanced Customization

Non-zero (true) indicates the Power button should follow the


stPwr.bShowFdbk (INT) the true state of the device that it is controlling. Zero (false)
indicates that it should not.
The device that is utilized as an input to the power sensing I/O
stPwr.nCtrlDevice (INT) port. Available constants are: c_nPCS, c_nPCS2, c_nVSS2,
c_nTVS.
The D:P:S address of the I/O device that should be used to
stPwr.dvInputLink (DEV) sense state. This member should only be populated if the
user opts to govern state (i.e., stPwr.bPwrCtrl == true).
The channel on the I/O device that should be used to sense
stPwr.nInputChan (INT) power. This member should only be populated if the user opts
to govern state (i.e., stPwr.bPwrCtrl == true).

How to create a custom Control Logic.


A Control Logic is a set of behaviors and properties that describe the means by which a device
should be controlled. Control Logics are written for specific devices or specific behaviors that
govern families of devices.
Control Logics may consist of NetLinx code geared towards the device(s) that they are intended to
control, or they may simply consist of calls into NetLinx modules or SYSTEM_CALLs.
Control Logics may act directly upon a device or they may simply set parameters that are passed in
by reference. For example, a Control Logic may initialize a parameter to some value so that the
calling function's value of the parameter will also change. Then, the caller can utilize that value to
act upon the device. In the context of DXP-HT, the "caller" will always be either
ControlSourceDevice or ControlDisplayDevice.

Control Logic parameters.


Following are descriptions of the parameters that are passed into each Control Logic:

nFunc A unique identifier that corresponds to the command ID


(c_nPlay, c_nStop, etc.). See _Define Constant.axi for a
complete list of unique identifiers.
nIR An "empty value" that is used by the caller (Control.axi) for IR
controlled devices. If this value is initialized within the Control
Logic then the caller will send IR after this function completes.
nPulseType Another "empty value" that is used by the caller (Control.axi).
If nIR is set then this parameter's value will be used to deter-
mine whether IR should be pulsed, turned ON, or turned OFF.
This parameter should only be set to one of the following:
c_nON, c_nOFF, or c_nPULSE.
bPush If non-zero, we are handling a PUSH. Otherwise, we are han-
dling a RELEASE.
nSrcDBIdx / Index into the Source table (v_rstSource) or the Display
nDispDBIdx table (v_rstDisplay) that corresponds to the device that we
are controlling.
nTPDBIdx Index into the interface database for the touch panel that sent
the event that we are handling.
stParams A "generic" parameters structure (declared in _Define Struc-
ture.axi as stPmtrs). This can be used to pass any neces-
sary value into the Control Logic.

If you are creating a custom Control Logic for an IR controlled device, you may act directly upon
the device or you may simply set the values of nIR and nPulseType. If you initialize nIR and

24 DXP-HT v1.2 - Advanced Programmer’s Guide


Advanced Customization

nPulseType within your Control Logic, functions within the parent file (Control.axi) will send IR
automatically. This occurs because modifying the value of the two parameters will also modify the
value of the variables that were passed in by the calling function (either ControlSourceDevice
or ControlDisplayDevice).

! nIR should be set equal to the value of the IR channel that you need to actuate.

! nPulseType should be set to either c_nPulse, c_nON, or c_nOFF.


If you choose to act upon the device from within the Control Logic itself, it is important that you do
not utilize nIR or nPulseType anywhere within your custom code. Instead, you should
programmatically send IR using standard NetLinx commands (PULSE, ON, and OFF).
When creating a custom RS-232 or Ethernet Control Logic, all actions should be accomplished
from within the Control Logic instead of allowing the calling function to handle communication
with the device. For example, if the unique identifier that is received via nFunc is c_nPlay, and if
the protocol for the device that you are controlling calls for transmission of a "PLAY" command,
you would handle that as follows: SEND_STRING v_rstSource[nSrcDBIdx].dvID,'PLAY'.
Control Logics may also utilize modules or SYSTEM_CALLs to control a device. For an example of
a Control Logic that utilizes a NetLinx module, see the function cl_RCVR01 within Control
Logics.axi. Note that the prefix 'cl_' is employed to indicate that the function is a Control Logic.
As the goal of any Control Logic is to govern device behaviors, knowledge of the current state of
the device may be required. Therefore, if the device that you are controlling is a source (as opposed
to a display device), you may utilize the nCurrState member of the Source table to track the
current state. Use of this member is shown in the following example of a rudimentary RS-232
Control Logic that utilizes a fictional protocol:
DEFINE_FUNCTION cl_MyCustomControlLogic01 (
INTEGER nFunc, // Unique command identifier
INTEGER nIR, // Empty value; passed by reference
INTEGER nPulseType, // Empty value; passed by reference
INTEGER bPush, // Non-zero = PUSH; otherwise RELEASE
INTEGER nSrcDBIdx, // Index into source database
INTEGER nTPDBIdx, // Index into interface database
stPmtrs stParams) // Misc. parameters
{
STACK_VAR DEV dvID

// Acquire the Device ID of the source that we are ctrling:


dvID = v_rstSource[nSrcDBIdx].dvID

// Handle the command (first validate database index):


IF ((nSrcDBIdx > 0) && bPush)
{
SWITCH (nFunc)
{
CASE c_nPlay :
{
// Send the command to the device:
SEND_STRING dvID,'PLAY'

// Set the new device state


v_rstSource[nSrcDBIdx].nCurrState = c_nPlay
}
CASE c_nStop :

DXP-HT v1.2 - Advanced Programmer’s Guide 25


Advanced Customization

{
// Send the command to the device:
SEND_STRING dvID,'STOP'

// Set the new device state


v_rstSource[nSrcDBIdx].nCurrState = c_nStop
}
CASE c_nPause : // Send PLAY to return from PAUSE
{
IF (v_rstSource[nSrcDBIdx].nCurrState == c_nPause)
{
// Send the command to the device:
SEND_STRING dvID,'PLAY'

// Set the new device state


v_rstSource[nSrcDBIdx].nCurrState = c_nPlay
}
ELSE
{
// Send the command to the device:
SEND_STRING dvID,'PAUSE'

// Set the new device state


v_rstSource[nSrcDBIdx].nCurrState = c_nPause
}
}
}
}
}
Note that the example Control Logic shown above includes a check for the value of bPush. This is
because we only want to send the strings on the PUSH event. It is important to understand that
Control Logics will always be called twice, once on the PUSH event and again on the RELEASE.
This is useful for such tasks as volume ramps or other ON/OFF needs. However, for simple
commands it is important that you ensure that they are sent to the device only on the PUSH or
RELEASE.
Any custom Control Logics must added to the SWITCH...CASE in Control.axi. If you are creating a
Control Logic for a source, search on SWITCH (v_rstSource[nSrcDBIdx].nCtrlLogic),
then add your Control Logic to the list. Note that you should first create a unique identifier for your
Control Logic. This unique identifier should be outside the range of those already defined in
_Define Constant.axi. An example of the initialization of a Control Logic identifier would be:
INTEGER c_nMyCustomControlLogic = 1000. This belongs in the DEFINE_CONSTANT
section of Custom.axi or anywhere within _Define Constant.axi.
If you are creating a Control Logic for a display device, search on SWITCH
(v_rstDisplay[nTVDBIdx].nCtrlLogic) within Control.axi, then add the call to your custom
Control Logic within the SWITCH...CASE.

Any changes to _Define Constant.axi, ControlLogics.axi, or Control.axi invalidate


subsequent regenerations of your project via the Wizard. It is very important that you
implement any modifications in a safe working directory, to prevent the Wizard from
overwriting your custom changes.

26 DXP-HT v1.2 - Advanced Programmer’s Guide


Advanced Customization

Feedback
By default, almost all button pushes utilize momentary feedback. That is, for the duration that the
button is pushed, it will remain ON and it will turn OFF when the user releases the button.
Feedback may be overridden for any Control Logic by adding the unique identifier of the Control
Logic to the c_rFdbkOverride array. Controlling feedback for your custom Control Logic via the
Control Logic itself is a 3-step process:
1. In the DEFINE_CONSTANT section of Main.axs, add the following compiler directive:
#DEFINE FdbkOverride.
2. In the DEFINE_CONSTANT section of Main.axs, add the following declaration:
c_nMaxFdbkOverrides = [x], where [x] is the number of custom Control Logics that
you have created plus 3. We add three because DXP-HT already overrides feedback for the
three built in relay Control Logics (see next step).
3. In the DEFINE_CONSTANT section of Main.axs, add the following declaration, where
c_nMyCtrlLogic represents the unique identifier that you created for your Control Logic
(note that the pre-existing relay Control Logics must be included in this array):
INTEGER c_rFdbkOverride[c_nMaxFdbkOverrides] = {
c_nRelay01,
c_nRelay02,
c_nRelay03,
c_nMyCtrlLogic }
After completing the steps described above, no feedback will be intrinsically available for any
device that utilizes your custom Control Logic. It is now your responsibility to handle feedback
within the Control Logic itself.
Several functions are available to facilitate interface feedback:

TPFdbkON (INTEGER nBtnSet, INTEGER nChan)


TPFdbkON is used to turn a channel ON for all interfaces within the system. Parameter descriptions
are as follows:

? nBtnSet The "Device Used" value of the buttons that are utilizing your
Control Logic. This must be a value 1-4.
? nChan The channel that you need to turn ON.

TPFdbkOFF (INTEGER nBtnSet, INTEGER nChan)


TPFdbkOFF is used to turn a channel OFF for all interfaces within the system. Parameter
descriptions are as follows:

? nBtnSet The "Device Used" value of the buttons that are utilizing your
Control Logic. This must be a value 1-4.
? nChan The channel that you need to turn OFF.

DXP-HT v1.2 - Advanced Programmer’s Guide 27


Advanced Customization

TPFdbk (INTEGER nBtnSet, INTEGER nChan, INTEGER bState)


TPFdbk is used to turn a button ON or OFF according to an evaluation. Parameter descriptions are
as follows:

? nBtnSet The "Device Used" value of the buttons that are utilizing your
Control Logic. This must be a value 1-4.
? nChan The channel that you need to turn OFF.
? bState A "Boolean" value used to determine whether the button
should be turned ON or OFF. This may be passed as an eval-
uation. Following is an example of a call to TPFdbk:
TPFdbk (c_nDVDSetIdx,
c_btnDVDPlay,
v_rstSource[nSrcDBIdx].nCurrState =
c_nPlay))

You may also manually set feedback from within your custom Control Logic by simply turning
interface channels ON and OFF. However, use of the functions described above will automatically
account for the following:

! ? Feedback will automatically propagate across all interfaces that exist within the
system.

! ? Feedback flags will be set so that interfaces will be properly initialized when they
come online.

28 DXP-HT v1.2 - Advanced Programmer’s Guide


Debugging and Diagnostics

Debugging and Diagnostics


The most effective way to debug DXP-HT code is by utilizing the built in debugging and diagnostic
messages. These messages may be enabled and disabled via the touch panel interface. To set a
debug messaging level via the touch panel interface, first press the "About" button on the main
menu, then press "Project Information". This will take you to the Help/About page. The bottom
section of the Help/About page includes a button labeled "Debug". Press this button to go on to the
page that will allow enabling and disabling of debug messaging.
Following are descriptions or the various debug messaging levels that are available:

! General Messaging - miscellaneous debug messaging that is used throughout the code.

! Path of Execution - debug messaging that is displayed when functions are entered and
exited. This can be used to track the logical flow of the code.

! Handler Properties - debug messaging specifically related to BUTTON_EVENT


handlers. Enable this level to view messaging regarding each BUTTON_EVENT as it
occurs.

! Macro Engine - technical debug messages related to the operation of the Macro Engine.
Typically, this level will be utilized only by AMX Technical Support.

! Errors & Exceptions - errors and warnings regarding database access, parameter
validation, and similar tasks.
Debug messages may be viewed via Terminal or Telnet connected to the NetLinx master. Be sure
NetLinx master messaging is enabled via the MSG ON command, which may be entered via
Terminal or Telnet.
You may add your own debugging and diagnostics statements via the Debug function. The
parameters of the Debug function are described as follows:

! INTEGER nLevel - The debugging level to which the statement applies. This must be
one of the following constants:
! c_nGeneral
! c_nPath
! c_nHandler
! c_nMacro
! c_nError

! CHAR strDebug[ ] - The debug string that you wish to display.

Following is an example of a debug string:


Debug (c_nGeneral, 'This is my debug statement')
Debugging & diagnostics may be enabled by default. This is accomplished by placing the
appropriate combination of the following statements within the DEFINE_START section
of Custom.axi:

DXP-HT v1.2 - Advanced Programmer’s Guide 29


Debugging and Diagnostics

DbgSetFlag (c_nGeneral)
DbgSetFlag (c_nPath)
DbgSetFlag (c_nHandler)
DbgSetFlag (c_nMacro)
DbgSetFlag (c_nError)

30 DXP-HT v1.2 - Advanced Programmer’s Guide


Glossary

Glossary
! Control Logic - A block of source code that is built around the behaviors and properties
of a specific device. Control Logics may drive any device type (RS-232, Ethernet, Relay,
or IR). Typically, Control Logics are geared towards RS-232 or Ethernet devices that
require specialized handling beyond simple "push & pulse". A Control Logic may call
directly into a module or it may act upon the device itself. For IR controlled devices, the
Control Logic may merely set a channel ID and pulse type for handling within it's parent
function, ControlSourceDevice or ControlDisplayDevice.

! D.O.C. - Disk On Chip. This is hardware that is built into the NetLinx controller for use
in storing and retrieving persistent data.

! Module - A compiled block of source code that is designed to control one specific device
or a set of devices that have identical or similar behavior. Modules are compiled code that
are instantiated as standalone binary entities, analogous to a COM Object in some
respects. Modules expose a standardized API which permits control of a host of devices
via the same NetLinx source code.

DXP-HT v1.2 - Advanced Programmer’s Guide 31


033-004-2716 12/03 ©2003 AMX Corporation. All rights reserved. AMX, the AMX logo, the building icon, the home icon, and the light bulb icon are all trademarks of AMX Corporation.
*In Canada doing business as Panja Inc.

AMX reserves the right to alter specifications without notice at any time.

ARGENTINA • AUSTRALIA • BELGIUM • BRAZIL • CANADA • CHINA • ENGLAND • FRANCE • GERMANY • GREECE • HONG KONG • INDIA • INDONESIA • ITALY • JAPAN
LEBANON • MALAYSIA • MEXICO • NETHERLANDS • NEW ZEALAND • PHILIPPINES • PORTUGAL • RUSSIA • SINGAPORE • SPAIN • SWITZERLAND • THAILAND • TURKEY • USA
ATLANTA • BOSTON • CHICAGO • CLEVELAND • DALLAS • DENVER • INDIANAPOLIS • LOS ANGELES • MINNEAPOLIS • PHILADELPHIA • PHOENIX • PORTLAND • SPOKANE • TAMPA

3000 RESEARCH DRIVE, RICHARDSON, TX 75082 USA • 800.222.0193 • 469.624.8000 • 469-624-7153 fax • 800.932.6993 technical support • www.amx.com

You might also like