amx netlinx programming ba01

87
instruction manual AMX University Introduction to AMX Programming

Upload: badgerarc

Post on 12-Nov-2014

10.063 views

Category:

Documents


5 download

DESCRIPTION

AMX Netlinx programming guide

TRANSCRIPT

Page 1: Amx Netlinx Programming Ba01

instruction manual

AMX University

Introduction toAMX Programming

Page 2: Amx Netlinx Programming Ba01

July 2004

CopyrightAMX Corporation, 2004. All rights reserved. No part of this publication may be reproduced, transcribed, stored in a

retrieval system or translated into any language in any form by any means without the written permission of AMX.

CreditsWritten by AMX University.

Printed in Dallas, Texas.

For additional questions or suggestions, feel free to call us.

AMX University

3000 Research Drive

Richardson, TX 75082

Phone 469.624.8000

Fax 469.624.7192

Page 3: Amx Netlinx Programming Ba01

July 2004

CopyrightAMX Corporation, 2004. All rights reserved. No part of this publication may be reproduced, transcribed, stored in a

retrieval system or translated into any language in any form by any means without the written permission of AMX.

CreditsWritten by AMX University.

Printed in Dallas, Texas.

For additional questions or suggestions, feel free to call us.

AMX University

3000 Research Drive

Richardson, TX 75082

Phone 469.624.8000

Fax 469.624.7192

Page 4: Amx Netlinx Programming Ba01

Table of Contents

iIntroduction to AMX Programming

Table of Contents

Welcome ....................................................................................................................1

Course Objectives ....................................................................................................1

Introduction ...............................................................................................................2

The AMX Language Course.............................................................................................. 2

What is NetLinx? ............................................................................................................... 2

Unit 1: Language Basics ..........................................................................................3

Chapter 1 - Simply the Basics .................................................................................3

Introduction........................................................................................................................ 3

Format of the Language .................................................................................................... 3

Statements and Compound Statements ........................................................................... 4

Comments Within the Program ......................................................................................... 5

Identifiers........................................................................................................................... 6

Reserved Words................................................................................................................ 6

Special Characters and Operators .................................................................................... 6

Chapter 2 - The Definition Sections ........................................................................7

Starting a New Program .................................................................................................... 7

Defining Devices ............................................................................................................... 7

Defining Constants ............................................................................................................ 9

Defining Variables ........................................................................................................... 10

Startup Code ................................................................................................................... 11

DEFINE_EVENT and Mainline in NetLinx....................................................................... 11

Chapter 3 - Using Input and Output ......................................................................13

Controlling Something Over There.................................................................................. 13

The Device-Channel Concept ......................................................................................... 13

All About the Channel...................................................................................................... 13

Changing the State of a Channel .................................................................................... 15

Putting Input and Output Together .................................................................................. 18

Chapter 4 - Channel Characteristics .....................................................................19

The Parts of an Output Channel...................................................................................... 19

Mutually Exclusive........................................................................................................... 19

Putting it All to Work ........................................................................................................ 21

Programming Feedback .................................................................................................. 23

Grouping Feedback Statements...................................................................................... 24

Unit 2: Conditionals and Waits ..............................................................................25

Page 5: Amx Netlinx Programming Ba01

ii Introduction to AMX Programming

Table of Contents

Chapter 5 – Conditional Expressions ...................................................................25

Introduction ..................................................................................................................... 25

Conditional Expressions.................................................................................................. 33

The IF Statement ............................................................................................................ 33

The IF...ELSE Set of Statements .................................................................................... 33

Repeating IF...ELSE Set of Statements.......................................................................... 34

Nesting ............................................................................................................................ 34

The SELECT...ACTIVE Statement.................................................................................. 35

Trying it Out..................................................................................................................... 36

Conditional Operators ..................................................................................................... 39

Chapter 6 – The Wait Keywords ............................................................................41

Controlling Time Within the AMX System ....................................................................... 41

The WAIT List ................................................................................................................. 41

Multiple Wait Statements ................................................................................................ 43

Special Uses of Wait ....................................................................................................... 45

Naming Wait Statements ................................................................................................ 45

Canceling, Pausing, and Restarting Wait Statements .................................................... 46

The WAIT_UNTIL Keyword............................................................................................. 46

Misusing WAIT_UNTIL.................................................................................................... 47

Naming and Removing WAIT_UNTIL Statements .......................................................... 47

Unit 3: Levels ..........................................................................................................49

Chapter 7 – Creating and Using Levels ................................................................49

Introduction ..................................................................................................................... 49

What is a Level?.............................................................................................................. 49

Creating Levels ............................................................................................................... 49

Reading Levels ............................................................................................................... 52

Making a Preset .............................................................................................................. 52

Using Bar Graphs............................................................................................................ 53

Connecting Levels........................................................................................................... 53

Unit 4: Arrays and Sending and Receiving Strings ............................................55

Chapter 8 – Arrays and Strings .............................................................................55

Introduction ..................................................................................................................... 55

Defining Arrays................................................................................................................ 55

Accessing and Storing Array Values............................................................................... 56

Data Types...................................................................................................................... 59

Strings ............................................................................................................................. 60

The String Expression..................................................................................................... 61

Page 6: Amx Netlinx Programming Ba01

Table of Contents

iiiIntroduction to AMX Programming

String Elements ............................................................................................................... 61

String Lengths ................................................................................................................. 62

Sending Strings and Arrays............................................................................................. 63

ASCII Codes.................................................................................................................... 64

Integer Arrays.................................................................................................................. 64

Chapter 9 – Working with Arrays ..........................................................................67

Grouping Data ................................................................................................................. 67

Conversion keywords ...................................................................................................... 67

Array Manipulation Keywords.......................................................................................... 69

UPPERCASE vs. lowercase ........................................................................................... 71

Setting Uppercase and Lowercase ................................................................................. 71

Chapter 10 – Receiving Strings .............................................................................73

Listening to the Outside World ........................................................................................ 73

Receiving Strings ............................................................................................................ 73

Storing characters ........................................................................................................... 73

Retrieving Characters...................................................................................................... 74

Appendix: Troubleshooting ...................................................................................75

ESCAPE.......................................................................................................................... 75

Appendix: Standard IR Function Order ................................................................77

Appendix: ASCII Code Chart .................................................................................79

Page 7: Amx Netlinx Programming Ba01

iv Introduction to AMX Programming

Table of Contents

Page 8: Amx Netlinx Programming Ba01

Welcome

1Introduction to AMX Programming

Welcome

Welcome to Introduction to AMX Programming. This self-paced course is for new Programmers,

Installers who want to learn AMX programming, and Technical Support Personnel and teaches the

basic techniques for programming an AMX Control System. A person completing this self-paced

course will be able to understand a basic AMX program and have the basis for successful

completion of subsequent AMX programming classes.

This manual is designed to be both a reference for on the job and a tool for self-paced training.

White space is available on every page for taking notes. There is references to programming code

that accompanies this manual. The companion code files are in the zip file that also contains this

manual. Good luck!

Course Objectives

Upon completion of this self-paced course you will be able to:

! Understand the basic principles of AMX Programming

! Understand the core components of AMX devices

! Understand how to program channels, levels, and strings related to each device

! Understand Buffer/ String Processing functions

! Utilize the basic techniques to debug programming errors in a NetLinx program

Page 9: Amx Netlinx Programming Ba01

Introduction

2 Introduction to AMX Programming

Introduction

The AMX Language CourseThis self-paced course takes the approach of teaching the common elements of AMX Programming

languages while developing real world AMX Control System programs. You will start with the

basic commands and simple control scenarios, and progress on to more complex programming as

you discover new programming functions and techniques. With the exception of additional

keywords and objects in the NetLinx programming language, there are very few differences in

many programs.

What is NetLinx?In the continuing evolutionary process of control systems AMX introduced the NetLinx Control

System. NetLinx is the most advanced control system developed in that process. The NetLinx

system can not only control devices connected directly to it’s control ports and local control

networks but can control and communicate seamlessly to other control systems and devices on

Ethernet networks and the Internet. The NetLinx hardware takes the experience gained from more

than a decade of Axcess system installations to make a more powerful control system.

To enable this giant step in system development the Axcess programming language, the basis of the

Axcess control system, was enhanced and supplemented to provide the programming power for

NetLinx.

The NetLinx system is an Event driven system. As inputs come into the system that input is

compared against an Event table. This Event table can keep track of things such as button presses

on a panel, channels turning on and off, and responses received from connected devices. You will

see many Events in examples throughout the tutorial, and this concept will be discussed later in

Chapter 2 in DEFINE_EVENT and Mainline in NetLinx on page 11 and in greater detail in AMX

Programmer I.

Page 10: Amx Netlinx Programming Ba01

Unit 1: Language Basics

3Introduction to AMX Programming

Unit 1: Language Basics

Chapter 1 - Simply the Basics

IntroductionThis unit will help you start writing AMX programs. By the end of this unit you should be familiar

with several concepts:

! Basic ground rules for writing AMX programs

! The device channel concept

! The different sections that make up an AMX program

! How NetLinx executes a program

! Basic input and output functions

! Simple feedback.

As you progress through the chapters you will develop a simple Axcess program containing these

basic features, and you will build on this program in later units.

Format of the LanguageThe AMX languages can be written in a free format, meaning that the source code is independent of

tabs and carriage returns. Because of this, it is advised to use a consistent method of code

placement in order to make the code more readable. In this manual, an “outline” format is used; that

is, each subsection of a section is slightly indented. For example:

BUTTON_EVENT[PANEL,1]{ PUSH: {

IF (X = 1) {

Y = 2 Z = 3

} }}

Page 11: Amx Netlinx Programming Ba01

Chapter 1 - Simply the Basics

4 Introduction to AMX Programming

Statements and Compound StatementsDuring programming, most of the keywords and operators require a complete statement. A

keyword is a word or series of words that signifies the operation for the system to execute. That

keyword and all its parameters form the statement. For example, the keyword to turn a channel on is

merely ON. However, the statement to turn on a particular channel (let’s say channel 6) is

ON[RELAY_CARD,6]. Statements can also involve mathematical or logical operations when

operators are used. An operator is a character that performs a specific mathematical or relational

function. For example, the operator used to set a variable equal to a value is the equal sign (=). As

expected, the statement used to set variable X to the number 5 is X = 5.

You will frequently have to group several different statements together into one compound

statement. The braces “{ }” are used to enclose this type of statement. Compound statements are

used if several statements are to be executed in a situation where program syntax will allow just

one. The statements are executed in the sequence in which they are programmed. The number of

open braces “{” and close braces “}” must be the same in your program. For each open brace there

should be a corresponding close brace. The compiler will point out this error to you if the quantities

are different after compiling.

Compound statements give you the ability to group multiple statements together into one unit,

much like grouping sentences together into one paragraph. The most common example of

compound statements occurs with the PUSH keyword. (This keyword is explained in depth later.)

BUTTON_EVENT[PANEL,1]{ PUSH: {

ON [RELAY_CARD,5] X = 5

}}

In this example, when button 1 on PANEL is pressed, relay 5 on RELAY_CARD is turned on. Also, the

variable X is assigned the value of 5. The open brace indicates the beginning of the compound

statement, and the close brace ends it. If you only needed the relay to be turned on, the statement

could have been written like this:

BUTTON_EVENT[PANEL,1]{ PUSH: { ON [RELAY_CARD,5] }}

Page 12: Amx Netlinx Programming Ba01

Chapter 1 - Simply the Basics

5Introduction to AMX Programming

The code example on the previous page uses two special operators. The chart below list more detail

about these operators. You will see these used throughout the manual.

Comments Within the ProgramAMX programming languages allow you to place helpful comments inside your program. A

comment is a description or remark that is not considered part of the actual program. Once

something is marked as a comment it will not be compiled. It exists only to help people read the

code. There are three ways to mark something as a comment. The quickest method is to use a //.

Any text following // will not be compiled. However, the // only designates that the text until the

end of that current line is a comment. The text which would appear on the next line would be

compiled. //This section will define all the devices used.DEFINE_DEVICEVCR = 1:1:0 // ACME VIDEO CASSETTE RECORDER MODEL 1000CD = 2:1:0 // ACME COMPACT DISC PLAYER MODEL 2000

In the above code the first line is just a header. It is preceded by a // so it is not compiled. After the

devices VCR and CD are addressed there is a comment explaining that line of code. This method

requires a // to be entered everywhere you want to make a comment. But, there may be situations

where you want to mark several lines as a comment. You could use // but you would have to insert

that before each line. To make this easier, NetLinx supports two more methods of making

comments. Both methods work the same way. Any text after (* and before *), or after /* and

before */ will also not be compiled, even if the text is separated over several lines. See the

following example:BUTTON_EVENT [T_PANEL,1] // SLIDE PRESET{ PUSH: { (* HERE IS WHERE I WILL PLACE SEVERAL LINES OF CODE TO BE RUN WHEN BUTTON NUMBER 1 IS PUSHED ON THE PANEL *) }}BUTTON_EVENT [T_PANEL,2] // VHS PRESET{ PUSH: { /* HERE IS WHERE I WILL PLACE SEVERAL LINES OF CODE TO BE RUN WHEN BUTTON NUMBER 2 IS PUSHED ON THE PANEL */ }}

Special OperatorsOperator Name Function

{ } Braces Combine several statements into a compound statement

[ ] Brackets

Enclose the device-channel: [device,channel]Enclose the size or location of a storage space in an arrayEnclose the instance number used with a SYSTEM_CALLEnclose a variable to be turned on or off

( ) ParenthesesEnclose the expression after an IF statementEnclose a mutually exclusive set in the Define sectionGroup a mathematical operation

Notes: The uses of braces, brackets, and parentheses cannot be interchanged within the program

Page 13: Amx Netlinx Programming Ba01

Chapter 1 - Simply the Basics

6 Introduction to AMX Programming

Here the button is labeled using // but the longer comments are marked using a different (* or */.

You can place any number of comments in your program. However, when the program is compiled,

they will be passed over. Comments have no effect on the actual operation of the program. It is wise

to use comments. They are especially helpful in a long program where you can label each part of

the program for future reference. If changes have to be made, you can merely look for the label of

the section you need to edit. As illustrated above, descriptions of PUSH statements are very useful.

IdentifiersIdentifiers are used to denote a device, constant, or variable. For example, T_PANEL could represent

an AMX Touch Panel, PLAY could represent the first channel, and CD_SELECT could represent the

current compact disc player. The guidelines for identifiers are as follows:

! They must begin with a letter followed by any combination of letters, numbers, or

underscores. No spaces are allowed.

❑ Valid identifiers: CD3, TOUCH_PANEL, VCR3_SELECT

❑ Invalid identifiers: 3VHS, CD PLAYER, *RGB4

! The identifier must have less than 26 characters.

! Identifiers are not case sensitive. For example, Touch_Panel is the exact same identifier

as TOUCH_PANEL

! The identifier must be unique. Once you define VHS3, do not choose the same name later

for a different identifier.

Reserved WordsThere are certain words that are reserved as keywords or functions. These are integral to the system

and cannot be redefined or used as identifiers. For example, PUSH cannot be used as an identifier,

because the system recognizes it as a keyword.

Special Characters and OperatorsThere is also a complete set of symbols that are used within the program. These symbols represent

a wide variety of characters and operators.

Mathematical Operators Relational OperatorsOperator Function Operator Function

( ) Parentheses < Less than

* Multiply > Greater than

/ Divide <= Less than or equal to

% Modulo >= Greater than or equal to

+ Add <> Not equal to

- Subtract = or == Equal to

Page 14: Amx Netlinx Programming Ba01

Chapter 2 - The Definition Sections

7Introduction to AMX Programming

Chapter 2 - The Definition Sections

Starting a New ProgramNow that the ground rules are laid out, you can start writing your first program! When you begin a

