CDX SCRIPT LANGUAGE REFERENCE

Synopsis: describes the CDX script language as used by laboratory instrument script writers. Other documents and reports describe the requirements and implementation of the language and its support tools.

RELATED DOCUMENTS

  1. [cdxan.doc] provides an overview of CDNext technology.
  2. [cdscfg.doc] configuration language reference manual.
  3. [cdsuser.doc] script language user's guide.
  4. [fscseq.doc] describes the compiler script dictionary design, implementation, and usage.
  5. [evfsq.doc] describes event-triggered scripts.
  6. [faults.doc] describes structured fault reporting.
  7. [cdxdbg.doc] script debugger user's guide.
  8. [aswmin.doc] system and software design meeting minutes.
  9. [reports.doc] compiler and analyzer program design and implementation.

HYPERLINKS

This document contains hyperlinks that enable jumping to related topics. Source points are identified by square braces plus underline. For example [Hyperlinks] jumps to the title of this section. The left arrow on the web toolbar returns to the source point. Square braces without underline are used to identify optional command parameters, and are unrelated to hyperlinking.

[Usage]

[Language Components]

[Error Reporting]

[Command Groups]

[Script control group]

[Loop group]

[VAR group]

[If group]

[Actuate group]

[Motor group]

[Echo group]

[Read-Write group]

[Monitor group]

[Miscellaneous group]

[Test and development group]

 

 

USAGE

EXECUTION UNITS

The analyzer comprises one or more execution units, which communicate with each other and with the system master. The system master is generally a PC computer running a data station or development program, but it may also be a simple interface to a remote control unit. The purpose of the system master is to download programs, scripts, and commands to the analyzer and to receive results from it.

Each execution unit serves as a slave to a preceding (upstream) master. The first (or only) unit is a slave to the system master. An execution unit may also serve as a master to subsequent (downstream) units. Masters can issue commands to their slaves. They also route programs, scripts, and commands from the system master to their slaves. Slaves cannot issue commands to their masters. If a unit serves as both a master and a slave, its master is automatically a master to all of its slaves. A unique ID character identifies each execution unit. The system master has ID '0' and its immediate slave has ID '1'.

SCRIPTS AND COMMANDS

The script language is primarily intended for use in scripts, which are compiled to efficient message forms. The system master downloads compiled scripts to the analyzer, which stores them for subsequent execution. Many of the script commands can also be used interactively, in which the system master sends one compiled command to the analyzer. The analyzer executes the command immediately, often returning some message to the system master. Nearly all commands can be used in scripts. Relatively few commands are useful for interactive operation but most of them are not specifically prohibited. A few commands are specifically rejected for interactive operation because they have no interpretation outside of a script.

The script language comprises a base set of commands, which all execution units recognize, plus additional specialized commands, for example those related to counting and gathering cell data, which only certain units recognize. The base set includes communication, mechanical, and fluid control commands. In addition to the native (base and specialized) commands, the configuration file can define macro commands, using native language components, to simplify usage or hide system-specific details.

 

LANGUAGE COMPONENTS

BASIC ELEMENTS

The script language comprises the following elements:

  1. Words. Words contain from 1 to 31 characters, which may be letters, numerals, or underscore. The first character must be a letter. The language is case-insensitive.
  2. Integer numbers. These are 0 through 65535 (2 ^ 16 – 1) in most cases but up to 4294967295 (2 ^ 32 – 1) in a few cases. The default radix (number base) is 10. Binary and hexadecimal numbers are support by adding a B (or b) or H (or h) suffix to the number. Hexadecimal numbers must begin with a numeral (0 if necessary). In this document, integers of unspecified size are called int or integer, while int8, int16, and int32 are used to identify integers comprising 1, 2 or 4 bytes.
  3. Floating point numbers. These are any combination of numerals that contains a period. The period may not appear at the beginning of the number. A values less than 1 requires a leading 0, for example 0.71. The script compiler rejects any construct that begins with a period, suggesting that a leading 0 be added (it doesn't know for sure the script writer's intent). The compiler does not warn about excessive precision. For example, the typical time resolution for most targets is 5 msec, but a wait delay of 2.0000080 seconds is accepted without warning. In this document, floating-point numbers are called floats.
  4. ByteArrays are quoted strings and comma- or space-delimited lists of numbers ranging from 0 to 255. Strings are quoted using the " character. Any value can be included in a string using the escape sequence \xhh, where hh comprises any two hexadecimal characters. Two characters are required even if the first one must be 0. Characters quoted with the ' character may be included in the number list. Examples are "My command", "\X1BV6\X0D", 'T' 'h' 'i' 's' 1, 2, 3. The ASCII value is taken for characters in strings and single-quoted characters in numeric lists.
  5. Replaceable parameters. These are any 8-character word with the prefix @. As the system master downloads the script to the analyzer, it replaces each of these with a value defined in the system master (usually through the user interface). The replacement may be BOOL (True/False), integer (1, 2, or 4 bytes), or string, depending on the script command. If the system master doesn’t define the parameter or defines the parameter as a different type, it will report an error. Replaceable parameters are accepted only as specified in particular commands; they are not a general substitute for BOOL, integer, or string in all contexts.
  6. Operators.
    1. The standard arithmetic operators, - + / * < > <= >= (minus, plus, divide, multiply, less than, greater then, less than or equal, greater than or equal) are accepted in arithmetic expressions involving both integer and floating point numbers. Not equal != is also accepted in both cases.
    2. Parentheses ( ) can be used for grouping and overriding precedence in floating point or integer arithmetic (but not logical) expressions.
    3. The modulus operator %, left (<<) and right (>>) shift operators, and bit-wise exclusive-or ^ are accepted in expressions involving integers but not floating point numbers. The characters & and | are accepted as bit-wise and and or in expressions involving only integers.
    4. | and & represent or and and in logical expressions involving bit testing. They cannot be mixed in one expression. For example if Door Open & Red On & Mixer Up is a legal statement but if Door Open & Red On | Mixer Up is not legal. They also cannot be used to construct compound statements, for example move motorX to 100 & move motorY to 200. The script language doesn’t support any form of compound statement.
    5. The char = represents assignment or equality test depending on context. In tests of sensor conditions = is optional. For example, if Door = Open and if Door Open are synonymous.
    6. Commercial-at @ is used in certain commands (e.g. count) and as the replaceable parameter prefix but not as an arithmetic operator.
    7. In most lists, elements may optionally be separated by a comma or space.

  7. Arithmetic expressions are supported only by VAR, move motor, wait motor, if motor, and channel device assignment commands. Logical expressions involving & and | are support only by IF commands.
  8. VARs. Unlike general-purpose languages, the script language does not support user-defined variables. However, it does support pre-defined variables, VAR0 through VAR99. Each of these is an independent 16-bit word that can only hold an integer. VAR0 through VAR7 are local to each executing script, while the rest are global.
  9. Comments are text that the compiler skips over. The script language affords four comment forms. The forms // and ; (semicolon) mark the beginning of a comment that extends to the end of the line. The forms /* ... */ and COMMENT ... ENDCOMMENT identify as comment all enclosed text. These two-part forms allow comments to occur in the middle of comments and over multiple lines. They are particularly useful to comment-out blocks of code under development. The /**/ form can be used anywhere, for example to hide text in the middle of a statement. COMMENT and ENDCOMMENT must be the first text on the line in which they appear. Any trailing text on a line containing either of these words is considered comment. "To-end-of-line" comments may occur in the text enclosed by either of the two-part comment forms. /**/ comments may occur in the text enclosed by COMMENT-ENDCOMMENT but not vice versa. Thus, there is a hierarchy of comment forms: COMMENT-ENDCOMMENT can hide anything; /* */ can hide text and to-end-of-line comments, which can hide only trailing text. To keep options open, the lowest comment form that is adequate should be used.
  10. Line continuation. Each script statement (command) must be presented on only one conceptual line (identified by CR/LF) of essentially any length. To support script source file formatting, a conceptual line can encompass multiple physical lines using a single backslash \ at the end of a line to be continued. Line continuation can be used repeatedly in one statement and nearly anywhere except in quoted strings.
  11. Command concatenation. Multiple commands can be concatenated into a single conceptual line using the line compaction operator '~'. This would serve no purpose in a normal script, but is useful in the define [Define] command, which, otherwise, would be able to assign only one command to an alias. For example, define PrepShearValve open Vent ~ move ShearValve CCW might be used to define PrepShearValve as an alias for two commands that are repeatedly used in combination.
  12. Optional statement components. The script language contains two kinds of optional components, functional and cosmetic. Functional components change the command. Cosmetic components serve only to make the source statement more readable. For example, in the statement VAR0 + 1.5 seconds, seconds is functional whereas in wait 1.5 seconds it is cosmetic. In this document, any language element enclosed in square braces (without underline-- with underline indicates a hyperlink) is optional. Optional elements may also be identified as such by description.

INTRINSIC WORDS

Intrinsic words are commands and parameters that are native to the script language and don’t change for different target units (analyzer in general or specific execution units within one analyzer). Most intrinsic words are reserved and can only be used for their intended purpose. The following list comprises the intrinsic words. This list is a portion of the output from the script compiler in response to the command line option –xwords, which can also be invoked by the script make target words and through the script debugger's edit menu. A few of these words (e.g. watch, stop, return) serve as command or parameter. The unreserved intrinsic words may be used as configuration words. For example open is a command but may also serve as a user-defined device state name.

.......... NATIVE COMMANDS ..........

BEGIN BREAK CLEAR CLOSE

COUNT DEBUGREAD DEFINE DELETE

ECHO ECHOLOG ECHOSTATE ECHOTITLE

ELSE END ENDIF ENDLOOP

FORK GATHER GET HALT

IF INITIALIZE LOOP MESSAGE

MOVE OPEN POSITION POWER

PRAGMA PRESET RAMP RAMPDEF

READ REPORT RESET RETURN

SEND SET SIMULATE STOP

TERMINATE TESTMOTOR TESTSYSTEM UNIT

VAR0-99 WAIT WATCH WRITE

.......... RESERVED PARAMETER NAMES .......

ALL ALLFAULTS AS BINARYBUBBLES BYTE BYTES CCW

CENTER CHANNEL CONFIG CW

CYCLE DONE EXCLUSIVE FAILOK

FALLING FALSE FAST FAULTREPORTER

FAULTS FOR FOREVER GATHERDONEACK

GOING HANDLE HARD HOLD

IDLE IN LEADING LEVEL

LINEAR LIST LOAD LONG

LONGS MAX MAXIMUM MAXLEVELGOING

MECHANICAL MONITOR MOTORS MOVING

NOHANDLER NOT OTHERS PEEK

POWERDOWN PROCESS REAL RECOIL

REPORTFAULTS RETURN RISING SAFETY

SAYDONE SAYSTAT SECOND SECONDS

SLAVECOM SLEW SLOW STEP

STEPPERS STEPS STOP SYSTEMSTATUS

TEXT THROUGH TIME TIMEOUT

TO TOMSECS TOSECONDS TRAILING

TRUE UNTIL VERSION WATCH

WORD WORDS

.......... UNRESERVED NATIVE WORDS ........

UP DOWN ON OFF

LOW MEDIUM HIGH OPEN

ALPHA OFF NoFluid Air

Fluid Blood WarnActuatorRead WarnSensorWrite

WarnLiteralHardVar FailFatalErrors HideEcho ClearRamps

.......... NATIVE TESTSYSTEM FUNCTIONS ........

BusFault IllegalInstruction AddressAlign DivideBy0

ComFault Irq FsqText Fsqs

Procs PowerDowns TqFreeSpace HeapStack

Scripts WipeNonVol TextReply EchoTime

IgnoreCmdFail ReportJoins ReportDones

 

CONFIGURATION WORDS

Configuration words are specific target system resources and definitions declared in the configuration file. The script compiler reads this file before compiling any script. From a script writer’s point of view, intrinsic and configuration words are nearly indistinguishable. There are only two differences. One is that most intrinsic words are reserved and cannot be redefined in a script. For example, even if ShearValve is defined in the configuration, define ShearValve something is legal while define wait something is rejected by the compiler, because wait is a reserved intrinsic word. The other difference is in error reporting by the compiler. When an intrinsic word is used incorrectly in a place where a configuration word could appear, the compiler often reports a general syntax error. If an incorrect non-intrinsic (configuration or undefined) word appears in this same place, the compiler usually reports a more specific error, such as "Up is not a state of PaddleSwitch".

Configuration words convey intuitive meanings. For example, Empty represents the same physical situation regardless of whether this means that a given sensor’s value is 1 or 0. In fact, one sensor’s Empty condition may be 0 and another’s 1 in the same configuration file. Although most intrinsic words cannot be used as configuration words, certain very common words, such as Open, have been singled out for exception. While OPEN may serve as a command or configuration name, CLOSE is a reserved command name. Closed may be used as a configuration name.

The majority of configuration words define physical or logical (such as memory-based flags) devices that can be used in script statements. Physical and logical devices are defined by the following characteristics:

  1. Type of device.
  2. Device name.
  3. Physical/logical address.
    1. This comprises two elements: space, the logical and/or physical group to which the device belongs; address, a number which uniquely identifies the device within the group. The script compiler accepts any space number from 0 to 31 and any address number from 0 to 256, including values that the execution unit does not support.
    2. Some script commands accept more than one device in a single statement, but, in all cases, these devices must be in the same space.
    3. Scripts normally should be written using the device name, but the equivalent space:address tuple is also accepted. Also, the numeric address alone is accepted, in which case the space number is implied by the type of command and the order of declarations in the configuration file.
      1. The default space for FLAGS, SENSORS, and ACTUATORS is the first such space declared in the configuration.
      2. If the script command is preset, or clear, the default space is FLAGS.
      3. If the script command is set, open, or close, the default space is ACTUATORS.
      4. If the script command is if, the default space is SENSORS.

    4. A script statement that identifies a device by number (tuple or address form) can access a device for which there is no definition in the configuration file. In fact, even if a corresponding device has been defined, none of its characteristics are available to the command statement. For example, the device can only be set or tested for 1/True or 0/False.

  4. Names of conditions that the device can assume (i.e. set and/or tested).
  5. Additional device-specific information, which is normally not visible to the script.

