SKIPPED: psi/el737hpdriv.c psi/el737hpv2driv.c psi/make_gen psi/psi.c psi/tas.c psi/tasdrive.c psi/tasinit.c psi/tasscan.c psi/tasutil.c
640 lines
32 KiB
TeX
640 lines
32 KiB
TeX
\chapter{Writing SICS Device Drivers}
|
|
This chapter deals with writing new hardware drivers for SICS. SICS
|
|
hardware has a dual identity: Towards upper level code SICS hardware
|
|
is represented by the logical hardware object. All the low level
|
|
detail is handled in the hardware driver. The point of this is that
|
|
upper level code does not need to know which type of hardware device
|
|
is being accessed. Experience shows that this scheme covers most usage
|
|
cases for a given hardware device. However, there were always
|
|
exceptions mostly in order to realize special configurations. Such
|
|
exceptions can be dealt with through special macros which implement
|
|
commands which do
|
|
special configuration tasks. In order to be able to write such scripts
|
|
it is feasible to organize hardware access into three layers:
|
|
\begin{itemize}
|
|
\item A communication layer. This layer allows for sending commands
|
|
and reading data along a given bus.
|
|
\item A controller layer. If a device or several share a controller
|
|
make the controller visible within the system. Allow for sending
|
|
suitable commands to it.
|
|
\item The actual SICS driver.
|
|
\end{itemize}
|
|
This organisation allows scripts to directly talk to devices through
|
|
either the controller or the communication layer. If something is
|
|
missing in the general driver interface it is usually easier to add
|
|
some code at controller or communications level, rather then change
|
|
all drivers present in the system.
|
|
|
|
All drivers use a common pattern for error handling. Please read the
|
|
section on the motor driver where this pattern is explained in more
|
|
detail. The same pattern is applied in most drivers.
|
|
|
|
Please be aware that the hardware drivers have a significant impact on
|
|
SICS's overall performance. Most of the time SICS will be sitting
|
|
there and wait for a counter or a motor to finish. And often the
|
|
devices controlling such things respond pretty slow. The most often
|
|
called function is the status check function of the driver. It is
|
|
advisable to optimize this is good as possible. Suggestions for this
|
|
include:
|
|
\begin{itemize}
|
|
\item Reduce the amount of data to be read from the controller as much
|
|
as possible.
|
|
\item Make the status function a state machine: in the first state a
|
|
status request command is sent and the second state is entered. In teh
|
|
second state, the function checks if data is available on the
|
|
communication port and process if this is so, else it returns the
|
|
appropriate busy code.
|
|
\end{itemize}
|
|
|
|
This section describes the actual drivers. How these drivers are
|
|
integrated into SICS is described in the chapter on the site data
|
|
structure (see \ref{site}).
|
|
|
|
|
|
\section{The Motor Driver}
|
|
A motor driver again is represented by an interface encapsulated in a
|
|
data structure. Polymorphy is achieved in two ways:
|
|
\begin{itemize}
|
|
\item Through the functions you have to define for your motor and to
|
|
assign to the function pointers in the motor driver data structure.
|
|
\item For the data structure, polymorphy is achieved through
|
|
overlay. This means, if you define your own motor driver data
|
|
structure the first fields up to KillPrivate MUST be the same as
|
|
defined in the MotorDriver structure defined below. You MUST append
|
|
your own fields below KillPrivate.
|
|
\end{itemize}
|
|
|
|
This is the motor driver data structure which has to be implemented:
|
|
\begin{verbatim}
|
|
typedef struct __AbstractMoDriv {
|
|
/* general motor driver interface
|
|
fields. REQUIRED!
|
|
*/
|
|
float fUpper; /* upper limit */
|
|
float fLower; /* lower limit */
|
|
char *name;
|
|
int (*GetPosition)(void *self, float *fPos);
|
|
int (*RunTo)(void *self,float fNewVal);
|
|
int (*GetStatus)(void *self);
|
|
void (*GetError)(void *self, int *iCode, char *buffer, int iBufLen);
|
|
int (*TryAndFixIt)(void *self, int iError,float fNew);
|
|
int (*Halt)(void *self);
|
|
int (*GetDriverPar)(void *self, char *name,
|
|
float *value);
|
|
int (*SetDriverPar)(void *self,SConnection *pCon,
|
|
char *name, float newValue);
|
|
void (*ListDriverPar)(void *self, char *motorName,
|
|
SConnection *pCon);
|
|
void (*KillPrivate)(void *self);
|
|
} MotorDriver;
|
|
\end{verbatim}
|
|
In order not to have to repeat trivial things all the time two general
|
|
things must be stated:
|
|
\begin{itemize}
|
|
\item The pointer self is always a pointer to the motor driver data
|
|
structure.
|
|
\item Functions return 1 on success or 0 on failure if not stated otherwise.
|
|
\end{itemize}
|
|
The elements of this data structure are:
|
|
\begin{description}
|
|
\item[fUpper,fLower] These are the motors hardware limits. These
|
|
values are supposed to be identical to the positions of the limit
|
|
switches on the real thing. Read them from the motor or initialize
|
|
them from parameters when initializing the motor driver.
|
|
\item[GetPosition] reads the position of the motor and puts the result
|
|
into fPos. This ought to be the position from the motor
|
|
controller. Software zeros are applied later by code in
|
|
motor.c. GetPosition returns either OKOK when the request succeeded
|
|
or HWFault on failure.
|
|
\item[RunTo] Starts the motor to run towards the new position
|
|
fNewVal. fNewVal must be a value valid for the controller. Software
|
|
zero points have already been taken account of by code in
|
|
motor.c. This function shall NOT wait for the completion of the
|
|
driving operation. RunTo returns either OKOK when the request succeeded
|
|
or HWFault on failure.
|
|
\item[GetStatus] This function is called repeatedly by upper level
|
|
code to poll for the progress of the driving operation. Possible
|
|
return values of this function are:
|
|
\begin{description}
|
|
\item[HWFault] If there is a fault in the hardware or the status
|
|
cannot be read.
|
|
\item[HWPosFault] The motor is still alive but the controller was
|
|
unable to position the motor.
|
|
\item[HWBusy] The motor is still driving.
|
|
\item[HWWarn] There is a warning from the controller.
|
|
\item[HWIdle] The motor has finished driving and is idle.
|
|
\end{description}
|
|
\item[GetError] retrieves information about an error which occurred on
|
|
the motor. An integer error code is returned in iCode. Up to iBufLen
|
|
characters of descriptive error information is copied into
|
|
buffer. This information is printed as error message by upper level
|
|
code.
|
|
\item[TryAndFixIt] Given an error code in iError, try to repair the
|
|
problem as far as this is possible in software. iError should be an
|
|
error code as returned by GetError in iCode. This function has the
|
|
following return codes:
|
|
\begin{description}
|
|
\item[MOTREDO] Problem fixed, try to redo the last the operation.
|
|
\item[MOTFAIL] The problem cannot be fixed in software.
|
|
\end{description}
|
|
The parameter fNew is the target position of the motor.
|
|
\item[Halt] stops the motor immediately.
|
|
\item[GetDriverPar] copies the value of the motor driver parameter
|
|
name into value, if such a parameter exists.
|
|
\item[SetDriverPar] sets the motor driver parameter name to
|
|
newValue. Report errors to pCon.
|
|
\item[ListDriverPar] write the names and values of all driver
|
|
parameters to the client connection pCon.
|
|
\item[KillPrivate] releases any memory possibly allocated for private
|
|
fields in the motor data structure.
|
|
\end{description}
|
|
|
|
In order to understand the relationship between GetError and
|
|
TryAndFixIt it helps to look at the way how errors are handled by
|
|
upper level code in motor.c: If an error in any function occurs,
|
|
GetError gets called. An error message is printed. Then TryAndFixIt is
|
|
called with the error code returned in iCode as a parameter. If
|
|
TryAndFixIt returns MOTFAIL, the code gives up. If TryAndFixIt
|
|
returns MOTREDO, the failed operation is retried. At max 3 retries are
|
|
performed. If the operation does not succeed after three
|
|
retries, a motor failure is reported.
|
|
|
|
The GetDriverPar, SetDriverPar and ListDriverPar functions implement
|
|
some support for driver private configuration parameters. Such
|
|
parameters are meant to be configured from the instrument
|
|
initialization file. Currently there is no support to include these
|
|
parameters into the status file. If there are
|
|
no such parameters have these functions do nothing and return 1.
|
|
|
|
\section{The Counter Driver}
|
|
A counter driver is a driver for some box which allows to count for a
|
|
preset time or monitor and manages single counters and monitors. Such
|
|
a driver is represented by a data structure:
|
|
\begin{verbatim}
|
|
typedef struct __COUNTER {
|
|
/* variables */
|
|
char *name;
|
|
char *type;
|
|
CounterMode eMode;
|
|
float fPreset;
|
|
float fLastCurrent;
|
|
float fTime;
|
|
int iNoOfMonitors;
|
|
long lCounts[MAXCOUNT];
|
|
int iPause;
|
|
int iErrorCode;
|
|
/* functions */
|
|
int (*GetStatus)(struct __COUNTER *self, float *fControl);
|
|
int (*Start)(struct __COUNTER *self);
|
|
int (*Pause)(struct __COUNTER *self);
|
|
int (*Continue)(struct __COUNTER *self);
|
|
int (*Halt)(struct __COUNTER *self);
|
|
int (*ReadValues)(struct __COUNTER *self);
|
|
int (*GetError)(struct __COUNTER *self, int *iCode,
|
|
char *error, int iErrLen);
|
|
int (*TryAndFixIt)(struct __COUNTER *self, int iCode);
|
|
int (*Set)(struct __COUNTER *self,char *name,
|
|
int iCter, float fVal);
|
|
int (*Get)(struct __COUNTER *self,char *name,
|
|
int iCter, float *fVal);
|
|
int (*Send)(struct __COUNTER *self, char *pText,
|
|
char *pReply, int iReplyLen);
|
|
void (*KillPrivate)(struct __COUNTER *self);
|
|
void *pData; /* counter specific data goes here, ONLY for
|
|
internal driver use!
|
|
*/
|
|
} CounterDriver, *pCounterDriver;
|
|
\end{verbatim}
|
|
Polymorphy is achieved through the function pointers. Differences in
|
|
the data structure for different counter boxes are accounted for
|
|
through the pData pointer. This is meant to be initialized by the
|
|
actual counter driver to a private data structure which holds data
|
|
relevant to this particular counter. All functions take a pointer to
|
|
this counter driver structure as parameter self. If not stated
|
|
otherwise functions return 1 on success and 0 on failure. The fields:
|
|
\begin{description}
|
|
\item[name] The counter name in SICS
|
|
\item[type] The driver type.
|
|
\item[eMode] The counter mode. Possible values eTimer for preset timer
|
|
and eMonitor for preset monitor operation. This mode will be set by
|
|
upper level code.
|
|
\item[fPreset] The preset for either timer or monitor.
|
|
\item[fLastCurrent] the last known value for the control variable
|
|
during counting. Gets updated in GetStatus while counting and is used
|
|
for reporting count status.
|
|
\item[fTime] The time the last counting operation took. This is a time
|
|
read from the counter box. This could be different from elapsed time
|
|
because the count may have paused for instance because the beam was
|
|
low.
|
|
\item[iNoOfMonitors] is the number of monitors and counters this
|
|
counter box supports.
|
|
\item[lCounts] An array for storing the values of counters and
|
|
monitors after counting. The PSI EL7373 counter box allows to read
|
|
values only once after counting finished. This is why the values had to be
|
|
cached in lCounts.
|
|
\item[iPause] A flag which becomes true if the counter has been
|
|
paused.
|
|
\item[iErrorCode] A private variable holding error codes.
|
|
\item[GetStatus] This function is called while upper
|
|
level code polls for the counter to finish. It has to return the
|
|
status of the counting operation and update the current value of the
|
|
control variable in fControl. Possible return values are:
|
|
\begin{description}
|
|
\item[HWBusy] when counting.
|
|
\item[HWIdle] when finished counting or idle.
|
|
\item[HWNoBeam] when counting is halted due to lack of beam.
|
|
\item[HWPause] if counting is paused.
|
|
\item[HWFault] if the status cannot be obtained.
|
|
\end{description}
|
|
\item[Start] start counting in the count mode and with the preset
|
|
previously confugured. Do NOT wait for counting to finish!
|
|
\item[Pause] pause counting.
|
|
\item[Continue] continue a paused counting operation.
|
|
\item[Halt] stop counting.
|
|
\item[ReadValues] read all counters and monitors into lCounts.
|
|
\item[GetError] retrieves information about an error which occurred on
|
|
the counter. An integer error code is returned in iCode. Up to iErrLen
|
|
characters of descriptive error information is copied into
|
|
error. This information is printed as error message by upper level
|
|
code.
|
|
\item[TryAndFixIt] Given an error code in iCode, try to repair the
|
|
problem as far as this is possible in software. iError should be an
|
|
error code as returned by GetError in iCode. This function has the
|
|
following return codes:
|
|
\begin{description}
|
|
\item[COREDO] Problem fixed, try to redo the last the operation.
|
|
\item[COTERM] The problem cannot be fixed in software.
|
|
\end{description}
|
|
\item[Set] set parameter name associated with counter iCter to fVal.
|
|
\item[Get] return in fVal the value of parameter name associated with
|
|
iCter. These two functions allow to set counter driver parameters.
|
|
\item[Send] send pText to the counter controller and return iReplyLen
|
|
characters of response from the counter controller in pReply. This is
|
|
a bypass to set controller parameters manually.
|
|
\item[KillPrivate] properly delete counter driver private data
|
|
pData. Also close any connections to the hardware.
|
|
\end{description}
|
|
|
|
|
|
|
|
\section{Environment Controller Driver}
|
|
This is the driver for all sample environment controllers, be it
|
|
temperature controllers, magnet controllers etc. An environment
|
|
controller driver is represented by the following data structure:
|
|
\begin{verbatim}
|
|
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 (*Init)(pEVDriver self);
|
|
int (*Close)(pEVDriver self);
|
|
void *pPrivate;
|
|
void (*KillPrivate)(void *pData);
|
|
} EVDriver;
|
|
\end{verbatim}
|
|
All functions take a pointer to their own data structure as the first
|
|
argument (self). They return 1 on success or 0 on failure if not
|
|
stated otherwise.
|
|
The fields:
|
|
\begin{description}
|
|
\item[SetValue] set fNew as the new set value for the device. It
|
|
should start heating or cooling or whatever then.
|
|
\item[GetValue] reads the current value from the device into *fPos.
|
|
\item[GetValues] is used when the readout sensor and the control
|
|
sensor are very different. This function then reads the current set
|
|
value, the current position and calculates the difference between
|
|
these value into fDelta. This function does not need to be defined, it
|
|
is replaced by a standard one based on GetValue if not present.
|
|
\item[Send] send a command in pCommand to the controller and returns
|
|
at max iReplBuflen bytes of result in pReplyBuffer. This is breakout
|
|
which allows to send arbitray data to the controller.
|
|
\item[GetError] retrieves information about an error which occurred on
|
|
the device. An integer error code is returned in iCode. Up to iErrLen
|
|
characters of descriptive error information is copied into
|
|
pError. This information is printed as error message by upper level
|
|
code.
|
|
\item[TryAndFixIt] Given an error code in iError, try to repair the
|
|
problem as far as this is possible in software. iError should be an
|
|
error code as returned by GetError in iCode. This function has the
|
|
following return codes:
|
|
\begin{description}
|
|
\item[DEVREDO] Problem fixed, try to redo the last the operation.
|
|
\item[DEVFAULT] The problem cannot be fixed in software.
|
|
\end{description}
|
|
\item[Init] initializes a connection to a controller and puts the
|
|
thing into the right mode.
|
|
\item[Close] closes a connection to a controller.
|
|
\item[pPrivate] A pointer to a driver specific data structure which
|
|
can be filled with meaning by instances of drivers.
|
|
\item[KillPrivate] a function which has to release all memory associated
|
|
with pPrivate.
|
|
\end{description}
|
|
|
|
|
|
\section{Histogram Memory Drivers}
|
|
Histogram memories are devices in which neutron events for area
|
|
detector or time--of--flight detectors are assigned to their correct
|
|
bins. Then these usually large data sets have to be transferred to
|
|
SICS for further processing. In SICS, histogram memories are also able
|
|
to do count control, i.e. count until a preset monitor or time is
|
|
reached. This gives a slightly complicated driver interface. If this
|
|
assumption does not hold there are two options:
|
|
\begin{itemize}
|
|
\item Pass in a counter as a configuration parameter and chain count
|
|
control to this counter.
|
|
\item Make the count control functions dummies and let HMControl do
|
|
the rest. See hmcontrol.h and .c for details.
|
|
\end{itemize}
|
|
|
|
Though never used so far the histogram memory driver has support for
|
|
multiple banks of detectors being controlled by one histogram memory.
|
|
|
|
A histogram memory driver is implemented by filling in the data
|
|
structure given below:
|
|
\begin{verbatim}
|
|
typedef struct __HistDriver {
|
|
pHMdata data;
|
|
/* counting operations data */
|
|
CounterMode eCount;
|
|
float fCountPreset;
|
|
/* status flags */
|
|
int iReconfig;
|
|
int iUpdate;
|
|
/* interface functions */
|
|
int (*Configure)(pHistDriver self,
|
|
SConnection *pCon,
|
|
pStringDict pOpt,
|
|
SicsInterp *pSics);
|
|
int (*Start)(pHistDriver self,
|
|
SConnection *pCon);
|
|
int (*Halt)(pHistDriver self);
|
|
int (*GetCountStatus)(pHistDriver self,
|
|
SConnection *pCon);
|
|
int (*GetError)(pHistDriver self,
|
|
int *iCode,
|
|
char *perror,
|
|
int iErrlen);
|
|
int (*TryAndFixIt)(pHistDriver self,
|
|
int iCode);
|
|
int (*GetData)(pHistDriver self,
|
|
SConnection *pCon);
|
|
int (*GetHistogram)(pHistDriver self,
|
|
SConnection *pCon,
|
|
int i,
|
|
int iStart, int iEnd,
|
|
HistInt *pData);
|
|
|
|
int (*SetHistogram)(pHistDriver self,
|
|
SConnection *pCon,
|
|
int i,
|
|
int iStart, int iEnd,
|
|
HistInt *pData);
|
|
long (*GetMonitor)(pHistDriver self,
|
|
int i,
|
|
SConnection *pCon);
|
|
float (*GetTime)(pHistDriver self,
|
|
SConnection *pCon);
|
|
int (*Preset)(pHistDriver self,
|
|
SConnection *pCon,
|
|
HistInt iVal);
|
|
int (*Pause)(pHistDriver self,
|
|
SConnection *pCon);
|
|
int (*Continue)(pHistDriver self,
|
|
SConnection *pCon);
|
|
int (*FreePrivate)(pHistDriver self);
|
|
void *pPriv;
|
|
} HistDriver;
|
|
\end{verbatim}
|
|
All functions take a pointer to their driver data structure as an
|
|
argument. If not stated otherwise they return 1 on success, 0 on failure.
|
|
\begin{description}
|
|
\item[data] Is a pointer to an HMdata object which does all the
|
|
dimension handling, buffers histogram memory content, deals with time
|
|
binnings etc.
|
|
\item[eCount] A counter mode, as defined above for counters.
|
|
\item[fCountPreset] A preset for either monitor or time.
|
|
\item[iReconfig] A flag which will be set by upper level code when a
|
|
reconfiguration is necessary.
|
|
\item[iUpdate] a flag which invalidates the buffered histogram. Should
|
|
be set 1 in each call to GetCountStatus.
|
|
\item[Configure] configures the histogram memory to the specifications
|
|
given in the fields of the HMdriver structure. Further driver specific
|
|
information can be read from the options dictionary passed
|
|
in. Configuration options are stored in the string dictionary
|
|
pOpt. This dictionary holds name value pairs which must be interpreted
|
|
by this routine. Then configure has to configure the histogram memory
|
|
according to the options passed in.
|
|
\item[Start] starts a counting operation according to the current
|
|
settings of the counter mode parameters.
|
|
\item[Halt] implements an emergency stop of a counting operation.
|
|
\item[GetCountStatus] serves to monitor the status of the counting
|
|
operation. Possible return values to this call are:
|
|
\begin{itemize}
|
|
\item HWBUSY when still counting.
|
|
\item HWNoBeam when the monitor is to low.
|
|
\item HWIDLE or OKOK when nothing is going on.
|
|
\item HWFault when there is an error on the device.
|
|
\end{itemize}
|
|
\item[GetError] will be called whenever an error has been detected on
|
|
the device. The task is to put an internal error code into the iCode
|
|
parameter. The string parameter perror will be filled with a text description
|
|
of the error. But maximum iErrlen characters will be transferred to the error
|
|
string in order to protect against memory corruption. Therefore iLen must be
|
|
the maximum field length of error.
|
|
\item[TryAndFixIt] is the next function called in case of an error on
|
|
the device. Its second parameter is the internal code obtained in the ICode
|
|
parameter of the call to GetError. The task of this function is to examine
|
|
the error code and do whatever is possible in software to fix the problem.
|
|
TryAndFixIt returns one of the following values:
|
|
\begin{itemize}
|
|
\item COREDO when the error could be fixed, but the upper level code will
|
|
need to rerun the command which failed.
|
|
\item COTERM when the software is unable to fix the problem and a real
|
|
mechanic with a hammer is needed (or somebody able to reboot!).
|
|
\item MOTOK when the error was fixed and nor further action is necessary.
|
|
\end{itemize}
|
|
\item[GetData] transfers all the data collected in the HM into the
|
|
host computers memory buffer.
|
|
\item[GetHistogram] copies data between iStart and iEnd from histogram
|
|
bank i into the data space pData. Please make sure that pData is big
|
|
enough to hold the data.
|
|
\item[SetHistogram] presets the histogram bank i with the data
|
|
given in lData. A conversion from different binwidth
|
|
to long is performed as well. iStart and iStop define the start and end of
|
|
the stretch of histogram to replace.
|
|
\item[GetMonitor] returns the counts in the monitor i. GetMonitor returns a
|
|
negative value on error. The error will have been printed to pCon.
|
|
\item[GetTime] returns the actual counting time.
|
|
\item[Preset] initializes the histogram memory to the value given by
|
|
iVal.
|
|
\item[Pause] pauses data collection.
|
|
\item[Continue] continues a paused data collection.
|
|
\item[FreePrivate] will be called automatically by DeleteHistDriver and
|
|
has the task to remove the private data installed by implementations of an
|
|
actual histogram memory driver.
|
|
\item[pPriv] is a pointer which a actual histogram memory driver may
|
|
use to hold a driver specific data structure.
|
|
\end{description}
|
|
|
|
|
|
\section{Velocity Selector Driver}
|
|
This is a driver for velocity selectors as used at SANS machines. A
|
|
velocity selector is a kind of turbine which selects wavelength
|
|
through rotation speed. Though it rotates fast it is not a chopper,
|
|
which are handled in SICS through the general controller driver
|
|
described below. The velocity selector driver data structure includes:
|
|
\begin{verbatim}
|
|
typedef struct __VelSelDriv {
|
|
void *pPrivate;
|
|
void (*DeletePrivate)(void *pData);
|
|
float fTolerance;
|
|
int (*Halt)(pVelSelDriv self);
|
|
int (*GetError)(pVelSelDriv self,
|
|
int *iCode, char *pError,
|
|
int iErrlen);
|
|
int (*TryAndFixIt)(pVelSelDriv self,
|
|
int iCode);
|
|
int (*GetRotation)(pVelSelDriv self,
|
|
float *fRot);
|
|
int (*SetRotation)(pVelSelDriv self,
|
|
float fRot);
|
|
int (*GetStatus)(pVelSelDriv self,
|
|
int *iCall, float *fCur);
|
|
int (*GetDriverText)(pVelSelDriv self,
|
|
char *pText,
|
|
int iTextLen);
|
|
int (*GetLossCurrent)(pVelSelDriv self,
|
|
float *fLoss);
|
|
int (*Init)(pVelSelDriv self,
|
|
SConnection *pCon);
|
|
}VelSelDriv;
|
|
\end{verbatim}
|
|
All functions take a pointer to their driver data structure as an
|
|
argument. If not stated otherwise they return 1 on success, 0 on failure.
|
|
The fields:
|
|
\begin{description}
|
|
\item[pPrivate] a pointer to a driver private data structure.
|
|
\item[DeletePrivate] a function which releases any memory associated
|
|
with pPrivate. DeletePrivate is called with a pointer to the driver
|
|
private data pPrivate as argument.
|
|
\item[fTolerance] This driver assumes it has reached the target speed
|
|
if the speed difference target speed - read speed is less then this
|
|
tolerance value for four consecutive times.
|
|
\item[Halt] stops the velocity selector.
|
|
\item[GetError] returns an error code in *iCode and iErrlen
|
|
bytes of textual description of the last error on the velocity
|
|
selector in pError.
|
|
\item[TryAndFixIt] tries to fix the error defined through iCode. iCode
|
|
should be the value as returned in *iCode in GetError. This function
|
|
returns:
|
|
\begin{description}
|
|
\item[VELOREDO] redo last operation, error fixed.
|
|
\item[VELOFAIL] cannot fix the error from software.
|
|
\end{description}
|
|
\item[GetRotation] reads the rotation speed into *fRot.
|
|
\item[SetRotation] sets a new rotation speed fRot for the selector. Do
|
|
NOT wait until finished.
|
|
\item[GetStatus] is used to poll for the status of the last driving
|
|
operation. It returns:
|
|
\begin{description}
|
|
\item[VSACCEL] when the velocity selector is accelerating.
|
|
\item[VSFAIL] if the status cannot be read.
|
|
\item[VSOK] when the velocity seelctor has reached its target speed.
|
|
\end{description}
|
|
The current rotation speed is returned in *fCur. iCall is a value
|
|
which indicates in which state the selector is:
|
|
\begin{description}
|
|
\item[ROTMOVE] normal running.
|
|
\item[ROTSTART] starting the velocity selector. The Dornier velocity
|
|
selector have a certain minimum speed. If they are standing they have
|
|
to be started first.
|
|
\end{description}
|
|
\item[GetDriverText] returns iTextLen bytes of additional status
|
|
information in pText. This is a list name: value pairs separated by
|
|
commata. This is meant to hold additional selector readouts such as
|
|
vacuum states, temperatures etc.
|
|
\item[GetLossCurrent] initiates a measurement of the loss current of
|
|
the velocity selector. The result is returned in *fLoss.
|
|
\item[Init] initiates a connection to a velocity selector.
|
|
\end{description}
|
|
|
|
It may be possible that this driver is not very general. It was
|
|
developed for Dornier velocity selectors because these were the only
|
|
one seen.
|
|
|
|
\section{General Controller Driver}
|
|
This is driver for a SICS general controller object. SICS sports a
|
|
general controller object which allows to read a selection of parameters and
|
|
to set some parameters. Adapters exists which implement the driveable
|
|
or environment interface for parameters in such a controller. The
|
|
parameters supported are part of the drivers interface. This
|
|
scheme is currently used to control choppers in SICS, but it is not
|
|
restricted to this usage. The driver:
|
|
\begin{verbatim}
|
|
typedef struct __CODRI {
|
|
int (*Init)(pCodri self);
|
|
int (*Close)(pCodri self);
|
|
int (*Delete)(pCodri self);
|
|
int (*SetPar)(pCodri self,
|
|
char *parname,
|
|
float fValue);
|
|
int (*SetPar2)(pCodri self,
|
|
char *parname,
|
|
char *value);
|
|
int (*GetPar)(pCodri self,
|
|
char *parname,
|
|
char *pBuffer,
|
|
int iBufLen);
|
|
int (*CheckPar)(pCodri self,
|
|
char *parname);
|
|
int (*GetError)(pCodri self, int *iCode,
|
|
char *pError,
|
|
int iErrLen);
|
|
int (*TryFixIt)(pCodri self, int iCode);
|
|
int (*Halt)(pCodri self);
|
|
char *pParList;
|
|
void *pPrivate;
|
|
}Codri;
|
|
\end{verbatim}
|
|
All functions take a pointer to their driver data structure as an
|
|
argument. If not stated otherwise they return 1 on success, 0 on failure.
|
|
The fields:
|
|
\begin{description}
|
|
\item[Init] initializes a connection to the controller and the driver.
|
|
\item[Close] closes the connection to a controller.
|
|
\item[Delete] releases all memory associated with this drivers private
|
|
data structure pPrivate.
|
|
\item[SetPar] sets the parameter parname to a new value fValue.
|
|
\item[SetPar2] same as SetPar but with new value as text.
|
|
\item[GetPar] read the current value of parname into pBuffer. The
|
|
value is formatted as text. At max iBufLen bytes are copied into
|
|
pBuffer.
|
|
\item[CheckPar] checks the progress of setting parname. CheckPar
|
|
returns:
|
|
\begin{description}
|
|
\item[HWFault] If there is a fault in the hardware or the status
|
|
cannot be read.
|
|
\item[HWBusy] The parameter is still driving.
|
|
\item[HWIdle] The parameter has finished changing and is idle.
|
|
\end{description}
|
|
\item[GetError] returns an error code in *iCode and iErrlen
|
|
bytes of textual description of the last error on the velocity
|
|
selector in pError.
|
|
\item[TryAndFixIt] tries to fix the error defined through iCode. iCode
|
|
should be the value as returned in *iCode in GetError. This function
|
|
returns:
|
|
\begin{description}
|
|
\item[CHREDO] redo last operation, error fixed.
|
|
\item[CHFAIL] cannot fix the error from software.
|
|
\end{description}
|
|
\item[Halt] stop any driving parameters.
|
|
\item[pParList] a comma separated list of parameters supported by this
|
|
driver.
|
|
\item[pPrivate] a driver private data structure.
|
|
\end{description} |