new program, also referred to as a source code file, in NetLinx Studio you are not given an empty

file with which to work. Instead, there are several definition headings to signify what should be

defined in each section. The definition sections that are given to you are the following:

! DEFINE_DEVICE

! DEFINE_CONSTANT

! DEFINE_TYPE

! DEFINE_VARIABLE

! DEFINE_LATCHING

! DEFINE_MUTUALLY_EXCLUSIVE

! DEFINE_START

! DEFINE_EVENT

! DEFINE_PROGRAM

Feel free to delete any of these headings you do not need, and keep those that you do. If you do not

have any statements under one of these headings, your program will not operate any differently.

However, you might want to keep the headings there for future reference. Although the definition

sections are not used within the main program, they create the materials the main program needs.

Devices and their channels are given names, channels are given different characteristics, and

variables are formed. Even the immediate startup procedures of the AMX control systems are

within a definition section. If you develop a good understanding of the Define statements, you will

be able to build an excellent foundation for the main part of your program.

Defining DevicesWhen you start writing a program, you should first label each device in the system. Each device

connected to the master must have a unique device number. Card 1 may have device number 1, and

card 2 may have device number 2. Any time these device numbers are referenced in the program,

the master checks the corresponding device. However, with a long list of devices connected to the

control networks, these numbers can be difficult for a programmer to remember. Assigning actual

names to these devices is much easier.

This is the function of the DEFINE_DEVICE section. It is placed at the beginning of the program,

and it lets you name the devices. Whenever you use this device name in your program, the compiler

will automatically use the corresponding device number to reference the device.

Page 15: Amx Netlinx Programming Ba01

Chapter 2 - The Definition Sections

8 Introduction to AMX Programming

You should start writing your program by first defining the devices in your system. Suppose you

have a VCR, a CD player, and a cassette deck, and you are controlling them with the first three IR

outputs on an NI-3000. These IR outputs have device numbers 5001:9:0, 5001:10:0 and

5001:11:0. They will have these device numbers because these devices are connected to ports 9,

10 and 11 on the NI-3000. The program will reference the port that you need to control. You can

name that port after the device you are going to connect to it. That way the code will make sense for

people who read it. The compiler will continue to reference the full port address. The naming is just

for readability.

Additionally, you also want to control a projection screen, some drapes, and lights. The relays of

the NI-3000 will control the screen and drapes and the I/O device of the NI-3000 will control the

lights. A Touch Panel will be the user interface to control all of these devices (in this instance an

NXT-CV15). Here is what your DEFINE_DEVICE section should look like:

DEFINE_DEVICERELAY = 5001:8:0 (*NI-3000 RELAY OUTPUTS 1-8 *)VCR = 5001:9:0 (*NI-3000 IR OUTPUT #1*)CD = 5001:10:0 (*NI-3000 IR OUTPUT #2*)CASS = 5001:11:0 (*NI-3000 IR OUTPUT #3*)LIGHTS = 5001:16:0 (*NI-3000 I/O 1-4*)TP = 10128:1:0 (*NXT-CV15 TOUCH PANEL*)

From this point on, you can reference device 9 with the name VCR, device 10 with the name CD, and

so on. The compiler will understand that when the code references CD it is actually referring to

5001:10:0 and so everything will work properly.

Notice the Touch Panel is the only device not addressed with 5001. That is because the Touch

Panel is an independent device. It is not integrated into the NI-3000 like the other references.

Where as the VCR, CD, CASS and LIGHTS are all controlled by different ports on the NI-3000, the

Touch Panel is a stand alone device; therefore, the addressing must be different.

FIG. 1 NI-3000 is Device 5001

VCRPort 9 CD

Port 10

CASSPort 11

Device 5001

Page 16: Amx Netlinx Programming Ba01

Chapter 2 - The Definition Sections

9Introduction to AMX Programming

Defining ConstantsConstants are identifiers whose values remain unchanged throughout the entire program. The

process of defining them is very similar to defining devices. Assigning a value to an identifier in

this section locks that value to the identifier for the entire program, making it possible to use

descriptive names instead of just numbers in your program.

In your system, the VCR, CD player, and cassette deck IR devices have channels that activate the

various transport functions, such as Play and Stop. As a general rule, Play is usually channel 1 and

Stop is channel 2. You could define these channel numbers as constants in your program to make it

more readable. DEFINE_CONSTANT

(* TRANSPORT (IR DEVICE) CHANNEL NUMBERS *)PLAY = 1STOP = 2PAUSE = 3FFWD = 4REW = 5

(* THE RELAY DEVICE CHANNEL DEFINITIONS *)SCREEN_UP = 1SCREEN_DOWN = 2SYS_POWER = 3DRAPE_OPEN = 4DRAPE_CLOSE = 5DRAPE_STOP = 6

(* THE LIGHTS DEVICE CHANNEL DEFINITIONS *)LIGHT_FULL = 1LIGHT_MED = 2LIGHT_LOW = 3LIGHT_OFF = 4

The value of the constant PLAY is 1. STOP has a value of 2. Both of these values cannot be changed

anywhere in the program. Later in your program when you need to activate the Play function of the

VCR, you don’t have to remember that it is channel 1 of the device—just use the constant PLAY and

the system knows to use channel 1. This works in a similar fashion to the DEFINE_DEVICE section.

You don't have to remember the full address of the device just what you called it. So you can write

code as:PULSE [VCR, PLAY]

This used the DEFINE_DEVICE reference and the DEFINE constant reference. Without these

references the code would have to be written as:PULSE [5001:8:0, 1]

If you have a number of devices with varying functions the device and channel numbers could be

difficult to remember. DEFINE_DEVICE and DEFINE_CONSTANT can help reduce that confusion.

By definition, the same constant cannot reference more than one number. This may seem obvious,

but this type of error could work its way into large programs. If you make this mistake, the compiler

will notify you with a “Duplicate symbol” error message upon compiling.

Page 17: Amx Netlinx Programming Ba01

Chapter 2 - The Definition Sections

10 Introduction to AMX Programming

Defining VariablesVariables are places to store data that will change as the program is executed. Think of a variable as

a "storage box;" nearly anything can be placed in here. Variables can hold many types of data. But,

any single variable can only hold one type of data. Since a variable can hold only one of several

possible types of data, you must specify what type of data is going into the variable when it is

defined. This 'box' that we are referring to is really an allocation of memory inside the processor.

Inside that memory the processor will store a value that can change based on the events that occur

and how the program is written to handle those events. Depending on what you are trying to

accomplish you may need to store integer values. An integer is an numeric value between 0 and

65535. Then again, you may have a situation which requires you to store character values.

Characters are letters or numbers between 0 and 255. If you do not define the type of data to be

stored in a variable when it is defined the processor will default the variable type to Integer.

Just as variables can store different types of data, they have different behavior characteristics.

Some variables retain there values even after the Master processor is powered off and some do not.

Some variables can be used throughout the whole program and some only in certain subsections.

These concepts will be covered in further detail as you get more involved in programming. For now,

you just need to understand that variables can hold different types of data and that these values can

change while the program is running.

In your first program you will not be using variables, but keep the DEFINE_VARIABLE header

because you will be using them in the future. The DEFINE_MUTUALLY_EXCLUSIVE section is also

used and explained later.

Page 18: Amx Netlinx Programming Ba01

Chapter 2 - The Definition Sections

11Introduction to AMX Programming

Startup CodeWhen the AMX Control System is turned on, the program that was last loaded into the system will

begin to operate. However, you can tell the system to run a series of statements immediately when

the system is turned on. These statements are placed under the DEFINE_START header, and they

are run only once on power-up. They cannot be executed again until another system power-up. In

your program, you may want to reset all three decks to STOP when the system is powered up. Here

is what your DEFINE_START section should look like:

DEFINE_START

PULSE[VCR,STOP]PULSE[CD,STOP]PULSE[CASS,STOP]

Remember, code in this section will only run when the Master processor powers up. Typically,

control systems will not be rebooted once they are in place. However, they may lose power, have

code reloaded, system maintenance, etc. Any of these situations could cause a reboot of the Master

which would allow the DEFINE_START code to run.

DEFINE_EVENT and Mainline in NetLinxThe DEFINE_EVENT section and the DEFINE_PROGRAM section is where most of the programming

will take place. These two sections run concurrently but in different ways to give the programmer

options on how the system could work. The DEFINE_EVENT section allows extremely fast program

functions. It makes no difference how large the program is, each button press or other input is

immediately accomplished. This section is where the majority of our programming is completed.

The DEFINE_PROGRAM section (also called Mainline) accesses its programming in a loop fashion.

The processor continually scans the program looking to keep all of its information current. The

processor starts at the beginning runs through the end of the program in order. Because of that, if

this section has a very large amount of programming, it could adversely affect the speed or timing

of the program. Therefore, it is recommended to put most of our programming in the

DEFINE_EVENT section.

Because the DEFINE_EVENT section is more efficient, when there is programming for a particular

button press in both sections, the Master will perform the programming in the DEFINE_EVENT

section and the programming in the DEFINE_PROGRAM section will be bypassed. So, the

DEFINE_PROGRAM section's primary role is maintaining feedback.

Figure 2, on page 12 illustrates message and mainline processing as it appears in the NetLinx

system. Note that bus servicing is taken care of by a separate process thread (Connection Manager

& Message Dispatcher) and therefore is not a task that must follow mainline.

You should avoid putting button presses in both sections of code even though the mainline section will be ignored in this event.

Page 19: Amx Netlinx Programming Ba01

Chapter 2 - The Definition Sections

12 Introduction to AMX Programming

FIG. 2 Message and Mainline Processing in the NetLinx System

d

Page 20: Amx Netlinx Programming Ba01

Chapter 3 - Using Input and Output

13Introduction to AMX Programming

Chapter 3 - Using Input and Output

Controlling Something Over ThereThe basic idea behind remote control is to do something over here to make something happen over

there. In an AMX system, the “something over here” is usually some kind of control panel, such as

a wireless remote control panel or a Touch Panel to generate an input. The “something over there”

can range from a simple relay to a complex lighting system to receive the output from the control

system.

In DEFINE_EVENT you define what happens when these inputs occur. But how do you get your

inputs in the program? How do you generate an output? The answer: you use devices and channels.

The Device-Channel ConceptEverything that is controlled by an AMX control system is considered to be a device on the system.

Each device in that system communicates to the master through control networks. Netlinx used 4

control networks: AXlink, ICSNet, ICSHub and Ethernet. Most devices, such as a Touch Panel or a

relay card, have channels which either accept an input, generate an output, or both. These inputs

and outputs are referred to in the program as a “device-channel pair,” which is written like this:

[8:1:0,1]

This device-channel references channel 1 of device 8 on port 1 in system 0. If device names and

constants are used instead of numbers, the same reference could look like this:

[VCR,PLAY]

Using device names and constants is obviously much more readable. This concept of the device-

channel is the most basic concept of the entire AMX control system, as it is the most common way

that the program communicates to the outside world.

All About the ChannelAlmost all methods of control using an AMX system require the use of channels on devices. Every

channel has two aspects: the input function and the output function. When a button is pressed on a

control panel, the input function of the button sends an input change to your program. The input

change alerts the Master to scan your program for a reference to that input.

In the NetLinx system a device can have multiple ports, therefore each port must be addressed. Additionally, since many NetLinx systems can be connected together, up to 65,535, each device receives the system ID of the connected Master. This addressing scheme is referred to as the Device:Port:System triplet.

Page 21: Amx Netlinx Programming Ba01

Chapter 3 - Using Input and Output

14 Introduction to AMX Programming

When there is an input change, the Master passes through the EVENT LIST section once to see if

the change is referenced. If so, the Master executes the statement(s) in the program associated with

the input change. There are 3 keywords used in conjunction with input changes:

PUSH

The PUSH keyword is used to find out if a channel has had an input change from “off” to “on,” such

as when a button is pressed. If the channel has been turned on, the corresponding PUSH statement is

activated. The operation or operations following this PUSH statement are only executed once after

the channel is turned on.

The BUTTON_EVENT/ PUSH keyword requires two parameters: a device number and a particular

channel enclosed in brackets. A device name or constant can be used in place of a literal number.

For example:

BUTTON_EVENT [10128:1:0,1]{ PUSH: {

Y = 2 Z = 3

}}

If PANEL is defined as device number 10128:1:0, and PLAY is defined as a constant with a value

of 1, the following is the same:

BUTTON_EVENT [PANEL, PLAY]{ PUSH: {

Y = 2 Z = 3

}}

Following the PUSH statement is the operation to be executed when the PUSH occurs. If more than

one event must happen, a compound statement must follow the PUSH. (See the earlier discussion on

compound statements.)

•PUSH

•RELEASE

•HOLD

Page 22: Amx Netlinx Programming Ba01

Chapter 3 - Using Input and Output

15Introduction to AMX Programming

RELEASE

The RELEASE keyword is used in the same way as a PUSH, except that the statements following a

RELEASE statement will be executed if the associated channel is released. For a button on a touch

panel this happens when you let up on the button.

BUTTON_EVENT [PANEL, PLAY]{ RELEASE: {

Y=1 }}

HOLD

A HOLD keyword specifies the actions that should be performed when a button is pressed and held

for a minimum length of time indicated by the Time Parameter. (TIME is specified in 0.1 second

increments). If a repeated action is desired at the same time increment, add the keyword REPEAT

within the Time Parameter brackets. Remember, REPEAT is optional.

BUTTON_EVENT [PANEL,PLAY]{ HOLD [TIME PARAMETER,REPEAT]: { Z=1 }}

All three of the keywords can be placed under the same BUTTON_EVENT.BUTTON_EVENT[PANEL,PLAY]{ PUSH: } RELEASE: { Y = 1 } HOLD[5]: { Z = 1 }}

Changing the State of a ChannelSo now you can respond to an input change in your program, and you want it to activate a different

device-channel. The next series of keywords allow you to activate channels based on an input

change. This activation is called an output change, which is a message to the output function of a

channel. The keywords to do this are:

•ON •TO

•OFF •PULSE

•TOTAL_OFF •MIN_TO

Page 23: Amx Netlinx Programming Ba01

Chapter 3 - Using Input and Output

16 Introduction to AMX Programming

When you use one of these keywords to activate a channel in a device, the device starts the

operation that is associated with the channel. For instance, activating channel 5 on a relay card

activates the physical relay number 5, whereas channel 5 on an infrared/serial card causes it to

generate the infrared pattern it has stored at location 5.

Variables can be used as output channels also, but doing so does not actually cause an output

change. When a variable is activated as a channel, turning it “on” gives it a value of 1 (or makes it

true), and turning it “off” gives it a value of 0 (or makes it false). Remember that in NetLinx

programming language off = false = 0 and on = true = any number greater than zero.

Following are brief definitions of each of the output change keywords.

ON

The ON keyword simply turns on a channel or variable. If the channel or variable is already on, its

status will remain unchanged. Here are two different examples:

ON[RELAY_CARD,2] //THIS TURNS ON CHANNEL 2 OF RELAY_CARD.

ON[TEMP] //This sets the value of the variable TEMP to 1.

A variable is considered “on” if it contains a nonzero number; in this case, the value is 1. If a

variable contains the value zero, it is considered “off.”

OFF

The OFF keyword turns a channel or variable off. The channel or variable will remain off if it is

already off. Here are two different examples:

OFF[RELAY_CARD,2] //THIS TURNS OFF CHANNEL 2 OF RELAY_CARD.

OFF[TEMP] //This sets the value of the variable TEMP to zero.

TOTAL_OFF

The TOTAL_OFF keyword acts in the same manner as OFF, except that it also turns off the status of

a channel or variable that is in a mutually exclusive set. Mutually exclusive sets are discussed later

in this unit.

PULSE

The PULSE keyword turns on a channel or variable for a certain amount of time. Once the time

