# Allowable Ranges for 2 Series Numeric Formats

Percent (Unsigned, 16b):  0.000% to 100%.  (3 decimal places of precision).

Legal for INTEGER_PARAMETER, LONG_INTEGER_PARAMETER

Percent (Signed, 16b):  -50% to 49.999% (3 decimal places of precision).

Legal for SIGNED_INTEGER_PARAMETER, SIGNED_LONG_INTEGER_PARAMETER

Decimal (Unsigned, 16b):  0d to 65535d

Legal for INTEGER_PARAMETER, LONG_INTEGER_PARAMETER

Decimal (Signed, 16b):  -32768d to 32767d

Legal for SIGNED_INTEGER_PARAMETER, SIGNED_LONG_INTEGER_PARAMETER

Decimal (Unsigned, 32b): 0d to 4294967295d

Legal for LONG_INTEGER_PARAMETER

Decimal (Signed, 32b):  -2147483648d to 2147483647d

Legal for SIGNED_LONG_INTEGER_PARAMETER

Ticks (Unsigned, 16b):  0t to 65535t

Legal for INTEGER_PARAMETER, LONG_INTEGER_PARAMETER

Ticks (Signed, 16b):  SIGNED TIME NOT LEGAL (i.e. can't allow -5t)

Ticks (Unsigned, 32b): 0t to 4294967295t

Legal for LONG_INTEGER_PARAMETER

Ticks (Signed, 32b):  SIGNED TIME NOT LEGAL (i.e. can't allow -5t)

Hex (Unsigned, 16b):  0h to FFFFh

Legal for INTEGER_PARAMETER, LONG_INTEGER_PARAMETER

Hex (Signed, 16b):  -8000h to 7FFFh

Legal for SIGNED_INTEGER_PARAMETER, SIGNED_LONG_INTEGER_PARAMETER

Hex (Unsigned, 32b):  0h to FFFFFFFFh

Legal for LONG_INTEGER_PARAMETER

Hex (Signed, 32b):  -80000000h to 7FFFFFFFh

Legal for SIGNED_LONG_INTEGER_PARAMETER

Time (Unsigned, 16b):  0s to 655.35s

Legal for INTEGER_PARAMETER, LONG_INTEGER_PARAMETER

Time (Signed, 16b):  SIGNED TIME NOT LEGAL (i.e. can't allow -5s)

Time (Unsigned, 32b):  0s to 4294967295s

Legal for LONG_INTEGER_PARAMETER

Time (Signed, 32b):  SIGNED TIME NOT LEGAL (i.e. can't allow -5s)

Character (Unsigned, 16b):  any single typeable character between '', i.e. 'a'.

Legal for INTEGER_PARAMETER, LONG_INTEGER_PARAMETER

Character (Signed, 16b):  NOT LEGAL (i.e. can't allow -'a')

Character (Unsigned, 32b):  NOT LEGAL

Character (Signed, 32):  NOT LEGAL

Note for time, the following formats are valid:

   HH.MM.SS.HS

   MM.SS.HS

   SS.HS

   SS

   .HS

Note that any of the above values don't need to be padded with leading 0's, so that

   02.03.04.5s = 2.3.4.5s

Padding HS with leading 0's makes it a different # since it's a fraction!

For example,

   2.25.36.08s (HH.MM.SS.HS)

   145.36.08s  (MM.SS.HS)

   8736.08s    (SS.HS)

Allowable Character Decimal Formats Hex INTEGER_PARAMETER LEGAL LONG_INTEGER_PARAMETER Numeric Percent Ranges SIGNED_INTEGER_PARAMETER SIGNED_LONG_INTEGER_PARAMETER Series TIME Ticks Time for


Examples

# Examples

This topic is provided to show cases of what is valid & invalid when declaring parameter properties.  Legal values for bounds/list elements/default values/etc. for parameter properties can be found in [Allowable Ranges for 2 Series Numeric Formats],

Example 1:

INTEGER_PARAMETER val;

By itself, an integer parameter is unsigned and may hold a value of 0d to 65535d in SIMPL.  If the programmer tries to enter a value of (for example) 70000d, SIMPL will reject it.

Example 2:

INTEGER_PARAMETER val;

#BEGIN_PARAMETER_PROPERTIES val

    propValidUnits=unitDecimal|unitHex;

    propDefaultUnit=unitPercent;

#END_PARAMETER_PROPERTIES

This is incorrect because the propDefaultUnit is not contained in propValidUnits.

Example 3:

INTEGER_PARAMETER val;

#BEGIN_PARAMETER_PROPERTIES val

    propValidUnits=unitDecimal|unitHex;

    propDefaultUnit=unitDecimal;

    propDefaultValue=25%;

#END_PARAMETER_PROPERTIES

This is incorrect because the propDefaultValue is not contained in the propValidUnits.

Example 4:

INTEGER_PARAMETER val;

LONG_INTEGER_PARAMETER val2;

#BEGIN_PARAMETER_PROPERTIES val, val2

    propValidUnits=unitDecimal|unitHex;

    propDefaultUnit=unitDecimal;

    propDefaultValue=70000d

#END_PARAMETER_PROPERTIES

Example 5:

This is incorrect because 70000d is not a legal value for an INTEGER_PARAMETER.  However, it is legal for the LONG_INTEGER_PARAMETER.

INTEGER_PARAMETER val;

#BEGIN_PARAMETER_PROPERTIES val

    propValidUnits=unitDecimal|unitHex;

    propDefaultUnit=unitDecimal;

    propList={5d, "Value1"},{6d, "Value2"};

#END_PARAMETER_PROPERTIES

This is a valid, legal case.  SIMPL will only let the programmer pick "Value1 [5d]" or "Value2 [6d]" from the dropdown.

Example 6:

INTEGER_PARAMETER val;

#BEGIN_PARAMETER_PROPERTIES val

    propValidUnits=unitDecimal|unitHex;

    propDefaultUnit=unitDecimal;

    propBounds=0x25,0x30;

#END_PARAMETER_PROPERTIES

This is legal since the propBounds specifies a legal unit based on the propValidUnits list and the upper & lower bounds are legal for an INTEGER_PARAMETER.   This example will restrict the the programmer using the module to typing in any value between 25h and 30h, whether they specify it in decimal or hex.  The default notation is decimal if they do not type in a unit.

Example 7:

INTEGER_PARAMETER val;

#BEGIN_PARAMETER_PROPERTIES val

    propDefaultUnit=unitTime;

    propDefaultValue=8d;

#END_PARAMETER_PROPERTIES

Although this does not list a propValidUnits, it is still legal because ALL units are considered valid when no propValidUnits is entered.  The default value when the symbol is dropped into SIMPL is 8d, however, when any value is entered without explicit units, the units are assumed to be "s".  (i.e. entering 5 and hitting ENTER will change to 5s).  This example may not be very practical, but it is legal.

  [Allowable Ranges for 2 Series Numeric Formats]: Allowable_Ranges_for_2_Series_Numeric_Formats.md

Allowable Examples Formats INTEGER_PARAMETER LONG_INTEGER_PARAMETER Numeric Ranges Series for


Comments

# Comments

It is beneficial to comment code to make it more readable and for documentation. Comments do not exist in any form after code generation and are not required.

SIMPL+ has two styles of comments, single line and block comments. Single line comments start with the characters //. The rest of the line (until a carriage return) is considered a comment. If they occur within a quoted string, such as in PRINT, they are NOT treated as comment characters, but rather as two backslash (Hex 2F) characters.

Examples:

PRINT("Hello, World!\n");  // This stuff is a comment.

PRINT("hello, // world!\n"); // This stuff is a comment,

                             // but the string actually

                             // printed is hello, // world.

The second form of comment characters are the block comments. /\* starts a block comment and \*/ ends a block comment. This is useful for commenting out large sections of code or writing large sections of documentation. Note that nested comments are not supported. Also, if /\* or \*/ appear inside of a quoted string such as in an PRINT statement, they are not considered comments but part of the string.

Examples:

    /\*

    This

    is

    all

    a comment!

    \*/

    PUSH Trig

    {

      // code that does something.

    }


Conventions Used

# Conventions Used

Variable names are placed in \<\> when discussing syntax. For example, PUSH \<variable\>.

Optional parameters are placed in [ ]. For example, when a list has many parameters, it would be described as \<var1\>[, \<var2\>...] When discussing array notation, [ ] is used for array subscripting and is not used to mark optional code.

Examples are placed in a Computer Style font, i.e.

MyVariable = ATOI(SomeOtherVariable);


Introduction

# Introduction

 SIMPL+ is a language extension that enhances SIMPL by using a procedural "C-like" language to code elements of the program that were difficult, or impossible, with SIMPL alone. This help system provides specific information about the SIMPL+ language syntax, and can be used as a reference manual.

For a tutorial on SIMPL+ programming, consult the Crestron SIMPL+ Software Programming Guide (Doc. 5789A). The latest version of the guide can be obtained from the Product Manuals area of the Crestron website ([www.crestron.com]). You can also click [here] to open the programming guide from this help file.

A SIMPL+ program is a module that directly interacts with the control system. To interact with the control system, a module must contain a few essential elements. The first element is a starting point.  A starting point is needed for two reasons. First, it serves as a convenient place to initialize any global variables that are declared within the module.  Second, any functionality that the module needs to perform on it’s own (instead of being triggered though an event), can be instantiated here. Another element is event processing. In order for a SIMPL+ module and a control system to interact, they must be able to send and receive signals to and from one another.  Input and output (I/O) signals are declared within the module and are then tied directly to the control system.  Input signals are sent from the control system and are received within the SIMPL+ module.  Output signals are sent from the SIMPL+ module to the control system.  Events are functions that are triggered through input signals from the control system.   I/O signals can be either digital, analog or serial and are declared within the SIMPL+ module. Events tell the SIMPL+ module that something has changed within the control system and allows the module to perform any action accordingly.

NOTE:     In some cases the version of the SIMPL+ Cross Compiler Include file can cause unexpected return values. If you experience this phenomenon check the Cross Compiler Include file version by opening Help | About SIMPL+ . . . in the SIMPL+ Editor.

hv.3.03.03; 23.5.18

  [www.crestron.com]: http://www.crestron.com
  [here]: ../SIMPL_Plus_Tutorial/What_is_SIMPL_Plus_.md


Legal Information (Part 1)

# Legal Information

Crestron Electronics, Inc.

Last Updated: 08 March 2023

**Description**

Crestron Software Development Tools (“Software Tools”) may incorporate, access, include or utilize software libraries or products not written by Crestron, but instead, provided by third parties (“Third Party Software”). Third Party Software may be subject to open source and third-party licensing terms. The license terms associated with open source and Third-Party Software require that Crestron acknowledges those third parties and third-party licensing terms (“Third-Party Software Notices”). These Third-Party Software Notices are incorporated into by reference and apply to all products installed by Crestron MasterInstaller and each Crestron Software Tools software. Not all products contain the same Third Party Software or portions thereof.

Crestron’s “MasterInstaller” Software contains virtually all the Software Tools that are used by Crestron authorized dealers and programmers to design a custom Crestron solution.

Once MasterInstaller is loaded and run on a target personal computer (PC) or other device, it will automatically contact the Crestron website to get all updates to each development tool and download and install the needed Crestron software in the background.

IMPORTANT: BY INSTALLING AND/OR USING THIS CRESTRON MASTERINSTALLER SOFTWARE, OR ANY CRESTRON SOFTWARE DEVELOPMENT TOOL INDIVIDUALLY, YOU ARE AGREEING TO BE BOUND BY THE TERMS CONTAINED IN THE FOLLOWING:

1.  [Crestron Software End-User License Agreement\
    \
    ]
2.  [Software Development Tools License Agreement\
    \
    ]
3.  [Third Party Software Notices\
    \
    ]
4.  [Crestron Privacy Statement Regarding Internet Data Collection\
    \
    ]
5.  [Trademark Acknowledgments\
    \
    ]

NOTICE: CERTAIN CRESTRON SOFTWARE TOOLS INCORPORATE FLASH® PLAYER SOFTWARE , DEVELOPED BY ADOBE INC., TO RENDER TEXT, VECTOR GRAPHICS, AND RASTER GRAPHICS IN ORDER TO PROVIDE ANIMATIONS AND DEVELOP END-USER APPLICATIONS FOR CRESTRON PRODUCTS. THE TERMS UNDER WHICH CRESTRON HAS LICENSED FLASH® PLAYER HAVE CHANGED. FLASH PLAYER MAY NO LONGER BE DISTRIBUTED IN THE PEOPLE’S REPUBLIC OF CHINA, INCLUDING BUT NOT LIMITED TO CRESTRON DEALERS, INSTALLERS, PROGRAMMERS, AND SERVICE PROVIDERS.

General Information
Legal-Information
Legal Information


Legal Information (Part 2)

  [Crestron Software End-User License Agreement\
  \
  ]: https://www.crestron.com/Legal/software-license-agreement/Crestron-Software-End-User-License-Agreement "https://www.crestron.com/Legal/software-license-agreement/Crestron-Software-End-User-License-Agreement"
  [Software Development Tools License Agreement\
  \
  ]: https://www.crestron.com/Legal/software-license-agreement/MasterInstaller-and-SW-Tools-Installation-Agree "https://www.crestron.com/Legal/software-license-agreement/MasterInstaller-and-SW-Tools-Installation-Agree"
  [Third Party Software Notices\
  \
  ]: https://www.crestron.com/Legal/software-license-agreement/Third-Party-Software-Notices-for-Crestron-Tools "https://www.crestron.com/Legal/software-license-agreement/Third-Party-Software-Notices-for-Crestron-Tools"
  [Crestron Privacy Statement Regarding Internet Data Collection\
  \
  ]: https://www.crestron.com/Legal/Privacy-Policy "https://www.crestron.com/Legal/Privacy-Policy"
  [Trademark Acknowledgments\
  \
  ]: https://www.crestron.com/Legal/software-license-agreement/Trademark-Acknowledgement-Notices "https://www.crestron.com/Legal/software-license-agreement/Trademark-Acknowledgement-Notices"

THE TERMS UNDER WHICH CRESTRON HAS LICENSED FLASH® PLAYER HAVE CHANGED. FLASH PLAYER MAY NO LONGER BE DISTRIBUTED IN THE PEOPLE’S REPUBLIC OF CHINA, INCLUDING BUT NOT LIMITED TO CRESTRON DEALERS, INSTALLERS, PROGRAMMERS, AND SERVICE PROVIDERS.


Relative Path Names for Files

# Relative Path Names for Files

Your current working directory is reset to the default ("/" or root) whenever "StartFileOperations" is performed. It is changed only by "SetCurrentDirectory".

File names can consist of full path names or relative path names.

Full path names have the same restrictions as DOS file names in characters and format, with maximum length of 256 characters.

Relative path names do not begin with a "\\ and start from the current working directory.

General Information
Relative Path Names for Files


Variable Names

# Variable Names

Variable names in SIMPL+ may be up to 30 characters long and may not contain any of the operators specified in the "Operators" section. Valid characters in a variable name are a-z, A-Z, 0-9, #, _, and $ but may not begin with 0-9.

Variable names may not duplicate existing function or keyword names.

Variable names in SIMPL+ are not case sensitive. For example, declaring a variable "joe" can be used as "jOe" or "JOE" or any variation of case.

NOTE:  Version 3.00.12 users: variable names may be 120 characters for 2-Series systems.


Arrays

# Arrays

Various one and two dimensional arrays are supported. All input and output arrays are 1-based, meaning that the first element has index 1, not 0. Internal variables are 0-based, meaning that the first element has index 0. In both cases, the index of the last element is the same as the dimension of the array.

Do not confuse the declaration of the length of STRINGs with the declaration of arrays. E.g., STRING s$[32] is a single string of length 32, and STRING ManyS$[10][32] is an array of 11 strings of length 32 each. You must use the BYTE function to access the character at a particular position in a string, but you can use the array index to access a particular string in an array of strings. Positions in a string are 1-based. See the discussion of Minimum Size Arrays in [Declaration Overview].

One dimensional arrays of the following types are supported:

DIGITAL_INPUT

DIGITAL_OUTPUT

ANALOG_INPUT

ANALOG_OUTPUT

STRING_OUTPUT

BUFFER_OUTPUT

STRUCTURES

One dimensional arrays of strings are also supported, although since the declaration also contains a string length, it looks like a 2-dimensional array:

STRING_INPUT

BUFFER_INPUT

STRING

One and two dimensional arrays of the following types are supported:

INTEGER

LONG_INTEGER

SIGNED_INTEGER

SIGNED_LONG_INTEGER

Examples:

|  |  |
|----|----|
| Declaration | Meaning |
| DIGITAL_INPUT in[10]; | 10 digital inputs, in[1] to in[10] |
| INTEGER MyArray[10][20]; | 11 rows by 21 columns of data, from MyArray[0][0] to MyArray[10][20] |
| STRING PhoneNumbers[100][32]; | 101 strings that are a maximum of 32 characters long, e.g. PhoneNumbers[0] to PhoneNumbers[100] |
| STRING_INPUT in$[32]; | One input string called in$ that is 32 characters long. |
| STRING_OUTPUT out$[10]; | Ten output strings, out$1 to out$[10]. Their length does not have to be specified. |
| STRING_INPUT in$[5][32]; | Five input strings, in$[1] to in$[5] that are 32 characters long. |
| \<struct_type\> myStruct[10]; | 11 structure elements from myStruct[0] to myStruct[10]. |

NOTE: An element of an integer array is not accepted where a function requires an integer.

  [Declaration Overview]: ../Declarations/Declarations_Overview.md

Language Constructs & Functions
Array Operations
Arrays


GetLastModifiedArrayIndex

# GetLastModifiedArrayIndex

Name:

GetLastModifiedArrayIndex

Syntax:

    INTEGER GetLastModifiedArrayIndex ();

Description:

Determines the specific index number of an input list array that has changed.

ANALOG_INPUT, BUFFER_INPUT, DIGITAL_INPUT, and STRING_INPUT arrays are subject to be used in CHANGE, PUSH, and RELEASE statements, but only the overall array can be specified in the statement, not an individual element. In order to find out what element has been modified (and hence caused the activation of the CHANGE, PUSH, or RELEASE), GETLASTMODIFIEDARRAYINDEX is used.

NOTE:  To use GETLASTMODIFIEDARRAYINDEX, only one array may be used in a single CHANGE, PUSH, or RELEASE statement. If more than one element of the array changes at the same time, multiple events are run. For example, if D[10] is a DIGITAL_INPUT array that is subject to a PUSH event, and D[1] and D[2] change at the same time, the PUSH is first run where D[1] changes and GETLASTMODIFIEDARRAYINDEX returns 1, then the PUSH is run again where D[2] changes and GETLASTMODIFIEDARRAYINDEX returns 2.

NOTE:  Using GetLastModifiedArrayIndex OUTSIDE of an event (PUSH, RELEASE, CHANGE or EVENT) may return an index to an ambiguous signal if more than one input array is declared within the program.  Therefore, do not use this function if more than one input signal array is declared within the program, unless you use it within one of the event statements.

Return Value:

The element of the array that has changed.

Example 1, Correct Use:

    DIGITAL_INPUT LIGHT_SCENES[10], MORE_LIGHT_SCENES[10};

    DIGITAL_OUTPUT INTERLOCKED_LIGHT_SCENES[10];

    INTEGER I;

    PUSH LIGHT_SCENES

    {

        FOR(I=1 to 10)

INTERLOCKED_LIGHT_SCENES[I] = 0;

      ProcessLogic();

      INTERLOCKED_LIGHT_SCENES[GetLastModifiedArrayIndex()] = 1;

    }

Example 2, Incorrect Use:

DIGITAL_INPUT LIGHT_SCENES[10];

DIGITAL_OUTPUT INTERLOCKED_LIGHT_SCENES[10];

INTEGER I;

PUSH LIGHT_SCENES,MORE_LIGHT_SCENES[10]

{//this PUSH statement will be called twice (once for LIGHT_SCENES and once for MORE_LIGHT_SCENES)

  FOR(I=1 to 10)

INTERLOCKED_LIGHT_SCENES[I]=0

ProcessLogic();

INTERLOCKED_LIGHT_SCENES[GetLastModifiedArrayIndex()] = 1;

    }

}

In this example, when one input element changes, all the output elements are set to 0 and then the output level corresponding to the changed input level is set to 1. This mimics the functionality of the Interlock symbol in SIMPL.

Version:

X Generation:  SIMPL v1.50.06

2-Series:  SIMPL v2.01.05 and later

Language Constructs & Functions
Array Operations
GetLastModifiedArrayIndex


GetNumArrayCols

# GetNumArrayCols

Name:

GetNumArrayCols

Syntax:

    INTEGER GetNumArrayCols(STRING | INTEGER

Description:

Finds the number of columns in a two-dimensional array or the size of the array for a one-dimensional array.

Parameters:

ARRAY_NAME is the array as determined by the size.

Return Value:

For the data types in the table after this paragraph, the return value of GetNumArrayCols is shown.

|                                             |              |
|---------------------------------------------|--------------|
| DATA TYPE                                   | RETURN VALUE |
| ANALOG INPUT X [size]                     | Size         |
| ANALOG INPUT X [size]                     | Size         |
| DIGITAL INPUT X [size]                    | Size         |
| DIGITAL OUTPUT X [size]                   | Size         |
| STRING INPUT X [size]                     | Chars        |
| STRING INPUT X [size] [chars]           | Chars        |
| STRING OUTPUT X [size]                    | Size         |
| STRING X [chars]                          | Chars        |
| STRING X [size] [chars]                 | Chars        |
| INTEGER X [size]                          | Size         |
| INTEGER X [size 1] [size 2]             | Size2        |
| SIGNED_INTEGER X [size]                   | Size         |
| SIGNED_INTEGER X [size 1] [size 2]      | Size2        |
| SIGNED_LONG_INTEGER X [size]              | Size         |
| SIGNED_LONG_INTEGER X [size 1] [size 2] | Size2        |
| BUFFER INPUT X [chars]                    | Chars        |
| BUFFER INPUT X [size] [chars]           | Chars        |

Example:

    DIGITAL_INPUT TEST;

    INTEGER My_Array[10][20];

    PUSH TEST

    {

      PRINT("Columns = %d\n", GetNumArrayCols(My_Array));

    }

In this example, Columns = 20 will be printed.

Version:

X Generation:  SIMPL v1.50.06

2-Series:  SIMPL v2.01.05 and later

Language Constructs & Functions
Array Operations
GetNumArrayCols

DIGITAL_INPUT GetNumArrayCols INTEGER PRINT PUSH RETURN SIGNED_INTEGER SIGNED_LONG_INTEGER STRING


GetNumArrayRows

# GetNumArrayRows

Name:

GetNumArrayRows

Syntax:

    INTEGER GetNumArrayRows(STRING | INTEGER ARRAY_NAME);

Description:

Returns the number of rows for two-dimensional arrays or string arrays.

Parameters:

ARRAY_NAME is the array name as determined by the size.

Return Value:

For the data types in the table after this paragraph, the return value of GetNumArrayRows is shown.

Example:

    DIGITAL_INPUT TEST;

    INTEGER My_Array[10][20];

    PUSH TEST

    {

      PRINT("Rows = %d\n", GetNumArrayRows(My_Array));

    }

In this example, Rows = 10 will be printed.

Version:

X Generation:  SIMPL v1.50.06

2-Series:  SIMPL v2.01.05 and later

Language Constructs & Functions
Array Operations
GetNumArrayRows

DIGITAL_INPUT GetNumArrayRows INTEGER PRINT PUSH STRING


GetNumStructureArrayCols

# GetNumStructureArrayCols

Name:

GetNumStructureArrayCols

Syntax:

    INTEGER GetNumStructureArrayCols( STRUCTURE_ARRAY );

Description:

Returns the number of columns in a structure array.

Parameters:

STRUCTURE_ARRAY is the structure array variable.

Return Value:

The number of columns in the structure array.

Example:

   STRUCTURE tagStruct

   {

      INTEGER i;

   };

   tagStruct myStructArr[10];

   FUNCTION foo()

   {

      INTEGER numCols;

      numCols = GetNumStructureArrayCols( myStructArr ); // numCols = 10

   }

Version:

X Generation:  SIMPL v1.50.06

2-Series:  SIMPL v2.01.05 and later

3-Series:

Language Constructs & Functions
Array Operations
GetNumStructureArrayCols

FUNCTION GetNumStructureArrayCols INTEGER STRUCTURE


Array Operations Overview

# Array Operations Overview

Array Operations functions are used to perform generalized operations on arrays, such as getting bounds and setting the elements of an array to a known value in a given SIMPL+ program.

| Operation                | Description                                                                                |
| ------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------- |
| GetNumArrayCols          | Finds the number of columns in a two-dimensional array or the size of the array for a one-dimensional array.                                      |
| GetNumArrayRows          | Returns the number of rows for two-dimensional arrays or string arrays. Returns 0 for one dimensional arrays or strings.                          |
| GetNumStructureArrayCols | Returns the number of columns in a structure array.                                                                                |
| ResizeArray              | Changes the allocated size of the string array to NewNumElements of NewSize bytes or the integer array to NewNumElements rows of NewSize columns. |
| ResizeStructureArray     | Changes the allocated size of the structure array to NewSize elements.                                                                            |
| SetArray                 | Sets every element of ARRAY_NAME to the INIT_VALUE.                                                                                |

Language Constructs & Functions
Array Operations
Overview
Array Operations Overview


ResizeArray

# ResizeArray

Name:

ResizeArray

Syntax:

    SIGNED_INTEGER ResizeArray (ARRAY_NAME, INTEGER NewNumElements, INTEGER NewSize);

Description:

Changes the allocated size of the string array to NewNumElements of NewSize bytes or the integer array to NewNumElements rows of NewSize columns or the structure array to NewSize elements.

NOTE: To use this function, the [#ENABLE_DYNAMIC] compiler directive must be present in the SIMPL+ module and the variable must be declared as [DYNAMIC].

NOTE: The NewNumElements parameter is optional.

Parameters:

ARRAYNAME can be either an integer or string array variable that needs a change in allocated size.

NewNumElements indicates the new number of elements in the string array or number of rows for a 2-D integer array (should be 0 for 1-D arrays).

NewSize indicates the new number of bytes in each string in the array or the new number of columns for the integer array.

Return Value:

|          |                                  |
|----------|----------------------------------|
| Status   | Definition                       |
| 0        | Success                          |
| 0x8001   | Generic Error                    |
| 0x8002   | Error – Max Resize limit reached |
| 0x8004\* | Error – Element is not dynamic   |
| 0x8008   | Warning – Truncation will occur  |
| 0x8010   | Error – Out of memory            |
| 0x8020   | Error – Out of memory            |
| 0x8040   | Error – Out of memory            |

\* This error indicates that the #ENABLE_DYNAMIC compiler directive is missing from the SIMPL+ module and/or that the variable has not been declared as DYNAMIC.

NOTE: The status might contain an error and a warning returned together. For example, if an array is resized from 20 to 10 elements, a truncation warning will result. However, if the system is out of memory, the resize cannot be completed. In this scenario, the returned status will be 0x8008 | 0x8010,  or 0x8018.

Example:

INTEGER MyIntArray[10][10];

STRING MyStringArray[10][10];

Function main()

{

SIGNED_INTEGER  Status;

    Status = ResizeArray(MyStringArray, 200, 80);

    If (status != 0)

        Print(“Error occurred in resizing string array MyStringArray\n”)

    Status = ResizeArray(MyIntArray, 200, 100);

    If (status != 0)

        Print(“Error occurred in resizing string array  MyIntArray\n”)

}

In this example, the columns and rows of MyIntArray and MyStringArray are changed from 10 and 10 (for both MyIntArray and MyStringArray) to 200 and 100 for MyIntArray and 200 and 80 for MyStringArray.

Version:

2 Series only

X Gen Not Supported

  [#ENABLE_DYNAMIC]: javascript:void(0);
  [DYNAMIC]: javascript:void(0);

Language Constructs & Functions
Array Operations
ResizeArray

ENABLE_DYNAMIC INTEGER If Print ResizeArray SIGNED_INTEGER STRING


ResizeStructureArray

# ResizeStructureArray

Name:

ResizeStructureArray

Syntax:

    SIGNED_INTEGER ResizeStructureArray (ARRAYNAME, INTEGER NewSize);

Description:

Changes the allocated size of the structure array to NewSize elements.

NOTE: To use this function, the [#ENABLE_DYNAMIC] compiler directive must be present in the SIMPL+ module and the variable must be declared as [DYNAMIC].

Parameters:

ARRAYNAME - a Structure array variable that needs a change in allocated size.

NewSize indicates the new number of elements for the structure array.

Return Value:

|          |                                  |
|----------|----------------------------------|
| Status   | Definition                       |
| 0        | Success                          |
| 0x8001   | Generic Error                    |
| 0x8002   | Error – Max Resize limit reached |
| 0x8004\* | Error – Element is not dynamic   |
| 0x8008   | Warning – Truncation will occur  |
| 0x8010   | Error – Out of memory            |
| 0x8020   | Error – Out of memory            |
| 0x8040   | Error – Out of memory            |

\* This error indicates that the #ENABLE_DYNAMIC compiler directive is missing from the SIMPL+ module and/or that the variable has not been declared as DYNAMIC.

NOTE: The status might contain an error and a warning returned together. For example, if an array is resized from 20 to 10 elements, a truncation warning will result. However, if the system is out of memory, the resize cannot be completed. In this scenario, the returned status will be 0x8008 | 0x8010,  or 0x8018.

Example:

STRUCTURE tagMyStruct

{

    INTEGER MyIntArray[10][10];

    STRING MyStrArray[10][10];

};

dynamic tagMyStruct myStructArr[10];

Function main()

{

          SIGNED_INTEGER  Status;

          Status = ResizeStructureArray(myStructArr, 20);

          If (status != 0)

                   Print(“Error occurred in resizing array  MyStructArr\n”)

}

Version:

2 Series only

X Gen not supported

  [#ENABLE_DYNAMIC]: javascript:void(0);
  [DYNAMIC]: javascript:void(0);

Language Constructs & Functions
Array Operations
ResizeStructureArray

ENABLE_DYNAMIC INTEGER If Print ResizeStructureArray SIGNED_INTEGER STRING STRUCTURE


SetArray

# SetArray

Name:

SetArray

Syntax:

 SetArray (ARRAY_NAME, INTEGER | STRING INIT_VALUE);

Description:

Sets every element of ARRAY_NAME to the INIT_VALUE.

Parameters:

ARRAY_NAME is the name of the array to be initialized. It may be any array type.

The INIT_VALUE may be a INTEGER or STRING. The following chart shows the various combinations of ARRAY_NAME types and INIT_VALUE types:

NOTE:  When working with DIGITAL_OUTPUT arrays, if the INIT_VALUE evaluates to 0, the digital signals are set low. For any non-zero value, the outputs are set high.

Return Value:

None.

Example:

    DIGITAL_INPUT InitializeArrays;

    INTEGER Levels[10];

    STRING Names[5][5];

    PUSH InitializeArrays

    {

      SetArray(Levels, 3);

      SetArray(Levels, "3");

      SetArray(Names, "xyz");

      SetArray(Names, 0x41);

    }

The first line initializes all elements of the integer array Levels to contain the integer 3.

The second line attempts to initialize the elements of the integer array Levels with a string value - an ATOI is done on the "3", which returns a 3, so that the end result is the same as the first line.

The third line initializes all elements of the elements of the string array Names to contain the string value "xyz".

The fourth line attempts to initialize the elements of the string array Names with an integer value - a CHR is done on the 0x41, which returns the string "A", so that the end result has all elements of the string array Names containing the string "A".

Version:

X Generation:  SIMPL v1.50.06

2-Series:  SIMPL v2.01.05 and later

Language Constructs & Functions
Array Operations
SetArray

ATOI CHR DIGITAL_INPUT DIGITAL_OUTPUT INTEGER PUSH STRING SetArray


Bit

# Bit

Name:

Bit

Syntax:

    INTEGER Bit(STRING SOURCE, INTEGER SOURCE_BYTE, INTEGER

                BIT_IN_BYTE);

Description:

Determine the state of a specified bit in a particular byte of a given string.

Parameters:

SOURCE contains a STRING in which a bit of one byte is to be examined. Each character in SOURCE is considered one byte.

SOURCE_BYTE references a character in the SOURCE string. The leftmost character in SOURCE is considered 1.

BIT_IN_BYTE specifies which bit in the SOURCE_BYTE of SOURCE is to be examined. BIT_IN_BYTE starts at position 0 (least significant or rightmost bit of the byte). 7 is the most significant or leftmost bit of the byte.

Return Value:

Returns 0 or 1 for a valid bit position. Illegal bit references will return 65535. It is illegal if SOURCE_BYTE is 0 or greater than the length of the SOURCE string. Note that it is legal to specify a bit beyond 7. This will reference a bit in another byte. In this way, a source string can be used as a set of packed bit flags. The algorithm for determining which bit in which byte is set when BIT_IN_BYTE is greater than 7 is as follows.

Actual Byte in SOURCE = (BIT_IN_BYTE / 8) + SOURCE_BYTE

Actual Bit in Actual Byte = (BIT_IN_BYTE MOD 8)

Applying this to BIT("abc",1,16) will reference bit 0 of byte 3 (the least significant bit of byte "c" in SOURCE).

Example:

This example takes an input string and creates an output string containing the elements of the input string that do not have the most significant bit (bit 7) set.

    STRING_INPUT SOURCE$[100];

    STRING_OUTPUT OUT$;

    STRING TEMP$[100];

    INTEGER I;

    CHANGE SOURCE$

    {

      FOR(I = 1 to LEN(SOURCE$))

      {

        IF(BIT(SOURCE$, I, 7) = 0)

        {

          MAKESTRING(TEMP$, "%s%s", TEMP$, MID(SOURCE$, I, 1));

        }

      }

      OUT$ = TEMP$;

    }

Version:

X Generation:  SIMPL v1.20.01 and later

2-Series:  SIMPL v2.01.05 and later

Language Constructs & Functions
Bit & Byte Functions
BIT
Bit

BIT Bit CHANGE FOR IF INTEGER LEN MAKESTRING MID STRING STRING_INPUT STRING_OUTPUT


Byte

# Byte

Name:

Byte

Syntax:

    INTEGER Byte(STRING SOURCE, INTEGER SOURCE_BYTE);

Description:

Returns the integer equivalent of the byte at position SOURCE_BYTE within a SOURCE string.

Parameters:

SOURCE is a STRING of characters. Each character in SOURCE is considered one byte.

SOURCE_BYTE references a character in the SOURCE string. The leftmost character in SOURCE is considered 1.

Return Value:

An integer containing the ASCII numeric value of the byte at position SOURCE_BYTE in the string SOURCE. If SOURCE_BYTE is greater than the length of the SOURCE string or is 0, 65535 is returned.

Example:

This piece of code will examine an input string to make sure that it starts with STX character (02). From there, it will test the second byte and process different command types accordingly.

    STRING_INPUT IN$[100];

    CHANGE IN$

    {

      IF(BYTE(IN$,1) = 02)

      {

        SWITCH(BYTE(IN$,2))

        {

          CASE (65):

          {

             // Process Command type 65 (A) here.

             }

          CASE (66):

             {

            // Process Command type 66 (B) here.

          }

        }

      }

    }

Version:

X Generation:  SIMPL v1.20.01 and later

2-Series:  SIMPL v2.01.05 and later

Language Constructs & Functions
Bit & Byte Functions
BYTE
Byte

BYTE Byte CASE CHANGE IF INTEGER STRING STRING_INPUT SWITCH


High

# High

Name:

High

Syntax:

    INTEGER High(INTEGER VALUE);

Description:

Returns the upper most significant 8-bits of an Integer.

Parameters:

VALUE is an integer containing the value of the most significant  byte. It is not sign extended.

Return Value:

The upper 8-bits of the passed value. The return value is not signed extended, It is intended only for unsigned short integers (16 bits).

Example:

    ANALOG_INPUT VALUE;

    CHANGE VALUE

    {

      PRINT("The upper byte of %X is %X\n", VALUE, HIGH(VALUE));

    }

This will print the input value and the upper 8-bits of the value in hexadecimal. For example, if VALUE is 0x1234, then the output is The upper byte of 1234 is 12.

Version:

X Generation:  SIMPL v1.20.01 and later

2-Series:  SIMPL v2.01.05 and later

Language Constructs & Functions
Bit & Byte Functions
HIGH
High

ANALOG_INPUT CHANGE HIGH High INTEGER PRINT


HighWord

# HighWord

Name:

HighWord

Syntax:

    INTEGER HighWord(LONG_INTEGER Value);

Description:

Returns the upper 16 significant bits of a LONG_INTEGER.

Parameters:

Value is a LONG_INTEGER containing the uppermost 16 significant bits the user wants.

Return Value:

The upper 16 significant bits of Value.

Example:

Function main()

{

LONG_INTEGER x;

INTEGER y;

x=0xAABBCCDD;

y=HighWord(x);

print("The UpperMost 16 Bits of %08IX are %04X\n", x, y);

 }

This will print: The UpperMost 16 bits of AABBCCDD are AABB.

Version:

SIMPL+ Version 3.03.00 or later

CUZ 3.154 or later required

Language Constructs & Functions
Bit & Byte Functions
HighWord


Low

# Low

Name:

Low

Syntax:

    INTEGER Low(INTEGER VALUE)

Description:

Returns the lower least significant 8-bits of an Integer.

Parameters:

VALUE is an integer containing the value of the least significant byte.

Return Value:

The lower 8-bits of the passed value.

Example:

    ANALOG_INPUT VALUE;

    CHANGE VALUE

    {

      PRINT("The lower byte of %X is %X\n", VALUE, LOW(VALUE));

    }

This will print the input value and the lower 8-bits of the value in hexadecimal. For example, if VALUE is 0x1234, then the output is The lower byte of 1234 is 34.

Version:

X Generation:  SIMPL v1.20.01 and later

2-Series:  SIMPL v2.01.05 and later

Language Constructs & Functions
Bit & Byte Functions
LOW
Low

ANALOG_INPUT CHANGE INTEGER LOW Low PRINT


LowWord

# LowWord

Name:

LowWord

Syntax:

    INTEGER LowWord(LONG_INTEGER Value);

Description:

Returns the lower 16 significant bits of a LONG_INTEGER.

Parameters:

Value is a LONG_INTEGER containing the lowermost 16 significant bits the user wants.

Return Value:

The lower 16 significant bits of Value.

Example:

Function main()

{

LONG_INTEGER x;

INTEGER y;

x=0xAABBCCDD;

y=LowWord(x);

print("The LowerMost 16 Bits of %08IX are %04X\n", x, y);

 }

This will print: The UpperMost 16 bits of AABBCCDD are CCDD.

Version:

SIMPL+ Version 3.03.00 or later

CUZ 3.154 or later required

Language Constructs & Functions
Bit & Byte Functions
LowWord


LowerChar

# LowerChar

Name:

LowerChar

Syntax:

    INTEGER LowerChar(INTEGER character);

Description:

Converts the given character to lower case, so long as the character is between 'A' (0x41) and 'Z' (0x5A).

Parameters:

Value is an INTEGER character: The character to convert to lower case.

Return Value:

The character converted to lower case.  If the character is not an upper case character, the same character is returned.

Example:

INTEGER Converted1, Converted2;

Converted1 = LowerChar('a');

Converted2 = LowerChar('5');

Print("Converted1=%c, Converted2=%c\n", Converted1, Converted2);

Converted1=a (this is returned if the converted character was an upper case character).

Converted2=5 (this would be returned if the character to be converted was not an upper case character).

Version:

SIMPL+ Version 3.03.00 or later

CUZ 3.137 or later required

Language Constructs & Functions
Bit & Byte Functions
LowerChar


Bit & Byte Functions Overview

# Bit & Byte Functions Overview

These functions perform bit and byte masking operations in a given SIMPL+ program.

|  |  |
|----|----|
| Function | Description |
| [Bit] | Determines the state of a specified bit in a particular byte of a given string. |
| [Byte] | Returns the integer equivalent of the byte at position SOURCE_BYTE within a SOURCE string. |
| [High] | Returns the upper most significant 8-bits of an Integer. |
| [HighWord] | Returns the upper 16 significant bits of a LONG_INTEGER. |
| [Low] | Returns the lower least significant 8-bits of an Integer. |
| [LowWord] | Returns the lower 16 significant bits of a LONG_INTEGER. |
| [LowerChar] | Converts the given character to lower case, so long as the character is between 'A' (0x41) and 'Z' (0x5A). |
| [UpperChar] | Converts the given character to upper case, so long as the character is between 'a' (0x61) and 'z' (0x7A). |
| [SetByte] | Sets the byte at the position given by POSITION in the string given by SOURCE to the value in VALUE. |

  [Bit]: BIT.md
  [Byte]: BYTE.md
  [High]: HIGH.md
  [HighWord]: HighWord.md
  [Low]: LOW.md
  [LowWord]: LowWord.md
  [LowerChar]: LowerChar.md
  [UpperChar]: UpperChar.md
  [SetByte]: SetByte.md

Language Constructs & Functions
Bit & Byte Functions
Overview
Bit & Byte Functions Overview

BIT BYTE Bit Byte Functions HIGH High HighWord LONG_INTEGER LOW Low LowWord LowerChar Overview SetByte UpperChar

Bit Byte High HighWord Low LowWord LowerChar UpperChar SetByte


RotateLeft

# RotateLeft

Name:

RotateLeft

Syntax:

 INTEGER RotateLeft( INTEGER X, INTEGER Y );

Description:

Rotate X to the left (more significant direction) by Y bits; full 16 bits used. Same as {{ operator.

(refer to [RotateRight] explanation)

Parameters:

X is the INTEGER to have bits rotated

Y is the amount of bits to rotate

Return Value:

An INTEGER containing the result of the rotated bits.

Example:

INTEGER X, Y, result;

result = RotateLeft( X, Y );

Version:

X Generation:  Not Supported

2-Series:  SIMPL v2.03.18 and later

  [RotateRight]: RotateRight.md

Language Constructs & Functions
Bit & Byte Functions
RotateLeft


RotateLeftLong

# RotateLeftLong

Name:

RotateLeftLong

Syntax:

    LONG_INTEGER RotateLeftLong( LONG_INTEGER X, INTEGER Y );

Description:

Rotate X to the left by Y bits; full 32 bits used.

Parameters:

X is the LONG_INTEGER to have bits rotated

Y is the amount of bits to rotate

Return Value:

A LONG_INTEGER containing the result of the rotated bits.

Example:

LONG_INTEGER X, Y, result;

result = RotateleftLong( X, Y );

Version:

X Generation:  Not Supported

2-Series:  SIMPL v2.03.18 and later

Language Constructs & Functions
Bit & Byte Functions
RotateLeftLong

INTEGER LONG_INTEGER RotateLeftLong RotateleftLong


RotateRight

# RotateRight

Name:

RotateRight

Syntax:

    INTEGER RotateRight( INTEGER X, INTEGER Y );

Description:

Rotate X to the right by Y bits; full 16 bits used. Same as }} operator.

e.g., Each bit takes the value of the bit that is Y bits more significant than it is. The most significant bit(s) are set from the least significant bits.

Parameters:

X is the INTEGER to have bits rotated

Y is the amount of bits to rotate

Return Value:

An INTEGER containing the result of the rotated bits.

Example:

INTEGER X, Y, result;

result = RotateRight( X, Y );

If X = 0x1234 and Y is 1, then the result is 0x091A

Version:

X Generation:  Not Supported

2-Series:  SIMPL v2.03.18 and later

Language Constructs & Functions
Bit & Byte Functions
RotateRight


RotateRightLong

# RotateRightLong

Name:

RotateRightLong

Syntax:

    LONG_INTEGER RotateRightLong( LONG_INTEGER X, INTEGER Y );

Description:

Rotate X to the right by Y bits; full 32 bits used.

Parameters:

X is the LONG_INTEGER to have bits rotated

Y is the amount of bits to rotate

Return Value:

A LONG_INTEGER containing the result of the rotated bits.

Example:

LONG_INTEGER X, Y, result;

result = RotateRightLong( X, Y );

Version:

X Generation:  Not Supported

2-Series:  SIMPL v2.03.18 and later

Language Constructs & Functions
Bit & Byte Functions
RotateRightLong


SetByte

# SetByte

Name:

SetByte

Syntax:

    INTEGER SetByte(STRING SOURCE, INTEGER POSITION, INTEGER VALUE);

Description:

Sets the byte at the position given by POSITION in the string given by SOURCE to the value in VALUE.

Parameters:

SOURCE is a STRING of characters. Each character in SOURCE is considered one byte.

POSITION references a character in the SOURCE string. The leftmost character in SOURCE is considered 1.  The only valid positions are 1 to LEN(SOURCE).  Any other position is out of bounds and will return an error.

VALUE is the data to set the source string position to.  If it is greater than 255, the lower 8 bits are used.

Return Value:

0 if success, -1 if failure.

Example:

function main()

{

   STRING Text$[25];

   INTEGER ReturnValue;

   Text$="CPQ1704TKS";

   ReturnValue = SetByte(Text$, 3, 'E');

   if(ReturnValue \<\> 0)

   {

      print("Error, could not Set Byte at given position\n");

   }

   else

   {

      print("New String is: \<%s\>\n", Text$);

   }

}

In this example, the output is "New String is: \<CPE1704TKS\>"

Version:

2-Series Only:  SIMPL v2.10.10 and later.

Language Constructs & Functions
Bit & Byte Functions
SetByte


UpperChar

# UpperChar

Name:

UpperChar

Syntax:

    INTEGER UpperChar(INTEGER character);

Description:

Converts the given character to upper case, so long as the character is between 'a' (0x61) and 'z' (0x7A).

Parameters:

Value is an INTEGER character: The character to convert to upper case.

Return Value:

The character converted to upper case.  If the character is not a lower case character, the same character is returned.

Example:

INTEGER Converted1, Converted2;

Converted1 = UpperChar('a');

Converted2 = UpperChar('5');

Print("Converted1=%c, Converted2=%c\n", Converted1, Converted2);

Converted1=A (this is returned if the converted character was a lower case character).

Converted2=5 (this would be returned if the character to be converted was not a lower case character).

Version:

SIMPL+ Version 2.10.00 or later

CUZ 3.137 or later required

Language Constructs & Functions
Bit & Byte Functions
UpperChar


BREAK

# BREAK

Name:

BREAK

Syntax:

    BREAK;

Description:

Terminates the innermost DO-UNTIL, FOR, or WHILE loop before the exit condition is met.

Execution resumes after the end of the loop.

Example:

    INTEGER X;

    ANALOG_INPUT Y;

    X=0;

    WHILE(X\<25)

    {

      IF(Y = 69)

        BREAK;

      X = X + 1;

      PRINT("X=%d\n", X);

    }

In this example, the WHILE loop will terminate if the ANALOG_INPUT Y equals the value of 69. Otherwise, the loop will exit via the normal termination condition.

Version:

X Generation:  SIMPL v1.20.01 and later

2-Series:  SIMPL v2.01.05 and later

Language Constructs & Functions
Branching & Decision Constructs
BREAK

ANALOG_INPUT BREAK DO FOR IF INTEGER PRINT UNTIL WHILE


CONTINUE

# CONTINUE

Name:

CONTINUE

Syntax:

    CONTINUE;

Description:

Resumes execution at the top of the innermost DO-UNTIL, FOR, or WHILE loop before the exit condition is met.

Execution resumes at the start of the loop.

Example:

    INTEGER X;

    ANALOG_INPUT Y;

    X=0;

    WHILE(X\<25)

    {

        IF(Y = 69)

        {

           CONTINUE;

        }

      PRINT( “X=%d”, X );

      X = X + 1;

    }

In this example, the WHILE loop will  print the value of X if ANALOG_INPUT Y does not equal the value of 69.  When Y=69, the loop will continue executing from the top of the loop.  If Y does not equal 69, the loop will exit via the normal termination condition.

Version:

2-Series:  SIMPL v2.01.05 and later

3-Series:  SIMPL v4.02.17 and later

Language Constructs & Functions
Branching & Decision Constructs
CONTINUE

ANALOG_INPUT CONTINUE DO FOR IF INTEGER PRINT UNTIL WHILE


CSWITCH

# CSWITCH

Name:

CSWITCH

Syntax:

CSWITCH (\<expression\>)

{

  CASE (\<unique integer constant\>):

  [{]

        \<statements1\>

        [break;]

  [}]

  CASE (\<unique integer constant \>):

  [{]

       \<statements2\>

       [break;]

  [}]

  [DEFAULT:

  [{]

       \<statements\>

       [break;]

  [}]

}

NOTE: In SIMPL+ v3.01.00 and later, the 'break' statement is required to terminate the case statement block that it resides within.  If no 'break' statement exists, the program will continuing executing to the next case statement block or default statement block.

NOTE:  Many CASE statements may be used in the body of the CSWITCH.

Description:

CSWITCH is a more direct method of writing a complex IF-ELSE-IF statement. In the CSWITCH, if \<expression\> is equal to a CASE’s constant, then the statement block for that CASE value is executed. This same method would apply to as many CASE statements as are listed in the body of the CSWITCH. Note that if any of the \<statements\> blocks are only a single statement, the { and } characters on the CASE may be omitted. If no condition is met in the CASE statements, the DEFAULT case, if specified, is used.

CSWITCH has the restriction that the case statement only contains unique integer constants. CSWITCH differs from SWITCH in that the operating system is able to evaluate and execute the CSWITCH statement faster.  Therefore, you should use CSWITCH in place of SWITCH whenever unique constants are being evaluated.

Example:

ANALOG_INPUT AIN;

INTEGER X;

CSWITCH( AIN )

{

     CASE (2):

     {

          X = 0;

          break; // terminate this case statement block

     }

     CASE (3):

     {

          X = AIN;

          // continue executing to next case statement block ==\> case(5)

     }

     CASE (5):

     {

          X = X + AIN + 1;

          break;

     }

     DEFAULT:

     {

          PRINT("Unknown command %d!\n", AIN);

          break;

     }

     }

In this example, if the value of AIN is 2, X is set equal to 0. If AIN is 3, X is set AIN + AIN + 1. If AIN is 5, X is set equal to AIN+1. If AIN is any other value, an error message is printed.

Version:

X Generation:  Not Supported

2-Series:  SIMPL v2.02.10 and later

Language Constructs & Functions
Branching & Decision Constructs
CSWITCH

ANALOG_INPUT CASE CSWITCH DEFAULT ELSE IF INTEGER PRINT SWITCH


IF - ELSE

# IF - ELSE

Name:

IF - ELSE

Syntax:

    IF ( \<expression\>)

    [{]

      \<statements\>

    [}]

    [ELSE]

    [{]

      \<statements\>

    [}]]

Since \<statements\> can be an IF construct, you can string out a series of IF-ELSE-IF statements of the form:

    IF (\<expression\>)

    [{]

      \<statements\>

    [}]

    [ELSE] IF (\<expression\>)

    [{]

      \<statements\>

    [}]]

NOTE:  A final ELSE may be used to express default handling if none of the previous conditions were met.

    IF (\<expression\>)

    [{]

      \<statements\>

    [}]

    [ELSE] IF (\<expression\>)

    [{]

      \<statements\>

    [}]

    [ELSE]

    [{]

      \<statements\>

    [}]

Description:

Executes a piece of code only if its associated \<expression\> evaluates to true. Many expressions can be tested if the IF-ELSE-IF construct is used. Note that only one \<statements\> block in an IF-ELSE or IF-ELSE-IF construct is executed. In any section of the construct, if \<statements\> is only a single statement, then the { and } characters may be omitted.

Example:

    STRING_INPUT IN$[100];

    STRING Y$[100];

    INTEGER X;

    IF (IN$ = "STRING1")

    {

      X=5;

      Y$ = IN$;

    }

    ELSE

    {

      X=6;

      Y$ = "";

    }

In this example, if IN$ is equal to STRING1, then the first two statements are executed. If IN$ is a different value, then the second groups of statements are evaluated. A more complex IF-ELSE-IF construct appears as:

    IF (IN$ = "STRING1")

    {

      X=5;

      Y$ = IN$;

    }

    ELSE IF (IN$="STRING2")

    {

      X=6;

      Y$ = "";

    }

    ELSE

    {

      X = 7;

      Y$ = "ZZZ";

    }

Version:

X Generation:  SIMPL v1.20.01 and later

2-Series:  SIMPL v2.01.05 and later

Language Constructs & Functions
Branching & Decision Constructs
IF - ELSE


SWITCH

# SWITCH

Name:

SWITCH

Syntax:

    SWITCH (\<expression\>)

    {

      CASE (\<expression1\>):

     [{]

        \<statements1\>

     [}]

      CASE (\<expression2\>):

     [{]

        \<statements2\>

     [}]

     [DEFAULT:

     [{]

        \<statements\>

     [}]

    }

NOTE:  Many CASE statements may be used in the body of the SWITCH.

Description:

SWITCH is a more direct method of writing a complex IF-ELSE-IF statement. In the SWITCH, if \<expression\> is equal to \<expression1\>, \<statements1\> is executed. If \<expression\> is equal to \<expression2\>, \<statements2\> is executed. This same method would apply to as many CASE statements as are listed in the body of the SWITCH. Note that if any of the \<statements\> blocks are only a single statement, the { and } characters on the CASE may be omitted.

SWITCH has the restriction that the expressions may not be STRING expressions, they can only be INTEGER type expressions. SWITCH may only have up to 32 CASE statements in SIMPL+ Version 1.00. If more are used, a "FULL STACK" error results at the time of uploading the module to the control system. Version 2.00 has no restriction.

When a SWITCH is evaluated, the first matching CASE is used. If another CASE (or more) would have matched, only the first one is used. If no condition is met in the CASE statements, the DEFAULT case is used if specified.

Example:

    ANALOG_INPUT AIN;

    INTEGER X;

    SWITCH(AIN)

    {

      CASE (2):

      {

        X = 0;

      }

      CASE (3):

      {

        X = AIN;

      }

      CASE (5):

      {

        X = AIN + 1;

      }

      DEFAULT:

        PRINT("Unknown command %d!\n", AIN);

    }

In this example, if the value of AIN is 2, X is set equal to 0. If AIN is 3, X is set equal to AIN. If AIN is 5, X is set equal to AIN+1. If AIN is any other value, an error message is printed.

Version:

X Generation

SIMPL v1.20.01, 32 CASE statements maximum.

SIMPL v1.50.06 and later, no CASE restriction.

2-Series

SIMPL v2.01.05 and later [same features as X Generation SIMPL v1.50.06]

Language Constructs & Functions
Branching & Decision Constructs
SWITCH

ANALOG_INPUT CASE DEFAULT ELSE IF INTEGER PRINT STRING SWITCH


CEN-OEM Specific Definitions Overview

# CEN-OEM Specific Definitions Overview

The CEN-OEM has one serial port which is used to communicate with a destination device. SIMPL+ defines several special purpose variables exclusively to work with the CEN-OEM to manipulate this serial port. These variables are only valid when the file is saved with an OEM extension. Each OEM variable has a specific type (DIGITAL_INPUT, etc.) to which all the same rules as any other variable declared of that type have.

In the following examples, the "device" port is the port that talks to the equipment (device) being controlled. The "main" port is the computer port of the CEN-OEM. This port is usually used for communicating with a host computer for maintenance, but various pins may be used for other applications as follows.

[_OEM_BREAK]

[_OEM_CD]

[_OEM_CTS][][\
_OEM_DTR]

[_OEM_LONG_BREAK]

[_OEM_MAX_STRING]

[_OEM_PACING]

[_OEM_RTS]

[_OEM_STR_IN]

[_OEM_STR_OUT]

  [_OEM_BREAK]: _OEM_BREAK.md
  [_OEM_CD]: _OEM_CD.md
  [_OEM_CTS]: _OEM_CTS.md
  [\
  _OEM_DTR]: _OEM_DTR.md
  [_OEM_LONG_BREAK]: _OEM_LONG_BREAK.md
  [_OEM_MAX_STRING]: _OEM_MAX_STRING.md
  [_OEM_PACING]: _OEM_PACING.md
  [_OEM_RTS]: _OEM_RTS.md
  [_OEM_STR_IN]: _OEM_STR_IN.md
  [_OEM_STR_OUT]: _OEM_STR_OUT.md

Language Constructs & Functions
CEN-OEM Specific Definitions
Overview
CEN-OEM Specific Definitions Overview


_OEM_BREAK

# _OEM_BREAK

Name:

_OEM_BREAK

Syntax:

    _OEM_BREAK = \<expression\>;  // Write to Variable

or

Any expression that can use a variable as part of its contents.

Description:

When set to a non-zero value, causes a short break to be transmitted on the port. A Short break is 17-20 bits of logic low. When the system is done generating the short break, it will set the variable to 0. The variable may also be read back from to determine its current status. It is treated the same as a DIGITAL_OUTPUT.

Example:

    _OEM_BREAK = 1; // Generate A Short Break

Version:

CEN-OEM ONLY:  SIMPL v1.50.06 and later.

Language Constructs & Functions
CEN-OEM Specific Definitions
OEM BREAK
_OEM_BREAK


_OEM_CD

# _OEM_CD

Name:

_OEM_CD

Syntax:

Any expression that can use a variable as part of its contents.

Description:

This variable is treated as a DIGITAL_INPUT and may be read from only. CD is the acronym for Carrier Detect. When a modem is hooked up to an RS-232 port and a connection (carrier) is made, the modem typically drives this pin high to let the connected hardware know that a data connection is present. This line may be used for other purposes depending on the hardware connected to the CEN-OEM.

Example:

    PUSH _OEM_CD

    {

      PRINT("Carrier Detect Pin has gone high!\n");

    }

Version:

CEN-OEM ONLY:  SIMPL v1.50.06 and later.

Language Constructs & Functions
CEN-OEM Specific Definitions
OEM CD
_OEM_CD


_OEM_CTS

# _OEM_CTS

Name:

_OEM_CTS

Syntax:

Any expression that can use a variable as part of its contents.

Description:

This variable is treated as a DIGITAL_INPUT and may be read from only. CTS is the acronym for Clear To Send. In flow control for handshaking, a device will typically control this line, and raise it high when the CEN-OEM is allowed to transmit, and drop it low when it wants the CEN-OEM to stop transmitting.

It can also be used in other situations besides flow control, and in these situations, the CEN-OEM can monitor the status of the line directly through this pin.

Example:

    PUSH _OEM_CTS

    {

      PRINT("CTS Pin has gone high!\n");

    }

Version:

CEN-OEM ONLY:  SIMPL v1.50.06 and later.

Language Constructs & Functions
CEN-OEM Specific Definitions
OEM CTS
_OEM_CTS


_OEM_DTR

# _OEM_DTR

Name:

_OEM_DTR

Syntax:

    _OEM_DTR = \<value\>;

or

Any expression that can use a variable as part of its contents.

Description:

When set to a non-zero value,  raises the DTR pin high. This pin is typically used to signify "Data Terminal Ready", which means that the CEN-OEM is telling an external piece of equipment that it is online and ready to function. The pin may be used for other purposes (or not at all). This value is treated as a DIGITAL_OUTPUT and may be read.

Example:

    PUSH _OEM_CTS

    {

      PULSE(500, _OEM_DTR);

    }

The above example will pulse the DTR pin for 5-seconds when the CTS line goes high.

Version:

CEN-OEM ONLY:  SIMPL v1.50.06 and later.

Language Constructs & Functions
CEN-OEM Specific Definitions
OEM DTR
_OEM_DTR


_OEM_LONG_BREAK

# _OEM_LONG_BREAK

Name:

_OEM_LONG_BREAK

Syntax:

    _OEM_LONG_BREAK = \<expression\>;

or

Any expression that can use a variable as part of its contents.

Description:

When set to a non-zero value, causes the start of a break being transmitted on the port. A break is continuous logic low being generated on the port. In order to stop break generation, the variable should be set to 0. The variable may also be read back from to determine its current status. It is treated the same as a DIGITAL_OUTPUT.

If break generation is in progress and data transmission on _OEM_STR_OUT will be ignored.

Example:

    PUSH _OEM_CTS

    {

      _OEM_LONG_BREAK = 1;

      WAIT(100)

        _OEM_LONG_BREAK=0;

    }

In this example, the break is generated for 1-second when the CTS pin is driven high.

Version:

CEN-OEM ONLY:  SIMPL v1.50.06 and later.

Language Constructs & Functions
CEN-OEM Specific Definitions
OEM LONG BREAK
_OEM_LONG_BREAK


_OEM_MAX_STRING

# _OEM_MAX_STRING

Name:

_OEM_MAX_STRING

Syntax:

    _OEM_MAX_STRING = \<expression\>;

or

Any expression that can use a variable as part of its contents.

Description:

Controls the maximum embedded packet size that is transmitted on the Ethernet port. This variable is treated the same as ANALOG_OUTPUT. The default is 250 bytes but it is recommended that this value not be changed for most applications.

Example:

    _OEM_MAX_STRING = 1000;

In this example, the maximum embedded packet size is changed to 1000 bytes.

Version:

CEN-OEM ONLY:  SIMPL v1.50.06 and later.

Language Constructs & Functions
CEN-OEM Specific Definitions
OEM MAX STRING
_OEM_MAX_STRING


_OEM_PACING

# _OEM_PACING

Name:

_OEM_PACING

Syntax:

    _OEM_PACING = \<expression\>;

or

Any expression that can use a variable as part of its contents.

Description:

Controls the number of milliseconds the system will delay between sending bytes in a given string. This variable is treated the same as ANALOG_OUTPUT. The maximum value allowed is 255 (250ms). Values greater than 255 will use the lower byte of the number.

Example:

    CHANGE _OEM_STR_IN

    {

      IF(_OEM_STR_IN = "\x01\x02")

      {

        _OEM_STR_OUT = "\x02ACK\x03";

        CLEARSTRING(_OEM_STR_IN);

      }

    }

    FUNCTION MAIN()

    {

      _OEM_PACING = 10;

    }

In this example, the pacing is set to 10ms. When the string "\x01\x02" comes into the port, a 5-byte string is sent out the port. The system waits 10ms after generating each character before sending the next one.

Version:

CEN-OEM ONLY:  SIMPL v1.50.06 and later.

Language Constructs & Functions
CEN-OEM Specific Definitions
OEM PACING
_OEM_PACING

ANALOG_OUTPUT CHANGE CLEARSTRING FUNCTION IF MAIN _OEM_PACING


_OEM_RTS

# _OEM_RTS

Name:

_OEM_RTS

Syntax:

    _OEM_RTS = \<expression\>;

or

Any expression that can use a variable as part of its contents.

Description:

This variable is treated the same as DIGITAL_OUTPUT. In a program where hardware handshaking is not being used, the program may control the RTS pin for its own application. Writing a non-zero value to this variable sets the RTS pin high, writing 0 sets it low.

Example:

    PUSH _OEM_CTS

    {

      DELAY(10);

      _OEM_RTS = 1;

    }

In this program, the RTS pin will be driven high by the CEN-OEM 0.1-seconds after the CTS pin is driven high by an external system.

Version:

CEN-OEM ONLY:  SIMPL v1.50.06 and later.

Language Constructs & Functions
CEN-OEM Specific Definitions
OEM RTS
_OEM_RTS


_OEM_STR_IN

# _OEM_STR_IN

Name:

_OEM_STR_IN

Syntax:

Any expression where a BUFFER_INPUT is legal.

Description:

This variable is treated the same as BUFFER_INPUT and reflects data coming into the CEN-OEM input buffer. The buffer is 255 bytes wide.

Example:

    INTEGER I;

    CHANGE _OEM_STR_IN

    {

      FOR(I=1 to len(_OEM_STR_IN))

        IF(byte(_OEM_STR_IN, I) = 0x7F

          _OEM_STR_OUT = "\x15";

      CLEARSTRING(_OEM_STR_IN);

    }

In this example, whenever the input buffer changes, it is scanned for the character with the hex value of 0x7F. Each time it is present, a 0x15 is transmitted. The buffer is cleared at the end of the iteration.

Version:

CEN-OEM ONLY:  SIMPL v1.50.06 and later.

Language Constructs & Functions
CEN-OEM Specific Definitions
OEM STR IN
_OEM_STR_IN

BUFFER_INPUT CHANGE CLEARSTRING FOR IF INTEGER _OEM_STR_IN


_OEM_STR_OUT

# _OEM_STR_OUT

Name:

_OEM_STR_OUT

Syntax:

Any expression where a BUFFER_OUTPUT is legal.

Description:

This variable is treated the same as BUFFER_OUTPUT and reflects data coming from the CEN-OEM input buffer. The buffer is 255 bytes wide.

Example:

    INTEGER I;

    CHANGE _OEM_STR_OUT

    {

      FOR(I=1 to len(_OEM_STR_OUT))

        IF(byte(_OEM_STR_OUT, I) = 0x7F

          _OEM_STR_IN = "\x15";

      CLEARSTRING(_OEM_STR_OUT);

    }

In this example, whenever the input buffer changes, it is scanned for the character with the hex value of 0x7F. Each time it is present, a 0x15 is transmitted. The buffer is cleared at the end of the iteration.

Version:

CEN-OEM ONLY:  SIMPL v1.50.06 and later.

Language Constructs & Functions
CEN-OEM Specific Definitions
OEM STR OUT
_OEM_STR_OUT

CHANGE CLEARSTRING FOR IF INTEGER _OEM_STR_OUT


CEvent

# CEvent

**Name:**

CEvent

**Syntax:**

     CEvent event;

**Description:**

Event is a synchronization primitive which allows threads to communicate with each other by signaling. The CEvent is signaled on startup. A thread waits on the event by calling “Wait” with the specified timeout ( -1 for infinite). The timeout is specified in milliseconds and is the time that the thread will wait before returning.

Please use the return value to ensure that the thread has access to the event before continuing. Once the CEvent has been signaled, it will wake up the first thread which is blocked on this event. Once that thread has been awakened, the event is reset and subsequent calls on the “Wait” will block and return an error (if a finite timeout is specified) until the event gets signaled again. The event is signaled using the “Set” call.

**Class Members:**

class CEvent

{

FUNCTION Close();

SIGNED_LONG_INTEGER Reset();

SIGNED_LONG_INTEGER Set();

SIGNED_LONG_INTEGER Wait( SIGNED_LONG_INTEGER timeOutInMs );

}

**Class Member Description:**

**Close**

This function should be invoked when the program is done using the event. This will free out all the associated resources.

**Set**

The set function sets the state of the event to be signaled and will wake up a single thread. If there are no waiting threads, the event remains signaled until a thread attempts to wait on it, or until its Reset method is called. Calling a Set on an event which is already set does not do anything.

The function returns a 1 if successful or 0 if failed.

**Reset**

The Reset function is used to set the state of the event to be non-signaled.

The function returns a 1 if successful or 0 if failed.

**Example:**

DIGITAL_INPUTtest1,test2;

CEvent myEvent;

Function ShowEventUsage()

{

 INTEGER retVal;

      // Wait on the event to happen.

 // By default the event is signaled so the first time we come into this function the event will be signaled and we

 // will fall through. Subsequent calls will block until the event is signaled using the Set method

      // The wait takes a timeout parameter in milliseconds. Pass a -1 for an INFINITE WAIT and a 0 for no timeout

 do

 {

 print(" Waiting for event to get signaled \r\n");

 retVal = myEvent.Wait(-1);

 if (retVal = 1)

 print(" Event signaled \r\n");

 else

  print(" Event wait failed - Event not signaled \r\n");

 } until (0);

}

PUSH test1

{

 INTEGER retVal;

 retVal = myEvent.Set();

 print(" Signaling event Now. Returned %ld \r\n", retVal);

}

RELEASE test1

{

}

PUSH test2

{

}

RELEASE test2

{

}

Function Main()

{

WaitForInitializationComplete();

      // Invoke the function - event will be triggered once since it is set on startup

 ShowEventUsage();

}

**Version:**

X Generation: N/A

2-Series: N/A

3-Series: SIMPL v4.02.02+

Language Constructs & Functions
Class Objects
CEvent

CEvent Close FUNCTION INTEGER Main PUSH RELEASE Reset SIGNED_LONG_INTEGER Set ShowEventUsage WAIT Wait WaitForInitializationComplete


CMutex (Part 1)

# CMutex

**Name:**

CMutex

**Syntax:**

     CMutex mutex;

**Description:**

Mutex is a synchronization primitive that grants exclusive access to the shared resource to only one thread. If a thread acquires a mutex, the second thread that wants to acquire that mutex is suspended until the first thread releases the mutex.

A mutex object is a synchronization object whose state is set to signaled when it is not owned by any thread and non-signaled when it is owned. Only one thread at a time can own a mutex object. A mutex is available on startup and can be grabbed using the WaitForMutex  call. The thread that owns a mutex can request the same mutex in repeated calls to WaitForMutex  without blocking its execution. However, the thread must call the ReleaseMutex method the same number of times to release ownership of the mutex.

**Class Members:**

class CMutex

{

FUNCTION Close();

FUNCTION ReleaseMutex();

SIGNED_LONG_INTEGER WaitForMutex();

}

**Class Member Description:**

**Close**

This function should be invoked when the program is done using the mutex. This will free all the associated resources.

**ReleaseMutex**

This function is invoked to release the mutex. If the calling thread does not own the mutex then an exception is thrown.

**WaitForMutex**

This function is used to get access to the mutex. This is a blocking call and the thread will block until it can get access to the mutex. Once a thread has access to the mutex, it can call the WaitForMutex function repeatedly without blocking. However, the thread must call the ReleaseMutex method the same number of times to release ownership of the mutex.

While one thread has access to the mutex, another thread will block infinitely until it gets access to the mutex.

**Example:**

DIGITAL_INPUTtest1,test2;

CMutex myMutex;

CEvent myEvent;

PUSH test1

{

 INTEGER retVal;

 // By default the mutex is not owned by the callee - Use WaitForMutex to grab the mutex. There is no timeout for the WaitForMutex function

 // Use ReleaseMutex to release the mutex

      // Mutex is used to provide mutual exclusion across two functions. If one thread has the mutex another one cannot

 // We need to release the mutex from within the same thread which obtained the mutex

 print(" Inside callback for test1 - Try grabbing the mutex \r\n");

 myMutex.WaitForMutex();

print(" Inside callback for test1 - Obtained mutex. Now waiting now event which will tell us to release the mutex \r\n");

      // Wait for an event to be signaled, then we can then release the mutex

 myEvent.Wait(-1);

 print(" Releasing the mutex now \r\n");

 myMutex.ReleaseMutex();

}

RELEASEtest1

{

 print(" Setting the event now which will tell the thread to release the mutex \r\n");

 myEvent.Set();

}

PUSHtest2

{

 print(" Inside callback for test2 - Try grabbing the mutex \r\n");

 myMutex.WaitForMutex();

 print(" Inside callback for test2 - Obtained mutex Now waiting now event which will tell us to release the mutex \r\n");

      // Wait for an event to be signaled, then we can then release the mutex

 myEvent.Wait(-1);

 print(" Releasing the mutex now in callback 2\r\n");

 myMutex.ReleaseMutex();

}

RELEASEtest2

{

 try

 {

  print(" Inside release callback for test2 - Release the mutex \r\n");

 // Release mutex throws an exception if we are trying to release a mutex which we do not own

Language Constructs & Functions
Class Objects
CMutex
CMutex

CMutex Close FUNCTION INTEGER PUSH Part ReleaseMutex SIGNED_LONG_INTEGER Set Wait WaitForMutex


CMutex (Part 2)

 // This will throw an exception

 myMutex.ReleaseMutex();

 print(" Inside release callback for test2 - Released the mutex \r\n");

 }

 catch

 {

            // This is expected since the thread which owns the mutex has to release it

 print(" Exception thrown %s \r\n", GetExceptionMessage());

 // Now set the event so that we can release the mutex

 myEvent.Set();

 }

}

FunctionMain()

{

WaitForInitializationComplete();

      // Invoke the function - event will be triggered once since it is set on startup

myEvent.Reset();

}

**Version:**

X Generation: N/A

2-Series: N/A

3-Series: SIMPL v4.02.02+

CMutex FunctionMain GetExceptionMessage Part ReleaseMutex Reset Set WaitForInitializationComplete

If one thread has the mutex another one cannot

 // We need to release the mutex from within the same thread which obtained the mutex

 print(" Inside callback for test1 - Try grabbing the mutex \r\n");

 myMutex.WaitForMutex();

print(" Inside callback for test1 - Obtained mutex. Now waiting now event which will tell us to release the mutex \r\n");

      // Wait for an event to be signaled, then we can then release the mutex

 myEvent.Wait(-1);

 print(" Releasing the mutex now \r\n");

 myMutex.ReleaseMutex();

}

RELEASEtest1

{

 print(" Setting the event now which will tell the thread to release the mutex \r\n");

 myEvent.Set();

}

PUSHtest2

{

 print(" Inside callback for test2 - Try grabbing the mutex \r\n");

 myMutex.WaitForMutex();

 print(" Inside callback for test2 - Obtained mutex Now waiting now event which will tell us to release the mutex \r\n");

      // Wait for an event to be signaled, then we can then release the mutex

 myEvent.Wait(-1);

 print(" Releasing the mutex now in callback 2\r\n");

 myMutex.ReleaseMutex();

}

RELEASEtest2

{

 try

 {

  print(" Inside release callback for test2 - Release the mutex \r\n");

 // Release mutex throws an exception if we are trying to release a mutex which we do not own


Array out of bounds

# Array out of bounds

An attempt was made to access an element of an array that is outside the declared range of the array. For an array size declaration, the allowable indices are 0 through the declared size. For example, INTEGER X[10][10] would allow access to X[0][0] through X[10][10].

Language Constructs & Functions
Common Runtime Errors
Array out of bounds


Bad printf format

# Bad printf format

The MAKESTRING or PRINT functions have encountered an invalid character following the % character. The most common reason for this is when a % is actually required, %% should be used to print a single % character. Refer to MAKESTRING and PRINT for a full list of valid format specifiers.

Language Constructs & Functions
Common Runtime Errors
Bad printf format


Full Stack

# Full Stack

The SWITCH construct may only have 32 CASE statements in SIMPL+ Version 1.00. If more than 32 are used, this error appears.

Language Constructs & Functions
Common Runtime Errors
Full Stack


Library not found

# Library not found

This occurs when a module tries to call a user-defined function that exists in an external library which was specified with #CRESTRON_LIBRARY or #USER_LIBRARY. During compilation, the compiler builds a file containing the libraries to send to the control system. Typically, this could be caused by a transfer error which would be seen at load time.

Language Constructs & Functions
Common Runtime Errors
Library not found


Rstack overflow

# Rstack overflow

The Rstack that this message refers to is the Return Stack. When an event is interrupted by some means (via a process_logic statement or an implied task switch from inside a loop), information about that event is put on the Return stack, so that when the event resumes, it knows how to continue. When the event continues, the saved information is removed from the return stack.

If during this interruption the event is called again, and interrupted again, more information is saved on the return stack. The return stack is of limited size and if this keeps occurring, the Return stack will not have enough space to contain more data and this message will be issued.

For a further discussion of how to handle the programming when events are likely to be interrupted, refer to "[Task Switching]".

  [Task Switching]: ../../Task_Switching/Task_Switching_for_2-Series_Control_Systems.md

Language Constructs & Functions
Common Runtime Errors
Rstack overflow


Common Runtime Errors Overview

# Common Runtime Errors Overview

The following errors will occur at runtime. In order for these error messages to be seen, the Crestron Viewport must be open and communications with the control system (via Ethernet or the computer port) must be established.

Language Constructs & Functions
Common Runtime Errors
Runtime Overview
Common Runtime Errors Overview


Scheduler is full

# Scheduler is full

Any time-based function such as DELAY, PULSE, or WAIT will schedule an event in SIMPL+. A scheduled event will add one or more entries to the SIMPL+ scheduler. The scheduler currently supports 200 events and is global to the entire SIMPL+ system. If the scheduler is full and another event is added, this message is issued.

NOTE:  The message "Skedder Full" is issued from a SIMPL program, not SIMPL+. "Skedder full" is a similar problem, but results if too many time-based events are occurring in a SIMPL program.

Language Constructs & Functions
Common Runtime Errors
Scheduler is full


String array out of bounds

# String array out of bounds

An attempt was made to access an element of a string array that is outside the declared range of the array. Remember that for an array size declaration, the allowable indices are 0 through the declared size. For example, STRING X$[5][20] declares six strings of 20 bytes each, accessed via X$[0] through X$[5].

Language Constructs & Functions
Common Runtime Errors
String array out of bounds


Too Much RAM Allocated

# Too Much RAM Allocated

Too much RAM was allocated for the data structures. Approximately 60K is available for user data. When compiling a program, it will tell you how much memory is required for one instance of the module. Each instantiation of the module in a SIMPL program takes up that much more space. For example, if a module says it requires 100 bytes after it is compiled, two instances of that module will require 200 bytes. If this message is received, reduce the number of variables. If string or buffers have been declared overly large, this is an easy place to reduce memory requirements.

Language Constructs & Functions
Common Runtime Errors
Too much ram allocated
Too Much RAM Allocated


Compiler Directives Overview (Part 1)

# Compiler Directives Overview

Compiler directives are used by the SIMPL+ compiler to control attributes of the symbol without generating actual SIMPL+ code. They come at the beginning of the program, and are used to provide explicit instructions to the compiler. As such, directives are not part of the SIMPL+ language itself and are distinguished from actual SIMPL+ code by the pound sign (#) preceding their names.

Compiler directives are provided in the template file that is created when a new program is started. The compiler directives are as follows:

Language Constructs & Functions
Compiler Directives
Overview
Compiler Directives Overview


Compiler Directives Overview (Part 2)

| Directive                                              | Description                                                                                |
| ------------------------------------------------------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| #ANALOG_SERIAL_EXPAND                                  | This provides a way to expand, or add, inputs and/or outputs for a specified symbol.                                                                                |
| #BEGIN_PARAMETER_PROPERTIES, #END_PARAMETER_PROPERTIES | This directive is used to declare parameter properties.                                                                                |
| #CATEGORY                                              | A Category is the name of the folder in the Logic Symbols library tree where the module is shown.                                                                                |
| #CRESTRON_LIBRARY                                      | Directs the compiler to include code from a Crestron provided library.                                                                                |
| #CRESTRON_SIMPLSHARP_LIBRARY                           | Directs the compiler to include code from a Crestron SIMPL# library. The module name specified is the library filename without the CLZ extension.                                                                                |
| #DEFAULT_NONVOLATILE                                   | Program variables retain their value if hardware power is lost.                                                                                |
| #DEFAULT_VOLATILE                                      | Program variables will not retain their value if hardware power is lost.                                                                                |
| #DEFINE_CONSTANT                                       | Define a <constant_value> that will be substituted anywhere in the current source file where <constant_name> is used.                                                                                |
| #DIGITAL_EXPAND                                        | This provides a way to expand, or add, inputs and/or outputs for a specified symbol.                                                                                |
| #ENABLE_STACK_CHECKING                                 | Allows run-time stack checking to be performed on a given module. If there is a stack overflow, an error will be produced.                                                                                |
| #ENABLE_TRACE                                          | When invoked, this enables trace output. If it is not invoked no console output will be generated.                                                                                |
| #ENCODING_ASCII                                        | This directive ensures that any strings in the SIMPL+ module without explicit encoding keywords are marked with ASCII encoding.                                                                                |
| #ENCODING_UTF16                                        | This directive will ensure that any strings in the SIMPL+ module without explicit encoding keywords are marked with UTF16 encoding.                                                                                |
| #ENCODING_INHERIT_FROM_PARENT                          | This directive will ensure that any strings in the SIMPL+ module without explicit encoding keywords are marked with default encoding of the parent of this module.                                                                |
| #ENCODING_INHERIT_FROM_PROGRAM                         | This directive will ensure that any strings in the SIMPL+ module without explicit encoding keywords are marked with default encoding of the SIMPL program.                                                                        |
| #HELP                                                  | Several #HELP lines can be specified.                                                                                |
| #HELP_BEGIN … #HELP_END                                | The #HELP_BEGIN, #HELP_END pair makes it easier to create help since each line does not need a separate #HELP directive.                                                                                |
| #HINT                                                  | The #HINT shows up in the status bar and provides a short tactical clue as to the function of the symbol in the same way that Crestron-defined built-in symbols do.                                                               |
| #IF_DEFINED … #ENDIF                                   | Results in compilation of the <code> only if <constant_name> has not been previously defined.                                                                                |
| #IF_NOT_DEFINED … #ENDIF                               | Results in compilation of the <code> only if <constant_name> has not been previously defined.                                                                                |
| #IF_SERIES2                                            | Using this compiler directive will cause the compiler to only include the statements for the 2-series control system.                                                                                |
| #IF_SERIES3                                            | Using this compiler directive will cause the compiler to only include the statements for the 3-series control system.                                                                                |
| #IF_SERIES4                                            | Using this compiler directive will cause the compiler to only include the statements for the 4-series control system.                                                                                |
| #INCLUDEPATH                                           | Directs the compiler to search for User SIMPL+ and SIMPL# Libraries in the specified paths.                                                                                |
| #LARGE_STACK                                           | This is used to increase the stack size when necessary.                                                                                |
| #MAX_INTERNAL_BUFFER_SIZE                              | Sets the maximum size for the compiler’s internal string allocations.                                                                                |
| #OUTPUT_SHIFT                                          | This provides a way to arrange the inputs and outputs on the symbol graphic so that they line up and are easy to read.                                                                                |
| #PRINT_TO_TRACE                                        | When invoked, this enables converts all print statements to trace statements.                                                                                |
| #SYMBOL_NAME                                           | By specifying <name of symbol>, this name will show up on the header of the symbol in the detail view as well as in the USER SIMPL+ section of the Symbol Library.                                                                |
| #USER_LIBRARY                                          | Directs the compiler to include code from a User written library.                                                                                |
| #USER_SIMPLSHARP_LIBRARY                               | Directs the compiler to include code from a User SIMPL# library. The module name specified is the library filename without the CLZ extension. Relative or absolute path are not allowed within this directive (see #INCLUDEPATH). |

Compiler directives are provided in the template file that is created when a new program is started. The compiler directives are as follows:


PARAMETER_PROPERTIES (Part 1)

# PARAMETER_PROPERTIES

Parameters in SIMPL+, have certain attributes by default (see [INTEGER_PARAMETER],  [LONG_INTEGER_PARAMETER], [SIGNED_INTEGER_PARAMETER], [SIGNED_LONG_INTEGER_PARAMETER], [STRING_PARAMETER] for more information)

Parameters may be further restricted by declaring parameter Properties.  The general format is below.

NOTE:  Note all combinations below can or should be used at the same time.

Syntax:

#BEGIN_PARAMETER_PROPERTIES parameter_variable[, parameter_variable ...]

   propValidUnits= unitString or unitDecimal|unitHex|unitPercent|unitCharacter|unitTime|unitTicks;

   propDefaultUnit=unitString or unitDecimal or unitHex or unitPercent or unitCharacter or unitTime or unitTicks;

   propDefaultValue=default_value or "default_value";

   propList={ "value","label" },{ "value","label" };

   propBounds=lower_bound , upper_bound;

   propShortDescription= "status_bar_hint_text";

#BEGIN_PROP_FULL_DESCRIPTION

line_1

...

line_n

#END_PROP_FULL_DESCRIPTION

#BEGIN_PROP_NOTES

line_1

...

line_n

#END_PROP_NOTES

#END_PARAMETER_PROPERTIES

NOTE: The values unitString unitDecimal or unitHex or unitPercent or unitCharacter or unitTime or unitTicks used with propValidUnits and propDefaultUnit are actual keywords and should be specified accordingly.

NOTE: The keywords used to describe the properties ValidUnits, DefaultUnits, DefaultValue, List, Bound,  ShortDescription, FullDescription and Notes are prefixed by the word "prop" in this directive (e.g., propValidUnits. propDefaultUnit, etc.). This applies only to this directive.

NOTE: The keywords used to describe the units Decimal, Hex, Percent, Character, Time and Ticks are prefixed by the word "unit" in this directive (e.g., unitDecimal. unitString, etc.). This applies only to this directive.

Description:

The parameter properties directive is used to restrict the behavior of parameters, similar to the way property sheets are used in SIMPL to modify the behavior of module parameters during data entry time (i.e. when a programmer is using the module and entering data into the parameter fields).

The "parameter_variable" is the identical name used when declaring one of the 5 parameter types.  If the parameter is an array type, the [] notation is not used, just the name.  Multiple parameters may be given the same property block by listing them separated by commas.

NOTE: If the variables are arrayed elements, the usual [ ] notation should not be used.

The parameters that are introduced to SIMPL+ by this directive are similar in form and function to their existing namesakes. For example, SIGNED_INTERGER_PARAMETER possesses the same basic attributes as SIGNED_INTEGER. The new parameters are:

Parameters:

Language Constructs & Functions
Compiler Directives
PARAMETER PROPERTIES
PARAMETER_PROPERTIES


PARAMETER_PROPERTIES (Part 2)

|  |  |
|----|----|
| Parameter | Similar to: |
| Non-Arrayed |  |
| [INTEGER_PARAMETER] | [INTEGER] |
| [SIGNED_INTEGER_PARAMETER] | [SIGNED_INTEGER] |
| [LONG_INTEGER_PARAMETER] | [LONG_INTEGER] |
| [SIGNED_LONG_INTEGER_PARAMETER] | [SIGNED_LONG_INTEGER] |
| [STRING_PARAMETER] | [STRING] |
| Arrayed |  |
| [INTEGER_PARAMETER] | [INTEGER] |
| [SIGNED_INTEGER_PARAMETER] | [SIGNED_INTEGER] |
| [LONG_INTEGER_PARAMETER] | [LONG_INTEGER] |
| [SIGNED_LONG_INTEGER_PARAMETER] | [SIGNED_LONG_INTEGER] |
| [STRING_PARAMETER] | [STRING] |

NOTE: The STRING parameters only set properties for propDefaultValue, propList, propShortDescription, propFullDescription and propNotes. All other values will be ignored.

The following values are set by this directive:

Values:

NOTE:  If the parameter variable specified in a property block is an array, the attributes in the block will be applied to all elements of the array.

For example, SIGNED_INTERGER_PARAMETER possesses the same basic attributes as SIGNED_INTEGER. The new parameters are:

Parameters:


PARAMETER_PROPERTIES (Part 3)

| Value         | Description        |
| ------------- | ------------------ |
| Parameter     | Valid Unit Example |
| unitDecimal   | 25d                |
| unitHex       | 25h                |
| unitPercent   | 25%                |
| unitCharacter | 'A'                |
| unitTime      | 25s                |
| unitTicks     | 25t                |

Therefore if propValidUnits=unitHex | unitDecimal, then only "h" and "d" constants would be accepted. Any others (e.g., 25%) would be rejected.  If nothing is specified, then this field should be assumed to be unitString|unitDecimal| unitHex|unitPercent|unitCharacter|unitTime| unitTicks (i.e. all types).

propDefaultUnits

This describes the behavior of what SIMPL will do with the parameter when a programmer types in a value and hits enter (without explicitly entering a type, i.e. they enter 25 and not 25d) or type in a value and move off the parameter field without typing a type.

STRING_PARAMETERs:  propDefaultUnits can only be set to unitString, however it is implied as it is the only legal value in this case.

All other parameter types:  propDefaultUnits is a subset of what is specified in propValidUnits, and must be one of unitDecimal, unitHex, unitPercent, unitCharacter, unitTime or unitTicks.  If this value is not specified, then it will be taken from–in the following order–propDefaultValue,  propBounds, propList and propValidUnits.

NOTE: This parameter must occur after propValidUnits or a compilation error will occur.

propDefaultValue

If this is a STRING_PARAMETER, it can be either left out or set to unitString. If this is a numeric parameter, it can be any bitwise OR separated list of a combination of any or all of unitString, unitDecimal, unitHex, unitPercent, unitCharacter, unitTime or unitTicks strings. These string units consist of a number suffixed with a single character or a single character surrounded by single quotes:

| Parameter     | Valid Unit Example |
| ------------- | ------------------ |
| unitDecimal   | 25d                |
| unitHex       | 0x25               |
| unitPercent   | 25%                |
| unitCharacter | 'A'                |
| unitTime      | 25s                |
| unitTicks     | 25t                |

NOTE: For unitHex, the value will actually appear as (in this example) 25h in SIMPL.  In SIMPL+ it must be specified with a leading '0x' and no 'h' suffix.

propList

This provides a drop-down list for a parameter. The list will show the contents of the "Label" field, but when compiled, the choice in the "Label" field is converted to the value specified in the appropriate Val field.   This directive is valid for all parameter types.

For example: if propList={0x25,"Address1"}, {0x26,"Address2"} then a drop-down list is shown containing 2 choices:  "Address1 [25h]" and "Address2 [26h]".  If the Address1 is chosen, when the program is compiled, the parameter passed is actually 25h.

The units for the values must be a unit that is expressed in the propValidUnits list.

NOTE:  Since the label field is in double quotes, spaces and commas are legal.

Values should be entered as show in the following table:

| Parameter     | Valid Unit Example |
| ------------- | ------------------ |
| unitDecimal   | 25d                |
| unitHex       | 0x25               |
| unitPercent   | 25%                |
| unitCharacter | 'A'                |
| unitTime      | 25s                |
| unitTicks     | 25t                |

NOTE: If propList and propBounds are both specified, propList will take priority and propBounds will be ignored.

NOTE: If a propList is used, a propDefaultValue may still be expressed, but it MUST be one of the values entered in the prop list.

NOTE: For unitHex, the value will actually appear as (in this example) 25h in SIMPL.  In SIMPL+ it must be specified with a leading '0x' and no 'h' suffix.

propBounds

This allows the programmer a range of values that can be typed in when using the parameter field by specifying upper_bound and lower_bound.

The units must be expressed in the propValidUnits list.

This directive is not valid for STRING_PARAMETER types.

For example: If upper_bound=25d and lower_bound=1000d, then SIMPL will restrict the type-in values to between 25d and 1000d.

NOTE: For unitHex, the value will actually appear as (in this example) 25h in SIMPL.  In SIMPL+ it must be specified with a leading '0x' and no 'h' suffix.

propShortDescription

This provides a single string for the status bar hint in SIMPL and when ALT+F3 is performed on a parameter.

#BEGIN_PROP_FULL_DESCRIPTION

#END_PROP_FULL_DESCRIPTION

The text entered in this field becomes the Parameter Properties text and is a more elaborate description. This is only seen in SIMPL when the user performs an ALT+F3 on the parameter. Multiple lines can be entered.

#BEGIN_PROP_NOTES

#END_PROP_NOTES

The text entered in this field becomes the Parameter Properties text and is a more elaborate description. This is only seen in SIMPL when the user performs an ALT+F3 on the parameter. Multiple lines can be entered.

All other values will be ignored. The following values are set by this directive:

Values:

NOTE:  If the parameter variable specified in a property block is an array, the attributes in the block will be applied to all elements of the array.


PARAMETER_PROPERTIES (Part 4)

NOTE: Examples of valid and invalid parameter properties can be found [here].

NOTE: For propDefaultValue: if the user enters a value in a parameter field and then moves away from that field, the value will be assumed to be that of the specified units (if any). Therefore entering 26 in the field will assume 26 seconds if propDefaultUnit=unitTime, etc.

NOTE: For propList: the Label field is contained in double quotes and therefore allowed to contain any character including spaces and commas.

Example:

   DIGITAL_INPUT trig;

   INTEGER_PARAMETER DelayTime;

   STRING_INPUT MyString[20];

   STRING_PARAMETER DeviceCode[33];

#BEGIN_PARAMETER_PROPERTIES DelayTime

   propValidUnits=unitTime|unitTicks

   propBounds=25s,36s;

   propDefaultValue=26s;

#END_PARAMETER_PROPERTIES

#BEGIN_PARAMETER_PROPERTIES DeviceCode

   propDefaultValue="35"

#END_PARAMETER_PROPERTIES

push trig

{

   String LocalString[50];

   Delay(DelayTime);

   LocalString = MyString + "Stuff" + DeviceCode;

   print("the string is %s, The DeviceCode is %s", LocalString, DeviceCode);

}

Version:

SIMPL Version 2.10.00 or later

SIMPL+ Version 3.03.00 or later

Control System:

2 Series Only, CUZ 4.00 or later

  [INTEGER_PARAMETER]: ../Declarations/INTEGER_PARAMETER.md
  [LONG_INTEGER_PARAMETER]: ../Declarations/LONG_INTEGER_PARAMETER.md
  [SIGNED_INTEGER_PARAMETER]: ../Declarations/SIGNED_INTEGER_PARAMETER.md
  [SIGNED_LONG_INTEGER_PARAMETER]: ../Declarations/SIGNED_LONG_INTEGER_PARAMETER.md
  [STRING_PARAMETER]: ../Declarations/STRING_PARAMETER.md
  [INTEGER]: javascript:void(0);
  [SIGNED_INTEGER]: javascript:void(0);
  [LONG_INTEGER]: javascript:void(0);
  [SIGNED_LONG_INTEGER]: javascript:void(0);
  [STRING]: javascript:void(0);
  [here]: ../../Examples.md

Multiple lines can be entered. </p></td>
</tr>
</tbody>
</table>


#ANALOG_SERIAL_EXPAND

# #ANALOG_SERIAL_EXPAND

Name:

#ANALOG_SERIAL_EXPAND

Syntax:

    #ANALOG_SERIAL_EXPAND \<value\>

Description:

This provides a way to expand, or add, inputs and/or outputs for a specified symbol. It is useful when you want to expand the number of outputs for a given input, expand the number of inputs for a specific output, expand both the inputs and outputs or for a variety of other combinations.

NOTE: Expansion directives can only be used in conjunction with an array input.

Values:

|  |  |
|----|----|
| Value | Description |
| Separately | This is the default value and allows for expansion of both inputs and outputs, in no particular order, on a given symbol. |
| OutputsWithParams | This allows a single input to be expanded into a number of outputs. |
| InputsWithOutputs | This allows the combined expansion of inputs and outputs. If you add an input, an output is also automatically added. |
| InputsWithParams | This allows the expansion of the number of inputs for a single output. |
| AllWithAny | This allows for the expansion of both inputs and outputs, but unlike InputWithOutputs, the relationship between inputs and outputs doesn't have to be one to one. |
| PWithIxorO | This allows for the expansion of either inputs or outputs. |

Example:

    #ANALOG_SERIAL_EXPAND OutputsWithParameters

A single input would be expanded into a specified number of outputs.

Version:

SIMPL+ Version 2.10.00 or later

Control System:

2 Series Only

Language Constructs & Functions
Compiler Directives
ANALOG SERIAL EXPAND
#ANALOG_SERIAL_EXPAND


#CATEGORY

# #CATEGORY

Name:

#CATEGORY

Syntax:

    #CATEGORY "\<category ID\>"

Description:

A Category is the name of the folder in the Logic Symbols library tree where the module is shown. To specify a category for a SIMPL+ module, the #CATEGORY directive must be used with a category specified in the list shown in the SIMPL+ Editor. Just click "Edit" then "Insert Category" for a list of categories. Choose one and the appropriate line of code is added to your SIMPL+ program.

Example:

    #CATEGORY "6" // Lighting

If a category ID does not exist in the Symbol Tree Category list, the SIMPL+ module will default to the Miscellaneous category type.

Version:

X Generation:  Not Supported

2-Series:  SIMPL v2.01.05 and later

Language Constructs & Functions
Compiler Directives
CATEGORY
#CATEGORY


#CRESTRON_LIBRARY

# #CRESTRON_LIBRARY

Name:

#CRESTRON_LIBRARY

Syntax:

    #CRESTRON_LIBRARY "\<Crestron Library Name\>"

Description:

Directs the compiler to include code from a Crestron provided library. The module name specified is the Crestron Library Filename without the CSL extension.

Example:

    #CRESTRON_LIBRARY "SpecialIntegerFunctions"

Directs the compiler to include the Crestron Library "SpecialIntegerFunctions.csl" from the Crestron SIMPL+ Archive.

Version:

X-Generation

SIMPL v1.50.06

SIMPL v2.01.05 and later, Global variables can no longer be declared within Crestron Library (.csl) files.

2-Series

SIMPL v2.01.05 and later [Same features as X Generation SIMPL v2.01.05]

3-Series

SIMPL v4.00.00 and later

4-Series

SIMPL v4.14.06 and later

Language Constructs & Functions
Compiler Directives
CRESTRON LIBRARY
#CRESTRON_LIBRARY