frig_data_structures (ul_friglib)

			FRIG Data Structures

	This document contains updated information on the devices and
	structures used by the cryogenic refrigerator systems.

	The refrigerator systems support nine distinct object types:

	1. Operations	Operations are fired from within a running FSM by
			transition rules and action rules.  Operations can
			also be fired manually by page F13. Once an operation
			is fired it works "backwards" reading the branches of
			its input tree.  The furthest branches of the tree
			will be processed first, with the results working
			their way back through the tree. When the calculations
			for the entire tree have been completed the result is 
			available for reading.  512 operations are supported.

	2. Timers	Timers provide a method to keep track of time.  Timers
			can be read within a running FSM by operations,
			transition rules and action rules and can be set/fired
			within a running FSM by actions and action rules.
			64 timers are supported.

	3. Storages	Storages provide a method to store a value.  Storages
			can be read by operations, transition rules and action
			rules and set by actions and action rules. 64 storages
			are supported.

	4. Actions	Actions are fired from within a running FSM by action
			rules.  Actions can also be fired manually by page F13.
			Once an action is fired, it works "forward" pushing
			information through the branches of its output tree.
			An action takes one input and passes it unfiltered to
			1 or 2 outputs.  256 actions are supported.

	5. States	States consist of two distinct parts; action rules and
			transition rules.  When the FSM enters a state, the
			respective action rules are executed exactly once.
			Action rules provide a method for the states to read
			devices and set devices.  Transition rules allow the
			FSM to switch to another state based on selected
			parameters.  Transition rules are processed at a fixed
			periodic rate.  128 states are supported

	6. FSMs		FSMs are the highest level of hierarchy contained
			within the refrigerator systems.  FSMs consist of a
			collection of states including which state is the
			initial state and which state is the final state.
			32 FSMs are supported.

	7. Events	Events tie ACNET events into finite state machine
			operation.  Events can be used as inputs to action
			rules or transition rules as well as inputs to
			operations. Single Events correlate to single ACNET
			events and can have the status of undefined, waiting
			for event, or event occurred.  64 events are supported.

	8. Filters	Filters allow a reading from an input device to be
			filtered.  Currently filters support two filtering
			types, time averaging smoothing and Butterworth
			filtering.  50 filters are supported.

	9. Loops	Loops allow the input to a device to be controlled
			via a PID feedback control loop based on the output
			of a device.  Loops can be combined with filters.
			25 loops are supported.

	Please note: The description field for all devices is padded with
		     nulls for all unused characters.  Page F13 requires at
		     least 1 null to terminate the description field in order
		     to work properly.  This effectively makes the maximum
		     description length 31 characters.

		     The unused fields present in several devices are filled
		     with zeroes.

		     A setting structure is considered to be fully undefined
		     if all of its members have a value of 0. The exceptions
		     to this rule are:
		     FSM_SET initial, final and FSM_READ current, history are
		     set to -1 by the micro to indicate undefined when the
		     FSM is undefined by setting num_states = 0

	Operations
	----------

	An operation can have 1 or 2 inputs and can perform several types of
	operations on the inputs.  An input can be a constant float, a constant
	int, a constant short or any readable device at the respective house
	which returns a float, an int, or a short.

	An operation can be fired from within a running FSM by transition
	rules, and action rules.  F13 also has the ability to fire operations
	manually.  Operations only calculate a result when fired.

	Once an operation is fired, it looks at its inputs. If the input is a
	readable device, timer, or storage, the value is simply read in.  If
	the input is another operation, the input operation is fired.
	If operation B is an input for operation A, then the result of
	operation B is calculated and used as an input to calculate the result
	for operation A.  Recursion is not allowed for operations, i.e. an
	operation cannot be an input to itself directly or indirectly.  If
	recursion is attempted, the micro will detect it and produce an error.
	When all inputs are read in and the desired calculation is performed,
	the result is made available for reading.

	Depending on the operation type (below) the operations are internally
	handled by the micro in either float or integers and produce either a
	float or an int result. The representation of inputs and result values
	is user selectable as either floats or ints. (SETTING property)

	Operation types are listed below along with the inner representation
	of operands and the result.

	Operation Type  Name             Operand Data Type  Result Data Type
	1  +            Addition               float              float
	2  -            Subtraction            float              float
	3  *            Multiplication         float              float
	4  /            Division               float              float
	5               Integration            float              float
	6  abs(x)       Absolute value         float(unary)       float
	7  sqrt(x)      Square root            float(unary)       float
	8  ln(x)        Natural logarithm      float(unary)       float
	9  exp(x)       Exponet                float(unary)       float
	10 sin(x)       Sine                   float(unary)       float
	11 cos(x)       Cosine                 float(unary)       float
	12 >            Greater than           float              integer
	13 >=           Greater or Equal       float              integer
	14 <            Less than              float              integer
	15 =            Equal                  integer            integer
	16 !=           Not Equal              integer            integer
	17 &&           Logical AND            integer            integer
	18 ||           Logical OR             integer            integer
	19 ^            Get bit                integer            integer
	20 ~            Logical NOT            integer(unary)     integer

	Please Note: 1. The integration operation is a substitute of the row
			operation which existed in the old FRIG.  The algorithm
			for integration is:
			if (oper1 > oper2) then memory = memory + oper1
			else memory = 0;
			The result of the operation is memory.
		     2. The get bit operation interprets operand 1 as a 32 bit
			value (4 bytes) and operand 2 as a bit number (0-31).
			The result of the operation is simply the value of the
			bit selected by operand 2 in operand 1 (0 or 1).  For
			example: operand 1 = 0x0001 and operand 2 = 0 produces
			a result of 1.

	The relevant structures for operations are:

	typedef struct
	    {
	    int	di;				// device index
	    short	pi;				// property index
	    union
		{
		char	ssdn[LEN_SSDN];			// device SSDN
		float	fcon;				// float constant
		int	icon;				// integer constant
		} data;
	    short	type;				// data type
	    short	len;				// length of data
	    short	offset;				// offset of data
	    } DEV_DATA;

	typedef struct
	    {
	    union
		{
		float	f_result;			// float result
		int	i_result;			// integer result
		} result;
	    } OPER_READ;

	#define	FRIG_INPUTS_PER_OPERATION	2	// number of inputs per operation

	typedef struct
	    {
	    short	defined;	(read only)	// defined flag
	    short	status;		(read only)	// status of the last read
	    union
		{
		float	f_value;			// float result
		int	i_value;			// integer result
		} result;		(read only)	// result of the last read
	    short	oper_type;			// operation type
	    short	num_operand; (clears structure if 0) // number of operands
	    short	reply_type;	(0 = float)	// type of reply
	    DEV_DATA	input_devices[FRIG_INPUTS_PER_OPERATION];	// description of input devices
	    char	description[FRIG_DESCRIPTION_LEN];	// descriptive ASCII text
	    short	user_tag;			// user assigned tag value
	    int		unused[2];			// spare storage
	    } OPER_SET;

	typedef struct
	    {
	    short	defined;			// defined flag
	    } OPER_STATUS;

	typedef struct
	    {
	    short	command;			// clear last result command
	    } OPER_CONTROL;

	Explanation of DEV_DATA members as they pertain to operations

	Device Index (DI) and Property Indices (PIs) for inputs (operands):

	special constants	DI = -1, PI < 0  type is always set to short
	data constants		DI = -1, PI = 0  type is float, int or short
	previous result		DI = -1, PI = 1  floats used by micro internally
	device's basic status property	DI = device's DI, PI = PRBSTS  SSDN
	device's reading property	DI = device's DI, PI = PRREAD  SSDN
	device's setting property	DI = device's DI, PI = PRSET   SSDN

	Please note: special constants are interpreted by the micro as data
	constants.  The micro does not change the PI, but instead leaves it
	untouched.  The PI < 0 is used by ul_friglib routines to determine
	which text string to associate with a given constant.  Since more
	than 1 text_string can map to a given constant, a PI < 0 is used by
	the friguti routines to build up a 1 to 1 mapping.

	Please note: All calculations in the micro are handled by the micro
		     as floats.

	type
	----
	0 = float
	1 = int
	2 = short

	if DI > 0, then the data field is interpreted as a SSDN

	length
	------
	length of data to be returned.
	float length = 4
	int length = 4
	short length = 2
	any other length is illegal

	offset
	------
	For reading devices, offset is the offset into the device for the
	desired data.
	Please note: When using frig objects, library routines such as
	frig_dev_data_to_pname_c make the offset and length transparent
	when using psuedo name devices.  For constants and previous results,
	the offset is ignored.

	Please note: 
	The micro requires the DI, PI, data and type for each input device
	to come in the same request.

	Setting of the number of operands to 0 results in the micro setting
	the device to undefined.

	Setting the DI = 0 results in the micro setting the respective
	operand to undefined.

	ACNET properties summary:
	OPER_READ is the structure returned by the READING property for 
	operations.  The value returned is the result of the operation.
	The READING property will fire the operation.

	OPER_SET is the structure used to send data for the SETTING property
	and to return data for the READING of SETTING property.

	OPER_STATUS is the structure returned by the BASIC STATUS property.
	The following masks indicate the repsective status for the operation:
	#define	FRIG_IS_DEFINED		1	

	BASIC CONTROL for operations is defined to be clearing of the last
	result field.  2 bytes of data is sent to the micro but is ignored.

	Actions
	-------

	An action can have 1 or 2 outputs.  The number of effective outputs
	can be increased by chaining actions together.  An action takes an
	input value when it is fired and outputs the value to its outputs.
	The input value, (and hence the output value) can be either an int
	or a float. An output can be any writable device at the respective
	house which takes a float, an int, or a short.

	An action can be fired from within a running FSM by action rules.
	The primary device for actions is used to fire an action. The sibling
	device is used to set the various parameters not pertaining to firing
	an action.

	The relevant structures for actions are:

	#define	FRIG_OUTPUTS_PER_ACTION	2	 // number of outputs per action

	typedef struct
	    {
	    short	defined;	(read only)	// defined flag
	    short	num_output; (clears structure if 0) // number of outputs
	    short	input_type;			// type of input
	    int		sdi;				// device index of the primary device
	    DEV_DATA	output_devices[FRIG_OUTPUTS_PER_ACTION];	// description of output devices
	    short	status;				// status of last action
	    char	description[FRIG_DESCRIPTION_LEN];	// descriptive ASCII text
	    short	user_tag;			// user assigned tag value
	    int		unused[2];			// spare storage
	    } ACTION_SET;

	typedef struct
	    {
	    union
		{
		float	f_value;			// float value
		int	i_value;			// integer value
		} result;
	    } ACTION_VALUE;

	typedef struct
	    {
	    short	defined;			// defined flag
	    } ACTION_STATUS;

	Explanation of DEV_DATA members as they pertain to actions

	Device Indices (DIs) and Property Indices (PIs) for outputs:

	device's setting property         DI = device's DI, PI = PRSET   SSDN

	ACNET properties summary:

	Primary device:
	ACTION_VALUE is the structure used to send data to the micro for
	the SETTING property and to return data from the micro for the
	READING of SETTING property.  The SETTING property has the effect
	of firing the action. Action rules can fire an action.  Page F13
	can also do this by using the SETTING property.

	The BASIC STATUS property for the primary device returns information
	regarding the status for the last time the action was fired.

	Sibling device:
	ACTION_SET is the structure used to send data for the SETTING
	property and to return data for the READING of SETTING property.

	ACTION_STATUS is the structure used to return the BASIC STATUS property.
	The following masks indicate the repsective status for the action:
	#define	FRIG_IS_DEFINED		1	

	Timers
	------

	A timer is an object which counts down variable amounts of time.

	A timer is fired when an amount of time (set time) is written to
	the timer via the  primary device.  Timers can be set/fired by
	actions and action rules.  The count value remaining for a timer
	can be read by operations and transition rules via the primary device.
	Page F13 can set/fire a timer manually.  The sibling device is used
	to set the various parameters not pertaining to setting the count or
	firing a timer. 

	A timer decrements one tick every 1 second. If the value of the timer
	becomes < = 0, the timer will deactivate itself.

	The relevant structures for timers are:

	typedef struct
	    {
	    short	defined;			// defined flag
	    int		sdi;				// primary device index
	    short	user_tag;			// user assigned tag value
	    char	description[FRIG_DESCRIPTION_LEN];	// descriptive ASCII text
	    short	active;				// active flag
	    short	unused_word;			// spare storage
	    int		unused;				// spare storage
	    } TIMER_SET;

	typedef struct
	    {
	    int		counter;			// timer counter value
	    } TIMER_VALUE;

	typedef struct
	    {
	    short	defined;			// defined flag
	    } TIMER_STATUS;

	ACNET properties summary:

	Primary device:
	TIMER_VALUE is the structure used to send data for the SETTING
	property and to return data for the READING of SETTING property.
	The setting property has the effect of setting the count and
	starting (firing) the timer.  The READING of SETTING property will
	return the original set time, not the current remaining time count.

	TIMER_STATUS is the structure used to return data for the BASIC STATUS
	property.  The following masks indicate the repsective status for the
	timer:
	#define	FRIG_IS_DEFINED		1	
	#define	FRIG_IS_ACTIVE		4	

	TIMER_VALUE is the structure used to return data for the READING
	property and gives the remaining count for a timer.

	Sibling device:
	TIMER_SET is the structure used to send data for the SETTING property
	and to return data for the READING of SETTING property.

	Storages
	--------

	A storage can hold a value, either a float or an int.

	A storage can be written to by an action or an action rule.  A storage
	can be read by an operation, transition rule or an action rule.

	The relevant structures for storages are:

	typedef struct
	    {
	    short	defined;	(not read only)	// defined flag
	    union					// setting value
		{
		float	f_value;			// float value
		int	i_value;			// integer value
		} setting;
	    short	type;				// data type
	    short	user_tag;			// user assigned tag value
	    char	description[FRIG_DESCRIPTION_LEN];	// descriptive ASCII text
	    int		unused[2];			// spare storage
	    } STORAGE_SET;

	typedef struct
	    {
	    union
		{
		float	f_value;			// float value
		int	i_value;			// integer value
		} setting;
	    } STORAGE_READ;

	typedef struct
	    {
	    short	defined;			// defined flag
	    } STORAGE_STATUS;

	ACNET properties summary:

	STORAGE_SET is the structure used to set the value stored in a
	storage as well as set the various parameters not pertaining to
	setting the stored value.  STORAGE_SET is used for the SETTING
	property and the READING of SETTING property.

	STORAGE_READ is the structure used to return data for the READING
	property and gives the value stored in the storage.

	STORAGE_STATUS is the structure used to return data for the BASIC
	STATUS property.  The following masks indicate the repsective status
	for the storage:
	#define	FRIG_IS_DEFINED		1

	States
	------

	A state consists of a set of action rules which are executed upon
	entry to the state and a set of transition rules which are executed
	at a set, periodic interval.  By definition, in any given FSM only 1
	state can be active at a time.

	Transistion rules fire a designated operation and read the result or
	can read any device at the respective house which returns an int,
	a short, or a float result.  If the result is TRUE (1), then control
	passes to the state assigned to the respective transition rule.
	Transition rules are processed at a 1hz rate.  Transition rules are
	processed in order, and the first one satisfied will result in a
	state transition if the respective FSM is still activated.

	One state can belong to several different FSMs.  Consequently, it is
	possible to have a transition defined to go to a state which is not
	a member of the current FSM.  In this case, the FSM will ignore
	transition rules which specify a transition to a state which is not
	currently a member of the FSM.

	Action rules consist of an input part and an output part.  An input
	can be a constant float, a constant int, a constant short, or any
	readable device at the respective house which returns a float,
	a short, or an int. The output part can be any writable device at
	the respective house which can receive a float, a short, or an int.
	An action rule automatically connects the input part with the output
	part. Thus an action rule couples a device which is read with a
	device which is written by writing the read value.

	Please note: Action rules are fired by the micro in the sequence
	they are written.  However, if an FSM is fired as one of the action
	rules, it will be started immediately at its predefined initial state
	or the given goto state.  Be advised: The action rules from this
	state in the new FSM will be fired before the original set of action
	rules are completed.  The nesting for this process is limited only by
	the number of FSM's the micro supports.

	Device Indices (DIs) and Property Indices (PIs) for input part:

	data constants                    DI = -1, PI = 0
	previous result                   DI = -1, PI = 1?? 
	device's basic status property    DI = device's DI, PI = PRBSTS
	device's reading property         DI = device's DI, PI = PRREAD
	device's setting property         DI = device's DI, PI = PRSET

	The micro only allows transition rules and action rules to be
	set/read in their entirety.

	The relevant structures for states are:

	#define	FRIG_TRANS_RULES_PER_STATE	8	// number of transition rules per state
	#define	FRIG_ACTION_RULES_PER_STATE	8	// number of action rules per state

	typedef struct
	    {
	    int		di;				// device index
	    char	ssdn[LEN_SSDN];			// device SSDN
	    short	offset;				// offset of data
	    } OPER_DEF;

	typedef struct
	    {
	    DEV_DATA	operation;			// operation to be fulfilled
	    OPER_DEF	state;				// state to which transition is to be done
	    } TRANS_RULE;

	typedef struct
	    {
	    DEV_DATA	setting;			// setting value
	    DEV_DATA	action;				// action object
	    } ACT_RULE;

	typedef struct
	    {
	    short	defined;	(read only)	// defined flag
	    short	active;		(read only)	// active flag
	    short	num_trans_rules;(read only)	// number of defined transition rules
					// however, if set to 0, micro clears entire
					   data structure regardless of rest of data
	    short	num_act_rules;	(read only)	// number of defined action rules
	    char	description[FRIG_DESCRIPTION_LEN];	// descriptive ASCII text
	    short	user_tag;			// user assigned tag value
	    int		num_fsms;			// number of FSMs presently using this state
	    int		time_active;			// number of seconds this state has been active
	    TRANS_RULE	transitions[FRIG_TRANS_RULES_PER_STATE];	// transitions
	    ACT_RULE	actions[FRIG_ACTION_RULES_PER_STATE];	// actions
	    } STATE_SET;

	typedef struct
	    {
	    short	defined;			// defined flag
	    } STATE_STATUS;

	ACNET properties summary:

	STATE_SET is the structure used to set the information pertaining
	to a state.  STATE_SET is used for the SETTING property and the
	READING of SETTING property.

	STATE_STATUS is the structure used to return data for the BASIC STATUS
	property.  The following masks indicate the repsective status for the
	state:
	#define	FRIG_IS_DEFINED		1
	#define	FRIG_IS_ACTIVE		4

	Finite State Machines
	---------------------

	An FSM is a collection of states, including an initial state and a
	final state.  The FSM also maintains a history of the last 8 states
	active for the FSM.  When an FSM is activated, the history is
	completely cleared and restarted.  A finite state machine can be
	enabled or disabled.  An FSM needs to be enabled in order to be
	activated.  If a respective FSM is active, states belonging to the
	FSM cannot have their SETTING property changed.  A currently active
	FSM can be disabled.  It will be automatically deactivated first.
	An FSM's initial or final states can only be changed if the FSM is not
	active.  The micro will not accept SETTING property if it is active.
	However, if the enable field has a value of 0, the micro will accept
	the SETTING property and will deactivate the FSM before disabling it.
	If an FSM is activated, attempting to activate it will result in an
	error.  In order to restart an FSM at a desired state, it must first
	be deactivated, then activated.

	When a FSM is activated, it will start with the initial state or
	another selected state as chosen by the BASIC CONTROL property.  If
	the FSM reaches the state declared to be the final state, the FSM
	will deactivate itself.  If there is no final state declared or the
	FSM never reaches the final state, it will run indefinitely or until
	it is deactivated or disabled.

	The relevant structures for FSMs are:

	#define FRIG_STATES_PER_FSM	16		// number of states per FSM

	typedef struct
	    {
	    short	defined;	(read only)	// defined flag
	    short	num_states;	(read only)	// number of states used
					// however, if set to 0, micro clears entire
					   data structure regardless of rest of data
	    short	active;		(read only)	// active flag
	    short	enable;				// enable flag
	    short	initial;			// initial state
	    short	final;				// final state
	    char	description[FRIG_DESCRIPTION_LEN];	// descriptive ASCII text
	    OPER_DEF	states[FRIG_STATES_PER_FSM];	// state definitions
	    } FSM_SET;

	#define	FRIG_HISTORIES_PER_FSM	8		// number of histories per FSM

	typedef struct
	    {
	    short	current;			// current state
	    short	history[FRIG_HISTORIES_PER_FSM];	// history of states
	    } FSM_READ;

	typedef struct
	    {
	    short	defined;			// defined flag
	    } FSM_STATUS;

	typedef struct
	    {
	    short	command;			// activation command
	    } FSM_CONTROL;

	ACNET properties summary:

	FSM_SET is the structure used to set the information pertaining to
	an FSM.  FSM_SET is used for the SETTING property and the READING
	of SETTING property.

	FSM_READ is the structure used to read the current state and the
	array of state histories for an FSM.  FSM_READ is used for the
	READING property.

	FSM_STATUS is the structure used to return data for the BASIC STATUS
	property.  The following masks indicate the respective status for
	the FSM:
	#define	FRIG_IS_DEFINED		1		// structure is defined
	#define	FRIG_IS_ENABLED		2		// structure is enabled
	#define	FRIG_IS_ACTIVE		4		// structure is active

	FSM_CONTROL is the structure used to send data for the BASIC CONTROL
	property.  The BASIC CONTROL property is used to set the desired
	starting state, or indicate the FSM should start at the previously
	declared initial state.  This property is also used to activate or
	deactivate the FSM.  Please note: The use of ul_friglib routines
	makes the intimate knowledge of the BASIC CONTROL property bit fields
	transparent.

	Events
	------

	An event is an object which allows finite state machines and
	associated objects to have knowledge of the current status of ACNET
	events.

	An defined event can be in one of two states; waiting for event or
	event occurred.  This status can be input into action rules or
	transition rules within state objects or can be an input into
	operation objects.

	The relevant structures for events are:

	typedef struct
	    {
	    short	defined;			// defined flag
	    unsigned short	ftd;			// requested event in the form of an FTD
	    unsigned int	delay;			// delay after event in milliseconds
	    short	user_tag;			// user assigned tag value
	    char	description[FRIG_DESCRIPTION_LEN];	// descriptive ASCII text
	    } EVENT_SET;

	typedef struct
	    {
	    short	status;				// status flag
	    } EVENT_STATUS;

	typedef struct
	    {
	    short	command;			// switch from event occuured to waiting for event
	    } EVENT_CONTROL;

	ACNET properties summary:

	EVENT_SET is the structure used to send data for the SETTING property
	and to return data for the READING of SETTING property.

	EVENT_STATUS is the structure used to return data for the BASIC STATUS 
	property.  The following masks indicate the respective status for the
	EVENT:
	#define	FRIG_IS_DEFINED		1	// structure is defined
	#define FRIG_HAS_OCCURRED	16	// structure event has occurred

	EVENT_CONTROL is the structure used to reset the event status via the
	BASIC CONTROL property. The event status is reset from 2 to 1 if the
	event is defined.  BASIC CONTROL does nothing if the event is
	undefined.  The data in the command field is ignored by the frig micro.

	Filters
	-------

	A filter is an object which reads an input device and performs one
	of two types of filtering on the input, time averaging or Butterworth.

	The relevant structures for filters are:

	typedef struct
	    {
	    int	di;				// device index
	    short	pi;				// property index
	    char	ssdn[LEN_SSDN];			// device SSDN with embedded offset
	    } FILTER_INPUT_DEVICE;

	typedef struct
	    {
	    int	input_depth;			// depth of the input stack (averaging)
	    float	boundary;			// boundary for smoothing algorithm
	    } FILTER_SMOOTHING_PARAMS;

	typedef struct
	    {
	    float	lower_frequency;		// lower frequency filter parameter
	    float	upper_frequency;		// upper frequency filter parameter
	    float	lower_gain;			// lower frequency gain filter parameter
	    float	upper_gain;			// upper frequency gain filter parameter
	    int	input_depth;			// depth of the input stack
	    int	input_depth;			// depth of the input stack
	    int	output_depth;			// depth of the output stack
	    float	numerator_coeffs[10];		// numerator coefficients
	    float	denominator_coeffs[10];		// denominator coefficients
	    } FILTER_BUTTERWORTH_PARAMS;

	typedef struct
	    {
	    int	algorithm;			// algorithm (0 -> smoothing, 1 -> Buttterworth)
	    FILTER_INPUT_DEVICE	input_device;		// filter input device
	    FILTER_SMOOTHING_PARAMS	smoothing;	// smoothing algorithm parameters
	    FILTER_BUTTERWORTH_PARAMS	butterworth;	// Butterworth algorithm parameters
	    char	description[FRIG_DESCRIPTION_LEN];	// descriptive ASCII text
	    short	user_tag;			// user assigned tag value
	    short	enable;				// enable flag
	    } FILTER_SET;

	typedef struct
	    {
	    float	output;				// filter output
	    } FILTER_READ;

	typedef struct
	    {
	    short	status;				// status flag (1 -> enabled, 0 -> disabled)
	    } FILTER_STATUS;

	typedef struct
	    {
	    short	command;			// enable or disable a filter
	    } FILTER_CONTROL;

	ACNET properties summary:

	FILTER_SET is the structure used to send data for the SETTING
	property and to return data for the READING of SETTING property.

	FILTER_READ is the structure used to return data for the READING
	property.

	FILTER_STATUS is the structure used to return data for the BASIC STATUS
	property.  The following masks indicate the respective status for the
	FILTER:
	#define	FRIG_IS_DEFINED		1		// structure is defined
	#define	FRIG_IS_ENABLED		2		// structure is enabled

	FILTER_CONTROL is the structure used to enable or disable the filter
	via the BASIC CONTROL property.  The following values are used to
	control a filter:

	bit 0 - define filter
	bit 1 - enable filter

	Loops
	-----

	A loop is an object which performs a PID control loop.  A selectable
	input is defined as is sampled periodically with a minimum period of
	1 second.  The loop object read the value of the input and calculates
	the value of the output variable.  If the output device is defined,
	the calculated value of the output is set. 

	Loops can be in 3 different states:

	disabled - nothing is happening
	enabled  - all the operations are fulfilled, but no setting is
		   performed on the output device
	active   - normal loop operation

	Loops support two loop algorithms:

	open loops 
	closed loops - extended cryo version of PID algorithm

	The relevant structures for loops are:

	typedef struct
	    {
	    int	di;				// device index
	    char	ssdn[LEN_SSDN];			// device SSDN with embedded offset
	    } DEV_SIMPLE;

	typedef struct
	    {
	    int		enabled;			// loop enable flag
	    int		active;				// loop active flag
	    int		algorithm;			// loop algorithm
	    DEV_SIMPLE	input_device;			// loop input device
	    DEV_SIMPLE	output_device;			// loop output device
	    int		output_sibling;			// loop output sibling device
	    int		sample_time;			// loop sample time
	    int		fast_sample_time;		// loop fast sample time
	    int		fast_sample_active;		// loop fast sample time active flag
	    float	set_value;			// loop set value (volts)
	    float	max_output;			// loop output device maximum value
	    float	min_output;			// loop output device minimum value
	    float	max_output_change;		// loop output device maximum change
	    float	min_output_change;		// loop output device minimum change
	    float	constants[6];			// loop constants
	    float	error_tol;			// loop maximum error tolerance
	    float	min_error;			// loop minimum error (deadband half width)
	    float	e_values[5];
	    int		unused[4];			// unused data area
	    } LOOP_SET;

	typedef struct
	    {
	    union
		{
		float	f_value;			// float value
		int	i_value;			// integer value
		} result;
	    } LOOP_READ;

	ACNET properties summary:

	LOOP_SET is the structure used to send data for the SETTING property
	and to return data for the READING of SETTING property.

	LOOP_READ is the structure used to return data for the READING property.

	BASIC_STATUS simply reads the enabled and active flags from the LOOP_SET
	structure and returns them.  The following masks indicate the
	respective status for the LOOP:
	#define	FRIG_IS_ENABLED		2		// structure is enabled
	#define	FRIG_IS_ACTIVE		4		// structure is active

	Related functions:

	frig_get_c, frig_get_status_c, frig_get_value_c, frig_get_global_c,
	frig_cancel_get_c, frig_cancel_get_global_c, frig_build_list_c,
	frig_build_global_list_c, frig_put_c, frig_fire_c,
	frig_dev_simple_to_pname_c, frig_dev_data_to_pname_c,
	frig_oper_def_to_pname_c, frig_fsm_current_state_c,
	frig_activate_fsm_c, frig_deactivate_fsm_c, frig_enable_fsm_c,
	frig_disable_fsm_c, frig_name_to_type_c, frig_type_to_name_c,
	frig_parse_name_c, frig_default_delete_c, frig_default_get_c,
	frig_default_put_c, frig_file_delete_c, frig_file_get_c,
	frig_file_put_c