elapses, the channel or variable is turned off. As an example, refer back to the discussion on

DEFINE_START. The PULSE keyword was used to activate the three decks’ Stop function. The

default duration of this pulse is one half-second, but it can be changed if necessary with the

SET_PULSE_TIME keyword. The pulse time is measured in tenths of seconds. The pulse time

remains the same value until it is changed within the program. For example:

SET_PULSE_TIME (12)

This sets the current duration of future pulses throughout the whole program to 1.2 seconds.

Page 24: Amx Netlinx Programming Ba01

Chapter 3 - Using Input and Output

17Introduction to AMX Programming

TO

The TO keyword is used to activate a channel or variable for as long as the corresponding device-

channel of its PUSH statement is activated. When the device-channel referenced by the PUSH

statement changes from OFF to ON, the TO starts activating the device-channel or variable in the

brackets following it. When the device-channel of its PUSH is released, the TO statement stops

activating its device-channel or variable. The TO keyword has several conditions:

! It must be used only below a PUSH statement.

! It cannot be used with the WAIT keyword. (This will be explained later.)

! It cannot be placed within the DEFINE_START section.

The channel or variable will act under the rules set by DEFINE_MUTUALLY_EXCLUSIVE. You will

learn what that definition section means later when you add more to your program.BUTTON_EVENT [PANEL, 6]{ PUSH: {

TO [RELAY, 6] // THE RELAY WILL TURN ON WHILE BUTTON HELD TO [TEMP] // THE VARIABLE WILL BE TRUE WHILE BUTTON HELD

}}

MIN_TO

The MIN_TO keyword is used to activate a channel or variable for at least a minimum amount of

time or as long as the corresponding device-channel of its PUSH statement is activated. When the

device-channel referenced by the PUSH statement changes from OFF to ON, the MIN_TO starts

activating the device-channel or variable in the brackets following it. When the device-channel of

its PUSH is released, the MIN_TO statement stops activating its device-channel or variable if the

button was held for at least the minimum amount of time as set by the pulse time. The MIN_TO

keyword has the same conditions as the TO keyword:

! It must be used only below a PUSH statement.

! It cannot be used with the WAIT keyword.

! It cannot be placed within the DEFINE_START section.

Direct Assignment

There is another method of generating an output change, but it does not involve the use of any

keywords. Any reference to a device-channel that does not have the keywords PUSH or RELEASE

preceding it is a reference to the output side of the channel. Thus assigning a value directly to a

device-channel changes the output of the channel. For example:

[PANEL,1] = 1

This statement will send an output change to channel 1 of device PANEL, telling the channel to turn

on since the master interprets any non-zero number as “on.” Putting this statement in mainline will

make the channel be forever on. Using direct assignment is only appropriate in feedback

statements. In most other situations, the keywords ON, OFF, and TO are more appropriate.

Page 25: Amx Netlinx Programming Ba01

Chapter 3 - Using Input and Output

18 Introduction to AMX Programming

Putting Input and Output TogetherCombining input and output changes into one statement is the basis of most AMX Control System

programming. Now that you have these tools, you can write the code that can actually accomplish

this. On your Touch Panel, you will have button numbers 1 through 5 activate the five transport

functions of the VCR: Play, Stop, Pause, Fast Forward, and Rewind. Here is your first section of

program code:

