\subsection{The Velocity Selector}
A velocity selector is a kind of turbine in the neutron beam. Only neutrons
which manage to travel through the device between two turbine blades make it
through the device, the rest is annihilated in the blades or the turbine
housing.  Thus, a velocity selector is a kind of monochromator. 
The behaviour of a velocity selector is determined by two
parameters: the rotation speed and the dejustment of the velocity selector
to the neutron beam, the tilt angle. The velocity
(wavelength) of the neutrons coming through is determined by the rotation speed
of the thing.  The tilt angle determines the velocity distribution function.

Velocity selectors have a few peculiarities due to the fact that they
rotate rather quickly. This may give rise to resonances at certain
rotation speeds which may damage the device and the surroundings of it. This
problem is coped with by having forbidden regions of rotation speeds which
cannot be selected. The second implication of the fast rotation is, that the
rotation needs to stop or be below a certain threshold before the tilt
angle may be changed. So, changing tilt has to go in three steps:
first stop rotation, drive tilt, accelerate rotation to the former speed.
Tilt is usually controlled by some stepper motor. 

The rotation speed of the velocity selector needs to be monitored at regular
intervalls. If it goes out of tolerances, a error handling procedure must be
initiated. Furthermore logging of the rotation speeds of the velocity
selector may be required. All this is already realised in the environment
controller code. In order to minimise duplication of code, these facilities
are implemented by installing a environment controller for the velocity
selector. This environement controller will have a dummy driver which does
not allow the velocity selector to be driven through the environment
controller. An object is installed into the SICServer with the name of the
velocity selector and watch appended to it. Through this object such things
as tolerances, error handling procedures and logging of velocity selector
values can be configured. The only task left for the velocity selector code
is to maintain the proper state of the environment controller mode at
apropriate places.  


From this introduction the necessary datastructure for this beast can be
easily deduced. Besides the usual objectdescriptor we need:
\begin{itemize}
\item A list of forbidden regions, realised as a standard linked list of
min, max values. 
\item A motor to drive the tilt with. 
\item Fields to hold rotation and tilt and some auxilliary parameters.
\item Various interrupt to trigger in case of failures. 
\item As an interface a drivable interface for the rotation is needed in 
oder to use the device executor for changing rotation speed.
\item A pointer to the environment controller object monitoring the velocity
selector.
\item A driver for actually driving the velocity selector.
\end{itemize}
A suitable datastructure  looks like this:

@d data @{
/*------------------ The velocity selector datastructure -----------------*/ 
 
     typedef struct __VelSel {
                        pObjectDescriptor  pDes;
                        char *pName;
                        pIDrivable         pDrivInt;
                        pICallBack         pCall;
                        int                iForbidden;
                        ObPar              *pPar;
                        pMotor             pTilt;
                        float              fRot;
                        float              fTilt;
                        pEVControl         pMonitor;
                        pVelSelDriv        pDriv;
                      } VelSel;  
/*----------------- Forbidden region single item -------------------------*/
    typedef struct __Verbot {
                       float fMin;
                       float fMax;
                    } Verbot, *pVerbot;

@}
The fields are:
\begin{description}
\item[pDes] The usual object descriptor.
\item[pName] The velocity selector name.
\item[pDrivInt] The drivable interface.
\item[pCall] The callback  interface.
\item[iForbidden] The handle to the lsit of forbidden regions.
\item[pPar] The velocity selector parameters.
\item[pTilt] The motor to use for tilting the turbine.
\item[pMonitor] The environment controller object representing the velocity
selector in the environment control subsystem.
\item[pDriv] The velocity selector driver.  
\end{description}
Verbot is a trivial little data structure holding a single forbidden
region for the vlocity selector. This is the structure held in the
forbidden list. Please note that the upper and lower limits of the
device are held in that list as well. 

In order to interface with this a few functions will be defined. All
functions starts with VS. Functions returning an int return 0 on failure, 1
on success for the rest of this discussion.  The first set of functions
deals with creating and configuring a velocity selector. 

@d proto1 @{
    typedef struct __VelSel *pVelSel;
    typedef struct __VelSelDriv *pVelSelDriv;

    pVelSel VSCreate(pMotor pTilt, pVelSelDriv pDriv);
    void    VSDestroy(void *self);

    int VSAddVerbot(pVelSel self, float fMin, float fMax);
    int VSSetPar(pVelSel self,SConnection *pCon, char *name, float fVal);
    int VSGetPar(pVelSel self,char *name, float *fVal);
    int VSGetRotation(pVelSel self, float *fRot);
    int VSGetTilt(pVelSel self, float *fTilt);
@} 

Most functions take a pointer to a velocity selector data structure as
first parameter. This parameter is not discussed furtheron.
\begin{description}
\item[VSCreate] Creates a velocity selector object. A driver and a
motor for the tiliting operation need to be given as parameters. On
return either a pointer to a newly allocated velocity selector data
structure is returned or NULL as indication of failure. 
The velocity selector will make sure that the tilt motor is only
accessible with internal
privilege. This effectively reserves the tilt motor to the velocity
selector object. This obliges the velocity selector to set a lower
privilege 
while running that motor and to set it back again afterwards. 
The idea behind this
scheme is to prevent a user from accidentally tampering with the tilt motor
without passing through the velocity selector interface.  
\item[VSDestroy] is a function which properly frees all data
structures associated with the velocity selector. This is the function
to specify as KillFunction for the interpreter.
\item[VSAddVerbot] adds a forbidden region between fMin and fmax
rotation speeds. 
\item[VSSetPar, VSGetPar] set and retrive velocity selector
parameters. Parameter names given as parameter name are the same as in
the user documentation. 
\item[VSGetRotation] retrieves the current rotation speed.
\item[VSGetTilt] retrieves the current tilt angle.  
\end{description}

