Initial revision
This commit is contained in:
260
evcontroller.w
Normal file
260
evcontroller.w
Normal file
@ -0,0 +1,260 @@
|
||||
\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;
|
||||
pEVDriver pDriv;
|
||||
EVMode eMode;
|
||||
float fTarget;
|
||||
char *pName;
|
||||
ObPar *pParam;
|
||||
int iLog;
|
||||
pVarLog pLog;
|
||||
int iWarned;
|
||||
int iTcl;
|
||||
int iStop;
|
||||
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. The fourth 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. pName is a pointer to a string representing the name of the
|
||||
controller. 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.
|
||||
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 (*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 (*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 [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 sated
|
||||
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);
|
||||
|
||||
/*-------------------------- 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
|
||||
|
||||
@<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);
|
||||
@}
|
||||
|
Reference in New Issue
Block a user