- Updated Makefiles
- Moved TAS code to psi - Updated programmers documentation SKIPPED: psi/make_gen psi/nextrics.c psi/t_conv.c psi/t_conv.f psi/t_rlp.c psi/t_rlp.f psi/t_update.c psi/t_update.f psi/hardsup/el734_utility.c psi/hardsup/makefile_alpha
This commit is contained in:
620
doc/programmer/sicsdriver.tex
Normal file
620
doc/programmer/sicsdriver.tex
Normal file
@@ -0,0 +1,620 @@
|
||||
\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.
|
||||
|
||||
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.
|
||||
\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.
|
||||
\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 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 reprsented 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
|
||||
elvel 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 interrupted 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 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[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 repsonse 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 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[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 (or mood?).
|
||||
\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}
|
||||
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 retun 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 error will be filled with a text description
|
||||
of the error. But maximum iLen 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 COFAIL 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 betwen 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 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. 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 retun 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] is 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
|
||||
komma. 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 seelctor. 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 seelctors 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 retun 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}
|
||||
Reference in New Issue
Block a user