348 lines
17 KiB
TeX
348 lines
17 KiB
TeX
\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:
|
|
\begin{flushleft} \small
|
|
\begin{minipage}{\linewidth} \label{scrap1}
|
|
$\langle$evdata {\footnotesize ?}$\rangle\equiv$
|
|
\vspace{-1ex}
|
|
\begin{list}{}{} \item
|
|
\mbox{}\verb@@\\
|
|
\mbox{}\verb@ typedef struct __EVControl {@\\
|
|
\mbox{}\verb@ pObjectDescriptor pDes;@\\
|
|
\mbox{}\verb@ pIDrivable pDrivInt;@\\
|
|
\mbox{}\verb@ pEVInterface pEnvir;@\\
|
|
\mbox{}\verb@ pICallBack pCall;@\\
|
|
\mbox{}\verb@ int callCount;@\\
|
|
\mbox{}\verb@ pEVDriver pDriv;@\\
|
|
\mbox{}\verb@ EVMode eMode;@\\
|
|
\mbox{}\verb@ float fTarget;@\\
|
|
\mbox{}\verb@ time_t start;@\\
|
|
\mbox{}\verb@ time_t lastt;@\\
|
|
\mbox{}\verb@ char *pName;@\\
|
|
\mbox{}\verb@ char *driverName;@\\
|
|
\mbox{}\verb@ char *errorScript;@\\
|
|
\mbox{}\verb@ ObPar *pParam;@\\
|
|
\mbox{}\verb@ int iLog;@\\
|
|
\mbox{}\verb@ pVarLog pLog;@\\
|
|
\mbox{}\verb@ int iWarned;@\\
|
|
\mbox{}\verb@ int iTcl;@\\
|
|
\mbox{}\verb@ int iStop;@\\
|
|
\mbox{}\verb@ SConnection *conn;@\\
|
|
\mbox{}\verb@ char *creationArgs;@\\
|
|
\mbox{}\verb@ char *runScript;@\\
|
|
\mbox{}\verb@ void *pPrivate;@\\
|
|
\mbox{}\verb@ void (*KillPrivate)(void *pData);@\\
|
|
\mbox{}\verb@ } EVControl;@\\
|
|
\mbox{}\verb@@$\Diamond$
|
|
\end{list}
|
|
\vspace{-1ex}
|
|
\footnotesize\addtolength{\baselineskip}{-1ex}
|
|
\begin{list}{}{\setlength{\itemsep}{-\parsep}\setlength{\itemindent}{-\leftmargin}}
|
|
\item Macro referenced in scrap ?.
|
|
\end{list}
|
|
\end{minipage}\\[4ex]
|
|
\end{flushleft}
|
|
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:
|
|
|
|
\begin{flushleft} \small
|
|
\begin{minipage}{\linewidth} \label{scrap2}
|
|
$\langle$evdriv {\footnotesize ?}$\rangle\equiv$
|
|
\vspace{-1ex}
|
|
\begin{list}{}{} \item
|
|
\mbox{}\verb@@\\
|
|
\mbox{}\verb@ typedef struct __EVDriver {@\\
|
|
\mbox{}\verb@ int (*SetValue)(pEVDriver self, float fNew);@\\
|
|
\mbox{}\verb@ int (*GetValue)(pEVDriver self, float *fPos);@\\
|
|
\mbox{}\verb@ int (*GetValues)(pEVDriver self, float *fTarget,@\\
|
|
\mbox{}\verb@ float *fPos, float *fDelta);@\\
|
|
\mbox{}\verb@ int (*Send)(pEVDriver self, char *pCommand,@\\
|
|
\mbox{}\verb@ char *pReplyBuffer, int iReplBufLen); @\\
|
|
\mbox{}\verb@ int (*GetError)(pEVDriver self, int *iCode,@\\
|
|
\mbox{}\verb@ char *pError, int iErrLen);@\\
|
|
\mbox{}\verb@ int (*TryFixIt)(pEVDriver self, int iCode);@\\
|
|
\mbox{}\verb@ int (*SavePars)(pEVDriver self, FILE *fil);@\\
|
|
\mbox{}\verb@ int (*Init)(pEVDriver self);@\\
|
|
\mbox{}\verb@ int (*Close)(pEVDriver self);@\\
|
|
\mbox{}\verb@ void *pPrivate;@\\
|
|
\mbox{}\verb@ void (*KillPrivate)(void *pData);@\\
|
|
\mbox{}\verb@ } EVDriver;@\\
|
|
\mbox{}\verb@@$\Diamond$
|
|
\end{list}
|
|
\vspace{-1ex}
|
|
\footnotesize\addtolength{\baselineskip}{-1ex}
|
|
\begin{list}{}{\setlength{\itemsep}{-\parsep}\setlength{\itemindent}{-\leftmargin}}
|
|
\item Macro referenced in scrap ?.
|
|
\end{list}
|
|
\end{minipage}\\[4ex]
|
|
\end{flushleft}
|
|
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.
|
|
|
|
\begin{flushleft} \small
|
|
\begin{minipage}{\linewidth} \label{scrap3}
|
|
$\langle$dvfunc {\footnotesize ?}$\rangle\equiv$
|
|
\vspace{-1ex}
|
|
\begin{list}{}{} \item
|
|
\mbox{}\verb@@\\
|
|
\mbox{}\verb@/*--------------------------- live & death --------------------------------*/ @\\
|
|
\mbox{}\verb@ typedef struct __EVControl *pEVControl;@\\
|
|
\mbox{}\verb@ typedef struct __EVDriver *pEVDriver;@\\
|
|
\mbox{}\verb@@\\
|
|
\mbox{}\verb@ pEVControl CreateEVController(pEVDriver pDriv, char *pName, int *iErr);@\\
|
|
\mbox{}\verb@ void DeleteEVController(void *pData);@\\
|
|
\mbox{}\verb@ pEVControl MakeEVController(pEVDriver pDriv, SConnection *pCon,@\\
|
|
\mbox{}\verb@ ObjectFunc wrapper, int argc, char *argv[]);@\\
|
|
\mbox{}\verb@/*-------------------------- driving ---------------------------------*/@\\
|
|
\mbox{}\verb@ int EVCDrive(pEVControl self,SConnection *pCon, float fNew);@\\
|
|
\mbox{}\verb@ int EVCGetPos(pEVControl self, SConnection *pCon,float *fVal);@\\
|
|
\mbox{}\verb@@\\
|
|
\mbox{}\verb@/*------------------------ parameters ----------------------------------*/@\\
|
|
\mbox{}\verb@ EVMode EVCGetMode(pEVControl self);@\\
|
|
\mbox{}\verb@ int EVCSetMode(pEVControl self, EVMode eNew);@\\
|
|
\mbox{}\verb@ int EVCSetPar(pEVControl self, char *name, float fNew, SConnection *pCon);@\\
|
|
\mbox{}\verb@ int EVCGetPar(pEVControl self, char *name, float *fVal);@\\
|
|
\mbox{}\verb@ int EVCList(pEVControl self, SConnection *pCon);@\\
|
|
\mbox{}\verb@/*------------------------- logging -----------------------------------*/@\\
|
|
\mbox{}\verb@ pVarLog EVCGetVarLog(pEVControl self);@\\
|
|
\mbox{}\verb@/*----------------- Interface to SICS interpreter -----------------------*/@\\
|
|
\mbox{}\verb@ int EVControlWrapper(SConnection *pCon, SicsInterp *pSics, void *pData,@\\
|
|
\mbox{}\verb@ int argc, char *argv[]);@\\
|
|
\mbox{}\verb@ @\\
|
|
\mbox{}\verb@ int EVControlFactory(SConnection *pCon, SicsInterp *pSics, void *pData,@\\
|
|
\mbox{}\verb@ int argc, char *argv[]);@\\
|
|
\mbox{}\verb@ @\\
|
|
\mbox{}\verb@@\\
|
|
\mbox{}\verb@@$\Diamond$
|
|
\end{list}
|
|
\vspace{-1ex}
|
|
\footnotesize\addtolength{\baselineskip}{-1ex}
|
|
\begin{list}{}{\setlength{\itemsep}{-\parsep}\setlength{\itemindent}{-\leftmargin}}
|
|
\item Macro referenced in scrap ?.
|
|
\end{list}
|
|
\end{minipage}\\[4ex]
|
|
\end{flushleft}
|
|
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}
|
|
|
|
\begin{flushleft} \small
|
|
\begin{minipage}{\linewidth} \label{scrap4}
|
|
\verb@"evcontroller.h"@ {\footnotesize ? }$\equiv$
|
|
\vspace{-1ex}
|
|
\begin{list}{}{} \item
|
|
\mbox{}\verb@@\\
|
|
\mbox{}\verb@/*--------------------------------------------------------------------------@\\
|
|
\mbox{}\verb@ E N V I R O N M E N T C O N T R O L L E R@\\
|
|
\mbox{}\verb@@\\
|
|
\mbox{}\verb@ This is the base class for all environment controllers. @\\
|
|
\mbox{}\verb@@\\
|
|
\mbox{}\verb@ Mark Koennecke, Juli 1997@\\
|
|
\mbox{}\verb@@\\
|
|
\mbox{}\verb@ copyright: see implementation file@\\
|
|
\mbox{}\verb@----------------------------------------------------------------------------*/@\\
|
|
\mbox{}\verb@#ifndef SICSEVCONTROL@\\
|
|
\mbox{}\verb@#define SICSEVCONTROL@\\
|
|
\mbox{}\verb@#include "varlog.h"@\\
|
|
\mbox{}\verb@@$\langle$dvfunc {\footnotesize ?}$\rangle$\verb@@\\
|
|
\mbox{}\verb@#endif@\\
|
|
\mbox{}\verb@@$\Diamond$
|
|
\end{list}
|
|
\vspace{-2ex}
|
|
\end{minipage}\\[4ex]
|
|
\end{flushleft}
|
|
\begin{flushleft} \small
|
|
\begin{minipage}{\linewidth} \label{scrap5}
|
|
\verb@"evcontroller.i"@ {\footnotesize ? }$\equiv$
|
|
\vspace{-1ex}
|
|
\begin{list}{}{} \item
|
|
\mbox{}\verb@@\\
|
|
\mbox{}\verb@/*-------------------------------------------------------------------------@\\
|
|
\mbox{}\verb@ Environment controller datastructure@\\
|
|
\mbox{}\verb@ @\\
|
|
\mbox{}\verb@ Mark Koennecke, Juli 1997@\\
|
|
\mbox{}\verb@@\\
|
|
\mbox{}\verb@---------------------------------------------------------------------------*/@\\
|
|
\mbox{}\verb@/*-------- Parameter defines */@\\
|
|
\mbox{}\verb@#define TOLERANCE 0@\\
|
|
\mbox{}\verb@#define ACCESS 1@\\
|
|
\mbox{}\verb@#define ERRORHANDLER 2@\\
|
|
\mbox{}\verb@#define INTERRUPT 3@\\
|
|
\mbox{}\verb@#define UPLIMIT 4@\\
|
|
\mbox{}\verb@#define LOWLIMIT 5@\\
|
|
\mbox{}\verb@#define SAFEVALUE 6@\\
|
|
\mbox{}\verb@#define MAXWAIT 7@\\
|
|
\mbox{}\verb@#define SETTLE 8@\\
|
|
\mbox{}\verb@@\\
|
|
\mbox{}\verb@@$\langle$evdata {\footnotesize ?}$\rangle$\verb@@\\
|
|
\mbox{}\verb@@$\Diamond$
|
|
\end{list}
|
|
\vspace{-2ex}
|
|
\end{minipage}\\[4ex]
|
|
\end{flushleft}
|
|
\begin{flushleft} \small
|
|
\begin{minipage}{\linewidth} \label{scrap6}
|
|
\verb@"evdriver.i"@ {\footnotesize ? }$\equiv$
|
|
\vspace{-1ex}
|
|
\begin{list}{}{} \item
|
|
\mbox{}\verb@@\\
|
|
\mbox{}\verb@/*-------------------------------------------------------------------------@\\
|
|
\mbox{}\verb@ Environment device driver datastructure@\\
|
|
\mbox{}\verb@ @\\
|
|
\mbox{}\verb@ Mark Koennecke, Juli 1997@\\
|
|
\mbox{}\verb@@\\
|
|
\mbox{}\verb@---------------------------------------------------------------------------*/@\\
|
|
\mbox{}\verb@#define DEVOK 1@\\
|
|
\mbox{}\verb@#define DEVFAULT 0@\\
|
|
\mbox{}\verb@#define DEVREDO 2@\\
|
|
\mbox{}\verb@@\\
|
|
\mbox{}\verb@@$\langle$evdriv {\footnotesize ?}$\rangle$\verb@@\\
|
|
\mbox{}\verb@/*-------------------- life & death of a driver --------------------------*/@\\
|
|
\mbox{}\verb@ pEVDriver CreateEVDriver(int argc, char *argv[]);@\\
|
|
\mbox{}\verb@ void DeleteEVDriver(pEVDriver pDriv);@\\
|
|
\mbox{}\verb@@$\Diamond$
|
|
\end{list}
|
|
\vspace{-2ex}
|
|
\end{minipage}\\[4ex]
|
|
\end{flushleft}
|