287 lines
13 KiB
OpenEdge ABL
287 lines
13 KiB
OpenEdge ABL
\subsection{Environment Controller}
|
|
An environemnet controller controls a piece of sample environemnet
|
|
equipment. Thereby it does not really matter if the device in question
|
|
is a temperature controller or a magnet or whatever. All devices need
|
|
to be driven to a new value and there must be some scheme for
|
|
monitoring the device during a measurement. This monitoring is done by the
|
|
environment monitor described in the kernel section of this book.
|
|
|
|
Then there must be some type of logging facility. SICS defers logging to
|
|
a separate module, the varlogger.
|
|
|
|
The Environment Controller (EVControl) is a kind of base class for all
|
|
environment devices. This poses the question how SICS implements
|
|
inheritance. The scheme is simple:
|
|
\begin{itemize}
|
|
\item The base class (in this case EVControl) will hold a void pointer.
|
|
Derived classes are meant to add their datastructures at that level.
|
|
Furthermore derived classes are required to provide a function, which
|
|
deletes its private data.
|
|
\item When overloading functions of the base class, the derived class
|
|
should call the overloaded function of the base class whenever apropriate.
|
|
\end{itemize}
|
|
|
|
|
|
|
|
\subsubsection{Environment Controller Datastructures}
|
|
To enhance understanding of this, see the definition of the datastructure
|
|
used by EVControl:
|
|
@d evdata @{
|
|
typedef struct __EVControl {
|
|
pObjectDescriptor pDes;
|
|
pIDrivable pDrivInt;
|
|
pEVInterface pEnvir;
|
|
pICallBack pCall;
|
|
int callCount;
|
|
pEVDriver pDriv;
|
|
EVMode eMode;
|
|
float fTarget;
|
|
time_t start;
|
|
time_t lastt;
|
|
char *pName;
|
|
char *driverName;
|
|
char *errorScript;
|
|
ObPar *pParam;
|
|
int iLog;
|
|
pVarLog pLog;
|
|
int iWarned;
|
|
int iTcl;
|
|
int iStop;
|
|
SConnection *conn;
|
|
char *creationArgs;
|
|
char *runScript;
|
|
void *pPrivate;
|
|
void (*KillPrivate)(void *pData);
|
|
} EVControl;
|
|
@}
|
|
|
|
The first field is a pointer to the usual object descriptor,
|
|
the second field a pointer to an Drivable interface. Each environment
|
|
controller needs to implement that in order to allow SICS drive the device
|
|
to a new value. The third field is a pointer to an environment interface.
|
|
This is needed in order to enable monitoring of the device when it has
|
|
reached its target value. Then there is a pointer to a callback
|
|
interface. The fifth field is a pointer to the driver for
|
|
the actual hardware. Next is the mode the device is in. Of course there
|
|
must be floating point value which defines the current target value for the
|
|
device. start and lastt are used to control the settling time.
|
|
|
|
pName is a pointer to a string representing the name of the
|
|
controller. driverName is the name of the driver used by this
|
|
device. errorScript is the name of a script command to run when the
|
|
controller goes out of tolerance.
|
|
Then there is a
|
|
parameter array. iLog is a boolean which says if data should be logged
|
|
for this controller or not. pLog is the a pointer to a Varlog structure
|
|
holding the logging information. Then there is a switch, iWarned, which is
|
|
used to prevent execessive output on environment controller error handling.
|
|
iTcl is a boolean stating if the driver used is a proper C language driver
|
|
or a Tcl driver.
|
|
creationArgs are the arguments needed to recreate the device. runScript
|
|
is a script called on every run or drive command. This script is intended
|
|
to set control parameters depending on the targetValue. The script is
|
|
called with the target temperature as argument.
|
|
This is followed by the void pointer for use by a derived
|
|
class. KillPrivate is a pointer to a function capable of deleting pPrivate
|
|
properly.
|
|
|
|
|
|
For the hardware drivers for environment controllers a similar scheme is
|
|
used:
|
|
|
|
@d evdriv @{
|
|
typedef struct __EVDriver {
|
|
int (*SetValue)(pEVDriver self, float fNew);
|
|
int (*GetValue)(pEVDriver self, float *fPos);
|
|
int (*GetValues)(pEVDriver self, float *fTarget,
|
|
float *fPos, float *fDelta);
|
|
int (*Send)(pEVDriver self, char *pCommand,
|
|
char *pReplyBuffer, int iReplBufLen);
|
|
int (*GetError)(pEVDriver self, int *iCode,
|
|
char *pError, int iErrLen);
|
|
int (*TryFixIt)(pEVDriver self, int iCode);
|
|
int (*SavePars)(pEVDriver self, FILE *fil);
|
|
int (*Init)(pEVDriver self);
|
|
int (*Close)(pEVDriver self);
|
|
void *pPrivate;
|
|
void (*KillPrivate)(void *pData);
|
|
} EVDriver;
|
|
@}
|
|
|
|
If not stated otherwise, member functions return 0 on failure and 1 on
|
|
success.
|
|
This datastructure in detail: \begin{description}
|
|
\item [SetValue] Sends a command to the environment device which drives it
|
|
to a new value specified as second parameter. Translation to device specific
|
|
values is done here. If an error occurs, SetValue returns 0, else 1.
|
|
\item [GetValue] Asks the device its current measured value.
|
|
If an error occurs, GetValue returns 0, 1 on success and -1 when there is
|
|
data pending. GetValue will be used for enquiring status. Some devices have
|
|
such a slow response that the first call will issue the command and the next
|
|
ones will check for data availability and read eventually.
|
|
\item [Send] Sends the command in pCommand to the environment device. For
|
|
replies, a pointer to a ReplyBuffer is provided. iReplBufLen is the maximum
|
|
length permissable for the ReplyBuffer. Send copies maximum iReplBufLen
|
|
bytes into pReplyBuffer in order to prevent memory overwrite. The idea of
|
|
send is to provide a means to load calibration data and parameters to the
|
|
environment device.
|
|
\item [GetError] GetError will be called when an error occurs. It is meant
|
|
to set iCode to an internal error code and fill pError with an textual
|
|
description of the error observed. Maximum iErrLen bytes of information
|
|
will be copied to pError.
|
|
\item [TryFixIt] TryFixIt will be called with the internal error code
|
|
retuned by GetError in iCode as second parameter. TryAndFixIt then analyses
|
|
the error code and figures out if something can be done in software to fix
|
|
the problem. If so, the apropriate actions are performed. TryFixIt returns
|
|
either DEVOK, if the device is OK, DEVFAULT, if TryFixIt cannot fix the
|
|
problem and DEVREDO if TryFixIt manged to fix the problem but requires the
|
|
last command to be resent.
|
|
\item [SavePars] Saves persistent parameters to status file.
|
|
\item [Init] Init is meant to initialise or reinitialise the driver.
|
|
\item [Close] Close is meant to close the driver and bring the device into a
|
|
safe state.
|
|
\item [pPrivate] is a pointer to a driver specific datastructure.
|
|
\item [KillPrivate] is a pointer to a function which is capable of removing
|
|
a drivers specific datastructure properly.
|
|
\end{description}
|
|
|
|
\subsubsection{Environment Controller Funtions}
|
|
All of the functions below return 1 on success, 0 on failure if not stated
|
|
otherwise. Most functions take a pointer to an environment controller
|
|
data structure as first parameter.
|
|
|
|
@d dvfunc @{
|
|
/*--------------------------- live & death --------------------------------*/
|
|
typedef struct __EVControl *pEVControl;
|
|
typedef struct __EVDriver *pEVDriver;
|
|
|
|
pEVControl CreateEVController(pEVDriver pDriv, char *pName, int *iErr);
|
|
void DeleteEVController(void *pData);
|
|
pEVControl MakeEVController(pEVDriver pDriv, SConnection *pCon,
|
|
ObjectFunc wrapper, int argc, char *argv[]);
|
|
/*-------------------------- driving ---------------------------------*/
|
|
int EVCDrive(pEVControl self,SConnection *pCon, float fNew);
|
|
int EVCGetPos(pEVControl self, SConnection *pCon,float *fVal);
|
|
|
|
/*------------------------ parameters ----------------------------------*/
|
|
EVMode EVCGetMode(pEVControl self);
|
|
int EVCSetMode(pEVControl self, EVMode eNew);
|
|
int EVCSetPar(pEVControl self, char *name, float fNew, SConnection *pCon);
|
|
int EVCGetPar(pEVControl self, char *name, float *fVal);
|
|
int EVCList(pEVControl self, SConnection *pCon);
|
|
/*------------------------- logging -----------------------------------*/
|
|
pVarLog EVCGetVarLog(pEVControl self);
|
|
/*----------------- Interface to SICS interpreter -----------------------*/
|
|
int EVControlWrapper(SConnection *pCon, SicsInterp *pSics, void *pData,
|
|
int argc, char *argv[]);
|
|
|
|
int EVControlFactory(SConnection *pCon, SicsInterp *pSics, void *pData,
|
|
int argc, char *argv[]);
|
|
|
|
|
|
@}
|
|
The functions in more detail:
|
|
\begin{description}
|
|
\item [CreateEVController] CreateEVController creates and initialises a
|
|
EVController. All interface functions are initialised with default
|
|
functions. The first parameter is a pointer to the driver to use, the second
|
|
the name of the thing.
|
|
\item [DeleteEVController] cleans a EVController from memory. A
|
|
KillFunction type for the SICS interpreter.
|
|
\item [EVCDrive] drives an EVcontroller to the new value fNew.
|
|
\item [EVCGetPos] retrieves the actual value of the environment value from
|
|
the device. It is put into fVal.
|
|
\item [EVCSetPar] sets a parameter in the EVControllers internal database.
|
|
name is the name of the parameter, fNew the value it should get. A
|
|
connection object is passed in this call, which will be used for error
|
|
reporting and in order to check if the client is permitted to change the
|
|
parameter.Parameters recognized are:
|
|
\begin{description}
|
|
\item [Tolerance] The permissable deviation from the target value before an
|
|
error is raised.
|
|
\item [Access] which user id has permission to access this controller.
|
|
Permited values are: 0 == internal, 1 == Manager, 2 == User, 3 == Spy.
|
|
\item [ErrorHandler] determines which error handling strategy will be used
|
|
if the EVcontroller gets out of range. Recognized values are:
|
|
0 == do nothing, 1 == pause measurement till back in tolerance, 2 ==
|
|
interrupt, 3 == drive controller to a value considered safe.
|
|
\item [SaveValue] Value to be used as safe value if ErrorHandler 3 is
|
|
requested.
|
|
\item [Interrupt] The interrupt to issue, when interrupt error handling had
|
|
been requested. Will also be used as interrupt if a hardware failure is
|
|
detected while driving. Valid values are: 0 == Continue, 1 == Abort
|
|
Operation (Count), 2 == Abort Scan, 3 == Abort Batch processing, 4 == Halt
|
|
system, 6 == end SICS server.
|
|
\item [UpperLimit] The upper limit of values possible for the environment
|
|
device.
|
|
\item [LowerLimit] The lower limit of values possible for the environment
|
|
device.
|
|
\end{description}
|
|
\item [EVCGetPar] retrieves the value of a parameter. Name must be one of
|
|
the recognized names.
|
|
\item [EVCGetMode] retrieves the mode the EVController is in.
|
|
\item [EVCList] lists all the parameters to pCon.
|
|
\item[EVCGetVarLog] returns a pointer to the variable logger for this
|
|
controller.
|
|
\item [EVControlWrapper] is the interpreter interface to the EVController.
|
|
See the documentation for commands understood.
|
|
\item [EVControlFactory] is the SICS function needed for creation and
|
|
deletion of environment controllers.
|
|
\end{description}
|
|
|
|
@o evcontroller.h -d @{
|
|
/*--------------------------------------------------------------------------
|
|
E N V I R O N M E N T C O N T R O L L E R
|
|
|
|
This is the base class for all environment controllers.
|
|
|
|
Mark Koennecke, Juli 1997
|
|
|
|
copyright: see implementation file
|
|
----------------------------------------------------------------------------*/
|
|
#ifndef SICSEVCONTROL
|
|
#define SICSEVCONTROL
|
|
#include "varlog.h"
|
|
@<dvfunc@>
|
|
#endif
|
|
@}
|
|
|
|
@o evcontroller.i -d @{
|
|
/*-------------------------------------------------------------------------
|
|
Environment controller datastructure
|
|
|
|
Mark Koennecke, Juli 1997
|
|
|
|
---------------------------------------------------------------------------*/
|
|
/*-------- Parameter defines */
|
|
#define TOLERANCE 0
|
|
#define ACCESS 1
|
|
#define ERRORHANDLER 2
|
|
#define INTERRUPT 3
|
|
#define UPLIMIT 4
|
|
#define LOWLIMIT 5
|
|
#define SAFEVALUE 6
|
|
#define MAXWAIT 7
|
|
#define SETTLE 8
|
|
|
|
@<evdata@>
|
|
@}
|
|
|
|
@o evdriver.i -d @{
|
|
/*-------------------------------------------------------------------------
|
|
Environment device driver datastructure
|
|
|
|
Mark Koennecke, Juli 1997
|
|
|
|
---------------------------------------------------------------------------*/
|
|
#define DEVOK 1
|
|
#define DEVFAULT 0
|
|
#define DEVREDO 2
|
|
|
|
@<evdriv@>
|
|
/*-------------------- life & death of a driver --------------------------*/
|
|
pEVDriver CreateEVDriver(int argc, char *argv[]);
|
|
void DeleteEVDriver(pEVDriver pDriv);
|
|
@}
|
|
|