BUTTON_EVENT[TP,1]{

PUSH:{

PULSE[VCR,PLAY]}}BUTTON_EVENT[TP,2]{

PUSH:{

PULSE[VCR,STOP]}}BUTTON_EVENT[TP,3]{

PUSH:{

PULSE[VCR,PAUSE]}

In this code, there are actually five separate but similar statements. Examine the first to see how it

all fits together. First there is a BUTTON_EVENT, meaning we are programming in the

DEFINE_EVENT section. This is followed by a device-channel reference, in this case [TP,1]. Next,

an action takes place on the PUSH. This tells the control system, "If channel 1 on the 10128:1:0

device receives an input change from OFF to ON (i.e. someone pushed a button) execute the

statement that follows." If such an input change occurs, the corresponding PULSE statement

executes. The PULSE statement tells the control system, “When channel 1 on device 10128:1:0 is

activated, PULSE device 5001:8:0, channel 1.” You may be wondering where the numbers came

from, since the PUSH and PULSE statements have the words TP, VCR, and PLAY. Remember, TP and

VCR are identifiers for devices 10128:1:0 and 5001:8:0 respectively and PLAY is a constant with

a value of 1.

Duplicate the above section for the CD player and the cassette deck, replacing VCR with CD and

CASS where needed. Also be sure to use different channel numbers for the PUSH statements, or one

activation of channel 1 could make all three decks play at the same time. Touch Panel

BUTTON_EVENT numbers for the CD player are 9-13, for the Cassette deck use channels 17-21.

Now that you have the transport functions of your decks programmed, you can add the rest of the

functions on your panel to the program. But before you do that, you need to learn about the other

definition sections: those that define the characteristics of a channel.

Page 26: Amx Netlinx Programming Ba01

Chapter 4 - Channel Characteristics

19Introduction to AMX Programming

Chapter 4 - Channel Characteristics

The Parts of an Output ChannelAn output channel actually has two parts, the physical part and the status part (simply referred to as

“status”). The physical part is the device-dependent physical control, such as a relay on a relay

card, a button light (“lamp”) on a Touch Panel, or an infrared pattern in an infrared card. The

physical part of a channel can be only one of two things, on or off. The status is what records the

state of the physical part and reports it to the Master. In most applications, these two parts act

exactly the same; when one is on, so is the other.

However, you can change the way the status (or reporting) part of an output channel behaves. In this

chapter, you will be shown how to change the status behavior, which in turn changes the way a

channel reacts when it is activated by the output change keywords.

All channels are momentary by default.1 When a momentary channel is activated with a TO

keyword, it activates its output and status only as long as the button which activated the TO keyword

is pressed. For example, the Focus channel for a certain slide projector is momentary. When the

corresponding Focus button is pressed, the slide projector will focus. The projector will continue to

do so until the button is released.

Mutually ExclusiveChannels can also be defined as mutually exclusive. This will change their functionality somewhat.

A mutually exclusive group is a set of channels in which only one channel of the set can be turned

on at a time. When a channel is activated in a mutually exclusive set, it turns on its physical output

for the time period specified by the keyword being used. However, when the physical output stops

the status does not follow as it normally would. Even after the physical output stops, the status still

indicates that the channel is on until another channel in the mutually exclusive set is activated. The

status is on to let you know which channel in the set was last activated. This is sometimes called

“last button pressed” feedback.

Before a channel or variable in this set is activated, all the other members of the set are turned off

beforehand. This is called “break before make” logic. This prevents an accidental activation of

more than one channel at the same time, which could cause serious damage to some devices.

For example, consider the drape and screen channels of the device RELAY. Since you cannot open

and close a drape all at once, and you cannot raise a screen and lower it at the same instant (it could

damage some motors if you tried!), only one channel can be turned on at a time. They must be

defined as mutually exclusive. When SCREEN_UP is activated, the SCREEN_DOWN channel is turned

1. Actually, the correct terminology here is the status of all channels is momentary by default. However, in the common language of programmers, �status� is understood. From this point on in the manual, the behavior of status will be described in this manner.

Page 27: Amx Netlinx Programming Ba01

Chapter 4 - Channel Characteristics

20 Introduction to AMX Programming

off and SCREEN_UP turns on. The corresponding SCREEN_UP status stays on even though the relay

is de-energized when the button is released. When SCREEN_DOWN is activated, SCREEN_UP is

turned off. The SCREEN_DOWN status is now the only status turned on.

You also will define the lighting relays as mutually exclusive so that you can utilize the “last button

pressed” logic when you program the feedback for these buttons. This will allow the user to look at

the panel and know which lighting preset he or she activated last.

Members of a mutually exclusive set are placed in parentheses underneath the

DEFINE_MUTUALLY_EXCLUSIVE keyword. The double period (..) shortcut is used to indicate a

range of channels. The example below would be used to define Mutually Exclusive channels for the

devices and channels illustrated on FIG. 1 on page 8 of this manual:

DEFINE_MUTUALLY_EXCLUSIVE([RELAY,SCREEN_UP],[RELAY,SCREEN_DOWN]) // RELAY CHANNELS 1 AND 2([RELAY,DRAPE_OPEN]..[RELAY,DRAPE_STOP]) // RELAY CHANNELS 4 - 6([LIGHTS,LIGHT_FULL]..[LIGHTS,LIGHT_OFF]) // LIGHTS CHANNELS 1 - 4([VCR,PLAY]..[VCR,REW]) // VCR TRANSPORT CHANNELS 1 - 5([CASS,PLAY]..[CASS,REW]) // CASS TRANSPORT CHANNELS 1 - 5([CD,PLAY]..[CD,REW]) // CD TRANSPORT CHANNELS 1 - 5

The first set defines the two screen channels as mutually exclusive. Using the shortcut, the second

set defines the three drape channels as mutually exclusive, and the third set defines the four lighting

relays as mutually exclusive. The fourth through the last sets also use the shortcut to define the five

transport functions as mutually exclusive. This is done to achieve “last button pressed” status for

those decks. When you add the feedback statements to the program, the buttons for the VCR, CD

player, and cassette deck will indicate the last button selected from each group.

Once a channel has its status turned on in a mutually exclusive group, there will always be one

channel with its status on in that group, unless it is turned off with the TOTAL_OFF keyword. The

TOTAL_OFF keyword is used when you need to turn off the physical channel and its status.

Page 28: Amx Netlinx Programming Ba01

Chapter 4 - Channel Characteristics

21Introduction to AMX Programming

Putting it All to WorkNow that you know how all these different types of channels operate, you can skip down to the

mainline section of the program and add these lines to activate your system power, screen, drape,

and lighting relays:

BUTTON_EVENT[TP,31]{ PUSH: { ON[RELAY,SYS_POWER] }}BUTTON_EVENT[TP,32]{ PUSH: { OFF[RELAY,SYS_POWER] }}BUTTON_EVENT[TP,33]{ PUSH: { PULSE[RELAY,SCREEN_UP] }}BUTTON_EVENT[TP,34]{ PUSH: { PULSE[RELAY,SCREEN_DOWN] }}BUTTON_EVENT[TP,41]{ PUSH: { ON [RELAY,DRAPE_OPEN] } RELEASE: { OFF [RELAY, DRAPE_OPEN] } }BUTTON_EVENT[TP,42]{ PUSH: { TO[RELAY,DRAPE_CLOSE] }}BUTTON_EVENT[TP,43]{ PUSH: { PULSE[RELAY,DRAPE_STOP]

Page 29: Amx Netlinx Programming Ba01

Chapter 4 - Channel Characteristics

22 Introduction to AMX Programming

} RELEASE: {

OFF[RELAY,DRAPE_STOP] }}BUTTON_EVENT[TP,45]{ PUSH: { ON[LIGHTS,LIGHT_FULL] }}BUTTON_EVENT[TP,46]{ PUSH: { ON[LIGHTS,LIGHT_MED] }}BUTTON_EVENT[TP,48]{ PUSH[TP,48] { ON[LIGHTS,LIGHT_OFF] }}

This section accomplishes several tasks:

! A press of the System Power On button turns on the SYS_POWER channel on the device

RELAY.

! A press of the System Power Off button turns off the SYS_POWER channel on the device

RELAY.

! A press of the Screen Up button will pulse the SCREEN_UP channel on device RELAY,

after turning off SCREEN_DOWN. The Screen Down button acts the same way as the

Screen Up button, but with the opposite channels. Remember that the PULSE command

will activate the channel for the specified pulse time. The default pulse time is one half

second.

! Pressing Drape Open, Drape Close or Drape Stop does several things. Button event 41 is

written

! so that the Drape Open channel will turn on when the button is pressed and off when the

button is released.

Page 30: Amx Netlinx Programming Ba01

Chapter 4 - Channel Characteristics

23Introduction to AMX Programming

! If it is off, it makes sure the other drape channels are off (due to its mutually exclusive

relationship), before it turns on. Button event 42 accomplishes the same thing but it uses

the TO keyword. The TO keyword automatically turns the channel on when the button is

pressed and off when it is released. With the TO keyword, the programmer does not have

to handle the ON and OFF commands with the PUSH and RELEASE of the button. These

two buttons will do the same thing. When the Drape Stop button is pressed it will PULSE

the DRAPE_STOP relay on the relay device. The physical relay will only be active for the

pulse but its status (feedback) remains on. (Remember, to turn off the status of a channel

in a mutually exclusive group, use the keyword TOTAL_OFF.)

! Since the LIGHTS channels are mutually exclusive, a press of the Lights Full button turns

on the LIGHT_FULL channel on the device LIGHTS, after turning off any LIGHTS channel

that was previously on. The other LIGHTS channels operate in a similar fashion. Since

this code is written using the ON command both the physical relay and the status of that

relay will stay on indefinitely unless another one of the relays in the Mutually Exclusive

Group is pressed. Notice that the program has no way to turn off any of the channels.

This is done by the fact that channels are part of a Mutually Exclusive Group.

Programming FeedbackSo far you have been shown how a channel’s output is affected in a program. You know what to do

with the input changes and how to create output changes, but now you want to see some feedback

on your control panel. Feedback refers to the lighting of a button during and after it is pressed. The

Master will not do this automatically; you must tell the system how to light the button. Feedback

involves only one statement per button. The first part of the statement references the device-channel

of the button that is going to be lit. It is followed by an equal sign (=) and the device-channel

corresponding to the source of the feedback, this is called Direct Assignment Feedback. For

example:

[TP,1] = [VCR,PLAY]

The light of touch panel channel one will be on when VCR channel 1 (constant value of PLAY) is

on. When the channel is off, the light will be off. Remember that any reference to a device-channel

that does not have the keyword PUSH or RELEASE preceding it is referring to the output side of the

channel. This is a very important concept, because it is the basis of how feedback works.

Also recall that one way of creating an output change is to assign a value directly to the device-

channel. If the value that you are assigning is another device-channel reference, this is in effect

saying to the system, “Take the output status of channel PLAY on device VCR, and send it as an

output change to channel 1 of device TP.” (In other words, reading from left to right.) "Make this

([TP,1]) equal to that ([VCR, PLAY])." So the first device-channel pair is going to be changed

to equal the state of the second pair. "Since you defined the device-channel [VCR,PLAY] as being

Remember that the left side always equals the right side. So, for feedback purposes you will always need to list the device channel pairing of the touch panel to the left of the device channel pairing that you wish to tie the feedback to. Touch Panel channel 1 must be equal to VCR channel PLAY. If you write the code the opposite way, the meaning changes entirely.

Page 31: Amx Netlinx Programming Ba01

Chapter 4 - Channel Characteristics

24 Introduction to AMX Programming

in a mutually exclusive group, its status will be on if it was the last channel activated in that set, and

the feedback assignment will light button 1 on the control panel. Once a channel has feedback on in

a mutually exclusive group, there will always be one channel with feedback on in that group, until

turned off with TOTAL_OFF.

Grouping Feedback StatementsThe feedback statements can be grouped together in a feedback section at the end of the program.

as shown below:

[TP,1] = [VCR,PLAY]

[TP,2] = [VCR,STOP]

[TP,3] = [VCR,PAUSE]

Direct Assignment feedback statements should only be placed in the DEFINE_PROGRAM section of

the program, so it will be updated on a regular basis regardless of event status.

It is recommended that you break your feedback into groups with headings. You can create headings by using comments in your program. This will allow the feedback to be broken into groups in the Mainline section of code that corresponds to hoe the code is written in the DEFINE_EVENT section. For smaller programs this may not be necessary.

Page 32: Amx Netlinx Programming Ba01

Unit 2: Conditionals and Waits

25Introduction to AMX Programming

Unit 2: Conditionals and Waits

Chapter 5 – Conditional Expressions

IntroductionWhile your first program may look complicated at first, it really doesn’t show the power of the

AMX programming languages. The program is what we at AMX call “one-to-one.” That means

that each button has one and only one function, with no special conditions or considerations. The

control panel has a separate section of buttons for each piece of equipment. (See FIG. 1)

FIG. 1 G3 Panel with each button having it’s only one function.

The companion code to this section is called STEP 1a.

Page 33: Amx Netlinx Programming Ba01

Chapter 5 – Conditional Expressions

26 Introduction to AMX Programming

PROGRAM_NAME='STEP1'

(* DATE:03/15/02 TIME:12:00:00 *)

(***********************************************************)

(* DEVICE NUMBER DEFINITIONS GO BELOW *)

(***********************************************************)

DEFINE_DEVICE

RELAY = 5001:8:0 (*NI-3000 RELAY OUTPUTS 1-8 *)

VCR = 5001:9:0 (*NI-3000 IR OUTPUT #1*)

CD = 5001:10:0 (*NI-3000 IR OUTPUT #2*)

CASS = 5001:11:0 (*NI-3000 IR OUTPUT #3*)

LIGHTS = 5001:16:0 (*NI-3000 I/O 1-4*)

TP = 10128:1:0 (*NXT-CV15 TOUCH PANEL*)

(***********************************************************)

(* CONSTANT DEFINITIONS GO BELOW *)

(***********************************************************)

DEFINE_CONSTANT

(* TRANSPORT CHANNEL NUMBERS *)

PLAY = 1

STOP = 2

PAUSE = 3

FFWD = 4

REW = 5

(* THE RELAY CARD CHANNEL DEFINITIONS *)

SCREEN_UP = 1

SCREEN_DOWN = 2

SYS_POWER = 3

DRAPE_OPEN = 4

DRAPE_CLOSE = 5

DRAPE_STOP = 6

(* THE LIGHT CARD CHANNEL DEFINITIONS *)

LIGHT_FULL = 1

LIGHT_MED = 2

LIGHT_LOW = 3

LIGHT_OFF = 4

(***********************************************************)

(* VARIABLE DEFINITIONS GO BELOW *)

(***********************************************************)

DEFINE_VARIABLE

(***********************************************************)

(* LATCHING DEFINITIONS GO BELOW *)

(***********************************************************)

DEFINE_LATCHING

(***********************************************************)

(* MUTUALLY EXCLUSIVE DEFINITIONS GO BELOW *)

(***********************************************************)

DEFINE_MUTUALLY_EXCLUSIVE

([RELAY,SCREEN_UP],[RELAY,SCREEN_DOWN])

([RELAY,DRAPE_OPEN]..[RELAY,DRAPE_STOP])

([LIGHTS,LIGHT_FULL]..[LIGHTS,LIGHT_OFF])

([VCR,PLAY]..[VCR,REW])

([CASS,PLAY]..[CASS,REW])

([CD,PLAY]..[CD,REW])

(***********************************************************)

(* STARTUP CODE GOES BELOW *)

Page 34: Amx Netlinx Programming Ba01

Chapter 5 – Conditional Expressions

27Introduction to AMX Programming

(***********************************************************)

DEFINE_START

PULSE [VCR,STOP]

PULSE [CD,STOP]

PULSE [CASS,STOP]

(***********************************************************)

(* THE EVENTS GO BELOW *)

(***********************************************************)

DEFINE_EVENT

BUTTON_EVENT[TP,1]

{

PUSH:

{

PULSE[VCR,PLAY]

}

}

BUTTON_EVENT[TP,2]

{

PUSH:

{

PULSE[VCR,STOP]

}

}

BUTTON_EVENT[TP,3]

{

PUSH:

{

PULSE[VCR,PAUSE]

}

}

BUTTON_EVENT[TP,4]

{

PUSH:

{

PULSE[VCR,FFWD]

}

}

BUTTON_EVENT[TP,5]

{

PUSH:

{

PULSE[VCR,REW]

}

}

BUTTON_EVENT[TP,9]

{

PUSH:

{

PULSE[CD,PLAY]

}

}

BUTTON_EVENT[TP,10]

{

PUSH:

Page 35: Amx Netlinx Programming Ba01

Chapter 5 – Conditional Expressions

28 Introduction to AMX Programming

{

PULSE[CD,STOP]

}

}

BUTTON_EVENT[TP,11]

{

PUSH:

{

PULSE[CD,PAUSE]

}

}

BUTTON_EVENT[TP,12]

{

PUSH:

{

PULSE[CD,FFWD]

}

}

BUTTON_EVENT[TP,13]

{

PUSH:

{

PULSE[CD,REW]

}

}

BUTTON_EVENT[TP,17]

{

PUSH:

{

PULSE[CASS,PLAY]

}

}

BUTTON_EVENT[TP,18]

{

PUSH:

{

PULSE[CASS,STOP]

}

}

BUTTON_EVENT[TP,19]

{

PUSH:

{

PULSE[CASS,PAUSE]

}

}

BUTTON_EVENT[TP,20]

{

PUSH:

{

PULSE[CASS,FFWD]

}

}

BUTTON_EVENT[TP,21]

Page 36: Amx Netlinx Programming Ba01

Chapter 5 – Conditional Expressions

29Introduction to AMX Programming

{

PUSH:

{

PULSE[CASS,REW]

}

}

BUTTON_EVENT[TP,31]

{

PUSH:

{

ON[RELAY,SYS_POWER]

}

}

BUTTON_EVENT[TP,32]

{

PUSH:

{

OFF[RELAY,SYS_POWER]

}

}

BUTTON_EVENT[TP,33]

{

PUSH:

{

PULSE[RELAY,SCREEN_UP]

}

}

BUTTON_EVENT[TP,34]

{

PUSH:

{

PULSE[RELAY,SCREEN_DOWN]

}

}

BUTTON_EVENT[TP,41]

{

PUSH:

{

ON [RELAY,DRAPE_OPEN]

}

RELEASE:

{

OFF [RELAY, DRAPE_OPEN]

}

}

BUTTON_EVENT[TP,42]

{

PUSH:

{

TO [RELAY,DRAPE_CLOSE]

}

}

BUTTON_EVENT[TP,43]

{

Page 37: Amx Netlinx Programming Ba01

Chapter 5 – Conditional Expressions

30 Introduction to AMX Programming

PUSH:

{

PULSE[RELAY,DRAPE_STOP]

}

}

BUTTON_EVENT[TP,45]

{

PUSH:

{

ON[LIGHTS,LIGHT_FULL]

}

}

BUTTON_EVENT[TP,46]

{

PUSH:

{

ON [LIGHTS,LIGHT_MED]

}

}

BUTTON_EVENT[TP,47]

{

PUSH:

{

ON [LIGHTS,LIGHT_LOW]

}

}

BUTTON_EVENT[TP,48]

{

PUSH:

{

ON[LIGHTS,LIGHT_OFF]

}

}

(***********************************************************)

(* THE ACTUAL PROGRAM GOES BELOW *)

(***********************************************************)

(* FEEDBACK *)

[TP,1] = [VCR,PLAY]

[TP,2] = [VCR,STOP]

[TP,3] = [VCR,PAUSE]

[TP,4] = [VCR,FFWD]

[TP,5] = [VCR,REW]

[TP,9] = [CD,PLAY]

[TP,10] = [CD,STOP]

[TP,11] = [CD,PAUSE]

[TP,12] = [CD,FFWD]

[TP,13] = [CD,REW]

[TP,17] = [CASS,PLAY]

[TP,18] = [CASS,STOP]

[TP,19] = [CASS,PAUSE]

[TP,20] = [CASS,FFWD]

[TP,21] = [CASS,REW]

[TP,31] = [RELAY,SYS_POWER]

[TP,32] = ([RELAY,SYS_POWER] = 0) // SYS_POWER RELAY IS OFF

Page 38: Amx Netlinx Programming Ba01

Chapter 5 – Conditional Expressions

31Introduction to AMX Programming

[TP,33] = [RELAY,SCREEN_UP]

[TP,34] = [RELAY,SCREEN_DOWN]

[TP,41] = [RELAY,DRAPE_OPEN]

[TP,42] = [RELAY,DRAPE_CLOSE]

[TP,43] = [RELAY,DRAPE_STOP]

[TP,45] = [LIGHTS,LIGHT_FULL]

[TP,46] = [LIGHTS,LIGHT_MED]

[TP,47] = [LIGHTS,LIGHT_LOW]

[TP,48] = [LIGHTS,LIGHT_OFF]

(***********************************************************)

(* END OF PROGRAM *)

(* DO NOT PUT ANY CODE BELOW THIS COMMENT *)

(***********************************************************)

Page 39: Amx Netlinx Programming Ba01

Chapter 5 – Conditional Expressions

32 Introduction to AMX Programming

But suppose you want the same number of functions with fewer buttons. A common solution is to

have several groups of buttons with similar functions reduced to one group, with a set of buttons

that selects which piece of equipment the buttons control. In your program, you could have one

button for each piece of equipment to select each deck, and one set of transport buttons. Your panel

could now look like FIG. 2:

You now have fewer buttons than you did before. What you want to happen with this panel is that

the user selects the deck with a Select button, then controls it with the Transport buttons. This will

not be a one-to-one program because the Transport buttons each have three possible functions. In

the program you will use conditional expressions to select the correct function of the Transport

buttons. Additionally, the System Power has been reduced to one toggling button, which will have

its feedback turned on when the system is powered and off when the system is not powered. In

other words, one button will perform different functions based on a given condition.

FIG. 2 G3 Panel with multi-functional transport buttons

The companion code to this section is STEP2a

Page 40: Amx Netlinx Programming Ba01

Chapter 5 – Conditional Expressions

33Introduction to AMX Programming

Conditional ExpressionsA conditional expression is used to tell the system whether or not to execute a particular function or

functions in the program. Picture yourself walking along a path in the country. Suddenly you come

upon a fork in the road. Which way should you go? If you guess, you might become lost. Therefore

you judge certain conditions before continuing. Is the left road heading north? Is the right road

heading east?

This is what the Master must do whenever you branch off in different directions in your program.

Either the Master continues in the direction it is going, or it must jump to a different section.

A conditional expression can have one of two results, true or false. In AMX programming, any non-

zero value is true and a zero value is false. When the Master evaluates a conditional expression, it

assigns a 1 for a true result, and a zero for a false result.

The IF StatementThe most common keyword in AMX programming that uses conditional expressions is the IF

keyword. Every IF statement must be followed by a conditional expression enclosed in

parentheses. This provides the beginning of a conditional execution of statements. The structure is

as follows:

IF(conditional expression){

Statement 1}

If the conditional expression is true, the Master executes Statement 1 and then continues with

whatever statements follow. If the conditional expression is false, Statement 1 is ignored. The

braces indicate that the statement below the condition is a subset. As such, the subset will only be

executed if the condition is true.

The IF...ELSE Set of StatementsThis is similar to the basic IF statement, with the addition of one more branch. If the conditional

expression is false, the Master executes a function independent of the “true” conditional expression.

For example:

IF(conditional expression){

Statement 1}ELSE{

Statement 2}

If the conditional statement is true, then Statement 1 is executed. Statement 2, underneath the ELSE

statement, is ignored. If the conditional statement is false, then Statement 2 is executed. Remember

that Statement 1 is automatically ignored if the expression is false.

Page 41: Amx Netlinx Programming Ba01

Chapter 5 – Conditional Expressions

34 Introduction to AMX Programming

Repeating IF...ELSE Set of StatementsUsing IF... ELSE allows two different paths for conditional branching. By repeating the

IF... ELSE statements multiple paths can be created. The Master will stop conditional evaluation

at the first true conditional expression and execute the associated statements. After completion, it

goes on to the rest of the program. For example:

IF(Conditional expression){

Statement 1}ELSE{

IF(Conditional expression){

Statement 2}ELSE{

IF(Conditional expression){ Statement 3}ELSE{ Statement 4}

}}

The last ELSE statement placed at the end of the conditional branching operates as a default

statement. That is, if the Master processor does not find a true IF statement, it executes the final

ELSE statement. However, the last ELSE statement is not necessary.

NestingOnce the Master processor is traversing along an IF branch you can tell it to branch off again with

another IF statement. This “branch within a branch” is called nesting. An IF can be within an IF

within an IF, and so on. The only restriction is the amount of memory available.

When you are nesting IF... ELSE statements, be sure to use braces. Look at the following

incorrect example:IF(X = 5){ Statement 1A IF(Y = 10) { Statement 1B }ELSE{ Statement 2}}

Page 42: Amx Netlinx Programming Ba01

Chapter 5 – Conditional Expressions

35Introduction to AMX Programming

Even though the alignment suggests the ELSE goes with the first IF, the braces force it to go with

the second (nested) IF. The second IF statement is not supposed to have an ELSE counterpart in

this example. However, such is not the case. The Master pairs the second IF statement with the

ELSE, because both are within the compound statement created by the first and last braces. By

rearranging the braces you can force the compiler to associate the ELSE with IF(X = 5). For

example:

IF(X = 5){

Statement 1AIF(Y = 10){

Statement 1B }}ELSE{

Statement 2}

By using the braces, you isolate the IF(Y = 10) statement from the IF... ELSE set of

statements.

The SELECT...ACTIVE StatementThere is a way to make nesting easier: the SELECT...ACTIVE statement. This allows the easy

placement of several branches from one path. Here is the format:

SELECT{

ACTIVE(conditional expression 1):{

Statement 1}ACTIVE(conditional expression 2):{

Statement 2}ACTIVE(conditional expression 3):{

Statement 3}(* ...etc. *)

}

Each one of the conditional expressions, in order, is evaluated until one is found to be true. The

statements associated with that true expression are then executed, and the path then flows to

whatever statements follow the closing brace. So if there are five conditional statements to evaluate

and the second one is true, its statements will be executed. The 3rd, 4th and 5th conditional

statements will never be checked. The processor will go to the statement following the closing

brace of the SELECT...ACTIVE. Using a SELECT...ACTIVE is much preferred to multiple

IF...ELSE statements; it uses less memory and it runs faster. If too many IF...ELSE

statements are chained together, they can overflow the Master processor memory and crash the

Page 43: Amx Netlinx Programming Ba01

Chapter 5 – Conditional Expressions

36 Introduction to AMX Programming

So what happens in a SELECT...ACTIVE if none of the conditions evaluate as true? In such a

case, no code of any ACTIVE statement will be executed, since SELECT...ACTIVE has no default

statement. You can, however, create your own default for a SELECT...ACTIVE:

SELECT{

ACTIVE(conditional expression 1):{

Statement 1}ACTIVE(conditional expression 2):{

Statement 2}ACTIVE(conditional expression 3):{

Statement 3}ACTIVE(1):{

Default statement}

}

Here, the last ACTIVE will always be true (remember in AMX programming a 1 is true and a 0 is

false), and will execute only if all of the conditions of the previous ACTIVE statements are false.

This makes the last ACTIVE statement the default statement.

Trying it OutNow you can write the code for your new panel layout. Before you do, however, you will need to

update your definition sections a little. The preferred method of implementing “select groups” is to

use one variable and change its value based on which deck is selected.

The “Variable Assignment” Method

Assigning different values to one variable depending on what is selected is the preferred method of

programming select groups. This method is actually more powerful than other methods, as it

provides more flexibility while using a lot less code.

First add just one variable, DECK to the program you wrote previously. This will be the select

variable. For a NetLinx Master you will define the variable to contain NetLinx device address

information by using the DEV keyword as shown below:

! DEFINE_VARIABLE

! DEV DECK

As we learned early in this manual, there are different types of variables. Meaning that variables

can hold different types of data. DEV is one type available to you in Netlinx. A DEV variable can

hold the Netlinx device address information in it. Meaning that if we create a variable called DECK

of type DEV, DECK will be able to store D:P:S info of any of the devices we declared in the

DEFINE_DEVICE section.

Page 44: Amx Netlinx Programming Ba01

Chapter 5 – Conditional Expressions

37Introduction to AMX Programming

Based on the code we already wrote in Step 1, DECK would be able to hold the Netlinx address

value of RELAY, VCR, CD, CASS, LIGHTS or TP. However, we don't want to hold all of these,

we just want to differentiate between which deck we are currently choosing to control.

The code below allows us to use certain buttons to change the value of DECK. Notice there is no way

to make DECK equal to TP. Even though our DEV variable can hold that information, that is not what

we want. We only want to be able to switch between the VCR, CD or CASS. That is done by using the

Device Select buttons on FIG. 2 on page 32 and the code written just below:

BUTTON_EVENT[TP,1]{ PUSH: { DECK=VCR }}BUTTON_EVENT[TP,2]{ PUSH: { DECK=CD }}BUTTON_EVENT[TP,3]{ PUSH: { DECK=CASS }}

Page 45: Amx Netlinx Programming Ba01

Chapter 5 – Conditional Expressions

38 Introduction to AMX Programming

You can reduce the number of transport sections from three to just one by using the variable DECK

as the device number in the PULSE statements, instead of using VCR, CD, and CASS. Here’s the

section of code:

BUTTON_EVENT[TP,17]{ PUSH: { PULSE[DECK,PLAY] }}BUTTON_EVENT[TP,18]{ PUSH: { PULSE[DECK,STOP] }}BUTTON_EVENT[TP,19]{ PUSH: { PULSE[DECK,PAUSE] }}BUTTON_EVENT[TP,20]{ PUSH[TP,20] { PULSE[DECK,FFWD] }}BUTTON_EVENT[TP,21]{ PUSH: { PULSE[DECK,REW] } }

Notice that no IF statement and no mutually exclusive variables are necessary for the variable

DECK, and this is the only deck transport section of programming needed in the whole program! But

how does this work? Suppose you want to play the CD player. First you press the CD Select button.

This assigns the value 5001:10:0 (the constant value of CD device) to the variable DECK. Now the

device-channel references of the PULSE transport statements will reference device number

5001:10:0 (the CD device). Pressing button number 17 on the Touch Panel will activate

[DECK,PLAY], which the Master will interpret as [5001:10:0,1].

The feedback for the transport section works in the same manner as the control section. The

feedback statements use the DECK variable as the device from which to get the feedback. These

statements for the selection buttons, however, are something new:[TP,1] = (DECK=VCR)[TP,2] = (DECK=CD)[TP,3] = (DECK=CASS)

Page 46: Amx Netlinx Programming Ba01

Chapter 5 – Conditional Expressions

39Introduction to AMX Programming

These statements, like all feedback statements, are direct assignment output changes; however, the

source of the assignment is a conditional expression. In interpreting this kind of feedback

statement, the master first evaluates the conditional expression. If the expression is evaluated as

true, the expression is replaced with a 1; otherwise it is replaced with a zero. (Remember, only one

of these will be evaluated as true because a variable cannot have two different values at one time.)

Thus the direct assignment will assign a 1 (”on”) to the Touch Panel button for which the

expression is true, and a zero (”off”) to the false ones. Recall that assigning a 1 to a device-channel

is the same as turning the output of a device-channel on

Conditional OperatorsThe previously discussed IF and IF...ELSE statements can only base the program flow on one

condition. You can, however, combine two of these conditions with a conditional operator. This

operator sets the rules for determining the end result.

The conditional operators used in AMX systems are AND, OR, XOR, and NOT. These are placed in

between the two conditions after the IF statement. For example:

IF((X = 10) AND (Y = 5)){

Statement 1}

For this condition to be met, 2 things have to be true. X must be equal to 10 and Y must be equal to

5. If the end result of the conditional expression is true, the system continues with Statement 1. If

the end result is false, the system simply ignores Statement 1.

In most conditional expressions, the possible conditions of two statements are analyzed to achieve

one result. A text formula can be followed to find that result:

""If <condition 1 (true/false)> <conditional operator> <condition 2

(true/false)>, then the result of the expression is true or false."

The result is found by basing the conditions of the statements against the rules set by the

conditional operator. Here are those specific rules:

AND Both statements must be true for the result to be true.

OR At least one of the conditions must be true for the result to be true.

XOR Only one statement can be true for the result to be true.

NOT If the statement is true, the result is false. On the contrary, if the condition is false, the

result is true. This expression uses only one statement.

Consider the following IF statement:

IF((NUM1 = 5) AND (NUM2 = 4))

Assume that it has been previously defined that NUM1 = 5 and NUM2 = 3. Insert the variables from

the example into the text formula:

”If NUM1 = 5 is true and NUM2 = 4 is false, then the result of the expression is false.”

Page 47: Amx Netlinx Programming Ba01

Chapter 5 – Conditional Expressions

40 Introduction to AMX Programming

The statement would have been true if NUM2 had been equal to 3, because in an AND expression both

statements must be true.

We can use the NOT operator to allow us to program the single power button on this touch panel

layout. Since the state of an output channel can be on (1) or off (0), using the NOT operator on a

device channel will change its state from off to on or on to off. The code for this button is shown

below:BUTTON_EVENT[TP,31]{ PUSH: { [RELAY,SYS_POWER] = NOT[RELAY,SYS_POWER] }}

Each press of the button will toggle the state of the SYS_POWER relay. If we did not use the NOT

operator to toggle the state, of SYS_POWER we would have to write out the conditional evaluations

and each action separately. The code below does the same thing without the NOT operator. Notice

the extra lines of code required.BUTTON_EVENT[TP,31]{ PUSH: { IF ([RELAY, SYS_POWER]) { OFF [RELAY,SYS_POWER] } ELSE IF ([RELAY, SYS_POWER]=0) { ON [RELAY, SYS_POWER] } } }

The feedback for this button will track the state of the relay channel:[TP,31] = [RELAY,SYS_POWER]

This would work with either method of code above.

The conditional operators can be abbreviated in your program as shown below:

Conditional Operator Abbreviations

Abbreviation Function Abbreviation Function

&& Logical AND & Bitwise AND

|| Logical OR | Bitwise OR

^^ Logical XOR ^ Bitwise XOR

! Logical NOT ~ Bitwise NOT

Page 48: Amx Netlinx Programming Ba01

Chapter 6 – The Wait Keywords

41Introduction to AMX Programming

Chapter 6 – The Wait Keywords

Controlling Time Within the AMX SystemWithin the AMX system there are a variety of timing keywords available for your use. Functions

can be delayed for a few seconds, or they can be delayed until certain conditions are right. This

chapter will help you learn each of these keywords and show you how to apply them to your

programs.

You will build on your previous program, but this time you will not be changing the layout of your

Touch Panel, you’ll just add more functions to the existing buttons.

The WAIT ListThe most common keyword relating to time is the WAIT keyword, which is used to activate

functions after a specified delay time has elapsed. The program flow does not stop when a WAIT is

encountered. Instead, the Master places the statement associated with the WAIT keyword into a list

in memory and continues on with the rest of the program. The Master scans this list, and if any

WAITs have come due, the Master executes the statement or compound statement associated with

the expired WAIT keyword. Up to 50 WAIT references are allowed in the list at a time.

Time in the WAIT list is measured in tenths of a second. A WAIT of 10 is one second, a WAIT of 15

is one and a half seconds, a WAIT of 20 is two seconds, and so on.

Suppose in your system you have two relays controlling system power. One is for the audio

amplifier, and the other is for the rest of the equipment (we’ll call that “rack power”). In many

cases, a time delay is desired between powering up the source equipment and powering up the

audio amplifier. The reason is that if both are powered up at the same time, there is sometimes a

loud “pop” over the audio system from the source equipment; but if there is a delay, the source

equipment is already on and there will be no “pop” when the amp is turned on. In most cases a one

half-second delay is enough.

In your program, you will first add a constant definition for your new relay and change the name of

the existing system power relay to RACK_POWER. If you use relay 7 (the next available relay on the

card), the line to add to the DEFINE_CONSTANT section is: AMP_POWER = 7

The companion code to this section is STEP3a.

Page 49: Amx Netlinx Programming Ba01

Chapter 6 – The Wait Keywords

42 Introduction to AMX Programming

As for the System Power button, you want the rack power to come on first (relay 3) when the power

is turned on; one half-second later, the amp power should turn on. When you turn the power off,

you want the reverse to happen. First, look at the organization of this set of statements. Here is a

simplified outline of the structure of this code:

BUTTON_EVENT[TP,31]{ PUSH: {

IF (device-channel) { compound statement }

ELSE {

compound statement }}

From this outline you can more easily examine what is happening here. Following the PUSH

statement is a single IF...ELSE statement which has only a device-channel reference for its

condition. In this case the Master checks that channel’s status. If it is on, the Master evaluates the

condition as true and executes the first compound statement. Otherwise the compound statement

following the ELSE is executed.

Here’s the new code for the System Power button:

BUTTON_EVENT[TP,31]{ PUSH: { IF([RELAY,RACK_POWER]) { OFF[RELAY,AMP_POWER] WAIT 5 { OFF[RELAY,RACK_POWER] } } ELSE { ON[RELAY,RACK_POWER] WAIT 5 { ON[RELAY,AMP_POWER] } } }}

The first compound statement, which is executed if the rack power is on, uses a WAIT to accomplish

a time-delayed powering-down of the system. The first statement inside the compound statement

turns off the amplifier relay. The next statement is a WAIT statement for five-tenths of a second

Page 50: Amx Netlinx Programming Ba01

Chapter 6 – The Wait Keywords

43Introduction to AMX Programming

(same as one half-second), followed by an OFF statement to the rack power relay. The Master

places this WAIT into the WAIT list and continues with the program. Since these statements are part

of an IF compound statement, the Master does not execute the compound statement following the

ELSE.

As the system continues to run, the WAIT is still in the WAIT list. After one half-second has elapsed,

the Master will execute the statement immediately following the WAIT, which in this case turns off

the rack power. The corresponding WAIT is then taken out of the list.

The compound statement following the ELSE is nearly the same as the one just described; its

functions are just slightly different. The Master first turns on the rack power, waits a half-second,

and then turns on the amp power.

Multiple Wait StatementsNow that you know how to delay an action for a specific amount of time, you can add a little

pizzazz to your system. Suppose you want a series of several events to happen when you press just

one button. At this point, the System Power button completes just two events with a delay in

between.

Now you will make the System Power button accomplish several more things when the power is

being turned on and off. Suppose that when the power is being turned on, you want a series of timed

events to take place. First, the rack power comes on as before. At the same time, the screen starts to

come down and the drapes start to close. One half-second later, the amp power comes on, just like

before. Twenty seconds after the button is pressed, the Medium lighting scene is selected.

Page 51: Amx Netlinx Programming Ba01

Chapter 6 – The Wait Keywords

44 Introduction to AMX Programming

When the power is turned off a different sequence happens. First, the amp power is turned off,

lights go to the Full setting, the screen is raised, and the drapes are opened. One half-second later

the rack power turns off. Two minutes later the lights go to the Off setting. Here is the code for the

System Power Push for the described scenario:BUTTON_EVENT[TP,31]{ PUSH: { IF ([RELAY,RACK_POWER]) (* power being turned off *) { OFF[RELAY,AMP_POWER]TO[LIGHTS,LIGHT_FULL]TO[RELAY,SCREEN_UP]TO[RELAY,DRAPE_OPEN]WAIT 5{ OFF[RELAY,RACK_POWER]}WAIT 1200 { PULSE[LIGHTS,LIGHT_OFF]} } ELSE (* power being turned on *) { ON[RELAY,RACK_POWER] TO[RELAY,SCREEN_DOWN] TO[RELAY,DRAPE_CLOSE] WAIT 5 { ON[RELAY,AMP_POWER]

} WAIT 200 { PULSE[LIGHTS,LIGHT_MED] } } } }

The companion code to this section is STEP3b.

Page 52: Amx Netlinx Programming Ba01

Chapter 6 – The Wait Keywords

45Introduction to AMX Programming

Notice the use of the PULSE keyword. This is done, as you may recall, because TO cannot be used

inside a WAIT. Since the lighting buttons are momentary, you use a PULSE to actuate the relay for

just a moment. WAIT statements can appear inside other WAIT statements. This is called “nesting”

WAIT statements. You don’t need to nest WAIT in your program here, but here is how it is done:

WAIT 200{ ON[RELAY,SCREEN_UP] WAIT 200 { OFF[RELAY,SCREEN_UP] }}

In this example, the system would wait twenty seconds, turn on the Screen Up relay, wait twenty

more seconds, then turn off the Screen Up relay. Any timed sequence of events can be

accomplished with or without nested WAIT statements. Non-nested WAIT statements use less code.

However, using nested WAIT statements is in many cases more readable than non-nested WAIT

statements. In addition, using nested waits can result in more efficient code with less burden on the

processor. Here is the same example without nesting:

WAIT 200 ON[RELAY,SCREEN_UP]WAIT 400 OFF[RELAY,SCREEN_UP]

Special Uses of WaitAny one WAIT can only be placed in the WAIT list once. If a particular WAIT is already in the WAIT

list, it cannot be placed into the list a second time until the first instance is either cancelled or

expired. For instance, suppose the following line appears in mainline where it will be executed

every pass through mainline:WAIT 5 FLASH = NOT FLASH

The first time this is executed, the WAIT is placed into the WAIT list. But what if this line is executed

again before the WAIT expires? Since the WAIT is already in the WAIT list, the line is simply

ignored. One half-second after the first execution of this statement, the value in variable FLASH is

inverted; if it was zero it will be changed to 1, and if it was non-zero it will be changed to zero. On

the next pass through mainline, the WAIT will again be placed into the WAIT list and the cycle will

repeat for the duration of the program. This in effect creates a variable whose state inverts every

half-second.

Naming Wait StatementsAs you saw in the examples above, it is not necessary to name waits but when a WAIT is given a

unique name, it can be cancelled, paused, or restarted. To name a WAIT, simply place a name in

single quotes after the WAIT statement. For example:WAIT 30 ’DELAY’

Once DELAY is entered into the list, it cannot be re-entered until the first has been removed

(cancelled or expired).

There are certain considerations in naming WAIT statements:

! They should not be previously defined constants or variables.

Page 53: Amx Netlinx Programming Ba01

Chapter 6 – The Wait Keywords

46 Introduction to AMX Programming

! They cannot be names that have already been assigned to buffers or subroutines.

! They can contain spaces, unlike other identifiers.

Canceling, Pausing, and Restarting Wait StatementsOnce a WAIT is named, it can be manipulated within the program with several keywords.

PAUSE_WAIT places a WAIT on “hold.” The WAIT does not continue counting down until it is

resumed with RESTART_WAIT. The WAIT then continues from where it was paused. CANCEL_WAIT

completely nullifies a WAIT, removing it from the WAIT list. If you do not name your waits you

won't be able to reference them individually. You would only be able to refer to all of them using

the next several keywords discussed. CANCEL_ALL_WAIT nullifies every WAIT currently in the list.

The keywords PAUSE_ALL_WAIT and RESTART_ALL_WAIT act the same as PAUSE_WAIT and

RESTART_WAIT, except they affect every WAIT in the WAIT list, named and unnamed.

You could use a named WAIT in your System Power PUSH routine. Suppose the user just turned off

the power. The program now has a two-minute WAIT in the WAIT list for the lights to go off. If the

user turns the power back on before this WAIT executes, the power-on sequence will start, but the

events of the LIGHT_OFF WAIT will still happen! The user could end up in a very dark room, which

is definitely not what he or she wanted. In this case it would be advantageous to name that WAIT

and cancel it in the power-on section of the PUSH. To do this, simply add the WAIT name to the

WAIT in the power-off section like this:

WAIT 1200 'LIGHTS OFF'{ PULSE [LIGHTS,LIGHT_OFF]

}

To cancel the WAIT in the power-on section, simply add this line:

CANCEL_WAIT ‘LIGHTS OFF’

The WAIT_UNTIL KeywordThe WAIT_UNTIL keyword is not a true “timing” keyword; the system does not wait for a certain

amount of time to elapse. Instead, it checks to see if a condition is true. When the condition

becomes true, the Master executes the statements listed directly below the WAIT_UNTIL statement.

All WAIT_UNTIL statements go into another list very similar to the WAIT list, called the

WAIT_UNTIL list. Just as it does with WAIT statements, each pass through mainline the Master

checks to see if any WAIT_UNTIL conditions have become true. For each one that has, the system

immediately executes the sequence below the WAIT_UNTIL statement. If not, the system keeps the

WAIT_UNTIL in the WAIT_UNTIL list until its condition becomes true.

Page 54: Amx Netlinx Programming Ba01

Chapter 6 – The Wait Keywords

47Introduction to AMX Programming

Misusing WAIT_UNTILSince the system only checks the status of pending WAIT_UNTIL statements after completely

running mainline, make sure that the condition has a chance to become true, or you will defeat the

purpose of the WAIT_UNTIL statement. You don’t need WAIT_UNTIL in your program yet, but this

program segment illustrates the misuse of WAIT_UNTIL:

WAIT_UNTIL (Y=4){

(* statements *)}Y=4Y=3

As you can see, Y will never equal four at the end of the program. The WAIT_UNTIL in this case is

completely useless.

It would be hard to make this mistake in a small program such as the one you are working on, but

this problem could make its way into a fairly large program. The compiler cannot detect this sort of

error, so make sure each WAIT_UNTIL statement can become true one way or another.

Naming and Removing WAIT_UNTIL StatementsIn the same manner as a WAIT, a WAIT_UNTIL can be named. To do this, a name in single quotes is placed at the end of the statement. Once a WAIT_UNTIL has a name, it can be cancelled with the CANCEL_WAIT_UNTIL keyword, which removes it from the WAIT_UNTIL list. The CANCEL_ALL_WAIT_UNTIL keyword removes all WAIT_UNTIL statements from the WAIT_UNTIL list.

Page 55: Amx Netlinx Programming Ba01

Chapter 6 – The Wait Keywords

48 Introduction to AMX Programming

Page 56: Amx Netlinx Programming Ba01

Unit 3: Levels

49Introduction to AMX Programming

Unit 3: Levels

Chapter 7 – Creating and Using Levels

IntroductionSo far, you have used channels in devices to interact both with the user and with what he or she

wants to control. Channels, however, are not the only method of controlling some devices, such as

volume control, voltage generator, and pan/tilt control devices. Devices such as these use “levels”

to interface with the outside world. Also, several control panels have bar graph displays capable of

displaying a level. This unit will show you how to create, read, and modify these levels, plus show

you how to use bar graphs and sliders on some of these devices.

What is a Level?An input/output (I/O) channel in AMX Control Systems is usually digital in nature; that is, it can

only have an “on” or an “off” state. Several devices, such as the volume control card and the pan/tilt

control card, have analog input and/or output capabilities. An analog input or output may have

many different states. Devices using analog I/O internally store the values relating to the state of

each of these analog inputs and outputs; these values are called levels. On a volume card, levels

relate to the volume levels of the card. Levels can be used to tell a pan/tilt control card where to

position a camera, or tell a voltage generator card the amount of voltage to generate.

Imagine that a volume control card has two volume knobs: one for the left speaker and one for the

right. Each knob has a range of values from 0 to 255. These knobs represent the two levels present

in the volume control card. When a “level” is discussed in the text, it is usually referring to the

value of one of these imaginary knobs.

Creating LevelsIn most AMX devices levels can have a value between 0 and 255. Level values can be stored in a

variable for later use. In order to read a level from a device that supports levels, you use the

keyword CREATE_LEVEL. Here is the syntax:

CREATE_LEVEL device, level number, variable

CREATE_LEVEL takes three parameters:

! The device from which to read the level

! Which level of the device to read (some devices have many different levels)

! The variable in which to store the level

Page 57: Amx Netlinx Programming Ba01

Chapter 7 – Creating and Using Levels

50 Introduction to AMX Programming

This keyword creates an association between the specified level of the device and the specified

variable. During execution of your program, the Master will continually update the variable to

contain the value of the level with which it is associated. Since this association only needs to be

done once, this keyword is only allowed to appear in the DEFINE_START section of your program.

In this unit, you will develop a new program that handles levels. This system will contain a volume

control card to control a volume level, and a Touch Panel (FIG. 1) for the user to control the volume

card. On the Touch Panel, there will be four buttons: Volume Up, Volume Down, Volume Mute, and

Volume Preset. There will also be a bar graph on the Touch Panel to display and control the volume

level.

Here are some code excerpts to get started:

DEFINE_DEVICE

VOLUME = 17:1:0TP = 128:1:0

DEFINE_CONSTANT

(* Three channels to control both outputs together *)V_UP = 1V_DN = 2V_MT = 3

DEFINE_VARIABLE

VOL_LEVEL (* This will store the volume level value*)PRESET (* This will store the preset level value*)

FIG. 1 Touch Panel used for Level Exercise

The companion code to this section is STEP4a.

Page 58: Amx Netlinx Programming Ba01

Chapter 7 – Creating and Using Levels

51Introduction to AMX Programming

DEFINE_START

CREATE_LEVEL VOLUME, 1, VOL_LEVEL

This code defines the devices you will use, a variable in which to store the volume level value, and

the statement in the startup code to create the association between level number 1 of the volume

card and the VOL_LEVEL variable. It also defines some constants that give names to the different

channels available in the volume control card. By turning on and off these channels the user can

raise, lower, and mute the volume levels of the card. Here is the code for the Volume Up, Volume

Down, and Volume Mute buttons on the Touch Panel:DEFINE_EVENT

BUTTON_EVENT[TP,1]{ PUSH: { OFF[VOLUME,V_MT] TO[VOLUME,V_UP] }}BUTTON_EVENT[TP,2]{ PUSH: { OFF[VOLUME,V_MT] TO[VOLUME,V_DN] }}BUTTON_EVENT[TP,3]{ PUSH: { [VOLUME, V_MT] = NOT[VOLUME, V_MT] }}DEFINE_PROGRAM[TP,1] = [VOLUME,V_UP][TP,2] = [VOLUME,V_DN][TP,3] = [VOLUME,V_MT]

Notice that the Volume Up and Volume Down buttons will automatically un-mute the volume

before starting to ramp the volume up or down. Also, these control channels affect both levels of the

volume card simultaneously, ramping both up and down together. This code handles all of the

functions of your system except for the bar graph and the Volume Preset button.

Page 59: Amx Netlinx Programming Ba01

Chapter 7 – Creating and Using Levels

52 Introduction to AMX Programming

Reading LevelsWhen a level is associated with a variable using CREATE_LEVEL, the Master continually keeps the variable updated with the value of that level. In your program, as the user ramps the volume level up, the value in VOL_LEVEL increases. When the volume is ramped up to the maximum, VOL_LEVEL will contain 255. The same goes for ramping down; when the volume is muted, the variable will contain zero.

Making a PresetNow you are going to add the code necessary to create a preset. A preset is a level stored for later

retrieval. What you will do here is give the Volume Preset button a dual role. If the button is pressed

and held for two seconds, the current level of the volume card is stored in the variable PRESET. If

the button is pressed for less than two seconds, it sends a command to the volume card to set the

level of the card to the previously saved level in PRESET. First, here is the code:

BUTTON_EVENT[TP,4] //VOL PRESET{ RELEASE: { SEND_COMMAND VOLUME, "'P0L', ITOA(PRESET)"

OFF[VOLUME,V_MT] } HOLD[20]: { PRESET = VOL_LEVEL }}

DEFINE_PROGRAM[TP,4] = (PRESET = VOL_LEVEL)

This code uses the HOLD keyword to be sure the button is held for at least 2 seconds (20 tenths).

Then the current level of the card (stored in VOL_LEVEL) is saved into the variable PRESET. When

the button is released a command is sent to the volume card to go to the level saved in PRESET

(even if only saved a moment earlier), and the volume is un-muted. Note that the feedback for the

Volume Preset button is turned on whenever the current volume level equals the value of the

PRESET variable.

AMX volume devices remember the previous level when it is muted so that it can un-mute to that same level.

Remember that Hold times can be measured in as little as a hundredth of a second (.1)

Page 60: Amx Netlinx Programming Ba01

Chapter 7 – Creating and Using Levels

53Introduction to AMX Programming

Using Bar GraphsNow you will add the code to continuously display the current level of the volume card on the

Touch Panel’s bar graph. To update a bar graph on a device, you use the SEND_LEVEL keyword.

Here is the syntax:

SEND_LEVEL device, level number, value

This keyword is used to update a level in a device. Assume your bar graph display on the Touch

Panel has level number 1. In order to keep the display updated continually, you will add the

following line into your program (in mainline):

SEND_LEVEL TP, 1, VOL_LEVEL

Since this code resides in mainline it will be executed continually, thus making sure that the bar

graph reflects the value of level number 1 of the volume card. As the volume ramps up, VOL_LEVEL

increases and the bar graph fills. As the volume ramps down, VOL_LEVEL decreases and the level

indicated on the bar graph also decreases. Since both volume levels are ramping together, you only

have to track one of them for the bar graph.

Connecting LevelsTouch Panel bar graphs have a unique feature if they are set to the active bar graph type: you can

touch and slide the bar graph itself and the level will raise or lower to that point; the level simply

tracks the movement of your finger. However, to do this you must set up a connection between the

bar graph and the volume level. That is what the keyword DEFINE_CONNECT_LEVEL accomplishes.

DEFINE_CONNECT_LEVEL is not a keyword that is used inside mainline, but is actually a definition

section like DEFINE_DEVICE or DEFINE_START. When you use it, the best location to place it is

immediately following the DEFINE_DEVICE section. Underneath the DEFINE_CONNECT_LEVEL

header is where all level connections are listed. Here is how DEFINE_CONNECT_LEVEL is used:

DEFINE_CONNECT_LEVEL(device 1,level number 1,device 2,level number 2,...etc.)

The section inside the parentheses represents a single connection. All levels listed in the connection

will follow each other. If any one level changes, all others will change to match. Any number of

levels may be supported per connection, and there is no limit to the number of connections. Here is

how you would use DEFINE_CONNECT_LEVEL in your program to connect the Touch Panel's bar

graph to the volume card's levels:

DEFINE_CONNECT_LEVEL(PANEL, 1, VOLUME, 1, VOLUME, 2)

This connects level number 1 on the Touch Panel (your bar graph) and levels 1 and 2 on the volume card together. The reason that two levels on the volume card are included is because volume control cards have two levels: the left audio channel and the right audio channel. These connections are a two-way street: anytime the bar graph is changed, both volume levels will follow, and anytime a volume level is changed (probably by the volume control buttons on the Touch Panel), the bar

Page 61: Amx Netlinx Programming Ba01

Chapter 7 – Creating and Using Levels

54 Introduction to AMX Programming

graph will automatically follow. When using DEFINE_CONNECT_LEVEL, it is not necessary to use the SEND_LEVEL keyword in your program since the connection constantly takes care of updating the bar graph.

The companion code to this section is STEP4b.

Page 62: Amx Netlinx Programming Ba01

Unit 4: Arrays and Sending and Receiving Strings

55Introduction to AMX Programming

Unit 4: Arrays and Sending and Receiving Strings

Chapter 8 – Arrays and Strings

IntroductionIn the previous units you developed a program that demonstrates the most common features of the

AMX programming languages. In this unit, more advanced concepts will be introduced: arrays,

strings, buffers, and two-dimensional arrays. Understanding these concepts and the keywords that

go with them will allow you to easily handle data, and will provide another means of

communicating with the outside world.

In this chapter, you will develop a small example program. For this program, you will need to

create a level and assign it to a variable. You will use the variable VOLUME_LEVEL for this. Your

control panel will have nine buttons: Volume Up (button 1), Volume Down (button 2), Store (button

3), Preset 1, Preset 2, Preset 3, Preset 4, Preset 5, and Preset 6 (buttons 9 through 14). The Volume

Up and Volume Down buttons ramp a volume card up and down. The Store button simply toggles a

state on and off. The Preset 1–6 buttons either store or recall a preset, depending on whether the

Store button is on or not.

Defining ArraysIn the program developed in Unit 2, you used a variable called DECK. This variable could only hold

one value at a time. However, if you need a variable to hold several values at once, use an array. An

array is a single variable that has more than one storage location.

Arrays must be defined as variables within the DEFINE_VARIABLE section of your program. Its

definition has two parts: a unique identifier and its storage capacity. The variable must be named

using a valid identifier first. (See Identifiers on page 6 for the rules concerning identifiers).

Second, the number of storage locations in the array must be indicated; a maximum of 65535

locations for NetLinx systems. For your new program, you want to store several preset levels for

the volume control device. You could create several individual variables and use IF statements or

SELECT...ACTIVE statements to select the preset you want to use. Or even better, you could

create an array and use an index value to pick the preset you want to use. Here is the array

declaration:DEFINE_VARIABLEPRESETS[6]

The companion code to this section is STEP5a.

Page 63: Amx Netlinx Programming Ba01

Chapter 8 – Arrays and Strings

56 Introduction to AMX Programming

This declares a new variable, PRESETS. The variable PRESETS is an array that can hold six distinct

values, as defined by the number 6 inside the brackets.

Accessing and Storing Array ValuesTo access a particular value in an array, simply refer to the storage location inside the array you

wish to read, such as follows:

THE_LEVEL=PRESETS[3]

The number inside the brackets is called the index value. The index value is the number that tells

the master which location in the array to read. In this example it is a number from 1 to 255. It also

assigns the value in the third location of PRESETS to the variable THE_LEVEL. Reading a value

from an array does not in any change the array.

You can place values into a storage location by setting the particular location equal to the needed

value. For example, PRESETS was previously defined as having six locations. If you want the

second location to hold a value of 6 you would type the following:

PRESETS[2]=6

The number 6 is placed into the second location. From now on, anytime PRESETS[2] is referenced,

its value is 6.

Page 64: Amx Netlinx Programming Ba01

Chapter 8 – Arrays and Strings

57Introduction to AMX Programming

In this program, pressing a Preset button either stores or recalls a preset. Examine the section of

code that accomplishes this:

BUTTON_EVENT [TP, 3] // PRESET VOLUME BUTTON (STORE / RECALL){ PUSH: { STORE = NOT STORE // TOGGLE THE STATE OF STORE }}

BUTTON EVENT [TP, 9] // PRESET NUMBER 1{ PUSH: { IF (STORE) // STORE MODE IS ON { PRESET [1] = VOLUME_LEVEL // STORE CURRENT LEVEL IN

// PRESET 1 } ELSE // STORE MODE IS OFF (RECAL EXSITING PRESET) { SEND_COMMMAND VOLUME, "'P0L',ITOA (PRESETS [1]) //SEND PRESET 1 } }}

BUTTON EVENT [TP,10] // PRESET NUMBER 2{ PUSH: { IF (STORE) // STORE MODE IS ON { PRESET [2] = VOLUME_LEVEL // STORE CURRENT LEVEL IN

// PRESET 2 } ELSE // STORE MODE IS OFF (RECAL EXSITING PRESET) { SEND_COMMMAND VOLUME, "'P0L',ITOA (PRESETS [2]) //SEND PRESET 2 } }}

BUTTON EVENT [TP, 11] // PRESET NUMBER 3{ PUSH: { IF (STORE) // STORE MODE IS ON { PRESET [3] = VOLUME_LEVEL // STORE CURRENT LEVEL IN

// PRESET 3 } ELSE // STORE MODE IS OFF (RECAL EXSITING PRESET) { SEND_COMMMAND VOLUME, "'P0L',ITOA (PRESETS [3]) //SEND PRESET 3 } }}

Page 65: Amx Netlinx Programming Ba01

Chapter 8 – Arrays and Strings

58 Introduction to AMX Programming

BUTTON EVENT [TP, 12] // PRESET NUMBER 4{ PUSH: { IF (STORE) // STORE MODE IS ON { PRESET [4] = VOLUME_LEVEL // STORE CURRENT LEVEL IN

// PRESET 4 } ELSE // STORE MODE IS OFF (RECAL EXSITING PRESET) { SEND_COMMMAND VOLUME, "'P0L',ITOA (PRESETS [4]) //SEND PRESET 4 } }}

BUTTON EVENT [TP, 13] // PRESET NUMBER 5{ PUSH: { IF (STORE) // STORE MODE IS ON { PRESET [5] = VOLUME_LEVEL // STORE CURRENT LEVEL IN

// PRESET 5 } ELSE // STORE MODE IS OFF (RECAL EXSITING PRESET) { SEND_COMMMAND VOLUME, "'P0L',ITOA (PRESETS [5]) //SEND PRESET 5 } }}

BUTTON EVENT [TP, 14] // PRESET NUMBER 1{ PUSH: { IF (STORE) // STORE MODE IS ON { PRESET [6] = VOLUME_LEVEL // STORE CURRENT LEVEL IN

// PRESET 6 } ELSE // STORE MODE IS OFF (RECAL EXSITING PRESET) { SEND_COMMMAND VOLUME, "'P0L',ITOA (PRESETS [6]) //SEND PRESET 6 } }}

DEFINE_PROGRAM[TP,3]=STORE //TURN ON BUTTON WHEN STORE MODE IS ON

Page 66: Amx Netlinx Programming Ba01

Chapter 8 – Arrays and Strings

59Introduction to AMX Programming

The BUTTON_EVENT [TP, 3] is the Store button, which simply toggles the STORE variable using

the NOT operator.

Next, there is a button event written for each of the 6 preset buttons. Each button events works the

same way. When the button is pushed, the processor checks to see if the variable STORE is true or

false (on or off). If it is true (on), then the current volume level is stored in that preset position. If

STORE is not true (off), then a command is sent to the device VOLUME to recall the VOLUME_LEVEL

value that is currently stored in that preset position. Each of these events works the same way. The

only difference is which preset is being manipulated.

Our array PRESET has a size of [6]. This means that is can store 6 values. Since we have six preset

buttons we associate each one with a different position of the array. These positions are referred to

as elements. So BUTTON_EVENT [TP, 9] handles PRESET [1], BUTTON_EVENT [TP, 10]

handles PRESET [2], BUTTON_EVENT [TP, 11] handles PRESET [3] and so on.

Next, we check to see if the STORE mode is on. If STORE is on, we assign the appropriate location

in the PRESETS array to the current volume level. If STORE is off, we send a command to the

volume card telling it to go to the previously stored level.

Data TypesWhen dealing with data, we often refer to "equivalents". With ASCII characters, we often refer to

the ASCII table that shows the ASCII character, Decimal equivalent, and Hexadecimal (Hex)

equivalent. The complete chart is on page 79 of this manual. It is important to understand that these

values really are interchangeable within your program. This provides you the flexibility of using the

most appropriate or convenient data type for each specific application. Further, it is extremely

important to understand that the machine code that actually runs in the Master after compilation, is

binary-1s and 0s. Each of the other data types we discuss are really equivalents of the underlying

binary value.

A simple way to communicate this data equivalent issue is to take the word 'HELLO' and break it

down into other data types. We'll use a mix of ASCII, Decimal, and Hex to create an equivalent

expression, then convert the entire thing to binary to see what the Master actually evaluates in the

compiled code. From the ASCII table, we look at each character:

Remember, NOT inverts the state of whatever follows it.

ASCII Decimal HexH

E 72

L 4C

L 76

O 4F

Page 67: Amx Netlinx Programming Ba01

Chapter 8 – Arrays and Strings

60 Introduction to AMX Programming

So the ASCII string literal 'HELLO' can also be expressed as a string expression

"'H',72,$4C,76,$4F".

Once this code is compiled, the Master would actually be evaluating binary values like this:

0100111101000101010011000100110001001111. We don't actually have a binary data type, so

this is just presented to you for your information. In future programming classes, you'll learn more

about working with binary values in a topic called "Bitwise Manipulation".

As you move forward through this manual, you will encounter various mentions of ASCII, decimal

and Hexadecimal values. Please keep this fundamental data type discussion in mind as you

proceed.

StringsMany times you may need to reference entire groups of values at once. You can do this by using

strings and string expressions. A string is a set of values grouped together with single and/or double

quotes. Strings enclosed in single quotes are called string literals -values from the ASCII table

ranging from decimal 32 (the space character) to decimal 126 (the tilde '~' character). An

expression is surrounded by double quotes, and may contain a combination of string literals,

decimal values and hexadecimal values.

Strings may be used in our control program as constants or variables. Constants are values or

strings that are set at compile time and will not change throughout the life of the program. Variables

are values or strings that may be initialized at compile time, but are expected to change as the

program runs. Here is an example of assigning a string to an array (either constant or variable):

FAVORITE = 'ESPN'

When the Master processes this assignment, it places the ASCII character 'E' (decimal value 69) in

location 1 of FAVORITE, ASCII character 'S' (decimal value 83) in location 2, and so on. String

'ESPN' is placed in the array FAVORITE. Note that an index value is not given when strings are

assigned to arrays. The first letter is automatically placed into the first storage location; the second

letter is placed into the second storage location; and so on. In this example, the array FAVORITE

would have to have a size of at least 4 when defined. The definition might look like this: DEFINE_VARIABLE

CHAR FAVORITE [4]

AMX uses the $ symbol to indicate the use of Hex values.

Page 68: Amx Netlinx Programming Ba01

Chapter 8 – Arrays and Strings

61Introduction to AMX Programming

The String ExpressionAMX Control System Masters interpret single and double quotes in two different ways. Whereas

single quotes enclose string literals, double quotes represent a different operation: they enclose

string expressions. A string expression combines several types of data into a single string. A string

expression can contain any ASCII value (0 to 255), as well as constants, variables, string literals,

and arrays. As the Master processes a string expression, it evaluates each member of the expression

from left to right, and the result is a complete string. Here is an example:

EXPRESSION="PLAY,5,0,'NO',X,$0D"

Assuming that PLAY is a constant previously defined with the value of 1, and X is a variable with

the current value of 10, the string expression is evaluated as a string with the following values:

1,5,0,N,O,10 and carriage return (Hex 0D). Since the expression is evaluated at run time, whatever

value is in the variable X when the expression is evaluated is what is placed into the result.

String ElementsThere are two ways of referencing data in arrays within AMX programming code: each location

within an array as an individual value, or each array as a group of values. So far you have seen how

to reference an entire string. However, each element of a string can also be accessed as individual

characters. If you refer to an array and specify an index value, the contents of that specific element

will be loaded or returned. Consider the following lines:

DEFINE_VARIABLES1[10] //DECLARE AN ARRAY WITH CAPACITY FOR 10 CHARACTERSCHAR FIRSTCHAR SECOND

DEFINE_PROGRAMS1='TEST ONE' //LOAD CONTENTS INTO THE ARRAY AS A STRINGFIRST=S1[1] //THIS VARIABLE GETS THE 1ST ELEMENT OF S1: TSECOND=S1[2] //THIS VARIABLE GETS THE 2ND ELEMENT OF S1: E

This small section of code shows how to read individual elements of an array, by returning them to

another variable. In this example, we loaded S1 as a string, but read it's contents out as individual

elements. In normal programming, it is recommended that you read data out in the same manner as

you load data in. For example, if you load S1 as a string, you would also read it as a string, but if

you load it one element at a time, you would read it out as individual elements.

Here is another example. Suppose that during power-up of the control system you want to set all of

the presets to default values. You could do this by assigning values to each individual location in the

PRESETS array as shown:DEFINE_START

PRESETS[1]=0PRESETS[2]=30PRESETS[3]=90

and so on and so on for all 6.

Page 69: Amx Netlinx Programming Ba01

Chapter 8 – Arrays and Strings

62 Introduction to AMX Programming

A better solution, however, is to use a string expression to set all six at once, like this:DEFINE_VARIABLEINTEGER PRESETS[6]={ 0, 30, 90, 128, 191, 255 // EACH POSITION IN THE ARRAY IS

// ASSIGNED A DEFAULT VALUE}

String LengthsEvery array declared in the DEFINE_VARIABLE section has a string length value associated with it.

The string length of an array indicates the actual contents of the array as by string assignment

operations. This number is different than the storage capacity declared in the DEFINE_VARIABLE

section. You can get this length value of an array by using the LENGTH_STRING function. Here is an

example:

Y = LENGTH_STRING(PRESETS)

Here are examples of some assignments, and what the above line of code would return to the

variable Y in each case:

PRESETS = 'FOUR' (* Y = 4 *)PRESETS = 'ONE' (* Y = 3 *)PRESETS = "12,5,'123'" (* Y = 5 *)PRESETS = "PLAY,5,0,'NO',X" (* Y = 6 ASSUMING PLAY AND X ARE INTEGERS*)

Notice that each character in a string literal is counted separately, but numeric values (decimal or

hex) are counted as a single entity. The length of a string array cannot exceed the number of storage

locations allocated to it in the DEFINE_VARIABLE section. If the string 'GOODBYE' is placed in

the PRESETS variable, the array will only contain the string 'GOODBY,' dropping the final 'E'

because PRESETS was defined to hold a maximum of six elements. The length of PRESETS would

also be set to 6.

Assigning string literals and string expressions automatically sets the length of the string array to

the length of the string literal or string expression being assigned to it. However, assigning values to

individual elements of an array does not affect the length value of the array. For instance, if the

letters 'W', 'O','R', and 'D' are assigned individually to elements of PRESETS as shown below, the

length will not change. If the length was previously 3, it will still be 3.

PRESETS[1] = 'W'PRESETS[2] = 'O'PRESETS[3] = 'R'PRESETS[4] = 'D'

There is a way, however, to explicitly set the string length value of an array variable. The

SET_LENGTH_STRING keyword accomplishes this. For instance, to set the length value of

PRESETS to 4, you would use the following statement:

SET_LENGTH_STRING(PRESETS,4)

Page 70: Amx Netlinx Programming Ba01

Chapter 8 – Arrays and Strings

63Introduction to AMX Programming

After execution, the string length value of the array PRESETS is 4. String lengths play an important

role in the handling of strings. Consider this string expression that contains an array in the

expression:"5,PRESETS,'GO'"

As the Master constructs a string from this string expression, the number of characters from the

array PRESETS will be equal to LENGTH_STRING (PRESETS). If PRESETS contains “1,2,3,4,5,6”

but its string length value is 3, the resulting string from the above string expression will look like

this:

"5,1,2,3,'G','O'"

The string length value of an array is very important to many string operations in AMX

Programming. This value determines how much of the string is used when the entire array is

referenced as a string. Knowing this will prevent subtle errors from creeping into your code. For

instance, if you assign values to individual elements in an array, and then assign that array to

another, nothing will actually be copied. Here is an example:

PRESETS[1] = 5PRESETS[2] = 6PRESETS[4] = 'A'SAVE_PRESETS = PRESETS

What do you think the array SAVE_PRESETS will contain after this code is executed? It will totally

depend on the length value of the PRESETS variable. If this were the entire program, PRESETS

would have a default length of 0, so nothing would be copied into SAVE_PRESETS. In order to

assure that SAVE_PRESETS were to hold a copy of PRESETS, you would first need to set the length

value of the PRESETS array with this line inserted before the copy statement:

SET_LENGTH_STRING (PRESETS,4)

After this, the length value of PRESETS is 4, so the first 4 locations of PRESETS will be used in all

cases where you refer to the entire array.

Sending Strings and ArraysTo send a string to the outside world, you use the SEND_STRING keyword. Here is the syntax:

SEND_STRING device,<string, variable, or string expression>

The first value after the SEND_STRING keyword is the device number or identifier to which you

wish to send the string. Following that is a comma, then the string, variable (which can be either a

normal variable or an array), or string expression you wish to send. When an array variable is

specified, the number of characters from the array that are sent is determined by the length value for

the array. (Remember, you can set that value with the SET_LENGTH_STRING function.)

For instance, if you need to send the PRESETS array to a device named RS232, you would write the

following line:

SEND_STRING RS232,PRESETS

Page 71: Amx Netlinx Programming Ba01

Chapter 8 – Arrays and Strings

64 Introduction to AMX Programming

String literals and string expressions can also be sent using SEND_STRING. Here are some

examples:

SEND_STRING RS232,'THIS IS A STRING LITERAL'SEND_STRING RS232,"'EXPRESSION ',PRESETS,$0D,$0A"

The first example sends the entire set of characters enclosed in the single quotes, from left to right,

through the port to the device named RS232. The second example first builds the string expression

using a string literal, followed by however many characters from PRESETS as defined by its length

value, and then two numbers expressed here in hexadecimal. (The hexadecimal numbers in the

example represent the codes for “carriage return” and “line feed,” respectively.)

ASCII CodesAs you have learned, a string literal is broken up into single letters when placed into a string array.

Each storage space returns the letter it is holding when referenced. For example, assume that

PRESETS[3] holds the letter ‘R.’ There are actually three ways you can reference this array

location (in this example using IF statements):

IF(TEMP[3] = 'R'){(* statement(s) *)}

orIF(TEMP[3] = 82){(* statement(s) *)}

orIF(TEMP[3] = $52){(* statement(s) *)}

The ASCII character ‘R’ has a value of 82 decimal and 52 in hexadecimal. In AMX Programming,

hexadecimal numbers begin with a dollar sign ($). Therefore, the third example above shows $52,

meaning, “this number, 52, is a hexadecimal number.”

All three methods—letters, decimal ASCII codes, and hexadecimal ASCII codes can be used

interchangeably. Feel free to use whichever method is easiest for the task at hand.

Integer ArraysSo far, in all of the arrays you have seen, the valid range of values in each element is 0-255. This is

the result of an 8-bit memory allocation for each element; all bits off results in the value 0, and all

bits on results in the value 255. If a value greater than 255 is assigned to an array location, the

number is truncated by wrapping around back to 0. For instance, if the number 500 is assigned to a

location in a character array, the actual number that is assigned is 244. (The way to find this is to

keep subtracting 256 from the number until the number is less than 256.)

Page 72: Amx Netlinx Programming Ba01

Chapter 8 – Arrays and Strings

65Introduction to AMX Programming

So what could you do if you need to create an array in which each location can contain values

greater than 255? The answer is to use an integer array. An integer array is just like a character

array, except that each location allocates 16-bits and can hold values from 0-65,535. To declare an

integer array, simply place the keyword INTEGER in front of the array definition in the

DEFINE_VARIABLE section. If you wanted your PRESETS array to be an integer array, here is how

you would declare it:

DEFINE_VARIABLEINTEGER PRESETS[6]

This declares an integer array with six locations; each location can hold values from 0-65,535.

There are certain limitations of integer arrays. If an integer value above 255 is assigned to a character array, all values are truncated above 255. (See the discussion on truncating values onpage 64.) This also happens if an integer array is sent to a device using the keywords SEND_STRING or SEND_COMMAND. There is no problem, however, in assigning a normal array to an integer array. If your array is only going to hold only alphanumeric values, do not make it an integer array.

Page 73: Amx Netlinx Programming Ba01

Chapter 8 – Arrays and Strings

66 Introduction to AMX Programming

Page 74: Amx Netlinx Programming Ba01

Chapter 9 – Working with Arrays

67Introduction to AMX Programming

Chapter 9 – Working with Arrays

Grouping DataThe ability to group data into cohesive units (arrays) is one of the more powerful features of the

AMX programming languages. Thus there are many keywords to help you manipulate arrays and

strings. These keywords can be grouped into two classes: conversion keywords and array

manipulation keywords.

Conversion keywordsThere are several string conversion keywords available:

UPPER_STRINGLOWER_STRING ITOAITOHEXATOI

The first two keywords generate an all upper case or lower case equivalent string for whatever

string they are operating on. (See UPPERCASE vs. lowercase on page 71 for more detail on this

topic). The last three serve to generate equivalent numeric values - either as a constant, in a

variable, or explicitly defined-into its string representation, and vice versa. The three keywords

ITOA, ITOHEX, and ATOI automatically set the length value of the resulting string.

It is important to understand that the conversion words, do not actually 'convert' the value of

whatever they are operating on. These keywords simply take the value as it is represented and

generate an equivalent value in some other form. Whether the value is represented in HEX, decimal

or ASCII is immaterial to the processor. The processor will convert any of these values to binary

once the code is compiled. The binary value will be the same no matter how the number is

represented. However, the programmer may need to represent that value in one form or another for

his or her own purposes.

ITOA

ITOA, which is short for “integer to ASCII,” creates a string that represents the decimal value of a

number. Here are some examples:

DEFINE_CONSTANTCONST = 456

DEFINE_VARIABLESTR[5]VAR

DEFINE_PROGRAMVAR = 789STR = ITOA(123) (* STR = ‘123’ *)STR = ITOA(CONST) (* STR = ‘456’ *)STR = ITOA(VAR) (* STR = ‘789’ *)

Page 75: Amx Netlinx Programming Ba01

Chapter 9 – Working with Arrays

68 Introduction to AMX Programming

The comment after each statement shows the value of the array STR after each assignment. The

length value of STR is set to 3 in each case, even though its storage capacity is 5.

ITOHEX

This keyword is short for “integer to hexadecimal.” ITOHEX works in the exact manner as ITOA,

except that the integer is transformed into a hexadecimal ASCII string. If you substitute the ITOA

keywords in the previous example with ITOHEX keywords, this would be the result:

STR = ITOHEX(123) (* STR = ‘76’ *)STR = ITOHEX(CONST) (* STR = ‘1C8’ *)STR = ITOHEX(VAR) (* STR = ‘315’ *)

Notice that result does not contain a dollar sign. This is because the dollar sign indicates a

numerical value expressed in hexadecimal, and is only used when telling the system that a number

is hexadecimal. The result is an ASCII string which contains a representation of the hexadecimal

value.

ATOI

The ATOI keyword stands for “ASCII to integer” and does just that. It takes a string literal, string

expression, or array as a parameter, and returns a single integer as the result. Here are some

examples:

DEFINE_CONSTANTSTR1 = ‘456’STR2 = ‘YES789GO19’

DEFINE_PROGRAMNUM = ATOI('123') (* NUM = 123 *)NUM = ATOI(STR1) (* NUM = 456 *)NUM = ATOI(STR2) (* NUM = 789 *)

If the string contains all non-numeric characters (such as ‘HELLO’), ATOI returns the integer 0.

However, if there are any numeric characters embedded within the string, ATOI returns the first

complete set it comes upon, as is the case with STR2 above. Notice that only the first set of numbers

from STR2 is returned. The ATOI function looks for the first character with an integer equivalent

(0-9). If it finds one, the function continues to process until a non-integer equivalent is encountered.

The original string remains intact and unchanged.

Page 76: Amx Netlinx Programming Ba01

Chapter 9 – Working with Arrays

69Introduction to AMX Programming

Array Manipulation KeywordsThere are a number of keywords at your disposal that allow you to manipulate arrays and to retrieve

certain portions of an array:

LEFT_STRINGMID_STRINGRIGHT_STRINGFIND_STRINGREMOVE_STRING

LEFT_STRING

For this keyword, you must specify two parameters: the string or array you are referencing and the

number of characters you need. LEFT_STRING returns a string containing the number of characters

specified starting at the beginning of the string. Here is an example:

STR = LEFT_STRING (PRESETS,3)

After execution of this line, the array STR will contain the first 3 characters of the array PRESETS. If

PRESETS has a length of 5 and contains the string ‘HELLO,’ then STR will contain ‘HEL.’ Also, the

length value of STR will be set to 3.

RIGHT_STRING

This keyword requires the same parameters as LEFT_STRING. However, RIGHT_STRING begins

reading at the end of the string array for the specified amount of characters. Assuming PRESETS

still contains ‘HELLO,’ replacing LEFT_STRING in the previous example with RIGHT_STRING

will assign the string ‘LLO’ to STR. This keyword also will set the length value of the array

receiving the result.

MID_STRING

This keyword returns the specified amount of characters starting at a specified location in the

source string. Three parameters, rather than two, are needed for its operation: the string to

reference, the position at which to start, and the number of characters to return. Here is an example:

STR = MID_STRING (PRESETS,2,3)

This line tells the Master: “Place three characters from the array PRESETS, starting at location 2 and

moving to the right, into the array variable STR.” If PRESETS contains ‘HELLO,’ this line will

assign ‘ELL’ to the array STR. This keyword also will set the length value of the array receiving the

result.

Finding Strings

The keywords explained previously are helpful when you know where certain parts of strings are

located within a string array. However, there will be many times when you have no idea where to

look. In these cases, the FIND_STRING keyword is used. This keyword will search through a string

for a specified sequence of characters. As soon as it finds a duplication of the sequence, it returns

the beginning position of that duplication.

Page 77: Amx Netlinx Programming Ba01

Chapter 9 – Working with Arrays

70 Introduction to AMX Programming

For example, suppose you don’t know the exact contents of the PRESETS array, but you want to find

out if it contains the string ‘LO.’ Assume that PRESETS has a length of 5 and contains ‘HELLO’

and the following line is executed.

X = FIND_STRING (PRESETS,'LO',1)

When the Master executes this statement, it will search the array PRESETS from the beginning,

looking for the string ‘LO.’ If the system finds the search string, as in this case it will, it returns the

starting position of the search string in the PRESETS array: in this case, 4. The third parameter (in

this example, 1) tells the Master where in the array PRESETS to start the search. Since the function

returns a value, FIND_STRING can be used as a conditional where 0 (False) means the string was

not found, or non-zero (true) means the string was found. If FIND_STRING were to return a zero,

we would say the string has ' no length', meaning it is empty.

Removing Strings

The REMOVE_STRING keyword works much like the FIND_STRING keyword. However, when the

Master finds the sequence it is looking for, it extracts every character up to and including the

sequence. All the other characters move up to fill in the space. Here is an example:

DEFINE_VARIABLESOURCE[20]DEST[20]

DEFINE_PROGRAMSOURCE = ‘THIS IS A TEST’DEST = REMOVE_STRING (SOURCE,‘IS’,1)

After the last line is executed, DEST will contain ‘THIS’ and SOURCE will contain ‘IS A TEST’.

Notice that after the removal, the first location of the array SOURCE contains a space. This is

because REMOVE_STRING removed all characters from the beginning of SOURCE up to and

including the string ‘IS’. It did not remove the space following the string ‘IS’ in SOURCE. Also,

notice that the first occurrence of ‘IS’ is embedded in the word ‘THIS’ To remove the word IS,

you could add the leading space to the search condition, like this: DEST= REMOVE_STRING(SOURCE,' IS',1)

The length values of both arrays are set according to the results of the operation. In this case, the

length value of SOURCE is set to 4, and DEST is set to 10.

Page 78: Amx Netlinx Programming Ba01

Chapter 9 – Working with Arrays

71Introduction to AMX Programming

UPPERCASE vs. lowercaseWhen using FIND_STRING and REMOVE_STRING, as well as when comparing two string values, it

is important to remember that such comparisons are case sensitive, which means that uppercase and

lowercase values are not evaluated the same.

As you recall, the compiler is not case sensitive when it comes to keywords and identifiers. The

compiler is case sensitive, however, when it comes to values inside single quotes (string literals).

Here are some examples:

DEFINE_PROGRAMIdentifier_1 = 'Fred'Identifier_2 = 'FRED'if(IDENTIFIER_1 = IDENTIFIER_2){ (*This is not be true because 'Fred' and 'FRED' are not the same.*)}

Notice that the string literals ‘FRED’ and ‘Fred’ are not the same. However, in the case of

identifiers IDENTIFIER_1 and IDENTIFIER_2, the compiler makes no differentiation based on

the case of the letters making up the identifier name. Also notice that in this example the keyword

IF is not capitalized. This also makes absolutely no difference to the compiler.

Setting Uppercase and LowercaseWithin the system, the lower case letter “a” is not the same as the upper case letter “A”. Each ASCII

character has its own decimal value; the value for “a” is 97, and the value for “A” is 65.

This could become a problem when, for example, your program compares an incoming string ABC

against another:

IF(ABC = 'YES'){(* statement(s) *)}

If the incoming string is ‘YES,’ there is no problem. The statements are executed as normal.

However, what if ABC equals ‘Yes’? Since ‘YES’ and ‘Yes’ do not have the same decimal

equivalent value, the statements below the IF would not be executed.

The solution is to change all incoming strings to either uppercase or lowercase. The keywords that

do this are UPPER_STRING and LOWER_STRING. For example, the following statement could have

been added before the preceding program:ABC_UP = UPPER_STRING(ABC)

The IF statement can now compare ABC_UP against ‘YES,’ providing that the IF statement reads

IF(ABC_UP = ‘YES’). The string ‘Yes’ is accepted since it has been converted into uppercase. As expected, LOWER_STRING converts a string into lowercase in the same manner that UPPER_STRING operates.

Page 79: Amx Netlinx Programming Ba01

Chapter 9 – Working with Arrays

72 Introduction to AMX Programming

Page 80: Amx Netlinx Programming Ba01

Chapter 10 – Receiving Strings

73Introduction to AMX Programming

Chapter 10 – Receiving Strings

Listening to the Outside WorldOne of the most powerful features of AMX Control Systems is its ability to send and receive any

combination of values using RS-232, RS-422, RS-485, MIDI, and a variety of other formats. You

have the ability to construct any combination of numbers and characters with the string expression

and send it to an external device. In addition, you can receive strings from external devices and

interpret them to obtain useful information.

Receiving StringsReceiving strings requires a few more steps than sending strings. To be able to receive strings from

a device, you must have a place to store that incoming message. This storage place can be either

one of the following:

! A user-defined array (e.g., INCOMING) when used in conjunction with the keyword

CREATE_BUFFER

OR

! A system-defined array (DATA.TEXT) inside the STRING clause of a DATA_EVENT

Once the user-defined array is linked to the controlled device with the CREATE_BUFFER keyword,

that array is referred to as a "buffer". A buffer is an array variable that is associated with a particular

device for the purpose of storing information received from that device. For more information on

buffers, see the help file for the CREATE_BUFFER keyword. For now, we will focus on the

DATA.TEXT method for storing incoming strings.

Storing charactersWhen a device sends string information to the Master, the Master places the incoming information

into an array, and updates the array's length value. Inside the DATA_EVENT for the device that sent

the message, DATA.TEXT will contain the incoming message up to 2000 characters. This system-

defined array saves the programmer from declaring it in the DEFINE_VARIABLE section. The

previously mentioned CREATE_BUFFER method can still be used if the incoming message is

expected to be larger than 2K, and is capable of storing up to 64K. If the contents of the incoming

message need to be used outside the DATA_EVENT, or need to be viewed in the Watch Window

during debugging, it should be copied into a user-defined array. The following is an example of a

message incoming from a switcher:

Data_Event[Switcher]{ String: { Watch=Data.Text//any incoming message from the switcher is //copied into "Watch" }}

Page 81: Amx Netlinx Programming Ba01

Chapter 10 – Receiving Strings

74 Introduction to AMX Programming

Retrieving CharactersThis is where the keyword GET_BUFFER_CHAR comes into play. This keyword has a two-part

operation:

! First, it retrieves the first character in the buffer for your own utilization. This creates the

same effect as if you retrieved the first storage location of a normal string array.

! Second, it removes that character from the buffer, causing all the other characters to shift

up one place. The second character is now the first, the third is now the second, and so on.

Here is the syntax of this keyword:

Temp_char = GET_BUFFER_CHAR(Data.Text)

If you copied the contents of Data.Text into Watch, your code would look like this:

Temp_char = GET_BUFFER_CHAR(Watch)

Page 82: Amx Netlinx Programming Ba01

Appendix: Troubleshooting

Introduction to AMX Programming

Appendix: Troubleshooting

ESCAPEThe key to troubleshooting any problem including an AMX control system is a structured

approach.

! Explain the problem completely

! Switches and Settings should be checked

! Cables and Connectors should be checked

! Attributes should be verified

! Programming should be verified

! Equipment should be checked

Explain

You need to get as much detail as you can about the problem. When does this problem happen?

What makes the problem occur? Did it work before?

Switches and Settings

Make sure that all the switches and other settings on both the AMX system and the controlled

device are set correctly. Do the communication settings match? Is the device address set correctly?

Cables and Connectors

Are the cables seated properly and firmly? Are all required wires connected in each connector? Is

the cable wired correctly?

Attributes

Make sure all properties are set correctly. Is the button set to the right type? Is it part of a Mutually

Exclusive Group? Is the carrier and data type set correctly for an IR/Serial device? Are the

communication port parameters set correctly on the AMX controller (NXI, NI, NXC, etc.)?

Programming

The program should never be the first solution to a problem if the system worked correctly

previously. Does the programming do what the customer wants? Has the program been modified?

Equipment

If everything else checks out okay then it could be a faulty piece of equipment. Verify that the

device is working properly. Verify that the controlled device is working properly from the front

panel controls or the OEM remote (hand control).

Page 83: Amx Netlinx Programming Ba01

Appendix: Troubleshooting

76 Introduction to AMX Programming

Page 84: Amx Netlinx Programming Ba01

Appendix: Standard IR Function Order

77Introduction to AMX Programming

Appendix: Standard IR Function Order

Channel # Function Channel # Function

1 Play 22 Channel Up

2 Stop 23 Channel Down

3 Pause, Still 24 Volume Up

4 FFwd, Skip Fwd 25 Volume Down

5 Rewind, Skip Rev 26 Mute

6 Search Fwd, Scan, Search 27 On (usually power)

7 Search Rev, Scan, Search 28 Off (usually power)

8 Record 29 TV/Video,TV/VCR,TV/DVD

9 Power, On/Off 30 TV

10 0, 10 31 Video 1, Line A, VCR 1, DVD, Input +

11 1 32 Video 2, Line B, VCR 2, Input –

12 2 33 Video 3

13 3 34 RGB 1, Tape 1

14 4 35 RGB 2, Tape 2

15 5 36 CD

16 6 37 Tuner

17 7 38 Phono

17 8 39 Aux

19 9 40 AM/FM

20 +10 41 Play Reverse

21 Enter 42 A/B

Note: Some channel numbers can apply to several different functions, which are separated by commas.

Page 85: Amx Netlinx Programming Ba01

Appendix: Standard IR Function Order

78 Introduction to AMX Programming

Page 86: Amx Netlinx Programming Ba01

Appendix: ASCII Code Chart

79AMX Programmer II

Appendix: ASCII Code Chart

The table lists the hexadecimal values for all ASCII characters.

Page 87: Amx Netlinx Programming Ba01

Appendix: ASCII Code Chart

80 AMX Programmer II