Device types range in complexity from single bit flags to complex behavioral entities (a few of which, such as GATHERS, are purely behavioral and don't express addressing information). The following device types are supported.

  1. MOTORS
    1. Stepper
    2. DcMotor is unidirectional.
    3. BiMotor is can go clockwise (CW) or counter-clockwise (CCW).
    4. TriMotor can go to CW or CCW extremes or to one or more fractional positions (but it is not a stepper).

  2. ACTUATORS are single-bit devices that are normally only written. Reading them is legal but evokes a warning from the compiler unless this warning is turned off by the script statement pragma off WarnActuatorRead. In some analyzer systems, the state of an ACTUATOR may be read back from the same address where it is written. In others, the analyzer program translates the read address to a different address where the state can be read. In other systems, reading an ACTUATOR simply makes no sense.
  3. SENSORS are single-bit devices that are normally only read. Writing to them is legal but evokes a warning from the compiler unless this warning is turned off by the script statement pragma off WarnSensorWrite. Writing to certain (or all SENSORS) is used for system diagnostics and program testing. Typically, physical sensors can’t be written, but the analyzer program may write to a memory image of the sensors that can appear to be the real sensors in certain (or all) situations. In some cases, such writes may establish values only temporarily.
  4. FLAGS are single-bit logical devices that are normally read and written. They are used by scripts to record and exchange status information between each other and with the underlying analyzer control program.
  5. STATES are multi-value logical devices that can be read and written. STATE devices are unique in that they have no name but are instead identified by a set of mutually exclusive states, for example OpenMode and ClosedMode. In the words listing (shown below) the number associated with each STATE identifies the set to which it belongs. Scripts do not use this number, but a script programmer may need to consult it to determine the full range of a state set.
  6. MULTISTATE devices are multi-value physical devices that can only be written.
  7. COM devices are intelligent devices, such as barcode readers, that communicate with the unit through text-based messages.
  8. CHANNEL devices are physical devices comprising identical addressable subunits that can be read and/or written with a numeric value. CHANNEL devices encompass a wide variety of entities, for example an explicit device like an ADC or a general-purpose bus. It is legal to define a CHANNEL device with only one channel. This is often done to create a subclass of a more generic CHANNEL device. For example, the CHANNEL device Psi9 may be defined as channel 42 of the CHANNEL device Adc. Psi9 inherits from the Adc all characteristics not specifically stated in its own declaration. The script compiler uses the declared CHANNEL characteristics to accept or reject script statements. The characteristics are:
    1. Channel range, e.g. 1-32.
    2. Value range, which may be continuous or discrete (enumerated), e.g. 0 – 4095 or 1,2,4, etc.
    3. Access type: write-only, read-only, read-write.

  9. CONFIGS are logical devices that define specific uses of nonvolatile memory. An analyzer contains only one CONFIG space, so CONFIGS are not identified by space:tuple but rather by a single character ID. All CONFIGS assume a string value ranging in length from one to 240 characters. Each CONFIG’S declaration (in the configuration file) limits the maximum length as well as the set of allowable characters to ALPHA (only A-Z and a-z), ALNUM (ALPHA plus 0-9), a specific set of characters, or no limit. CONFIGS are set to or tested against a byteArray. Typically, the legal values for a CONFIG are defined in the configuration file by aliases that include the quotes, which are, therefore, not used in scripts. For example, Opticon is defined as "1", allowing the statement set BcReader = "1" to be stated as the more self-explanatory set BcReader = Opticon.
  10. GATHERS are purely behavioral devices that express the methods to be used for collecting cell data. Both gather, which collects list mode data, and count, which counts each cell, operate on GATHERS defined in the configuration file. A GATHER declaration tells the collection name, e.g. Reds, the channels to be captured, the maximum number of cells to gather (no limit on count), whether to decimate and, if so, by how much and the selection criteria (essentially a notch filter). For instruments that have multiple independent cell monitoring means (e.g. optics benches and impedance cells) the declaration identifies the bench used for the gather.
  11. MSG devices are unusual devices for which the script language has no specific syntax. An MSG device may be unique to a particular instrument, it may be new and under development, or it may represent an unusual component of a real or virtual device, for example an initialization message.

The configuration file also supports arbitrary text definitions, similar to the macro capability of many computer languages. Any word defined in a DEFINE section in the file becomes a global alias that is available to all scripts. The compiler substitutes the assigned text wherever the word appears (only in scripts-- not in the configuration file itself). This affords a means of extending the script language for a particular instrument without affecting the generality of the base language. For example, all instruments may have some set of valves to open in an emergency but the specific set may vary. Each instrument's set could be defined, e.g. as EmergencyValves, in its configuration file. Then the statement open EmergencyValves could be a universal command, adapted to any instrument simply by recompiling scripts.

The capability to define words in the configuration file can also be used to create complete instrument-specific commands. For example, most instruments have some means of setting gains and thresholds for cell detection, but the specific details can vary widely. These variations can be hidden from scripts by a definition in the configuration file, for example SetRBCThreshold = write 52000H word @RBCT. Obviously, knowing to write a replaceable parameter value to a specific hardware address, as this does, requires intimate knowledge of the instrument. In fact, the primary purpose of the configuration file is to bridge the script and hardware domains.

The following is an excerpt (the entire configuration portion) from the script compiler’s words option output for a CD3200-class instrument configuration file. In this table the number in square braces identifies the unit that directly controls the device and the phrase in parentheses tells information relevant to the device type as follows:

The list for a different instrument would be similar but not identical. Words listed as Extended TestSystem Functions (none in this example), Times, and Faults are not devices but instrument-specific facilities. Their names become part of the script language similarly to device names. Extended TestSystem Functions name instrument-specific functions of the testSystem [testSystem] command. Times and Faults are parameters for, respectively, set time [set time] and report [report] commands. Macro Commands are definitions located in a COMMAND section of the configuration file. They are treated as standard definitions except for being listed as Macro Commands (as well as Definitions) in the words listing.

.......... MACRO COMMANDS .............

AnyOcfault ClearFatalFaults ClearOcFaults FatalFaults

ForceCloseP2 ForceCloseP3 ForceCloseV2 ForceOpenP2

ForceOpenP3 ForceOpenV2 NoOcfault OcFaults

ServoP2 ServoP3 ServoV2 Set10dThresh

SetRBCThresh

.......... EXTENDED TESTSYSTEM FUNCTIONS .............

.......... MOTORS .............

[1]YVALVE (BiMotor #25) [1]ShearValve (TriMotor #24)

[2]M0 (Stepper #0) [2]M1 (Stepper #1)

[2]M2 (Stepper #2) [2]M3 (Stepper #3)

[2]M4 (Stepper #4) [2]M5 (Stepper #5)

[2]M6 (Stepper #6) [2]M7 (Stepper #7)

[2]M8 (Stepper #8) [2]M9 (Stepper #9)

[2]TowerProbe (Stepper #0) [2]TowerSpinner (Stepper #1)

[2]PeriPump (Stepper #2) [2]SpareMsmStepper (Stepper #3)

[2]PeriPump1 (Stepper #2) [2]PeriPump2 (Stepper #3)

[2]Syringe1 (Stepper #4) [2]Syringe2 (Stepper #5)

[2]Mixer (Stepper #6) [2]Tower (Stepper #8)

[2]PeriPump3 (Stepper #9) [2]SampInjMtr (Stepper #1)

[2]HgbLyseMtr (Stepper #2) [2]WbcLyseMtr (Stepper #3)

[2]RbcDilMtr (Stepper #4) [2]OpenProbeMtr (Stepper #5)

[2]FillLineMtr (Stepper #7) [2]SPINNER (DcMotor #1)

.......... ACTUATORS .............

[1]VpmSol1 (OPEN/CLOSED) [1]PresPump (Off/Servoed)

[1]OpenP2 (ON/OFF) [1]CloseP2 (OFF/ON)

[1]OpenP3 (ON/OFF) [1]CloseP3 (OFF/ON)

[1]VacPump (Off/Servoed) [1]OpenV2 (ON/OFF)

[1]CloseV2 (OFF/ON) [1]ShearValveOn (OPEN/CLOSED)

[1]LPM81 (OPEN/CLOSED) [1]RackAdvance (Retracted/Extended)

[1]LPM82 (OPEN/CLOSED) [1]LoadArms (Retracted/Extended)

[1]LPM83 (OPEN/CLOSED) [1]Lifter (UP/DOWN)

[1]LPM84 (OPEN/CLOSED) [1]LPM91 (OPEN/CLOSED)

[1]Gripper (OPEN/CLOSED) [1]LPM92 (OPEN/CLOSED)

[1]UnloadArms (Retracted/Extended)[1]LPM93 (OPEN/CLOSED)

[1]LPM94 (OPEN/CLOSED) [2]GS2Release (OPEN/CLOSED)

[2]TowerDoorRelease (OPEN/CLOSED) [2]LoaderLed (ON/OFF)

.......... MULTISTATE DEVICES .............

[1]SecPress2 (Opened/Servoed/Closed)

[1]SecPress3 (Opened/Servoed/Closed)

[1]SecVac2 (Opened/Servoed/Closed)

.......... COM DEVICES .............

[2]Barcode (Rack/RackPos/Sample)

.......... SENSORS .............

[1]PaddleSwitch (Pressed/NotPressed)[1]RbcDilPress (Over/Ok)

[1]SvInput (NoFluid/Fluid) [1]CsDoor (Open/Closed)

[1]SvOutput (Blood/Air) [1]Va1WetSens (Wet/NotWet)

[1]Va2WetSens (Wet/NotWet) [1]SvInSim (NoFluid/Fluid)

[1]SvOutSim (Blood/Air) [1]SensWbcLyse (NotEmpty/Empty)

[1]SensHgbLyse (NotEmpty/Empty) [1]SensDilSheath (NotEmpty/Empty)

[1]SensWasteLevel (Full/NotFull) [1]SensDilLevel (Full/NotFull)

[1]SensSheathLevel (Full/NotFull) [1]V2Valve (Open/Closed)

[1]Vacuum (On/Off) [1]P3Valve (Open/Closed)

[1]P2Valve (Open/Closed) [1]Pressure (On/Off)

[1]Vac2 (Dry/Wet) [1]Vac1 (Dry/Wet)

[2]LoaderSwitch (Pressed/Unpressed) [2]M0F1 (0-F/1-T)

[2]M0F2 (0-F/1-T) [2]M1F1 (0-F/1-T)

[2]M1F2 (0-F/1-T) [2]M2F1 (0-F/1-T)

[2]M2F2 (0-F/1-T) [2]M3F1 (0-F/1-T)

[2]M3F2 (0-F/1-T) [2]M4F1 (0-F/1-T)

[2]M4F2 (0-F/1-T) [2]M5F1 (0-F/1-T)

[2]M5F2 (0-F/1-T) [2]M6F1 (0-F/1-T)

[2]M6F2 (0-F/1-T) [2]M7F1 (0-F/1-T)

[2]M7F2 (0-F/1-T) [2]M8F1 (0-F/1-T)

[2]M8F2 (0-F/1-T) [2]M9F1 (0-F/1-T)

[2]M9F2 (0-F/1-T) [2]Syringe2Home (NotHome/index)

[2]MixerHome (Home/NotHome) [2]TowerHome (NotHome/index)

.......... CHANNEL DEVICES .............

[1]IoBus (Channels=0-31. Range=0-255)

[1]InBus (Channels=0-31. Range=0-255)

[1]TestChan (Channel=2. Range=0-255)

[1]BeepVolume (Channel=12. Range=0-255)

[1]BeepFreq (Channel=13. Range=0-255)

[1]Dac (Channels=1-32. Range=0-4095)

[1]Gain (Channels=3-6. Range=0-4095)

[1]Prescale (Channels=1-4. Range=1,2,4,8)

[1]Adc (Channels=0-99. Range=0-4095)

[1]AdcBipolar (Channels=0-99. Range=0-4095)

[1]Psi9 (Channel=42. Range=0-4095)

[1]HgbSample (Channel=40. Range=0-4095)

[1]HgbReference (Channel=40. Range=0-4095)

.......... FLAGS .............

[1]VA1Wet (0-F/1-T) [1]VA2Wet (0-F/1-T)

[1]ShearValveFault (0-F/1-T) [1]RbcDilOverPres (0-F/1-T)

[1]WbcLyseEmpty (0-F/1-T) [1]HgbLyseEmpty (0-F/1-T)

[1]DilSheathEmpty (0-F/1-T) [1]WasteFull (0-F/1-T)

[2]BcReady (NotReady/Ready)

.......... STATES .............

[1]OpenMode (#0) [1]ClosedMode (#0) [1]LatexMode (#1) [1]DefaultMode (#1)

[1]NeoMode (#2) [1]CntMode (#2) [1]MeasureNormal (#3)[1]TestMam (#3)

[1]TestSpm (#3) [1]SvCw (#4) [1]SvCcw (#4) [1]SvCenter (#4)

[1]SvFractional (#4)[1]SvUnknown (#4) [1]SvBusy (#4) [1]SvMoveFail (#4)

[1]SvSensFail (#4) [2]OpenMode (#0) [2]ClosedMode (#0) [2]LatexMode (#1)

[2]DefaultMode (#1) [2]NeoMode (#2) [2]CntMode (#2)

.......... ECHO-TITLES .............

EchoTitle1 EchoTitle2 Aspirating RemoveSpecimen

Dispensing Counting Rinsing

.......... ECHO-STATES .............

EchoState1 EchoState2 BeginData PaddlePressed

Ready NoTube

.......... GATHER/COUNTS .............

Reds Whites Noc TestReds

TestWhites Gauss

.......... CONFIGURATIONS .............

Number Kind BcReader

.......... TIMES .............

TxTime RxTime RxIntraTime

.......... FAULTS .............

MIX_VERT_INACTIVE MIX_VERT_ACTIVE LIFT_UP_INACTIVE LIFT_UP_ACTIVE

LDEMPTY_ACTIVE UNLOAD_NOT_FULL UNLOAD_NOT_WARN TUBEPOS3_ACTIVE

TUBEPOS4_ACTIVE TOWERCOVER HOME_ACTIVE TOWERDOOR

HOME_INACTIVE NOSAMPBC BADHEIGHT NOTUBE

COMPLETED XCYCLING UNLOADFULL UNLOADNEARFULL

UNLOADPROBLEM MIX_LOST_TUBES TUBEPOSITION ADVANCE_GAINED_TUBE

ADVANCE_LOST_TUBE RACK_IN_MIXZONE BC_RACK BC_TUBE_POS

MIX_TIMER_EXPIRED BC_READER_FAILURE MIX_LOST_RECOVERED LOAD_EMPTY

NoSample ShortSample BubbleSample RbcDilOverPressure

Va1WetFault Va2WetFault ShearValveFault WbcLyseFault

HbgLyseFault DilSheathFault WasteFault NoFault

CsDoorOpen TestFault

.......... DEFINITIONS ...........

AnyOcfault = WasteFull | HgbLyseEmpty | WbcLyseEmpty | DilSheathEmpty

BC_CHECKDIGIT = @B00

BC_CODABAR = @B03

BC_CODE128 = @B04

BC_CODE39 = @B01

BC_GOT_BADSAMPLE = 14

BC_GOT_POS = 12

BC_GOT_RACK = 11

BC_GOT_SAMPLE = 13

BC_I2OF5 = @B02

BCREADSTATUS = VAR98

BLOCK_FORK = VAR97

ClearFatalFaults = clear 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 ~ clear 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31

ClearOcFaults = clear 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 ~ clear 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63

COMFAULT_NONE = 1

CS = "C"

FatalFaults = VA1Wet VA2Wet ShearValveFault RbcDilOverPres

FAULT_MASTER_CRC = 2

FAULT_MASTER_CRC_FATAL = 3

FAULT_MASTER_DUMP = 14

FAULT_MASTER_DUMP_FATAL = 16

FAULT_MASTER_OVER = 10

FAULT_MASTER_OVER_FATAL = 11

FAULT_MASTER_UNDER = 6

FAULT_MASTER_UNDER_FATAL = 7

FAULT_SLAVE_CRC = 4

FAULT_SLAVE_CRC_FATAL = 5

FAULT_SLAVE_DUMP = 15

FAULT_SLAVE_DUMP_FATAL = 17

FAULT_SLAVE_OVER = 12

FAULT_SLAVE_OVER_FATAL = 13

FAULT_SLAVE_UNDER = 8

FAULT_SLAVE_UNDER_FATAL = 9

ForceCloseP2 = set OpenP2 Off CloseP2 On

ForceCloseP3 = set OpenP3 Off CloseP3 On

ForceCloseV2 = set OpenV2 Off CloseV2 On

ForceOpenP2 = set OpenP2 On CloseP2 Off

ForceOpenP3 = set OpenP3 On CloseP3 Off

ForceOpenV2 = set OpenV2 On CloseV2 Off

GAIN0 = GAIN 6

GAIN10 = GAIN 5

GAIN90 = GAIN 4

GAIN90D = GAIN 3

LA = "A"

LdrLoadState = VAR20

LdrTestState = VAR21

LdrUnldState = VAR22

LEVEL_INFORMATION = 2

LEVEL_INITIALIZE = 5

LEVEL_LOG = 1

LEVEL_REBOOT = 6

LEVEL_RESET = 4

LEVEL_RESUME = 3

Microscan = "2"

NO_RACK = 0

NoOcfault = Not WasteFull & Not HgbLyseEmpty & Not WbcLyseEmpty & Not DilSheathEmpty

OcFaults = WasteFull HgbLyseEmpty WbcLyseEmpty DilSheathEmpty

Opticon = "1"

PRESCALE0 = PRESCALE 1

PRESCALE10 = PRESCALE 2

PRESCALE90 = PRESCALE 3

PRESCALE90D = PRESCALE 4

PROBE_STATUS = VAR96

ServoP2 = set OpenP2 Off CloseP2 On

ServoP3 = set OpenP3 Off CloseP3 Off

ServoV2 = set OpenV2 Off CloseV2 Off

Set10dThresh = set DAC 1 = @TR10

SetRBCThresh = write 51000h @RBCT

SL = "S"

SpeakerVolume = DAC 1

THRESHOLD = DAC 8

TRIGGER_EVENT = VAR99

WatchTimeout = 0FFFFh

 

ERROR REPORTING

The analyzer configuration file affords the script compiler a means of determining whether a command statement makes sense as well as whether it follows the language rules. Although devices can be identified by address for convenience during development, this should be avoided for production scripts because it cripples the compiler's ability to guard against unrealistic but syntactically correct commands.

Generally, the analyzer does not guard against unrealistic commands, assuming that the compiler has already done this. The program does refuse to execute commands that would damage itself, such as writing to an address beyond the known range of some resource (memory or I/O) but it doesn't, for example, refuse a command to open a non-existent valve at a supported I/O address.

The compiler can issue warnings and errors. In both cases, it tells the file name, line number, and specific description of the problem, often telling what would be legal. It always continues compiling the source file after a warning but, by default, stops at the first error. Pragma off FailFatalErrors can be used to tell the compiler to continue after errors. The compiler translates defined words (by replacing each word with its assigned text) that occur in a statement before evaluating the statement as a whole. Consequently, it reports any errors it encounters in terms of the translated text instead of the words that appear in the statement. To reduce confusion, if an erroneous statement contains any defined words, the compiler reports this fact and displays the definition of the last defined word in the statement prior to the error. This is usually the source of the error even if the statement contains other defined words.

Not all command errors can be detected at compile-time, especially those involving run-time value range limits. In all of these cases, the analyzer program blocks bad commands and reports the error in the general message type DM_SCRIPT subtype SCRIPT_FAIL. The DM_SCRIPT message comprises two parts. The first part contains binary information for a master unit (or system master) to track the status of its slave. The second part is an English explanation of the problem. The first character of this text tells the type of error as follows:

FAIL_MISSINGREM ('a') Remote script isn't loaded.

FAIL_STARTREM ('b') Unable to start remote script.

FAIL_MISSING ('c') Local script missing.

FAIL_START ('d') Unable to start local script.

FAIL_BADMSG ('e') Error in message syntax e.g. unrecognized type.

FAIL_BADPARM ('f') Parameter value out of range.

FAIL_NOTREADY ('g') Legal command but the physical object is not responding correctly.

FAIL_INTERNAL ('h') Internal program error, e.g. illegal function argument value.

FAIL_BADGATHER ('i') Started gather at wrong time.

Although the message type and subtype characters are intended for machine communication, they are readable. The text is intended only for script and program developers. The message is formatted as follows:

For example:

71.....EcUnit1,NOSCRIPTOK@2,Script 268 doesn't exist,cmdfsq.c@619

'7' identifies this as a DM_SCRIPT message.

'1' identifies the first unit as the master (in this case the command is local).

'E' is SCRIPT_FAIL.

'c' identifies the problem as a missing script referenced in a fork (or related) command.

"Unit1" is the execution unit.

"NOSCRIPTOK" is the script in which the failure occurs.

"@2" tells that second command in the script is the failure.

"Script 268" tells the ID of the missing script. The script dictionary associates this with a name.

"cmdfsq.c@619" tells the source file and line number of the unit's program where the failure is detected. This is normally of value only to system programmers but the source code may help to clarify the command's problem and suggest a correction.

In most cases, a command failure causes the offending script to abort. When a direct master-to-slave (interactive) command fails, the master script is usually aborted. The slave and master will issue separate error reports in this case. For example, the following pair of messages may be generated if master Unit1 tries to test an unsupported I/O address in slave Unit2.

7~~~~~~EfUnit2,Master,Bad IfBit address 31:7,bitops.c@122

71.....EfUnit1,MASTERIFBITFAIL@1,Remote IF predicate error,fsqman.c@759

In this case, the slave does not know the specific source of the command-- only that it is some upstream master-- so it fills the binary portion of the message with '~' and reports the source as "Master". The second message results from Unit1 recognizing that the slave's failure relates to one of its own scripts, MasterIfBitFail. Unit1 aborts this script and issues the error message.

All run-time script errors are reported in a DM_SCRIPT message. Most command errors are reported as subtype SCRIPT_FAIL. The major exception is fork command failure. In the following command descriptions, run-time error messages that are type SCRIPT_FAIL are shown with only the fail subtype and problem text. The actual messages include all of the details described above.

 

COMMAND GROUPS

The command groups are:

  1. [Script control group]. Commands for loading, running, and terminating scripts. These include unit, begin, end, terminate, fork, return, wait, halt, and delete.
  2. [Loop group]. This includes loop, endloop, and break.
  3. [VAR group]. This comprises VARxx, where xx is 0 through 99, with one of the following operators: = | ^ & << >> + – * / %.
  4. [If group]. This includes if, else, and endif.
  5. [Actuate group]. These commands set the state of devices defined in the configuration file. In most cases the devices are physical elements of the analyzer, but this group also includes logical devices, such as STATES and FLAGS. This group includes the commands clear, preset, open, close, and set.
  6. [Motor group]. This includes, position, move, stop, power, ramp, rampdef, and testmotor. Also see [Initialize].
  7. [Echo group]. These commands cause the analyzer to immediately send a message to the system master. Other commands may cause messages to be sent during the course of execution but do not entail a direct command-response sequence (except read, which is grouped with write and motor test commands). These include echo, echolog, echostate, echotitle, report, get, and send.
  8. [Read-Write group]. Commands for reading and writing normal or special memory. This group includes read and write.
  9. [Monitor group]. These commands control complex processes. Executing a command starts the process, which eventually ends due to time, condition, or command. The command that starts the process does not wait for the process to end. This group includes count, gather, stop gather, sample, watch, and stop watch.
  10. [Miscellaneous group] includes initialize, define, message, and reset.
  11. [Test and development group]. Most of these commands are used only for testing the analyzer’s script interpreter. These include version, pragma, simulate list, simulate watch, testsystem, and debugread.

The commands, in alphabetic order are:

COMMAND GROUP

[BEGIN] Script Control

[BREAK] Script Control

[CLEAR] Actuate

[CLOSE] Actuate

[COUNT] Monitor

[DEBUGREAD] Test and Development

[DEFINE] Miscellaneous

[DELETE] Script Control

[ECHO] Echo

[ECHOLOG] Echo

[ECHOSTATE] Echo

[ECHOTITLE] Echo

[ELSE] If

[END] Script Control

[ENDIF] If

[ENDLOOP] Script Control

[FORK] Script Control

[GATHER] Monitor

[GET] Echo

[HALT] Script Control

[IF] If

[INITIALIZE] Miscellaneous

[LOOP] Script Control

[MESSAGE] Miscellaneous

[MOVE] Motor

[POSITION] Motor

[OPEN] Actuate

[POWER] Motor

[PRAGMA] Test and Development

[PRESET] Actuate

[RAMP] Motor

[RAMPDEF] Motor

[READ] Read-Write

[REPORT] Echo

[RESET] Miscellaneous

[RETURN] Script Control

[SAMPLE] Monitor

[SEND] Echo

[SET] Actuate

[SIMULATE LIST] Test and Development

[SIMULATE WATCH] Test and Development

[STOP] Motor

[STOP GATHER] Monitor

[STOP WATCH] Monitor

[TERMINATE] Script Control

[TESTMOTOR] Motor

[TESTSYSTEM] Test and Development

[UNIT] Script Control

[VARxx (0-99)] Var

[VERSION] Test and Development

[WAIT] Script Control

[WATCH] Monitor

[WRITE] Read-Write

SCRIPT CONTROL GROUP

[unit], [begin], [end], [terminate], [fork], [return], [wait], [halt], and [delete]

UNIT

SYNTAX

The word Unit acts as a command when it appears outside of a script. The format for the Unit command is:

unit = unitName or unit unitName

unitName is a name defined in the configuration file by the statement:

UNITS = unitName1 unitName2 ...

unitNames are, for example, APU, MSM, CDM, TOWER, and LOADER.

DESCRIPTION

The unit command does not generate a command to be executed by the analyzer, but, instead, tells the script compiler to generate code for the named unit. This allows one configuration file to describe multiple execution units, which is convenient if the target instrument contains multiple processors.

All scripts in the source file following a unit command are compiled for that unit and are identified in the script dictionary (used for fork and wait) as belonging to that unit unless their begin statement declares otherwise. The unit declaration may also appear as a parameter in begin, fork, and wait commands.

One source file may contain any number of unit commands. Each one replaces the previous default unit. The unit command may not appear in the body of a script.

EXAMPLES

unit = APU

unit MSM

ERRORS

Compile Time

"Syntax error" if unitName isn’t listed in the configuration file.

 

BEGIN

SYNTAX

begin scriptName scriptOptions

scriptName comprises one to 31 alphanumeric characters or underscore. The first character must be a letter.

scriptOptions comprises zero or more of the following attribute clauses (in any order):

unitDeclaration comprises:

unit name or unit = name

name is as described for the unit command.

faultHandlerDeclaration comprises:

handle faultRange

faultRange is one of the following:

faultLow and faultHigh are integers ranging from 1 to 32,000 or fault names.

levelDeclaration is safety, monitor, config, mechanical, or process

reportDeclaration is reportFaults or faultReporter

sayDoneDeclaration is the single word sayDone

DESCRIPTION

FaultHandler

A faultHandlerDeclaration causes the script to be registered as a handler for the identified fault or range of faults. Registration occurs when the analyzer loads the script. The first currently loaded script to have registered as a handler for a specific fault is started, if possible, when that fault occurs. If the script can't be started, the next script to have so registered is tried. This continues until one such script is successfully started. If no such script can be started or if no script has registered to handle the specific fault, the script with the narrowest range that includes the fault will be started. For example, if script A registers as a handler for faults 10 through 20, script B as a handler for faults 10 through 15, and no script handles fault 13, if fault 13 occurs, script B will be invoked regardless of which script, A or B, was loaded first. The first script registered as a handler of allFaults is tried if no more specific handler is loaded.

Scripts that handle a range of faults may need to know the trigger event. The numeric ID of the trigger event is passed to the script in its local VAR0. As described in VAR commands, the script can test any VAR for a literal numeric value or a fault name (as well as many other value types). Certain events may cause additional information to be passed in VAR1 and VAR2. Therefore, for scripts whose begin statement includes a faultHandlerDeclaration, the compiler does not issue a warning if the value of VAR0, VAR1, or VAR2 is taken before the corresponding VAR has been locally assigned a value.

Scripts that register themselves as fault handlers are, in all other respects, normal and may be invoked by another script. They are sometimes called event-triggered scripts, which only means that they may be invoked in response to an unplanned event. An event-triggered script that may sometimes be invoked by another script or interactively should not test the initial value of VAR0 (or VAR1 or VAR2) because it is random in this situation.

Fault handling scripts may do nothing more than send a report message to the system master, but they usually also take care of safety issues, such as halting mechanical and process level scripts. Consequently, they are normally assigned the Safety level.

Level

The level of a script determines under which circumstances it should be prevented from starting or should be forced to stop. For example, a script that watches for a safety hazard should be able to run at any time, even if a potentially dangerous mechanical fault has been detected; but a mechanical script should be immediately halted in the same situation.

The levels form a hierarchy, with lower levels indicating greater independence from current circumstances. The level characteristics are as follows:

In the absence of a level declaration, the default level is mechanical.

Report

Some faults, such as mechanical failure, should be reported to the system master as soon as they are detected. For these, any script can report specific faults to the system master using report commands. For other faults, such as vacuum accumulator wet, it is more appropriate to wait for the current sample cycle to finish before reporting. Depending on circumstances, it may be better to have the system master specifically request a complete fault report (comprising one report message for each active fault) or to have one sent automatically when a script, particularly a process type, finishes.

A script declared as a faultReporter is registered as such when downloaded to the analyzer. The last such script downloaded (there really should be only one) will be started whenever all analyzer faults are to be reported to the system master. Using a script for this allows fluidic and mechanical faults to be defined entirely in the script domain rather than being embedded in the analyzer program.

The fault reporter script is started by any of three methods:

  1. By being forked by name as an ordinary script.
  2. By the system master sending a get faults command (this could also be embedded in a script).
  3. By being automatically started when any script declared as a reportFaults type finishes by terminate or end. If a reportFaults type script is halted or terminates due to command error, the fault reporter is not started.

Normally, only process level scripts are reportFault type and one safety or monitor level script is faultReporter type. The script compiler does not allow a script to be declared as both reportFaults and faultReporter.

SayDone

At certain script execution points, the analyzer has to synchronize with the system master. One way that a script can indicate that it has reached a particular point is by an echoState command. Another is by reporting that a script has finished. When a script started directly by the system master finishes, the analyzer automatically sends a done message, identifying the script by name and numeric ID. This behavior cannot be turned off-- if the system master is not interested then it should accept but ignore the done message.

Sometimes the termination of an indirectly started script is important. A done message is sent for any script declared with the sayDone attribute. For program development, the testSystem ReportDones command causes a done message to be sent for all scripts.

EXAMPLES

begin Checks Apu monitor faultReporter

begin SLF Cdm handle 40 through 156

begin SampleLoaderFaultHandler \

safety \

handle MIX_VERT_INACTIVE through BC_READER_FAILURE

begin Rinse sayDone

begin Count process reportFaults

begin SvFaultHandler safety handle ShearValveFault

ERRORS

Compile Time

 

END

SYNTAX

end

DESCRIPTION

End indicates the end of a script. The end command may not appear at any other point in a script. End and terminate execute similarly but terminate can appear only within the body of the script (and only in an if block) and does not indicate the end of the script’s code.

EXAMPLES

begin SomeScript

echo "Some Script"

end

ERRORS

Compile Time

TERMINATE

SYNTAX

terminate

DESCRIPTION

The terminate command immediately stops the script in which it appears. While terminate may be predicated on some abnormal event, terminate is not, in itself, considered abnormal. All details of script termination are the same whether a script executes to its end command or stops at a terminate. For example, if a script has the sayDone attribute, a done message will be issued in either case. Terminate can only appear in an if block. The if block may appear in a loop body so that the terminate command, in effect, stops the loop (as well as the entire script).

EXAMPLES

if LdEmpty = Empty

terminate

endif

loop 0

if LdFull = Full

terminate

endif

endLoop

ERRORS

Compile Time

 

FORK

SYNTAX

fork unit scriptName optReturn optFailOk

unit is blank or unit = unitName or unit unitName

unitName is as described under unit command.

scriptName comprises one to 31 alphanumeric characters or underscore. The first character cannot be a number.

optReturn is blank or return varId.

varId is VAR0 through VAR99.

optFailOk is blank or failOk.

DESCRIPTION

The fork command causes the target script (scriptName) to begin executing. The target script is called child and the script that forks it parent. The child script is local if it executes on the same unit as the fork command; otherwise, it is remote. A master unit can fork any script resident in any of its slaves. Slaves may not fork their masters' scripts.

If the child is local, its first command will execute either immediately before or immediately after the next parent command, i.e:

  1. The parent's fork command will finish before the child executes its first command.
  2. The parent will not execute two commands after fork before the child executes its first command.
  3. The child will not execute its first two commands before the parent executes its next command.

If the child is remote, the parent is very likely to execute at least its next command before the child begins executing (this is not guaranteed and should not be assumed). The parent may execute many commands before the child begins executing. If a remote fork fails, the parent is aborted (unless it has failOk); the error message tells both its current command number and that of the failed fork. Return, wait return, wait going, and wait done commands can be used to provide tighter parent-child synchronization.

A fork is not the same as a function or subroutine call in other languages. No arguments are passed to the child script; the child script does not "return" (the return command has a different interpretation); and the parent script does not wait for the child but immediately advances to its next command.

The target script must exist in the script dictionary when the script compiler translates a fork statement. There are several ways that this can be ensured:

  1. The target script is located earlier in the same source file as the fork.
  2. The target script is located in another source file that has been compiled at least once before the compiler encounters the fork.
  3. The script dictionary builder, sequpdat.exe, has been executed. The script make system includes a target called "D", which invokes sequpdat to build a dictionary for all of the normal scripts (FLIST and FSLIST in the script domain’s targets.mac). Unlike the script compiler, sequpdat can process scripts in any order. Sequpdat builds an entirely new dictionary, while the script compiler only incrementally adds new scripts to an existing dictionary. If script files contain no forward referencing fork statements, it is not necessary to use sequpdat or to modify targets.mac. It is not necessary to use sequpdat repeatedly even if there are forward references. A script remains registered in the dictionary unless it is removed from the source file and sequpdat is invoked to build a fresh dictionary.

Unit

The unit clause is used only if more than one unit contains a script of the target name. Otherwise, the script compiler knows the execution unit and automatically generates the appropriate command message. In any given system, each unit performs unique tasks. Consequently, multiple instances of a particular script name are rare. However, certain generic names, such as PrepareForShutdown, might be applied to scripts that execute on different units. These scripts may or may not be identical.

A fork statement should not include a unit clause unless it is required, as it reduces flexibility. Without the unit clause, the parent doesn't have to know which unit is responsible for executing the child script. The script writer doesn't have to worry about a script not executing as expected because of a missing unit clause. If one is needed, the compiler will reject the command and explain the problem.

Return

The return clause (and wait return command) works in concert with return commands in the child script to synchronize the parent and child. In the return clause, the parent identifies a VAR to receive the value sent by the child whenever it executes a return command (return means to return a value, not control flow). If the VAR is 0 through 7, one of the parent's local VARs will receive the return value and no other scripts will be able to see it. Otherwise, the VAR is global and all other scripts will be able to see the return value.

The return value automatically appears in the VAR named by the parent whenever the child executes a return. Therefore, in most cases, the parent would not use the VAR for other purposes. However, the parent might initialize the VAR to some value that it knows the child will not return, in order to be able, at some later point, to determine whether the child had returned anything. The child might indicate its progress in a series of steps by returning a different value at the end of each step. The parent could track the child's progress by watching for changes in the VAR (especially in conjunction with wait return). Another possible use is for the child to tell the parent the status of the job it was forked to perform. For example, one value could indicate that the child had finished the job and another that there was some kind of failure preventing the child from finishing.

If a script containing fork statements with returns to local VARs terminates without all related children returning a value at least once, a run-time warning is sent to the system master. No warning is sent for global VARs in a similar condition, because the purpose may be to make the return available to scripts other than the terminating parent.

FailOk

The standard execution unit can run up to 16 local and 16 remote scripts at once. If a fork would exceed one of these limits, the command fails. A fork command also fails if the script isn't resident in the execution unit, or if the requirements explained in the begin command are violated. As with nearly all other commands, if a script's fork statement fails, the would-be parent is aborted unless the statement includes failOk. In any case, it is not aborted if the child, once successfully started, experiences its own problems. Whether or not the would-be parent is aborted, a fork failure always causes a message to be sent to the system master.

FailOk should be used sparingly. It is primarily intended for system recovery scripts to fork scripts in slaves whose status is unknown.

EXAMPLES

fork TestBubbles

fork Msm PrepareForShutdown

fork Apu PrepareForShutdown

fork HomeTower return VAR80

fork RecoverControl return VAR7 failOk

ERRORS

Compile Time

Run Time

 

RETURN

SYNTAX

return value

value is varId or int16

varId is VAR0 through VAR99.

DESCRIPTION

The return command is used by a child script (see fork command [FORK] ) to transmit values to its parent or to all scripts in the execution unit of the parent. The value is either a literal number or the current value of a VAR, which may be local to the child or global. The value is written into the VAR specified by the parent's fork return clause. It is independent of any VAR returned by the child. For example, if the child is started by the statement fork scriptName return VAR0 and the child executes return VAR0, the source and destination VARs are entirely unrelated.

Although a return (source) VAR may be global, for a local child this would not usually make sense, as the parent and child both see the VAR without using the return mechanism. However, this might be legitimately used where the child has several possible return sources that are not all global VARs. Returning a global VAR is more likely in a remote child, even though a master can directly read the slave's global VARs, because the master generally should not be intimately aware of the slave's global VAR usage. Obtaining a value from the slave through the return mechanism instead of directly reading a global VAR yields more easily maintained scripts.

A child script can contain any number of return statements. Each one transmits a new value to the destination VAR. This capability can be used to indicate the slave's progress through a series of steps. At each return, the value might increment to identify the completed step, but this is not necessary in many cases, because a series of wait return commands (for details see wait return) in the parent can track the slave.

If a script that has not been forked with a return clause executes a return command, nothing happens. Thus, a script may be forked by one parent that wants returns or by another that doesn't care.

EXAMPLES

return 10

return VAR6

return VAR80

ERRORS

Compile Time

 

WAIT

SYNTAX

wait waitType

waitType is one of the following:

forOrUntil is for or until.

optForUntil is blank, for, or until

time is a floating point or int16 number of seconds.

varId is VAR0 through VAR99.

gatherState is gather or gatherDoneAck

OptGatherType is blank or the name of a GATHER defined in the configuration file.

optWaitLimit is blank or maximum time [second[s]]

maximum may be abbreviated as max

scriptEvent is going, return, or done.

optUnit is blank or the name of an execution unit.

motor is the name of a stepper motor or of a motor type that provides position feedback, such as a TriMotor (Shear Valve).

motorCondition is blank, idle, > motorPosition, or < motorPosition.

motorPosition is an int16, except 0 or 65535, or an arithmetic expression whose result is between 0 and 65535 exclusively.

DESCRIPTION

The wait command (except for wait reset) causes the script to not advance until the specified condition is met. The conditions are based on time, (other) script execution, gather state, or motor state or position.

Wait For and Until

Each process (and the script attached to that process) has two independent timers, one for delay and one for rendezvous. The delay timer, used by wait for commands, provides a momentary pause. It is reset at each use and, therefore, affords no measure of accumulated time. The rendezvous timer, used by wait until commands, is used to stop the script from advancing until a certain point in time has been reached. This point is relative to the timer’s reset time, which is when the script starts and whenever the wait reset command executes. Wait until commands do not reset the rendezvous timer, which, therefore, tells accumulated time.

Except for the command wait for 0.0, wait for always causes the script to delay. Wait until delays the script only if the rendezvous time has not yet been reached. Wait until typically is used to support parallel operations within one script. For example, a mechanical/fluidic process is started and the rendezvous timer reset (wait reset). Then the script carries out other activities. When these are done, to be sure that the first process has had sufficient time to complete, the script uses a wait until time command.

Wait for and until both require that a time be specified. This can be a literal value, such as 2.5 seconds (seconds is optional), or a VAR. When a VAR is specified for the time, the VAR does not contain a time in seconds but in system tick counts. The script writer should not normally be aware of the relationship between time and ticks, although this is declared in the configuration file. Although legal, it would be unusual for a script to assign a literal value to a VAR that will be used in a wait command. More likely, the VAR will be directly assigned a time value, for example VAR3 = 1.5 seconds, or indirectly assigned a tick value via a watch, which can assign to a VAR the tick count of the duration of a process, such as the time required for a fluid sample to move between two points. Subsequently, the VAR’s value (normally after some mathematical manipulation) is used to time an aspiration period, automatically adjusted (by the VAR) to the sample’s mobility.

The maximum tick count that a VAR can support is 65,535. Virtually all execution units have a 5 msec. tick period, enabling the VAR to support a maximum time of about 5.5 minutes. This is sufficient for nearly all conceivable uses of wait for but not necessarily of wait until. A useful wait until command would require the VAR to first be assigned the current value of the script's rendezvous timer, by VARxx = time. Then some offset from this would be added, e.g. VARxx + 1.5 seconds, to produce a future time relative to the current timer. This will fail in a script that executes continuously without resetting the rendezvous timer, because the timer's value will exceed the VAR's range. For continuously operating scripts (generally safety and monitor level) that need to perform a periodic task, the if time command is easier to use and safer than wait until VAR.

Timeout

The optional wait limit available to the wait gather, count, script event, and motor commands sets a time limit (in seconds, from the start of the command) on the wait. Without this, the script can wait indefinitely (hang). During development, it might be preferable for the script to hang, because the testSystem Scripts command can be used to tell the current command location of all executing scripts (including any stuck in an endless wait). If the wait times out and the script simply advances to the next command, there is no direct indication of what has happened.

Production-ready scripts typically should not simply advance to the next command after a timeout but should instead engage an alternate instruction path. This can be done using the command if timeout. Whenever a wait command ends by timeout, the script's timeout flag is set. It remains set until the next wait command.

Wait Gather, GatherDoneAck, and Count

Wait gather causes the script to not advance until the current gather parse (not raw data collection) is done. This does not mean that all of the data has been sent to the system master. Wait gatherDoneAck causes the script to not advance until the system master acknowledges receiving the gatherDone message, which means that it has received all of the data related to the gather. If the event has already occurred before the wait command is executed, the script will immediately advance.

The optional gather type is used to stop the gather in a specific bench of an instrument that has multiple optics benches. The GATHER definition (in the configuration file) identifies the bench associated with the GATHER name. For such an instrument, if the wait statement does not include the gather type then the script will wait until the gather is done for all active benches. For an instrument that has only one bench, a gather type is accepted but not necessary.

Wait count causes the script to not advance until the current cell count process (started by count command) is done. If there is no count process going, the script advances immediately. No optional time limit is supported or needed, as this is already provided in the count statement.

Wait Script Event

Wait going, return, and done cause the script to not advance until the specified event occurs or the optional timeout has been reached. Wait going and done can target any script, whether a child of the waiting script or not. If the target script of wait return has not been forked directly by the waiting script or has terminated, this command will cause a run-time error and the script will be aborted.

If the target script is already executing when a wait going command executes, the test is immediately true and the script advances to the next command. Local child scripts are going immediately when they are forked. After the parent's fork command, a remote child script is in a state of limbo until the slave returns a message (DM_SCRIPT) indicating that the child has started. During this limbo period, the target script is not considered to be going. Wait going without a time limit for a remote script that is not in limbo or going evokes a run-time error.

Wait going requires some care for reliable use. If the target script executes quickly and terminates, it is possible for the wait going to not see that the script ever ran. Any script that executes for at least .5 second will be detected but less than this is indeterminate. To guarantee that a fast script has executed, a return command could be used or the script could post its status directly to a global VAR. Another solution would be to define a status FLAG or STATE in the configuration file. The script's parent would set the FLAG or STATE to one value before forking the script, which would subsequently change the value to signal that it did execute.

Wait done tests for the target script not currently executing. Although the word done implies knowledge that the script has executed, there actually is no run-time history. Typically, a script is known to have been forked, so wait done means what it implies. As with wait going, a situation may require an absolute guarantee that the script has executed in some recent time period. The same solutions apply here as well. Remote child scripts in a state of limbo are considered to be not done. The limbo state will be resolved by a status message from the slave. If the remote script's status advances to going, wait done will continue to wait. If the fork fails or the script subsequently fails or finishes, the done condition will be met. As far as wait done is concerned, failure and successful execution and termination are indistinguishable.

Wait return tests for the child to return a value to its parent. Wait return for a script that is not a direct child or for a child that was not forked with a return clause, evokes a run-time error. Multiple returns are supported by a handshake between parent and child. When the child is forked, the return event is false. At the first return, the event becomes true; the next (or current) wait return is immediately released; and the event reverts to being false. Consequently, the next wait return before another return will see the event false. By restoring the event state to false at the conclusion of each wait return, the parent can track the child's progress. However, as with wait going, child execution times under .5 seconds may go undetected. For example, if the parent engages each step of a process in lockstep with child returns and the child executes two returns less than .5 seconds apart, the parent may not see the first one. One solution to this problem is for the child to return progressive values, which the parent uses to advance its state. If the child gets two steps ahead of the parent, the parent just executes its next two steps and catches up. This assumes that it is safe for the child to advance faster than the parent. If this is not the case, a better solution would be to divide the child into several scripts, which the parent can fork sequentially.

Wait Motor

Wait motor motorCondition causes the script to not advance until the named motor has achieved the specified condition or until the optional timeout occurs. Wait for a non-stepper is allowed only if the named motor is of a type that provides position feedback. There is only one such type, the Trimotor, e.g. ShearValve. The script compiler rejects all other types.

For all motor types, blank motorCondition specifies that the motor not be moving. This is the only condition accepted for non-steppers. For steppers, this means that the motor is off (which occurs only briefly during initialization), holding, or idling. The other conditions accepted for steppers are idle and > or < a particular position. If a motor is holding or idling, it is not moving. The primary purpose of the position conditions is to afford a means to engage some activity predicated on a motor's position without requiring the motor to stop at that position. Although most steppers have a limited range, the compiler accepts any int16 value for the position parameter except 0 and 65353, or an arithmetic expression whose result is between 0 and 65535 exclusively. An arithmetic expression may contain floating point as well as integer numbers and the operators +, -, /, *, (, and ). The compiler reduces the expression to an int16. It is the responsibility of the script writer to determine positions that actually make sense for a particular motor.

Typically, only one unit in a system directly controls steppers. Scripts executing on this unit directly test motor conditions. Masters to this unit can wait for motors by sending it remote wait requests. This is entirely transparent to the source script, as the compiler and execution units sort out the details. However, the distinction can become evident if one or more masters try to post more simultaneous remote waits than the direct motor controller can handle. Typically, this is 16 (which is the same as the number of simultaneous scripts typically supported by one unit). Scripts waiting for the same motor to reach the same condition will automatically share a remote wait even if they execute on different masters. Otherwise, each waiting (master) script consumes one of the motor controller's remote waits.

For testing a motor's condition without wait, see the if motor condition command [IfMotorCondition].

EXAMPLES

wait for 7 seconds

wait for 7.0

wait reset

wait until 4.0 seconds

wait until 4.0

wait for VAR7

wait until VAR45

wait going AdvanceLoader

wait going AdvanceLoader maximum 2 seconds

wait return FluidStep

wait return FluidStep max 0.5

wait done Msm ResetSystem max 3.0

wait done HomeTower

wait until gather

wait for gatherDoneAck

wait until gather maximum 10.0 seconds

wait gatherDoneAck reds

wait gather reds max 5 seconds

wait count

wait until count

wait for SampInjMtr

wait HgbLyseMtr idle max 3 seconds

wait until TowerProbe > (8000 + 250) * 2

wait Probe < 4000h max 2.5 seconds

wait for ShearValve

ERRORS

Compile Time

Run Time

(All messages are DM_SCRIPT-SCRIPTFAIL)

 

HALT AND DELETE

SYNTAX

halt optUnit targetScript optLevel sayWhat

delete optUnit targetScript optLevel sayWhat

optUnit is blank or the name of an execution unit.

targetScript is the name of a script or others or all.

optLevel is blank or safety, monitor, config, mechanical, or process

sayWhat is blank or sayStat or sayDone.

DESCRIPTION

The halt command immediately stops one or more scripts. Basically, halt others halts all scripts other than the one in which the command occurs and halt all adds that one as well, i.e. a script can halt itself.

The unit option would typically be used to halt all of the scripts in a slave. It would also be needed if the master and slave have a script by the same name. In this case, neither script could be halted without naming the unit; i.e. there is no default in this case. When invoked interactively (from a master unit to a slave) an others argument is illogical, so the script compiler automatically (and silently) converts others to all when the command is remote.

If targetScript names a specific script, only this script is halted. If this script doesn't exist, the compiler rejects the statement. However, it is not considered an error if the script isn't resident (or going) when the command executes, in which case nothing happens.

The optional level argument specifies the lowest level of scripts that will be halted in response to halt all or others. As explained in the begin command [ScriptLevel] the lower a script's level, the less susceptible it is to being halted and prevented from starting. If the level argument is blank, the level defaults to monitor, i.e. only scripts with levels of monitor, config, mechanical, or process are halted. Any level argument is ignored if targetScript names a specific script; i.e. a named script is halted without regard to its level.

SayDone causes a script done message to be issued just before the script is halted. See begin command sayDone option [BeginSayDone] and testSystem reportDones [TestsystemReportDones] for alternate means of issuing done messages. This option operates only if the script is named; i.e. only one done message can be issued. The compiler issues a warning, but doesn't reject the statement, if sayDone is included in a halt others or all statement. In this case, the halt command will execute but will not issue a done message. A done message will not be sent for a script that is halted without sayDone even if the script itself is defined with the sayDone option.

SayStat causes a script status message telling the name and current command number of the one named or all (if others or all) executing scripts to be issued just before the scripts are halted. Halting/deleting with sayStat is not the only means of generating the script status message. The testSystem Scripts [TestSystemScripts] command also causes it to be issued but without any other effect. SayStat and sayDone are mutually exclusive. If the statement includes both, the compiler will reject it, claiming a general syntax error.

Delete operates similarly to halt except that it removes the target script or scripts from memory. If a script is going when targeted by delete, it is first halted and then removed. When sayStat is included in a delete statement, the script report message contains all going scripts, but the delete is performed on all scripts in the targetScript argument. A script may delete itself, in which case it executes no statements after the delete. For example, motor ramps may be defined in a script whose last statement (before the end statement) deletes the script.

Halt and delete can be invoked interactively (through the script debugger or other program) using the !H and !D text commands. These commands accept the name of a single script. If no script is named, all scripts are targeted. A level argument cannot be specified. The level is safety by default, not monitor, as with the halt and delete commands. Thus, all scripts are targeted regardless of their level.

EXAMPLES

halt others

halt WashScript saydone

halt all mechanical

halt others monitor sayStat

halt Msm all

delete others

delete Myself // Myself is the name of a script, which may be the one executing the command.

delete all mechanical

ERRORS

Compile Time

 

 

LOOP GROUP

[loop], [endloop], and [break]

LOOP, ENDLOOP, BREAK

SYNTAX

loop loopControl

loopControl is loopCount or for time [second[s]]

loopCount is an integer 1 through 65534 or 0 (or 65535) to loop forever.

time is a float.

endLoop

break

DESCRIPTION

Loop causes the loop body (all of the subsequent commands up to the matching endLoop command) to be executed loopCount times (forever if loopCount is 0) or for time seconds after which execution continues with the next command after endLoop. Loops may be nested up to four deep, but a loop based on time may not be nested in another time-based loop.

The loop body may execute fewer than loopCount times or for a shorter period than time due to a terminate or break command (the script can also be halted). The break command can appear only in the body of a loop. Break stops only the loop, with script execution continuing at the next command after the nearest endLoop. Normally, a break would appear in the body of an if block that appears in the loop, but this is not required. Terminate must appear in an if block. It stops the entire script.

When a time-based loop terminates due to timeout (rather than break), the script's timeout flag is set. This can be tested after the endLoop with an if timeout command.

EXAMPLES

loop 0

if Cover Open

break

endif

endloop

loop 5

loop 10

loop 4

loop 8

echo "The count is \VAR0"

VAR0 + 1

endloop

endloop

endloop

endloop

loop 4

loop 3

wait for 0.2

if Barcode

send Barcode "\x1BS8\x0D"

terminate

endif

endloop

echo "Tube position barcode read warning"

endloop

loop for 2.5 seconds

if Barcode

break

endif

endloop

if timeout

report NoBarcode

endif

ERRORS

Compile Time

Run Time

 

 

VAR GROUP

VARxx = | ^ & << >> + – * / %

Vars appear as parameters in many commands that are not considered part of the VAR group. Every command in the VAR group comprises a VAR ID (VAR0 through VAR99) followed by an operator and a variable number of parameters.

SYNTAX

optUnit varId operator parameters

optUnit is blank or the name of an execution unit.

varId is VAR0 through VAR99.

operator is one of the following:

parameters is one of the following:

replaceableParameter is a @name that must evaluate to a word (int16).

seqLevel is safety or monitor or config or mechanical or process.

barCode is rackId or tubePosId.

faultName is a fault declared in the configuration file.

comDevice is a COM_DEVICE declared in the analyzer configuration file.

optPeek is blank or peek.

channelDevice is a CHANNEL_DEVICE declared in the analyzer configuration file.

float is a single floating point number.

expression is a floating point mathematical expression containing floating point numbers and any of the following operators: * / + – ) ( . The main operator (against the VAR) can be only * or /.

DESCRIPTION

Every VAR command reads or computes a value and leaves the result in the named VAR. The optUnit enables a master to assign values to a slave's global VARs. No means exists to access a slave script's local VARs or to read the values of a slave's global VARs as VAR command parameters, for example VAR7 = Slave VAR80. A slave's global VARs can only be read (tested) as an if predicate, for example if Slave VAR80 = 25.

The script language supports much more extensive arithmetic and logical manipulation of VARs than specific devices. For operations other than simple testing, reading, or setting, device values are read into VARs (by VARxx = device) where they are subsequently manipulated.

The most basic VAR command is VARxx = something, which assigns a value to VARxx. Something can be a number or name whose value is known at compile-time or when the script is downloaded (replaceable parameter) or the name of some device whose value is determined when the command is executed. Anything whose value can be assigned to a VAR can also serve as a parameter in the logical and integer arithmetic operations. For example VARxx = time and VARxx | time are both legal and assign a value to VARxx. The logical and integer arithmetic operators assign a value to the named VAR as follows:

= the compile-time or run-time value of the parameter.

| the VAR’s current run-time value bit-wise OR’d with the parameter’s value.

^ the VAR’s current run-time value bit-wise XOR’d with the parameter’s value.

& the VAR’s current run-time value bit-wise AND’d with the parameter’s value.

<< the VAR’s current run-time value shifted left by the parameter’s value.

>> the VAR’s current run-time value shifted right by the parameter’s value.

the VAR’s current run-time value plus the parameter’s value.

the VAR’s current run-time value minus the parameter’s value.

the VAR’s current run-time value times the parameter’s value.

/ the VAR’s current run-time value divided by the parameter’s value.

% the remainder after dividing the VAR’s current run-time by the parameter’s value.

The operators +, -, *, and / can also appear in floating-point expressions. A floating point expression must be evaluable at compile time and the run-time resolution and range of the result are much less than normally associated with floating point numbers. For any value less than 255.996, the resolution is .00391. Values greater than 255.996 are rounded to the nearest integer. The main operator must be * or /, i.e. VAR * expression or VAR / expression. The script compiler converts the expression to a scaled integer literal value, but VARs hold only unscaled integer values. The purpose of floating-point expressions is to allow the integer value in a VAR to be fractionally changed to another integer without significant loss. For example, if a VAR containing 400 were multiplied by 1.5 without scaling, the multiplier would be either 1 or 2, as there would be no way to express 1.5 in a literal integer. With scaling, the result is 600. This ability is needed wherever the VAR's value provides a run-time measure of some phenomenon that can be used to calculate the control value for an operation. For example, aspiration and dispensing use the draw time to the first sensor as a measure of sample mobility, from which subsequent aspiration times can be computed. Another example is computing a motor step count based on the observed position of a mechanical object, such as the bottom of sample tube (particularly one with a false bottom).

Floating point expressions can contain any number of operators and operands, all of which must be floating-point constants. Integer expressions can contain only one operator and one operand, which may be a literal integer from 0 to 65535 or any one of the following:

time the current value of rendezvous timer for the script in which this command appears. See adaptive aspiration.

toSeconds the current value in the VAR is assumed to be a native tick count and is converted to time in seconds. See adaptive aspiration.

toMsecs the current value in the VAR is assumed to be a native tick count and is converted to time in milliseconds. See adaptive aspiration.

maxSeqLevelGoing the highest level of any script currently running. Levels range from safety (lowest), monitor, config, mechanical, to process (highest). MaxSeqLevelGoing can be tested to determine whether a particular operation can be safely performed. See Begin-Level.

seqLevel (safety or monitor or config or mechanical or process) can be assigned to a VAR but more typically a VAR is assigned maxSeqLevelGoing and is then tested against one of these levels. See Begin-Level.

barCode (rackId or tubePosId). Depending on the analyzer system, the selected barcode source (number) is either immediately read and assigned to the VAR or the previously recorded value is assigned to the VAR. In either case, the number represents the functionally current value of the barcode.

faultName A VAR may be assigned a fault name declared in the configuration file. However, typically a VAR containing the fault (numeric ID) is tested against one of these names. See Begin-Fault.

comDevice The oldest undeleted message received from the device is translated to a numeric value and assigned to the VAR. The compiler accepts only the = operator. If the message contains non-numeric characters or represents a value greater than 65535, the VAR is assigned 65535; a run-time error is not automatically reported. Since this value indicates an error, the usable range is 0 to 65534. Unless the optional peek argument is present, the device message is automatically deleted even if the message represents an illegal value.

channelDevice Channel devices that are uniquely declared in a form that specifies both the general device and channel number need only be specified by name, e.g. VARxx = Psi9. For channel devices not specified to the channel level, the device and channel number are both required, e.g. VARxx = ADC 7. To transmit the value of a channel device to the system master use the get command [GetChannel].

float second[s] The compiler converts the number of seconds (including fraction) specified by float to an integer number of ticks based on the execution unit's PERIOD specified in the TIMERS section of the configuration file. Second or seconds is required.

Local (0 through 7) and global VARs (8 through 99) are nearly identical syntactically. However, a local VAR has no legal value unless it has been assigned one within the current script, and the script compiler rejects attempts use it for a value otherwise. For example VAR0 = VAR1 is rejected if the script in which it appears has not assigned a value to VAR1. Whether VAR0 has a value at this point is irrelevant.

A VAR that is hard-defined (see define command [HardVar]) may still be accessed by its VARxx name but the script compiler will issue a warning. The preferred syntax is to use the defined alias name.

EXAMPLES

VAR0 = 10

VAR80 = 0ABCDh

VAR15 = @RBCTHR

VAR7 = time

VAR7 + 1.5 seconds

VAR6 = VAR7

VAR7 = toSeconds

VAR6 = toMsecs

VAR4 / 10

VAR5 + 1

VAR20 >> VAR0

VAR20 % VAR1

VAR3 = maxSeqLevelGoing

VAR6 = Barcode ; Com device destructive read.

VAR6 = Barcode peek ; Com device non-destructive read.

VAR30 = Psi9

VAR30 = Adc 4

VAR7 * 1.5

VAR7 / ( ( 3.5 + 2.4 ) * 2.1 )

Slave VAR30 = VAR3

Slave VAR40 + 5

ERRORS

Compile Time

Run Time

The VAR command interpreter guards against all illegal operations and operands and can send appropriate error messages to the system master, but these should never occur because the script compiler guards against the same errors.

 

 

IF GROUP

[if], [else], and [endif]

IF

SYNTAX

if optUnit predicate

optUnit is blank or the name of an execution unit. It must be blank if predicate is time or timeout or bitTestList in timeperiod.

predicate is varTest, stateTest, configTest, comDeviceTest, bitTestList, time, timeout, or motorTest.

varTest is varId compOp operand

varId is VAR0 through VAR99

compOp is = or != or < or > or <= or >=

operand is int16 or varId or seqLevel or faultName

seqLevel is safety or monitor or config or mechanical or process

faultName is a fault name declared in the configuration file.

stateTest is a STATE declared in the configuration file or a replaceable parameter (@name). There is no comparison operator or operand. The run-time condition is tested for the STATE, i.e. essentially the STATE tested for True or False. The replaceable parameter is replaced by True or False as the script is downloaded.

comDeviceTest is comDevice or not comDevice.

comDevice is a COM_DEVICE declared in the analyzer configuration file.

configTest is configDevice = byteArray

configDevice is a CONFIG_DEVICE defined in the configuration file.

byteArray may contain only values (characters) in the range defined for configDevice in the configuration file.

 

bitTestList is bitTest [ conjunction bitTest ... ] [ in time ]

(the clauses in square braces are optional)

bitTest is bitDevice optEqual condition

bitDevice is a FLAG, SENSOR, ACTUATOR (with compiler warning) identified by name space:address tuple or address (within the first SENSOR space).

optEqual is blank or =.

condition is blank (bitDevice is tested for 1/True) or True or False or 0 or 1 or the aliases of 0 or 1 defined in the declaration of bitDevice.

conjunction is & or |. The statement may contain as many as 39 conjunction clauses for a total of 40 tested bitDevices, but only one conjunction type, & or |, is allowed and all bitDevices must reside in the same space.

time is float [second[s]] (integer cannot be substituted for float here)

timeperiod is a float or int16 number of seconds.

motorTest is motor optNot motorCondition

motor is the name of a stepper motor or of a motor type that provides position feedback, such as a TriMotor (Shear Valve).

optNot is not or blank.

motorCondition is cw, ccw, or center if the motor is a TriMotor or moving, idle, > motorPosition, or < motorPosition if the motor is a stepper.

motorPosition is an int16, except 0 or 65535, or an arithmetic expression whose result is between 0 and 65535 exclusively.

DESCRIPTION

The if command controls whether or not the subsequent commands up to the matching else or endif are executed. Practically unlimited if nesting (up to 65535 levels) is supported. The predicate is tested every time the if command is executed. If the entire predicate is true, the subsequent commands are executed. In most cases, the predicate’s value depends on run-time conditions. However, whether a replaceable parameter is true or false is determined as the system master downloads the script to the analyzer. Thus, the predicate will always have the same value unless the replaceable parameter’s value changes and the script is downloaded again.

VAR Predicates

If VAR affords the greatest range of operators and operands. The run-time value of the VAR can be tested for all types of equality and inequality against literal values (or their named aliases), the run-time value of another VAR, the script level names (these are defined by the language, not by the configuration), or the fault names defined in the configuration file. Only one comparison clause is allowed in the predicate.

State and Config Predicates

Like the varTest predicate, the stateTest and configTest afford only one comparison clause. Further, they are much more restrictive in terms of the range of test operators and operands. The STATES and replaceable parameters in a stateTest predicate can only be tested for (essentially) True or False. A CONFIG can only be tested against strings of characters from a range (and type) limited by the CONFIG’S declaration.

Com Device Predicate

If com device tests for whether any undeleted messages have been received from the device. If not com device tests the negative case. For example, if the device is a barcode reader named Barcode, if Barcode is true if the device has sent one or more messages that have not already been deleted by get or VAR = without peek [Peek].

Bit Predicates

A bit device can only be tested for True, False, 0, 1 (actually any non-0 integer), or its declared aliases of 0 and 1. However, multiple bit devices can be tested in a single predicate as long as they reside in the same space and only one conjunction type is used. Each device in a bitTestList can be tested for any condition that it can be independently tested against. If the conjunction is &, every test must be true for the predicate to be considered true. If the conjunction is |, only one test needs to be true to make the predicate true. If single numeric addressing is used (i.e. not space:address tuple) the first SENSOR space declared in the configuration file is assumed.

The optional in time clause causes the command interpreter to wait until either the predicate becomes true or the time limit (from the time that the command begins to execute) is reached. If the predicate becomes true within the allowed time period, the subsequent commands are executed.

Timeout Predicate

The timeout predicate represents the terminating condition of the most recent wait for event with time limit. For example:

wait going SomeScript for 3.0 seconds

if timeout

Time Predicate

The time predicate is used to perform some task with a stable period. Due to timing uncertainties, there are always minor variations (typically less than 1 msec.) in the timing of execution of even an apparently periodic command. This cannot be avoided. However, long term drift can be avoided by using the if time command, which provides a period referenced to the first time that the command executes in a particular script. In contrast, a wait for command can be used in a periodic script, but the actual duration of each period results from the specified delay plus the execution time of commands, which is unpredictable. If execution is faster than expected, the accumulated period will be larger than expected, if slower then smaller. In most situations, this accumulated uncertainty is unimportant. But, in any case, the if time command affords a simpler construct for triggering a periodic task. It is simply:

if time

<do the periodic task>

endif

Each script has a period timer that can operate for as long as 248 days with 5 msec. (depending on the execution unit's native tick rate) resolution. At the first if time statement, this timer is set equal to the current tick time plus the period time specified in the command (the compiler converts time seconds to ticks), and the predicate is considered true, i.e. the predicate is always true when the command is first encountered in a script. At each subsequent execution of the command, if the ticker has not reached the time indicated by the period timer, the predicate is false. When the ticker reaches the indicated time, the predicate is true and the period time is again added to the period timer. Thus, even if individual trigger times vary due to execution timing uncertainty, the long-term timing does not vary.

Motor Condition Predicate

The motor's condition is tested against the predicate. The conditions for a stepper are the same as for the wait motor command [WaitMotor], except that, instead of the blank condition, which signifies wait for motor not moving, there is an explicit moving condition. The not moving condition can be tested by if motor not moving. For a TriMotor, whereas the only wait condition is not moving, as implied by blank, the if conditions are cw, ccw, and center. A TriMotor cannot be tested against the general condition of moving except by waiting for it.

In most situations, waiting for a motor condition is more useful than testing for it with if. Scripts waiting for a particular motor condition usually can't do anything until the condition is met, and they can use the optional wait time limit to avoid hanging up in case of instrument failure. However, there are some situations in which it is useful to test a motor's condition without waiting. For example, a loop hunting for a motor's home flag might break on either the flag's or the motor's condition. Except for these relatively rare situations, a script that uses an if motor condition statement is likely to be more complicated than one that achieves the same results using wait.

Remote Command

All of the if types except timeout, time, and bitTestList in time can be executed as a remote command, i.e. the predicate refers to a slave unit. The capabilities, requirements, and restrictions are the same as for the local command except that resource restrictions are those imposed by the slave and local VARs cannot be tested. Generally, the unit doesn't have to be specified, as the compiler knows the unit from the definitions of named devices and will generate the appropriate command message. If the predicate refers to a name that occurs in both the master and slave and the unit is not named, the compiler generates a master local command message; remote will be generated only if the slave unit is named. The unit must be named if the predicate contains a slave VAR or bit devices identified by numeric address.

Although remote local VARs cannot be included in the predicate, a predicate can compare a remote global to a local local VAR, for example:

if Slave VAR20 = VAR0

However, the remote VAR must be listed first in all cases, whether any local VAR is involved or not. For example, the compiler rejects the following as a syntax error:

if VAR20 = Slave VAR20 but it accepts:

if Slave VAR20 = VAR20

EXAMPLES

if VAR0 = VAR10 // VAR against VAR.

if VAR15 > 89 // VAR against literal.

if VAR8 < 01101001b // VAR against literal.

if VAR1 >= Mechanical // VAR against level.

if VAR0 != MIX_LOST_TUBES // VAR against fault.

if @B00 // Replaceable parameter T/F.

if ClosedMode // State T/F

if LatexMode // State T/F.

if Kind = SL // Config against single character (SL is alias of "S")

if BcReader = Opticon // Config against single character (Opticon is alias of "1")

if Number = "1234" // Config against string.

if Kind = "\x1BV6\x0D" // Compare config to string with escape sequences.

if Kind = 1,2,3,4 // Compare config to numeric array. Not "1234".

if Kind = '1' '2' '3' '4' // Same as compare config to "1234"

if Barcode // Test for messages from com device Barcode.

if not Barcode // Test for no messages from com device Barcode.

if Wastefull // Flag

if Not WasteFull & \ // Multiple Flags with &

Not HgbLyseEmpty & \

Not WbcLyseEmpty & \

Not DilSheathEmpty

if WasteFull | \ // Multiple Flags with |

HgbLyseEmpty | \

WbcLyseEmpty | \

DilSheathEmpty

if not DilSheathEmpty // Not Flag

if not Wastefull | SampCover = OPENED // Not multiple Flags with |

if Wastefull & SampCover = CLOSED // Flags with mixed named conditions.

if Red On & Yellow On & Green On // Read back actuators with &

if Red Off | Yellow Off | Green Off // Read back actuators with |

if 0:10 // Read space:address tuple

if SensHgbLyse = NotEmpty in 3.0 seconds // Sensor in time

if Yellow On in 2.5 seconds // Read back actuator in time.

if Red = On & Yellow = Off & Green = On in 2.0 seconds // Multiple acts in time.

if WbcLyseEmpty = 0 & \ // Multiple & flags in time

HgbLyseEmpty = 1 & \

DilSheathEmpty = 1 & \

WasteFull = 0 in 2.0 seconds

if PaddleSwitch Pressed & RbcDilPress = Over // Multiple sensors in time.

if 2:24 = 1 & 2:25 = 0 & 2:26 = 0 & 2:27 = 1 in 2.4 seconds // tuples in time.

if 16 // Test (for condition = 1) device at address 16 in the first sensor space.

if 16.0 // Periodically true at 16 second intervals.

if 16.0 seconds // same thing.

if timeout // Test terminating condition of most recent time-limited wait for event.

if Slave 0:10 11 12 // Test bits 10, 11, and 12 for true in Slave's space 0.

if Slave VAR40 > 25 // Test for Slave's global VAR40 greater than 25.

if SlaveDoor = Open // If SlaveDoor is a sensor defined for Slave, this tests that remote sensor.

if RackVertical moving

if Theta > 1020

if Theta < 100.5 * 4

if SyringeB idle

if ShearValve Cw

ERRORS

Compile Time

All of the device usage errors (based on configuration definitions) that the compiler detects for local predicates are also detected for remote predicates.

if 1 & 2 & 3 & 4 & 5 & 6 & 7 & 8 & 9 & 10 & \

11 & 12 & 13 & 14 & 15 & 16 & 17 & 18 & 19 & 20 & \

21 & 22 & 23 & 24 & 25 & 26 & 27 & 28 & 29 & 30 & \

31 & 32 & 33 & 34 & 35 & 36 & 37 & 38 & 39 & 40 & 41.

define FirstName SecondName

define SecondName ThirdName

define ThirdName FirstName

Run Time

The only errors that can occur at run-time are references to bit device space numbers or addresses that don't exist in the target unit. These can occur if predicate devices are identified numerically, by one number (in which case the default space is almost surely supported) or by space:address tuple. They can also occur if the predicate contains a device that is incorrectly defined in the configuration file. The compiler will not generate if command messages with bad VAR predicates. Bad STATE and CONFIG if messages are possible and are detected at run-time but are not likely to be generated unless the configuration file is terribly wrong.

Space IDs range from 0 to 31, bit addresses from 0 to 255, byte indices from 0 to 31, and word indices from 0 to 15. For a bit-oriented space (FLAG, SENSOR, ACTUATOR) whether a bit, byte, or word-mapped command message is generated depends on how many devices are included in the statement and where they reside in the space. The compiler cannot generate messages that exceed the basic range limits, but individual execution units very likely limit at least their number of spaces (typically, no more than six spaces are realized) and possibly the address ranges within those spaces. The compiler can't know this and has to assume that any definition in the configuration file (or literal numeric command reference) is correct unless it is beyond the basic limits. Errors in usage, i.e. an incorrect but legal address used for a particular device, are much more likely than range errors and cannot be detected either at run-time or compile-time.

If a run-time predicate error is detected in a remote if command, two messages will be generated, one from the slave describing the problem and one from the master telling the name and command number of the offending script (which is aborted).

All run-time predicate failure messages are DM_SCRIPT-SCRIPT_FAIL-FAIL_BADPARM, including the master's response to an error message from the slave. The message text distinguishes the various error conditions.

ELSE and ENDIF

SYNTAX

if predicate

<true branch commands>

endif

if predicate

<true branch commands>

else

<false branch commands>

endif

DESCRIPTION

After the block of commands that are executed when an if predicate is true, there must be an endif or an else with a block of commands to be executed when the if predicate is false.

The script language does not afford an elseif, but the equivalent can be synthesized using if statements within the else code block. As with if, else affords essentially unlimited nesting.

EXAMPLES

if Kind = SL

echo "This is an SL model"

else

echo "This is a CS model"

endif

if OpenMode

if PaddleSwitch Pressed

if Green = On

echo "OK"

else

echo "Not OK"

endif

endif

endif

ERRORS

Compile Time

 

 

ACTUATE GROUP

[clear], [preset], [open], [close], and [set]

CLEAR COM DEVICE

SYNTAX

clear ComDevice

comDevice is a COM_DEVICE declared in the analyzer configuration file.

DESCRIPTION

Clear ComDevice is not functionally related to actuators. The word clear is used for a alternate purpose. This command deletes all messages that have been received from the named device. It is typically used to ensure that there are no residual messages before beginning a sequence of operations involving the device.

EXAMPLES

clear Barcode

 

CLEAR, PRESET, OPEN, CLOSE

SYNTAX

command optUnit bitList forTime power or clear comDevice

command is clear or preset or open or close

optUnit is blank or the name of an execution unit.

bitList is bitDevice [commaSpace bitDevice... ]

(the clause in square braces is optional)

bitDevice is a FLAG, SENSOR (evokes a compiler warning) or ACTUATOR identified by name space:address tuple or address (within the default space for the command type or the space identified by a preceding bitDevice in this bitList).

commaSpace is , or whitespace.

forTime is blank or for time.

time is float [second[s]].

power is blank or powerDown or not powerDown.

comDevice is a COM_DEVICE declared in the analyzer configuration file.

DESCRIPTION

All of these commands set the state of from one to 40 bitDevices (FLAG, SENSOR, or ACTUATOR) to 0 or 1. Clear and preset set the state of each device to specifically 0 and 1, respectively, and can be applied to any bit device, although the script compiler issues a warning if the device is a SENSOR. This warning can be disabled using the command pragma off WarnSensorWrite. Open and close can be applied to any bitDevice identified numerically (by space:address or address) in which case open sets the device state to 0 and close sets it to 1, or to any device declared as an open/close type ACTUATOR, in which case the open/close-0/1 alias assignments in the declaration provide the appropriate value. Thus, when open and close are applied to open/close ACTUATORS, the command may set some devices to 0 and others to 1. In all other uses of open, close, clear, and preset, all of the devices listed in one command are set to the same value, 0 or 1. Any ACTUATOR declared without 1 and 0 aliases in the configuration file is by default a normally-open (0 = open) open/close device.

If bitList contains more than one device, all of the devices must reside in the same space. If a device is identified by address alone, the space is assumed to be the first FLAG space defined in the configuration file if the command is clear or preset, or the first ACTUATOR space if the command is open or close.

For Time

The optional forTime tells the analyzer to immediately set the indicated device values and then invert them all after the specified time delay. The script is not delayed by this waiting period but moves immediately to the next command. The bit reversing command is independent of all other commands related to the devices. Thus, even if the same script or another changes a device’s state before the timeout, the delayed command will still execute, setting the state to the opposite of what was specified in the command containing the forTime clause, regardless of the device’s current state. The delayed bit reversing command inherits the power-down selection of the original command.

Power Down

The power clause is used to request power down to be scheduled or not. Only ACTUATORS support power down. When the analyzer changes the state of a power-down ACTUATOR, it initially raises the drive voltage for that device. After one-half second, the voltage is reduced to minimize heat and power consumption.

The execution unit program does not know which specific ACTUATORS, in fact, have power down capability. The program only knows a general formula relating power control bits to state bits. It is the responsibility of the command message to tell the unit whether or not to use power-down. There is only one power-down indicator for all devices in the message. Therefore, in addition to the requirement that all devices in the command reside in the same space, they must all either have or not have power-down. By default, unless the listed devices indicate otherwise, the compiler generates the command message with no power-down. However, if the statement contains a power clause, all devices will receive the specified treatment.

The script compiler examines the configuration declaration of each named device in bitList. ACTUATORS are declared as having power-down by the clause POWERDOWN = Y or as not having power-down by POWERDOWN = N. Open/close ACTUATORS have power-down by default while all other types have no power-down by default. If the command statement doesn’t contain a power clause (i.e. neither powerDown nor not powerDown) then the compiler will generate a message with power-down off or on to match the devices. If bitList contains a mix of power-down and non-power-down named devices, the compiler will issue a warning but still generate a command message, which will specify no power-down.

In additional to forcing power-down to be applied to devices identified only by space:address or address (default for unnamed devices is not powerDown) powerDown can be used to force power-down to be applied to named devices that are declared as POWERDOWN = N. The compiler accepts this but issues a warning. Not powerDown can be used to force a no power-down command message even when all devices are declared as having power-down. The compiler does not issue a warning in this case.

It is much safer and easier to refer only to named devices in these commands, affording the script compiler an opportunity to prevent potentially hazardous blunders. Referring to devices by space:address or address is reasonable only for system diagnostic functions that are purposefully not interested in the attached devices and for developing hardware. The powerDown option, in particular, should be used cautiously.

Remote Command

All of the set-like commands (set, open, close, clear, preset) can be executed as a remote command. The capabilities, requirements, and restrictions are the same as for the local command except that resource restrictions are those imposed by the slave. Generally, the unit doesn't have to be specified, as the compiler knows the unit from the definitions of named devices and will generate the appropriate command message. If the command refers to a name that occurs in both the master and slave and the unit is not named, the compiler generates a master local command message; remote will be generated only if the slave unit is named. The unit must be named if the statement uses numeric addresses to identify devices.

As for remote if command with an address range error, the slave issues a detailed error message. In this case, however, the master passes the message up to the system master without determining whether one of its own scripts is the offender. The offending script will not be reported or aborted.

Clear ComDevice

This command causes all messages in a com device input buffer (messages received from the device) to be deleted. For example, moving a tube rack may fill a barcode reader input buffer with unwanted tube and rack position ID's that clear Barcode removes.

EXAMPLES

preset 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15 // Default space is first FLAGS space.

clear 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15

clear ShearValveFault

open 10 powerDown // Default space is first ACTUATORS space.

clear 3:10,11,12 // The first tuple sets the default space for others.

preset 2:10 2:11 2:15

preset SensWbcLyse // Evokes warning if SensWbcLyse is a Sensor

open ShvDilFlush \

SmplAspirationVac \

ShvDrain \

OpenProbeDrain \

OpenProbeDilFlush

close ShvDilFlush not powerDown

open ShvDrain for 0.1 second not powerDown

preset Green for 2.0 seconds

ERRORS

Compile Time

preset 1 2 3 4 5 6 7 8 9 10 \

11 12 13 14 15 16 17 18 19 20 \

21 22 23 24 25 26 27 28 29 30 \

31 32 33 34 35 36 37 38 39 40 41

Run Time

See if command run-time failures for explanation [IfRunTime].

 

SET

SYNTAX

set optUnit setType

optUnit is blank or the name of an execution unit.

setType is one of the following:

setBitList is setBitDevice [commaSpace setBitDevice... ]

(the clause in square braces is optional)

setBitDevice bitDevice optToEqual state.

bitDevice is a FLAG, SENSOR (evokes a compiler warning) or ACTUATOR identified by name space:address tuple or address (within the default FLAG space or the space identified by a preceding bitDevice in this setBitList).

timeDevice is a name listed in the TIMES section of the execution unit's configuration.

optToEqual is blank or to or =

optEqual is blank or =

state is 0 or 1 or True or False or stateName

stateName is the 0 or 1 alias of the named device’s declaration in the configuration file.

commaSpace is , or whitespace

forTime is blank or for time

time is float [second[s]]

power is blank or powerDown or not powerDown

channelDevice is a CHANNEL device declared in the configuration file.

channel is integer selected from the channel range in the device declaration. If channelDevice has only one channel (this usually means that it is a single-channel sub-set of a CHANNEL device, i.e. it is a derived device) then Channel may be blank.

toEqual is to or =

channelVal is varID or a replaceable parameter (@name) or int16 or an arithmetic expression, which may contain floating point as well as integer numbers and the operators +, -, /, *, (, and ). The compiler reduces the expression to an int16.

msDevice is a MULTISTATE device (MS_DEVICES) declared in the configuration file.

optToEqual is blank or to or =

stateName is one of the states defined in the declaration of msDevice.

DESCRIPTION

The set command is the most general actuate command. Its setBitDevices form affords an expanded version of all of the other bit device actuate commands, open, close, clear, and preset. The setChannelDevice setType controls CHANNEL devices, such as DAC. The setMsDevice setType controls MULTISTATE devices. The stateDevice setType activates STATES. All setTypes except stateDevice are composed from a basic assignment clause, which names a device and the value to be assigned to it. SetChannelDevice and setMsDevice accept optional assignment operators (to or =) to make the source more readable. SetChannelDevice requires an assignment operator in order to distinguish between channel (which may be blank) and channelVal, both of which are numbers (channelVal may be an arithmetic expression that the compiler can reduce to a number).

As with the other bit device actuate commands, one set setBitDevices statement can assign states to as many as 40 bit devices. All other setTypes allow a single statement to control only one device.

With the setBitDevices setType, set can do everything that open, close, clear, and preset can do. But it can also mix states in one statement, e.g. set dev1 opened dev2 closed, and control devices with unique state names (defined in each device’s declaration) e.g. set Green On. The other bit device actuate commands exist for convenience, because set requires that a state be identified for each device in the statement. For example, open dev1 dev2 dev3 and set dev1 = opened, dev2 = opened, dev3 = opened are functionally equivalent. In all other regards, the description of the other bit device actuate commands applies to set setBitDevices.

Note that set bitDevice is not a valid statement, because it doesn’t tell the assigned state. If the intent of this statement were to assign the value 1 to bitDevice then the correct statement would be preset bitDevice or set bitDevice = 1.

Set time timeDevice is used to set unit-specific timeouts and alarms, particularly those related to communication error detection and recovery. This command is intended for use during development and testing, but it might also be used in an ordinary script to resolve a unique timing problem. There are no intrinsic time device names but certain names are common to many different units. Three of these are:

The legal range of the time parameter in set device for and set time commands is unit-dependent. The script compiler knows the range based on configuration information and issues a fatal error if the value is larger than the maximum. The timekeeper in most units has a 5 msec. period, establishing a maximum command value of 327 seconds.

EXAMPLES

// bit devices

set Green On, Red Off

set Green = On Red = Off

set Red = On, Green = Off, Yellow = Off, Beep = On

set ShvDilFlush Closed, ShvDrain Open

set Yellow to On

set Beep On for 1.0

set 2:20 = 0 21 = 1 22 = 1 23 = 0 for 2.5 seconds

set Slave 15 = 1

// channel devices

set DAC 7 to 2000

set DAC 8 = VAR90

set Volume = 40 <-- single-channel device derived from DAC

set Gain 3 to @WbcGain

set Prescale 1 = 8

set IoBus 1Ah to 0CCh

set VpmP2High = (9.1 * 1023) / 15

// multistate devices

set SecPress2 Opened

set SecPress2 = Servoed

set SecPress2 to Closed

// state devices

set OpenMode

set ClosedMode

set NeoMode

set LatexMode

// time devices

set time txTime = 3.0 seconds

set time rxTime 1.0

set time rxIntraTime

ERRORS

Compile Time

Run Time

If the configuration file is correct for the target analyzer and only named devices are accessed, the script compiler will catch all device selection errors. It will also catch all invalid value assignments except VAR and replaceable parameter assignments to channel devices. The system master should guard against the latter, but only the analyzer itself can guard against an invalid run-time value from a VAR. It also guards against errors that should have been caught by the compiler or system master. See if command run-time failures for additional details [IfRunTime]. Also see open et. al. Remote Command [RemoteSet].

 

 

MOTOR GROUP

[move], [stop], [position], [ramp], [rampdef], [power], and [testmotor]

Also see [Initialize]

MOVE

SYNTAX

move motor moveType

motor is a motor named in the configuration file.

moveType is stepperMove or dcMove or triMove

stepperMove is reference intRepVar

reference is to or + or -

intRepVar is int16, integer expression, replaceable parameter (@name), varID, or forever. The value is the literal value at compile-time if int16 or integer expression; the replacement value when the script is downloaded to the execution unit if @name; or the run-time value of the VAR if varID. In all cases, the value is unsigned, ranging from 1 to 65535 (0FFFFFh). 0 is reserved for internal use. 65535 (0FFFFh) and forever mean to run forever (until a stop command) and can only be used when reference is + or -. Physical interpretation of numeric stepper positions depends entirely on the mechanism and prior use of the position command, which can label the current position of a stepper with any value from 1 to 65534.

dcMove is optTo CW or CCW optForTime

optForTime is for float optSeconds or blank.

optSeconds is second[s] or blank.

triMove is optTo moveDir optFraction

moveDir is CW or CCW or Center

optFraction is float or blank.

optTo is to or blank.

DESCRIPTION

The different moveTypes are motor type-specific. StepperMove is legal only for steppers; dcMove is legal only for DcMotors and BiMotors; triMove is legal only for TriMotors. The script compiler rejects command statements in which motor and moveType don't match.

A stepper can be moved to an absolute position relative to the value set by a prior position command using the to reference or to a position relative to its current position by the - and + references. All movement is measured by motor steps, which can translate to any kind of movement or distance. Thus, script commands that refer to a particular motor are valid across multiple analyzer systems only if the motor's mechanical linkage and step size are the same in all systems.

The three types of step count arguments-- integer (single value or expression), replaceable parameter, and varID represent increasingly late-binding of the value. The integer hard-codes a literal number of steps into the script. The replaceable parameter allows the system master to determine this value when the script is downloaded. The varID allows on-the-fly determination of the step count. For example, to drive the sampling needle to the bottom of a tube, if the script knows the tube type, it can use an integer step count; if the tube type can change by user selection at the system master, then a replaceable parameter can be used; if the analyzer determines the tube type or locates its bottom by inspection, then a VAR can be used. In this example, the greatest flexibility is provided by visually locating the tube bottom and transforming this information to a step count, most likely using a VAR /* floating-point expression computation.

DcMotors and BiMotors both can be moved CW and CCW. DcMotors are unidirectional, so CW and CCW produce the same command message for them. To avoid confusion, it is advisable to use the direction that reflects the actual motor movement. The optional "for time" clause causes the motor to be turned on for the specified number of seconds. This clause is not legal for TriMotors or steppers.

TriMotors are normally moved to CW, CCW, or Center. However, they can also be moved to fractional positions even though they are not steppers and only provide feedback at the CW and CCW extremes. This is possible because at every full travel move (which are most of the moves) the traversal time is measured and stored. Thus, the analyzer knows how long it takes the motor to move from CW to CCW and from CCW to CCW (the two directions are not expected to produce identical times). If the command statement contains an optFraction argument whose value is less than 1.0 then the parameter is interpreted as a move time multiplier. For example, move ShearValve CCW 0.25 would move ShearValve toward CCW for 1/4 of the time that is required to move the full distance from CW to CCW. Fractional moves toward CW are also supported. Once a TriMotor experiences a fractional move, it cannot execute a move to center (the request would evoke a run-time error) until it has reached one of the endpoints (CW or CCW) where its exact position is reestablished.

The optFraction parameter serves a different purpose if its value is greater than 1.0. In this case, it represents a move timeout, again based on the last recorded full travel time. For example, if optFraction is 2.0 then the timeout is twice the recorded full travel time. If the motor doesn't reach its target position (CW or CCW) in less than the specified time, the analyzer will shut down the motor's drive and report a run-time error. The compiler accepts the timeout for a move to Center but TriMotors are not required by definition to have a center position detector. If the analyzer system doesn't support TriMotors with center detectors or the particular motor doesn't have a center detector then the analyzer program ignores the parameter.

It is not normally necessary to specify a TriMotor's move timeout, because the motor's declaration in the configuration file defines a normal timeout. The normal timeout is fairly tight, because the motor is expected to be in position when subsequent operations occur. For example, the shear valve must be properly positioned before aspiration begins. If the timeout were relaxed, the script would have to wait by a commensurate amount, potentially reducing throughput. However, to move a dirty shear valve for cleaning may require substantially more time. In this case, the normal timeout could prematurely declare a motor failure, shut down the motor, and leave the instrument in an unnecessarily difficult fault recovery situation. The normal timeout specified in the motor's declaration is based on absolute time (with 5 msec. resolution) rather than on the recorded traversal time.

EXAMPLES

move SampInjMtr to 65534 // Maximum absolute.

move WbcLyseMtr +65534 // Maximum positive relative if not forever.

move RbcDilMtr -65534 // Maximum negative relative if not forever.

move M5 -forever // Forever in negative direction.

move M5 +forever // Forever in positive direction.

move SyringeA + 900 / 2 + 10

move OpenProbeMtr to VAR20

move FillLineMtr + VAR20

move FillLineMtr - VAR20

move OpenProbeMtr to @ProbeHi

move OpenProbeMtr - @Step

move OpenProbeMtr + @Step

move Yvalve CW

move Yvalve to CW // Optional "to" makes no difference.

move Yvalve CCW for 1.5 seconds

move ShearValve CW

move ShearValve to Center

move ShearValve to CCW

move ShearValve Center 4.0 // Allow 4 times normal full travel time.

move ShearValve CCW 0.5 // Move half of full travel time.

ERRORS

The script compiler verifies that the moveType matches the motor. It rejects negative absolute stepper moves (e.g. to -100) and any position (absolute or relative) argument larger than 65534 or equal to 0. However, there are many other stepper move errors that can't feasibly be detected at compile time. The compiler can't validate the value of a replaceable parameter or VAR used in a move statement. It can't determine the validity of a relative move even with a literal (int16) step count because it can't know the motor's starting position. For example, move + 1000 is valid only if the motor's position is less than 64535. Neither the compiler nor the command interpreter knows whether the destination is mechanically feasible.

Compile Time

Run Time

DcMotors and BiMotors are controlled through the analyzer's general I/O space rather than through the motor command processor. TriMotor commands are routed through the motor command processor. Therefore, the run-time errors reported for DcMotors and BiMotors are not the same as those reported for steppers and TriMotors, which share a general error detection front end before branching to specifically stepper and TriMotor command processing. For example, there is no means to detect attempts to move DcMotors and BiMotors that are still moving in response to a previous move command. In contrast, an attempt to move a TriMotor or stepper that has not finished moving is blocked and a run-time error reported. The stepper controller accepts a move command if the motor is in the hold phase as well as idle. For a definition of stepper ramp phases, see ramp and rampdef commands [ramp].

begin testm unit msm move M3 +1000 move M3 +100

STOP

SYNTAX

stop motor stopType

motor is the name of one motor or motors

stopType is blank, hard, or off. hard and off can only be used if motor is one stepper.

DESCRIPTION

Note that stop gather and stop watch commands are unrelated to motor stop.

The stop command causes the motor(s) to stop immediately. Depending on the motor type and stopType, the motor's position may become unknown. Thus, this should not normally be used with a stepper, which should instead be allowed to finish each move, leaving it at a known position. On the other hand, stop is used routinely with DcMotors and BiMotors, which, otherwise, would run forever in response to a move CW or CCW command. TriMotors do not support stop. They automatically stop at CW and CCW extremes and under software control at fractional positions (including Center). The TriMotor control program shuts down motors that exceed their travel timeout, so there is no need for an emergency stop.

When a stepper is stopped with blank stopType, its normal down ramp is immediately engaged unless it is already in its down ramp phase or not moving at all. It doesn't stop instantly but as quickly as possible without losing position control. Therefore, it is the most desirable means of effecting a quick but controlled stop. StopType off turns off the stepper's drivers, allowing the motor to coast to a stop or not move at all if mechanically blocked. Electrically, it is the gentlest stop, potentially preventing destruction of the drivers. In most situations, it also is the most mechanically gentle, providing no resistance to mechanical forces on the motor. StopType hard immediately engages the motor's hold phase. The duration (up to 2 seconds) and strength (off, low, medium, and high) of the hold is determined by the motor's current ramp hold assignment. This provides the most rapid stop. It is useful for debugging (to see motor's position at a particular point in script execution) and for freezing the motor's position at a home flag during initialization.

EXAMPLES

stop motors

stop Yvalve

stop SampInjMtr

stop Probe hard

stop Probe off

ERRORS

Compile Time

Run Time

 

POSITION

SYNTAX

Position motor position

motor is the name of a stepper

position is blank or int16 from 1 to 65534

DESCRIPTION

Position serves two purposes. If position is blank, the current step position of the motor is echoed to the system master. This mode of the command should only be used during development and diagnostics. If position is not blank, its value is assigned to the motor. Normally, a stepper is initialized by a script that moves it to a home flag and then uses this command to set its permanent "home" position. All subsequent absolute moves are relative to this. Extreme values (1 or 65534) are typically not used to identify the home position but instead values that afford some margin in case the motor overshoots its home flag. Since any legal motor position can be assigned to "home", the home flag can be located anywhere in a motor's travel.

EXAMPLES

position SampInjMtr

position Probe 8000h

ERRORS

Compile Time

Run Time

 

RAMP

SYNTAX

ramp motorName segmentList

motorName is the name of a stepper motor.

segmentList is = trajectoryName and/or one or more phrases of segmentDefinition or slew rate or hold time.

trajectoryName is the name of a previously defined (by rampdef) trajectory.

rate is an integer number of steps per second.

time is a float or integer number of seconds, including 0, limited to approximately 2 seconds (determined exactly by the motor controller's minimum step period).

segmentDefinition is segment segmentDescriptor.

segment is up, down, or recoil.

segmentDescriptor is the name of a previously defined (by rampdef) ramp segment or segmentComponentList

segmentComponentList is one or more segmentComponents separated by +

segmentComponent is an optionally comma-delimited series of integer steps per second or a synthesizedRamp or 0 (only for recoil).

synthesizedRamp is beginSteps [exclusive] [to] endSteps [exclusive] slope.

beginSteps is the integer steps per second at the beginning of the ramp.

endSteps is the integer steps per second at the end of the ramp.

slope is linear grade [%] or linear grade [%] to grade [%] or in steps [steps]

linear is linear or @

grade is a float from 0.01 to 1000.0 or an integer from 1 to 1000.

steps is an integer from 1 to 118.

DESCRIPTION

Ramps describe acceleration and deceleration profiles for stepper motors. The trajectory of a stepper is described by the following sequence of ramp segments: up, slew, down, recoil, hold, idle. The motor accelerates in the up segment, maintains a steady speed during slew, decelerates in the down segment, accelerates (or steps at a constant rate) backwards in the recoil segment, holds a particular power state during hold, and switches (possibly) to another power state at idle. The recoil ramp and hold state are optional.

Ramp Segments

A particular power state-- off, low, medium, or high-- is associated with each segment of the trajectory (see [power] command). Since the motor doesn't move during hold and idle, these segments serve only to control the power applied to the motor. The hold period can last for no more than two seconds. Typically, relatively high power is used for hold to prevent step loss due to mechanical momentum, while low (possible off) power is used for idle to prevent electrical component stress. Idle is not included in the definition of a ramp but is treated as a trajectory segment in the power command.

Slew and hold segments are characterized by a single value representing the steps per second for slew and the number of seconds (typically fractional, such as 0.5) to remain in hold before switching to idle. A recoil segment provides a short reversal at the end of a move. The same effect can be achieved more subtly with hold and down power assignments [Power-based Recoil].

Accelerating and Decelerating Ramps

The up, down, and recoil segments are characterized by a series of increasing or decreasing number of steps per second. Under most conditions, it is best to accelerate or decelerate a stepper using a linear ramp, in which each step change is proportional to the duration of the step (the "ramp" is the plot of step change-- i.e. acceleration-- vs. step size-- i.e. 1/speed). This approach matches the mechanical difficulty of the step change to the decreasing torque at higher speeds characteristic of steppers. Two kinds of linear ramps are supported, single- and multiple-slope.

For single-slope ramps, the grade is the ratio of each step change to the current step width. A grade of 1% means that each step change is 1/100 the size of the step. A grade of 1000% means that each step change is 10 times the size of the step. Typical grades are 10% to 30% for up ramps and 20% to 40% for down. The slew rate is usually determined by the application (although in some cases, the goal is simply to go as fast as possible). The last step rate of an up ramp and the first of a down ramp nearly always match the slew rate. The step rate at the low end of the ramp and the ramp's grade are normally chosen to accelerate (or decelerate) the motor as rapidly as possible without step loss. The more shallow the grade the noisier and rougher the motor's movement, particularly at the low end.

In most circumstances, the ideal ramp is exponential. A single-slope ramp roughly approximates this. A multiple-slope ramp can come much closer to the ideal. Normally, such a ramp is defined with a steep grade at the low end and shallow at the high. This allows the motor to quickly get through the rough low end without increasing the risk of step loss at the high end, where the motor's torque is diminished. The ramp compiler continuously varies the grade between the two endpoints. Multiple-slope ramps serve not only to closely approximate ideal exponential ramps, but may also be used for the opposite purpose, to start an up ramp or end a down ramp slowly. Typically the desired effect of this, a very gentle start or stop, is defeated by the motor's rough movement at low speeds unless micro-stepping is used (supported by special hardware) or the movement is mechanically damped. Because multiple segments can define a ramp, it is feasible to combine two or more multiple-slope ramps into one comprising, for example, an exponential starting segment followed by a reverse exponential segment.

For every single-slope ramp, an equal or better multiple-slope ramp can be found. The only reason for using the former instead of the latter is convenience. The motors on many mechanisms, for example syringes and pumps, are supported equally well by either.

The optional word, exclusive, after the begin and end step rates tells the compiler to not include the associated endpoint step in the ramp. Typically, this is used to exclude the end step in an up ramp and the begin step in a down ramp, because the slew already provides these steps.

The script compiler can synthesize another common ramp type, which uses a constant step change throughout, yielding a logarithmic plot of step change vs. step size. This is requested by the phrase in steps, where steps tells the number of steps in the ramp. The compiler divides the range from begin step rate to end step rate evenly by the step count. As with the linear ramp, exclusive can be used to exclude the begin and/or end step. The compiler rejects a step count of 0 or larger than 118.

The script language also allows the script writer to explicitly specify the width (in steps per second) of each step in the ramp with an optionally comma-delimited list of integers.

Typically, a ramp comprises just one of the basic types, linear, log, or user-specified list. However, any number (limited to 118 steps in the composite ramp) of these can be concatenated, using +, to create a more complex ramp. An identical ramp could be defined by a single user-specified list but only with significantly greater effort.

One possible motivation for creating a complex ramp could be to avoid a resonant region in an otherwise ideal standard ramp. Another could be to produce a very gentle start or (less frequently) stop without paying the price of a long ramp time, for example to reduce splashing at the start of fluid delivery into an open container. While it would be possible to create a piece-wise approximation of a sine ramp for this purpose, such complexity is neither necessary nor ideal. A two-piece ramp composed of a user-specified slow startup list followed by a fast linear ramp affords better performance because the independent pieces don't compromise each other.

Trajectories

The purpose of the ramp command is to assign a full or partial trajectory to a motor for subsequent use in executing move commands. A stepper cannot be moved unless its assigned trajectory includes at least an up, slew, and down segment. However, it is not necessary to assign all of these in one statement, because ramp allows superposition of partial trajectories. The segments defined in a ramp statement (directly or indirectly by reference to a named trajectory) replace any corresponding segments previously assigned to the motor without affecting the others. Thus, it is possible to build up a trajectory or to modify part of a motor's trajectory even as the motor is being used.

While it may be useful to change only part of a motor's trajectory during normal operation, the capability is provided primarily for ramp development. For example, a recoil segment can be added, removed, or modified to test the effect on fluid shear or backlash without having to redesign the entire trajectory; the slew rate of a continuously running motor can be increased until step loss becomes evident to test the limits of the motor; the gradient of an up ramp can be increased to find the limit or decreased to reduce noise or to avoid resonance.

For up, slew, and down segments, the ramp command can only add or replace the motor's existing assignments. The script language affords no means to remove these because a motor can't operate without them. For recoil and hold, which are optional, assigning a value of 0 removes any existing assignments; for example, ramp Motor4 hold 0 recoil 0.

The rampdef command provides a means to define single ramp segments and full or partial trajectories for subsequent assignment to motors. The statement ramp motorName = rampName assigns all segments defined by rampName to motorName. The named ramp does not have to define a complete trajectory. Multiple assignments and explicit segments can be assigned to a motor in one statement, for example ramp motorName = Up200 = Down200 slew 200. For each segment, the last element in the statement to define the segment determines what is assigned to the motor. For example, in the statement ramp motorName = Ramp50 = Ramp100, if both Ramp50 and Ramp100 define an up segment, Ramp100's up ramp will be assigned to the motor.

For routine scripts, motors should be assigned named up, down, and recoil ramps (defined by rampdef) instead of ramp definitions embedded in the ramp statement, because this can lead to more efficient run-time operation. Whether a motor's slew and hold definitions derive from a named ramp or from the motor's own ramp statement is immaterial. Typically, a named ramp includes the slew and it is simply a matter of convenience to inherit this. The motor controller's ramp memory is wasted if two named ramps differ only in their hold specification, so a good general policy is to define hold in motors' ramp statements instead of in rampdefs.

Although motors cannot be moved without up and down ramp segment assignments, they can move smaller distances than the number of steps in these ramps. The stepper controller truncates the up and down ramps symmetrically down to a single step (for which the up ramp's power and first step are used) as needed to execute short moves.

Viewing Synthesized Ramps

The script compiler instantly generates ramps as good as the best that an expert could design by hand. There are only two reasons for viewing the synthesized ramp contents, for program verification and to support hand tailoring to bypass a resonant zone. In practice, the latter should rarely be needed, as the same result can usually be achieved more easily by choosing a different gradient. In any case, the compiler accepts a command line argument to write all ramps and rampdefs to a file. The argument is -R and the file is always ramp.lst. The file shows the motor or ramp name, step list, and execution time for each ramp. For example, ramp M5 up 20 to 300 linear 20% down 300 to 20 linear 40% is listed as:

--- Motor M5 ---

UP: 1632, 1363, 1137, 949, 793, 662, 552, 461, 385, 321, 268, 224, 187, 156, 130, 109, time=0.286122.

DOWN: 109, 152, 214, 300, 421, 590, 827, 1160, 1627, time=0.165619.

EXAMPLES

ramp X up 200 to 1600 @ 20% to 0.1%

ramp Theta up 50 to 100 @1% to 20% + 100 to 700 @20% to 1%

ramp Mixer \

up 20 to 100 linear 40% \

slew 100 \

down 100 to 20 linear 60% \

recoil 0 \

hold 1.0

ramp Syringe2 \ up 50 to 400 linear 40% slew 400 down 400 to 50 linear 60% recoil 0 \

hold 0.3 // Temporary for homing

ramp Syringe2 hold 0 // Don't need hold for normal operation.

ramp TowerProbe recoil 0

ramp PeriPump slew 250

ramp M5 recoil 20,30,40 hold 0.75

ramp M5 up 5 to 200 exclusive linear 5%

ramp M5 down 200 exclusive to 5 linear 10%

ramp M5 up 20 to 300 in 10 steps

ramp M5 = MyTrajectory

ramp LyseSyringe = Ramp50_300 recoil 50,60 hold 0.5

ramp M5 up U5_200 slew 200 down D200_5 hold 1

ramp Syringe up 5,10,15,20,25 + 30 to 300 linear 20%, slew 300, down 300 to 30 linear 30%

ERRORS

Compile Time

Run Time

 

RAMPDEF

SYNTAX

rampdef rampName segmentList

rampName is the name, which must begin with a letter, that will be assigned to this ramp definition.

segmentList is exactly as described for the ramp command. It may contain as little as a single hold time or slew rate or as much as a complete trajectory.

DESCRIPTION

The rampdef statement is nearly identical to the ramp statement. The only differences are:

  1. a rampdef statement can appear only in a script whose execution unit is a stepper controller, for example one that begins with the statement begin ramps unit MSM. A ramp statement can appear in any script.
  2. rampName must be distinct from all analyzer configuration and reserved names. In particular, it cannot be the name of a motor, whereas the motorName in a ramp statement must be the name of a stepper motor.

Rampdef defines a ramp or trajectory for subsequent assignment to one or more stepper motors. There is no functional difference between a ramp simultaneously defined and assigned to a motor in a single ramp statement and one defined by rampdef and subsequently assigned by a ramp statement.

Rampdef can save memory in the stepper controller by allowing multiple motors to share a ramp definition, but this is insignificant, as most stepper controllers have sufficient ramp memory to support a full complement (up, down, and recoil) of maximum (118-step) ramps for all supported motors. Of much greater significance is that changing up, down, or recoil ramp assignments during normal operation may force the stepper controller to prune discarded ramps (no longer in use by any motor) from its memory. This "garbage collection" requires the CPU to perform work that otherwise serves no purpose. Ramp garbage collection can be reduced or eliminated by using rampdef statements to define ramps and ramp statements to assign them to motors.

When a ramp is defined in a ramp statement, it serves only the motor named in the statement. Having no name of its own, it can't be referenced in another ramp statement. Consequently, it becomes permanently useless if another ramp displaces it. For example, ramp SyringeA up 20 to 200 linear 25% defines and assigns an up ramp to SyringeA. This ramp has no name. A subsequent statement, such as ramp SyringeA up 20 to 200 linear 15%, can render the first ramp unusable. In fact, even reassigning an identical ramp to the motor causes the first one to be discarded. In contrast, a named ramp defined by rampdef is permanently loaded when the rampdef command executes.

That rampdef can enhance run-time performance doesn't means it should always be used to define ramps in lieu of defining unnamed equivalents in ramp statements. For one thing, ramp statements are considerably more convenient to use during development. A ramp defined by a rampdef command does not exist in the motor controller until that unit executes the command. For example, if the MSM serves as the motor controller for both itself and the APU and a script in the APU wants to change a motor's ramp, the MSM must execute the required rampdef command before the APU executes the ramp command. With a ramp command, either unit may at any time simultaneously define the ramp and assign it to the motor.

If a ramp is used only in special circumstances, it should be temporary (defined in a ramp command instead of rampdef). For example, a predictive diagnostic routine may generate many ramps for a motor to test to its SOA (Safe Operating Area). In this situation, not only is the garbage collection overhead immaterial but, additionally, ramp memory could quickly fill up with permanent ramps, whereas it will never become full with temporaries.

Both ramp and rampdef support ramp segment superposition. Up, down, and recoil ramps can be individually defined by rampdef statements and then combined into trajectories by other rampdef or statements. This will yield more efficient ramp memory usage as well as reduced script code duplication when individual ramp segments are shared. For example, two motors might use the same up, slew, and down ramps but only one requires a recoil. The most efficient means of realizing this would be to define the common trajectory in one rampdef and derive the ramp with recoil from this; e.g.

rampdef Ramp50_250 up 50 to 250 linear 30% slew 250 down 250 to 50 linear 40%

rampdef Ramp50_250R = Ramp50_250 recoil 50,60,50

Unlike up, down, and recoil segments, the slew rate and hold time are not stored in ramp memory but are, instead, stored with the motor. Consequently, they are included in rampdefs only for convenience. If a rampdef defines both up and down ramps, the slew rate would certainly be fixed and it would serve no purpose to require every ramp statement referencing the defined ramp to restate the slew rate. On the other hand, one motor might require a hold period with a given ramp while another would use the same ramp without hold. In this case, it is more efficient for the rampdef to define the ramp without hold and then include the hold as needed in ramp statements; e.g.

rampdef Ramp20_180 up 20 to 180 linear 20% slew 180 down 180 to 20 linear 40%

ramp LyseSyringe = Ramp20_180

ramp HgbLyseSyringe = Ramp20_180 hold 0.5

Rampdef statements may appear in any script executed by the targeted motor controller. Multiple files may contain rampdef statements. However, given that rampdef commands must execute before the ramps they define can be used, the most convenient approach is to put all rampdefs into one script that is routinely downloaded and executed before all others. Typically this script is included in the file that contains the Home script, which initializes all motors. Since ramps defined by rampdefs are permanent, the rampdef commands need only execute once unless the motor controller CPU is reset. Thus, script memory would be wasted if the rampdef script were to remain resident. To avoid this, the last statement of the script (which still needs an end statement) can delete the script itself. For example, if the script were named DefineRamps, the last statement would be delete DefineRamps.

EXAMPLES

rampdef U50_200L10 up 50 to 200 linear 10%

rampdef R50_200 = U50_200L10 slew 200 down 200 to 50 linear 20%

rampdef R50_200R = R50_200 recoil 50,60,50

ERRORS

Compile time and run time errors are the same as for the ramp command. However, the run time error "FAIL_NOTREADY, Insufficient ramp memory" is more likely to occur for both ramp and rampdef commands when there are rampdef commands, which produce permanent ramps. Temporary ramps can't overflow ramp memory because they exist only as long as they are in use by a motor. Since a motor controller supports a maximum number of motors and each can have at most three ramps (up, down, and recoil) and no ramp may contain more than 118 steps, there is a finite limit to the amount of memory consumed by temporary ramps. There is no limit to the amount of memory that permanent ramps may try to consume.

POWER

SYNTAX

power motorName powerList.

motorName is the name of a stepper declared in the configuration file.

powerList is an optionally comma-delimited list of powerAssignment.

powerAssignment is rampSegment optEqual powerLevel.

rampSegment is up, slew, down, recoil, hold, or idle.

optEqual is blank or =

powerLevel is high or medium or low or off

DESCRIPTION

The power command sets the power level of segments in a stepper motor's trajectory. The stepper controller sets the specified level at the beginning of the first step of a ramp (up, down, or recoil) or at the beginning of the hold or idle time. Like the ramp command, power supports superposition of assignments, replacing only the specified segments without affecting any other existing assignments.

Although power assignments can be changed at any time, the motor controller changes actual power settings only at segment transitions. For example, if a motor has already entered its slew segment, changing its slew power assignment will have no effect until the motor's next move command. If the motor is running forever (which means it must be in its slew segment) it will never respond to the change unless it is stopped and restarted. In contrast, any change to its slew step rate (i.e. ramp motorName slew rate) takes effect almost immediately. To stop applying power to a motor whose idle power is not off and that is not moving, it is necessary to first change the idle power to off and then issue a move command.

The up and slew segments are most the most sensitive to insufficient power levels because during these times the motor pulls against some force. If the power level is not high enough, step loss will occur. However, excessive power increases ringing, leading to noisier operation and possible step loss due to resonance. The lowest power setting that avoids step loss should be assigned to each segment. Obviously, off should not be used for any ramp or the slew segment. Typically, off is assigned to idle, but idle may require power to hold a position. Rarely should this power level be more than low and it should not be high unless the motor is never idle for more than a few seconds.

Power-based Recoil

A recoil segment provides a gross reversal of a motor's movement at the end of its trajectory. A more subtle reversal can be effected using the power command. Motors don't instantly stop at the center position of their last step but are carried somewhat beyond this by momentum. Assuming no step loss, the magnetic force of the last step phase will pull a motor back toward the detent position. The trajectory becomes a dying oscillation about this point as the decreasing momentum is increasingly dominated by the constant magnetic force. Reducing down ramp power will allow momentum to carry the mechanism further beyond the detent position, but it also reduces the recoil effect of the magnetic force. However, at this moment, the motor transitions to its hold segment if one is assigned. If hold power is high, the mechanism will be pulled hard back to the detent position, creating a more pronounced recoil. This effect could be used, for example, to increase the shearing of a fluid stream delivered by a stepper-driven syringe.

EXAMPLES

power SampInjMtr up medium slew medium down low hold high idle off

power Probe up = high, slew = high, idle low

power PeriPump slew medium

power Mixer idle off // Follow this with move Mixer +1 to effect the power change.

ERRORS

Compile Time

Run Time

 

TESTMOTOR

SYNTAX

testmotor time

time is float from 0.1 through 1.5

DESCRIPTION

The testmotor command applies a test voltage, for the specified time, to a scan chain comprising all of the stepper motors' windings connected in series. A capacitor is charged through the scan chain (i.e. the test voltage is applied to one end of the chain and the capacitor is located at the other). At the end of the charging time, the voltage on the capacitor is read and sent to the system master, thereby indicating the total resistance of all of the motors.

Some analyzer systems don't support this function and others support it using a different electrical method than the one described here. For some of the latter, the time parameter is irrelevant.

EXAMPLES

testmotor 0.2

ERRORS

Compile Time

Run Time

 

 

ECHO GROUP

[echo], [echolog], [echostate], [echocomment], [echotitle], [report], and [get]

ECHO and ECHOLOG

SYNTAX

echo "string" or echoComDevice

echoComDevice is ComDevice optOnOff

ComDevice is a COM_DEVICE declared in the analyzer configuration file.

optOnOff is blank, on, or off

echoLog "string"

string is a list of one to 240 characters. Double quote characters may be embedded in the string but the string must not comprise just one of these. Line continuation is only allowed before the string. The string itself must appear on one line. The string may contain any number of the following escape sequence:

\VARx

x is 0 through 99.

Each time the command executes, the run time value of the VAR replaces the escape sequence in the string.

DESCRIPTION

Echo and EchoLog are primarily used to send English messages from a script directly to the system master’s user interface and/or error log (DM_ECHO or DM_ECHOLOG message). Echo messages are displayed and stored in the error log, while echoLog messages are stored but not displayed. An alternate use of echo (but not echoLog) is to control relaying of messages received from a com device to the system master.

The English message form of Echo is only used during development (particularly regression testing of the script compiler and analyzer programs) because the user interface cannot be exposed to untranslated messages. EchoLog may be also be used during development but is more useful for normal operation, where it would be used to log events for diagnostic purposes. In this context, English-only is preferred in order to reduce the risk of subtle but important details, particularly obscure technical terms, being mistranslated.

Depending on the receiver of the echo message, if the first character of the string is '!', the string may be displayed specially. For example, the script debugger normally displays echo messages only in the received message window. However, if the first character is '!', the string will also be displayed in the command edit window. This is helpful when the debugger is operating primarily as a high-level instrument controller. Major events can be echoed to the command edit field, which is always exposed, while more detailed information can still be displayed in the message window.

The DM_ECHO message from the execution unit normally contains exactly the string (plus any VAR value replacements) from the CM_ECHO command message. However, it may also contain a time-stamp. The command testSystem EchoTime true turns on automatic time-stamping; testSystem EchoTime false turns it off. When time-stamping is on, the echoed string is preceded by, in parentheses, the value of the unit's main timer when the DM_ECHO message is enqueued. Typically, each timer count represents 5 msec. The timer runs continuously for up to 240 days. Consequently, the absolute value of any single time-stamp is usually not as important as the difference between two values. However, it is possible to establish a starting base time by resetting the timer. This can be done by the command reset idle whenever no scripts are executing wait or timed I/O commands.

Echo ComDevice causes the oldest message received from the device to be sent to the system master as a DM_ECHO message. The device message is always deleted from the unit's input buffer (there is no peek argument as for get com device item [Peek]). If no message has been received from the device, no message will sent to the system master.

Echo ComDevice on turns on continuous echoing of messages received from the device. Echo ComDevice off turns this off. While echoing is on, every message received from the device is immediately sent to the system master. Typically, this operating mode is used for testing and configuration, such as aligning a barcode reader.

EXAMPLES

echo "**** BEGIN REGTEST ****"

echo "Time is \VAR0"

echo "VAR14 = \VAR14 "

echo "Error: this should be closed mode"

echo \

"Line continuation before the string is allowed, e.g. for a long string when echo is indented"

echoLog "Several rack advances required to read barcode." // Check for slipping if this

// occurs frequently.

echo Barcode

echo Barcode on

echo Barcode off

ERRORS

Compile Time

ECHOCOMMENT

SYNTAX

echoComment "string"

string is a list of one to 240 characters. Double quote characters may be embedded in the string but the string must not comprise just one of these. Line continuation is only allowed before the string. The string itself must appear on one line. The string may

DESCRIPTION

EchoComment is used to insert a comment into the raw data (FCS) file of the next gather. The purpose of this is to associate sample preparation and fluidics information with each sample to assist subsequent analysis. For example, a comment telling the dilution ratio of a sample might help subsequent data reviewers understand a sudden change in data. This is primarily intended for research, as all aspects of production instruments are under version control and any information of this nature would be available from the version database.

Like echo and echoLog, echoComment supports only a literal English string. Also like echoLog, the normal user does not see the EchoComment string. Unlike echo and echoLog, echoComment does not support the VAR escape sequence.

EXAMPLES

echoComment "Experiment with 500:1 dilution and 30 seconds incubation at 40C"

gather Retics

ECHOSTATE and ECHOTITLE

SYNTAX

echoState stateName

stateName is an ECHO_STATE declared in the configuration file.

echoTitle titleName

titleName is an ECHO_TITLE declared in the configuration file.

DESCRIPTION

EchoState and echoTitle send to the system master a message (DM_ECHOSTATE or DM_ECHOTITLE) that contains a single number associated with the declared ECHO_STATE or ECHO_TITLE. The difference between these two commands lies in their different interpretation by the system master.

The system master uses the echoTitle number to retrieve and display a string from its translated string library, thus affording a limited (and controlled) means for the script domain to communicate directly with the user. Depending on the nature of the title, the system master may take additional action, such as recording an analyzer state change.

The system master uses the echoState number internally to synchronize to the analyzer. There is no direct relationship between this number and any user message. However, the system master may, as a consequence of an analyzer state change, elect to display one or more messages of its own choosing.

EXAMPLES

echoState BeginData

echoState PaddlePressed

echoTitle Aspirating

echoTitle RemoveSpecimen

ERRORS

Compile Time

 

REPORT

SYNTAX

report reportId extReport handler

reportId is int16 or a the name of a fault declared in the configuration file.

extReport is blank or extendedReport

handler is blank or noHandler

extendedReport is severityLevel qstring

severityLevel is int8 or severityName

severityName is LEVEL_LOG or LEVEL_INFORMATION or LEVEL_RESUME or LEVEL_RESET or LEVEL_INITIALIZE or LEVEL_REBOOT, which correspond to the numeric levels 1 through 6.

qstring is blank or "string"

string is a list of one to 230 characters. Double quote characters may be embedded in the string but the string must not comprise just one of these. Line continuation is only allowed before the string. The string itself must appear on one line.

DESCRIPTION

The report command is used to report faults that are detected in the script domain, such as wet vacuum accumulators or a dropped tube. System level faults, such as communication and nonvolatile memory errors are reported by get systemStatus.

The report command has short and long forms. The short form comprises a number or the name of a fault declared in the configuration file. Any literal number may be used, but if it corresponds to the number of a declared fault, the command will be interpreted as if that fault were named in the statement. Consequently, it serves no purpose to refer to a declared fault by its number, which is less intuitive and more likely to change than its name. A literal number should be used only when the fault is not declared in the configuration file, and this should not be the case for released scripts.

Like the short numeric ID form, the long form identifies the fault by a number and should only be used during development. In addition to the fault number, the long form tells the severity level of the fault and an English-only message to be displayed and/or logged. Intermediate forms are not allowed; if a severity level is given then a message string is required.

Both the short and long forms of report cause a message type DM_FAULT, correspondingly short or long, to be sent to the system master. The short form contains only the fault ID, which the system master uses to access a database of fault descriptors. Each descriptor, which is automatically created from the fault definition in the configuration file, contains the severity level and a message reference. The system master uses the message reference to retrieve the local language version of the message, if one exists, or the original English message given in the configuration file. The long form embeds this information in the message itself, giving the system master no opportunity to present a translated message to the user.

The short named (or coincidental number-name) form and the long form both provide a severity level, which the system master uses to determine its role in recovering from the fault. It can display the number of a short numbered form but can take no further action. Although this is insufficient for a released product, it is useful during development to avoid having to edit the configuration file (although this is trivial) and/or the foreign language libraries (which is not trivial).

By default the report command interpreter also checks to see if any script has been registered to handle the fault number (see begin [FaultHandler]). If one has, that script is started. Typically, each fault type is detected by only one script. If the fault requires any script domain response other than reporting to the system master, this response can be provided by one of three ways:

  1. The detecting script takes appropriate action.
  2. The detecting script forks a handler.
  3. A script registered to handle the fault is automatically started.

Normally, if either of the first two methods is implemented, there will be no script registered to handle the fault. Whichever script does handle the fault will use the report command to communicate the fault to the system master. The report command interpreter will waste a little time searching for a non-existent handler but this won’t create any serious problem. However, if the fault is detected in more than one script (or automatically by system software) and one handles the fault itself while the other depends on a registered handler, the fault could be handled twice. To avoid this possibility, the report command takes the optional parameter noHandler, which tells the report function to not try to find a handler. Any script that either fully handles a fault itself or knows that there is no handler should include this in the report command statement.

EXAMPLES

report 1000

report 500 LEVEL_RESET "New motor malfunction"

if EdgeVar = WatchTimeout

report NoSample

if WasteFull

report WasteFault noHandler

ERRORS

Compile Time

 

GET

SYNTAX

get optUnit getType

optUnit is blank or the name of an execution unit.

getType is faults or systemStatus or channelDevice or getComDevice

channelDevice is a CHANNEL_DEVICE declared as readable in the configuration file.

getComDevice is ComDevice item optPeek

ComDevice is a COM_DEVICE declared in the configuration file.

item is one of the items declared in the ComDevice declaration.

optPeek is peek or blank.

DESCRIPTION

The get command affords the script domain a means of retrieving run-time information from an execution unit and sending it immediately to the system master. Each of the four getTypes causes a different message (or group of messages) to be sent to the system master. SystemStatus evokes DM_SYSSTAT; channelDevice evokes DM_CHANDEV; and ComDevice evokes DM_COMDEV. If there is a registered faultReporter script (see begin [FaultReporter]) get faults causes that script to begin, and it will send one DM_REPORT message for each extant fault. If there is no such script, one bit-mapped fault list message, DM_FAULTS, is sent to the system master.

The faults reported by get faults involve devices or situations directly related to the script domain, particularly sensors defined in the configuration file. The analyzer program itself has little knowledge of these details. On the other hand, the program is directly involved with detecting and reporting system level faults. For a few system faults, the analyzer independently alerts the system master, but for most of them, the system master or a script has to ask for a system fault report with get systemStatus. Each unit in system can be independently queried. The DM_SYSSTAT message reply is in text form if the unit has executed a testSystem TextReply True command; otherwise in a binary structure that is not human-readable. The content can vary with the particular analyzer system, but the following list is typical. Each item is listed here with its full structure name and (in bold type) the abbreviated name used in the text form DM_SYSSTAT message. After successfully sending a DM_SYSSTAT message, the unit resets all error counters to 0.

Get channelDevice retrieves the current data from a device that has been defined as readable. The configuration language syntax description document fully describes CHANNEL device declarations. Briefly, the declaration must contain one of the clauses ACCESS = RO, ACCESS = RW, or READ = id, where id is a number from 2 to 255 (or a single-quoted character, e.g. 'A') that will be included in the message sent to the system master to identify the device. The READ clause can also simply be READ, implying that id is the previous id (not necessarily of the previous device, since a device can be declared without an id) plus 1. If the declaration includes a COUNT = max clause, each get command causes the current value in the device to be added to an array of up to max values. The system master determines what can be done with these values, but typically they can be displayed and saved as a group. Channel devices can also be read into a VAR using the VARxx = command [VarChannel].

To understand CHANNEL devices' relationship to the system master, it is instructive to consider the following excerpts from the APU’s configuration file:

Adc = 10 CHANNELS = 0-99 RANGE = 0-4095 ACCESS = RO

Hgb = Adc CHANNEL = 40

HgbSample = Hgb READ = HGB_SAMPLE COUNT = 6

HgbReference = Hgb READ = HGB_REFERENCE COUNT = 6

AdcBipolar = 11 CHANNELS = 0-99 RANGE = 0-4095 ACCESS = RO

Adc10VN = AdcBipolar CHANNEL = 04

AdcST15N = AdcBipolar CHANNEL = 52

Dac = 20 CHANNELS = 0-11 RANGE = 0-4095 ACCESS = WO

ch0Threshold = Dac ;0

ch10Threshold = Dac ;1

The Adc, AdcBipolar, and Dac all comprise multiple devices, as indicated by their CHANNELS definition. For example, get Adc 4 would send the current reading of Adc channel 4 to the system master. The message would tell the system master that the data was from device 10 channel 4. This message would be useful only if the system master either didn’t care what was attached to Adc channel 4, as for general diagnostics, or had embedded knowledge regarding Adc usage, which should be avoided. The other devices are defined as having only one channel. With properly selected IDs, readings from these can be meaningful even if the electrical configuration is unknown. For example, the script statement get HgbReference sends data that the system master can use knowing only the device ID. The HGB_SAMPLE and HGB_REFERENCE assigned as READ IDs are predefined values (respectively 2 and 3) which should only be used for these specific devices.

Get ComDevice sends the oldest existing message received from the com device to the system master. The DM_COMDEV message sent to the system master includes the item's ID as defined in the configuration file. The message from the device is conveyed as text; a flag in the DM_COMDEV message indicates this fact to the system master. Get ComDevice does not wait for a message from the com device. If one has not already been received, the single character '~' will be sent in its place. If the optional peek argument is included, the message is not deleted when it is retrieved. Peek is used to retain the message temporarily. For example, after get Barcode RackPos peek, the script can read the same barcode label into a VAR for its own use. Eventually, some command should read the device without peek in order to remove the message. The only other way to remove it is by clear ComDevice, which removes all messages.

A script uses get comdevice when the message from the device is directly associated with the device item. For example, if the com device is a barcode reader and the script rotates a sample tube in front of it, the resulting device message will be the sample barcode. The statement get Barcode Sample will then relay this to the system master. If, on the other hand, there is no directly applicable message to relay, such as the first rack position implied by the rack number barcode, the send command should be used.

EXAMPLES

get faults

get Msm faults

get systemStatus

get Slave systemStatus

get IoBus 250

get Psi9

get HgbSample

get Barcode Sample

get Barcode RackPos peek

ERRORS

Compile Time

Run Time

SEND

SYNTAX

send sendType

sendType is comDeviceMessage or varOrUiAs

comDeviceMessage is comDevice byteArray

comDevice is the name of a COM_DEVICE declared in the analyzer configuration file.

varOrUiAs is varOrUi as comDevice comDeviceItem

varOrUi is varId or int16

comDeviceItem is the name of one of the items contained in the declaration of comDevice in the configuration file.

varId is VAR0 through VAR99

DESCRIPTION

The send command is used for two different purposes, both related to a com device. One is to send a message to a com device. The other is to send the value in a VAR or a literal value (embedded in the script statement) to the system master, identifying it as one of the items associated with the device in its configuration declaration.

Send Com Device Message

A com device may be anything that communicates with the execution unit through text-based messages. Barcode readers are the most common type of com device. Messages are sent to a com device to configure it and to command it. Every device has a unique command language. Typically, command messages comprise text with leading and trailing characters that cannot be expressed as ordinary text. For example, the Opticon barcode reader requires each message to begin with the ESC character, whose value is 27, and end with the CR character, whose value is 13. These can be expressed in a byteArray either as escape sequences in a string or as numbers in a list.

Send As

Sometimes scripts need to read a message received from a com device only for their own internal use, for which they use varId = device. Other times they need to relay the message to the system master, for which get device item is most commonly used. Generally, the script knows the meaning of device's message because it controls activities around the device. For example, when the script moves a fresh sample rack into position, it knows that the next input from the barcode reader is the rack ID. Sometimes the script has to calculate or deduce a value that it wants to send to the system master and there is no device message that can be relayed. For example, if each position in a rack has a barcode, get Barcode PositionID might be used to relay this information to the system master. But if the first position is implied by the rack barcode, there is no position message to relay. In this case, send varId as Barcode PositionID or send 0 as Barcode PositionID could be used to send the value that the script deduces from other information.

Whether send as or get is used to convey a value to the system master, the same data message type, DM_COMDEV, is used. However, with send as the value is conveyed as an int16, whereas with get the same value is conveyed as a string. A flag in the message tells the system master which form is being used.

EXAMPLES

send Barcode "\x1BV6\x0D"

send Barcode "\X1BV6\X0D"

send Barcode 27 'V' '6' 13

send VAR20 as Barcode RackID

send 0 as Barcode PositionID

ERRORS

Compile Time

Run Time

None

 

READ-WRITE GROUP

[read] and [write]

READ

SYNTAX

read optUnit readType

optUnit is blank or the name of an execution unit.

readType is memory or version or configDevice

memory is address count size type

address is int32 (0 through 0FFFFFFFFh)

count is 1 through 240 or less, depending on size and type.

size is byte, bytes, word, words, long, longs, or blank.

type is text, binary, or blank.

version is version or version int8

configDevice is a CONFIG defined in the configuration file.

DESCRIPTION

The read command is used to read general or specific-purpose memory in the analyzer. For all readTypes, the data is sent to the system master; there is no command for reading memory from one part of the analyzer to another (e.g. VAR = address or address = address). Read supports development and instrument configuration and is not used by normal scripts.

Read memory accesses general memory. Each read memory command specifies:

Read version retrieves the version of the current or specified execution unit. The version int8 form allows the version of sub-units within one execution unit to be read. Read version and read version 0 both mean to read the main program version of the unit, e.g. APUAPP. The numbering scheme is unit-specific and the script compiler only enforces a generic int8 limit, 1 through 255. The version label is retrieved from memory without modification and sent to the system master in a DM_READVERSION message.

Read configDevice retrieves the string assigned to non-volatile memory elements, such as Kind, BcReader, and serial number. The device value (string) is sent to the system master in a DM_READCFG message, which also includes the single byte (character) ID of the CONFIG device. Some of these elements, such as Kind and BcReader, provide essential run-time information as well as supporting instrument configuration. In this context, read is not the appropriate command. To test a configuration item in order to select between branches of code, an if command should be used.

EXAMPLES

read 0 100 words

read 0ACF0h 10 longs binary

read Slave 0 100

read 0FFFFFF00h 200

read version

read Slave version

read version 1

read Kind

read BcReader

read Number

read Msm Number

ERRORS

Compile Time

Run Time

 

WRITE

SYNTAX

write optUnit writeType

optUnit is blank or the name of an execution unit.

writeType is writeMemory or writeConfig

writeMemory is address size values

address is int32 (0 through 0FFFFFFFFh)

size is byte, bytes, word, words, long, longs, or blank.

values is a byteArray or a single replaceable parameter, which must evaluate to the same size, byte (default), word, or long, as specified in the statement.

writeConfig is configDevice = byteArray

configDevice is a CONFIG defined in the configuration file.

byteArray may contain only values (characters) in the range defined for configDevice in the configuration file.

Note that writeConfig syntax is identical to that of configTest in the if command.

DESCRIPTION

The write command provides a means to initialize general or specific (e.g. memory-mapped I/O) memory in the execution unit. It accesses the same memory areas as read except for version, which identifies the unit’s program and should not be written (although a general memory write could do this). Write writeConfig is also very similar to the if configTest command. The two commands have identical syntax, because if tests exactly the same things that write initializes. Unlike if configTest, write writeConfig should be not be used in normal scripts, but only to configure the instrument.

Write memory supports writing to any address, including portions of nonvolatile memory. However, the command interpreter will not allow write to the BIOS or CONFIG device areas of nonvolatile memory. It also rejects attempts to write words or longs to any portion of nonvolatile memory. Each write memory command specifies:

EXAMPLES

write 1000 12h ABh DEh

write 0AC100h "Test version"

write 100 'T' 'h' 'i' 's' 100, 101, 102

write 5100h "\x1BV5\x0D"

write 01000h word 100,200,300

write 02000h longs 0ABCD1234h, 12345678h

write 51000h word @RBCGain

write Slave 100h 12h

write 200 1,2,3,4,5

write Number "123-A"

write Msm Number "123-B"

write Kind "A"

write Kind 'A' // Identical to previous.

write Kind 41h // Identical to previous two.

write BcReader "1"

write Kind SL // SL is defined as "S"

write BcReader Opticon // Config against single character (Opticon is alias of "1")

The last two examples are supported by the following definitions in the configuration file:

CONFIGS

Kind LENGTH = 1 RANGE = "CSA"

BcReader LENGTH = 1 RANGE = "12"

DEFINE

SL = "S"

Opticon = "1"

ERRORS

Compile Time

Run Time

MONITOR GROUP

[count], [gather], [stop gather], [sample], [watch], and [stop watch]

COUNT

SYNTAX

count gatherType [for] time [second[s]] optPeriod

gatherType is a GATHER device declared in the configuration file.

time is a float

optPeriod is blank or @ period

period is a float from 0.1 through 25.5.

DESCRIPTION

The count command starts a cell counting process that lasts for the stated time. The process terminates itself and there is no other means of stopping it. If another count command is issued before a previous one has finished, a run-time error is reported.

The script containing the count command advances immediately to the next command. A wait until count command can be used to wait for the process to finish.

The count process contains two separate but related processes, a high precision cell counter and a periodic list data count sampler. List data itself is collected by a simultaneous independent gather process. During the count time, the cell counter and the list data count are periodically sampled. Each pair of numbers tells how many cells were counted and how many cells were measured in the preceding period. The sampling period is 1/2 second (period = 0.5) by default but can be set to any value between .1 and 25.5 seconds (with 100 msec. real resolution) using the @ period clause. For most purposes, only the total count is actually needed, but the sampled correlated counts can be used to detect and roughly measure rate changes that may indicate cell breakdown ("declining rate") or flow changes. When the sampled counts indicate a declining rate, whether this is caused by cell breakdown or reduced flow rate can be ascertained by comparing the average cell size (simple average of the list data captured during a period) in the periods in question. If the average cell size shows no change, the apparent declining rate is caused by reduced cell flow and not by cell breakdown.

The cell counter begins within 5 msec. of processing the count command. The list count sampler begins within 100 msec. of this time (regardless of the sampling period). The count process sends DM_COUNT type messages to the system master. These tell the cell type (from the GATHERS descriptor) and contain a list of count pairs (cell count and list count). Depending on the sample period and count duration, multiple messages may be sent.

Typically, the gather process is stopped when the count finishes. This is not automatic but requires a stop gather command.

EXAMPLES

gather Reds

count Reds for 7.0 seconds @ 0.3

wait until count

stop gather

ERRORS

Compile Time

Run Time

count Reds for 7.0

count Whites for 7.0

 

GATHER

SYNTAX

gather gatherType

gatherType is a GATHER device declared in the configuration file.

DESCRIPTION

The gather command starts the list mode data collection process. The gather process comprises two overlapping phases, collecting of raw list (event) data and processing of that data. Collecting is done by hardware (DMA) in the analyzer. A software function called "parsing" follows behind the collector, transforming the raw data into (DM_LIST) messages and sending them to the system master. The parser may also perform decimation, a data reduction technique used when simultaneously collecting multiple cell types from one aliquot in which one of the cell types is expected to be significantly over-represented.

A gather can be stopped in three ways:

  1. By a stop gather command, which can optionally stop both collecting and parsing of event data or just the collecting.
  2. When the maximum counts specified in the gatherType declaration are reached. When this occurs, collecting immediately stops. When all of the collected data has been parsed and sent to the system master, the entire gather process is done.
  3. By another gather command. In this case, the previous gather will continue to parse cell events that have already been collected but not collect any more. No more than two gather processes can operate simultaneously and only one of them can be collecting.

The syntax of a GATHERS type declaration is described in detail in the configuration language guide. Briefly, the declaration comprises:

  1. The name, e.g. Reds or Whites, or a special gather for a standard type, e.g. TestReds.
  2. The ID to be used in list data messages (DM_LIST) sent to the system master.
  3. The channels to be collected.
  4. Whether to decimate and, if so:
    1. DCHAN is the channel used for the cell filter.
    2. HIGH and LOW are the low and high values of the filter window. Any cell whose value in the filter channel lies within this window is of the decimated type.
    3. FACTOR is the decimating factor, which tells the discard ratio. For example, if FACTOR is 5 then the data for 4 out of every 5 of the decimated cells is discarded. 0 means no decimation (this can also be expressed by not defining DCHAN, HIGH, LOW, FACTOR, UDMAX, or DMAX). 1 is illegal.
    4. If not decimating then COUNT is the maximum number of cells to collect.
    5. If decimating, UDMAX is the maximum number of undecimated cells to collect.
    6. If decimating, DMAX is the maximum number of decimated cells to collect. This is the number of raw cells. For example, if DMAX is 20000 and FACTOR is 5 then the maximum amount of data that will be sent to the system master is for 4000 cells.

  5. The bench used if the analyzer contains multiple (optics and/or impedance) benches.

In the following example of a GATHERS declaration:

Reds = 'A'

CHANNELS = 0,10,90

DCHAN = 0 LOW = 30000 HIGH = H_FFFF FACTOR = 5 UDMAX = 6680 DMAX = 26120

BENCH = 0

The GATHER name is Reds. List data will be sent as a DM_LIST subtype 'A' message. Channels 0, 10, and 90 are collected. Decimation is used. The filter channel is 0 and the window is all values at or higher than 30,000 (HIGH = H_FFFF means no upper limit). The decimated data will be reduced by a factor of 5. No more than 6680 cells of the undecimated type will be collected. No more than 26120 cells of the decimated type will be collected, which means that no more than 5,224 decimated cells will be sent to the system master.

DM_LIST messages contain only one gather type name. List data is sent in exactly the order that it is collected even if decimating. Decimated and undecimated cells are included in the same message. Otherwise, it would be impossible to relate the list data to the counts sampled by the count process. The system master can determine which cells represent the decimated fraction by checking their values in the filter channel.

When decimating, the gather process doesn't stop collecting the decimated cells until the count reaches DMAX, and it doesn't stop collecting the undecimated cells until that count reaches UDMAX. Inevitably, one of the fractions reaches its maximum before the other (unless the maxima are set so high that neither is reached). At the moment that this occurs, the count of the other fraction is recorded. The system master will need this information in order to properly apportion the cell count. Data collected after this point is useful only for analyzing the lagging fraction individually.

When a gather command is executed, in addition to starting the gather process, the command message is reflected to the system master to help it understand the ensuing list data messages. For example, algorithms may apply the inverse of the decimation factor to reconstitute decimated data. After sending the last list data message, the gather parser sends a GatherDone message, indicating the end of the gather process and providing details that can be useful for detecting and diagnosing both method and system errors. This DM_GATHERDONE message is described in more detail in analyzer interface documentation, but, briefly, it comprises the following:

EXAMPLES

gather Reds

gather Whites

gather Nocs

ERRORS

Compile Time

Run Time

 

STOP GATHER

SYNTAX

stop gather optGatherType stopType

OptGatherType is blank or the name of a GATHER defined in the configuration file.

stopType is terminate or blank.

DESCRIPTION

The gather process automatically stops collecting cell data when the count reaches the limit (or both limits if decimating) defined in the GATHERS declaration. The entire gather process is done when the parser sends the GatherDone message. Typically, the count maxima are set higher than the number of cells expected and serve mainly to avoid wasting processing and communication time on unnecessary data. The gather is stopped immediately or with a small delay after the count process ends using the stop gather command.

Normally, only the collection phase of the gather should be stopped, as the parsing phase may be lagging considerably. However, the optional argument terminate can be included to stop both phases. If the parsing phase is thus stopped, the parser will immediately send the GatherDone message.

For instruments that have multiple flow or impedance cells, specifying a gather type causes only that gather process to stop. Not specifying the gather type causes all gather processes to stop.

EXAMPLES

See typical usage sequence in count examples.

stop gather

stop gather terminate

stop gather reds

stop gather whites terminate

ERRORS

None reportable.

SAMPLE

SYNTAX

sample state

state is begin or end

DESCRIPTION

The sample command causes a sample message to be sent to the system master. Like echo and other "reflected" commands, this has no effect in the execution unit. It serves only to synchronize the system master with the script process.

The system master may do anything (including nothing) in response to sample messages reflected to it. However, the standard interpretation is that all data sent by the unit after sample begin and before sample end forms a distinct set. If the execution unit is capable of gather/count, this normally means that the data set comprises all of the data collected for a single sample, which typically includes the list mode and count data from one or more gathers plus other data, such as hemoglobin sample and reference readings. The system master normally responds to sample begin by resetting (or starting a new) data storage means and to sample end by finishing the store (e.g. by closing a file), transmitting, and/or displaying the data. Sample begin typically resets all relevant data stores, eliminating the need to reset individual devices [ResetChannelDevice].

EXAMPLES

sample begin

sample end

ERRORS

Compile Time

 

WATCH

SYNTAX

watch watchDevice for watchConditions

watchDevice is a SENSOR declared in the configuration file.

watchConditions is a white space or comma-delimited list of a combination (in any order) of watchState, watchVar, and watchTime

watchState is rising or falling or bubbles or leading or trailing or 0 or 1 or a 0/1 condition alias, particularly Blood or Air or Fluid or NoFluid, of watchDevice as defined in the configuration file.

watchVar is a VarId (VAR0 through VAR99)

watchTime is float [second[s]] (integer cannot be substituted for float here)

Syntax Semantic Qualifiers

  1. WatchState is required.
  2. The statement must include a timeout, which can be provided either by watchTime or watchVar, i.e. at least one of these must be present in the statement.
  3. The watchStates bubbles, leading and trailing can be used only if the watchDevice declaration specifies Blood, Air, Fluid, or NoFluid for at least one of the 0/1 alias names.
  4. If the watchState is bubbles then the statement must include watchVar.

DESCRIPTION

The watch command starts a process to monitor one sensor for a particular condition. Although this could be used to watch for any condition, the process is optimized for monitoring fluid (possibly consuming substantial CPU bandwidth) and should not be considered for other uses. All analyzers support at least two simultaneous watches. The CDM analyzer supports four.

The watchStates 0, 1, rising, falling, and bubbles all represent physical sensor conditions: 0 and 1; 0 followed by 1; 1 followed by 0; and repeated 0/1/0 transitions. Except for bubbles, these physical watchStates should generally be avoided because they expose the script to the electro-mechanical characteristics of the sensor. The symbolic conditions leading, trailing, blood, air, fluid, and noFluid should be used instead, because they represent the same phenomena in any system. Leading represents the transition from noFluid to fluid, trailing the transition from fluid to noFluid.

The watch process ends either when the stated condition (except bubbles) occurs or the timeout is reached. The timeout can be expressed literally by using watchTime or by a run-time-determined number of native ticks in watchVar (except for bubbles). If watchVar is used for the timeout, it is important that the VAR have a controlled value before the watch command executes. However, the script should not attempt to preload it with a literal number of ticks. Instead, this value is carried over from a preceding operation as part of an adaptive aspiration method. WatchVar can also serve as output from the watch process. If the intent is to use it only for this purpose and not also as the timeout (it can serve both purposes) then the statement should include watchTime, which, if present, always overrides watchVar as the timeout source. Although not recommended, "no timeout" can be requested by using 0.0 for watchTime or if watchVar (when there is no watchTime) has a run-time value of 0.

Watch for bubbles is a non-blocking command, which means that the script advances as soon as the watch process has been started. Also, the bubble watch doesn't end when bubbles are seen; the bubbles are counted and the watch continues. Watch for any other condition is blocking and causes the script to not advance until the watch process finishes. Therefore, one script can start at most two simultaneous watches and the first of those must be for bubbles. The only reason for a script to start two watches is to watch for bubbles at the inlet to a critical fluidic section while watching for the leading edge to reach the outlet sensor (or the trailing edge to reach the inlet). If the leading edge reaches the outlet without the inlet seeing bubbles, the critical section has a solid slug. Typically, the next statement after a blocking watch is a stop watch to stop the bubble watch. If more than two watches are needed simultaneously, additional scripts should be used.

For all watches except for bubbles, for which it is required, watchVar is optional. If present, in addition to its possible use as the timeout, it serves as the means by which the watch process reports its terminating condition to the script. Without this, the script doesn't know whether the watch ended due to timeout or condition. In some situations this may not matter but it normally does matter. If the watch terminates on condition, the duration of the watch is reported (in the VAR) in native ticks from 0 to 65,519 (0xFFEF). If the watch terminates on timeout, the value 65,535 (0xFFFF) is reported. WatchTimeout = 0FFFFh is defined in the configuration file to hide this magic number from scripts. A script can test the general termination cause by if varId = WatchTimeout.

The native tick duration of a blocking watch can be used to calculate timing for subsequent sample movement that is not guarded by sensor feedback. Initially, a known volume is drawn to a sensor. The time and volume provide a relative measure of the sample's mobility. The easiest formula for using this capability is based on tubing lengths, with cross-section, resistance, and back-vacuum differences folded into one constant. L1 is the length of the reference draw. L2 is the length of the subsequent timed draw. K is the empirically determined constant. Any VAR can be used as the reference tick count. The subsequent draw time is L2/L1 * K * VAR. Multiple timed draws can occur, possibly changing the K to reflect changes, such as increasing back-vacuum. The wait for and wait until commands accept any VAR as a native tick time parameter. This can be used to time a sample draw.

A bubble watch statement must identify a VAR that serves as both a dynamic command parameter and the means by which the watch reports its result to the script. As a command parameter, the VAR contains the number of native ticks in the trailing bubble count cutoff (0 means no cutoff). Normally, a certain portion of the end of the sample that passes through the bubble watch sensor does not become part of the aliquot. The cutoff discounts this portion in the bubble result. Using a VAR allows the cutoff portion to be automatically adapted to the mobility of the sample. The same formula used for calculating timed draws is used to calculate the cutoff time. L2 is the tubing length of the desired cutoff. A run-time error is issued if the VAR's value coming into the watch command specifies a cutoff that is too long for the bubble watch facilities.

For the result report, the bubble watch assigns the VAR a measure of the bubbles counted. The bubble watch (more or less) continuously reads the sensor, counting 1s and 0s. The value written to the VAR is the normalized count, which is the Fluid count divided by the NoFluid count. This is the only reason that a bubble watch can't be applied to a sensor which doesn't define fluid/noFluid aliases of 1/0. Without this information, the bubble watch couldn't produce its report. If the NoFluid count is 0 or the calculated result is larger than 65,535 then 65,535 will be reported. A result of 1 indicates that the sample is half air. Larger numbers indicate less air. Any result less than 10,000 is probably suspect.

Scripts should define VAR aliases, such as SvInputVar (Shear Valve Input) instead of using literals for watch and subsequent command arguments. Since scripts normally quickly consume these VAR values, local VARs (VAR0 through VAR7) are the most appropriate ones for this use. In all situations, except watch for non-bubble state when an explicit timeout is specified, the VAR should have a value coming into the command. The compiler warns if this does not appear to be the case (i.e. the referenced VAR is not the target of an assignment earlier in the script).

It is possible to watch for both bubbles and one of the other watchStates ("blocking watch") simultaneously on one sensor. This would be done in a one-sensor system. The sensor is located at the inlet to the critical fluidic section. Fluid is drawn up to the sensor (watch for leading edge). Then the sensor is watched for both bubbles and trailing edge while the fluid is drawn through the critical section. When a bubble and a blocking watch both watch the same sensor, if the blocking watch terminates before the bubble watch then it will also terminate the bubble watch. A normal watch report (into a VAR) is generated, but the bubble counts (both states) taken during the final 40 msec. (the stable state detector period) need to be discounted from the totals by adding 8 (8 * 5msec/tick = 40 msec) to the VAR's value coming into the watch bubble statement (otherwise calculated as explained above).

Watches are used both to control fluid and to detect errors. All errors, regardless of the particular conditions leading up to them, lie in three basic types, NoSample, ShortSample, and BubbleSample. Corresponding faults are declared in the configuration file of all analyzers. The report command is used to send these to the system master. The analyzer doesn't automatically send any messages related to watch to the system master.

  1. NoSample should be sent when the draw from the source to the first (or only sensor) incurs a watch Leading timeout.
  2. ShortSample should be sent for secondary draws that run out of sample. If a second sensor is used for feedback, ShortSample error is indicated if the Leading watch on this sensor times out. If the first sensor is used for feedback, ShortSample error is indicated if the Trailing watch on this sensor terminates by condition and the remaining time indicates that the delivery tube following this sensor does not contain sufficient fluid to meet the requirements. The L2/L1 * K * VAR formula can be used in this situation to compute the amount of aspiration time (and, therefore, fluid volume) remaining in the delivery tube.
  3. BubbleSample should be sent for secondary draws for which a bubble watch reports a small result (low ratio of fluid to air).

EXAMPLES

Syntax Variations

watch SvInput for Fluid, 3.5, VAR0

watch SvInput for Leading, 1.5 seconds, VAR0

watch SvInput for Bubbles, 0.5 seconds, VAR0

watch SvInput for Bubbles, VAR10

watch SvInput for Trailing, 3.5, VAR8

watch SvOutput for Blood 5.0, VAR7

Usage In Context

define EdgeVar VAR7

define BubbleVar VAR6

define OML2 9.0 // Open Mode aspiration length through Shear Valve.

define OML1 9.0 // Open Mode aspiration length from probe tip to S1.

define OMK 1.0 // Open Mode L2/L1 aspiration mobility factor.

open SmplAspirationVac

watch SvInput for Leading, 6.0, EdgeVar

close SmplAspirationVac

if EdgeVar = WatchTimeout

report NoSample

endif

// STEP 05: TRANSFER BLOOD SAMPLE TO SHEAR VALVE.

EdgeVar * OML2 / OML1 * OMK // Compute next aspiration time.

BubbleVar = 20 // Tick count for trailing bubble discount.

open SmplAspirationVac

wait for 0.5

watch SvInput for Bubbles, BubbleVar // Automatically remove trailing bubbles.

watch SvInput for NoFluid, EdgeVar // Watch for EdgeVar time or NoFluid.

close SmplAspirationVac

if EdgeVar != WatchTimeout

report ShortSample // NoFluid before timeout means short sample.

endif

if BubbleVar < 10000

report BubbleSample

endif

ERRORS

Compile Time

watch SensWbcLyse for bubbles, VAR10

watch SensWbcLyse for leading, VAR10

watch SensWbcLyse for trailing, VAR10

Run Time

 

STOP WATCH

SYNTAX

stop watch watchName

watchName is blank or all or sensorCondition

sensorCondition is sensorName [watchState]

sensorName is the name of a SENSOR declared in the configuration file.

Optional (square braces indicate optional-- not syntax) watchState is rising or falling or bubbles or leading or trailing or 0 or 1 or a 0/1 condition alias, particularly Blood or Air or Fluid or NoFluid, of sensorName as defined in the configuration file.

DESCRIPTION

The stop watch command can be used to stop any type of watch, but is most often used to stop a bubble watch. A bubble watch can be started with a timeout (stated in the command, as the VAR is used for another purpose) but this would be illogical in most circumstances. Instead, normally a fluid edge watch provides the trigger (timeout or condition) to stop watching. Then the script has to explicitly stop the simultaneous bubble watch, unless both watches are on the same sensor, in which case the bubble watch is automatically turned off.

One stop watch statement can stop multiple watches. The arguments determine the extent and specificity of the command as follows:

Stop watch is not like an abort but simply another terminating condition. All stopped watches respond as if they have timed out, including generating any requested reports (via VAR).

EXAMPLES

stopWatch

stopWatch all

stopWatch SvInput

stopWatch SvOutput Leading

ERRORS

Compile Time

MISCELLANEOUS GROUP

[initialize], [define], [message], and [reset]

INITIALIZE

SYNTAX

initialize optUnit device

optUnit is blank or the name of an execution unit.

device is steppers, motorName, ComDevice, SenseStrobe, or MsgDevice.

motorName is the name of one motor (see restrictions in description).

ComDevice is a COM_DEVICE declared in the analyzer configuration file.

SenseStrobe is a SENSE_STROBE declared in the analyzer configuration file (embedded in a sensor space declaration.

MsgDevice is a MSG_DEVICE declared in the analyzer configuration file.

DESCRIPTION

Initialize Steppers

The stepper motor controller supports both full-stepping and micro-stepping (as well as other synchronous types) motors. The two types have a different hardware interface and the controller treats them differently. The controller assumes that all steppers are full-stepping unless told otherwise. Micro-stepping and other synchronous motors are identified by one or more SYNCHRONOUS declarations in a STEPPER_MOTORS section in the analyzer configuration file. This information is conveyed to the motor controller by an initialize steppers statement, which the controller must execute before any micro-stepper can be moved.

When the controller executes initialize steppers, in addition to configuring support for synchronous motors, it establishes default power and ramp settings for all motors. These are identical to the settings established when the motor control unit is reset. Typically, this statement is the first one in a homing script and serves only to define the synchronous motors. However, during instrument development, the secondary effect of resetting the motor control system without resetting the unit can be useful. For example, if a script stops at a breakpoint leaving a motor in an idle state with power on, the motor may be difficult to move by hand. An interactive initialize steppers command turns all idle power settings to off.

The initialize steppers command is applied to the entire stepper control system. Each motor individually requires script-based homing and setting of position prior to effective use. After this, the command should not appear in normal scripts, as its execution will wipe out all application motor settings.

If the analyzer configuration file identifies only one execution unit as directly controlling steppers then the statement initialize steppers will be automatically translated to a message for that unit regardless of the execution unit of the script in which the statement appears. Otherwise, the message will be directed to the unit executing the script unless the statement names a unit.

Initialize MotorName

Initialize motorName is used with motors that require individual initialization, which currently includes only TriMotors (e.g. shear valve). The script compiler rejects statements that name a motor of any other type.

Initialize can be applied to only one TriMotor at a time. The command message (generated from the statement) contains a detailed description of the TriMotor taken from the configuration file. The analyzer stores this information for use in interpreting subsequent commands to the motor. It also immediately starts an automatic initialization routine that moves the motor to establish its position. This contrasts with stepper motors, which require scripts to find their home and establish their position.

Although it takes some time for the TriMotor initialization operation to execute, the script containing the initialize command is not automatically delayed. Even while one TriMotor is being initialized, the analyzer system can start initializing another. However, attempting to move a TriMotor that hasn't finished initialization will evoke a run-time error. To avoid this possibility, it is best to wait for the motor at some point (e.g. as the next command) after the initialize command.

One TriMotor can be repeatedly initialized. The analyzer program recognizes when a TriMotor is being re-initialized (by recognizing the motor's ID) and reuses the memory initially allocated for it. This might be done to reestablish control after a motor fault or system error. In this case, the same motor description information would be recorded. It is also possible for new information to replace the original. This would be done only during development to correct a TriMotor description (in the configuration file) without having the reset the analyzer.

Initialize Com Device

Initialize com device causes the communication interface associated with the device to be reinitialized. All previously received messages and all input (from the device) and output (to the device) messages in progress are deleted. If the device's declaration specifies Baud rate and/or parity, these are set. If not, the default values (9600 Baud with even parity) are set. This command is used only at system initialization and in error recovery.

Initialize SenseStrobe

Certain kinds of input bit devices, for example fluid sensors, do not continuously reflect the value of the measured phenomenon but instead must be strobed to capture a signal for subsequent reading. Such sensors and their strobes are realized as ordinary input and output bits with special behavior. The execution unit understands this behavior but does not know which bits it applies to, as this is application level information defined in the analyzer configuration file. SENSE_STROBES are declared within a SENSOR space. The declaration explicitly tells the SENSE_STROBE device name, the output bit that serves as the strobe, whether the strobe is active high or low, and the refresh rate of the strobe. The dependent sensors are implicitly declared by all of the sensor declarations in the space. Initialize SenseStrobe causes the execution unit to store this information for subsequent use. Whenever one of the dependent sensors is read, if its space has not been strobed for a longer time than the refresh period then the strobe is issued and, after an appropriate delay (determined by hardware and associated with the sensor space), the sensor is read.

Initialize Msg Device

Msg devices are often not physical devices but rather a byte stream used to initialize a unique device or memory. For these, initialize is a much more intuitive command name than message, which could mean anything [Message]. For these devices initialize is a source level alias for message. This serves only to make the script more readable. The same command message is generated in either case. The optional state argument accepted by message is not accepted by initialize.

EXAMPLES

initialize ShearValve // should be followed by wait for ShearValve

initialize Barcode

initialize steppers

initialize MSM steppers

initialize FluidSense

initialize Vpm // VPM's initialization message is defined as an MSG_DEVICE

ERRORS

Compile Time

Run Time

 

DEFINE

SYNTAX

define alias phrase

alias is any unreserved name or VarId

phrase is any group of characters.

DESCRIPTION

The simple description of define is that wherever alias appears, except in comments, the compiler substitutes phrase. The compiler processes the statement after substitution exactly as if phrase were literally in the source file. The purpose of define is to hide something, either because it is too complicated and inconvenient to repeat or because it may change and we don't want to have to change it in multiple places.

Normally, phrase extends to the end of the define line or the beginning of a comment. However, it can be extended over multiple lines using a backslash (the line continuation operator [LineContinuation]) in which case, each line can have its own comment (after the backslash) that is not included in phrase. Define can be used to create an alias for a single command statement or, by using the line compaction operator [CommandConcatenation], for multiple statements.

A define statement can occur anywhere in a script source file. Whether the statement occurs outside or inside of a script is immaterial-- the definition exists for the remainder of the script. It does not exist in other script files. In most cases, alias may be redefined, but the compiler issues a warning. If the redefining phrase is identical to the existing one, the compiler will warn about a "superfluous" redefinition. If it is different, the compiler will warn that alias is being redefined.

Global definitions, which are visible to all scripts, can be made in DEFINE sections of the configuration file. The syntax of the configuration DEFINE is somewhat different from that of the define statement, reflecting the section-orientation of the configuration language, but the two are functionally identical except for scope. The decision whether to use a configuration or statement define is a programmer prerogative but two rules are strongly encouraged even though the compiler won't enforce them. One is that no define statement should be repeated. If the definition is required in more than one script file, it should be made in the configuration file. The other is that hardware-aware definitions should be made only in the configuration file. For example, control (e.g. On, Off, Servoed) of a multi-state device may be defined by combinations of single-bit outputs (ACTUATORS). This affords a very simple means of extending the script language and is reliable if the author is well aware of the hardware domain. The configuration file represents the intersection of the scripting and hardware domains and thus is a reasonable venue for such a definition. In contrast, scripts should be as unaware of underlying hardware as is feasible.

One of the more common uses of define is to assign a particular usage to a VAR. VARs are a general resource. A VAR may serve one purpose in a particular context and a completely different purpose in another. When multiple statements refer to the VAR for a particular purpose, using an alias makes the script more readable and easier to maintain. If the VAR usage changes, a different VAR can be assigned to the same alias by changing just the define statement. VAR aliasing is so common that define has a special format for expressing a fixed usage called a hard Var. VarIds (VAR0 through VAR99) are the only reserved words that can serve in the alias position in a define statement. This does not redefine the VAR but instead says that the definition is permanent (in this source file-- or globally if a hard Var definition is made in the configuration file). The compiler will reject any attempt to use the VAR (in either role, as long as it appears singly) in another define statement. Further, the compiler warns about references to the literal VAR (instead of the phrase/alias), which suggests that the script writer is not aware of the hard definition. See usage in VAR command [HardVarUse].

EXAMPLES

define BubbleVar VAR6

BubbleVar = 20 // Tick count for trailing bubble discount.

watch SvInput for Bubbles, BubbleVar // Automatically remove trailing bubbles.

if BubbleVar < 10000

report BubbleSample

endif

define waitForPower wait for 0.5

waitForPower

define SDM2 RbcMixDrain \ // 24

SmplSyrSheath \ // 25

MainWbcLyse \ // 26. Normally closed

HgbLyseSyrOut \ // 27

WbcLyseSyrOut \ // 28

HgbDil \ // 29

RbcDil \ // 30

MainHgbLyse // 31. Normally closed

open SDM2

define StatusMsg "Bubble ratio is \VAR6" // Comment

echo StatusMsg

define waitType for

define waitTime 0.5

wait waitType waitTime

define EdgeVar VAR1 // Soft Var

define VAR1 EdgeVar // Hard Var

ERRORS

Compile Time

define test VAR0

define test VAR0

define test VAR0

define test VAR1

define VAR10 svinput

define VAR10 svoutput

define VAR10 svoutput

VAR10 = 1

define SDM2 RbcMixDrain \

MainHgbLyse \

end

MESSAGE

SYNTAX

message device [optEqual state]

syntax in square braces is optional

device is an MSG_DEVICE declared in the configuration file.

optEqual is = or blank.

state is a state name defined in the declaration of device

DESCRIPTION

The message command is used:

  1. for controlling devices that have a consistent logical but not physical structure across different instruments.
  2. for downloading instrument-specific data (system or method) to the analyzer.
  3. for development of new devices.

None of the reasons for a device requiring control via the message command are evident at the script level. Further, a device may be initially developed as a MESSAGE type and eventually become another existing type or an instance of a new type with more rigorous definition than MESSAGE. The initialize command may also be used with Msg devices [InitializeMsgDevice].

EXAMPLES

message PRES2 = servoed

message nonVolInitData

ERRORS

Compile Time

Run Time

 

RESET

SYNTAX

reset optUnit resetType

optUnit is blank or the name of an execution unit.

resetType is level or channelDevice.

level is slaveCom or idle or hard or level levelNumber

levelNumber is 0 though 9

channelDevice is a CHANNEL_DEVICE defined in the configuration file.

DESCRIPTION

Note that this is completely unrelated to wait reset. Reset level performs a software reset of the execution unit. The level affords a relative measure of how far back toward complete re-initialization that the unit will be taken. 0, which is the same as idle, is the softest reset, i.e. the one that goes back the least. 9, which is the same as hard, goes back as far as possible without physically resetting the system. SlaveCom resets only slave communication.

Reset idle is the only reset command that should appear in ordinary scripts. Its purpose is to maintain the long-term health of the unit. Its primary action is to reset the timer used for all timed activities in the unit. This must be done at least once every 240 days but may be done much more frequently. All timing in progress is maintained when the timer is reset. Resetting the timer executes quickly and doesn't interfere with most normal functions. However, some analyzers may also perform a self-check at this time, so it is a good policy to not invoke reset idle while processing a sample. A good time to invoke it is during a periodic or wakeup system initialization.

Only analyzer and/or system master programmers should use reset levels 1 through 9 (hard). The exact extent of intermediate reset levels depends on the analyzer program implementation and, in fact, may shift during development and debugging. The APU program of 1/16/2001 affords an example:

Levels 4 through 8 cause the application program to return to the BIOS program.

Levels 7 through 9 cause the execution unit to return to the BIOS startup code, 7 and 8 by retracing through the main BIOS program and 9 by a direct jump from the application.

Reset slaveCom should only be invoked after slave communication has failed. All messages directed toward the slave after the point of failure are discarded. This should only be done in lieu of rebooting the analyzer system, typically during script or program development. However, it might also be useful in automated extreme error recovery situations. If slave communication has failed, the system cannot be trusted, but regaining control to effect a safe mechanical situation is preferable to simply freezing the system.

Reset channelDevice serves either or both of two purposes, to reset the physical device or to cause a message to be sent ("reflected") to the system master telling it to reset whatever storage mechanism it has for the device. The execution unit determines how for itself how respond to a reset command directed toward a specific device. Typically, the message is sent to the system master when the indicated device comprises one channel but physical reset is performed if the device has multiple channels. The effect of this is to physically reset a base device, such as Adc, but to reflect a reset message for any of its derived channel devices, such as HgbSample. If a sample begin message [Sample] is sent to the system master, this is usually sufficient to reset all channel device stores, eliminating the need to reset individual devices (unless used for physical reset).

EXAMPLES

reset idle

reset Slave idle

reset hard

reset level 2

reset slaveCom // Reset the executing unit's slave communication.

reset Slave slaveCom // Remotely tell Slave to reset its slave communication.

reset Adc

reset HgbSample

ERRORS

Compile Time

Run Time

There are no run-time errors per se. However, reset levels 1 through 3 (at least in the APU system) cause a DM_SYSERR type message of subtype SYSERR_RESET1, SYSERR_RESET2, or SYSERR_RESET3 to be sent to the system master. These messages include explanatory text as follows:

 

 

TEST AND DEVELOPMENT GROUP

[version] [pragma], [simulate list], [simulate watch], [testsystem], [debugread]

For most of these commands, the script compiler affords only a modest level of syntax checking. Version and pragma generate no command messages but control compiler operation. The other commands generate command messages that cause the execution unit to operate in an unusual manner, which would be inappropriate for normal scripts.

VERSION

SYNTAX

version number

number is int32 excluding 0 (1 to 4294967295)

DESCRIPTION

Version associates a number with the current version of the file. The number is entirely arbitrary but is typically increased by 1 when any script in the file is functionally changed. Usually, comment and formatting changes do not trigger a version change. The version number does not affect the translation of the file but it is recorded in the compiled file, where it may be inspected to determine which version of the file is in use on the instrument.

The version statement may appear anywhere outside of a script. Typically, it is the first statement in the file. One version applies to the entire file. A similar int32 analyzer configuration file version number (the configuration language statement is version = number) and an int16 script compiler version number are also recorded in the compiled file. Additionally, the compiler computes and records an int16 CRC (checksum) for each script, which can identify those scripts that have changed and those that have not regardless of any change to the file version number.

EXAMPLES

version 100222

ERRORS (compile time only)

begin test

version 100

PRAGMA

SYNTAX

pragma onOffOpt pragType

onOffOpt is On or Off or blank

pragType is WarnActuatorRead or WarnSensorWrite or WarnLiteralHardVar or FailFatalErrors or HideEcho or Clear Ramps

DESCRIPTION

Pragma represents an instruction to the script compiler. It does not cause any command messages to be generated (directly from the pragma itself). The compiler issues warnings on syntactically legal but questionable practices, such as reading a device defined as an ACTUATOR. Most pragmas provide a means to turn off (and back on) specific warnings. A pragma statement can occur anywhere in a script source file. Whether the statement occurs outside or inside of a script is immaterial-- the effect exists for the remainder of the script or until reversed by a complementary pragma. Most pragma types are in complementary pairs, with On or blank turning on one state and Off turning on the complementary state. The pragTypes are:

There is no good reason for normal scripts to turn off WarnLiteralHardVar or FailFatalErrors. The literal VAR should never be used when a hard definition exists, and any script with fatal errors at best won't execute and at worst might damage the analyzer. The pragmas to turn these off exist for script compiler and interpreter testing.

There are several reasons why normal scripts might want to turn off the WarnActuatorRead and/or WarnSensorWrite warnings, such as:

  1. An entire device class in a particular analyzer system has unusual properties that are useful, such as ACTUATORS all providing feedback or Sensors all being writeable (e.g. requiring a write strobe to take a new reading). In this case, the warning would be turned off at the beginning of the source file and not turned back on.
  2. A single device uniquely has unusual properties that are useful. In this case, the warning can be turned off before accessing the device and back on afterward. There is no run-time penalty for repeatedly toggling the warning in this way and the impact on compile time is negligible.
  3. A particular section or an entire script, especially a diagnostic routine, accesses devices deliberately in a non-standard way. In this case, the warning is turned off just before the block begins and back on immediately after.

The purpose of the HideEcho pragma is to allow echo statements, which are helpful for development, to remain in production code without incurring a run-time penalty. A single pragma on HideEcho statement can turn off all echo messages in a script block or in an entire script source file. The echo statements can lie dormant until turned back on as needed for further development or debugging. As with all pragmas, HideEcho does not provide run-time control-- the affected script must be recompiled to restore or remove the echo messages from compiled scripts.

EXAMPLES

pragma off WarnActuatorRead

pragma on WarnSensorWrite

pragma on HideEcho

pragma HideEcho

pragma off HideEcho

pragma ClearRamps

ERRORS

Compile Time

SIMULATE LIST

SYNTAX

simulate list listDataOptions

listDataOptions is a combination of speed and cycle and patternName and wordPattern

speed is real or fast or slow

cycle is cycle optEqual integer

optEqual is = or blank.

patternName is ALPHA

wordPattern is a list of int16s.

DESCRIPTION

The simulate list command simulates the production of raw list mode data for testing the gather process. Data is simulated at the DMA source, allowing the entire data path from DMA to system master to be tested.

Data is simulated by storing a list of int16 words in memory and configuring DMA to read this instead of the ADC. Each int16 in wordPattern simulates the value read from one channel source. For example, the pattern 10, 20, 30 40 read by a two-channel gather (e.g. 10, 90) yields two events, 10/20 and 30/40. These repeat until the gather is done. However, the same pattern read by a three-channel gather yields a 10/20/30 event followed by a 40/10/20 event, etc.

The speed of source data, which is determined by cell flow rates in the real system, is not accurately simulated. Two speeds of simulation are provided: fast, which is approximately 200 times faster than real data; and slow, which is approximately 100 times slower than real data. The speed real restores normal operation-- the ADC feeding the DMA.

Two kinds of data patterns are supported, a named pattern embedded in the analyzer (either as a hard-coded list or a dynamic list built algorithmically) or an arbitrary list, wordPattern, defined in the command statement. Currently (2/11/2000) only one embedded pattern, ALPHA, exists. The ALPHA pattern comprises pairs of upper-case letters, i.e. AABBCC...ZZ. These are not strings but the binary values AABBh, CCDDh, etc. DM_LIST messages containing this data exhibit repeating patterns, which are easy to verify by eye. This is a good pattern for checking data flow but not necessarily the most useful for checking data algorithms in the system master.

Typically, the most useful pattern for verifying data flow is one that repeats synchronously with some characteristic of the system under test, such as the number of channels defined for the gather. The cycle parameter is used to specify the length to be used regardless of the underlying pattern length. For example, the ALPHA pattern with a cycle of three is AABBCCAABBCC...; the same pattern with a cycle of four is AABBCCDDAABBCCDD. When an arbitrary pattern is listed in the command statement, the cycle count is automatically the pattern length and any cycle phrase in the statement is ignored.

EXAMPLES

simulate list fast cycle = 8 ALPHA

simulate list real

simulate list slow cycle 3 ALPHA

simulate list fast 1234 5678 1234 0ABCDh

ERRORS

Compile Time

Run Time

 

SIMULATE WATCH

SYNTAX

simulate watch watchDevice simWatch [optComma simWatch]...

watchDevice is a SENSOR declared in the configuration file.

simWatch is watchState optForTime

optComma is , or blank.

watchState is bubbles or 0 or 1 or a 0/1 condition alias, particularly Blood or Air or Fluid or NoFluid, of watchDevice as defined in the configuration file.

optForTime is blank or for float [second[s]]

DESCRIPTION

The simulate watch command simulates fluid events at the given sensor for the purpose of testing analyzer software or scripts that contain watch commands. Simulate watch should not appear in normal scripts. The simulate watch statement essentially defines a fluid event script. Each simWatch tells a condition to simulate and the length of time to hold this condition. The simulation engine reads each simWatch, establishes the condition, and then begins timing. When the specified time has elapsed, the interpreter moves to the next simWatch. All but the last simWatch should have a non-blank optForTime clause, because "no timeout" is interpreted as infinite timeout.

The simulation engine does not operate unless a watch process is active. The normal sequence of commands is a simulate watch statement to set up a simulation script, which begins running at the next watch command.

The analyzer has an orthogonal I/O and functional relationship, which allows any I/O device, including an I/O mimic, to be attached to any complex behavior such as watch, TriMotor, or simulate. Thus, the watch process can be tested entirely in software, by using a memory location as the supposed sensor to be monitored by the watch and stimulated by the simulate watch command. The watch itself can't tell the difference between this and a real sensor.

EXAMPLES

simulate watch SvInSim Fluid

simulate watch SvInSim NoFluid

simulate watch SvInSim Bubbles for 3.0

simulate watch SvInSim Fluid for 0.8

simulate watch SvInSim NoFluid for 0.5, Fluid

simulate watch SvInSim Bubbles for 0.5, Fluid for 0.50, Bubbles for 0.5, NoFluid

ERRORS

Compile Time

Run Time

TESTSYSTEM

SYNTAX

testSystem optUnit systemFunction optArgs

optUnit is blank or the name of an execution unit.

systemFunction is nativeSystemTestFunction or a name listed in a SYSTEM_TEST section in the configuration file.

optArgs is blank or a space-delimited list of one or more int16s or TRUE or FALSE

nativeSystemTestFunction is BusFault, IllegalInstruction, AddressAlign, DivideBy0, ComFault, Irq, FsqText, Fsqs, Procs, PowerDowns, TqFreeSpace, HeapStack, MotorCpu, Scripts, WipeNonVol, TextReply, EchoTime, IgnoreCmdFail, ReportJoins, ReportDones, DebugFlag, or the name of a motor.

DESCRIPTION

The testSystem command provides special test, development, and configuration functions. It should not be used in normal scripts. There are two kinds of testSystem functions, native and extended. Native functions are a permanent part of the script language. Their names are intrinsic to the compiler but not reserved. That is, these names could also be used for device or device state names, although such usage could be confusing. Extended functions are named in a SYSTEM_TEST section of the analyzer configuration file. Native function names should not be used for extended functions; the compiler will not complain but will simply generate the native function message.

Native and extended functions differ only in that the compiler inherently recognizes the native function names. Native functions are identical in name, syntax, and operation on all units that execute them but any particular execution unit may not execute all of them. Extended functions are unit-specific. Different units may accept the same extended function by name, in which case they may interpret it in the same way or uniquely. Extended functions afford execution unit developers a means of controlling unique features without having to change the script compiler in any way.

By design, the compiler performs very little syntax checking on testSystem statements. This makes it easy to add new functions, but it also means that the compiler provides little protection against erroneous statements. In no case will the compiler or an execution unit crash because of statement errors, but the desired result may not be achieved. The compiler requires either a native or extended function name but provides no indication when required numeric arguments are missing or the statement contains meaningless extra arguments. Superfluous arguments in no way effect execution but some missing arguments may be replaced by random values that the execution unit may not perceive as erroneous.

Many testSystem functions (most of the native ones) require no arguments and many of those that do take a single argument of FALSE (or 0) or TRUE (or any value but 0). Although this argument is required, the compiler provides a default value of TRUE, which, in most cases, turns on some feature. Frequently, this is the desired behavior, because all special test features can be turned off by rebooting. For example, the statements testSystem EchoTime TRUE and testSystem EchoTime produce identical results. The EchoTime feature is turned off by rebooting or by executing the statement testSystem EchoTime FALSE.

The native functions BusFault, IllegalInstruction, AddressAlign, DivideBy0, and ComFault force the unit to execute run-time errors. Some of these errors are severe and would crash other systems, but all CDNext compliant execution units catch these errors before they can cause any damage, restore communication (if required), and report the nature and program address (if applicable) of the offender. The purpose of these testSystem functions is to confirm compliance.

The native functions FsqText, Fsqs, Procs, PowerDowns, TqFreeSpace, and HeapStack report resource utilization for the purpose of determining headhoom, i.e. how close the unit has come to exhausting a limited resource. The other native functions provide various configuration and reporting services.

EXAMPLES

testSystem ShearValve

testSystem BusFault

testSystem IllegalInstruction

testSystem AddressAlign

testSystem DivideBy0

testSystem ComFault FAULT_SLAVE_UNDER_FATAL

testSystem Irq 6 FALSE

testSystem Irq 6 TRUE

testSystem HeapStack

testSystem Msm Scripts

testSystem Scripts

testSystem WipeNonVol 0

testSystem WipeNonVol 1

testSystem TextReply True

testSystem FsqText

testSystem MotorCpu

testSystem ReportJoins True

testSystem ReportJoins False

testSystem TxTimeout 327

testSystem Msm TxTimeout 3

testSystem DebugFlag 5

ERRORS

Compile Time

Run Time

All other run-time failures are deliberately induced by various testSystem commands to check the program response.

DEBUGREAD

SYNTAX

debugread control optUnit bitDevice

control is on, off, or blank

optUnit is blank or the name of an execution unit.

bitDevice is a FLAG, SENSOR, ACTUATOR (with compiler warning) identified by name space:address tuple or address (within the first SENSOR space).

DESCRIPTION

Scripts read bit devices using the if command, which combines four operations: reading one or more devices, testing each against a value, combining the tests (if multiple devices), and branching according to the result. This is convenient and efficient for normal operation, but not for interactive development. Debugread affords a means of simply reading a single bit in one of a unit's defined spaces.

While debugread is legal in a script, it would serve no purpose, as the language contains no means of acting in response to the bit's state. It is expected that either the script writer will directly observe the unit's response message or, more likely, the script debugger will parse and display the response, which contains considerably more information than simply the device's state.

If control is blank, the target unit reads the device state immediately and sends the response message. This also occurs if control is on, but additionally the target begins monitoring the device for changes. In this state, if the device is an actuator or flag then every script command that effects the device causes the target to send another state message. If the device is a sensor, the target repeatedly samples it and sends a message whenever its state changes. The sampling rate varies with the target's workload but typically ranges from 500 usec to 5 msec. If control is off, the device monitor is turned off.

For direct reading by the script writer, the target's state message tells the device state as '0' or '1' and, if monitoring an actuator, the name of the script that has accessed it. The message also contains, in binary, the time (5 msec. resolution) of the sample and the script message number. The script development system can convert the time to its human-readable form and the message number to the corresponding script source line number.

EXAMPLES

debugRead ShearValveFaultdebugRead RackAdvancedebugRead APU 1:2

debugRead on ShearValveFault

debugRead off RackAdvance

debugRead APU2 off 1:2

debugRead on 3:4

ERRORS

Compile Time