@d protos2 @{
/*
    int VSSetRotation(pVelSel self, SConnection *pCon, float fNew);
    int VSSetTilt(pVelSel self, SConnection *pCon, float FNewTilt);
*/
    int VSSetTiltRot(pVelSel self, SConnection *pCon,
                     float fNewRot, float fNewTilt);
@}

\begin{description}
\item[VSSetTiltRot] sets both rotation speed and tilt angle to new
values.   
\end{description}

Please note, that further manipulation functions are hidden in the Drivable
interface functions for the rotation which this module defines. 


Another common task for a velocity selector is to measure its  loss current.
This is done regularly in order to catch possible problems with the
velocity selector early on. 

@d protos4 @{
   int VSGetLossCurrent(pVelSel self, SConnection *pCon, float *fLoss);
@}


Last not least a velocity selector needs an interface to the interpreter as
well. As usual there are two functions: a creation function and a bigger
action function which takes the widget commands. 

@d protos3 @{
     int VelSelFactory(SConnection *pCon, SicsInterp *pSics, void *pData,
                       int argc, char *argv[]);
     int VelSelAction(SConnection *pCon, SicsInterp *pSics, void *pData,
                       int argc, char *argv[]);
 
@} 

\subsubsection{The velocity selector driver}
As usual for hardware devices in SICS the velocity selector consists of the
logical selector described above and a hardware driver which takes care of
simulating actual hardware or talking to it. This driver is described here. 
@d Driver @{
    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;   
@}

pPrivate is an area where individual drivers may store their necessary data.
DeletePrivate is a function which will be automatically called when the
driver is destroyed with pPrivate passed as parameter. This functions
purpose is to destroy pPrivate and remove all memory associated with it.
Each driver is resonsible for filling the right thing in here.

The description of the rest of the functions is very much like as described
for the motor interface. Possible return values for GetStatus can be:
\begin{itemize}
\item VSNOCON: connection to velocity selector lost.
\item VSACCEL: selector accelerating or breaking.
\item VSFAIL: velocity selector failure.
\item VSOK:   all fine, at requested velocity.
\end{itemize}

Special is the GetDriverText which is meant to
return a formatted string of hardware specific information from the device.
This is put into pText, but maximum iTextlen characters. 

Another special is the GetLossCurrent. This is a special self test of the
velocity selector which helps to identify possible problems with the device
early on. This test must be  made regularly and, of course,  the driver must
support it.

Init is meant to do what it says, initialize the velocity selector. This is
here in order to support restarting the velocity selector in case of a
problem.

At the time of writing (Juli 1997) two drivers for velocity selectors exist:
 a simulation driver and a driver for a Dornier velocity selector run
through a Macintosh--PC terminal server communicating with the velocity
selector control PC. Please note, that the Dornier program had been slightly
modified in order to make this scheme work.

@o velo.h -d @{
/*-------------------------------------------------------------------------

		V E L O C I T Y   S E L E C T O R

  Header file for the SICS velocity selector module. For documentation
  see velo.w.

  Mark Koennecke, Juli 1997

  copyright: see implementation file
-----------------------------------------------------------------------------*/
#ifndef SICSVELO
#define SICSVELO

/*------------------------- live & death & shape ------------------------*/
@< proto1 @>
/*------------------------- drive around -----------------------------------*/
@< protos2 @>
@< protos4 @>
/*------------------------- Interpreter interface ------------------------*/
@< protos3 @>
#endif
@}

@o velo.i -d @{
/*--------------------------------------------------------------------------

  Internal header file describing the velocity selector data structure.

  Mark Koennecke, Juli, 1997

----------------------------------------------------------------------------*/
#ifndef VELOINTERNAL
#define VELOINTERNAL
@< data @>
#define VELOREDO  2
#define VELOFAIL  0
#define VELOOK    1

#define VSNOCON 0
#define VSOK    1
#define VSACCEL -7
#define VSFAIL -2

#endif

@}

@o velodriv.h -d @{
/*--------------------------------------------------------------------------
	V E L O C I T Y   S E L E C T O R  D R I V E R

  Header file for the velocity selector driver and its related functions.

  Mark Koennecke, Juli 1997
  copyright: see implementation file
-----------------------------------------------------------------------------*/
#ifndef VELODRIV
#define VELODRIV
#include <tcl.h>
@< Driver @>
/*-------------------- live & death ----------------------------------------*/
  pVelSelDriv VSCreateSim(void);
  pVelSelDriv VSCreateDornierSINQ(char *name,Tcl_Interp *pTcl);

  void        VSDeleteDriver(pVelSelDriv self);

#endif 
@}

