Professional Documents
Culture Documents
VERSION 2.1
ADVANCED
AXCESS
PROGRAMMING
Version 2.1
March, 1993
Copyright
AMX Corporation, 1993. 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 Corporation.
Trademarks
IBM is a trademark of International Business Machines Corporation. M S-DOS is a trademark of Microsoft Corporation. Phoenix is a trademark of Phoenix Terminal Blocks Inc.
Credits
Written by David Hooker and Erik Engstrom.
Illustrated by Erik Engstrom and David Hooker.
Layout and design by Erik Engstrom.
Cover designs by Don Crum.
Special thanks to all at AMX for invaluable input and support.
Printed in USA.
For additional technical support, feel free to call us.
AMX Corporation
11995 Forestgate Drive
Dallas, Texas 75243
(214) 644-3048
(800) 222-0193
(214) 907-2053 FAX
Table of Contents
Introduction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ix
Necessary equipment
Video monitors
Device numbers
9
12
13
15
Table of Contents
Editor basics
17
Blocking
18
18
19
20
Compilation errors
20
iii
23
23
24
25
Identifiers
26
Reserved words
26
27
29
29
29
Defining devices
30
Defining constants
31
Defining variables
32
Startup code
33
Mainline
33
35
35
37
Direct assignment
39
39
Channel Characteristics . . . . . . . . . . . . . . . . . . . . . . . .
The parts of an output channel
41
Defining latching
42
Mutually exclusive
43
43
44
44
45
Programming feedback
46
47
35
41
iv
49
Table of Contents
57
Boolean expressions
58
The If statement
58
58
59
Nesting
59
60
Trying it out
61
61
63
65
65
57
67
67
Multiple Waits
69
70
Naming Waits
71
71
72
Misusing Wait_Until
72
73
73
74
Table of Contents
While
77
Long_While
78
Medium_While
78
Unit 4: Levels
Creating Levels . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 81
Introduction
81
What is a level?
81
Creating levels
82
Using Levels . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 85
Reading levels
85
Making a preset
85
86
Connecting levels
86
91
Defining arrays
91
92
Strings
94
94
Arrays as strings
95
String lengths
96
98
ASCII codes
99
Integer arrays
100
101
Conversion keywords
101
103
Finding strings
104
Removing strings
104
105
106
vi
107
Receiving strings
107
Creating buffers
107
Storing characters
108
Retrieving characters
108
Clearing a buffer
110
Table of Contents
Two-Dimensional Arrays . . . . . . . . . . . . . . . . . . . . . .
Powerful grouping
111
111
Storing values
112
Retrieving values
113
111
117
Subroutines
117
Defining a subroutine
117
118
Sample program
118
123
Local variables
123
Parameters
124
125
127
Include files
127
129
Factory System_Calls
130
131
123
127
Glossary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 137
Index . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 143
Table of Contents
vii
Introduction to AXCESS
What is AXCESS?
The AXCESS system is a microprocessor-based control system capable of controlling the simple to the most complex devices. Its basic function is to give you
complete control of every device in any system. Through a flexible language,
AXCESS can be programmed to handle almost any task. AXCESS can automatically dim lights, increase volume controls to preset levels, turn on video projectors, and much more.
An IBM-compatible computer is required to program the AXCESS system. Not
much memory is needed; even the more complex AXCESS programs can be handled by an average laptop computer. Once the system is programmed, the computer is only needed for diagnostics tests and any loading or saving of programs.
Introduction to AXCESS
ix
UNIT 1
USING THE
AXCESS
PROGRAM
Getting Started
Introduction
This unit guides you through the simple installation of the AXCESS system for
both the software and the hardware. In addition, the programming environment
is explained, from the main menus to editing techniques.
Necessary equipment
In order to operate the AXCESS system, you need an IBM-compatible computer,
the AXCESS software, the CardFrame, the Master Card, and an appropriate cable.
The computer should have a minimum of 512K of memory. In addition, it must
be functioning on DOS 2.0 or higher.
AMX provides the necessary software, either on one 5.25-inch disk or one 3.5inch disk. The disk contains a number of files: the editor/compiler program,
support files, pre-written block files, code library files, and documentation
files. To read more information about what is on the disk, insert the disk into
your floppy disk drive, change to that drive (either A: or B:), and type README at
the DOS prompt. Up-to-date information about the contents of the disk along
with any additional information will be displayed for you to read.
The AXCESS PC program can be run from the distribution diskette. To start
AXCESS, change to the disk drive containing the floppy disk. Then simply type
AXCESS at the DOS prompt to start the program.
The installation program copies all of the necessary files into the specified directory, in this case C:\AXCESS. If the directory does not exist, the installation
program will create it. The AXCESS system can now be enabled by typing the following command:
Getting Started
C:\AXCESS> AXCESS
For more help on the commands used in this section, see your DOS manual.
Video monitors
The AXCESS system automatically detects color or monochrome monitors. However, for a monitor that reports being a CGA monitor but actually has no color
(such as LCD or plasma-type monitors) you must force the AXCESS system into
the monochrome mode. To do this, enable AXCESS by typing the following:
C:\AXCESS> AXCESS/B
Cause
Solution
Getting Started
Device #
17
33
49
65
81
97
113
Figure 1-2
Recommended device
numbers for the card in slot
1 of each CardFrame within
the AXCESS control system.
In the bottom left corner of the computer screen is the push window, which
displays the status of your AXCESS connections. It should now display the message AX Present. If it says AX Not Responding, there is a communications
problem. See Figure 1-1 for help. (More uses of the push window are described
later in this unit.)
Device numbers
Each device on AXlink must have a unique device number. The device number of
a card is set by the slot number and the DIP switch setting on the Server Card.
The DIP switch on the Server Card sets the address of the card in slot 1. The card
in slot 2 is the Server Cards DIP switch setting plus 1. As follows, the card in slot
3 is the Server Cards DIP switch setting plus 2. This will continue until slot 16.
For example, suppose the DIP switch on the Server Card is 17. The device
number of card slot 1 will also be 17. Card slot 2s device number will be 18
(17+1), card slot 3s device number will be 19 (17+2), and so on. Card slot 16s
device number will be 32 (17+15).
Each AXlink deviceexcept the AMX Touch Panelhas its own DIP switch to
select its device number. The Touch Panel has a keypad to enter its device number on the protected setup page.
At AMX, we have general rules for setting device numbers. For systems up to
eight CardFrames, we recommend the device numbers in Figure 1-2. These
numbers are only for the card in slot 1 of each CardFrame; for each consecutive
device, add one to the appropriate number.
We also recommend that all panels, infrared receivers, and radio frequency
receivers start on device number 128 and increase with each device.
Getting Started
Getting Started
Open..
This option gives you a list of existing AXCESS program files that are in the current directory (files with the DOS extension AXS). Simply move the cursor down
with the arrow keys and select the file you would like to open by pressing <Enter>. You can find your file more quickly by pressing the first letter of your filename; your cursor will appear before the files whose names begin with that same
letter. Once you are within the text editor, changes can be made to your program.
Listed below are special functions available with the Open.. option. They
appear at the bottom of the screen when you are in this menu.
<F1>
File information
<F2>
Delete file
<F3>
Rename file
<F9>
When <F1> is pressed, some basic information about the file you highlighted is
displayed. This information includes the filename, date and time the file was last
modified, and the file size. <F2> allows you to delete an unwanted file. Simply
highlight a file, press <F2>, and then AXCESS will ask you if you are absolutely
sure about deleting the file. <F3> lets you change the name of a file you highlight. <F9> allows you to bring in any text file to the editor. It does not matter if
the file is not related to AXCESS; you can use the program as a simple text editor.
Pressing <Ctrl-O> also activates the Open.. command.
Open include..
This option is identical to the Open.. command, except the program lists the
available include files that you can edit. An include file is an AXCESS program
file which actually contains a portion of code used by another AXCESS program
file. Include files have the DOS extension AXI.
New..
This option creates a basic new file for you. AXCESS loads the file NEW.OVL
(which must be present in the current directory), inserting a few headings and
comments to help you in your programming. The editor is then ready for you to
begin a new program.
Save
When you select this option, AXCESS asks you to give your file a name. If the file
already has a name, press the <Enter> key to overwrite the old file. To save the
file under a new name, type in a different name and press <Enter>.
To save a new file as an include file, instead of pressing <Enter> after typing
in the filename, press the <F1> key.
Normally in DOS, filenames can consist of a maximum of eight characters (not
including the extension). However, AXCESS allows a maximum of 57 characters,
and spaces are acceptable. This gives you greater flexibility for your file description. AXCESS converts your filename into a unique name that the computer can
recognize, and stores the entire name on the first line of the file with the keyword Program_Name.
It is highly recommended to save often and keep a backup copy of all programs.
Pressing <Ctrl-S> also activates the Save.. command.
Source code
The AXCESS program that
you type and edit.
Executable code
A translated version of the
source code that the AXCESS
system can understand.
Compile
This option compiles the source code into executable code. Source code is another name for the AXCESS program that you type and edit; executable code is
what the AXCESS system can understand. By compiling your program, the
source code is translated into executable code. After compiling, the file is stored
in the computers memory. (To download this code to the Master Card, use the
Send... option in the AX File menu.)
This feature also tells you if the AXCESS system is unable to compile your program. If this is the case, a list of errors are displayed. The cursor appears at the
first error. (For information about correcting these errors, see the next chapter.)
Pressing <Ctrl-C> also activates the Compile command.
Print..
This option sends the source code to the printer if one is available. If this command cannot operate the printer, use the Configure... option in the Communications menu to check the LPT setting. This setting should be the same as the LPT
port number in which the printer cable is connected.
Change dir...
This menu option allows you to change the working directory from where you will
load and save your files. Selecting this option displays a window on the screen
where you can edit the DOS path to a different directory. After a new directory
path is entered, AXCESS rebuilds its lists of available files for the new directory.
Version...
Selecting this option displays a window showing the current version of the
AXCESS PC program you are running, plus information on the amount of
memory available. Simply press any key to go back to the editor.
Exit
This option lets you exit to DOS. AXCESS asks if you want to save the current file
if any changes have not been previously saved.
Pressing <Ctrl-X> also activates the Exit command.
AX File
Retrieve
Send...
ctrl-p
Source-send
ON
Verify
Create S19 file...
Send w/password...
Options...
Press <F2> to enter this menu. The AX File menu helps you transfer both the executable code and the source code of a file to the Master Card. In addition, you
can retrieve source code from the Master Card.
Retrieve
This option retrieves the source code from the Master Card, if possible. There
are two reasons why the source code was not saved in the Master Card:
There was not enough memory in the Master Card to store the source code.
The Source-send option was toggled off. For more information, see the
Source-send option explained a little later in this chapter.
Always save the source code on either the hard drive or a floppy disk. Do not
rely on the Master Card to keep all of the source code in memory.
Send...
BUZZWORD
Downloading is the sending
of data from computer to a
device (such as a Master
Card). Uploading is the
opposite: the computer is
the receiver.
This option sends the current executable code to the Master Card. If possible, the
source code is also stored in Master Card memory. If there is not enough room
in the Master Card for the program, AXCESS will stop downloading and give you
a warning. When this happens, try to send the program again, but without sending the source code.
If you have made changes to your source code, AXCESS asks if you want to
recompile your program. If you do not accept this option, the file sent to the
Master Card is not the same as the file in the text editor, but instead the last
compiled code.
Pressing <Ctrl-P> also activates the Send... command.
Source-send
This option toggles on and off. The current status is listed at the right of the
Source-send option.
With Source-send on, AXCESS will attempt to download both the executable
code and the source code to the Master Card when you select the Send... option, memory permitting. This allows the Retrieve option to re-load the source
code from the Master Card. If Source-send is off, AXCESS downloads only the
executable code, which cannot be retrieved from the Master Card.
It is a good idea to leave this option turned on. The only reasons to turn the
Source-send option off are to speed up downloading time during program
development, or because you know the source code is too large to send.
Verify
As a safeguard, this option checks to see if your compiled program is the exact
same as that in the Master Card. It is possible that the Master Card does not
have the latest compiled version of your program. If your compiled program
fails this test, simply recompile the program and send it to the Master Card.
10
Send w/password...
This menu command is identical to the Send... command, but with one addition: it allows the specification of a password which will be needed to retrieve
the program in the future. This password can only be numerical; no alphabetic
characters are allowed in the password.
When a password-protected program is retrieved from a Master Card, AXCESS
will prompt the user for the password before it decompresses and displays the
program in the editor. This provides a means of storing the source code in the
Master Card so that only authorized persons can retrieve it. If the password is
forgotten, however, there will be no way to retrieve the source code from the
Master Card, so do not forget it!
Options...
This menu command brings up a window (Figure 1-3) where the user can set
various options concerning compile-time warning and error messages and other
compiler options. The options are divided into compiler messages and compiler
options. Here is what each selection in the compiler messages section means:
Parameter mismatch: turning this option on enables errors when a parameter of the wrong type is passed to an AXCESS function
Assignment of unlike types: turning this option on enables warnings when a
variable or constant of one type is assigned to a variable of a different type
Variable is not used: turning this option on enables warnings when a
variable declared anywhere in the program is not actually used
DEFINE_CALL is not used: turning this option on enables warnings when a
Define_Call subroutine declared in the program is not actually used
The compiler options section has only one option to turn on or off: Separate
DEFINE_CALL list. Compiling with this option on causes all Define_Call subrou-
Figure 1-3
Screen produced by the
Options... selection in the
AX File menu.
[
[
[
[
]
]
]
]
OPTION
Compiler messages
Parameter mismatch
Assignment of unlike types
Variable is not used
DEFINE_CALL is not used
Compiler Options
[ ] Separate DEFINE_CALL list
to toggle
11
tines to be stored in a separate section of the Master Card memory than the
Define_Program section. This effectively allows the code size of a program to
reach 128K (64K for the Define_Calls and 64K for the Define_Program section).
When this option is turned on, the dialog box asks for a size of the Define_Call
memory segment.
Diagnostics
Press <F3> to enter this menu. The Diagnostics menu allows you to view and
compare the devices on AXlink and the devices defined in the current program
stored in the Master Card.
Figure 1-4
Screen produced by the
Show current devices
option in the Diagnostics
menu.
DEVICE
-----1
2
3
4
128
DEVICE TYPE
----------UNIVERSAL 8 RELAY
UNIVERSAL 8 RELAY
IR/SERIAL DATA
VOLUME CONTROL
SOFTWIRE PANEL
PROGRAM NAME
-----------CASS
LIGHTS
VCR
VOLUME
PANEL
12
Figure 1-5
Screen produced by the
Compare Current Devices... option in the
Diagnostics menu.
BUZZWORD
Firmware is the software that
resides in the EPROMs in
many of the AXCESS devices.
This software is what makes
these devices operate.
Communications
Terminal emulator... ctrl-t
Configure...
Send file...
Receive file...
Pass thru...
When this option is selected, AXCESS displays a list of the devices present in the
system, along with the firmware version of the device (if applicable).
Watch variables...
This item brings up the Variable Watch window. This window allows you to
observe the contents of selected variables while the program is running. See the
AXCESS Programming Guide for details on how to use this feature.
Terminal emulator...
Dumb terminal
A serial communications
device. Whatever you type
goes out the communications port, and whatever
comes in the port is
displayed on the screen.
This option puts the AXCESS system into a dumb terminal mode. Whatever you
type on the screen exits through the communications port, and anything coming
in from the communications port is displayed on your monitor. This mode is
used to communicate directly to the Master Card, modems or other RS-232 devices, and also to debug RS-232 controlled devices. For more information, consult
the AXCESS Programming Guide for Master Card communication commands.
Pressing <Ctrl-T> also activates the Terminal emulator... command.
Configure...
This option lets you choose which communications port, baud rate, and printer
port you need for the AXCESS system. Upon selecting this, a window appears list-
13
COM
COM
COM
COM
1
2
3
4
CONFIGURE
BAUD RATE
300
600
1200
LPT 1
2400
4800
9600
LPT 2
19200
38400
Figure 1-6
Screen produced by the
Configure... option in the
Communications menu.
ing the choices. Move the cursor with the arrow keys next to the item you need
to change. Pressing <Enter> places a check mark next to that item. See Figure 1-6.
Send file...
This option is not the same as the Send... option in the AX File menu. Instead,
it allows the transfer of files between two computers through a connecting serial
cable or modem. Both computers must be running the AXCESS program in order
for the transfer to be complete.
Receive file...
This option works in conjunction with the Send file... option. Once two computers are connected with a serial cable or modem, select Send file... on the
computer that has the file to be sent. Select Receive file... on the other computer to initiate the transfer of data.
Pass thru...
This option allows you to pass data between two of the computers communications ports. All data going in one port comes out the other, and vice versa. Immediately after you select this option, a window appears allowing you to select
the two communications ports you wish to use. When you have done that,
pressing <F10> establishes the pass-thru connection. A window on the screen
will show the number of characters of data being received by each port. Pressing
the <Esc> key quits the pass-thru.
14
Help
Help on Help
Editor
Keywords
Sample Program
15
Editor basics
The AXCESS system offers you a simple text editor for manipulating text in your
programs. Whenever a menu is not displayed on the screen, the editor is in effect. Figure 1-7 lists the commands used within the editor.
Cursor movement around the screen is controlled by the arrow keys. (If you
do not have an extended keyboard, make sure the <NumLock> feature on the
keyboard is off so you can use the keypad instead.) <Home> brings you to the
beginning of the current line, and <End> puts you at the end of the current
line. Also, <Pg Up> takes you one screen of text up, and <Pg Dn> takes you
one screen of text down. <Ctrl-Home> takes you to the very beginning of the
program, and <Ctrl-End> takes you to the very end.
Figure 1-7
Editing commands
Command
Function
Command
Function
<Alt-C>
Copy block
<Alt-W>
<Alt-D>
Delete block
<Alt-Z>
<Alt-F>
<Alt-minus>
<Alt-G>
<Alt-=>
<Alt-I>
<Ctrl-A>
<Alt-L>
Mark block
<Ctrl-E>
<Alt-M>
Move block
<Ctrl-Home>
Go to beginning of program
<Alt-N>
Go to next error
<Ctrl-End>
Go to end of program
<Alt-O>
Print block
<Home>
<Alt-P>
Go to previous error
<End>
<Alt-R>
<Pg Up>
<Alt-S>
<Pg Dn>
<Alt-U>
Unmark block
<Ins>
17
Pressing the <Ins> key toggles the insert/overwrite mode. If you are in the
Insert mode, every character you type is inserted into the current cursor position. In the Overwrite mode, any character under the cursor is overwritten with
the new one.
If you would like to delete an entire line in the program, type <Alt-minus
sign>. If you accidentally delete the wrong line, simply press <Alt-=> to undo
the last command.
There is a status line near the bottom of the screen when you are in the editor.
This tells you which line the cursor is currently on, the amount of available
memory, and the current insert/overwrite mode.
Blocking
NOTE
A number of pre-written
blocks are included on the
AXCESS distribution diskette.
This feature allows you to treat one section of text as a complete block. This
block as a whole can be copied, moved, or deleted.
To mark a block, position the cursor at the beginning of the section of text.
Type <Alt-L>, and this line of text will be highlighted. Move down to the end of
the section and type <Alt-L> again. All the text between the first <Alt-L> and
the last will now be highlighted. To shorten or lengthen this text block, position
the cursor at the new ending for the section and type <Alt-L>.
Now that a block is highlighted, it can be manipulated. To copy the block,
move the cursor to the desired place for the copied text and type <Alt-C>. The
block is copied into the specified place. In order to move the block, move the
cursor again to the desired place for the text and type <Alt-M>. The block disappears from its previous position and is inserted into the new specified place. If
you would like to delete the entire block, type <Alt-D> and the block is erased.
Blocks can also be saved to a disk and then retrieved. To write a block to disk,
type <Alt-W> and AXCESS will ask you for a filename. Even though the block is
saved to disk, it still remains in your current program. To retrieve the block from
disk, position the cursor in the place where you would like to insert the new
text. Type <Alt-G> and supply AXCESS with the blocks filename. The new block
is inserted into your program where the cursor appears.
Once you are finished manipulating a block, it must be unmarked by typing
<Alt-U>. The block returns to a normal background color, and you can resume
editing.
18
Case sensitive
Uppercase and lowercase
values are not evaluated the
same.
text you would like to find. The search function is not case sensitive. This means
that an entry of CASS will return possible references of CASS and cass2,
and even Cassette.
If the fragment or word is found, the current cursor position is set at the beginning of the first line found. Type <Alt-S> again to go to the next line containing the fragment or word.
If you would like to replace text automatically with a new fragment or line,
use the search and replace function. Do the same positioning as the search command, but type <Alt-R>. AXCESS asks you for the text you are searching for, as
well as the text that will replace it. Be careful with this function. If you try to replace all references of cass with CD, cassette would become CDette. (The
cass of cassette was replaced with CD, thus creating the strange new
word.) As a safety precaution, AXCESS asks if you would like to replace the line
or fragment, case by case.
Push window
A window on the bottom left
of the AXCESS program that
displays the Push statement
of the last button pressed in
the AXCESS system.
This feature allows you to find the Push statement of an existing button or to
insert the Push statement of a new button into your program. For more information on the Push statement, see Chapter 6.
In the bottom left corner of the screen, there is a small window (colored magenta on color monitors). This Push window displays the Push statement of the
last button pressed in the AXCESS system. If AXCESS has just been powered up
and no buttons have been pressed, the window displays AX Present. If the
Master Card is not connected or communicating properly, the window displays
AX Not Responding.
For example, an AMX Touch Panel is defined as TOUCH_PANEL in the
Define_Device section of the program (for more information, see Chapter 5).
When button 2 on the Touch Panel on AXlink is pressed, the Push window displays the following:
PUSH[TOUCH_PANEL,2]
In order to find this Push statement in your program, type <Alt-F> when the
statement is in the Push window. The cursor is placed on the line containing the
exact statement. If there is not a Push statement in the program that matches the
text in the Push window, the computer responds with a beep.
You can also insert the displayed Push statement into the program; this is especially useful when a button is not yet programmed. To add a new button into
the program, press the button; its Push statement now appears in the Push win-
19
dow. Position the cursor where the statement should be inserted and type <AltI>; the Push statement will be inserted into your program.
If this button already appears in the program, the computer beeps and takes
the cursor to the existing Push statement. This function does not allow you to
insert the same Push statement twiceyou must do this manually.
Compilation errors
After compiling a program (see the previous chapter for the Compile option
in the File menu), a list of errors and/or warnings may appear in a window at
the bottom of the screen. The cursor is automatically placed at the first of these
in the file, and the type of error or warning is highlighted in the window. See the
AXCESS Programming Guide for more details on warnings and errors.
Once you finish correcting the mistake, you can go to the next error by typing
<Alt-N>. The cursor appears at the next error. To go back to previous mistakes,
type <Alt-P>. The cursor will move to the appropriate place.
After the first error is corrected, it is a good idea to recompile your program.
That one error could be causing many more down the line. For example, if you
forgot to define the device VHS2 earlier in the file, every line that references VHS2
is considered wrong. If you define VHS2 in the appropriate section, all the other
lines are now correct. When the program is recompiled, those errors are repaired.
You might want to have more space on the screen, especially if there is a large
number of errors in a particular section. To remove the error window, press
<Ctrl-E>. This command toggles the error window on and off, so press <Ctrl-E>
to get the window back on the screen.
20
UNIT 2
LANGUAGE
BASICS
Introduction
This unit will help you start writing AXCESS programs. By the end of this unit
you should be familiar with several concepts: the basic ground rules for writing
AXCESS programs, the device-channel concept, the different sections that make
up an AXCESS program, how AXCESS executes a program, basic input and output
functions, and 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.
The AXCESS language is 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:
IF (X = 1)
{
PUSH[PANEL,1]
{
Y = 2
Z = 3
}
}
However, the program section will be executed in the same manner even if it
looks like this:
All the elements are in the correct places, but the spacing is different. Use
whatever method is easiest for you to type and understand.
23
Keyword
A word or series of words
that signifies the operation
for AXCESS to execute.
Statement
A keyword and all of its
parameters or conditions.
Operator
A character or group of
characters that performs a
specific mathematical or
relational function.
Compound statement
A group of several statements, enclosed by a set of
braces.
PUSH[PANEL,1]
{
ON [RELAY_CARD,5]
X = 5
}
PUSH[PANEL,1]
ON [RELAY_CARD,5]
24
Figure 2-1
The uses of braces,
brackets, and parentheses.
These operators cannot be
interchanged within the
program.
Special operators
Operator
Name
Function
{}
Braces
[]
Brackets
()
Parentheses
PUSH[PANEL,1]
{
ON [RELAY_CARD,5]
}
Since there is only one (and only one) statement after the line PUSH[PANEL,1],
braces are not needed.
AXCESS allows you to place helpful comments inside your program. A comment
is a description or remark that is not considered part of the actual program. Any
text after (* and before *) will not be compiled, even if the text is separated over
several lines. See the following example:
You can place any number of comments in your program. However, when the
program is compiled, the compiler will pass over these. They 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 in the next example, descriptions of Push statements are
very useful.
25
PUSH[T_PANEL,1]
{
(* statement(s) *)
}
PUSH[T_PANEL,2]
{
(* statement(s) *)
}
PUSH[T_PANEL,3]
{
(* statement(s) *)
}
(* SLIDE preset *)
(* VHS preset *)
(* V_PROJ preset *)
This will help you find the SLIDE preset, VHS preset, and the V_PROJ preset of
the Touch Panel much faster.
Identifiers
Identifier
A combination of letters,
numbers, or underscores
that represents a device,
constant, or variable.
Reserved words
There are certain words that are reserved for AXCESS 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 AXCESS recognizes it
as a keyword.
26
Figure 2-2
Operator
Function
Operator
Function
()
Parentheses
<
Less than
Multiply
>
Greater than
Divide
<=
Modulus
>=
Add
<>
Not equal to
Subtract
27
29
both. These inputs and outputs are referred to in the AXCESS program as a device-channel, which is written like this:
[5,1]
This device-channel references channel 1 of device 5. 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 AXCESS system,
as it is the most common way that AXCESS communicates to the outside world.
Defining devices
Device number
A unique number from 1 to
255 designated to each
device connected to AXCESS
via AXlink.
30
When you start writing a program, you should first label each device in the system. Each device on AXlink 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, AXCESS checks the corresponding device.
However, with a long list of devices connected to AXlink, these numbers can be
difficult 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, AXCESS will automatically use the corresponding device
number to reference the device.
You will 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 cards in your CardFrame. These cards have
device numbers 1, 2, and 3. You also will need to control a projection screen,
some drapes, and lights. Two relay cards, one in slot 4 and one in slot 5, will
handle these (the first card handles both the screen and drapes). A Softwire
Panel will be used to control all of these devices. Here is what your
Define_Device section should look like:
DEFINE_DEVICE
VCR
= 1
CD
= 2
CASS
= 3
RELAY = 4
LIGHTS = 5
SWP
= 128
From this point on, you can reference device 1 with the name VCR, device 2
with the name CD, and so on.
Also, the push window at the bottom of the screen is changed. If the devices
in the previous example are on AXlink, AXCESS modifies the window to use the
given device name instead of the devices number. This provides a quick reference tool for future programming.
There is one more reason for using Define_Device. When you compare devices using the Compare current devices... option in the Diagnostics menu,
AXCESS checks all the devices listed under Define_Device. Next, it checks which
devices are on AXlink. AXCESS then tells you the devices that you did not define
in your program. These devices cannot be used or referenced until they are defined, so make sure that all devices are under this heading.
The name you assign to a device number cannot change in the program. It
must remain the same to the very end.
AMX encourages the practice of starting control panel device numbers at device 128. This includes radio frequency (RF) receivers, Touch Panels, Softwire
Panels, and all other control panels and receivers.
Defining constants
Constant
An identifier whose value
remains unchanged
throughout the entire
program.
Transport functions
Common functions of
devices such as VCRs and
cassette decks. For
example: Play, Stop, Pause,
Fast Forward, and Rewind.
Constants 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 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 channel numbers *)
PLAY = 1
STOP = 2
PAUSE = 3
FFWD = 4
REW
= 5
(* Relay card
SCREEN_UP
=
SCREEN_DOWN =
SYS_POWER
=
DRAPE_OPEN =
DRAPE_CLOSE =
DRAPE_STOP =
channel definitions *)
1
2
3
4
5
6
31
The value of the constant PLAY from now on is 1. Also, 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 dont have to remember that it is channel 1 of the devicejust use the
constant PLAY and AXCESS knows to use channel 1.
More than one constant can have the same number. For example, PLAY and
FWD can both equal 1. You will probably come across this if two cards do not
have the same channels for the same functions. PLAY on the VCR control card
might be channel 1, and FWD on the slide control card might also be channel 1.
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, AXCESS will notify you with a Duplicate
symbol error message upon compiling.
Defining variables
Variable
A place to store data that will
change as the program is
executed.
32
Variables are places to store data that will change as the program is executed.
Think of a variable as an anything box; nearly anything can be placed in here.
For example, a variable can represent a number. The numeric range is from 0 to
65,535; variables cannot hold a negative number. If one variable is subtracted
from another, the result will be positive. (If, however, you do subtract a larger
number from a smaller number, the result wraps around at 65,535. For instance, if you subtract 20 from 10, the result is 65,525).
Once the system is turned off, variables do not lose their values. If a certain
variable equals 3 when AXCESS is shut down, it will remain 3 when the system is
re-activated. This function has both advantages and drawbacks. It obviously
helps when you need AXCESS to retain values for the variables. However, if you
need those variables to be reset when the system is turned on, they must be reset
manually within the Define_Start section.
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, Define_Latching, and Define_Toggling sections are
also explained later.
Startup code
When the AXCESS system is turned on, the program that was last loaded into the
Master Card is in operation. It is waiting for input from the user. However, you
can tell AXCESS 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
AXCESS power-up.
In your program, you may want to reset all three decks to STOP when AXCESS
is powered up. Here is what your Define_Start section should look like:
DEFINE_START
PULSE [VCR,STOP]
PULSE [CD,STOP]
PULSE [CASS,STOP]
Mainline
Before you begin the main program, you must have the Define_Program
header. This has no real function except to tell AXCESS that you are beginning the
actual program at this point. It is used simply like this:
DEFINE_PROGRAM
(* Your program starts here. *)
Mainline
The section of the program
that actually is executed
continuously by the Master
Card. Also known as the
Define_Program section.
The Define_Program header marks the start of what is called mainline. Mainline is the section of the program that actually runs while the Master Card is
operating. Mainline is the heart of the AXCESS program, and it is where you will
spend most of your time while programming an AXCESS system.
33
Figure 2-3
AXCESS continually loops
through mainline.
DEFINE_PROGRAM
Mainline
AXCESS continually
loops through mainline
34
Input change
A signal sent by the input
function of a channel that
alerts AXCESS to scan
mainline for a reference to
that signal.
Almost all methods of control using an AXCESS system require the use of channels on devices. Every channel has two aspects: the input function and the output function. See Figure 2-4. 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 Card to scan your program for a reference to that input.
When there is an input change, AXCESS passes through the entire program
once to see if the change is referenced. If so, AXCESS executes the statement(s) in
the program associated with the input change. There are six keywords used in
conjunction with input changes:
Push
Release
Push_Device
Figure 2-4
PUSH [Device,Channel]
INPUT
Input change
RELEASE [Device,Channel]
OUTPUT
Channel
Mainline
35
Release_Device
Push_Channel
Release_Channel
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.
Push must be followed by a device number and a particular channel, and
both are enclosed in brackets. Variables can be used in their places, but this is
done only in special circumstances. 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.)
Release
The Release keyword is used in the same way as a Push, except that the operation underneath a Release statement will be executed if the corresponding button is released.
Push_Device
System variable
A value kept in the Master
Card that can be referenced
by certain keywords.
Push_Device is a system variable containing the number of the device having the
channel that was just turned on due to an input change. If a button for device
T_PANEL was pressed, Push_Device would be equal to the device number of
T_PANEL. This variable is set when a channel is turned on, and it remains constant for one pass through mainline. If no channel has been turned on,
Push_Device will contain zero.
Release_Device
NOTE
Push_Device and
Release_Device cannot both
have a non-zero value
during the same pass
through mainline. At least
one will always be zero.
36
Release_Device stores the number of the device containing the channel whose
button was most recently released. If a button for device T_PANEL was released,
Release_Device would be equal to the device number of T_PANEL. This system
variable is used in a program in the same manner as Push_Device. This variable
will have the same value for only one pass through the program.
Push_Channel
Push_Channel is the same as Push_Device, except in this case the channel number that was most recently turned on is stored inside the variable.
Release_Channel
NOTE
Push_Channel and
Release_Channel cannot
both have a non-zero value
during the same pass
through mainline. At least
one will always be zero.
Output change
A message to the output
function of a channel.
Release_Channel, on the other hand, stores the channel whose button was most
recently released. This system variable is used in a program in the same manner
as Push_Channel.
Figure 2-5
Keywords affecting output
changes.
[Device,Channel]
INPUT
ON [Device,Channel]
Output change
OUTPUT
Channel
OFF [Device,Channel]
TOTAL_OFF [Device,Channel]
TO [Device,Channel]
PULSE [Device,Channel]
Mainline
37
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, and turning it off gives it a value of 0.
The following are some 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 [1,2]
ON [TEMP]
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 [1,2]
OFF [TEMP]
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.
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 devicechannel 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. For this reason, To must be found only underneath a
Push statement.
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.
38
The channel or variable will act under the rules set by Define_Latching,
Define_Mutually_Exclusive, and Define_Toggling. You will learn what these
definitions mean later when you add more to your program.
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 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, and the AXCESS
default is one half-second. The Pulse time remains the same value until it is
changed within the program. Here is an example of Set_Pulse_Time:
SET_PULSE_TIME(12)
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:
[SWP,1] = 1
This statement will send an output change to channel 1 of device SWP, telling
the channel to turn on since AXCESS 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
situations, the keywords On, Off, and To are more appropriate.
39
PUSH[SWP,1]
TO [VCR,PLAY]
PUSH[SWP,2]
TO [VCR,STOP]
PUSH[SWP,3]
TO [VCR,PAUSE]
PUSH[SWP,4]
TO [VCR,FFWD]
PUSH[SWP,5]
TO [VCR,REW]
In this code, there are actually five separate but similar statements. Examine
the first to see how it all fits together. First there is the keyword Push, followed
by a device-channel reference, in this case [SWP,1]. This tells AXCESS, OK,
look here if channel 1 on device 128 receives an input change from off to on. If
such an input change occurs, the corresponding To statement executes. The To
statement tells AXCESS, For as long as channel 1 on device 128 is activated,
turn on device 1, channel 1. You may be wondering where the numbers came
from, since the Push and To statements have the words SWP, VCR, and PLAY.
Remember, SWP is a device definition for device 128, and VCR is a constant with
a value of 1, as is PLAY.
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.
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.
40
Channel Characteristics
Figure 2-6
Parts of an output channel.
INPUT
OUTPUT
Physical
Output change
Status
Channel
Channel Characteristics
41
Defining latching
Momentary
A defined behavior of status
that causes its output
channel to be activated as
long as the corresponding
button is pressed.
Latching
A defined behavior of status
that causes its output
channel to stay on or off until
activated once more.
DEFINE_LATCHING
[RELAY,SYS_POWER]
[RELAY,DRAPE_OPEN]
[RELAY,DRAPE_CLOSE]
If you have a series of consecutive channels to be defined, you can use a shortcut. The use of double periods (..) will specify a range of channels between the
first and last channel. Suppose the lights your system controls needs latched relays to operate. Instead of defining each one right after the other, you can do this:
[LIGHTS,LIGHT_FULL]..[LIGHTS,LIGHT_OFF]
* 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.
42
Channel Characteristics
Mutually exclusive
Channels can also be defined as mutually exclusive. A mutually exclusive group
is a set of channels in which only one channel of the set can be turned on at a
time. There are three kinds of mutually exclusive channels: momentary, latching, and toggling.
IMPORTANT
Make sure you find out which
devices need mutually
exclusive channels. Do not
wait until you test out the
program, as you may
damage some devices.
NOTE
Once a channel has
feedback in a mutually
exclusive group, there will
always be one channel with
its status on in that group,
unless it is turned off with
Total_Off.
DEFINE_MUTUALLY_EXCLUSIVE
([RELAY,SCREEN_UP],[RELAY,SCREEN_DOWN])
([RELAY,DRAPE_OPEN]..[RELAY,DRAPE_STOP])
Channel Characteristics
43
([LIGHTS,LIGHT_FULL]..[LIGHTS,LIGHT_OFF])
([VCR,PLAY]..[VCR,REW])
([CASS,PLAY]..[CASS,REW])
([CD,PLAY]..[CD,REW])
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.
Mutually exclusive
latching
A characteristic of status
that allows only one channel
of a pre-defined set to be on
at a time. The output channel
stays on until another channel
of the set is activated.
There is a way for a mutually exclusive channel have its physical output continually on if necessary: a channel can be defined as both mutually exclusive and
latching, resulting in the description mutually exclusive latching. If you define a
channel in this manner, the physical output remains on until another button in
its mutually exclusive set is pressed.
The status of a mutually exclusive latching channel behaves in the same manner
as that for a mutually exclusive momentary channel. Note that the physical part
and the status of a mutually exclusive latching channel operate in the same manner.
In your program, the lighting relays are already defined as latching. However, you also want them to have the characteristics of a mutually exclusive set;
only one lighting mode can be on at one time. Thus you would also place the
device-channels of these relays in the Define_Mutually_Exclusive section:
DEFINE_MUTUALLY EXCLUSIVE
([LIGHTS,LIGHT_FULL]..[LIGHTS,LIGHT_OFF])
44
Channel Characteristics
distribution diskette.
DEFINE_TOGGLING
[RELAY,SCREEN_UP]
[RELAY,SCREEN_DOWN]
PUSH[SWP,8]
TO [RELAY,SYS_POWER]
PUSH[SWP,33]
TO [RELAY,SCREEN_UP]
PUSH[SWP,34]
TO [RELAY,SCREEN_DOWN]
PUSH[SWP,41]
TO [RELAY,DRAPE_OPEN]
PUSH[SWP,42]
TO [RELAY,DRAPE_CLOSE]
PUSH[SWP,43]
TO [RELAY,DRAPE_STOP]
PUSH[SWP,45]
TO [LIGHTS,LIGHT_FULL]
PUSH[SWP,46]
TO [LIGHTS,LIGHT_MED]
PUSH[SWP,47]
TO [LIGHTS,LIGHT_LOW]
PUSH[SWP,48]
TO [LIGHTS,LIGHT_OFF]
Channel Characteristics
45
Programming feedback
Feedback
The lighting of a button
during and after it is pressed.
So far you have been shown how a channels 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 Softwire Panel. Feedback refers
to the lighting of a button during and after it is pressed. AXCESS 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. For example:
[SWP,1] = [VCR,PLAY]
When VCR channel 1 (the constant value of PLAY) is on, the light of SWP button 1 will also be 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.
46
Channel Characteristics
NOTE
Once a channel has
feedback in a mutually
exclusive group, there will
always be one channel with
feedback on in that group,
until turned off with Total_Off.
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 AXCESS, Take the output status
of channel PLAY on device VCR, and send it as an output change to channel 1 of
device SWP. Since you defined the device-channel [VCR,PLAY] as being 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 Softwire Panel.
PUSH[SWP,1]
TO[VCR,PLAY]
[SWP,1] = [VCR,PLAY]
When SWP button 1 (Play) is pressed, both VCR channel 1 (PLAY) and the
buttons feedback are turned on.
The feedback statements can also be grouped together in a feedback section at
the end of the program. For example:
distribution diskette.
NOTE
For the sake of saving space,
the additional feedback
statements for your program
are listed in the next chapter.
But first, try to write them on
your own.
[SWP,1] = [VCR,PLAY]
[SWP,2] = [VCR,STOP]
[SWP,3] = [VCR,PAUSE]
This feedback section will act no differently if each statement is placed under
its corresponding Push statement.
Where you locate your feedback statements inside your program makes no
difference to the operation of the system, but it does make a difference in the
readability of your program. Grouping all of the feedback statements at the end
of the program is fine, but in larger programs it can be a hassle to skip from the
top where the Push is located to the bottom where the feedback statements is
located. Smaller programs, however, may be easier to manage if all the Pushes
are together and all the feedback statements are together. A good compromise
is to break your program into sections of code where each section has a similar
group of functions, and put the feedback statements for each section right below it. (See Figure 2-7.)
Channel Characteristics
47
Code
Code
Code
Feedback
Code
Code
Code
Code
Code
Feedback
Feedback
Feedback
Feedback
Code
Feedback
Code
Feedback
Feedback
Code
Feedback
Code
Feedback
Feedback
Feedback
Combination
Figure 2-7
Different positions for
feedback statements.
48
Channel Characteristics
VCR
CD
CASS
SCREEN
DRAPE
PLAY
PLAY
PLAY
UP
OPEN
STOP
STOP
STOP
DOWN
CLOSE
PAUSE
PAUSE
PAUSE
FFWD
SKIP
FWD
FFWD
REW
SKIP
REV
REW
STOP
LIGHTS
FULL
MED
LOW
SYSTEM POWER
OFF
Figure 2-8
The Softwire Panel layout
based on your program.
49
(***********************************************************)
(*
DEVICE NUMBER DEFINITIONS GO BELOW
*)
(***********************************************************)
DEFINE_DEVICE
VCR
CD
CASS
RELAY
LIGHTS
SWP
=
=
=
=
=
=
1
2
3
4
5
128
(***********************************************************)
(*
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
LIGHT_FULL =
LIGHT_MED =
LIGHT_LOW =
LIGHT_OFF =
(***********************************************************)
(*
VARIABLE DEFINITIONS GO BELOW
*)
(***********************************************************)
DEFINE_VARIABLE
(***********************************************************)
(*
LATCHING DEFINITIONS GO BELOW
*)
(***********************************************************)
DEFINE_LATCHING
[RELAY,SYS_POWER]
[RELAY,DRAPE_OPEN]
[RELAY,DRAPE_CLOSE]
[LIGHTS,LIGHT_FULL]..[LIGHTS,LIGHT_OFF]
50
(***********************************************************)
(*
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])
DEFINE_TOGGLING
[RELAY,SCREEN_UP]
[RELAY,SCREEN_DOWN]
(***********************************************************)
(*
STARTUP CODE GOES BELOW
*)
(***********************************************************)
DEFINE_START
PULSE [VCR,STOP]
PULSE [CD,STOP]
PULSE [CASS,STOP]
(***********************************************************)
(*
THE ACTUAL PROGRAM GOES BELOW
*)
(***********************************************************)
DEFINE_PROGRAM
PUSH[SWP,1]
TO [VCR,PLAY]
PUSH[SWP,2]
TO [VCR,STOP]
PUSH[SWP,3]
TO [VCR,PAUSE]
PUSH[SWP,4]
TO [VCR,FFWD]
PUSH[SWP,5]
TO [VCR,REW]
PUSH[SWP,9]
TO [CD,PLAY]
PUSH[SWP,1]
TO [CD,STOP]
PUSH[SWP,11]
TO [CD,PAUSE]
PUSH[SWP,12]
TO [CD,FFWD]
PUSH[SWP,13]
TO [CD,REW]
PUSH[SWP,17]
TO [CASS,PLAY]
PUSH[SWP,18]
TO [CASS,STOP]
51
PUSH[SWP,19]
TO [CASS,PAUSE]
PUSH[SWP,2]
TO [CASS,FFWD]
PUSH[SWP,21]
TO [CASS,REW]
PUSH[SWP,8]
TO [RELAY,SYS_POWER]
PUSH[SWP,33]
TO [RELAY,SCREEN_UP]
PUSH[SWP,34]
TO [RELAY,SCREEN_DOWN]
PUSH[SWP,41]
TO [RELAY,DRAPE_OPEN]
PUSH[SWP,42]
TO [RELAY,DRAPE_CLOSE]
PUSH[SWP,43]
TO [RELAY,DRAPE_STOP]
PUSH[SWP,45]
TO [LIGHTS,LIGHT_FULL]
PUSH[SWP,46]
TO [LIGHTS,LIGHT_MED]
PUSH[SWP,47]
TO [LIGHTS,LIGHT_LOW]
PUSH[SWP,48]
TO [LIGHTS,LIGHT_OFF]
(* FEEDBACK *)
[SWP,33] = [RELAY,SCREEN_UP]
[SWP,34] = [RELAY,SCREEN_DOWN]
[SWP,1]
[SWP,2]
[SWP,3]
[SWP,4]
[SWP,5]
=
=
=
=
=
[VCR,PLAY]
[VCR,STOP]
[VCR,PAUSE]
[VCR,FFWD]
[VCR,REW]
[SWP,9] = [CD,PLAY]
[SWP,1] = [CD,STOP]
[SWP,11] = [CD,PAUSE]
[SWP,12] = [CD,FFWD]
[SWP,13] = [CD,REW]
[SWP,17]
[SWP,18]
[SWP,19]
[SWP,2]
[SWP,21]
=
=
=
=
=
[CASS,PLAY]
[CASS,STOP]
[CASS,PAUSE]
[CASS,FFWD]
[CASS,REW]
[SWP,8] = [RELAY,SYS_POWER]
52
[SWP,41] = [RELAY,DRAPE_OPEN]
[SWP,42] = [RELAY,DRAPE_CLOSE]
[SWP,43] = [RELAY,DRAPE_STOP]
[SWP,45]
[SWP,46]
[SWP,47]
[SWP,48]
=
=
=
=
[LIGHTS,LIGHT_FULL]
[LIGHTS,LIGHT_MED]
[LIGHTS,LIGHT_LOW]
[LIGHTS,LIGHT_OFF]
(***********************************************************)
(*
END OF PROGRAM
*)
(*
DO NOT PUT ANY CODE BELOW THIS COMMENT
*)
(***********************************************************)
53
UNIT 3
CONDITIONALS,
LOOPS,
AND WAITS
Introduction
While your first program may look complicated at first, it really doesnt show
the power of the AXCESS language. The program is what we at AMX call one-toone. 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.
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 the one in Figure 3-1.
SELECT
TRANSPORT
SCREEN
DRAPE
VCR
PLAY
UP
OPEN
CD
STOP
DOWN
CLOSE
CASS
PAUSE
STOP
FFWD
LIGHTS
REW
FULL
MED
LOW
SYSTEM POWER
OFF
Figure 3-1
The revised Softwire Panel
layout for your program. The
functions are the same, but
there are fewer buttons.
57
You now have seven 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 Boolean expressions to select the correct function of the Transport buttons.
Boolean expressions
Boolean expression
A conditional statement used
to tell AXCESS whether or not
to execute a particular
function or functions in the
program. Also known as a
relational expression.
The If statement
The most common keyword in AXCESS that uses Boolean expressions is the If
keyword. Every If statement must be followed by a Boolean expression enclosed
in parentheses. This provides the beginning of a conditional execution of statements. The structure is as follows:
IF (Boolean expression)
(Statement 1)
If the Boolean expression is true, AXCESS executes Statement 1 and then continues with whatever statements follow. If the Boolean expression is false, Statement 1
is ignored. If Statement 1 is a compound statement, it must be enclosed in braces.
58
IF (Boolean expression)
(Statement 1)
ELSE
(Statement 2)
If the Boolean statement is true, then Statement 1 is executed. Statement 2, underneath the Else statement, is ignored. If the Boolean statement is false, then
Statement 2 is executed. Remember that Statement 1 is automatically ignored if
the expression is false.
IF (Boolean expression)
(Statement 1)
ELSE IF (Boolean expression)
(Statement 2)
ELSE IF (Boolean expression)
(Statement 3)
(* As many Else If statements as memory allows... *)
Default statement
A statement (or compound
statement) that executes if
none of the conditions being
tested comes true.
Nesting
Placing conditional branches
inside other conditional
branches.
A last Else statement (not Else If) can be placed at the end as a default statement; that is, if AXCESS does not find a true If or Else If statement, it executes the
final Else statement. However, this last statement is not necessary.
Nesting
Once AXCESS is travelling along a branch (for example, Statement 1 in the previous example), you can tell it to branch off again with another If statement. This
branch within a branch is called nesting. There can be any level of branches; 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)
IF (Y = 1)
(Statement 1)
ELSE
(Statement 2)
59
You can see by the alignment of the Else statement with the IF (X = 5) that
these two should be associated. The second If statement is not supposed to have
an Else counterpart in this example. However, such is not the case. AXCESS pairs
the second If statement with the Else, because the compiler associates the Else
with the closest If statement.
With braces, you can force the compiler to associate the Else with IF (X =
5). For example:
IF (X = 5)
{
IF (Y = 1)
(Statement 1)
}
ELSE
(Statement 2)
By using the braces, you isolate the IF (Y = 1) statement from the If...Else
set of statements.
SELECT
{
ACTIVE (Boolean expression 1) : (Statement 1)
ACTIVE (Boolean expression 2) : (Statement 2)
ACTIVE (Boolean expression 3) : (Statement 3)
(* ...etc. *)
}
Each one of the Boolean 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.
Using a Select...Active is much preferred to multiple If...Else If statements; it
uses less memory and it runs faster. If too many If...Else If statements are
chained together, they can overflow the Master Cards memory and crash the
entire system. Obviously it is much better to use Select...Active in such situations.
When using the If...Else set of statements, the code following the Else is the
default statementif the condition of the If is false, the default statement following the Else is executed. So what happens in a Select...Active if none of the con-
60
ditions 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
ACTIVE
ACTIVE
ACTIVE
}
(condition) : (statement)
(condition) : (statement)
(condition) : (statement)
(1) : (default statement)
Here, the last Active will always be true, and will execute only if all of the
conditions of the previous Actives are false. This makes the last Actives statement the default statement.
Trying it out
BUZZWORD
Select groups refer to a
group of buttons that select
a single deck or device out of
a group. In this case, the
select group consists of the
VCR, CD player, and the
cassette deck.
Now you can write the code for your new panel layout. Before you do that,
however, you will need to update your definition sections a little.
There are two methods of implementing select groups. One is to base the
selection on which variable of a mutually exclusive set is active. The other is to
use one variable and change its value based on which deck is selected. You will
explore the mutually exclusive variable method first.
DEFINE_VARIABLE
VCR_SELECT
CD_SELECT
CASS_SELECT
Now you make the variables mutually exclusive by adding this line to the
Define_Mutually_Exclusive section:
(VCR_SELECT,CD_SELECT,CASS_SELECT)
61
Notice that there are only parentheses around the whole group and no brackets. This is because brackets are only necessary when a device-channel reference
is used. Now you can make the Push for each Select button go To one of these
variables. Due to the last button pressed nature of the variables status, you
can determine which deck was last selected. Here is the mainline code:
PUSH [SWP,1]
TO [VCR_SELECT]
PUSH [SWP,2]
TO [CD_SELECT]
PUSH [SWP,3]
TO [CASS_SELECT]
Notice that even though you do not use brackets in the mutually exclusive
section with variables, you do in the To statement. This is because the To statement always requires brackets.
Now you can add your conditional statements. Look at the VCR functions
first, noting that the button numbers on the Softwire Panel for the transport buttons are 17 through 21 for all three decks.
IF (VCR_SELECT)
{
PUSH[SWP,17]
TO [VCR,PLAY]
PUSH[SWP,18]
TO [VCR,STOP]
PUSH[SWP,19]
TO [VCR,PAUSE]
PUSH[SWP,2]
TO [VCR,FFWD]
PUSH[SWP,21]
TO [VCR,REW]
}
62
Not only are the functions of the Transport buttons conditional, but the feedback is too. You could make three more If statements, one for the feedback of
each deck. Yet a better method is to include each decks feedback statements in
the same If statement as the control statements. By doing this, your VCR section
now looks like this:
IF (VCR_SELECT)
{
PUSH[SWP,17]
TO [VCR,PLAY]
PUSH[SWP,18]
TO [VCR,STOP]
PUSH[SWP,19]
TO [VCR,PAUSE]
PUSH[SWP,2]
TO [VCR,FFWD]
PUSH[SWP,21]
TO [VCR,REW]
[SWP,17]
[SWP,18]
[SWP,19]
[SWP,2]
[SWP,21]
=
=
=
=
=
[VCR,PLAY]
[VCR,STOP]
[VCR,PAUSE]
[VCR,FFWD]
[VCR,REW]
Repeating this procedure for each deck completes the programming required
to implement your new panel layout using mutually exclusive variables. The
entire source code up to this point is on your distribution disk as STEP2.AXS.
Select variable
A variable whose value
determines which device in a
group is currently selected.
PUSH[SWP,1]
DECK = VCR
PUSH[SWP,2]
DECK = CD
PUSH[SWP,3]
DECK = CASS
63
Now here is where you see some of the real power of the AXCESS language.
You can reduce the number of transport sections from three to just one by using
the variable DECK as the device number in the To statements, instead of using
VCR, CD, and CASS. Heres the section of code:
PUSH[SWP,17]
TO [DECK,PLAY]
PUSH[SWP,18]
TO [DECK,STOP]
PUSH[SWP,19]
TO [DECK,PAUSE]
PUSH[SWP,2]
TO [DECK,FFWD]
PUSH[SWP,21]
TO [DECK,REW]
These statements, like all feedback statements, are direct assignment output
changes; however, the source of the assignment is a Boolean expression. In interpreting this kind of feedback statement, AXCESS first evaluates the Boolean expression. If the expression is evaluated as true, AXCESS replaces the expression
with a 1; otherwise AXCESS replaces it 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 Softwire Panel
64
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 that devicechannels output on.
The entire source code for this program using the variable assignment
method is included on the distribution disk as STEP3.AXS.
Boolean operator
A keyword or symbol that
creates a relation between
two items.
The previously discussed If and If...Else statements could only base the program
flow on one condition. You can, however, combine two of these conditions with
a Boolean operator. This operator sets the rules of what the end result will be.
The Boolean operators used in the AXCESS system are And, Or, Xor, and Not.
These are placed in between the two conditions after the If statement. For example:
If the end result of the Boolean expression is true, AXCESS continues with
Statement 1. If the end result is false, AXCESS simply ignores Statement 1.
Figure 3-2
Abbrev
Function
Abbrev
Function
&&
Logical And
&
Bitwise And
||
Logical Or
Bitwise Or
^^
Logical Xor
Bitwise Xor
Logical Not
Bitwise Not
65
Figure 3-3
A pictorial explanation of the
Boolean expression table for
the operator And.
Figure 3-4
An example of how a
Boolean expression table is
used to compare multiple
conditions.
And
Boolean operator
Statement 2
possible conditions
T
T T
F
F
F F
And
Boolean operator
Statement 2:
(NUM2 = 4) is false
T T
T T T
F F
The result is found by basing the conditions of the statements against the
rules set by the Boolean operator. Here are those specific rules:
And
Or
At least one of the conditions must be true for the result to be true.
Xor
Not
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.
The statement would have been true if NUM2 had been equal to 3, because in
an And expression both statements must be true (see Figure 3-4).
The Boolean expression tables in Figure 3-5 are a quick reference guide for the
result of a Boolean expression. They are not necessary, but they can be very helpful.
And
Figure 3-5
Tables of results of various
Boolean operators.
66
Or
Xor
Not
T
T T
F
F
T F
T T T
T F
T F T
T F
T F T
F F
F T
F T
F T
10
Wait list
A list containing unexpired
Wait statements. After each
pass through mainline, the
Master Card scan this list to
see if any have come due.
The 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, AXCESS places the Wait statement into a list in memory and continues on with the rest of the program. After
each pass through mainline, the Master Card scans this Wait list, and if any
Waits have come due, AXCESS executes the statement or compound statement
immediately following the expired Wait keyword. Up to 50 Waits are allowed in
the list at a time. (Refer to the AXCESS Programming Guide for a complete discussion of mainline and the AXCESS bus.)
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 (well
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.
67
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 looks like this:
AMP_POWER = 7
PUSH[SWP,8]
{
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]
}
}
PUSH[SWP,8]
{
IF (device-channel)
compound statement
ELSE
compound statement
}
From this simpler 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 AXCESS checks that
68
channels status. If it is on, AXCESS evaluates the condition as true and executes
the first compound statement. Otherwise AXCESS executes the compound statement following the Else.
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 (same as one half-second), followed by an Off statement to the rack power relay. AXCESS places this
Wait into the Wait list and continues with the program. Since these statements
are part of an If compound statement, AXCESS does not execute the Elses compound statement.
As AXCESS continues to run, the Wait is still in the Wait list. After one halfsecond has elapsed, AXCESS 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. AXCESS first turns on the rack
power, waits a half-second, and then turns on the amp power.
Multiple Waits
Now 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 accomplishes 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.
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:
PUSH[SWP,8]
{
IF ([RELAY,RACK_POWER]) (* Power being turned off *)
{
69
OFF [RELAY,AMP_POWER]
TO [LIGHTS,LIGHT_FULL]
TO [RELAY,SCREEN_UP]
TO [RELAY,DRAPE_OPEN]
WAIT 5 OFF [RELAY,RACK_POWER]
WAIT 12 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 2 PULSE [LIGHTS,LIGHT_MED]
}
}
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.
Waits can appear inside other Waits. This is called nesting Waits. You dont
need to nest Waits in your program here, but here is how it is done:
WAIT 2
{
ON [RELAY,SCREEN_UP]
WAIT 2 OFF [RELAY,SCREEN_UP]
}
In this example, AXCESS 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 Waits. Using
nested Waits is in many cases more readable than non-nested Waits. Non-nested
Waits, however, use less code. Here is the same example without nesting:
WAIT 2 ON [RELAY,SCREEN_UP]
WAIT 4 OFF [RELAY,SCREEN_UP]
70
the list for expired Waits, the Wait will be due to execute. Using Wait is
only done in special cases.
Any 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:
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 Waits
When a Wait is given a unique name, it can be either cancelled, paused, or
restarted. To name a Wait, simply place a name in single quotes after the Wait
statement. For example:
WAIT 3 DELAY
Once DELAY is entered into the list, it cannot be re-entered until the first has
been removed.
There are certain considerations in naming Waits:
They should not be previously defined constants or variables.
They cannot be names that have already been assigned to buffers or
subroutines. (Buffers and subroutines are explained later in the manual.)
They can contain spaces, unlike other AXCESS identifiers.
71
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. 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 all Waits in the Wait list, named and un-named.
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:
To cancel the Wait in the power-on section, simply add this line:
Wait_Until list
A list containing unexpired
Wait_Until statements. After
each pass through mainline,
the Master Card scan this list
to see if any have come due.
The Wait_Until keyword is not a true timing keyword; AXCESS does not wait
for a certain amount of time to elapse. Instead, AXCESS checks to see if a condition is true. When the condition becomes true, AXCESS executes the statements
listed directly below the Wait_Until statement.
All Wait_Untils go into another list very similar to the Wait list, called the
Wait_ Until list. Just as it does with Waits, each pass through mainline AXCESS
checks to see if any Wait_Until conditions have become true. For each one that
has, AXCESS immediately executes the sequence below the Wait_Until statement. If not, AXCESS keeps the Wait_Until in the Wait_Until list until its condition becomes true.
Misusing Wait_Until
Since AXCESS only checks the status of pending Wait_Untils 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 dont need Wait_
Until in your program yet, but this program segment illustrates the misuse of
Wait_Until:
72
WAIT_UNTIL (Y=4)
{
(* statements *)
}
Y=4
Y=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.
AXCESS cannot detect this sort of error, so make sure each Wait_Until statement
can become true one way or another.
Set_Timer
The timer provided to you is a simple one. It cannot be stopped or pausedonly
set. Like a Wait, time is measured in increments of tenths of seconds. There is
only one such timer available.
To set the timer, the Set_Timer keyword is used. You must specify a number
between 0 and 65,535, and the timer will start counting up from that point. After
the timer reaches 65,535 it wraps around to 0 and starts over.
Get_Timer
The Get_Timer system variable contains the current status of the timer. Usually
this keyword is used in conjunction with an If statement. For example, look at
the following code segment:
73
IF (GET_TIMER >= 1)
{
(* do something *)
}
Notice that a greater than sign was combined with the equal sign. There
is a chance that the timer will reach the number 100 while the program is being
executed elsewhere. When AXCESS reaches the Get_Timer section, the timer
might be 103. If the condition was that Get_Timer be equal to 100, the following
statements would have been skipped. Never use only an equal sign with the
Get_Timer system variable in an If statement.
Unlike variables, the timer loses its value when the AXCESS system is turned
off. When the system is reactivated, the timer is reset to zero.
IF (TIME = 23::)
PULSE [LIGHTS,LIGHT_OFF]
74
The statements following the If statement will be executed every day at 11:00
PM. Suppose you wanted to change it so that every hour the lights would turn
off. The statement would simply be changed to read:
IF (TIME = ??::)
PULSE[LIGHTS,LIGHT_OFF]
The question mark (?) acts like a wildcard character, allowing any character
to be in its place. Since question marks are in place of the hour, the comparison
will be true once an hour when the minutes and seconds are zero, and the lights
will turn off.
Your entire program up to this point is contained in the file STEP4.AXS on your
distribution disk.
75
11
While
Sometimes it may be necessary to loop through a certain section of a program
until a condition becomes true. This is the purpose of the While family of keywords. When AXCESS comes to a While, it checks to see if the condition following
it is true. If the condition is false, AXCESS skips the statement immediately following the Whilejust like the If keyword. However, if the condition is true,
AXCESS executes the statement and then rechecks the Whiles conditional expression. If the condition is still true, the statement is executed again.
This sequence continues until the condition is evaluated as false. When the
condition comes up false, program execution continues with the statement following the Whiles block of code. Here is an example:
X = 1
WHILE (X < 5)
{
ON [RELAY,X]
X = X + 1
}
In this code example, the variable X is first set to 1. Next, the While statement
checks to see if X is less than 5. Since it is, AXCESS executes the compound statement directly following the While: the device-channel referenced by [RELAY,1]
(since X equals 1) is turned on, and X is incremented by one. Then program execution goes back to the While statement. This loop continues until X becomes 5,
in which case the compound statement following the While is not executed, and
AXCESS goes on to the rest of the program. This block of code essentially turns
on the first four channels of device RELAY.
There is a limitation on using the While keyword. The amount of time AXCESS
spends executing any single While cannot exceed 0.5 seconds. This is because the
Master Card updates AXlink (the communications bus between all AXCESS devices) between each pass through mainline. If AXlink is not updated at certain
time intervals, problems could develop during bus communications. Therefore,
to prevent an AXCESS program from stalling mainline too long, there is a 0.5 sec-
77
ond time-out on While loops; that is, AXCESS will forcibly exit the While after one
half-second, regardless of the operation it is executing. (Remember, Waits are
checked after mainline and thus are not subject to such restrictions.)
Long_While
There are cases where a While loop cannot help but to take longer than one halfsecond to execute. If this becomes the case, simply change the While keyword in
question to a Long_While.
The main difference between a While and a Long_While is that after each loop
through the Long_Whiles statement, the AXlink bus is updated. This, in effect,
makes the statement or compound statement following a Long_While to be a
mini-mainline for as long as the condition of the Long_While is true. Therefore, Long_While has absolutely no timeout period. But be careful! If you dont
provide a way out of your Long_While (by allowing the condition to become
false), the program will become stuck inside the Long_While and no other code
outside of the loop will be executed.
Medium_While
During the execution of a Long_While, AXCESS scans AXlink just like it does
when running mainline. It is during this scanning that AXCESS receives information about input changes from devices such as Softwire Panels and Touch Panels. This activity also takes place after each loop through a Long_While. Therefore, if
a user presses a button while AXCESS is looping through a Long_While, the input
change is lost to any programming outside the Long_While loop.
If this becomes a problem, the Medium_While keyword may be used. This
keyword operates just like a Long_While, but it ignores input changes from
AXCESS devices. These input changes are not lost, but will remain pending until
the Master Card scans for them againeither before the next pass through
mainline, or after a pass through a Long_While. (Refer to the AXCESS Programming Guide for a complete discussion of mainline and the AXCESS bus.)
Once again, be very careful when using Long_While and Medium_While. If
the condition associated with one of these in your program can never become
false, your program could get stuck in an infinite loop, requiring a reset of the
Master Card or maybe even a re-loading of the systems programming.
78
UNIT 4
LEVELS
12
Creating Levels
Introduction
So 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 cards, voltage generator cards,
and pan/tilt control cards. Devices such as these use levels to interface with
the outside world. Also, several AXCESS 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 the
AXCESS devices.
What is a level?
Digital
An input or output can have
only two values: on and off.
Analog
An input or output can have
many values.
Level
Figure 4-1
The imaginary knob. The
knob is the level, which can
have a range of values.
LEVEL 1
0
Unit 4: Levels
LEVEL 2
255
255
Creating Levels
81
Imagine that a volume control card has two volume knobs: one for the left
speaker and one for the right. See Figure 4-1. 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 levels
In the AXCESS language, a level 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 an
AXCESS device that supports levels, you use the keyword Create_Level. Here is
the syntax:
This keyword creates an association between the specified level of the device
and the specified variable. During execution of your program, AXCESS will continually update the variable to contain the value of the level with which it is associated.
(Refer to the AXCESS Programming Guide for a complete discussion of mainline
Figure 4-2
The Touch Panel layout for
this unit.
VOLUME CONTROL
UP
DOWN
MUTE
PRESET
82
Creating Levels
Unit 4: Levels
and the AXlink bus.) 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
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. See Figure 4-2. Here are some code excerpts to get started:
DEFINE_DEVICE
VOLUME = 1
PANEL = 128
DEFINE_CONSTANT
(* Three channels to control both outputs together *)
V_UP = 1
V_DN = 2
V_MT = 3
DEFINE_VARIABLE
VOL_LEVEL
DEFINE_LATCHING
[VOLUME,V_MT]
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 which 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. Notice that the V_MT channel is latching; this is the channel that mutes the volume. By making it latching,
subsequent presses toggle the muting on and off. Here is the code for the Volume Up, Volume Down, and Volume Mute buttons on the Touch Panel:
Unit 4: Levels
DEFINE_PROGRAM
PUSH[PANEL,1]
{
OFF [VOLUME,V_MT]
TO [VOLUME,V_UP]
}
Creating Levels
83
PUSH[PANEL,2]
{
OFF [VOLUME,V_MT]
TO [VOLUME,V_DN]
}
PUSH[PANEL,3]
TO [VOLUME, V_MT]
[PANEL,1] = [VOLUME,V_UP]
[PANEL,2] = [VOLUME,V_DN]
[PANEL,3] = [VOLUME,V_MT]
Ramp
To change a level from one
value to another smoothly
over a period of time.
84
Creating Levels
Notice that the Volume Up and Volume Down buttons will automatically
unmute 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. You will add the code for these in the next chapter.
Unit 4: Levels
13
Using Levels
Reading levels
NOTE
The volume card remembers
the last level when it is muted
so that it can unmute to that
same level.
When a level is associated with a variable using Create_Level, AXCESS 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 preset
Preset
A level saved for later
retrieval. When a preset is
recalled, the level returns to
the preset value.
For information on a
particular devices
Send_Command functions,
see the AXCESS Programming Guide and the
products literature.
Now 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:
PUSH[PANEL,5]
{
SET_TIMER()
}
RELEASE[PANEL,5]
{
IF (GET_TIMER>2)
{
PRESET = VOL_LEVEL
}
ELSE
{
SEND_COMMAND VOLUME, "'PL', ITOA(PRESET)"
OFF [VOLUME,V_MT]
}
}
[PANEL,5] = (PRESET = VOL_LEVEL)
This code uses the timing keywords Set_Timer and Get_Timer to test the
amount of time between the Push and the Release of the Preset button. If the time
is greater than two secondsremember, Get_Timer returns time in increments
Unit 4: Levels
Using Levels
85
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 (on mainline):
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 levels
Touch Panel bar graphs have a unique feature: 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_Variable section. Underneath the Define_Connect_Level header is where all level connections are listed. Here is how Define_Connect_Level is used:
86
Using Levels
Unit 4: Levels
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 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 example programs for this unit can be found on the AXCESS distribution
diskette. The file STEP5.AXS uses the Create_Level and Send_Level keywords,
and STEP6.AXS uses the Define_Connect_Level keyword.
Unit 4: Levels
Using Levels
87
UNIT 5
ARRAYS,
STRINGS,
AND BUFFERS
14
Introduction
In the previous unit you developed a program that demonstrates the most common features of the AXCESS language. 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 first 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 16 buttons either store or recall a
preset, depending on whether the Store button is on or not.
Defining arrays
Array
A single variable that has
more than one storage
location.
In 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. First, the variable must be named by a valid identifier (see Chapter 4
for the rules concerning identifiers). Second, the number of storage locations in
the array must be indicated; a maximum of 255 locations can be specified.
For your new program, you want to store several preset levels for the volume
control card. 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 the index value (explained later) to pick the
preset you want to use. Here is your array declaration:
91
PRESETS
Figure 5-1
The array PRESETS has six
empty storage locations.
DEFINE_VARIABLE
PRESETS[6]
This declares a new variable, PRESETS, which is shown in Figure 5-1. The variable PRESETS is an array which can hold six distinct values, as defined by the
number 6 inside the brackets.
THE_LEVEL=PRESETS[3]
Index value
The number that tells AXCESS
which location in an array to
retrieve. This value must be
an integer from 1 to 255.
The number inside the brackets is called the index value. The index value is the
number that tells AXCESS which location in the array to retrieve, and it must be a
number from 1 to 255. This example assigns the value in the third location of
PRESETS to the variable THE_LEVEL. Retrieving a value from an array does not in
any way change the array. See Figure 5-2.
PRESETS
Figure 5-2
The value in PRESETS[3] is
assigned to the variable
THE_LEVEL.
A
PRESETS[3]
92
THE_LEVEL
PRESETS
Figure 5-3
The storage location
PRESETS[2] is assigned a
value of 6.
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, as shown in Figure 5-3. From
now on, anytime PRESETS[2] is referenced, its value is 6.
In the example program, pressing a Preset button either stores or recalls a preset. Examine the section of code that accomplishes this:
PUSH[SWP,3]
STORE = NOT STORE
[SWP,3] = STORE
NOTE
The keyword
Send_Command sends a
string to an AXCESS device,
which then interprets the
string as a command for an
action. See the AXCESS
Programming Guide for a list
of device-specific commands.
The first PUSH[SWP,3] is the Store button, which simply toggles the STORE
variable using the Not operator. (Remember, Not inverts the state of whatever
follows it.) The Push statement is immediately followed by a feedback statement
for the Store button. The next statement is an If statement which checks to see if
Push_Channel is greater than or equal to nine, and less than or equal to 14. In
other words, the statements inside the Ifs block are executed if one of the Preset
buttons are pressed. Inside the block is another If statement which uses the state
of the variable STORE to determine whether to assign the volume cards level to a
93
location in the PRESETS array, or to send a command to the volume card telling it
to go to a previously stored level. In order to place the variable VOLUME_LEVEL
into the array PRESETS at the correct location, 8 must be subtracted from
Push_Channel to find the index value.
Strings
String
A set of values grouped
together with single and/or
double quotes.
String literal
A set of characters (values
ranging from 32 to 127)
enclosed in single quotes.
Many 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.
Single quotes can only enclose values ranging from decimal 32 (the space character) to decimal 126 (the tilde character ~). These string literals are constant
values that are set at compile time. Once loaded into the master card these strings
cannot be changed, except when a new program is loaded into the Master Card.
Here is an example of assigning a string to an array:
PRESETS='FOUR'
When AXCESS processes this assignment, it places the F (ASCII value 70) in
location 1 of PRESETS, O (ASCII value 79) in location 2, and so on. See Figure 5-4.
String FOUR is placed in the array PRESETS. 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.
String expression
Single and double quotes are interpreted in two different ways by the AXCESS
system. 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
PRESETS
Figure 5-4
The string FOUR is assigned
to the array PRESETS.
94
PRESETS
10
PLAY
Figure 5-5
A string expression is
assigned to the array
PRESETS.
ASCII value (0 to 255), as well as variables, string literals, and arrays. The differ-
Run time
When the program is
executed in the Master Card.
ence between a string literal and the string expression is that the string expression is built at run time instead of compile time. As AXCESS 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:
Compile time
PRESETS="PLAY,5,,'NO',X"
NOTE
A string expression cannot
contain another string
expression; i.e. a set of
double quotes cannot
enclose another set of
double quotes.
Assuming that PLAY is a constant with the value of 1, and X is a variable with
the value of 10, the string expression is evaluated as a string with the following
values: 1,5,0,N,O,10. See Figure 5-5. 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.
Arrays as strings
There are two ways of referencing data in arrays within AXCESS programs: each
location as an individual value, or each array as a group of values. So far you have
seen how to access the individual locations. However, an entire array can be accessed as one unit. If you refer to an array without specifying an index value, the
contents of the entire array is referenced as a string. Consider the following lines:
DEFINE_VARIABLE
S1[1]
DEFINE_PROGRAM
S1='TEST ONE'
SEND_STRING CARD,'TEST TWO'
SEND_STRING CARD,S1
This small section of code will send two strings to the card named CARD: first
TEST TWO, then TEST ONE. Notice that there are no quotes around the variable
95
DEFINE_START
PRESETS = ,3,9,128,191,255
String lengths
String length
An internal value set for
arrays by string assignment
operations.
Every array declared in the Define_Variable section has a string length value
associated with it. The string length of an array is an internal value set for arrays
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
PRESETS
PRESETS
PRESETS
=
=
=
=
'FOUR'
'ONE'
"12,5,'123'"
"PLAY,5,,'NO',X"
(*
(*
(*
(*
Y
Y
Y
Y
=
=
=
=
4
3
5
6
*)
*)
*)
*)
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 locations.
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
96
PRESETS[1]
PRESETS[2]
PRESETS[3]
PRESETS[4]
=
=
=
=
'W'
'O'
'R'
'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)
"5,PRESETS,'GO'"
As AXCESS constructs a string from this string expression, the number of characters from the array PRESETS it will add will be equal to PRESETS string length
value. 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 AXCESS. 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:
97
PRESETS[1]
PRESETS[2]
PRESETS[4]
SAVE_PRESETS
=
=
=
=
5
6
'A'
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.
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 card named RS232, you
would write the following line:
SEND_STRING RS232,PRESETS
String literals and string expression can also be sent using Send_String. Here
are some examples:
98
The first example sends the entire set of characters enclosed in the single
quotes, from left to right, to the card 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 codes
As you have learned, a string 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) *)
}
or
IF(TEMP[3] = 82)
{
(* statement(s) *)
}
or
IF(TEMP[3] = $52)
{
(* statement(s) *)
}
99
Integer arrays
Integer array
An array where each location
can hold a value ranging from
zero to 65,535. Note that an
integer array will take up
twice as much AXCESS
memory than a normal array
of the same storage capacity
would.
NOTE
If your array is only going to
hold alphanumeric values, do
not worry about making it an
integer array.
100
So far, in all of the arrays you have seen, the range of values in each location is
zero to 255. Recall that the range of values in a single variable is zero to 65,535,
and when a value greater than 255 is assigned to an array location, the number
is truncated above 255. For instance, if the number 500 is assigned to a location
in an 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.)
So what 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 normal array, except that each location can hold values from zero to
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_VARIABLE
INTEGER PRESETS[6]
This declares an integer array with six locations; each location can hold values
from zero to 65,535.
There are certain limitations of integer arrays. If an integer array is assigned
to a normal array, all values are truncated above 255. (See the earlier discussion
on truncating values.) 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.
15
Grouping data
The ability to group data into cohesive units (arrays) is one of the more powerful
features of the AXCESS language. 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 keywords
There are five conversion keywords available:
Itoa
Itohex
Atoi
Upper_String
Lower_String
The first three keywords serve to convert numberseither as a constant, in a
variable, or explicitly definedinto its string representation, and vice versa. The
last two convert a string into all uppercase or all lowercase.
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_CONSTANT
CONST = 456
DEFINE_VARIABLE
STR[5]
VAR
DEFINE_PROGRAM
VAR = 789
STR = ITOA(123)
STR = ITOA(CONST)
STR = ITOA(VAR)
(* STR = 123 *)
(* STR = 456 *)
(* STR = 789 *)
101
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 = ITOHEX(CONST)
STR = ITOHEX(VAR)
(* STR = 76 *)
(* STR = 1C8 *)
(* STR = 315 *)
Notice that there are no dollar signs in the results. This is because the dollar
sign indicates a numerical value expressed in hexadecimal, and is only used
when telling AXCESS that a number is hexadecimal.
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_CONSTANT
STR1 = 456
STR2 = YES789GO19
DEFINE_PROGRAM
NUM = ATOI('123')
NUM = ATOI(STR1)
NUM = ATOI(STR2)
NOTE
The three keywords Itoa,
Itohex, and Atoi automatically
set the length value of the
resulting string.
102
(* NUM = 123 *)
(* NUM = 456 *)
(* 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.
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:
After execution of this line, the array STR will contain the first 3 characters of
the array PRESETS. If PRESETS 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:
103
This line tells AXCESS: 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.
For example, suppose you dont know the exact contents of the PRESETS array, but you want to find out if it contains the string LO. Assume that PRESETS
contains HELLO, and the following line is executed.
X = FIND_STRING (PRESETS,'LO',1)
When AXCESS executes this statement, it will search the array PRESETS from
the beginning, looking for the string LO. If AXCESS finds the substring, as in this
case it will, it returns the starting position of the substring in the PRESETS array:
in this case, 4. The third parameter (in this example, 1) tells AXCESS where in the
string to start the search.
Removing strings
The Remove_String keyword works much like the Find_String keyword. However, when AXCESS 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_VARIABLE
SOURCE[2]
DEST[2]
DEFINE_PROGRAM
SOURCE = THIS IS A TEST
DEST
= REMOVE_STRING (SOURCE,IS,1)
104
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. 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.
In Find_String, each of the first two parameters can be a string literal, string
expression, or array. However, in the case of Remove_String, having anything
except an array as the first parameter makes no sense because AXCESS cannot
remove part of a string literal or string expression, only an array variable. This is
because string literals are constant values and string expressions may contain
constant values. Once loaded into the Master Card, constant values cannot be
changed. Look at these examples:
STR = REMOVE_STRING(PRESETS,12,1)
STR = REMOVE_STRING(2,HELLO,1,13,HELLO,1)
(* OK *)
(* NO *)
DEFINE_PROGRAM
Identifier_1 = 'Fred'
Identifier_2 = 'FRED'
if (IDENTIFIER_1 = IDENTIFIER_2)
{
(* This will not be true because 'Fred' and 'FRED'
are not the same. *)
}
105
NOTE
When programming, you
may use whatever capitalizing scheme you wish. At
AMX, as a standard we
capitalize all keywords and
identifiers in the program.
Notice that the string literals FRED and Fred are not the same. However, in
the case of identifiers IDENTIFIER_1 and IDENTIFIER_2, AXCESS 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 AXCESS compiler.
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 ASCII 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:
ABC2 = UPPER_STRING(ABC)
The If statement can now compare ABC2 against YES, providing that the If
statement reads IF (ABC2 = 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.
106
16
Using Buffers
Receiving strings
Buffer
An array variable that is
associated with a particular
device for the purpose of
storing information sent by
the device.
Receiving strings requires several more steps than sending strings. To be able to
receive strings from a device, you must first create a buffer for that device. A
buffer is an array variable that is associated with a particular device for the purpose of storing information received from the device.
Creating buffers
To create a buffer, use the Create_Buffer keyword. This keyword can only appear in the Define_Start section of your program, and it has the following syntax:
IMPORTANT
The Create_Buffer keyword directs AXCESS to place any data received from the
specified device into the specified array. When AXCESS places the byte into the
Figure 5-6
When data comes in from a
device, it goes into the spot
determined by the length
value of the array. Here, the
length value was 3. So the
Y is put into location 4, and
the length value is
incremented to 4.
BUFFER
10
Y
from device
Using Buffers
107
array, it increments the length value for the array and then places the byte into
the array at the current end of the array. See Figure 5-6 for a pictorial explanation.
Even though the array is acting as a buffer, it is still an array and can be
treated as one. You can still access the individual locations, send it to a device,
assign it to other arrays, assign other arrays to it, as well as use the array manipulation keywords discussed in the previous chapter.
Storing characters
NOTE
A buffer is said to be full
when its length value is equal
to its storage capacity.
When a device sends string information to the Master Card, the Master Card
places the incoming information into the buffer created for that device, and updates the buffers length value. (Remember, a buffer is an array.) These actions
are executed after the Master Card has passed through mainline. Since all data
going in and out of these devices is serial (that is, one byte at a time), each byte
is handled one at a time.
If the buffer is full when a character needs to be inserted into it, AXCESS drops
the first character, shifting the contents of the buffer left in order to insert the new
character at the end of the buffer. See Figure 5-7 for a diagram showing this action.
Retrieving characters
This 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.
from device
Figure 5-7
BUFFER
C
dropped
108
Using Buffers
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:
The parameter passed to Get_Buffer_Char must be an array, but does not need
to be a buffer. (Remember: All buffers are arrays, but not all arrays are buffers.)
The statement will operate identically in either case. The result must be a simple
variable (not an array), because one and only one character will ever be returned.
In these examples, you will create an array called BUFR with a capacity of ten
characters. Then you will make it a buffer associated with a device named RS232.
DEFINE_VARIABLE
BUFR[1]
CHAR
DEFINE_START
CREATE_BUFFER RS232,BUFR
Now all string data sent to the Master Card from the device RS232 will go
into the array BUFR, as described earlier. Now, suppose you want to get the
data out of the buffer as soon as it enters. This is usually a two-step process.
Here is an example:
IF (LENGTH_STRING (BUFR))
CHAR = GET_BUFFER_CHAR (BUFR)
These two lines of code are actually one statement: an If statement. The condition of the If is the result of the Length_String keyword; if there are not any
characters in the buffer (length value of BUFR is zero), then AXCESS will skip the
second part of the statement. The second part, which will be executed if there
are one or more characters in BUFR, tells AXCESS to get the first character in BUFR
place it into the variable CHAR. This process is diagrammed in Figure 5-8.
Using Buffers
109
BUFR
LENGTH_STRING = 6
GET_BUFFER_CHAR (BUFR)
Figure 5-8
Getting the next character
out of a buffer with
Get_Buffer_Char.
LENGTH_STRING = 5
CHAR
Clearing a buffer
AXCESS provides a single keyword which clears a buffer: Clear_Buffer. Here is
how it is used:
CLEAR_BUFFER BUFR
BUZZWORD
A null string is simply an
empty set of single quotes,
which represents a string
literal with no content and a
length value of zero.
110
Using Buffers
This keyword effectively sets the length of the buffer to zero, so that subsequent Get_Buffer_Char statements will not return anything. Using Clear_Buffer
is preferable to other methods, such as assigning a null string to the buffer, or
using Set_Length_String. The Clear_Buffer keyword actually compiles into
smaller code and executes faster than the other methods, plus it is clearer to the
reader as to what the programmer is trying to accomplish.
17
Two-Dimensional Arrays
Powerful grouping
In the previous two chapters, you learned how to group data into arrays and
how to manipulate those arrays as single units. In this chapter, you will see how
to group multiple arrays together into one two-dimensional array. Using twodimensional arrays provides even greater flexibility and power for the more
complex applications.
Two-dimensional
array
A storage place holding
multiple one-dimensional
arrays.
To understand the structure of the two-dimensional array you must refer back
to the basic single variable. A variable holds one and only one value at a time.
Using arrays, you can create a variable that can hold many values, and you reference the value you want with an index value. In this way, you are able to perform many programming feats such as storing several related values and
accessing a particular one.
The two-dimensional array expands on the one-dimensional array in the same
way that the one-dimensional array expands on the simple variable: it holds
multiple one-dimensional arrays which can be referenced with an index value.
Heres how you declare a two-dimensional array:
DEFINE_VARIABLE
NAMES[1][3]
Figure 5-9
NAMES
Single location is
NAMES[3][6]
Two-Dimensional Arrays
111
NOTE
A two-dimensional array can
be declared with the Integer
keyword, just like a onedimensional array can. This
allows values in the range
zero to 65,535 to be
assigned to locations within
the two-dimensional array.
Notice how this declaration differs from the one-dimensional array. Instead of
a single storage capacity value, there are two. Heres how to interpret this variable declaration: NAMES is a two-dimensional array that can hold 10 one-dimensional arrays, each with a storage capacity of 30 characters. The total storage
capacity of NAMES is 10 characters by 30 characters, for 300 characters total. The
variable NAMES might be used to store up to 10 names, each with a maximum
length of 30 characters. Figure 5-9 depicts the structure of the array NAMES.
Storing values
The method of storing values into a two-dimensional array is basically the same
as that of a one-dimensional array. You can assign values to individual locations; you can assign one-dimensional arrays, string literals, and string expressions to one of the one-dimensional arrays inside the two-dimensional array;
and you can assign entire two-dimensional arrays to other two-dimensional arrays. Here is a small program as an example:
DEFINE_VARIABLE
NAMES[1][3]
PEOPLE[8][2]
ONE_NAME[3]
A_VALUE
(*
(*
(*
(*
two-dimensional array *)
another two-dimensional array *)
one-dimensional array *)
single-value variable *)
DEFINE_PROGRAM
A_VALUE = 1
ONE_NAME = 'EMMITT SMITH'
NAMES[1][1] = 6
NAMES[1][2] = A_VALUE
NAMES[2] = 'TROY AIKMAN'
NAMES[3] = "1,2,ONE_NAME,3"
(*
(*
(*
(*
(*
(*
1
2
3
4
5
6
*)
*)
*)
*)
*)
*)
Figure 5-10 depicts what the two-dimensional array NAMES will look like after
this code is executed.
Each row in the two-dimensional array has a length value just like a one-dimensional array. When a string literal or string expression is assigned to a row
of a two-dimensional array (see statements 5 and 6 in the above example), that
row has its length value set in the same manner as a one-dimensional array
does. The Length_String and Set_Length_String functions operate on rows in
two-dimensional arrays in the same way as whole one-dimensional arrays. Assuming that the above example has executed, here is what the Length_String
function returns on the first three rows of NAMES:
112
Two-Dimensional Arrays
NAMES
10
Figure 5-10
The two-dimensional array
NAMES after the assign-
ments.
X = LENGTH_STRING (NAMES[1])
(* X will contain
*)
X = LENGTH_STRING (NAMES[2])
(* X will contain 11 *)
X = LENGTH_STRING (NAMES[3])
(* X will contain 15 *)
Retrieving values
Retrieving values from a two-dimensional array is done in the same manner as a
one-dimensional array. Recall that there are two ways of referencing data in a
one-dimensional array: referencing a single value inside the array, and referencing the entire array. When using a two-dimensional array, there are three ways
of referencing the contents:
BUZZWORD
VALUE = NAMES[3][6]
Two-Dimensional Arrays
113
This line of code takes whatever value is in the sixth location of the third row
in the two-dimensional array NAMES, and assigns it to the variable VALUE. In the
context of the previous examples, VALUE will now contain an E.
Retrieving a whole row from a two-dimensional array is done in the same
way, except only the first index value is used. The index value will indicate the
row that is to be retrieved, and the length value for that row determines how
many locations from the row are actually retrieved. For instance:
ONE_NAME = NAMES[2]
After this line is executed, the array ONE_NAME will contain the string TROY
AIKMAN, and its length value will be 11. If you were to try to retrieve the entire
first row, nothing would be returned because its length value is zero.
The third method of accessing a two-dimensional array is to assign it to another two-dimensional array:
PEOPLE = NAMES
This will copy the entire contents of NAMES into PEOPLE, regardless of the individual rows length values. Making an assignment like this copies the entire contents of the two dimensional array, including the rows length values.
PEOPLE[2] will contain TROY AIKMAN and have a length value of 11, just like
NAMES[2].
If you go back to the original example, however, you will notice that the twodimensional array PEOPLE is defined with a size 8 by 20, whereas NAMES is 10
by 30. When AXCESS performs a copy from a two-dimensional array into a
smaller one, any information that falls outside the ranges of the smaller array
is not copied.
114
Two-Dimensional Arrays
UNIT 6
ADVANCED
AXCESS
PROGRAMMING
18
Using Subroutines
Introduction
By now you should have a firm grasp of the basics of AXCESS programming.
Now you will delve into some more complex topics such as using subroutines,
creating local variables, and passing parameter. With these tools, you will be
able to tame complex systems with a relatively small amount of code.
Subroutine
Subroutines
There is a way to break the program into smaller, more manageable parts called
subroutines. A subroutine is a section of code that stands alone and can be
called from anywhere else in the program.
You may create subroutines for a variety of reasons. The most common usage
of subroutines is to execute the same group of instructions from different places
in the program. Using a subroutine to do this means that you dont have to re-type
those instructions over and over in the programyou can just call the subroutine.
Defining a subroutine
In AXCESS, subroutines are created using the Define_Call statement. Enclosed in
single quotes, the subroutine name follows the Define_Call keyword. There are
certain restrictions for these subroutine names:
They cannot be previously defined contents or variables.
They cannot be names that have already been assigned to buffers or Waits.
They are case-sensitive. Test and TEST are not the same.
Subroutines must be defined before they can be used. For this reason,
Define_Calls are usually found right before the Define_Start section of the program. For example:
Using Subroutines
117
DEFINE_START
(* startup code goes here *)
DEFINE_PROGRAM
(* the main program starts here *)
Spaces in the subroutine name are allowed since it is a string literal. Notice
that the subroutines code is enclosed in braces. No matter how long the subroutine is, it must be in this format.
When AXCESS executes the Call, program execution jumps to the first line
inside the braces of the Define_Call. The subroutine is executed only once, and
then AXCESS returns to the statement directly following the Call statement.
Sample program
Now you will look at a complete example program using a subroutine. Here are
the basic requirements for the program:
The devices used are four infrared/serial cards and an AMX TX Series
wireless (radio frequency) remote controller. The device numbers are 1, 2, 3,
4, and 128, respectively. The infrared/serial cards will transmit infrared
code to three different VCRs and a video projector.
The TX transmitter will have three buttons. Here are the functions to be
associated with each button:
Button 1: Projector to input 1, stop all VCRs, wait 5 seconds, play VCR 1.
This code listing is from
STEP8.AXS on the AXCESS
distribution diskette.
118
Using Subroutines
Button 2: Projector to input 2, stop all VCRs, wait 5 seconds, play VCR 2.
Button 3: Projector to input 3, stop all VCRs, wait 5 seconds, play VCR 3.
DEFINE_DEVICE
VCR1 = 1
VCR2 = 2
VCR3 = 3
VPROJ = 4
RADIO = 128
DEFINE_CONSTANT
(* COMMON TRANSPORT CONSTANTS *)
PLAY
= 1
STOP
= 2
PAUSE
= 3
FFWD
= 4
REWIND
= 5
DEFINE_VARIABLE
WHICH_VCR
CALL_ACTIVE
DEFINE_CALL DO SWITCH
{
CALL_ACTIVE = 1
PULSE [VPROJ,WHICH_VCR+1]
PULSE [VCR1,STOP]
PULSE [VCR2,STOP]
PULSE [VCR3,STOP]
WAIT 5 PULSE [WHICH_VCR,PLAY]
WAIT 6 CALL_ACTIVE =
}
DEFINE_START
CALL_ACTIVE =
DEFINE_PROGRAM
PUSH[PANEL,1]
{
IF (NOT CALL_ACTIVE)
{
WHICH_VCR = VCR1
CALL DO SWITCH
}
}
PUSH[PANEL,2]
{
IF (NOT CALL_ACTIVE)
{
WHICH_VCR = VCR2
CALL DO SWITCH
}
}
Using Subroutines
119
PUSH[PANEL,3]
{
IF (NOT CALL_ACTIVE)
{
WHICH_VCR = VCR3
CALL DO SWITCH
}
}
DEFINE_DEVICE
VCR1 = 1
VCR2 = 2
VCR3 = 3
VPROJ = 4
RADIO = 128
DEFINE_CONSTANT
(* COMMON TRANSPORT CONSTANTS *)
PLAY
= 1
STOP
= 2
PAUSE = 3
FFWD
= 4
REWIND = 5
This section defines the common locations in the IR cards for the transport
functions PLAY through REWIND.
DEFINE_VARIABLE
WHICH_VCR
CALL_ACTIVE
DEFINE_START
CALL_ACTIVE =
120
Using Subroutines
When the system is turned on or reset, this will initialize CALL_ACTIVE to zero.
DEFINE_CALL DO SWITCH
{
This begins the subroutine. Notice that the sequence must begin with a brace
no matter how long the subroutine is.
CALL_ACTIVE = 1
BUZZWORD
A flag is a variable that is
used to store an on or off
state.
The first statement of the subroutine turns CALL_ACTIVE on. In this program
CALL_ACTIVE acts as a flag to let the rest of the program know that the Waits
inside the subroutine are still pending, and the subroutine is not to be re-activated until the Waits are finished.
PULSE [VPROJ,WHICH_VCR+1]
PULSE [VCR1,STOP]
PULSE [VCR2,STOP]
PULSE [VCR3,STOP]
WAIT 5 PULSE [WHICH_VCR,PLAY]
This section is the heart of the Define_Call. The first statement Pulses the
function on the video projectors controller card corresponding to the input desired on the projector. A little trick was used here: since the functions on IR cards
for video projectors have the switcher inputs located at 1120, you can simply
add 10 to the desired input number to obtain the needed IR function number. For
instance, if WHICH_VCR contains 2meaning you selected VCR number 2 and
input number 2 on the projectorthe first Pulse statement will activate function 12, which (on video projector cards) is usually the input 2 Select function.
The next three Pulses stop all three VCRs, and then a Wait is started with a
time of five seconds. When this Wait is over, AXCESS will Pulse the Play function
on the VCR whose device number equals WHICH_VCR.
WAIT 6 CALL_ACTIVE =
}
Using Subroutines
121
BUZZWORD
When flags are used to
disable events in this way, it
is called locking or locking
out. When the flag is turned
off, the event or code is
unlocked.
Six seconds after the subroutine is called, CALL_ACTIVE is reset to zero. This
will create a one half-second delay between the end of the Play Pulse and the
unlocking of the subroutine. Thus, six seconds after being called, the subroutine can be safely re-activated again.
DEFINE_PROGRAM
PUSH[PANEL,1]
{
IF (NOT CALL_ACTIVE)
{
WHICH_VCR = 1
CALL DO SWITCH
}
}
The main program starts here. The code inside each Push first checks to see if
the subroutine is busy by checking CALL_ACTIVE with an If statement. If the flag
is not on, the code sets WHICH_VCR to the desired VCR number and projector input number, and then calls DO SWITCH. This is repeated for each button.
You may realize that the value assigned to the variable WHICH_VCR in each
Push is equivalent to the channel in the Push statement. Since this is true, the
three button presses could be combined into one section like this:
DEFINE_PROGRAM
PUSH[PANEL,1]
PUSH[PANEL,2]
PUSH[PANEL,3]
{
IF (NOT CALL_ACTIVE)
{
WHICH_VCR = PUSH_CHANNEL
CALL DO SWITCH
}
}
This works great for control panels with buttons positioned sequentially, but
not so well if the buttons channel codes are not sequential. Since you will build
on this program in the upcoming chapters, leave the section as three separate
Pushes.
122
Using Subroutines
19
Local variables
Local variable
A variable declared in a
subroutine, and whose
scope is limited to that
subroutine.
Global variable
Any variable defined in the
Define_Variable section of
the program. The scope of
these variables extends
throughout the entire
program.
Scope
The part of the program
where the variable can be
accessed. A variable has
global scope if the entire
program has access to it; a
variable has local scope if
only a section of the program
has access to it.
NOTE
A global variable is said to be
hidden if a local variable of
the same name is in scope.
The first of these two features is the local variable. A local variable is a variable
which is declared inside a Define_Call and can only be used inside that same
Define_Call. Variables declared in the main Define_Variable section are called
global variables. The words local and global refer to a variables scope, which
is the part of the program that can access the variable. Global variables have
global scope; that is, the entire program has access to them. A local variable has
local scope, and can only be accessed inside the Define_Call in which it is declared. Here is an example of a local variable declaration:
This section of code defines the subroutine TEST CALL. It then declares two local
variables, LOC_VAR (a simple variable) and LOC_ARRAY (an array with a storage
capacity of 10.) Local variables are defined after the Define_Call and before the
first open brace, with the keyword Local_Var preceding the block of local variables defined. Nowhere else in the entire program can any code access the two
variables LOC_VAR and LOC_ARRAY; they are local to the subroutine TEST CALL.
A local variable can have the same name as a local variable in another subroutine. If another subroutine declares a local variable LOC_VAR, that subroutine will use its LOC_VAR and TEST CALL will use its own LOC_VAR. A local
variable can also have the same name as a global variable. If this happens, the
local variable takes precedence in its scope; the global variable is hidden. For
123
instance, if in the previous example there was a global variable LOC_VAR, the
reference in the subroutine still refers to the local variable. In this case the global LOC_VAR is hidden from the subroutine.
Local variables are best used in cases where a subroutine needs to use a variable, but no other piece of code needs it. Such variables are usually temporary
flags, loop counters, and other variables a subroutine may need to do its work.
A well-organized program may even have more local variables than global variables, because the main work of the program is handled mostly by subroutines
rather than the main program.
Parameters
Several AXCESS keywords and functions use parameters, such as Atoi and
Mid_String. Your Define_Call subroutines can also use parameters. Parameters
are variables defined as part of the Define_Call declaration that can receive values from and pass back values to the Call statement that called the subroutine.
Here is a subroutine declaration using parameters:
This subroutine is defined as having two parameters, INPUT and OUTPUT (enclosed in parentheses), which are essentially local variables of the subroutine.
These variables, however, have their initial values set by the parameters in the
Call statement which called the routine. Here is a Call to this subroutine:
This calls the subroutine DO SWITCH, and assigns the value 3 to INPUT and 7
to OUTPUT. The subroutine uses a string expression to construct the string I3O7
and then sends the string to the card named SWITCHER. This shows the power
of using parameters. Later in the program, the same subroutine can be used
with different parameters to produce different strings. Here are some examples:
124
(* sends I1O2 *)
(* sends I2O12 *)
(* sends I1O2 *)
BUZZWORD
The caller refers to the Call
statement that called the
subroutine.
When the subroutine SQUARE is called with a variable as a parameter (in this
case X), a series of events occurs.
The value of the variable (in this case, 5) is assigned to NUMBER.
The subroutine takes the parameter, multiplies it by itself (thus squaring it)
and assigns the result back to itself.
AXCESS then re-assigns NUMBER back to the variable X, so that upon return
from the subroutine, X will contain its previous value squared.
If, however, a constant value is passed to the routine, a re-assignment cannot
be made. For example:
CALL SQUARE ( 5 )
This will assign the value 5 to the parameter variable NUMBER in the subroutine, and NUMBER will be squared. However, AXCESS cannot take the value in
NUMBER and re-assign it to the constant value 5. Calling a routine in which a parameter is expected to return some sort of result should not be called with a constant value as that parameter. If you want to use a constant value as a parameter
to this subroutine and still get a new value returned, rewrite the Define_Call to
have two parameters:
125
DEFINE_VARIABLE
GLOBAL
DEFINE_CALL BUGGY (PARAM)
{
PARAM = 1
GLOBAL = 2
}
DEFINE_PROGRAM
GLOBAL = 5
CALL BUGGY (GLOBAL)
(* What will GLOBAL contain here? *)
You might expect GLOBAL to contain 20 when AXCESS reaches the comment.
However, this is not the case. In the subroutine BUGGY, after GLOBAL is set to 20,
AXCESS re-assigns the value in PARAM to the variable in the Call statement which
called BUGGYin this case GLOBAL. The parameter variable PARAM contains the
value 10 at the end of the subroutine, and this value is re-assigned to the variable in the Call statement: GLOBAL. In the end, GLOBAL will contain the value 10
at the comment.
126
20
Include files
Include file
A DOS file which is included
in the compiling process
without having to reside in
the computers memory.
Most of the time, your program will reside in a single file. AXCESS program files
are saved with a DOS extension of AXS. When you compile your program,
AXCESS compiles it in the computers memory, and when you save your program, AXCESS saves it to disk using this extension.
Sometimes, however, a program may grow to be too large to fit into your
computers memory all at once. In such a case, it is possible to break the program up into multiple files. This is done by taking portions of your program and
putting them into one or more include files. An include file is a DOS file which is
included in the compiling process without having to reside in the computers
memory. Include files always have the DOS extension AXI.
To include a file in a program, use the keyword Include, followed by the
filename in single quotes. Here is an example:
DEFINE_PROGRAM
(* Program statements can go here *)
INCLUDE TEST.AXI
(* More program statements can go here *)
When the compiler reaches the Include statement, it jumps into the specified file and continues compiling. When it has reached the end of the file, it
comes back to the line following the Include statement and continues compiling.
See Figure 6-1 for a pictorial explanation.
127
#INCLUDE TEST.AXI
Figure 6-1
Compilation flow using an
include file.
The code compiled in the include file is compiled just as if it were in the main
program where the Include statement is located. The Include statement can appear anywhere in your program, since it is actually a statement to the compiler
and not the AXCESS control system. What you decide to put into include files is
up to you. Here are several suggestions on their use in large programs:
Place each definition section in its own include file
Group sections of the main program into include files
Place all subroutines into an include file
Place routines that you want to share between multiple programs into an
include file
Place code you wish to re-use in other systems into include files
This by no means is a comprehensive nor mandatory list of how to organize
your programs, but simply some suggestions to get you started toward bigger
and better system programming.
Include files are loaded and edited using the AXCESS editor much like normal
program files (see Unit 1). Like program files, the AXCESS name (not the DOS
name) of the include file is stored on the first line of the file as a Program_Name
declaration.
128
Library file
A special file containing
AXCESS program code.
These files are used only for
System_Calls.
Using include files makes it very easy to share already-written code between
multiple programs. For instance, suppose you had created a subroutine to
handle a certain audio/video switcher, and you saved the subroutine into an
include file. When you need to use the subroutine in another program, you simply include the file into your program and bingo, you have a pre-written piece
of code ready for use.
This is where library files come in. Library files are actually special types of
include files which have the DOS extension LIB. The difference between these
and include files is that these files must contain a Define_Call subroutine having
the same name as the Program_Name on the first line of the library file. This
Define_Call can then be called from within a program using the System_Call
keyword. Here is a small example library file listing:
PROGRAM_NAME = SQUARE
DEFINE_CALL SQUARE (NUMBER)
{
NUMBER = NUMBER * NUMBER
}
This is the entire contents of a library file. Now if you have a variable X which
you want to square within a program, use the following line:
PROGRAM_NAME = SQUARE
When AXCESS finds this file, it is compiled. Since the library file contains a
Define_Call with the same name as the Program_Name in the file, the
System_Call to SQUARE actually calls the Define_Call SQUARE in this library
file. See Figure 6-2.
129
Library file
PROGRAM_NAME = SQUARE
DEFINE_CALL SQUARE (NUMBER)
{
NUMBER = NUMBER * NUMBER
}
Figure 6-2
The compilation order of a
library file.
When using System_Calls, you do not have to implicitly include the file with
the subroutine you wish to use because AXCESS automatically does this for you.
In essence, the System_Call is almost like the Include and Call keywords
bundled into one keyword.
Factory System_Calls
BUZZWORD
The look and feel of
something refers to how it
interacts with the user. In the
case of control panels, this
refers to how a device reacts
when certain buttons are
pressed, and what kind of
feedback the user receives.
This is also called the user
interface.
130
AMX has written a number of System_Calls to handle many of the most common
programming requirements in AXCESS systems. These library files are included
on the AXCESS distribution diskette. The System_Calls are divided into several
categories including VCRs, switchers, laser discs, and others. Factory System_
Calls follow a standard naming convention, and the System_Calls in each group
take the same parameters. See Figure 6-3 for descriptions of these two standards.
The main goal of these System_Calls is to maintain a consistent look and
feel for the control panels, regardless of how the deck behaves from its own
remote control. For instance, when some VCRs are in the pause mode, pressing
Pause again will cause the deck to play, whereas on other VCRs, pressing Pause
again does nothing. However, when using a VCR System_Call, pressing Pause
on the control panel while the deck is in pause mode will always cause the deck
to play. This is because the different VCR System_Calls were written to take into
Factory System_Calls
Device type
System_Call*
Parameters required
VCR
VCR
Cassette deck
CAS
LDP
CDP
Slide projector
SLD
Switcher
SWT
Other
Varies
Varies
Figure 6-3
A list of pre-written
System_Calls for your use.
* There is a complete set of System_Calls for each type of device. Following the first three
letters of the System_Call name is a number. For instance: System_Call VCR3.
DEFINE_VARIABLE
NUM1
NUM2
DEFINE_PROGRAM
NUM1 = 5
NUM2 = 6
SYSTEM_CALL SQUARE (NUM1)
SYSTEM_CALL SQUARE (NUM2)
131
This code generates two calls to the subroutine SQUARE in the library file, but
it only includes and compiles the library file once. The two System_Calls call the
same routine. This is fine for most System_Calls, but there are occasions where
this could cause problems.
To illustrate this, make a new library file which has Wait statements in its subroutine. Here is a listing:
This code compiles and works fine. But what happens when you add another
System_Call to the program?
Only one Define_Call SEND is compiled, and both of these lines call the same
subroutine. The first call sets the routines STR1, STR2, and CARD parameter variables, sends the string AMX to device 3, and starts the named Wait. The next
System_Call resets the parameter variables to all new values, and sends the
string GOOD to card 5. Since the Wait is already in the wait list, however, it is
not restarted. Thus when the Wait comes due, it will use the latest values stored
in the parameter variables CARD and STR2. In this case, CARD will still be 5 and
STR2 will contain the string TIMES, so TIMES is sent to device number 5.
132
Notice that the string AXCESS is never sent to card 3. This is because the
STR2 parameter variable in the subroutine is overwritten by the second
Instance number
A number enclosed in
brackets after the System_
Call keyword to denote
which copy of the compiled
library file to call.
System_Call before the Wait comes due. This is the problem with using Waits
in System_Call subroutines.
There is a way to get around this, however. By using an instance number, you
can force the compiler to compile two separate copies of the subroutine. Here is
an example of the same System_Calls using instance numbers:
The number in the brackets is the instance number. By using this number, you
tell the compiler to compile multiple copies of the routine, and have the different
System_Calls each call a separate copy. The compiler accomplishes this by using
the instance number to modify the actual name of the Define_Call before compiling it. When compiling a library file called with an instance number, AXCESS converts the number to ASCII and appends it to the Define_Call name (see Figure 6-4.)
Figure 6-4
Library file
DEFINE_CALL SEND1
133
Name mangling
The process where the name
of the Define_Call and any
Waits and Wait_Untils in a
library file are changed so
that multiple separate copies
can be compiled into a
program.
SYSTEM_CALL
SYSTEM_CALL
SYSTEM_CALL
SYSTEM_CALL
[1]
[2]
[2]
[3]
SEND
SEND
SEND
SEND
(HOW,FEE,3)
(DO,FI,3)
(YOU,FO,3)
(DO,FUM,3)
(*
(*
(*
(*
calls
calls
calls
calls
copy
copy
copy
copy
1
2
2
3
*)
*)
*)
*)
Suppose there is a Define_Call SEND1 in your program, and you attempt the
following line of code:
After name mangling, this generates a call to SEND1, which will actually call
the subroutine SEND1 in the program file, not the library file. In fact, since the
call to SEND1 is resolved (that is, a subroutine SEND1 was found) the library file is
never compiled. However, if the instance number was 2, the SEND1 subroutine
would not be called, and the SEND library file would be compiled with the
names mangled using the character 2.
134
GLOSSARY
AND INDEX
ADVANCED
AXCESS
PROGRAMMING
Glossary
Analog An input or output that can have many values.
Array A single variable that has more than one storage location.
ASCII A coding scheme that assigns numeric values to letters, numbers, and
other characters.
AXlink The AXCESS communications bus.
Bar graph A visual representation of a level.
Baud rate Speed of data transmission; measured in bits per second (bps).
Bitwise operator A keyword or symbol that performs a bit-by-bit operation
between two items.
Block Highlighted section of text in the AXCESS text editor.
Block file File saved on disk using the Write Block to Disk command (Alt-W);
it has the DOS extension AXB.
Boolean expression A conditional statement used to tell AXCESS whether or
not to execute a particular function or functions in the program. This is also
known as a relational expression.
Boolean operator A keyword or symbol that creates a relation between two
items.
Buffer An array variable that is associated with a particular device for the purpose of storing information sent by the device.
Caller The Call statement that called a subroutine.
CardFrame Housing for the AXCESS control cards.
Case sensitive Uppercase and lowercase values are not evaluated the same;
for example, CASS is not the same as cass.
Cell One particular location in a two-dimensional array.
Channel The basic input/output unit. Channels correspond to actual control
functions such as relays and infrared signals. Each AXCESS device has 255
channels, although all are not always used.
Glossary
137
Comment A description or remark within an AXCESS program that is not considered part of the actual program; it is ignored by the compiler.
Communications port Port through which serial data is transferred.
Compilation error An error that occurs at compile time.
Compile time When the program is compiled.
Compound statement A group of several statements enclosed by a set of
braces.
Constant An identifier whose value remains unchanged throughout the entire
program.
Decimal Base 10 numbering system.
Deck Any piece of equipment controlled by an AXCESS device.
Default statement A statement (or compound statement) that is executed if
none of the conditions being tested is true.
Definition section One of the various divisions of the AXCESS program. These
sections are Define_Device, Define_Constant, Define_Variable, Define_
Latching, Define_Mutually_Exclusive, Define_Start, and Define_Program.
Device A component that can be connected to AXlink.
Device-channel A reference to a specific channel in the AXCESS system in the
format [device,channel].
Device number A unique number from 1 to 255 designated to each device
connected to AXCESS via AXlink.
Digital An input or output that can have only two values: on or off.
DIP switch A switch on a circuit board that can be turned on or off to determine various settings.
Direct assignment Generating an output change by assigning a value to a
device-channel.
Downloading The sending of data from a computer to a device (such as a
Master Card).
Dumb terminal A serial communications device. Whatever is typed goes out
the communications port, and whatever comes in the port is displayed on the
screen.
EPROM Acronym for erasable programmable read-only memory.
Glossary
138
Glossary
139
Library file A special file containing AXCESS program code. These files are used
only for System_Calls.
Local variable A variable declared in a subroutine, and whose scope is limited
to that subroutine.
Locking When flags are used to disable events.
Logic error An error in the actual design of the program.
Look and feel How something interacts with the user. This is also called the
user interface.
Loop A block of code that is continuously executed until a condition is satisfied.
Master Card The AXCESS card that controls the activities of the AXCESS system.
Mainline The section of the program that actually is executed continuously by
the Master Card. This is also known as the Define_Program section.
Modem Communications device used to transfer serial data through phone
lines.
Momentary A defined behavior of status that causes its output channel to be
activated as long as the corresponding button is pressed.
Momentary mutually exclusive A characteristic of status that allows only one
channel of a pre-defined set to be on at a time. The output channel is activated
as long as the corresponding button is pressed.
Mutually exclusive latching A characteristic of status that allows only one
channel of a pre-defined set to be on at a time. The output channel stays on
until another channel of the set is activated.
Mutually exclusive set Only one channel or variable in this set can be on at a
time.
Mutually exclusive toggling A characteristic of status that allows only one
channel of a pre-defined set to be on at a time. The output channel stays on
until it is re-activated or another channel of the set is activated.
Name mangling The process where the name of the Define_Call and any
Waits and Wait_Untils in a library file are changed so that multiple separate
copies can be compiled into a program.
Nesting Placing conditional branches inside other conditional branches.
Null string An empty set of single quotes, which represents a string literal with
no content and a length value of zero.
Glossary
140
One-to-one Each button has one and only one function, with no special
conditions or considerations.
Operator A character or group of characters that performs a specific
mathematical or relational function.
Output change A message to the output function of a channel.
Password A series of numbers that allows access to restricted data.
Preset A level saved for later retrieval. When a preset is recalled, the
level returns to the preset value.
Program file File containing the AXCESS program source code; it has the
DOS extension AXS.
Push window A window on the bottom left of the AXCESS program that
displays the Push statement of the last button pressed in the AXCESS system.
Ramp To change a level from one value to another smoothly over a period of time.
Re-assignment When AXCESS assigns a new value to a parameter variable after a subroutine is executed, but before it returns to the caller.
Relational expression See Boolean expression.
Reserved word An identifier reserved for use by the AXCESS compiler.
Row A one-dimensional array of values in a two-dimensional array.
Run time When the program is executed in the Master Card.
Run-time error An error that occurs during program execution.
S19 format File format used to place code or data into EPROM chips.
Scope The part of the program where the variable can be accessed. A
variable has global scope if the entire program has access to it; a variable
has local scope if only a section of the program has access to it.
Select group A group of buttons that selects a single deck or device out
of a group.
Select variable A variable whose value determines which device in a
group is currently selected.
Serial The transfer of data one byte at a time.
Server Card The AXCESS card that distributes command signals among
device cards, to and from the Master Card, and within its CardFrame.
Glossary
141
Source code The AXCESS program that you type and edit.
State The on or off status of a channel.
Statement A keyword and all of its parameters or conditions.
Status Records the state of the physical part of a channel.
String A set of values grouped together with single and/or double quotes.
String expression Enclosed by double quotes, this expression combines several types of data into a single string.
String length An internal value set for arrays by string assignment operations.
String literal A set of characters (values ranging from 32 to 127) enclosed in
single quotes.
Subroutine A section of code that stands alone and can be called from anywhere else in the program.
System variable A value kept in the Master Card that can be referenced by
certain keywords.
Transport function A common function of devices such as VCRs and cassette
decks. For example: Play, Stop, Pause, Fast Forward, and Rewind.
Two-dimensional array A storage place holding multiple one-dimensional
arrays.
Uploading The opposite of downloading; the computer receives data from a
device.
User interface See look and feel.
Variable A place to store data that will change as the program is executed.
Wait list A list containing unexpired Wait statements. After each pass through
mainline, the Master Card scans this list to see if any have come due.
Wait_Until list A list containing unexpired Wait_Until statements. After each
pass through mainline, the Master Card scans this list to see if any have come
due.
Warning A statement by the compiler urging caution with a potentially hazardous statement in the source code.
Wildcard character Allows any character to be in its place; in AXCESS, this is
the question mark (?). This is only valid when comparing dates and times.
Glossary
142
Index
A
Active. See Select...Active
Analog input or output 81
And 66
Arrays 91100
accessing values 9294
as strings 95
defining 9192
integer 100
manipulation keywords 103
sending 9899
storing values 9294
string lengths 96
two-dimensional 111114
ASCII codes 99
Atoi 102
AX File menu 912
Create S19 file... 10
Options... 11
Retrieve 910
Send w/password... 11
Send... 10
Source-send 9, 10
Verify 10
AXCESS
color mode 4
firmware version information 13
installation 3
mainline 3334
memory 9
monochrome mode 4
power-up 33
program files. See Program files
starting program 3
text editor 8
version information 9
AXlink
and While 77
comparing devices on 12
Index
device numbers 5
errors 6
listing devices on 12
B
Bar graphs 86
Blocks 18
Boolean expression tables 6566
Boolean expressions 58
and Wait_Until 72
in feedback statements 64
Boolean operators 65
Braces 24
nesting If...Else statements 59
nesting Waits 70
with compound statements 58
with subroutines 118
Brackets
with arrays 92
with Push 36
with To 38
Branching 58. See also If, Select...Active.
Buffers 107110
clearing 110
creating 107108
retrieving characters from 108110
storing characters in 108
C
118. See also Subroutines
parameters 124
Calling
subroutines 118
Cancel_All_Wait 72
Cancel_All_Wait_Until 73
Cancel_Wait 72
Cancel_Wait_Until 73
CardFrame
Call
143
connections 4
power supply 4
Cards
device numbers 5
Channels 2930, 3537
changing states of 3739
input function 35
momentary 42
momentary mutually exclusive 43
mutually exclusive 43
mutually exclusive latching 44
mutually exclusive toggling 4445
output function 37
specifying ranges 42
status 41, 43, 44
Clear_Buffer 110
Clearing
buffers 110
Comments 2526
Communications
baud rate 13
configuring 13
pass-thru 14
problems 5
terminal emulator 13
Communications menu 13
Configure... 13
Pass thru... 14
Receive file... 14
Send file... 14
Terminal emulator... 13
Compiled code. See Executable code
Compiler
messages 11
options 11
warnings 11
Compiling 8
comments 25
include files 127
Computer 3
Conditional statements. See Boolean
expressions
Connecting
levels 8687
Constants
assignment of unlike types 11
defining 3132
strings 94
Create_Buffer 107
144
Create_Level 82
Creating
buffers 107108
D
Date 74
Day 74
Define_Call 117
and System_Call 129
local variables 123
parameters 124
storing in separate section of memory
11
unused 11
Define_Connect_Level 8687
Define_Constant 31
identifiers 26
Define_Device 30
identifiers 26
Define_Mutually_Exclusive 43
Define_Program 33
Define_Start 33
and Create_Buffer 107
and Create_Level 83
and Define_Call 117
and To 33, 38
setting variables 32
Define_Variable 32
array string lengths 96
arrays 91
identifiers 26
integer arrays 100
Defining
arrays 9192
constants 3132
devices 3031
latching 4243
momentary mutually exclusive 4344
mutually exclusive latching 44
mutually exclusive toggling 4445
subroutines 117
variables 32
Delays. See Wait
Device numbers 5, 30
receivers 5
Touch Panel 5
Device-channel 2930
Index
direct assignment 39
Devices
defining 3031
Diagnostics menu 12
Compare current devices... 12
Show current devices... 12
Show current versions... 13
Watch variables... 13
DIP switches
settings 5
Direct assignment 39
using a Boolean expression 64
Directories
changing 9
Disk files 3, 8, 15
Double periods 42
Double quotes
with string expressions 94
with strings 94
E
Else 5859, 59. See also If
Equipment 3
Error window 20
Errors
parameter mismatch option
viewing 20
Executable code 8
sending 10
F
Feedback
direct assignment 39
grouping statements 47
last button pressed 43
programming 4647
File menu 7
Change dir... 9
Compile 89
Exit 9
New.. 8, 29
Open include.. 8
Open.. 78
Print.. 9
Save 8
Version... 9
Find_String 104
Index
11
Finding
strings
104
G
Get_Buffer_Char 108
Get_Timer 7374, 85
Global variables 123
H
Help menu 15
HELP.OVL file 15
I
Identifiers 26
constants 31
guidelines 26
If 58
associating with Else 60
nesting 5960
If...Else 5859
default statement 59
If...Else If 59
Include 127
files 127
opening files 8
saving files 8
Indenting 23
Index values 92
Input changes 35
and While keywords 78
keywords 3537
Installation
AXCESS program 3
Instance numbers 131
Integer 100
arrays 100
Itoa 101
Itohex 102
K
Keywords
24
145
L
Latching 42
defining 4243
status 42
Left_String 103
Length_String 96, 109, 112
Levels 8184
and bar graphs 86
connecting 8687
creating 8284
preset 8586
reading 85
sending 86
Library files 129
Local variables 123124
Local_Var 123
Long_While 78
Loops 7778
Lower_String 106
Lowercase 105
M
Mainline 3334. See also Define_Program
and buffers 108
and Push_Channel 37
and Push_Device 36
and Release_Channel 37
and Release_Device 36
and Wait 71
and Wait_Until 72
and While 77
Master Card
CardFrame slot 4
executing mainline 33
LED 6
sending compiled program to 10
sending source code to 9
verifying program 10
Medium_While 78
Menus 715
AX File menu 912
Communications menu 13
Diagnostics menu 12
File menu 7
Help menu 15
Messages
setting options for 11
146
Mid_String 103104
Modems
transferring files 14
Momentary 42
Momentary mutually exclusive
defining 4344
Monitors 4
Mutually exclusive 43
double periods 43
latching 44
momentary 4344
parentheses 43
toggling 4445
variables 61
Mutually exclusive latching
defining 44
Mutually exclusive toggling
defining 4445
N
Name mangling 131
Nesting
If statements 5960
Waits 70
NEW.OVL file 8
Not 66
O
Off 38
On 38
Operators 24
Or 66
Output changes 37
and channel status 41
direct assignment 39
keywords 3839
Output channels 41
physical part 41
status 41
P
Parameters 124126
mismatch error 11
reassignment 125126
Index
Parentheses
and If 58
Call parameters 124
mutually exclusive set 43
Passwords 11
Pause_All_Wait 72
Pause_Wait 71
Presets
creating 8586
Printing 9
configuring 13
Program execution sequence 24
and Waits 67
Program files
compiling 8
creating 8
deleting 8
information on 7
naming 8
opening 7
printing 9
saving 8
Program spacing 23
Program_Name
and include files 128
and program files 8
and System_Call 129
Pulse 39
and Wait 70
Push 36
and feedback 47
and To 38
compound statements 24
finding 19
inserting 19
simulated 20
Push window 5, 19
and Define_Device 31
Push_Channel 37
Push_Device 36
Q
Question marks 75
Quotation marks
with strings 94
Index
R
README file 3
Receiving
strings 107
Relational expressions. See Boolean
expressions
Release 36
Release_Channel 37
Release_Device 36
Remove_String 104
Removing
strings 104
Reserved words 26
Restart_All_Wait 72
Restart_Wait 72
Retrieving
source code 910
Right_String 103
S
S19 files 10
Search and replace 18
Select groups
Mutually exclusive variable method
6163
variable assignment method 6365
Select...Active 6061
default statement 61
Send_Command 93
Send_Level 86, 87
Send_String 98
Sending
arrays 9899
levels 86
program to Master Card 10
Source-send option 10
strings 9899
Server Card
DIP switch settings 5
Set_Length_String 97, 110, 112
Set_Pulse_ Time 39
Set_Timer 73, 85
Simulated button press 20
Single quotes
and case-sensitivity 105
with Include files 127
147
with strings 94
with subroutines 117
Source code 8
retrieving from Master Card 9
sending 10
Startup code 33
Statements 2425
compound 2425
String expressions 9495
Strings 91100, 94
array string lengths 96
assigning to a two-dimensional array
112
assigning to an array 94, 96
conversion keywords 101102
finding 104
receiving 107
removing 104
sending 9899
setting upper/lower case 106
string literals 94
Subroutines 117122
calling 118
defining 117
restrictions on names 117
Substrings. See Arrays: manipulation
keywords
Symbols 27
System_Call 129
from the factory 130
Touch Panels
bar graphs 86
device numbers 5
levels 86
Transferring files 14
Two-dimensional arrays 111114
retrieving values from 113114
storing values in 112
U
Upper_String 106
Uppercase 105
V
Variable Watch window 13
Variables
arrays 91
as output channels 38
assignment of unlike types
defining 32
local 123124
mutually exclusive 61
scope 123
unused 11
Verifying Master Card program
Versions
AXCESS program 9
firmware 13
Video monitors 4
11
10
T
W
Text editor 8, 1720
blocking 1820
commands 17
exiting 9
insert/overwrite mode 18
search and replace 18
Time 74
Timer keywords 7374
To 3839
and Define_Start 33, 38
and Wait 38
momentary channels 42
Total_Off 38
and mutually exclusive groups
148
Wait
67
and Pulse 70
and To 38, 70
cancelling 7172
list 67
multiple Waits 6970
naming 71
nesting Waits 70
pausing 7172
problems in library files
restarting 7172
special uses 70
132
43
Index
Wait_Until 72
list 72
misusing 7273
naming 73
problems in library files 132
removing 73
Warnings
assignment of unlike types 11
Define_Call is not used 11
turning on and off 11
variable is not used 11
While 7778
timeout 78
Wildcard characters 75
X
Xor
Index
66
149