PSI sics-cvs-psi_pre-ansto
This commit is contained in:
5
doc/programmer/README
Normal file
5
doc/programmer/README
Normal file
@@ -0,0 +1,5 @@
|
||||
The entry points in this file are:
|
||||
|
||||
pub.tex for a SICS publication
|
||||
programmer.tex for a SICS programming guide
|
||||
reference.tex for the SICS reference manual
|
||||
140
doc/programmer/SCinter.tex
Normal file
140
doc/programmer/SCinter.tex
Normal file
@@ -0,0 +1,140 @@
|
||||
\subsection{The SICS Interpreter} \label{scinter}
|
||||
The SICS interpreter does the first step of command interpretation. Each
|
||||
SICS command is a name followed by parameters. The interpreter holds for
|
||||
each command a function (the object function) and a data structure. When a
|
||||
command is invoked the list will be searched for a fitting command and then
|
||||
its object function will be invoked for further processing.
|
||||
|
||||
The object
|
||||
function is the object wrapper function as discussed in much detail in the
|
||||
Guide to Object Writers. It looks like this:
|
||||
\begin{verbatim}
|
||||
typedef int (*ObjectFunc)(pSConnection pCon, pSicsInterp pInter, void
|
||||
*pData, int argc, char *argv[]);
|
||||
\end{verbatim}
|
||||
{\bf pCon} is a pointer to the the connection for which the command
|
||||
was invoked. {\bf pInter} is the SICS interpreter in which the command
|
||||
was invoked. {argc, argv[]} are the command arguments similar to the
|
||||
classic C main() function arguments. This is an objects interface to
|
||||
the SICS interpreter.
|
||||
|
||||
|
||||
{\bf pData} is a pointer to a command own data structure. This data structure
|
||||
is deleted by the interpreter when the command is removed by calling
|
||||
a special removal function with the pointer as parameter. This
|
||||
function looks like this:
|
||||
\begin{verbatim}
|
||||
typedef void (*KillFunc)(void *pData);
|
||||
\end{verbatim}
|
||||
|
||||
|
||||
In order to do ist job the SICS interpreter has for each command a data
|
||||
structure defined below:
|
||||
\begin{verbatim}
|
||||
typedef struct __Clist {
|
||||
char *pName;
|
||||
ObjectFunc OFunc;
|
||||
KillFunc KFunc;
|
||||
void *pData;
|
||||
struct __Clist *pNext;
|
||||
struct __Clist *pPrevious;
|
||||
} CommandList;
|
||||
\end{verbatim}
|
||||
The fields are: \begin{description}
|
||||
\item[name] The command name.
|
||||
\item[OFunc] The object wrapper function.
|
||||
\item[KFunc] The object data structure removal function.
|
||||
\item[pData] The objects data structure.
|
||||
\item[pNext, pPrevious] pointers necessary to maintain the doubly linked
|
||||
list of commands.
|
||||
\end{description}
|
||||
|
||||
The interpreter itself is described by the following data structure:
|
||||
\begin{verbatim}
|
||||
typedef struct __SINTER
|
||||
{
|
||||
CommandList *pCList;
|
||||
OutCode eOut;
|
||||
void *pTcl;
|
||||
char **argv;
|
||||
int iDeleting;
|
||||
}SicsInterp;
|
||||
\end{verbatim}
|
||||
The fields are: \begin{description}
|
||||
\item[pCList] A pointer to the command list.
|
||||
\item[eOut] an out code.
|
||||
\item[pTcl] a pointer to the Tcl macro interpreter.
|
||||
\item[argv] An argv[] array with command arguments.
|
||||
\item[iDeleting] a flag which is set when the interpreter is in the
|
||||
process of being removed.
|
||||
\end{description}
|
||||
|
||||
Please note, that currently commands are searched for by linear scanning of
|
||||
the command list, doing a strcmp at each stop. This is inherently
|
||||
inefficient. If in some stage interpreter inefficiency is a problem this
|
||||
scheme should be chnaged to a hash table system or a randomized binary tree.
|
||||
|
||||
|
||||
The interpreter can be controlled with the following functions:
|
||||
\begin{description}
|
||||
\item[SicsInterp *InitInterp(void)]
|
||||
Makes a new interpreter. Returns him on success, else NULL
|
||||
\item[int AddCommand(SicsInterp *pInterp, char *pName, ObjectFunc pFunc,
|
||||
KillFunc pKFunc, void *pData)]
|
||||
Adds a new command, Returns True or False, depending on success
|
||||
Parameters:
|
||||
\begin{itemize}
|
||||
\item pInterp : the interpreter to add the command to.
|
||||
\item pName : the commands name
|
||||
\item pFunc : the object function to call when this command is
|
||||
invoked. Definition of type: see above
|
||||
\item pKFunc : function to call in order to delete command data.
|
||||
type definition: above
|
||||
\item pData : pointer to the command's own datastructure. Will be
|
||||
passed as pData with each call to Ofunc.
|
||||
\end{itemize}
|
||||
It is possible to install commands without an associated data structure.
|
||||
Then pData must be NULL. In such cases AddCommand provides a default data
|
||||
structure with a default object descriptor.
|
||||
\item[int RemoveCommand(SicsInterp *pInterp, char *pName)]
|
||||
Kills the command name from the interpreter pInterp
|
||||
\item[int InterpExecute(SicsInterp *self,pSConnection pCon,char *pCommand)]
|
||||
Executes a command in the interpreter self. Essentially converts
|
||||
pCommand in an argc, argv[] pair, sets various status things and
|
||||
invokes the object function. Takes care of status and error reporting
|
||||
afterwards.
|
||||
Parameters: \begin{itemize}
|
||||
\item self : interpreter to invoke command in.
|
||||
\item The connection pCon will be used for I/O and status reporting.
|
||||
\item The command to invoke is the string pCommand.
|
||||
\end{itemize}
|
||||
Returns -1 if the command can not be found.
|
||||
If the command is found, 1 is returned on success, 0 on failure in
|
||||
the command.
|
||||
\item[CommandList *FindCommand(SicsInterp *pInterp, char *name)]
|
||||
Searches the Interpreters pInterp command list for a command
|
||||
with name. Returns its data structure if found, NULL else
|
||||
\item[int WriteSicsStatus(SicsInterp *pSics,char *file)]
|
||||
SICS needs a way to save the status of each object into a file.
|
||||
This is done by invoking for each object the object descriptor
|
||||
function SaveStatus. This function does just that.
|
||||
Parameters: \begin{itemize}
|
||||
\item pSics : the interpreter to use.
|
||||
\item file : the file to write the information to.
|
||||
\end{itemize}
|
||||
Returns: 1 on success, 0 on failure.
|
||||
|
||||
\item[int InterpWrite(SicsInterp *pSics, char *buffer)]
|
||||
Writes result to Tcl, used for Macro mechanism.
|
||||
This is an internal function and should not be used.
|
||||
\item[void DeleteInterp(SicsInterp *self)]
|
||||
Deletes the interpreter self aand clears all asoociated datastructures.
|
||||
self will no longer be vaild after this.
|
||||
\item[FindAlias] find the alias for a given data structure. This is a
|
||||
special function required internally.
|
||||
\item[FindCommandData] is a convenience wrapper around FindCommand
|
||||
which returns the commands data structure instead the CommandList
|
||||
entry fo a given command name. Returns NULL, if the command was not
|
||||
found.
|
||||
|
||||
\end{description}
|
||||
37
doc/programmer/alias.tex
Normal file
37
doc/programmer/alias.tex
Normal file
@@ -0,0 +1,37 @@
|
||||
\subsection{The Alias Facility}
|
||||
Aliases make commands available under a different name. SICS currently supports two types of aliases:
|
||||
\begin{itemize}
|
||||
\item Object aliases. This is a facility for renaming first class SICS
|
||||
objects such as commands and hardware objects. This is installed into
|
||||
SICS by creating a new name in the interpreter but with the data
|
||||
structures of the original object. Thus all interface operations such
|
||||
as driving etc will work. Object aliases are installed from the
|
||||
initialization script through the SicsAlias command.
|
||||
\item Command aliases. This is just plain text replacement. For
|
||||
instance one may define ``sttll'' instead of ``a4 softlowerlim''. Such
|
||||
an alias can be installed with the ``alias'' command at any
|
||||
time. However, renaming a motor with this scheme will not work
|
||||
properly as this alias facility has no way to forward interfaces
|
||||
properly.
|
||||
\end{itemize}
|
||||
There is no
|
||||
data structure associated with object aliases. The trick is done by
|
||||
just putting in
|
||||
the same command as a new name into the interpreter.
|
||||
|
||||
Corrspondingly there is only one function to it:
|
||||
\begin{verbatim}
|
||||
int SicsAlias(SConnection *pCon, SicsInterp *pSics, void *pData,
|
||||
int argc, char *argv[]);
|
||||
\end{verbatim}
|
||||
SicsAlias is the object wrapper function which implements the alias command.
|
||||
|
||||
|
||||
Command aliases are implemented through:
|
||||
\begin{verbatim}
|
||||
int MakeAlias(SConnection *pCon, SicsInterp *pSics, void *pData,
|
||||
int argc, char *argv[]);
|
||||
\end{verbatim}
|
||||
There is a little trivial data structure associated with command
|
||||
aliases which is defined in alias.c.
|
||||
|
||||
176
doc/programmer/amor2t.tex
Normal file
176
doc/programmer/amor2t.tex
Normal file
@@ -0,0 +1,176 @@
|
||||
\subsection{AMOR Two Theta}
|
||||
AMOR is SINQ's new reflectometer. It has the peculiar feature that the
|
||||
two theta movement of the detector is expressed in translations along
|
||||
the reflectometer base axis and the detector height. Additionally the
|
||||
detector is tilted. The height of two diaphragms has to be adjusted as
|
||||
well. And, in polarizing mode, the analyzer has to be operated as
|
||||
well. Quite a complicated movement. I fear this module may only be
|
||||
useful for AMOR, but may be, other reflectometers may profit as well.
|
||||
This object implements this complex movement as a virtual motor.
|
||||
|
||||
The following formulas are used for the necessary calculations:
|
||||
\begin{eqnarray}
|
||||
delta height & = & h_{s} - R \sin \alpha \\
|
||||
delta x & = & |x_{c} - x_{s}| - R \cos \alpha \\
|
||||
omega & = & -2 MOM + 2 SOM \\
|
||||
\end{eqnarray}
|
||||
with
|
||||
\begin{eqnarray}
|
||||
h_{s} & = & \tan(2MOM)|x_{c} - x_{s}| \\
|
||||
R & = & \sqrt{hs^{2} - |x_{c} - x_{s}|^{2}} \\
|
||||
\alpha & = & 180 -90 - \beta - 2SOM \\
|
||||
\beta & = & 180 - 90 - 2MOM \\
|
||||
MOM & = & polarizer \omega \\
|
||||
SOM & = & sample \omega \\
|
||||
x_{c} & = & counter position \\
|
||||
x_{s} & = & sample position\\
|
||||
\end{eqnarray}
|
||||
The same equations hold true for the calculations of the diaphragm
|
||||
heights, just replace the distances. The equations for the analyzer
|
||||
are not yet known.
|
||||
|
||||
Due to this complicated movement this module needs to know about a lot
|
||||
of motors and a lot of parameters. The distances of the various
|
||||
components need to be modified at run time in order to allow for
|
||||
configuration changes. These are not motorized but must be entered
|
||||
manually.
|
||||
|
||||
\subsubsection{Data Structures}
|
||||
Consequently data structures are complex. The first data structure
|
||||
used is an entry in an array of motors to start:
|
||||
\begin{flushleft} \small
|
||||
\begin{minipage}{\linewidth} \label{scrap1}
|
||||
$\langle$putput {\footnotesize ?}$\rangle\equiv$
|
||||
\vspace{-1ex}
|
||||
\begin{list}{}{} \item
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@ typedef struct {@\\
|
||||
\mbox{}\verb@ pMotor pMot;@\\
|
||||
\mbox{}\verb@ char pName[80];@\\
|
||||
\mbox{}\verb@ float fTarget;@\\
|
||||
\mbox{}\verb@ }MotEntry, *pMotEntry;@\\
|
||||
\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}
|
||||
\begin{description}
|
||||
\item[pMot] is a pointer to the motors data structure.
|
||||
\item[pName] is the name of the motor to start.
|
||||
\item[fTarget] is the target value for the motor.
|
||||
\end{description}
|
||||
|
||||
The next data structure is the class data structure for amor2t:
|
||||
\begin{flushleft} \small
|
||||
\begin{minipage}{\linewidth} \label{scrap2}
|
||||
$\langle$amoredata {\footnotesize ?}$\rangle\equiv$
|
||||
\vspace{-1ex}
|
||||
\begin{list}{}{} \item
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@ typedef struct __AMOR2T {@\\
|
||||
\mbox{}\verb@ pObjectDescriptor pDes;@\\
|
||||
\mbox{}\verb@ pIDrivable pDriv;@\\
|
||||
\mbox{}\verb@ pMotor aEngine[MAXMOT];@\\
|
||||
\mbox{}\verb@ MotEntry toStart[MAXMOT];@\\
|
||||
\mbox{}\verb@ int iStart;@\\
|
||||
\mbox{}\verb@ ObPar *aParameter;@\\
|
||||
\mbox{}\verb@ }Amor2T;@\\
|
||||
\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}
|
||||
\begin{description}
|
||||
\item[pDes] The standard SICS object descriptor.
|
||||
\item[pDriv] The drivable interface. The functions defined for the
|
||||
drivable interface implement most of the work of this class.
|
||||
\item[aEngine] An array of pointers to the motor data structures this
|
||||
class has to deal with. The proper initialization of this is taken
|
||||
care of during the initialization of the object.
|
||||
\item[toStart] An array of motors to start when all calculations have
|
||||
been performed.
|
||||
\item[iStart] The number of valid entries in toStart.
|
||||
\item[aParameter] An array of parameters for this object.
|
||||
\end{description}
|
||||
|
||||
\subsubsection{The Interface}
|
||||
The interface to this module is quite primitive. Most of the
|
||||
functionality is hidden in the drivable interface. So there are only
|
||||
functions for interacting with the interpreter.
|
||||
|
||||
\begin{flushleft} \small
|
||||
\begin{minipage}{\linewidth} \label{scrap3}
|
||||
$\langle$amorinterface {\footnotesize ?}$\rangle\equiv$
|
||||
\vspace{-1ex}
|
||||
\begin{list}{}{} \item
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@ typedef struct __AMOR2T *pAmor2T;@\\
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@ int Amor2TFactory(SConnection *pCon, SicsInterp *pSics, void *pData,@\\
|
||||
\mbox{}\verb@ int argc, char *argv[]);@\\
|
||||
\mbox{}\verb@ int Amor2TAction(SConnection *pCon, SicsInterp *pSics, void *pData,@\\
|
||||
\mbox{}\verb@ int argc, char *argv[]);@\\
|
||||
\mbox{}\verb@ void Amor2TKill(void *pData); @\\
|
||||
\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}
|
||||
\begin{flushleft} \small
|
||||
\begin{minipage}{\linewidth} \label{scrap4}
|
||||
\verb@"amor2t.i"@ {\footnotesize ? }$\equiv$
|
||||
\vspace{-1ex}
|
||||
\begin{list}{}{} \item
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@/*--------------------------------------------------------------------------@\\
|
||||
\mbox{}\verb@ A m o r 2 T . i@\\
|
||||
\mbox{}\verb@ Internal data structure definitions for Amor2T. For details see amor2t.tex.@\\
|
||||
\mbox{}\verb@ DO NOT TOUCH! This file is automatically created from amor2t.w.@\\
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@ Mark Koennecke, September 1999@\\
|
||||
\mbox{}\verb@----------------------------------------------------------------------------*/@\\
|
||||
\mbox{}\verb@@$\langle$putput {\footnotesize ?}$\rangle$\verb@@\\
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@@$\langle$amoredata {\footnotesize ?}$\rangle$\verb@@\\
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@@$\diamond$
|
||||
\end{list}
|
||||
\vspace{-2ex}
|
||||
\end{minipage}\\[4ex]
|
||||
\end{flushleft}
|
||||
\begin{flushleft} \small
|
||||
\begin{minipage}{\linewidth} \label{scrap5}
|
||||
\verb@"amor2t.h"@ {\footnotesize ? }$\equiv$
|
||||
\vspace{-1ex}
|
||||
\begin{list}{}{} \item
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@/*-------------------------------------------------------------------------@\\
|
||||
\mbox{}\verb@ A m o r 2 T@\\
|
||||
\mbox{}\verb@ A class for controlling the two theta movement of a reflectometer. @\\
|
||||
\mbox{}\verb@ Especially the AMOR reflectometer at SINQ. For details see the file @\\
|
||||
\mbox{}\verb@ amor2t.tex. DO NOT TOUCH! This file is automatically created from amor2t.w@\\
|
||||
\mbox{}\verb@ with nuweb.@\\
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@ Mark Koennecke, September 1999@\\
|
||||
\mbox{}\verb@---------------------------------------------------------------------------*/@\\
|
||||
\mbox{}\verb@#ifndef AMOR2T@\\
|
||||
\mbox{}\verb@#define AMOR2T@\\
|
||||
\mbox{}\verb@@$\langle$amorinterface {\footnotesize ?}$\rangle$\verb@@\\
|
||||
\mbox{}\verb@#endif @\\
|
||||
\mbox{}\verb@@$\diamond$
|
||||
\end{list}
|
||||
\vspace{-2ex}
|
||||
\end{minipage}\\[4ex]
|
||||
\end{flushleft}
|
||||
71
doc/programmer/amorscan.tex
Normal file
71
doc/programmer/amorscan.tex
Normal file
@@ -0,0 +1,71 @@
|
||||
\subsection{Amor Scan}
|
||||
This is a special adaption of the general scan routines for the
|
||||
reflectometer AMOR at SINQ. It works by replacing the configurable
|
||||
routines in the general scan command with special ones, suited to the
|
||||
reflectometers purpose. There are several adaptions to the standard
|
||||
scan command:
|
||||
\begin{itemize}
|
||||
\item Data is written to NeXus files instead of ASCII files.
|
||||
\item There are two counters to keep track of.
|
||||
\item Furthermore stubs are provided for dealing with spin flippers.
|
||||
\end{itemize}
|
||||
|
||||
In order to keep track of counters and monitors the following
|
||||
convention has been devised:
|
||||
\begin{itemize}
|
||||
\item GetCounts gets the main detector.
|
||||
\item GetMonitor 0 the second detector
|
||||
\item GetMonitor 1 the first detector other spin
|
||||
\item GetMonitor 2 the second detector other spin
|
||||
\item GetMonitor 3 the first monitor
|
||||
\item GetMonitor 4 the second monitor
|
||||
\end{itemize}
|
||||
Thus the monitor channels are used to keep the additional counter
|
||||
information.
|
||||
|
||||
This module provides only one external function:
|
||||
\begin{flushleft} \small
|
||||
\begin{minipage}{\linewidth} \label{scrap1}
|
||||
$\langle$amorscan {\footnotesize ?}$\rangle\equiv$
|
||||
\vspace{-1ex}
|
||||
\begin{list}{}{} \item
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@ int ConfigureAmor(pScanData pScan);@\\
|
||||
\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}
|
||||
which configures the variable fields and function pointers in pScan to
|
||||
functions defined in this module. These then do the right thing. This
|
||||
module is also an example of how the scan command can be configured to do
|
||||
tricks based on the syntax and hooks defined in scan.*.
|
||||
|
||||
|
||||
\begin{flushleft} \small
|
||||
\begin{minipage}{\linewidth} \label{scrap2}
|
||||
\verb@"amorscan.h"@ {\footnotesize ? }$\equiv$
|
||||
\vspace{-1ex}
|
||||
\begin{list}{}{} \item
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@/*-----------------------------------------------------------------------@\\
|
||||
\mbox{}\verb@ A M O R S C A N@\\
|
||||
\mbox{}\verb@ Adaption of the scan command to do things specific to the@\\
|
||||
\mbox{}\verb@ reflectometer AMOR at SINQ.@\\
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@ Mark Koennecke, September 1999@\\
|
||||
\mbox{}\verb@-----------------------------------------------------------------------*/@\\
|
||||
\mbox{}\verb@#ifndef AMORSCAN@\\
|
||||
\mbox{}\verb@#define AMORSCAN@\\
|
||||
\mbox{}\verb@@$\langle$amorscan {\footnotesize ?}$\rangle$\verb@@\\
|
||||
\mbox{}\verb@#endif@\\
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@@$\diamond$
|
||||
\end{list}
|
||||
\vspace{-2ex}
|
||||
\end{minipage}\\[4ex]
|
||||
\end{flushleft}
|
||||
138
doc/programmer/amorstat.tex
Normal file
138
doc/programmer/amorstat.tex
Normal file
@@ -0,0 +1,138 @@
|
||||
\subsection{Amor Status Display Support}
|
||||
The reflectometer AMOR has a few unique status display requirements:
|
||||
\begin{itemize}
|
||||
\item In scan mode up to four detector counts curves must be shown for
|
||||
the two counters in spin-up or spin-down mode. This needs to be
|
||||
updated after each scan point.
|
||||
\item Additionally user defined curves may need to be displayed.
|
||||
\item The usual helper information muste be displayed.
|
||||
\item In TOF mode it must be possible to define a region on the
|
||||
detector whose summed counts are displayed versus the time
|
||||
binning. This must be sent on request.
|
||||
\end{itemize}
|
||||
In order to cover all this a special object within SICS is required
|
||||
which deals with all this and packages information in a status display
|
||||
compliant way.
|
||||
|
||||
In order to do this the amorstatus object registers callbacks both
|
||||
with the histogram memory and the scan object. These callback
|
||||
functions are then responsible for updating the status displays. In
|
||||
order for amorstatus to be able to do this, the client must register
|
||||
itself with a special command.
|
||||
|
||||
In order to achieve all this some data structures are needed:
|
||||
\begin{flushleft} \small
|
||||
\begin{minipage}{\linewidth} \label{scrap1}
|
||||
$\langle$asdata {\footnotesize ?}$\rangle\equiv$
|
||||
\vspace{-1ex}
|
||||
\begin{list}{}{} \item
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@/*---------------------------------------------------------------------*/@\\
|
||||
\mbox{}\verb@ typedef struct {@\\
|
||||
\mbox{}\verb@ float *fX, *fY;@\\
|
||||
\mbox{}\verb@ int iNP;@\\
|
||||
\mbox{}\verb@ char *name;@\\
|
||||
\mbox{}\verb@ }UserData, *pUserData; @\\
|
||||
\mbox{}\verb@/*---------------------------------------------------------------------*/@\\
|
||||
\mbox{}\verb@ typedef struct __AMORSTAT {@\\
|
||||
\mbox{}\verb@ pObjectDescriptor pDes;@\\
|
||||
\mbox{}\verb@ pICallBack pCall;@\\
|
||||
\mbox{}\verb@ int iUserList;@\\
|
||||
\mbox{}\verb@ pScanData pScan;@\\
|
||||
\mbox{}\verb@ pHistMem pHM;@\\
|
||||
\mbox{}\verb@ int iTOF;@\\
|
||||
\mbox{}\verb@ }AmorStat, *pAmorStat;@\\
|
||||
\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 fourth data structure is the amor status object data structure. It
|
||||
has the following fields:
|
||||
\begin{description}
|
||||
\item[pDes] The standard SICS object descriptor.
|
||||
\item[pCall] The callback interface.
|
||||
\item[iUserList] A list of user data loaded data.
|
||||
\item[pScan] A pointer to the scan object.
|
||||
\item[pHM] A pointer to the histogram memory.
|
||||
\item[iTOF] A flag which is true if we are taking measurements in TOF
|
||||
mode.
|
||||
\end{description}
|
||||
|
||||
In terms of a function interface this object has not much to
|
||||
offer. Its main purpose is really as an interface to the status
|
||||
display clients and thus it is configured through the interpreter
|
||||
interface function. No need for other SICS objects to access it.
|
||||
|
||||
\begin{flushleft} \small
|
||||
\begin{minipage}{\linewidth} \label{scrap2}
|
||||
$\langle$asinter {\footnotesize ?}$\rangle\equiv$
|
||||
\vspace{-1ex}
|
||||
\begin{list}{}{} \item
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@ int AmorStatusFactory(SConnection *pCon, SicsInterp *pSics, void *pData,@\\
|
||||
\mbox{}\verb@ int argc, char *argv[]);@\\
|
||||
\mbox{}\verb@ int AmorStatusAction(SConnection *pCon, SicsInterp *pSics, void *pData,@\\
|
||||
\mbox{}\verb@ int argc, char *argv[]);@\\
|
||||
\mbox{}\verb@ void KillAmorStatus(void *pData);@\\
|
||||
\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}
|
||||
\begin{flushleft} \small
|
||||
\begin{minipage}{\linewidth} \label{scrap3}
|
||||
\verb@"amorstat.i"@ {\footnotesize ? }$\equiv$
|
||||
\vspace{-1ex}
|
||||
\begin{list}{}{} \item
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@/*------------------------------------------------------------------------@\\
|
||||
\mbox{}\verb@ A M O R S T A T U S@\\
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@ Internal data structure definitions for the AMOR status display @\\
|
||||
\mbox{}\verb@ facilitator object. DO NOT CHANGE. This file is automatically@\\
|
||||
\mbox{}\verb@ created from amorstat.w.@\\
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@ Mark Koennecke, September 1999@\\
|
||||
\mbox{}\verb@---------------------------------------------------------------------*/@\\
|
||||
\mbox{}\verb@@$\langle$asdata {\footnotesize ?}$\rangle$\verb@@\\
|
||||
\mbox{}\verb@ @\\
|
||||
\mbox{}\verb@@$\diamond$
|
||||
\end{list}
|
||||
\vspace{-2ex}
|
||||
\end{minipage}\\[4ex]
|
||||
\end{flushleft}
|
||||
\begin{flushleft} \small
|
||||
\begin{minipage}{\linewidth} \label{scrap4}
|
||||
\verb@"amorstat.h"@ {\footnotesize ? }$\equiv$
|
||||
\vspace{-1ex}
|
||||
\begin{list}{}{} \item
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@/*------------------------------------------------------------------------@\\
|
||||
\mbox{}\verb@ A M O R S T A T U S@\\
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@ Public definitions for the AMOR status display @\\
|
||||
\mbox{}\verb@ facilitator object. DO NOT CHANGE. This file is automatically@\\
|
||||
\mbox{}\verb@ created from amorstat.w.@\\
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@ Mark Koennecke, September 1999@\\
|
||||
\mbox{}\verb@---------------------------------------------------------------------*/@\\
|
||||
\mbox{}\verb@#ifndef AMORSTATUS@\\
|
||||
\mbox{}\verb@#define AMORSTATUS@\\
|
||||
\mbox{}\verb@@$\langle$asinter {\footnotesize ?}$\rangle$\verb@@\\
|
||||
\mbox{}\verb@#endif@\\
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@@$\diamond$
|
||||
\end{list}
|
||||
\vspace{-2ex}
|
||||
\end{minipage}\\[4ex]
|
||||
\end{flushleft}
|
||||
64
doc/programmer/bruker.tex
Normal file
64
doc/programmer/bruker.tex
Normal file
@@ -0,0 +1,64 @@
|
||||
\subsubsection{Bruker Magnet Controller B-EC-1}
|
||||
SANS is using a Bruker magnet controller. This controller is integrated
|
||||
into SICS as a derivate of an environment controller. The Bruker controller
|
||||
can be operated in two modes: in the first the current is controlled,
|
||||
in the second the current
|
||||
is controlled by an external hall sensor giving the magnetic field. Whatever
|
||||
is the controlling sensor, the magnetic field and the current need to be
|
||||
read. Furthermore this device supports switching the polarity. All this is
|
||||
achieved with a special driver and an additional wrapper function for
|
||||
handling extra commands. All this is implemented in the file bruker.h
|
||||
and bruker.c. The functions defined are:
|
||||
|
||||
\begin{verbatim}
|
||||
pEVDriver CreateBrukerDriver(int argc, char *argv[]);
|
||||
|
||||
int BrukerReadField(pEVControl self, float *fField);
|
||||
int BrukerReadCurrent(pEVControl self, float *fCurrent);
|
||||
|
||||
int BrukerAction(SConnection *pCon, SicsInterp *pSics, void *pData,
|
||||
int argc, char *argv[]);
|
||||
|
||||
\end{verbatim}
|
||||
|
||||
\begin{description}
|
||||
\item[CreateBrukerDriver] creates a driver for the bruker magnet
|
||||
controller.
|
||||
\item[BrukerReadField] reads the current magnetic field.
|
||||
\item[BrukerReadCurrent] reads the current current in Ampere.
|
||||
\item[BrukerAction] a special SICS interpreter wrapper function for
|
||||
the Bruker Magnet. This function handles the few special Bruker
|
||||
commands and passes everything else to the standard environment
|
||||
controller handler function.
|
||||
\end{description}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
81
doc/programmer/buffer.tex
Normal file
81
doc/programmer/buffer.tex
Normal file
@@ -0,0 +1,81 @@
|
||||
\subsection{The LNS R\"unbuffer}
|
||||
R\"unbuffers are a special LNS feature for handling instruments. Essentially
|
||||
a R\"unbuffer is a list of commands which can be executed as a block. On
|
||||
line editing of such a R\"unbuffer is supported as well. R\"unbuffers can
|
||||
also be saved to or read from disk files. R\"unbuffers are related to the
|
||||
batch file processing facility FileEval. However, there are subtle
|
||||
differences. The first is I/O: When evaluating a batch file with FileEval
|
||||
all messages except errors and warnings are suppressed. This is a nice
|
||||
feature if the file evaluated contains a macro, where a user might be
|
||||
confused when confronted with all internal messages. With R\"unbuffers all
|
||||
output is written to the user. R\"unbuffers support only SICS commands, with
|
||||
FileEval Tcl commands can be given as well.
|
||||
|
||||
|
||||
It turned out that the R\"unbuffer system together with the R\"unlist
|
||||
facility documented in the next section is rarely
|
||||
used. Experimentators prefer the batch file facility ``fileeval''
|
||||
instead. Consequently, this may be retracted and cleaned out in some
|
||||
stage.
|
||||
|
||||
A R\"unbuffer is characterized by a an own data structure:
|
||||
\begin{verbatim}
|
||||
typedef struct {
|
||||
pObjectDescriptor pDes; /* needed */
|
||||
char *name; /* BufferName */
|
||||
int iLineList; /* Handle to the Line List */
|
||||
} RuenBuffer, *pRuenBuffer;
|
||||
\end{verbatim}
|
||||
The fields:
|
||||
\begin{description}
|
||||
\item[pDes] A pointer to the usual SICS object descriptor.
|
||||
\item[name] The name of the R\"unbuffer.
|
||||
\item[iLineList] The handle of the lldlist holding the lines of the
|
||||
R\"unbuffer.
|
||||
\end{description}
|
||||
|
||||
Interaction with R\"unbuffers happesn through the functions listed below.
|
||||
All functions return 0 on failure or 1 on success, if not stated otherwise.
|
||||
Most functions take as first parameter a pointer to the R\"unbuffer to act
|
||||
upon.
|
||||
\begin{description}
|
||||
\item[pRuenBuffer CreateRuenBuffer(char *name)] creates a R\"unbuffer.
|
||||
Returns the pointer to the new r\"unbuffer on success, or NULL on failure.
|
||||
\item[void DeleteRuenBuffer(void *pSelf)] Deletes a R\"unbuffer.
|
||||
\item[pRuenBuffer CopyRuenBuffer(pRuenBuffer pOld, char *NewName)] copies a
|
||||
R\"unbuffer including all data lines. Returns NULL on failure, a pointer to
|
||||
a new R\"unbuffer structure otherwise.
|
||||
\item[int BufferAppendLine(pRuenBuffer self, char *line)] appends line to
|
||||
r\"unbuffer self.
|
||||
\item[int BufferDel(pRuenBuffer self, int iLine)] deletes line iLine from
|
||||
r\"unbuffer self.
|
||||
\item[int BufferInsertAfter(pRuenBuffer self, int iLine, char *line)]
|
||||
inserts line line AFTER line number iLine in the RuenBuffer self.
|
||||
\item[int BufferPrint(pRuenBuffer self, SConnection *pCon)]
|
||||
lists the contents of the RuenBuffer on the Connection pCon.
|
||||
\item[int BufferReplace(pRuenBuffer self, char *pattern, char *pReplace)]
|
||||
replaces all occurences of the string pattern in the whole RuenBuffer
|
||||
by the replacement string pReplace.
|
||||
\item[int BufferRun(pRuenBuffer self, SConnection *pCon, SicsInterp *pSics)]
|
||||
executes the lines of the Ruenbuffer one by one.
|
||||
Returns 1 on success, 0 on error.
|
||||
\item[int BufferSave(pRuenBuffer self, char *file)]
|
||||
writes the contents of Ruenbuffer self to the file specified by
|
||||
file.
|
||||
Returns 1 on success, 0 on error.
|
||||
\item[int BufferLoad(pRuenBuffer self, char *file)]
|
||||
reads the contents of file into the RuenBuffer self.
|
||||
Returns 1 on success, 0 on error.
|
||||
\item[int InitBufferSys(SConnection *pCon, SicsInterp *pSics, void *pData,\\
|
||||
int argc, char *argv[])] The factory function for the
|
||||
R\"unbuffer system. Initialises the Buf command and the ruli command.
|
||||
\item[int BufferCommand(SConnection *pCon, SicsInterp *pSics, void *pData,\\
|
||||
int argc, char *argv[])] The object wrapper function
|
||||
which implements the Buf command.
|
||||
\item[int BufferAction(SConnection *pCon, SicsInterp *pSics, void *pData,\\
|
||||
int argc, char *argv[])] The object wrapper function for
|
||||
the R\"unbuffer itself.
|
||||
\item[pRuenBuffer FindRuenBuffer(SicsInterp *pSics, char *name)] finds
|
||||
r\"unbuffer name in the interpreter pSics. Returns a pointer to the
|
||||
r\"unbuffers data structure if it exists, NULL otherwise.
|
||||
\end{description}
|
||||
79
doc/programmer/center.tex
Normal file
79
doc/programmer/center.tex
Normal file
@@ -0,0 +1,79 @@
|
||||
\subsection{Fit and Center}
|
||||
This is a fit routine for SICS. It takes a scan and tries to find a peak and
|
||||
its position. Trials showed that fitting a gauss function is not robust
|
||||
enough for this facility which has to cope with bizarre peak shapes, half
|
||||
finished measurements and the like. The algorithm choosen tries to find the
|
||||
center of gravity of the peak. It does this by searching for the maximum
|
||||
point in the diagram first. Then the points where the peak is below
|
||||
half maximum are searched for either side of the peak. Within these
|
||||
limits the COG is calculated. When this is done fit will print some
|
||||
info about the peak.
|
||||
|
||||
Center will the drive the scan variable to the COG of the peak.
|
||||
|
||||
The interface to this simple facility is simple:
|
||||
|
||||
\begin{flushleft} \small
|
||||
\begin{minipage}{\linewidth} \label{scrap1}
|
||||
$\langle$fitinter {\footnotesize ?}$\rangle\equiv$
|
||||
\vspace{-1ex}
|
||||
\begin{list}{}{} \item
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@ typedef struct __FitCenter *pFit;@\\
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@/*--------------------------------------------------------------------------*/@\\
|
||||
\mbox{}\verb@ pFit CreateFitCenter(pScanData pScan);@\\
|
||||
\mbox{}\verb@ void DeleteFitCenter(void *pData);@\\
|
||||
\mbox{}\verb@/*-------------------------------------------------------------------------*/@\\
|
||||
\mbox{}\verb@ int CalculateFit(pFit self);@\\
|
||||
\mbox{}\verb@ /* @\\
|
||||
\mbox{}\verb@ CalcluateFit returns: -1 when left FWHM could not be found@\\
|
||||
\mbox{}\verb@ -2 when right FWHM could not be found@\\
|
||||
\mbox{}\verb@ 1 on success@\\
|
||||
\mbox{}\verb@ */@\\
|
||||
\mbox{}\verb@ int CalculateFitFromData(pFit self, float fAxis[], long lSum[], @\\
|
||||
\mbox{}\verb@ int iLen);@\\
|
||||
\mbox{}\verb@ void GetFitResults(pFit self, float *fNewCenter, float *fStdDev,@\\
|
||||
\mbox{}\verb@ float *FWHM, float *fMax);@\\
|
||||
\mbox{}\verb@ int DriveCenter(pFit self, SConnection *pCon, SicsInterp *pSics);@\\
|
||||
\mbox{}\verb@/*-------------------------------------------------------------------------*/@\\
|
||||
\mbox{}\verb@ int FitFactory(SConnection *pCon,SicsInterp *pSics, void *pData,@\\
|
||||
\mbox{}\verb@ int argc, char *argv[]);@\\
|
||||
\mbox{}\verb@ int FitWrapper(SConnection *pCon,SicsInterp *pSics, void *pData,@\\
|
||||
\mbox{}\verb@ int argc, char *argv[]);@\\
|
||||
\mbox{}\verb@ int CenterWrapper(SConnection *pCon,SicsInterp *pSics, void *pData,@\\
|
||||
\mbox{}\verb@ int argc, char *argv[]);@\\
|
||||
\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}
|
||||
\begin{flushleft} \small
|
||||
\begin{minipage}{\linewidth} \label{scrap2}
|
||||
\verb@"fitcenter.h"@ {\footnotesize ? }$\equiv$
|
||||
\vspace{-1ex}
|
||||
\begin{list}{}{} \item
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@/*---------------------------------------------------------------------------@\\
|
||||
\mbox{}\verb@ F I T C E N T E R@\\
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@ A simple peak finding and center of gravity determination facility for@\\
|
||||
\mbox{}\verb@ SICS.@\\
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@ copyright: see copyright.h@\\
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@ Mark Koennecke, October 1997@\\
|
||||
\mbox{}\verb@----------------------------------------------------------------------------*/@\\
|
||||
\mbox{}\verb@#ifndef SICSFITCENTER@\\
|
||||
\mbox{}\verb@#define SICSFITCENTER@\\
|
||||
\mbox{}\verb@@$\langle$fitinter {\footnotesize ?}$\rangle$\verb@@\\
|
||||
\mbox{}\verb@#endif@\\
|
||||
\mbox{}\verb@@$\diamond$
|
||||
\end{list}
|
||||
\vspace{-2ex}
|
||||
\end{minipage}\\[4ex]
|
||||
\end{flushleft}
|
||||
380
doc/programmer/choco.tex
Normal file
380
doc/programmer/choco.tex
Normal file
@@ -0,0 +1,380 @@
|
||||
\subsection{Chopper Controller}
|
||||
Yet another way to deal with a controller has been devised for
|
||||
SICS. This uses the concept of a general controller which can have
|
||||
parameters enquired and set. Furthermore it may have parameters which
|
||||
may be driven like a motor or environment controller through special
|
||||
adapters . This scheme is
|
||||
used for the chopper controller for FOCUS.
|
||||
\begin{itemize}
|
||||
\item A driver for a particular controller which allows to set and get
|
||||
parameters.
|
||||
\item The general controller object which holds things together.
|
||||
\item An adapter object which allows to drive special parameters in a general
|
||||
controller. Such adapter objects can be configured for each drivable parameter
|
||||
in a controller.
|
||||
\item An adapter to an environment controller driver.
|
||||
\end{itemize}
|
||||
The test case for this way of doing things is a controller for running
|
||||
choppers. This is why it gets the name.
|
||||
|
||||
The chopper system in question is the FOCUS chopper system. There are two
|
||||
choppers, a fermi chopper and a disk chopper. This system can be run in two
|
||||
different modes: In synchronous mode both choppers run at a
|
||||
predefined ratio of speeds. For instance the fermi chopper is two
|
||||
times faster then the disk chopper. This means, that setting a new
|
||||
value for one chopper also changes the speed of the other chopper. In
|
||||
asynchronous mode both choppers operate independently. Also the ration
|
||||
to use for synchronous mode can be changed. Another parameter which
|
||||
frequently changes is the phase of the two choppers. In order to
|
||||
compensate for the fligh path between the two choppers there is a
|
||||
small angular displacement of the choppers against each other which
|
||||
varies with wavelength.
|
||||
|
||||
\subsubsection{The Controller Driver}
|
||||
The controller driver is represented by the following data structure:
|
||||
\begin{flushleft} \small
|
||||
\begin{minipage}{\linewidth} \label{scrap1}
|
||||
$\langle$codri {\footnotesize ?}$\rangle\equiv$
|
||||
\vspace{-1ex}
|
||||
\begin{list}{}{} \item
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@ typedef struct __CODRI *pCodri;@\\
|
||||
\mbox{}\verb@ typedef struct __CODRI {@\\
|
||||
\mbox{}\verb@ int (*Init)(pCodri self);@\\
|
||||
\mbox{}\verb@ int (*Close)(pCodri self);@\\
|
||||
\mbox{}\verb@ int (*Delete)(pCodri self);@\\
|
||||
\mbox{}\verb@ int (*SetPar)(pCodri self, @\\
|
||||
\mbox{}\verb@ char *parname,@\\
|
||||
\mbox{}\verb@ float fValue);@\\
|
||||
\mbox{}\verb@ int (*SetPar2)(pCodri self, @\\
|
||||
\mbox{}\verb@ char *parname,@\\
|
||||
\mbox{}\verb@ char *value);@\\
|
||||
\mbox{}\verb@ int (*GetPar)(pCodri self,@\\
|
||||
\mbox{}\verb@ char *parname,@\\
|
||||
\mbox{}\verb@ char *pBuffer,@\\
|
||||
\mbox{}\verb@ int iBufLen);@\\
|
||||
\mbox{}\verb@ int (*CheckPar)(pCodri self, @\\
|
||||
\mbox{}\verb@ char *parname);@\\
|
||||
\mbox{}\verb@ int (*GetError)(pCodri self, int *iCode,@\\
|
||||
\mbox{}\verb@ char *pError, @\\
|
||||
\mbox{}\verb@ int iErrLen);@\\
|
||||
\mbox{}\verb@ int (*TryFixIt)(pCodri self, int iCode);@\\
|
||||
\mbox{}\verb@ int (*Halt)(pCodri self);@\\
|
||||
\mbox{}\verb@ char *pParList;@\\
|
||||
\mbox{}\verb@ void *pPrivate;@\\
|
||||
\mbox{}\verb@ }Codri;@\\
|
||||
\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}
|
||||
All functions take a pointer to the controller driver itself as a
|
||||
parameter. All functions except TryFixIt and CheckPar
|
||||
return 0 on failure and 1 for success.
|
||||
\begin{description}
|
||||
\item[Init] initializes the controller driver. The parameters argc,
|
||||
argv are main() style parameters for the initialization of the
|
||||
controller driver.
|
||||
\item[Close] closes the connection to the controller but does not delete a thing.
|
||||
\item[Delete] closes the connection to the controller and deletes private data structures. Called when deleting the controller.
|
||||
\item[SetPar] tries to set the parameter parname to the value
|
||||
fValue. The last is floating point which covers the frequent
|
||||
occurence of numeric values.
|
||||
\item[SetPar2] The same as SetPar but uses test string as input for
|
||||
parameter setting.
|
||||
\item[GetPar] retrieves the parameter parname formatted as text. The
|
||||
value is put into the buffer pBuffer. iBufLen is the maximum number of
|
||||
bytes permissable for pBuffer.
|
||||
\item[CheckPar] When parameters are driven a means is needed to find
|
||||
out about the progress of operations and errors during the
|
||||
operation. This is done by CheckPar for the parameter parname. The
|
||||
return value of this function must be one of the HWBusy, HWError,
|
||||
HWDone family documented in the motor driver object description.
|
||||
\item[GetError] retrieves the last error. An integer error code is
|
||||
placed into iCode and a textual description of the problem is written
|
||||
to pError. Maximum iErrLen bytes are copied to pError.
|
||||
\item[TryFixIt] tries to fix the error condition specified by iCode in
|
||||
software if this possible. TryFisIt returns HWRedo if the last command
|
||||
needs to resent, HWFault if the problem could not be fixed and HWOK if
|
||||
the error can be ignored or was fully resolved.
|
||||
\item[pParList] is text string containing a comma separated list of
|
||||
all parameters understood by this driver.
|
||||
\item[pPrivate] Is a pointer to a driver specific specific data
|
||||
structure. This data structure will not be messed with by upper level code.
|
||||
\end{description}
|
||||
|
||||
\subsubsection{The Controller Object}
|
||||
This is the general controller object visible from the SICS
|
||||
interpreter. This object allows to list all possible
|
||||
parameters. Internal functions are provided for setting
|
||||
parameters. But this is meant to be operated through a drive adapter
|
||||
object (see below) in SICS. Thus the interface to this object
|
||||
includes:
|
||||
\begin{flushleft} \small
|
||||
\begin{minipage}{\linewidth} \label{scrap2}
|
||||
$\langle$chocoint {\footnotesize ?}$\rangle\equiv$
|
||||
\vspace{-1ex}
|
||||
\begin{list}{}{} \item
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@ typedef struct __CHOCO *pChoco;@\\
|
||||
\mbox{}\verb@/*------------------------------------------------------------------------*/@\\
|
||||
\mbox{}\verb@ int CHGetParameter(pChoco self, char *pParName, @\\
|
||||
\mbox{}\verb@ char *pParValue, int iBuflen); @\\
|
||||
\mbox{}\verb@ @\\
|
||||
\mbox{}\verb@ pCodri CHGetDriver(pChoco self);@\\
|
||||
\mbox{}\verb@ int CHList(pChoco self, SConnection *pCon, char *name);@\\
|
||||
\mbox{}\verb@/*------------------------------------------------------------------------*/@\\
|
||||
\mbox{}\verb@ int ChocoAction(SConnection *pCon, SicsInterp *pSics, void *pData,@\\
|
||||
\mbox{}\verb@ int argc, char *argv[]);@\\
|
||||
\mbox{}\verb@ int ChocoFactory(SConnection *pCon, SicsInterp *pSics, void *pData,@\\
|
||||
\mbox{}\verb@ int argc, char *argv[]);@\\
|
||||
\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}
|
||||
\begin{description}
|
||||
\item[CHGetParameter] retrieves the value of the parameter ParName
|
||||
converted to text. Maximum iBufLen of result or error text are copied into the
|
||||
buffer pParvalue.
|
||||
\item[CHGetDriver] returns a pointer to the controller driver. This
|
||||
function will be used by the drive adapters for interfacing with the
|
||||
driver directly.
|
||||
\item[CHList] prints a listing of all parameters to the client
|
||||
described by pCon. name is the name of the controller.
|
||||
\item[ChocoAction] is the SICS interpreter interface function for the
|
||||
controller.
|
||||
\item[ChocoFactory] is the SICS interpreter interface function which
|
||||
installs a controller into SICS.
|
||||
\end{description}
|
||||
|
||||
Most of the actual work of the controller is left to the driver. Thus
|
||||
the internal data structure for a controller object is very simple:
|
||||
\begin{flushleft} \small
|
||||
\begin{minipage}{\linewidth} \label{scrap3}
|
||||
$\langle$chocodata {\footnotesize ?}$\rangle\equiv$
|
||||
\vspace{-1ex}
|
||||
\begin{list}{}{} \item
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@ typedef struct __CHOCO {@\\
|
||||
\mbox{}\verb@ pObjectDescriptor pDes;@\\
|
||||
\mbox{}\verb@ pCodri pDriv;@\\
|
||||
\mbox{}\verb@ } Choco;@\\
|
||||
\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}
|
||||
It consists just of the standard SICS object descriptor and a pointer
|
||||
to the driver.
|
||||
|
||||
\subsubsection{The Drive And Environment Adapters}
|
||||
Most of the work of the drive adaptor is hidden in the functions
|
||||
implementing the drivable interface. Thus the interface to the
|
||||
DriveAdapter is fairly simple:
|
||||
\begin{flushleft} \small
|
||||
\begin{minipage}{\linewidth} \label{scrap4}
|
||||
$\langle$adapter {\footnotesize ?}$\rangle\equiv$
|
||||
\vspace{-1ex}
|
||||
\begin{list}{}{} \item
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@ typedef struct __CHADAPTER *pCHAdapter;@\\
|
||||
\mbox{}\verb@/*-----------------------------------------------------------------------*/@\\
|
||||
\mbox{}\verb@ int CHAdapterFactory(SConnection *pCon, SicsInterp *pSics, @\\
|
||||
\mbox{}\verb@ void *pData,@\\
|
||||
\mbox{}\verb@ int argc, char *argv[]);@\\
|
||||
\mbox{}\verb@ @\\
|
||||
\mbox{}\verb@ int CHAdapterAction(SConnection *pCon, SicsInterp *pSics, @\\
|
||||
\mbox{}\verb@ void *pData,@\\
|
||||
\mbox{}\verb@ int argc, char *argv[]);@\\
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@ pEVDriver MakeControllerEnvironmentDriver(int argc, char *argv[]);@\\
|
||||
\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}
|
||||
\begin{description}
|
||||
\item[CHAdapterFactory] is the SICS interpreter factory function for
|
||||
creating a drive adapter.
|
||||
\item[CHAdapterAction] is the SICS interpreter function for
|
||||
representing the object in SICS. Just a single action is supported:
|
||||
request the value of the parameter.
|
||||
\item[MakeControllerEnvironmentDriver] creates an environment control
|
||||
driver for a parameter in a general controller object.
|
||||
\end{description}
|
||||
|
||||
The data structure for the drive adapter is slightly more interesting:
|
||||
\begin{flushleft} \small
|
||||
\begin{minipage}{\linewidth} \label{scrap5}
|
||||
$\langle$adadata {\footnotesize ?}$\rangle\equiv$
|
||||
\vspace{-1ex}
|
||||
\begin{list}{}{} \item
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@ typedef struct __CHADAPTER {@\\
|
||||
\mbox{}\verb@ pObjectDescriptor pDes;@\\
|
||||
\mbox{}\verb@ pCodri pDriv;@\\
|
||||
\mbox{}\verb@ pIDrivable pInt;@\\
|
||||
\mbox{}\verb@ float fUpper;@\\
|
||||
\mbox{}\verb@ float fLower;@\\
|
||||
\mbox{}\verb@ float fTarget;@\\
|
||||
\mbox{}\verb@ char *pParName;@\\
|
||||
\mbox{}\verb@ }CHAdapter;@\\
|
||||
\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}
|
||||
\begin{description}
|
||||
\item[pDes] is the standard object descriptor.
|
||||
\item[pDriv] is a pointer to the controller driver.
|
||||
\item[pInt] is a pointer to the drivable interface implemented by the
|
||||
adapter.
|
||||
\item[fUpper] upper limit for the parameter.
|
||||
\item[fLower] lower limit for the parameter.
|
||||
\item[pParName] is the name of the parameter which is driven through
|
||||
this adapter.
|
||||
\end{description}
|
||||
|
||||
This is the data structure for the private part of the environment
|
||||
controller driver:
|
||||
\begin{flushleft} \small
|
||||
\begin{minipage}{\linewidth} \label{scrap6}
|
||||
$\langle$evada {\footnotesize ?}$\rangle\equiv$
|
||||
\vspace{-1ex}
|
||||
\begin{list}{}{} \item
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@ typedef struct __CHEV {@\\
|
||||
\mbox{}\verb@ char *pParName;@\\
|
||||
\mbox{}\verb@ pCodri pDriv;@\\
|
||||
\mbox{}\verb@ int iLastError;@\\
|
||||
\mbox{}\verb@ }CHev, *pCHev;@\\
|
||||
\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}
|
||||
\begin{flushleft} \small
|
||||
\begin{minipage}{\linewidth} \label{scrap7}
|
||||
\verb@"codri.h"@ {\footnotesize ? }$\equiv$
|
||||
\vspace{-1ex}
|
||||
\begin{list}{}{} \item
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@/*-------------------------------------------------------------------------@\\
|
||||
\mbox{}\verb@ C o n t r o l l e r D r i v e r@\\
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@ This file contains the description of the data structure for a@\\
|
||||
\mbox{}\verb@ general controller driver.@\\
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@ Mark Koennecke, January 1998@\\
|
||||
\mbox{}\verb@--------------------------------------------------------------------------*/@\\
|
||||
\mbox{}\verb@#ifndef CODRIV@\\
|
||||
\mbox{}\verb@#define CODRIV@\\
|
||||
\mbox{}\verb@#define CHFAIL -1@\\
|
||||
\mbox{}\verb@#define CHREDO -2@\\
|
||||
\mbox{}\verb@#define CHOK -3@\\
|
||||
\mbox{}\verb@@$\langle$codri {\footnotesize ?}$\rangle$\verb@@\\
|
||||
\mbox{}\verb@#endif@\\
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@@$\diamond$
|
||||
\end{list}
|
||||
\vspace{-2ex}
|
||||
\end{minipage}\\[4ex]
|
||||
\end{flushleft}
|
||||
\begin{flushleft} \small
|
||||
\begin{minipage}{\linewidth} \label{scrap8}
|
||||
\verb@"choco.h"@ {\footnotesize ? }$\equiv$
|
||||
\vspace{-1ex}
|
||||
\begin{list}{}{} \item
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@/*-----------------------------------------------------------------------@\\
|
||||
\mbox{}\verb@ C h o p p e r C o n t r o l l e r@\\
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@ This is both the header file for a general controller and a SICS@\\
|
||||
\mbox{}\verb@ chopper controller.@\\
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@ Mark Koennecke, January 1998@\\
|
||||
\mbox{}\verb@--------------------------------------------------------------------------*/@\\
|
||||
\mbox{}\verb@#ifndef CHOCOSICS@\\
|
||||
\mbox{}\verb@#define CHOCOSICS@\\
|
||||
\mbox{}\verb@#include "codri.h"@\\
|
||||
\mbox{}\verb@@$\langle$chocoint {\footnotesize ?}$\rangle$\verb@@\\
|
||||
\mbox{}\verb@#ifdef CHOCOINTERNAL@\\
|
||||
\mbox{}\verb@@$\langle$chocodata {\footnotesize ?}$\rangle$\verb@@\\
|
||||
\mbox{}\verb@#endif@\\
|
||||
\mbox{}\verb@#endif @\\
|
||||
\mbox{}\verb@@$\diamond$
|
||||
\end{list}
|
||||
\vspace{-2ex}
|
||||
\end{minipage}\\[4ex]
|
||||
\end{flushleft}
|
||||
\begin{flushleft} \small
|
||||
\begin{minipage}{\linewidth} \label{scrap9}
|
||||
\verb@"chadapter.h"@ {\footnotesize ? }$\equiv$
|
||||
\vspace{-1ex}
|
||||
\begin{list}{}{} \item
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@/*------------------------------------------------------------------------@\\
|
||||
\mbox{}\verb@ C H a d a p t e r@\\
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@ This is the header file for a drive adapter for collaboration with a@\\
|
||||
\mbox{}\verb@ general device controller as implemented in choco.*@\\
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@ Mark Koennecke, January 1998@\\
|
||||
\mbox{}\verb@--------------------------------------------------------------------------*/@\\
|
||||
\mbox{}\verb@#ifndef SICSCHADA@\\
|
||||
\mbox{}\verb@#define SICSCHADA@\\
|
||||
\mbox{}\verb@#include "codri.h"@\\
|
||||
\mbox{}\verb@@$\langle$adapter {\footnotesize ?}$\rangle$\verb@@\\
|
||||
\mbox{}\verb@#ifdef CHADAINTERNAL@\\
|
||||
\mbox{}\verb@@$\langle$adadata {\footnotesize ?}$\rangle$\verb@@\\
|
||||
\mbox{}\verb@@$\langle$evada {\footnotesize ?}$\rangle$\verb@@\\
|
||||
\mbox{}\verb@#endif@\\
|
||||
\mbox{}\verb@#endif@\\
|
||||
\mbox{}\verb@@$\diamond$
|
||||
\end{list}
|
||||
\vspace{-2ex}
|
||||
\end{minipage}\\[4ex]
|
||||
\end{flushleft}
|
||||
\subsubsection{To Do}
|
||||
This scheme seems to be quite promising for handling many SICS
|
||||
objects. The following enhancements could be considered. Allow to set
|
||||
certain primitive parameters without a drivable interface. And add an
|
||||
adapter for an environment variable in the controller.
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
108
doc/programmer/costa.tex
Normal file
108
doc/programmer/costa.tex
Normal file
@@ -0,0 +1,108 @@
|
||||
\subsection{The Command Stack}
|
||||
This is a helper class to the connection class.
|
||||
Each connection to a client has a command stack associated with it. The
|
||||
command stack is a stack of command strings as generated by the SICS
|
||||
clients. Commands are added to the top of the command queue by the network
|
||||
reader. Each time the task associated with a connection runs one command
|
||||
is popped from the command stack and executed. During execution the command
|
||||
stack must be locked in order to prevent commands being accepted by tasks
|
||||
busy waiting for some other process to finish.
|
||||
|
||||
Correspondingly, the interface to the command stack looks like this:
|
||||
|
||||
\begin{flushleft} \small
|
||||
\begin{minipage}{\linewidth} \label{scrap1}
|
||||
$\langle$costaint {\footnotesize ?}$\rangle\equiv$
|
||||
\vspace{-1ex}
|
||||
\begin{list}{}{} \item
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@ typedef struct __costa *pCosta;@\\
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@/*----------------------------- live & death ----------------------------*/@\\
|
||||
\mbox{}\verb@ pCosta CreateCommandStack(void);@\\
|
||||
\mbox{}\verb@ void DeleteCommandStack(pCosta self);@\\
|
||||
\mbox{}\verb@ int SetCommandStackMaxSize(pCosta self, int iNewSize);@\\
|
||||
\mbox{}\verb@/*----------------------------------------------------------------------*/@\\
|
||||
\mbox{}\verb@ int CostaTop(pCosta self, char *pCommand);@\\
|
||||
\mbox{}\verb@ int CostaBottom(pCosta self, char *pCommand);@\\
|
||||
\mbox{}\verb@ int CostaPop(pCosta self,char **pPtr);@\\
|
||||
\mbox{}\verb@/*----------------------------------------------------------------------*/@\\
|
||||
\mbox{}\verb@ void CostaLock(pCosta self);@\\
|
||||
\mbox{}\verb@ void CostaUnlock(pCosta self);@\\
|
||||
\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}
|
||||
Internally, two data structure need to be defined, the first for the
|
||||
list implementing the command stack, the second for the command stack
|
||||
itself.
|
||||
|
||||
\begin{flushleft} \small
|
||||
\begin{minipage}{\linewidth} \label{scrap2}
|
||||
$\langle$costadat {\footnotesize ?}$\rangle\equiv$
|
||||
\vspace{-1ex}
|
||||
\begin{list}{}{} \item
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@/*------------------------------------------------------------------------*/@\\
|
||||
\mbox{}\verb@ typedef struct __costa {@\\
|
||||
\mbox{}\verb@ int iLock;@\\
|
||||
\mbox{}\verb@ int iList;@\\
|
||||
\mbox{}\verb@ int iMaxSize;@\\
|
||||
\mbox{}\verb@ int iCount;@\\
|
||||
\mbox{}\verb@ } Costa;@\\
|
||||
\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}
|
||||
\begin{flushleft} \small
|
||||
\begin{minipage}{\linewidth} \label{scrap3}
|
||||
\verb@"costa.h"@ {\footnotesize ? }$\equiv$
|
||||
\vspace{-1ex}
|
||||
\begin{list}{}{} \item
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@/*-------------------------------------------------------------------------@\\
|
||||
\mbox{}\verb@ C O S T A@\\
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@ A command stack implementation for SICS. To be used by each connection.@\\
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@ Mark Koennecke, September 1997@\\
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@ copyright: see implementation file.@\\
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@----------------------------------------------------------------------------*/@\\
|
||||
\mbox{}\verb@#ifndef SICSCOSTA@\\
|
||||
\mbox{}\verb@#define SICSCOSTA@\\
|
||||
\mbox{}\verb@@$\langle$costaint {\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{scrap4}
|
||||
\verb@"costa.i"@ {\footnotesize ? }$\equiv$
|
||||
\vspace{-1ex}
|
||||
\begin{list}{}{} \item
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@/*---------------------------------------------------------------------------@\\
|
||||
\mbox{}\verb@ C O S T A@\\
|
||||
\mbox{}\verb@ Internal data structures for the command stack.@\\
|
||||
\mbox{}\verb@--------------------------------------------------------------------------*/@\\
|
||||
\mbox{}\verb@@$\langle$costadat {\footnotesize ?}$\rangle$\verb@@\\
|
||||
\mbox{}\verb@@$\diamond$
|
||||
\end{list}
|
||||
\vspace{-2ex}
|
||||
\end{minipage}\\[4ex]
|
||||
\end{flushleft}
|
||||
180
doc/programmer/counter.tex
Normal file
180
doc/programmer/counter.tex
Normal file
@@ -0,0 +1,180 @@
|
||||
\subsection{The Counter}
|
||||
This is the SICS object responsible for handling single counters and
|
||||
monitors. As usual for SICS hardware objects the
|
||||
counter is subdivided in a driver and a logical object. The driver will be
|
||||
discussed first. The same concept with overlaying structures is used
|
||||
for counters as for motors in order to allow for different drivers.
|
||||
|
||||
\subsubsection{The Counter Driver}
|
||||
Counter drivers are polymorphic. This means that different drivers look the
|
||||
same to the logical counter objects. This is achieved by having pointers to
|
||||
functions in the driver. These pointers must be initialised by an actual driver
|
||||
with functions which implement the required behaviour.
|
||||
The counter driver is a large data structure defined below:
|
||||
\begin{verbatim}
|
||||
typedef struct __COUNTER {
|
||||
/* variables */
|
||||
char *name;
|
||||
char *type;
|
||||
CounterMode eMode;
|
||||
float fPreset;
|
||||
int iNoOfMonitors;
|
||||
long lCounts[MAXCOUNT];
|
||||
int iPause;
|
||||
/* 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);
|
||||
void *pData; /* counter specific data goes here, ONLY for
|
||||
internal driver use!
|
||||
*/
|
||||
} CounterDriver, *pCounterDriver;
|
||||
\end{verbatim}
|
||||
All functions take a pointer to a counter structure as first parameter. If
|
||||
not described otherwise all functions return 0 on failure and 1 on success.
|
||||
The fields have the following meanings:
|
||||
\begin{description}
|
||||
\item[name] The counter name in the system.
|
||||
\item[type] A string describing the counter type.
|
||||
\item[eMode] The counting mode of the counter. Can be eTimer for counting
|
||||
till a preset time has passed or ePreset for counting until one of the
|
||||
monitors has reached a certain count rate.
|
||||
\item[fPreset] Depending on the count mode either the time to count or the
|
||||
monitor rate to wait for for.
|
||||
\item[iNoOfMonitors] The number of monitors handled by this counter.
|
||||
\item[lCounts] An array which stores the counts in the array position 0, and
|
||||
the monitor counts in the other fields of the array.
|
||||
\item[iPause] A logical which is set when the counter is paused.
|
||||
\item[GetStatus] GetStatus is the first of the functions a driver has to
|
||||
define. GetStatus reads the counter status. Possible return values are:
|
||||
\begin{description}
|
||||
\item[HWIdle, OKOK] The counter is finished or idle.
|
||||
\item[HWFault] A fault has been found at the counter instead of an
|
||||
reasonable answer.
|
||||
\item[HWNoBeam] There is currently no incident beam. This is usually
|
||||
detected through a monitor which does not increase over time.
|
||||
\item[HWPause] Counting has been paused.
|
||||
\item[HWBusy] The counter is busy counting.
|
||||
\end{description}
|
||||
The parameter fControl is set to the current value of the counting control
|
||||
variable. This can either be the counting time already passed or the count
|
||||
rate of the control monitor in ePreset mode.
|
||||
\item[Start] Starts counting with the current mode and preset parameters.
|
||||
\item[Pause] pauses a counting operation.
|
||||
\item[Continue] continues a paused counting operation.
|
||||
\item[Halt] cancels a counting operation. This a emergency stop used when
|
||||
interrupting an operation.
|
||||
\item[ReadValues] reads the counter and the monitors in the lCounts array.
|
||||
This gets automatically called through the TransferData routine of the
|
||||
countable interface after a counting operations finishes. The point is that
|
||||
data is transfered from the counter once and further requests operate on the
|
||||
contents of the local array instead of bothering the hardware again.
|
||||
\item[GetError] This gets called when an error has been detected during one
|
||||
of the previous operations. The function has to return more information
|
||||
about the error: iCode an driver dependent integer error code and maximum
|
||||
iErrLen characters of problem description in error.
|
||||
\item[TryAndFixIt] takes the integer error code returned in iCode from
|
||||
GetError and tries to solve the problem with the hardware. This function can
|
||||
either return COREDO which means the problem has been fixed and the
|
||||
operation needs to redone or COTERM which means that it is not possible to
|
||||
resolve the problem in software.
|
||||
\item[pData] A pointer to a driver dependent data structure. Whereas the
|
||||
fields above are required and expected by the counter module for a driver,
|
||||
this is an area private to the actual driver.
|
||||
\end{description}
|
||||
|
||||
As most of the action of the counter driver is done in the functions given
|
||||
in its data structure only few functions are available in order to interact
|
||||
with it:
|
||||
\begin{description}
|
||||
\item[pCounterDriver CreateCounterDriver(char *name, char *type)] creates a
|
||||
general default counter driver structure.
|
||||
\item[void DeleteCounterDriver(pCounterDriver self)] deletes a counter
|
||||
driver.
|
||||
\item[pCounterDriver NewEL737Counter(char *name, char *host, int iPort,
|
||||
int iChannel)] creates a PSI--EL737 counter
|
||||
driver. The counter box is meant to be reachable at the terminal server
|
||||
host, listening at iPort and connected to channel iChannel at the macintosh.
|
||||
\item[void KillEL737Counter(pCounterDriver self)] deletes an EL737 counter
|
||||
driver.
|
||||
\item[pCounterDriver NewSIMCounter(char *name)] creates a simulated counter
|
||||
driver. Needed for software testing and instrument simulation.
|
||||
\item[void KillSIMCounter(pCounterDriver self)] deletes a simulated counter
|
||||
driver.
|
||||
\end{description}
|
||||
|
||||
\subsubsection{The Logical Counter Object}
|
||||
This is the object which represents the counter to the system. For all
|
||||
actual hardware action the driver is called. The counter objects data
|
||||
structure:
|
||||
\begin{verbatim}
|
||||
typedef struct {
|
||||
pObjectDescriptor pDes;
|
||||
char *name;
|
||||
int isUpToDate;
|
||||
int iExponent;
|
||||
pICountable pCountInt;
|
||||
pCounterDriver pDriv;
|
||||
pICallBack pCall;
|
||||
unsigned long tStart;
|
||||
} Counter, *pCounter;
|
||||
\end{verbatim}
|
||||
The fields:\begin{description}
|
||||
\item[pDes] The required object descriptor for any SICS object.
|
||||
\item[name] The counters name in the system.
|
||||
\item[isUpToDate] a logical which is true when counting is finished and the
|
||||
data in the drivers lCount array represent the correct values.
|
||||
\item[iExponent] The exponent to apply on preset values in monitor mode. At
|
||||
SINQ monitor count rates in millions are usual. The exponent saves typing
|
||||
all those 0's. Each monitor preset value given is multiplied by this value.
|
||||
\item[pCountInt] A pointer to the countable interface.
|
||||
\item[pDriv] A pointer to a counter driver for this counter.
|
||||
\item[pCall] A pointer to the callback interface implemented by this
|
||||
counter.
|
||||
\item[tStart] The start time of the last counting operation.
|
||||
\end{description}
|
||||
|
||||
Unlike the counter driver, there exist many functions for interaction with
|
||||
the counter. Mosts functions take a pointer to a counter structure as first
|
||||
parameter. In order to communicate error messages, functions which interact
|
||||
with hardware take a pointer to a connection object as parameter.
|
||||
\begin{description}
|
||||
\item[pCounter CreateCounter(char *name, pCounterDriver pDriv)] Creates a
|
||||
new counter object with name name and counter driver pDriv.
|
||||
\item[void DeleteCounter(void *self)] deletes a counter object.
|
||||
\item[int MakeCounter(SConnection *pCon, SicsInterp *pSics, void *pData,\\
|
||||
int argc, char *argv[])] The counter object factory
|
||||
function. The function to be hacked (plus DeleteCounter) when a new driver
|
||||
needs to be introduced into the system.
|
||||
\item[int SetCounterMode(pCounter self, CounterMode eNew)] sets a new
|
||||
counter mode.
|
||||
\item[CounterMode GetCounterMode(pCounter self)] requests the current
|
||||
counter mode.
|
||||
\item[int SetCounterPreset(pCounter self, float fVal)] sets a new preset
|
||||
time or monitor.
|
||||
\item[float GetCounterPreset(pCounter self)] returns the current preset time
|
||||
or monitor.
|
||||
\item[long GetCounts(pCounter self, SConnection *pCon)] returns the detector
|
||||
counts.
|
||||
\item[long GetMonitor(pCounter self, int iNum, SConnection *pCon)] returns
|
||||
the monitor counts in monitor iNum. This function returns -1 when the
|
||||
requetsed monitor does not exist.
|
||||
\item[ GetNMonitor(pCounter self)] returns the number of monitors
|
||||
available.
|
||||
\item[int DoCount(pCounter self,float fPreset, SConnection *pCon, SicsInterp
|
||||
*pSics)] does a count operation with fPreset as preset value.
|
||||
\item[int CountAction(SConnection *pCon, SicsInterp *pSics, void *pData,\\
|
||||
int argc, char *argv[])] The counter objects wrapper
|
||||
function. This function defines the user interface to the counter object.
|
||||
\end{description}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
16
doc/programmer/cron.tex
Normal file
16
doc/programmer/cron.tex
Normal file
@@ -0,0 +1,16 @@
|
||||
\subsection{cron}
|
||||
This module allows to install commands into SICS which will be repeated
|
||||
periodically. The syntax is: sicscron intervall command. intervall is
|
||||
the time intervall and command is the command to execute. A problem
|
||||
is I/O becasue the original connection which installed the cron job
|
||||
may be lost. Therefore cron commands are executed within the context
|
||||
of special connection which does not do socket output. All I/O will be
|
||||
logged into the command log though for control. As
|
||||
this is a single system facility all data structure will be defined
|
||||
in the implementation file. The public interface to this is just the
|
||||
installation routine. This stuff is implemented in the files
|
||||
sicscron.h and sicscron.c.
|
||||
|
||||
The installation routine installs another task into the SICS system
|
||||
which will invoke the command to be executed at the predefined
|
||||
intervalls.
|
||||
92
doc/programmer/danu.tex
Normal file
92
doc/programmer/danu.tex
Normal file
@@ -0,0 +1,92 @@
|
||||
\subsection{Data Number}
|
||||
In some points of its life SICS has to write data files. The file names
|
||||
usually consist of a header, a serial number and an indicator for the
|
||||
year. The serial number must be unique and steadliy increasing. In order to
|
||||
achieve this, the serial number are written into a file after any change.
|
||||
Incrementing the serial number thus involves the following steps:
|
||||
\begin{itemize}
|
||||
\item Open file and read current number.
|
||||
\item Increment number
|
||||
\item Write File and close
|
||||
\end{itemize}
|
||||
This little task is implemented in this module.
|
||||
|
||||
The interface to this looks like:
|
||||
\begin{flushleft} \small
|
||||
\begin{minipage}{\linewidth} \label{scrap1}
|
||||
$\langle$dni {\footnotesize ?}$\rangle\equiv$
|
||||
\vspace{-1ex}
|
||||
\begin{list}{}{} \item
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@ typedef struct __DataNumber *pDataNumber;@\\
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@ pDataNumber CreateDataNumber(char *pFilename);@\\
|
||||
\mbox{}\verb@ void DeleteDataNumber(void *pData);@\\
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@ int IncrementDataNumber(pDataNumber self, int *iYear);@\\
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@ int DecrementDataNumber(pDataNumber self);@\\
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@ int DNWrapper(SConnection *pCon, SicsInterp *pSics, void *pData,@\\
|
||||
\mbox{}\verb@ int argc, char *argv[]);@\\
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@ int DEWrapper(SConnection *pCon, SicsInterp *pSics, void *pData,@\\
|
||||
\mbox{}\verb@ int argc, char *argv[]);@\\
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@ int DNFactory(SConnection *pCon, SicsInterp *pSics, void *pData,@\\
|
||||
\mbox{}\verb@ int argc, char *argv[]);@\\
|
||||
\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}
|
||||
\begin{description}
|
||||
\item [CreateDataNumber] creates a data number data structure. It checks if
|
||||
the file requested as parameter exists and asserts if not. Returns a pointer
|
||||
on success, NULL else.
|
||||
\item [DeleteDataNumber] deletes a data number structure form memory.
|
||||
\item [IncrementDataNumber] is the main working function of this module.
|
||||
It performs the steps listed above. It returns a new id for the data number
|
||||
in case of success, a negative value otherwise. iYear is filled with a value
|
||||
for the year.
|
||||
\item[DecrementDataNumber] decrements the data number and is used for
|
||||
implementing the killdata function. Whis is the invalidation of a
|
||||
data file by overwriting it.
|
||||
\item[DNWrapper] is the wrapper function which makes DataNumber accessible
|
||||
from within SICS.
|
||||
\item[DEWrapper] is the wrapper for the killdata functionality.
|
||||
\item [DNFactory] is the SICS factory function which creates a Data Number
|
||||
object from the initialisation file. Only parameter is the filename.
|
||||
\end{description}
|
||||
|
||||
\begin{flushleft} \small
|
||||
\begin{minipage}{\linewidth} \label{scrap2}
|
||||
\verb@"danu.h"@ {\footnotesize ? }$\equiv$
|
||||
\vspace{-1ex}
|
||||
\begin{list}{}{} \item
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@/*-----------------------------------------------------------------------@\\
|
||||
\mbox{}\verb@ D A T A N U M B E R@\\
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@ A module to provide a unique data number for data file writing.@\\
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@ Mark Koennecke, Juli 1997@\\
|
||||
\mbox{}\verb@ @\\
|
||||
\mbox{}\verb@ copyright: see implementation file.@\\
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@---------------------------------------------------------------------------*/@\\
|
||||
\mbox{}\verb@#ifndef SICSDATANUMBER@\\
|
||||
\mbox{}\verb@#define SICSDATANUMBER@\\
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@@$\langle$dni {\footnotesize ?}$\rangle$\verb@@\\
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@#endif@\\
|
||||
\mbox{}\verb@@$\diamond$
|
||||
\end{list}
|
||||
\vspace{-2ex}
|
||||
\end{minipage}\\[4ex]
|
||||
\end{flushleft}
|
||||
322
doc/programmer/devexec.tex
Normal file
322
doc/programmer/devexec.tex
Normal file
@@ -0,0 +1,322 @@
|
||||
\subsection{The Device Executor}
|
||||
The Device Executor (devexec) is a core component of the system. It has to
|
||||
fulfill three main tasks:
|
||||
\begin{itemize}
|
||||
\item Permit non--blocking hardware operations.
|
||||
\item Ensure regular monitoring of running devices.
|
||||
\item Ensure that only one client controls the hardware.
|
||||
\end{itemize}
|
||||
The devexec in its current form monitors driving and counting
|
||||
operations only. The emonitor implements another monitor for
|
||||
environment controllers.
|
||||
|
||||
Please note, that this module is quite crucial for the functioning of
|
||||
SICS. Any changes here may have side effects throughout the whole
|
||||
system. Be VERY careful with any changes. The current version does its job!
|
||||
|
||||
Some users want to continue typing commands while some hardware device is
|
||||
still running. This is sensible, because some hardware devices require a
|
||||
lot of time before they run to completion. Some people also require to count
|
||||
while driving motors for quick overview measurements. This requirement was
|
||||
the main reason for the invention of the devexec.
|
||||
|
||||
Of course, when devices are in operation it is needed to check on them
|
||||
regularly in order to catch and report error conditions and in order to
|
||||
find out when devices are finished with their job.
|
||||
|
||||
In a client server system many clients might issue commands to the hardware.
|
||||
This could quickly lead into an undesirable form of chaos (There are
|
||||
desirable forms of chaos, but not here!). In order to prevent this a means
|
||||
is needed to ensure that at any given time only one client controls the
|
||||
hardware. This function is also performed by the devexec.
|
||||
|
||||
The device executor also has to take care of special error conditions.
|
||||
|
||||
\subsubsection{Starting Devices}
|
||||
These are the most important SICS operations. Environment controllers are
|
||||
monitored by the environment monitor. Then here is a convention: {\bf Any
|
||||
SICS object which
|
||||
initiates driving or counting operations has to do so by registering this
|
||||
operation with the devexec}. For this purpose the following interface
|
||||
functions are provided.
|
||||
|
||||
\begin{flushleft} \small
|
||||
\begin{minipage}{\linewidth} \label{scrap1}
|
||||
$\langle$devreg {\footnotesize ?}$\rangle\equiv$
|
||||
\vspace{-1ex}
|
||||
\begin{list}{}{} \item
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@ int StartDevice(pExeList self, char *name, pObjectDescriptor pDes,@\\
|
||||
\mbox{}\verb@ void *pData, SConnection *pCon, float fNew);@\\
|
||||
\mbox{}\verb@ int StartMotor(pExeList self, SicsInterp *pSics, SConnection *pCon,@\\
|
||||
\mbox{}\verb@ char *name, float fNew);@\\
|
||||
\mbox{}\verb@ int StartCounter(pExeList self, SicsInterp *pSics, SConnection *pCon,@\\
|
||||
\mbox{}\verb@ char *name); @\\
|
||||
\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 main interface function is {\bf StartDevice}. The parameters are:
|
||||
\begin{itemize}
|
||||
\item {\bf self}. A pointer to the device executor in which SICS operates.
|
||||
\item {\bf name}. The name of the object which operates.
|
||||
\item {\bf pDes}. A pointer to the ObjectDescriptor of the object to drive or count.
|
||||
\item {\bf pData}. A pointer to the data structure coming with the object.
|
||||
\item {\bf pCon}. A pointer to the client connection on whose request the
|
||||
operation was initiated.
|
||||
\item {\bf fNew}. A floating point value which sets the target value for
|
||||
drivable devices.
|
||||
\end{itemize}
|
||||
{\bf StartMotor, StartCounter} are just convenience wrappers around
|
||||
StartDevice which retrieve objects from the SICS interpreter and calls
|
||||
StartDevice thereafter.
|
||||
|
||||
Once invoked StartDevice takes care of the following operations:
|
||||
\begin{itemize}
|
||||
\item It first checks on the connection object. If nobody else is running
|
||||
hardware it enters the connection object specifed as owner of the devexec in
|
||||
its data structure. If an owner was already specified by a prior drive or
|
||||
count request StartDevice checks if the connection requesting the new
|
||||
operation is the same. If this is not the case, an error message about this
|
||||
situation will be issued. If it is the case, i. e. the client requesting the
|
||||
new operation is the same as the one who has reserved the devexec, the
|
||||
operation is performed. This scheme reserves the devexec to one client.
|
||||
\item If the authorisation is OK, StartDevice then proceeds to start the
|
||||
drive or counting operation.
|
||||
\item StartDevice then enters all information regarding
|
||||
the running device into an list for future monitoring.
|
||||
\item If it not already running a DevExecTask is registered with the
|
||||
task module in order to ensure the monitoring of the devices running.
|
||||
\end{itemize}
|
||||
|
||||
\subsubsection{Monitoring devices}
|
||||
|
||||
From within the SICS main loops this special function is called:
|
||||
\begin{flushleft} \small
|
||||
\begin{minipage}{\linewidth} \label{scrap2}
|
||||
$\langle$devcheck {\footnotesize ?}$\rangle\equiv$
|
||||
\vspace{-1ex}
|
||||
\begin{list}{}{} \item
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@ int CheckExeList(pExeList self);@\\
|
||||
\mbox{}\verb@ /*@\\
|
||||
\mbox{}\verb@ checks the entries for success and deletes entries which have finished@\\
|
||||
\mbox{}\verb@ operation. If there are none left, the pOwner will be set to NULL.@\\
|
||||
\mbox{}\verb@ */ @\\
|
||||
\mbox{}\verb@ int Wait4Success(pExeList self);@\\
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@ long GetDevexecID(pExeList self);@\\
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@ int DevExecTask(void *pEL);@\\
|
||||
\mbox{}\verb@ void DevExecSignal(void *pEL, int iSignal, void *pSigData);@\\
|
||||
\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}
|
||||
CheckExeList then scan through its list of executing objects and request a
|
||||
status from each of them. The next action depend on the status returned from
|
||||
the device and any pending interrupts:
|
||||
\begin{itemize}
|
||||
\item If the device is still busy and no interrupts are pending, nothing
|
||||
happens.
|
||||
\item If there is a hardware error, this will be reported and apropriate
|
||||
actions are intitiated depending on the type of problem and possible
|
||||
interrupts being sets.
|
||||
\item If a device is done, either naturally or due to an error or interrupt,
|
||||
it is removed from devexec's list.
|
||||
\item If the list is empty, the owner field of the devexec's datastructure
|
||||
is reset to NULL. Then a new client is free to grab control over the
|
||||
hardware.
|
||||
\end{itemize}
|
||||
|
||||
{\bf DevExecTask} is the task function for the device executor. Calls
|
||||
CheckExeList in the end. If all devices registered with the devexec
|
||||
are finished running this function returns 0 and thus stops.
|
||||
|
||||
{\bf DevExecSignal} is the signal function for the device executor task.
|
||||
|
||||
{\bf Wait4Success} This function waits for the DevExecTask to
|
||||
end. This is the case when the current devices running are finished.
|
||||
There are occasions in the program where it is needed to wait for
|
||||
an operation to complete before other tasks can be tackled. Wait4Success is
|
||||
the function to call in such cases. Wait4Success returns DEVDONE for a
|
||||
properly finished operation, DEVERROR for an operation which finished
|
||||
with an error code and DEVINT for an aoperation which was interrupted
|
||||
by the user.
|
||||
|
||||
\subsubsection{Influencing Execution}
|
||||
In certain cases it is necessary to interact with running devices directly.
|
||||
This is done via the following interface.
|
||||
|
||||
\begin{flushleft} \small
|
||||
\begin{minipage}{\linewidth} \label{scrap3}
|
||||
$\langle$devstop {\footnotesize ?}$\rangle\equiv$
|
||||
\vspace{-1ex}
|
||||
\begin{list}{}{} \item
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@ int StopExe(pExeList self, char *name);@\\
|
||||
\mbox{}\verb@ int StopExeWait(pExeList self);@\\
|
||||
\mbox{}\verb@ /*@\\
|
||||
\mbox{}\verb@ will stop the entry name and its subentries from executing.@\\
|
||||
\mbox{}\verb@ If ALL is specified as name, everything will be stopped and@\\
|
||||
\mbox{}\verb@ the Executor cleared.@\\
|
||||
\mbox{}\verb@ StopExeWait will stop all running things and wait for the stop@\\
|
||||
\mbox{}\verb@ to complete.@\\
|
||||
\mbox{}\verb@ */@\\
|
||||
\mbox{}\verb@/*------------------------------------------------------------------------*/@\\
|
||||
\mbox{}\verb@ void ClearExecutor(pExeList self);@\\
|
||||
\mbox{}\verb@ /*@\\
|
||||
\mbox{}\verb@ clears the executor without sending commands to the devices.@\\
|
||||
\mbox{}\verb@ */@\\
|
||||
\mbox{}\verb@/*-----------------------------------------------------------------------*/@\\
|
||||
\mbox{}\verb@ int IsCounting(pExeList self);@\\
|
||||
\mbox{}\verb@ int PauseExecution(pExeList self);@\\
|
||||
\mbox{}\verb@ int ContinueExecution(pExeList self);@\\
|
||||
\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}
|
||||
{\bf StopExe} tackles the interrupting of pending operations. This may
|
||||
happen on a users request. StopExe then invokes a halt on that device.
|
||||
As parameters, the name of a device to stop can be specified. If ALL is
|
||||
given as name to StopExe all executing devices are stopped. Please note, that
|
||||
this stop does not automatically finish the operation. Motors need some time
|
||||
to stop, too. This function is usally called as consequence of an
|
||||
interrupt.
|
||||
|
||||
|
||||
{\bf ClearExecutor} clears the executor without invoking commands on the
|
||||
devices. Is probably only used internally to clean out the executor.
|
||||
|
||||
I some cases, for example if a environment controller gets out of range, an
|
||||
error handling strategy may want to pause counting until the problem has
|
||||
been rectified and continue afterwards. {\bf PauseExecution, ContinueExecution}
|
||||
take care of invoking the apropriate commands on all registered counting
|
||||
devices.
|
||||
|
||||
|
||||
\subsubsection{The Rest}
|
||||
The rest of the interface includes initialisation and deletion routines
|
||||
and some access routines. With the devexec being such an important system
|
||||
component a function {\bf GetExecutor} is provided which retrieves a pointer
|
||||
to the global SICS device executor.
|
||||
|
||||
\begin{flushleft} \small
|
||||
\begin{minipage}{\linewidth} \label{scrap4}
|
||||
\verb@"devexec.h"@ {\footnotesize ? }$\equiv$
|
||||
\vspace{-1ex}
|
||||
\begin{list}{}{} \item
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@/*----------------------------------------------------------------------------@\\
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@ D E V I C E E X E C U T O R@\\
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@ Joachim Kohlbrecher wants to give several commands to the server@\\
|
||||
\mbox{}\verb@ and than wait for them to happen before proceeding. Actually a useful@\\
|
||||
\mbox{}\verb@ thing. A command will map to one or several positioning commands for a@\\
|
||||
\mbox{}\verb@ device. This scheme is also useful for implementing objects which@\\
|
||||
\mbox{}\verb@ drive several motors simulataneously, such as Monochromators. etc.@\\
|
||||
\mbox{}\verb@ However, the whole thing is rather complicated.@\\
|
||||
\mbox{}\verb@ @\\
|
||||
\mbox{}\verb@ It is forbidden, that several clients drive the instrument. In order@\\
|
||||
\mbox{}\verb@ to ensure this the Executor remembers the connection which emitted the@\\
|
||||
\mbox{}\verb@ first command. Subsequent AddExeEntries from different clients will@\\
|
||||
\mbox{}\verb@ be rejected. The owner will be reset when the execution is found finished@\\
|
||||
\mbox{}\verb@ in calls to CheckExe, Wait4Success or StopExe.@\\
|
||||
\mbox{}\verb@ @\\
|
||||
\mbox{}\verb@ @\\
|
||||
\mbox{}\verb@ Mark Koennecke, December 1996@\\
|
||||
\mbox{}\verb@ @\\
|
||||
\mbox{}\verb@ copyright: see implementation file@\\
|
||||
\mbox{}\verb@---------------------------------------------------------------------------*/@\\
|
||||
\mbox{}\verb@#ifndef SICSDEVEXEC@\\
|
||||
\mbox{}\verb@#define SICSDEVEXEC@\\
|
||||
\mbox{}\verb@#include "obdes.h"@\\
|
||||
\mbox{}\verb@#include "task.h"@\\
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@ typedef struct __EXELIST *pExeList;@\\
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@/* Returncodes */@\\
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@#define DEVDONE 1@\\
|
||||
\mbox{}\verb@#define DEVINT 0@\\
|
||||
\mbox{}\verb@#define DEVERROR 2@\\
|
||||
\mbox{}\verb@#define DEVBUSY 3@\\
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@/*------------------------------------------------------------------------@\\
|
||||
\mbox{}\verb@ B I R T H & D E A T H@\\
|
||||
\mbox{}\verb@*/@\\
|
||||
\mbox{}\verb@ pExeList CreateExeList(pTaskMan pTask);@\\
|
||||
\mbox{}\verb@ void DeleteExeList(void *self);@\\
|
||||
\mbox{}\verb@ @\\
|
||||
\mbox{}\verb@/* ================= Functions to talk to the above ====================== */@\\
|
||||
\mbox{}\verb@@$\langle$devreg {\footnotesize ?}$\rangle$\verb@@\\
|
||||
\mbox{}\verb@/*------------------------------------------------------------------------*/@\\
|
||||
\mbox{}\verb@@$\langle$devcheck {\footnotesize ?}$\rangle$\verb@@\\
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@ /*@\\
|
||||
\mbox{}\verb@ Waits for execution to finish. returns 1 on Success, 0 if problems@\\
|
||||
\mbox{}\verb@ ocurred. Than the Interrupt code shall be checked and acted upon@\\
|
||||
\mbox{}\verb@ accordingly.@\\
|
||||
\mbox{}\verb@ */@\\
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@/*-------------------------------------------------------------------------*/@\\
|
||||
\mbox{}\verb@ SConnection *GetExeOwner(pExeList self);@\\
|
||||
\mbox{}\verb@/*-------------------------------------------------------------------------*/@\\
|
||||
\mbox{}\verb@ int isInRunMode(pExeList self);@\\
|
||||
\mbox{}\verb@/*--------------------------------------------------------------------------*/@\\
|
||||
\mbox{}\verb@ int ListPending(pExeList self, SConnection *pCon);@\\
|
||||
\mbox{}\verb@ /*@\\
|
||||
\mbox{}\verb@ lists the Operations still pending on pCon. @\\
|
||||
\mbox{}\verb@ */@\\
|
||||
\mbox{}\verb@/*-------------------------------------------------------------------------*/@\\
|
||||
\mbox{}\verb@@$\langle$devstop {\footnotesize ?}$\rangle$\verb@@\\
|
||||
\mbox{}\verb@/*-------------------------- Commands ------------------------------------*/@\\
|
||||
\mbox{}\verb@ int StopCommand(SConnection *pCon, SicsInterp *pSics, void *pData,@\\
|
||||
\mbox{}\verb@ int argc, char *argv[]);@\\
|
||||
\mbox{}\verb@ /*@\\
|
||||
\mbox{}\verb@ implements the stop command@\\
|
||||
\mbox{}\verb@ */@\\
|
||||
\mbox{}\verb@ @\\
|
||||
\mbox{}\verb@ int ListExe(SConnection *pCon, SicsInterp *pSics, void *pData,@\\
|
||||
\mbox{}\verb@ int argc, char *argv[]);@\\
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@ /*@\\
|
||||
\mbox{}\verb@ lists all currently executing objects@\\
|
||||
\mbox{}\verb@ */@\\
|
||||
\mbox{}\verb@ int Success(SConnection *pCon, SicsInterp *pSics, void *pData,@\\
|
||||
\mbox{}\verb@ int argc, char *argv[]);@\\
|
||||
\mbox{}\verb@ /*@\\
|
||||
\mbox{}\verb@ waits until completion of all pending operations. Used in@\\
|
||||
\mbox{}\verb@ connection with non blocking operation such as motors started@\\
|
||||
\mbox{}\verb@ with run.@\\
|
||||
\mbox{}\verb@ */@\\
|
||||
\mbox{}\verb@ @\\
|
||||
\mbox{}\verb@/* -------------------------- Executor management -------------------------*/@\\
|
||||
\mbox{}\verb@ @\\
|
||||
\mbox{}\verb@ pExeList GetExecutor(void);@\\
|
||||
\mbox{}\verb@ void SetExecutor(pExeList pExe);@\\
|
||||
\mbox{}\verb@ @\\
|
||||
\mbox{}\verb@#endif @\\
|
||||
\mbox{}\verb@@$\diamond$
|
||||
\end{list}
|
||||
\vspace{-2ex}
|
||||
\end{minipage}\\[4ex]
|
||||
\end{flushleft}
|
||||
52
doc/programmer/difrac.tex
Normal file
52
doc/programmer/difrac.tex
Normal file
@@ -0,0 +1,52 @@
|
||||
\subsection{The Difrac Subsystem}
|
||||
Difrac is a F77 package for controlling a four circle diffractometer
|
||||
developed by P. Gabe and White for PC's. This package became only
|
||||
available very late. This package has been included into SICS for four
|
||||
circle diffraction. All the code for the difrac package resides in the
|
||||
difrac subdirectory to sics. For more information about the difrac
|
||||
system see the documentation coming with difrac. In order to
|
||||
integrate difrac into SICS the following steps had to be taken:
|
||||
\begin{itemize}
|
||||
\item Define an interface from SICS to DIFRAC.
|
||||
\item Modify the DIFRAC hardware control to run the hardware through
|
||||
SICS.
|
||||
\item Adapt I/O
|
||||
\item Modify DIFRAC to be a subsystem instead of a program of its own.
|
||||
\item Adapt measurement procedures to the special needs of TRICS.
|
||||
\end{itemize}
|
||||
|
||||
\subsubsection{The Interface SICS to DIFRAC}
|
||||
This is implemented in difrac.c. It it is just a interface wrapper
|
||||
function which takes the command given and forwards it to the DIFRAC
|
||||
interpreter. A tricky bit about this ist, that this module has to keep
|
||||
track of which cconnection issued the command. This is done through a
|
||||
connection stack.
|
||||
|
||||
\subsubsection{DIFRAC HW control}
|
||||
DIFRAC controls the hardware through a couple of function originally
|
||||
defined in the file ralf.f. This file has been replaced by a file
|
||||
trics.f which in turn calls C-functions implemented in difrac.c which
|
||||
do the actual job.
|
||||
|
||||
\subsubsection{DIFRAC I/O}
|
||||
In contrast to many F77 prograsm DIFRAC has a very intelligent I/O
|
||||
system. All input is channelled through the function GETLIN in
|
||||
gwrite.f. This function has been modified to call a C-function which
|
||||
gets a line of input from SICS. This adpater is again in difrac.c. All
|
||||
output is printed first into a internal string buffer, COUT, and then
|
||||
printed using the function GWRITE. This function has been modified to
|
||||
call a C-function which writes the output to a SICS connection. The
|
||||
integration of DIFRAC into SICS was only possible because of the
|
||||
existence of this I/O system.
|
||||
|
||||
\subsubsection{Changes in DIFRAC}
|
||||
The DIFRAC main program was taken apart into a initialisation routine
|
||||
(difini.f) and a callable interpreter function (difint.f). Further
|
||||
changes were required because TRICS does not do continous scans in the
|
||||
way a X-ray four circle diffractometer does. DIFRAC's concept of a
|
||||
scan drives a motor slowly and collects data. This has been modified
|
||||
to do step scans for TRICS. Some commands which do not make sense
|
||||
within SICS have been disabled. Some little changes to measurement
|
||||
routines were necessary.
|
||||
|
||||
|
||||
48
doc/programmer/dmc.tex
Normal file
48
doc/programmer/dmc.tex
Normal file
@@ -0,0 +1,48 @@
|
||||
\subsection{DMC module}
|
||||
This module initialises all DMC specific commands. Currently there is only
|
||||
one: StoreData. This does not do much, it is just here as a container for
|
||||
things to come.
|
||||
|
||||
\begin{flushleft} \small
|
||||
\begin{minipage}{\linewidth} \label{scrap1}
|
||||
$\langle$Protos {\footnotesize ?}$\rangle\equiv$
|
||||
\vspace{-1ex}
|
||||
\begin{list}{}{} \item
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@ int InitDmc(SConnection *pCon, SicsInterp *pSics, void *pData, @\\
|
||||
\mbox{}\verb@ int argc, char *argv[]);@\\
|
||||
\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}
|
||||
\begin{flushleft} \small
|
||||
\begin{minipage}{\linewidth} \label{scrap2}
|
||||
\verb@"dmc.h"@ {\footnotesize ? }$\equiv$
|
||||
\vspace{-1ex}
|
||||
\begin{list}{}{} \item
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@/*-------------------------------------------------------------------------@\\
|
||||
\mbox{}\verb@ D M C @\\
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@ this modules purpose is solely to initialise the commands specific to@\\
|
||||
\mbox{}\verb@ the powder diffractometer DMC.@\\
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@ Mark Koenencke, March 1997@\\
|
||||
\mbox{}\verb@ @\\
|
||||
\mbox{}\verb@ copyright: see implementation file.@\\
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@--------------------------------------------------------------------------*/@\\
|
||||
\mbox{}\verb@#ifndef SICSDMC@\\
|
||||
\mbox{}\verb@#define SICSDMC@\\
|
||||
\mbox{}\verb@@$\langle$Protos {\footnotesize ?}$\rangle$\verb@@\\
|
||||
\mbox{}\verb@#endif@\\
|
||||
\mbox{}\verb@@$\diamond$
|
||||
\end{list}
|
||||
\vspace{-2ex}
|
||||
\end{minipage}\\[4ex]
|
||||
\end{flushleft}
|
||||
30254
doc/programmer/dmccom.eps
Normal file
30254
doc/programmer/dmccom.eps
Normal file
File diff suppressed because it is too large
Load Diff
BIN
doc/programmer/dmccom.gif
Normal file
BIN
doc/programmer/dmccom.gif
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 13 KiB |
22
doc/programmer/drive.tex
Normal file
22
doc/programmer/drive.tex
Normal file
@@ -0,0 +1,22 @@
|
||||
\subsection{The Drive and Run Command}
|
||||
This command implements driving of real motors or virtual motors (variables
|
||||
which control multiple motors). The drive command has no associated data
|
||||
structure going with it. There are just a few function:
|
||||
\begin{description}
|
||||
\item[int Drive(SConnection *pCon,SicsInterp *pSics, char *name, float
|
||||
fNew)] drives motor name to fNew and waits for the motor to finish. Possible
|
||||
errors will be written to the connection object pCon.
|
||||
\item[int Start2Run(SConnection *pCon, SicsInterp *pSics, char *name, float
|
||||
fNew)] starts the motor name to run to fNew. This
|
||||
function will NOT wait for the motor to get there. In spite of this,
|
||||
possible errors will be printed to the connection object pCon.
|
||||
\item[int DriveWrapper(SConnection *pCon, SicsInterp *pSics, void *pData,
|
||||
int argc, char *argv[])] the object wrapper
|
||||
function for the drive command.
|
||||
\item[int RunWrapper(SConnection *pCon, SicsInterp *pSics, void *pData,
|
||||
int argc, char *argv[])] the object wrapper
|
||||
function for the run command.
|
||||
\item[int MakeDrive(SConnection *pCon, SicsInterp *pSics, void *pData,
|
||||
int argc, char *argv[])]
|
||||
The factory command which installs the drive and run commands into SICS.
|
||||
\end{description}
|
||||
140
doc/programmer/dynar.tex
Normal file
140
doc/programmer/dynar.tex
Normal file
@@ -0,0 +1,140 @@
|
||||
\subsection{Dynamic Array}
|
||||
This section describes a dynamic array of arbitrary pointers. Dynamic means,
|
||||
that the array gets enlarged automatically when an index outside of the
|
||||
current bounds has been requested. Negative values are supported as well.
|
||||
|
||||
The interface to this module looks like this:
|
||||
|
||||
\begin{flushleft} \small
|
||||
\begin{minipage}{\linewidth} \label{scrap1}
|
||||
$\langle$dynarint {\footnotesize ?}$\rangle\equiv$
|
||||
\vspace{-1ex}
|
||||
\begin{list}{}{} \item
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@ typedef struct __SDynar *pDynar;@\\
|
||||
\mbox{}\verb@/*-------------------------------------------------------------------------*/@\\
|
||||
\mbox{}\verb@ pDynar CreateDynar(int iStart, int iEnd, int iGrain, @\\
|
||||
\mbox{}\verb@ void (*DataFree)(void *pData));@\\
|
||||
\mbox{}\verb@ void DeleteDynar(pDynar self);@\\
|
||||
\mbox{}\verb@/*------------------------------------------------------------------------*/@\\
|
||||
\mbox{}\verb@ int DynarPut(pDynar self, int iIndex, void *pData);@\\
|
||||
\mbox{}\verb@ int DynarPutCopy(pDynar self, int iIndex, void *pData, int iDataLen);@\\
|
||||
\mbox{}\verb@ int DynarReplace(pDynar self, int iIndex, void *pData, int iDatLen);@\\
|
||||
\mbox{}\verb@ @\\
|
||||
\mbox{}\verb@ int DynarGet(pDynar self, int iIndex, void **pData);@\\
|
||||
\mbox{}\verb@ int DynarGetCopy(pDynar self, int iIndex, void *pData, int iDataLen);@\\
|
||||
\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}
|
||||
If not stated otherwise, all functions return 1 on success and 0 on failure.
|
||||
|
||||
\begin{description}
|
||||
\item[CreateDynar] creates a new dynamic array. On success a pointer to a
|
||||
new dynamic array is returned, else NULL. The parameters are: iStart, the
|
||||
initial start index of the array, iEnd, the initial end index of the array,
|
||||
iGrain, the packet of new space to allocate when the array is enlarged
|
||||
dynamically, DataFree, a function which takes a pointer to one of the data
|
||||
items stored in the dynamic array and the free's all the memory associated
|
||||
with the data item. DataFree will be used automatically by Dynar for
|
||||
releasing memory when data items are replaced or the whole array is deleted.
|
||||
\item[DeleteDynar] removes the dynamic arary from memory. The pointer to
|
||||
self will point to rubbish afterwards and shall not be used.
|
||||
\item[DynarPut] puts the pointer pData at position iIndex in the dynamic
|
||||
array. pData needs to be allocated from dynamic memory, otherwise you'll
|
||||
experience core dumps. A data item which was previously at the position
|
||||
denoted by iIndex will be freed.
|
||||
\item[DynarPutCopy] does the same as DynarPut, but copies the data item.
|
||||
iDataLen bytes of new memory will be allocated and the data from pData be
|
||||
put into it. Then this will be entered into the dynamic array at position
|
||||
iIndex.
|
||||
\item[DynarReplace] replaces the data at iIndex by the data pointed to by
|
||||
pData by a memcpy. If there was no data defined previously, this call has
|
||||
the same effect as DynarPutCopy.
|
||||
\item[DynarGet] retrieves the pointer pData at position iIndex from the dynamic
|
||||
array.
|
||||
\item[DynarGetCopy] copies iDataLen bytes from the data at position iIndex
|
||||
into the buffer pData. pData must be large enough to hold iDataLen bytes.
|
||||
|
||||
\end{description}
|
||||
|
||||
Nowe, here is the definition of the internal datastructure for the
|
||||
dynamic array class.
|
||||
|
||||
\begin{flushleft} \small
|
||||
\begin{minipage}{\linewidth} \label{scrap2}
|
||||
$\langle$dynardat {\footnotesize ?}$\rangle\equiv$
|
||||
\vspace{-1ex}
|
||||
\begin{list}{}{} \item
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@ typedef struct __SDynar {@\\
|
||||
\mbox{}\verb@ int iStart;@\\
|
||||
\mbox{}\verb@ int iEnd;@\\
|
||||
\mbox{}\verb@ int iGrain;@\\
|
||||
\mbox{}\verb@ void **pArray;@\\
|
||||
\mbox{}\verb@ void (*DataFree)(void *pData);@\\
|
||||
\mbox{}\verb@ } Dynar;@\\
|
||||
\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}
|
||||
\begin{flushleft} \small
|
||||
\begin{minipage}{\linewidth} \label{scrap3}
|
||||
\verb@"sdynar.h"@ {\footnotesize ? }$\equiv$
|
||||
\vspace{-1ex}
|
||||
\begin{list}{}{} \item
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@/*---------------------------------------------------------------------------@\\
|
||||
\mbox{}\verb@ D Y N A M I C A R R A Y@\\
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@ This file describes the interface to a dynamic array module for pointers.@\\
|
||||
\mbox{}\verb@ This sort of array resizes dynamically.@\\
|
||||
\mbox{}\verb@ @\\
|
||||
\mbox{}\verb@ Mark Koennecke, September 1997@\\
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@ copyright: see copyright.h@\\
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@-----------------------------------------------------------------------------*/@\\
|
||||
\mbox{}\verb@#ifndef SICSDYNAR@\\
|
||||
\mbox{}\verb@#define SICSDYNAR@\\
|
||||
\mbox{}\verb@@$\langle$dynarint {\footnotesize ?}$\rangle$\verb@@\\
|
||||
\mbox{}\verb@#endif@\\
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@@$\diamond$
|
||||
\end{list}
|
||||
\vspace{-2ex}
|
||||
\end{minipage}\\[4ex]
|
||||
\end{flushleft}
|
||||
\begin{flushleft} \small
|
||||
\begin{minipage}{\linewidth} \label{scrap4}
|
||||
\verb@"sdynar.i"@ {\footnotesize ? }$\equiv$
|
||||
\vspace{-1ex}
|
||||
\begin{list}{}{} \item
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@/*----------------------------------------------------------------------------@\\
|
||||
\mbox{}\verb@ D Y N A M I C A R R A Y@\\
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@ This file defines the internal data structure used by the dynamic@\\
|
||||
\mbox{}\verb@ array module.@\\
|
||||
\mbox{}\verb@ @\\
|
||||
\mbox{}\verb@ More info: see sdynar.h@\\
|
||||
\mbox{}\verb@-----------------------------------------------------------------------------*/@\\
|
||||
\mbox{}\verb@@$\langle$dynardat {\footnotesize ?}$\rangle$\verb@@\\
|
||||
\mbox{}\verb@@$\diamond$
|
||||
\end{list}
|
||||
\vspace{-2ex}
|
||||
\end{minipage}\\[4ex]
|
||||
\end{flushleft}
|
||||
218
doc/programmer/emonitor.tex
Normal file
218
doc/programmer/emonitor.tex
Normal file
@@ -0,0 +1,218 @@
|
||||
\subsection{SICS Sample Environment Handling}
|
||||
In addition to driving motors and counting SICS has to take care of sample
|
||||
environment devices as well. These can be temperature controllers, current
|
||||
controllers etc. It can be assumed, that SICS has to take care of
|
||||
intelligent sample environment devices only, i. e. devices which do their
|
||||
own realtime processing. SICS, however, has to implement the logic to drive
|
||||
an environment controller to a new value. Furthermore SICS has to do the
|
||||
error handling when an environment controller fails. In order to do this the
|
||||
following software components will be needed:
|
||||
\begin{itemize}
|
||||
\item An environment monitor. This component will register any active
|
||||
environment control device. A test function will be called from the main
|
||||
loop which checks for controller out of range and initiates error handling.
|
||||
\item A new interface, the environment interface (see \ref{interface}).
|
||||
\item Controller objects. One for each environment controller. Again, the
|
||||
SICS distinction between logical objects and hardware drivers will be
|
||||
maintained.
|
||||
\end{itemize}
|
||||
|
||||
Controller objects will be able to share some code among them. Each
|
||||
environemnt controller will hold a target value, a permissable tolerance,
|
||||
a selctor variable which defines the type of error handling to perform and
|
||||
an interrupt code to issue when that form of error handling is choosen.
|
||||
Furthermore each environment controller needs to implement the drivable
|
||||
interface (for driving to new values) and the environment interface (for
|
||||
monitoring the controller). Controller object will also share the error
|
||||
handling during the monitor phase between them. The scheme is that each controller will have a
|
||||
variable which selects the error handling mechanism. Depending on this
|
||||
variable an error managment routine will be invoked. Current two schemes for
|
||||
handling errors are supported:
|
||||
\begin{itemize}
|
||||
\item Print a warning but do nothing else.
|
||||
\item Interrupt: an interrupt will be issued.
|
||||
\item Pause: the measurement will be paused.
|
||||
\item Try to drive to a safe value. This may be used to rescue a oven
|
||||
gone haywire by setting a low setpoint where the device is safe.
|
||||
\end{itemize}
|
||||
This scheme allows for adding more error handling strategies when necessary
|
||||
and to implement them in one place for all environment controllers.
|
||||
Consequently, there will be some some general controller code in files
|
||||
evcontrol.*. In the object oriented paradigm environment controller would
|
||||
inherit from this general controller. This is implemented by delegation in
|
||||
SICS.
|
||||
|
||||
Please note, that any environment device has three modes of
|
||||
operation. The first, trivial one, is idle. The second one is the driving
|
||||
phase. This phase is entered when a drive or run command tries to set the
|
||||
controller to a new value. Once this target has been reached a environment
|
||||
controller will be registered in the environment monitor which will take
|
||||
care of monitoring the controller during its operation. This is the
|
||||
third stage: inMonitor.
|
||||
|
||||
|
||||
\subsection{The Environment Monitor}
|
||||
The environment monitors (emon) task is to register all active environment
|
||||
controllers. It will be called from the main loop to check if each
|
||||
registered environment controller is still within tolerances. If not, emon
|
||||
has to enforce error processing. Else it does nothing.
|
||||
|
||||
The environment monitor uses the following datastructures:
|
||||
\begin{flushleft} \small
|
||||
\begin{minipage}{\linewidth} \label{scrap1}
|
||||
$\langle$emondat {\footnotesize ?}$\rangle\equiv$
|
||||
\vspace{-1ex}
|
||||
\begin{list}{}{} \item
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@ typedef struct __EnvMon {@\\
|
||||
\mbox{}\verb@ pObjectDescriptor pDes;@\\
|
||||
\mbox{}\verb@ int iList;@\\
|
||||
\mbox{}\verb@ int iEnd;@\\
|
||||
\mbox{}\verb@ } EnvMon;@\\
|
||||
\mbox{}\verb@/*---------------------------------------------------------------------------*/@\\
|
||||
\mbox{}\verb@ typedef struct {@\\
|
||||
\mbox{}\verb@ pDummy pDum;@\\
|
||||
\mbox{}\verb@ char *pName;@\\
|
||||
\mbox{}\verb@ pEVInterface pInter;@\\
|
||||
\mbox{}\verb@ } EVEntry, *pEVEntry; @\\
|
||||
\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}
|
||||
As it it will be accessible as SICS object emon needs an object descriptor.
|
||||
The other data member is a list of active controllers.
|
||||
|
||||
The EVEntry structure contains the data held in the list for each active
|
||||
controller. It is, disguised as pDum, a pointer to the controllers
|
||||
datastructure, the name of the controller, and the environment interface of
|
||||
the controller.
|
||||
|
||||
The following interface is implemented by the environment monitor:
|
||||
\begin{flushleft} \small
|
||||
\begin{minipage}{\linewidth} \label{scrap2}
|
||||
$\langle$emonint {\footnotesize ?}$\rangle\equiv$
|
||||
\vspace{-1ex}
|
||||
\begin{list}{}{} \item
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@ pEnvMon CreateEnvMon(void);@\\
|
||||
\mbox{}\verb@ void DeleteEnvMon(void *pData);@\\
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@ int EVRegisterController(pEnvMon self, char *pName, void *pData,@\\
|
||||
\mbox{}\verb@ SConnection *pCon);@\\
|
||||
\mbox{}\verb@ int EVUnregister(pEnvMon self, char *name);@\\
|
||||
\mbox{}\verb@ @\\
|
||||
\mbox{}\verb@ int EVMonitorControllers(pEnvMon self);@\\
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@ int EVList(pEnvMon self, SConnection *pCon);@\\
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@ int EVWrapper(SConnection *pCon, SicsInterp *pSics, void *pData,@\\
|
||||
\mbox{}\verb@ int argc, char *argv[]);@\\
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@ pEnvMon FindEMON(SicsInterp *pSics);@\\
|
||||
\mbox{}\verb@ @\\
|
||||
\mbox{}\verb@ int EnvMonTask(void *pEv);@\\
|
||||
\mbox{}\verb@ void EnvMonSignal(void *pEndv, int iSignal, void *pSigData);@\\
|
||||
\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}
|
||||
{\bf CreateEnvMon} initialises a emon data structure. As usual it returns
|
||||
NULL on error, a pointer to a new structure on success.
|
||||
|
||||
{\bf DeleteEnvMon} deletes and emon data structure and frees all memory
|
||||
associated with it.
|
||||
|
||||
{\bf EVRegisterController} registers a controller for monitoring. The
|
||||
parameters are:
|
||||
\begin{itemize}
|
||||
\item {\bf self}. A pointer to the environment monitor where to register the
|
||||
controller.
|
||||
\item {\bf pName}. The name of the controller object.
|
||||
\item {\bf pData}. A pointer to the data structure belonging to the
|
||||
controller object.
|
||||
\item {\bf pCon}. A pointer to the client connection to which erros shall be
|
||||
reported.
|
||||
\end{itemize}
|
||||
|
||||
{\bf EVUnregister} Removes the controller name from the monitoring list.
|
||||
|
||||
{\bf EVMonitorControllers} is the function which will be called from the
|
||||
main loop and which is responsible for monitoring the registered
|
||||
controllers.
|
||||
|
||||
|
||||
{\bf EVList} prints a status report about the emon to the Connection object
|
||||
specified.
|
||||
|
||||
{\bf EVWrapper} is the wrapper function necessary to make the emon
|
||||
available from SICS. The user may interact with the emon through SICS. The
|
||||
user will be enabled to list the currently registered environment
|
||||
controllers and their current state and to register and unnregister
|
||||
controllers.
|
||||
|
||||
{\bf EnvMonTask} is the task function associated with the environment
|
||||
monitor. This is called by the task handling object and eventually
|
||||
invokes EVMonitorControllers for checking on the environment
|
||||
controllers configured into SICS.
|
||||
|
||||
{\bf EnvMonSignal} is the signale handler for the environment monitor task.
|
||||
|
||||
\begin{flushleft} \small
|
||||
\begin{minipage}{\linewidth} \label{scrap3}
|
||||
\verb@"emon.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 M O N I T O R@\\
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@ The environment monitor is responsible for monitoring active environment@\\
|
||||
\mbox{}\verb@ devices. @\\
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@ Mark Koennecke, Juli 1997@\\
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@ copyright: see implementation file.@\\
|
||||
\mbox{}\verb@ doc: programmers reference.@\\
|
||||
\mbox{}\verb@----------------------------------------------------------------------------*/@\\
|
||||
\mbox{}\verb@#ifndef SICSEMON@\\
|
||||
\mbox{}\verb@#define SICSEMON@\\
|
||||
\mbox{}\verb@ typedef struct __EnvMon *pEnvMon;@\\
|
||||
\mbox{}\verb@/*-------------------------------------------------------------------------*/@\\
|
||||
\mbox{}\verb@@$\langle$emonint {\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{scrap4}
|
||||
\verb@"emon.i"@ {\footnotesize ? }$\equiv$
|
||||
\vspace{-1ex}
|
||||
\begin{list}{}{} \item
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@/*--------------------------------------------------------------------------@\\
|
||||
\mbox{}\verb@ Internal header file defining the datastructure for the environment@\\
|
||||
\mbox{}\verb@ controller.@\\
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@ Mark Koennecke, Juli 1997@\\
|
||||
\mbox{}\verb@---------------------------------------------------------------------------*/@\\
|
||||
\mbox{}\verb@@$\langle$emondat {\footnotesize ?}$\rangle$\verb@@\\
|
||||
\mbox{}\verb@@$\diamond$
|
||||
\end{list}
|
||||
\vspace{-2ex}
|
||||
\end{minipage}\\[4ex]
|
||||
\end{flushleft}
|
||||
321
doc/programmer/evcontroller.tex
Normal file
321
doc/programmer/evcontroller.tex
Normal file
@@ -0,0 +1,321 @@
|
||||
\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@ pEVDriver pDriv;@\\
|
||||
\mbox{}\verb@ EVMode eMode;@\\
|
||||
\mbox{}\verb@ float fTarget;@\\
|
||||
\mbox{}\verb@ char *pName;@\\
|
||||
\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@ 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. 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:
|
||||
|
||||
\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 (*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 (*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 [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.
|
||||
|
||||
\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@@\\
|
||||
\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@@\\
|
||||
\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}
|
||||
110
doc/programmer/evdrivers.tex
Normal file
110
doc/programmer/evdrivers.tex
Normal file
@@ -0,0 +1,110 @@
|
||||
\subsubsection{LTC-11 Driver}
|
||||
This is a driver for the Kyocera LTC-11 temperature controller which
|
||||
is used with the Kryo furnace at SINQ (funny idea, a kryo
|
||||
furnace). As with the ITC-4 this device has a few special functions
|
||||
and requires an additional interpreter function which delegates to the
|
||||
standard one for the general stuff. This is mainly the switching of
|
||||
the operation mode of the LTC-11. It has two modes: analog mode and
|
||||
heater mode. For more details about this see the controller
|
||||
manual. The driver is implemented in the
|
||||
file ltc11.h and ltc11.c. The following functions, besides those
|
||||
required for the standard driver, are defined:
|
||||
|
||||
\begin{verbatim}
|
||||
pEVDriver CreateLTC11Driver(int argc, char *argv[]);
|
||||
|
||||
int LTC11GetMode(pEVDriver self, int *iMode);
|
||||
int LTC11SetMode(pEVDriver self, int iMode);
|
||||
|
||||
int LTC11Action(SConnection *pCon, SicsInterp *pSics, void *pData,
|
||||
int argc, char *argv[]);
|
||||
\end{verbatim}
|
||||
These are:
|
||||
\begin{description}
|
||||
\item[CreateLTC11Driver] creates a driver for a LTC-11. Returns a
|
||||
pointer to a newly allocated LTC-11 driver or NULL in case of failure.
|
||||
\item[LTC11GetMode] retrieves the current operation mode of the
|
||||
LTC-11.
|
||||
\item[LTC11SetMode] sets the operation mode for the LTC-11.
|
||||
\item[LTC11Action] The interpreter interface function for the
|
||||
LTC-11. Implements the special commands for the LTC-11 and calls
|
||||
EVControlWrapper for anything else.
|
||||
\end{description}
|
||||
|
||||
|
||||
\subsubsection{The Dillution Cryostat}
|
||||
This is the old monster cryostat inherited from Saphir. Its driver is
|
||||
implemented in dilludriv.h and dilludriv.c. There is additional code
|
||||
for this device in the hardsup subdirectory in the file dillutil.h and
|
||||
dillutil.c. This device has a fairly involved command protocoll. A
|
||||
change of the set point requires heater output and and various
|
||||
parameters for the resistance bridge used for temperature measurement
|
||||
to be set. Then the set value has to be formatted in a range specific
|
||||
way in a hexidecimal format. Most of this code is a C adaption of an
|
||||
earlier F77 code from Elsenhans. Additionally this controller does not
|
||||
provide a temperature but a resistance value. This resistance value
|
||||
has to be converted to temperature through a calibration table. Thus
|
||||
there is an additional file, dilu.tem, which holds this conversion
|
||||
table.
|
||||
|
||||
\subsubsection{Eurotherm Temperature Controller}
|
||||
SANS is Eurotherm temperature controller somewhere. These controllers
|
||||
are quite common and the problem may come up again. The Eurotherm
|
||||
supports not one but several command protocolls, each weirder then the
|
||||
other. The implementation here serves the EI-Bisynch protocoll. The
|
||||
thing ahs to be configured manually to run this protocoll. This
|
||||
protocoll uses specific message formats for communication, the command
|
||||
protocoll is not plain ASCII. For more details about the protocoll see
|
||||
the documentation coming with the gadget. Due to this protocoll
|
||||
restriction the usual Send function of the driver just returns an
|
||||
error. The driver is impelemwnted
|
||||
in file eurodriv.h and eurodriv.c. The following functions are
|
||||
provided:
|
||||
\begin{verbatim}
|
||||
pEVDriver CreateEURODriv(int argc, char *argv[]);
|
||||
|
||||
/*
|
||||
these are hooks to implement further functionality which,
|
||||
I'am sure, Joachim Kohlbrecher will request.
|
||||
*/
|
||||
int EuroGetParameter(void **pData, char *pPar, int iLen, float *fVal);
|
||||
int EuroSetParameter(void **pData, char *pPar, int iLen,
|
||||
char *pFormat, float fVal);
|
||||
|
||||
\end{verbatim}
|
||||
These are:
|
||||
\begin{description}
|
||||
\item[CreateEuroDriver] creates a driver for a Eurotherm controller. Returns a
|
||||
pointer to a newly allocated Eurotherm driver or NULL in case of failure.
|
||||
\item[EuroGetParameter] gets one out of many parameters possible with
|
||||
the Eurotherm. This is a hook to implement further functionality. For
|
||||
possible values for parameter names pPar see the Eurotherm
|
||||
documentation. iLen is the length of pPar.
|
||||
\item[LTC11SetParameter] retrieves the value of a parameter from the
|
||||
Eurotherm. Again a hook for further expansion. pFormat is the format
|
||||
how to print the parameter into the command string.
|
||||
\end{description}
|
||||
|
||||
\subsubsection{EL755 Magnet Controller}
|
||||
This is a driver for the PSI manufactured EL755 magnet
|
||||
controller. There is additional code for this in the hardsup directory
|
||||
with files el755\_utility.*. The functions there are documented in that
|
||||
file. For SICS there is only an adapter to this implemented in
|
||||
el755driv.h and el755driv.c. The only external function is a driver
|
||||
creation function with the usual parameters and return values.
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
144
doc/programmer/event.tex
Normal file
144
doc/programmer/event.tex
Normal file
@@ -0,0 +1,144 @@
|
||||
\subsection{SICS Events}
|
||||
This section lists the callback events known to Sics, their purpose, and
|
||||
their associated event datastructures when applicable. See the
|
||||
\ref{inter} section about callbacks for more information about
|
||||
callbacks. This only defines the integer codes possible. Please be
|
||||
aware that the implementation of the callbacks is a duty of the SICS
|
||||
objects generating it. The mentioning of an event code here means it
|
||||
is used somewhere in SICS but does not mean that it is implemented by
|
||||
all objects which might implement the event.
|
||||
|
||||
This module defines several event related functions as well.
|
||||
|
||||
\begin{flushleft} \small
|
||||
\begin{minipage}{\linewidth} \label{scrap1}
|
||||
$\langle$eFunc {\footnotesize ?}$\rangle\equiv$
|
||||
\vspace{-1ex}
|
||||
\begin{list}{}{} \item
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@ int Text2Event(char *pText);@\\
|
||||
\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}
|
||||
{\bf Text2Event } converts a text value into an event code. It returns -1
|
||||
if the event code is not known, else the apropriate event code.
|
||||
|
||||
\begin{flushleft} \small
|
||||
\begin{minipage}{\linewidth} \label{scrap2}
|
||||
$\langle$VE {\footnotesize ?}$\rangle\equiv$
|
||||
\vspace{-1ex}
|
||||
\begin{list}{}{} \item
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@#define VALUECHANGE 0@\\
|
||||
\mbox{}\verb@#define MOTDRIVE 1@\\
|
||||
\mbox{}\verb@#define MONITOR 2 @\\
|
||||
\mbox{}\verb@#define ROTSTART 3@\\
|
||||
\mbox{}\verb@#define ROTMOVE 4@\\
|
||||
\mbox{}\verb@#define SCANEND 5@\\
|
||||
\mbox{}\verb@#define SCANSTART 6@\\
|
||||
\mbox{}\verb@#define SCANPOINT 7@\\
|
||||
\mbox{}\verb@#define WLCHANGE 8@\\
|
||||
\mbox{}\verb@#define REFLECTIONDONE 9@\\
|
||||
\mbox{}\verb@#define COUNTSTART 10@\\
|
||||
\mbox{}\verb@#define COUNTEND 11@\\
|
||||
\mbox{}\verb@#define FILELOADED 12@\\
|
||||
\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}
|
||||
\begin{description}
|
||||
\item[VALUECHANGE] This is a variable changing its value. As event data a pointer to the
|
||||
SicsVariable is passed along. This is defined in sicsvar.h.
|
||||
\item[MOTDRIVE] a motor is moving. The event data is the current position.
|
||||
\item[MONITOR] The control value for a counting operation has changed.
|
||||
The event data is the new value.
|
||||
\item[ROTSTART] A velocity selector is starting up.
|
||||
\item[ROTMOVE] A velocity selector changes its rotation speed.
|
||||
\item[SCANEND] A scan has ended.
|
||||
\item[SCANSTART] A new scan has been started.
|
||||
\item[SCANPOINT] A scan point has finished and there is new data.
|
||||
\item[WLCHANGE] is incoked when the wavelength of a crystal monochromator
|
||||
changes. The event parameter is a pointer to the wave length or energy
|
||||
variable being driven. Client code can then get what it needs to know.
|
||||
\item[REFLECTIONDONE] is issued when a single reflection of a four circle
|
||||
fiffractometer has been measured.
|
||||
\item[COUNTSTART] is an event which signals the start of a counting
|
||||
operation.
|
||||
\item[COUNTEND] is an event signalling the end of a counting operation.
|
||||
\end{description}
|
||||
|
||||
Furthermore event contains system wide signal codes which are interpreted in
|
||||
the signal functions provided by each SICS task. These code are
|
||||
evaluated by the TaskSignalFunction which may be configured for each
|
||||
SICS task. See the task section for more information. Here, only
|
||||
possible codes are defined.
|
||||
|
||||
\begin{flushleft} \small
|
||||
\begin{minipage}{\linewidth} \label{scrap3}
|
||||
$\langle$VSIG {\footnotesize ?}$\rangle\equiv$
|
||||
\vspace{-1ex}
|
||||
\begin{list}{}{} \item
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@#define SICSINT 300@\\
|
||||
\mbox{}\verb@#define SICSBROADCAST 301@\\
|
||||
\mbox{}\verb@#define TOKENGRAB 302@\\
|
||||
\mbox{}\verb@#define TOKENRELEASE 303@\\
|
||||
\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}
|
||||
\begin{description}
|
||||
\item[SICSINT] An interrupt has ocurred. The signal data is the interrupt
|
||||
number which ocurred.
|
||||
\item[SICSBROADCAST] A message shall be sent to each SICS client. The signal
|
||||
data is the string to send.
|
||||
\item[TOKENGRAB] A connection has successfully grabbed the control token.
|
||||
\item[TOKENRELEASE] A connection has released the control token.
|
||||
|
||||
\end{description}
|
||||
\begin{flushleft} \small
|
||||
\begin{minipage}{\linewidth} \label{scrap4}
|
||||
\verb@"event.h"@ {\footnotesize ? }$\equiv$
|
||||
\vspace{-1ex}
|
||||
\begin{list}{}{} \item
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@/*----------------------------------------------------------------------------@\\
|
||||
\mbox{}\verb@ E V E N T@\\
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@ This header file lists the event codes known to SICS. These event code@\\
|
||||
\mbox{}\verb@ are used in callback functions. Where apropriate, the event data@\\
|
||||
\mbox{}\verb@ structures are also defined in this file.@\\
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@ Mark Koennecke, 1997@\\
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@----------------------------------------------------------------------------*/@\\
|
||||
\mbox{}\verb@#ifndef SICSEVENT@\\
|
||||
\mbox{}\verb@#define SICSEVENT@\\
|
||||
\mbox{}\verb@@$\langle$eFunc {\footnotesize ?}$\rangle$\verb@@\\
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@@$\langle$VE {\footnotesize ?}$\rangle$\verb@@\\
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@/*--------------- Signals for the Signalfunction of each task ------------*/@\\
|
||||
\mbox{}\verb@@$\langle$VSIG {\footnotesize ?}$\rangle$\verb@ @\\
|
||||
\mbox{}\verb@#endif@\\
|
||||
\mbox{}\verb@@$\diamond$
|
||||
\end{list}
|
||||
\vspace{-2ex}
|
||||
\end{minipage}\\[4ex]
|
||||
\end{flushleft}
|
||||
70
doc/programmer/faverage.tex
Normal file
70
doc/programmer/faverage.tex
Normal file
@@ -0,0 +1,70 @@
|
||||
\subsection{The FOCUS Averager}
|
||||
This is a special object for the instrument FOCUS and its Status display
|
||||
client. In the FOCUS status display the averaged data from a number of
|
||||
detectors is displayed. Thus there is already a reduced form of data. The
|
||||
actual raw data would be 150*1024*4 bytes of data and possibly more. Rather
|
||||
then transporting all this data to the status display client at regular
|
||||
intervalls it was choosen to implement this averaging process at the server
|
||||
and only send the reduced form to the status display client. Which is two
|
||||
arrays of floating point data 1024 items long. This little object implements this
|
||||
averager.
|
||||
|
||||
As all SICS objects this object has a little data structure:
|
||||
\begin{verbatim}
|
||||
typedef struct __FocusAverager {
|
||||
pObjectDescriptor pDes;
|
||||
pHistMem pHist;
|
||||
} FocusAverager;
|
||||
\end{verbatim}
|
||||
|
||||
The two fields are the standard object descriptor and a pointer to the
|
||||
histogram memory object holding the data.
|
||||
|
||||
The interface is minimal: it consists just of the factory function for
|
||||
installing this object into SICS and the actual function doing the
|
||||
averaging in the interpreter.
|
||||
|
||||
\begin{flushleft} \small
|
||||
\begin{minipage}{\linewidth} \label{scrap1}
|
||||
$\langle$faint {\footnotesize ?}$\rangle\equiv$
|
||||
\vspace{-1ex}
|
||||
\begin{list}{}{} \item
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@ int MakeFA(SConnection *pCon, SicsInterp *pSics, void *pData,@\\
|
||||
\mbox{}\verb@ int argc, char *argv[]);@\\
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@ int FocusAverageDo(SConnection *pCon, SicsInterp *pSics, void *pData,@\\
|
||||
\mbox{}\verb@ int argc, char *argv[]);@\\
|
||||
\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}
|
||||
\begin{flushleft} \small
|
||||
\begin{minipage}{\linewidth} \label{scrap2}
|
||||
\verb@"faverage.h"@ {\footnotesize ? }$\equiv$
|
||||
\vspace{-1ex}
|
||||
\begin{list}{}{} \item
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@/*-----------------------------------------------------------------------@\\
|
||||
\mbox{}\verb@ F o c u s A v e r a g e@\\
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@ An averager for FOCUS data. See faverage.tex for more details.@\\
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@ Mark Koennecke, October 1998@\\
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@--------------------------------------------------------------------------*/@\\
|
||||
\mbox{}\verb@#ifndef FOCUSAVERAGE@\\
|
||||
\mbox{}\verb@#define FOCUSAVERAGE@\\
|
||||
\mbox{}\verb@@$\langle$faint {\footnotesize ?}$\rangle$\verb@@\\
|
||||
\mbox{}\verb@#endif@\\
|
||||
\mbox{}\verb@@$\diamond$
|
||||
\end{list}
|
||||
\vspace{-2ex}
|
||||
\end{minipage}\\[4ex]
|
||||
\end{flushleft}
|
||||
22
doc/programmer/fowrite.tex
Normal file
22
doc/programmer/fowrite.tex
Normal file
@@ -0,0 +1,22 @@
|
||||
\subsection{FOCUS Data File Writing}
|
||||
FOCUS writes NeXus files. This file writing is impleneted in the files
|
||||
fowrite.h and fowrite.c. So these files contain the code for writing
|
||||
FOCUS NeXus files. But there is more to it: FOCUS has a scheme where
|
||||
the data file is updated any 20 minutes during the course of an
|
||||
measurement. This scheme is implemented with the following bits and
|
||||
pieces:
|
||||
\begin{itemize}
|
||||
\item Data file updating is triggered by a special task function,
|
||||
FoTask, which is installed into the SICS tasker when counting starts.
|
||||
\item The module registers callbacks with the histogram memory which
|
||||
are invoked when counting starts or ends. These callback functions
|
||||
take care of craeting a new file and updating it.
|
||||
\item There is a special command which allows to start and update the
|
||||
data file manually.
|
||||
\end{itemize}
|
||||
|
||||
As is it not likely that more then one FOCUS writing object is ever
|
||||
needed, all the data structures are file statics in fowrite.c. The
|
||||
external interface of this module is just a interpreter initialisation
|
||||
function and a interpreter interface function for interacting with the
|
||||
data file writing object.
|
||||
83
doc/programmer/fupa.tex
Normal file
83
doc/programmer/fupa.tex
Normal file
@@ -0,0 +1,83 @@
|
||||
\subsection{Function Parser}
|
||||
A utility module to take some of the pain from parsing input while
|
||||
writing text wrapper function for SICS.
|
||||
The idea is that you specify an array of function templates.
|
||||
These function templates will contain function names and argument
|
||||
information. This module will than parse the input against this
|
||||
template. It will return -1 if an error occurs and provide error
|
||||
information.
|
||||
On success the index of the function found will be returned.
|
||||
Arguments will have been updated with their proper values.
|
||||
Invoking functions ist still your job, probably in a switch statement
|
||||
following the call to the evaluation function.
|
||||
|
||||
The function parser supports these different argument types:
|
||||
\begin{verbatim}
|
||||
#define FUPATEXT 0 /* text*/
|
||||
#define FUPAINT 1 /* integer */
|
||||
#define FUPAFLOAT 2 /* a float */
|
||||
#define FUPAOPT 3 /* optional argument, in this case text contains it
|
||||
and iVal indicates its presence
|
||||
*/
|
||||
\end{verbatim}
|
||||
|
||||
Each template for a function has these fields:
|
||||
\begin{verbatim}
|
||||
typedef struct {
|
||||
char *name;
|
||||
int iArgs;
|
||||
int pArgs[MAXARG];
|
||||
} FuncTemplate, *pFuncTemplate;
|
||||
\end{verbatim}
|
||||
\begin{description}
|
||||
\item[name] the name of the function.
|
||||
\item[iArgs] The number of arguments to the function.
|
||||
\item[pArgs] An array with iArgs entries of the integer argument description
|
||||
types stated above.
|
||||
\end{description}
|
||||
|
||||
On return the actual values of the arguments will be returned as a field in
|
||||
this structure, according to type.
|
||||
\begin{verbatim}
|
||||
typedef struct {
|
||||
char text[80];
|
||||
int iVal;
|
||||
float fVal;
|
||||
} FuPaArg;
|
||||
\end{verbatim}
|
||||
|
||||
The whole result is returned in the structure defined below:
|
||||
\begin{verbatim}
|
||||
typedef struct {
|
||||
char pError[132];
|
||||
int iArgs;
|
||||
FuPaArg Arg[MAXARG];
|
||||
} FuPaResult;
|
||||
|
||||
\end{verbatim}
|
||||
The fields are: \begin{description}
|
||||
\item[pError] An error description in case of an error.
|
||||
\item[iArgs] the number of arguments actually read.
|
||||
\item[Arg] An array of argumnet result structures as defined above.
|
||||
\end{description}
|
||||
|
||||
Function parsing is done with this function:
|
||||
\begin{verbatim}
|
||||
int EvaluateFuPa(pFuncTemplate pTemplate,int iFunc, int argc, char *argv[],
|
||||
FuPaResult *pRes);
|
||||
\end{verbatim}
|
||||
The parameters are:
|
||||
\begin{description}
|
||||
\item[pTemplate] a parsing template.
|
||||
\item[iFunc] The number of functions in the template array.
|
||||
\item[argc,argv] The text to parse.
|
||||
\item[pRes] A pointer to a retuned result array.
|
||||
\end{description}
|
||||
The return value is -1 on error, or the number of the template identified on
|
||||
success.
|
||||
|
||||
|
||||
For more information, look on a usage example in counter.c.
|
||||
|
||||
|
||||
|
||||
463
doc/programmer/hart.eps
Normal file
463
doc/programmer/hart.eps
Normal file
@@ -0,0 +1,463 @@
|
||||
%!
|
||||
%%BoundingBox: 24 540 514 775
|
||||
%%Title: hart
|
||||
%%CreationDate: Fri May 30 10:02:56 1997
|
||||
%%Creator: Tgif-3.0-p7 by William Chia-Wei Cheng (william@cs.UCLA.edu)
|
||||
|
||||
/tgifdict 4 dict def
|
||||
tgifdict begin
|
||||
|
||||
/tgifellipsedict 6 dict def
|
||||
tgifellipsedict /mtrx matrix put
|
||||
|
||||
/tgifellipse
|
||||
{ tgifellipsedict begin
|
||||
/yrad exch def
|
||||
/xrad exch def
|
||||
/y exch def
|
||||
/x exch def
|
||||
/savematrix mtrx currentmatrix def
|
||||
x y translate
|
||||
xrad yrad scale
|
||||
0 0 1 0 360 arc
|
||||
savematrix setmatrix
|
||||
end
|
||||
} def
|
||||
|
||||
end
|
||||
|
||||
%%PageBoundingBox: 24 540 514 775
|
||||
tgifdict begin
|
||||
/tgifsavedpage save def
|
||||
|
||||
1 setmiterlimit
|
||||
1 setlinewidth
|
||||
|
||||
0 setgray
|
||||
|
||||
72 0 mul 72 11.00 mul translate
|
||||
72 128 div 100.000 mul 100 div dup neg scale
|
||||
|
||||
gsave
|
||||
|
||||
/tgiforigctm matrix currentmatrix def
|
||||
|
||||
% BOX
|
||||
0 setgray
|
||||
gsave
|
||||
10 setmiterlimit
|
||||
gsave
|
||||
newpath
|
||||
112 163 moveto 227 163 lineto 227 189 lineto 112 189 lineto
|
||||
closepath
|
||||
stroke
|
||||
grestore
|
||||
grestore
|
||||
|
||||
% BOX
|
||||
0 setgray
|
||||
gsave
|
||||
10 setmiterlimit
|
||||
gsave
|
||||
newpath
|
||||
125 99 moveto 214 99 lineto 214 150 lineto 125 150 lineto
|
||||
closepath
|
||||
stroke
|
||||
grestore
|
||||
grestore
|
||||
|
||||
% RCBOX
|
||||
0 setgray
|
||||
gsave
|
||||
gsave
|
||||
newpath
|
||||
202 112 moveto 202 138 lineto 138 138 lineto 138 112 lineto
|
||||
closepath
|
||||
stroke
|
||||
grestore
|
||||
grestore
|
||||
|
||||
% BOX
|
||||
0 setgray
|
||||
gsave
|
||||
10 setmiterlimit
|
||||
gsave
|
||||
newpath
|
||||
368 99 moveto 509 99 lineto 509 176 lineto 368 176 lineto
|
||||
closepath
|
||||
stroke
|
||||
grestore
|
||||
grestore
|
||||
|
||||
% TEXT
|
||||
0 setgray
|
||||
/Courier findfont [17 0 0 -17 0 0] makefont setfont
|
||||
gsave
|
||||
573 75 moveto (Motor Controller) show
|
||||
grestore
|
||||
|
||||
% TEXT
|
||||
0 setgray
|
||||
/Courier findfont [17 0 0 -17 0 0] makefont setfont
|
||||
gsave
|
||||
573 139 moveto (Motor Controller) show
|
||||
grestore
|
||||
|
||||
% TEXT
|
||||
0 setgray
|
||||
/Courier findfont [17 0 0 -17 0 0] makefont setfont
|
||||
gsave
|
||||
573 228 moveto (Counter Box) show
|
||||
grestore
|
||||
|
||||
% TEXT
|
||||
0 setgray
|
||||
/Courier findfont [17 0 0 -17 0 0] makefont setfont
|
||||
gsave
|
||||
573 305 moveto (Counter) show
|
||||
grestore
|
||||
|
||||
% TEXT
|
||||
0 setgray
|
||||
/Courier findfont [17 0 0 -17 0 0] makefont setfont
|
||||
gsave
|
||||
368 382 moveto (Histogram) show
|
||||
368 399 moveto (Memory) show
|
||||
grestore
|
||||
|
||||
% BOX
|
||||
0 setgray
|
||||
gsave
|
||||
10 setmiterlimit
|
||||
gsave
|
||||
newpath
|
||||
560 202 moveto 726 202 lineto 726 240 lineto 560 240 lineto
|
||||
closepath
|
||||
stroke
|
||||
grestore
|
||||
grestore
|
||||
|
||||
% BOX
|
||||
0 setgray
|
||||
gsave
|
||||
10 setmiterlimit
|
||||
gsave
|
||||
newpath
|
||||
330 355 moveto 483 355 lineto 483 445 lineto 330 445 lineto
|
||||
closepath
|
||||
stroke
|
||||
grestore
|
||||
grestore
|
||||
|
||||
% POLY/OPEN-SPLINE
|
||||
0 setgray
|
||||
gsave
|
||||
newpath
|
||||
48 266 moveto
|
||||
483 266 lineto
|
||||
tgiforigctm setmatrix
|
||||
5 setlinewidth
|
||||
stroke
|
||||
1 setlinewidth
|
||||
grestore
|
||||
|
||||
% POLY/OPEN-SPLINE
|
||||
0 setgray
|
||||
gsave
|
||||
newpath
|
||||
432 176 moveto
|
||||
432 266 lineto
|
||||
tgiforigctm setmatrix
|
||||
5 setlinewidth
|
||||
stroke
|
||||
1 setlinewidth
|
||||
grestore
|
||||
|
||||
% POLY/OPEN-SPLINE
|
||||
0 setgray
|
||||
gsave
|
||||
newpath
|
||||
150 189 moveto
|
||||
150 266 lineto
|
||||
tgiforigctm setmatrix
|
||||
5 setlinewidth
|
||||
stroke
|
||||
1 setlinewidth
|
||||
grestore
|
||||
|
||||
% POLY/OPEN-SPLINE
|
||||
0 setgray
|
||||
gsave
|
||||
newpath
|
||||
381 266 moveto
|
||||
381 355 lineto
|
||||
tgiforigctm setmatrix
|
||||
5 setlinewidth
|
||||
stroke
|
||||
1 setlinewidth
|
||||
grestore
|
||||
|
||||
% TEXT
|
||||
0 setgray
|
||||
/Courier findfont [17 0 0 -17 0 0] makefont setfont
|
||||
gsave
|
||||
176 292 moveto (TCP/IP) show
|
||||
grestore
|
||||
|
||||
% POLY/OPEN-SPLINE
|
||||
0 setgray
|
||||
gsave
|
||||
newpath
|
||||
509 112 moveto
|
||||
560 74 lineto
|
||||
tgiforigctm setmatrix
|
||||
2 setlinewidth
|
||||
stroke
|
||||
1 setlinewidth
|
||||
grestore
|
||||
|
||||
% POLY/OPEN-SPLINE
|
||||
0 setgray
|
||||
gsave
|
||||
newpath
|
||||
509 138 moveto
|
||||
560 138 lineto
|
||||
tgiforigctm setmatrix
|
||||
2 setlinewidth
|
||||
stroke
|
||||
1 setlinewidth
|
||||
grestore
|
||||
|
||||
% POLY/OPEN-SPLINE
|
||||
0 setgray
|
||||
gsave
|
||||
newpath
|
||||
509 163 moveto
|
||||
560 214 lineto
|
||||
tgiforigctm setmatrix
|
||||
2 setlinewidth
|
||||
stroke
|
||||
1 setlinewidth
|
||||
grestore
|
||||
|
||||
% POLY/OPEN-SPLINE
|
||||
0 setgray
|
||||
gsave
|
||||
newpath
|
||||
611 240 moveto
|
||||
611 291 lineto
|
||||
tgiforigctm setmatrix
|
||||
2 setlinewidth
|
||||
stroke
|
||||
1 setlinewidth
|
||||
grestore
|
||||
|
||||
% POLY/OPEN-SPLINE
|
||||
0 setgray
|
||||
gsave
|
||||
newpath
|
||||
624 240 moveto
|
||||
624 291 lineto
|
||||
tgiforigctm setmatrix
|
||||
2 setlinewidth
|
||||
stroke
|
||||
1 setlinewidth
|
||||
grestore
|
||||
|
||||
% TEXT
|
||||
0 setgray
|
||||
/Courier findfont [17 0 0 -17 0 0] makefont setfont
|
||||
gsave
|
||||
483 75 moveto (RS-232) show
|
||||
grestore
|
||||
|
||||
% BOX
|
||||
0 setgray
|
||||
gsave
|
||||
10 setmiterlimit
|
||||
gsave
|
||||
newpath
|
||||
560 48 moveto 752 48 lineto 752 96 lineto 560 96 lineto
|
||||
closepath
|
||||
stroke
|
||||
grestore
|
||||
grestore
|
||||
|
||||
% BOX
|
||||
0 setgray
|
||||
gsave
|
||||
10 setmiterlimit
|
||||
gsave
|
||||
newpath
|
||||
560 112 moveto 752 112 lineto 752 160 lineto 560 160 lineto
|
||||
closepath
|
||||
stroke
|
||||
grestore
|
||||
grestore
|
||||
|
||||
% BOX
|
||||
0 setgray
|
||||
gsave
|
||||
10 setmiterlimit
|
||||
gsave
|
||||
newpath
|
||||
560 288 moveto 672 288 lineto 672 320 lineto 560 320 lineto
|
||||
closepath
|
||||
stroke
|
||||
grestore
|
||||
grestore
|
||||
|
||||
% TEXT
|
||||
0 setgray
|
||||
/Courier findfont [17 0 0 -17 0 0] makefont setfont
|
||||
gsave
|
||||
384 126 moveto (Terminal) show
|
||||
384 143 moveto (Server) show
|
||||
grestore
|
||||
|
||||
% TEXT
|
||||
0 setgray
|
||||
/Courier findfont [17 0 0 -17 0 0] makefont setfont
|
||||
gsave
|
||||
864 62 moveto (M1) show
|
||||
grestore
|
||||
|
||||
% TEXT
|
||||
0 setgray
|
||||
/Courier findfont [17 0 0 -17 0 0] makefont setfont
|
||||
gsave
|
||||
864 126 moveto (M2) show
|
||||
grestore
|
||||
|
||||
% TEXT
|
||||
0 setgray
|
||||
/Courier findfont [17 0 0 -17 0 0] makefont setfont
|
||||
gsave
|
||||
864 190 moveto (M3) show
|
||||
grestore
|
||||
|
||||
% TEXT
|
||||
0 setgray
|
||||
/Courier findfont [17 0 0 -17 0 0] makefont setfont
|
||||
gsave
|
||||
864 254 moveto (M4) show
|
||||
grestore
|
||||
|
||||
% TEXT
|
||||
0 setgray
|
||||
/Courier findfont [17 0 0 -17 0 0] makefont setfont
|
||||
gsave
|
||||
864 334 moveto (M5) show
|
||||
grestore
|
||||
|
||||
% OVAL
|
||||
0 setgray
|
||||
gsave
|
||||
gsave
|
||||
newpath 864 56 32 24 tgifellipse
|
||||
stroke
|
||||
grestore
|
||||
grestore
|
||||
|
||||
% OVAL
|
||||
0 setgray
|
||||
gsave
|
||||
gsave
|
||||
newpath 880 120 32 24 tgifellipse
|
||||
stroke
|
||||
grestore
|
||||
grestore
|
||||
|
||||
% OVAL
|
||||
0 setgray
|
||||
gsave
|
||||
gsave
|
||||
newpath 880 184 32 24 tgifellipse
|
||||
stroke
|
||||
grestore
|
||||
grestore
|
||||
|
||||
% OVAL
|
||||
0 setgray
|
||||
gsave
|
||||
gsave
|
||||
newpath 880 248 32 24 tgifellipse
|
||||
stroke
|
||||
grestore
|
||||
grestore
|
||||
|
||||
% OVAL
|
||||
0 setgray
|
||||
gsave
|
||||
gsave
|
||||
newpath 880 328 32 24 tgifellipse
|
||||
stroke
|
||||
grestore
|
||||
grestore
|
||||
|
||||
% POLY/OPEN-SPLINE
|
||||
0 setgray
|
||||
gsave
|
||||
newpath
|
||||
752 64 moveto
|
||||
832 48 lineto
|
||||
tgiforigctm setmatrix
|
||||
1 setlinewidth
|
||||
stroke
|
||||
grestore
|
||||
|
||||
% POLY/OPEN-SPLINE
|
||||
0 setgray
|
||||
gsave
|
||||
newpath
|
||||
752 80 moveto
|
||||
848 112 lineto
|
||||
tgiforigctm setmatrix
|
||||
1 setlinewidth
|
||||
stroke
|
||||
grestore
|
||||
|
||||
% POLY/OPEN-SPLINE
|
||||
0 setgray
|
||||
gsave
|
||||
newpath
|
||||
752 144 moveto
|
||||
848 176 lineto
|
||||
tgiforigctm setmatrix
|
||||
1 setlinewidth
|
||||
stroke
|
||||
grestore
|
||||
|
||||
% POLY/OPEN-SPLINE
|
||||
0 setgray
|
||||
gsave
|
||||
newpath
|
||||
752 144 moveto
|
||||
848 240 lineto
|
||||
tgiforigctm setmatrix
|
||||
1 setlinewidth
|
||||
stroke
|
||||
grestore
|
||||
|
||||
% POLY/OPEN-SPLINE
|
||||
0 setgray
|
||||
gsave
|
||||
newpath
|
||||
752 144 moveto
|
||||
848 320 lineto
|
||||
tgiforigctm setmatrix
|
||||
1 setlinewidth
|
||||
stroke
|
||||
grestore
|
||||
|
||||
% TEXT
|
||||
0 setgray
|
||||
/Courier findfont [17 0 0 -17 0 0] makefont setfont
|
||||
gsave
|
||||
96 238 moveto (Data Aquisition Computer) show
|
||||
grestore
|
||||
|
||||
grestore
|
||||
tgifsavedpage restore
|
||||
end
|
||||
%MatchingCreationDate: Fri May 30 10:02:56 1997
|
||||
BIN
doc/programmer/hart.gif
Normal file
BIN
doc/programmer/hart.gif
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 6.0 KiB |
656
doc/programmer/histogram.tex
Normal file
656
doc/programmer/histogram.tex
Normal file
@@ -0,0 +1,656 @@
|
||||
|
||||
\subsection{Histogram memory}
|
||||
A histogram memory is the interface to a large multidetector. This is quite
|
||||
a complex piece of equipment. It does not only provide lots of data but also
|
||||
has a lot of configuration options. Things which need configuration are:
|
||||
histogram mode, overflow mode, measurement mode and the layout of the
|
||||
histograms. Let's discuss these different modes first.
|
||||
|
||||
\begin{flushleft} \small
|
||||
\begin{minipage}{\linewidth} \label{scrap1}
|
||||
$\langle$Modes {\footnotesize ?}$\rangle\equiv$
|
||||
\vspace{-1ex}
|
||||
\begin{list}{}{} \item
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@ typedef enum {@\\
|
||||
\mbox{}\verb@ eHTransparent,@\\
|
||||
\mbox{}\verb@ eHNormal,@\\
|
||||
\mbox{}\verb@ eHTOF,@\\
|
||||
\mbox{}\verb@ eHStrobo,@\\
|
||||
\mbox{}\verb@ eHRPT@\\
|
||||
\mbox{}\verb@ } HistMode;@\\
|
||||
\mbox{}\verb@@$\diamond$
|
||||
\end{list}
|
||||
\vspace{-1ex}
|
||||
\footnotesize\addtolength{\baselineskip}{-1ex}
|
||||
\begin{list}{}{\setlength{\itemsep}{-\parsep}\setlength{\itemindent}{-\leftmargin}}
|
||||
\item Macro defined by scraps ?, ?.
|
||||
\item Macro referenced in scrap ?.
|
||||
\end{list}
|
||||
\end{minipage}\\[4ex]
|
||||
\end{flushleft}
|
||||
A histogram memory can be operated in transparent mode. It has not yet been
|
||||
defined what this means but it is sort of storing raw data from the detector
|
||||
without any summing or processing. Normal mode is better defined, this is
|
||||
sorting and summing data from the detector into apropriate bins for each
|
||||
detector. Time is not resolved. TOF mode means time of flight mode. In this
|
||||
mode incoming is not only sorted and summed into the correct detector bins
|
||||
but also resolved in time (which means energy for neutrons). This means for
|
||||
each detector there is a histogram counts versus time. Similar is
|
||||
stroboscopic mode (eHStrobo). In stroboscopic mode there is a histogram
|
||||
counts versus pulses for each physical detector. The bin switching is done
|
||||
via a secondary hardware signal or from software. This is useful for
|
||||
measuring diffraction data versus oscillating environment conditions. eHRPT
|
||||
is a special mode for the HRPT Cerca detector. It requires special handling,
|
||||
this is why there is a special flag.
|
||||
|
||||
\begin{flushleft} \small
|
||||
\begin{minipage}{\linewidth} \label{scrap2}
|
||||
$\langle$Modes {\footnotesize ?}$\rangle\equiv$
|
||||
\vspace{-1ex}
|
||||
\begin{list}{}{} \item
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@ typedef enum {@\\
|
||||
\mbox{}\verb@ eOIgnore,@\\
|
||||
\mbox{}\verb@ eOCeil,@\\
|
||||
\mbox{}\verb@ eOCount,@\\
|
||||
\mbox{}\verb@ eReflect@\\
|
||||
\mbox{}\verb@ } OverFlowMode;@\\
|
||||
\mbox{}\verb@@$\diamond$
|
||||
\end{list}
|
||||
\vspace{-1ex}
|
||||
\footnotesize\addtolength{\baselineskip}{-1ex}
|
||||
\begin{list}{}{\setlength{\itemsep}{-\parsep}\setlength{\itemindent}{-\leftmargin}}
|
||||
\item Macro defined by scraps ?, ?.
|
||||
\item Macro referenced in scrap ?.
|
||||
\end{list}
|
||||
\end{minipage}\\[4ex]
|
||||
\end{flushleft}
|
||||
Histogram memories may support different schemes for handling overflow
|
||||
conditions. In this condition there are more counts than fit into the
|
||||
configured
|
||||
binwidth. The simplest thing to do is to ignore the condition and simply
|
||||
wrap over to zero (eOIgnore). The other mode is to keep the bin at the
|
||||
highest count possible (eOCeil). More sophisticated histogram memories
|
||||
maintain a separate list where all those overflowed bins are registered.
|
||||
This is eOCount. eReflect has nothing to do with overflows. It says that the
|
||||
histogram should be reflected. This means counter 1 becomes counter max etc.
|
||||
This is special for HRPT. It happens to live in the OverFlowMode enum because
|
||||
this is really a sub mode descriptor.
|
||||
|
||||
The measurement mode is the simple counter operation mode: wait for a timer
|
||||
or wait for a monitor to run full.
|
||||
|
||||
The layout of the histogram memory (HM) is defined by the rank (i.e. the number
|
||||
of dimensions of the HM, the number of points in each dimension and by the
|
||||
binwidth in bits for each bin. For TOF and stroboscopic modes information
|
||||
about the binning in time or pulses is needed as well. Needless to say that
|
||||
these values have to match the geometry of the detector.
|
||||
|
||||
Histograms usually have a number type associated with them. In order to
|
||||
minimise conversion overhead in the logical object, the data size will
|
||||
defined by a typedef, HistInt.
|
||||
|
||||
There is a scheme for handling all this configuration information
|
||||
which may even be more for a Histogram memory with a specific
|
||||
driver. There is a dictionary of configuration options in the logical
|
||||
histogram memory object. These options can be set with a special
|
||||
command. Then on initialisation first the logical histogram memory
|
||||
evaluates the general options and then the driver in its Config
|
||||
function evaluates the driver specific options.
|
||||
|
||||
|
||||
\subsubsection{The Histogram memory driver}
|
||||
Adhering to the Sics paradigm of dividing any device into a logical device
|
||||
and a hardware driver, the Sics histogram memory needs drivers as well. This
|
||||
section describes this driver interface. For an overview, see the structure
|
||||
definition:
|
||||
|
||||
\begin{flushleft} \small
|
||||
\begin{minipage}{\linewidth} \label{scrap3}
|
||||
$\langle$HistType {\footnotesize ?}$\rangle\equiv$
|
||||
\vspace{-1ex}
|
||||
\begin{list}{}{} \item
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@ typedef struct __HistDriver {@\\
|
||||
\mbox{}\verb@ /* configuration data */@\\
|
||||
\mbox{}\verb@ HistMode eHistMode;@\\
|
||||
\mbox{}\verb@ OverFlowMode eFlow;@\\
|
||||
\mbox{}\verb@ int iRank;@\\
|
||||
\mbox{}\verb@ int iDims[MAXDIM];@\\
|
||||
\mbox{}\verb@ int nDim;@\\
|
||||
\mbox{}\verb@ int iLength;@\\
|
||||
\mbox{}\verb@ int iBinWidth;@\\
|
||||
\mbox{}\verb@ float fTime[MAXCHAN];@\\
|
||||
\mbox{}\verb@ int iTimeChan;@\\
|
||||
\mbox{}\verb@ /* counting operations data */@\\
|
||||
\mbox{}\verb@ CounterMode eCount;@\\
|
||||
\mbox{}\verb@ float fCountPreset;@\\
|
||||
\mbox{}\verb@ /* status flags */@\\
|
||||
\mbox{}\verb@ int iReconfig;@\\
|
||||
\mbox{}\verb@ int iUpdate;@\\
|
||||
\mbox{}\verb@ /* interface functions */@\\
|
||||
\mbox{}\verb@ int (*Configure)(pHistDriver self,@\\
|
||||
\mbox{}\verb@ SConnection *pCon,@\\
|
||||
\mbox{}\verb@ pStringDict pOpt,@\\
|
||||
\mbox{}\verb@ SicsInterp *pSics);@\\
|
||||
\mbox{}\verb@ int (*Start)(pHistDriver self, @\\
|
||||
\mbox{}\verb@ SConnection *pCon);@\\
|
||||
\mbox{}\verb@ int (*Halt)(pHistDriver self);@\\
|
||||
\mbox{}\verb@ int (*GetCountStatus)(pHistDriver self,@\\
|
||||
\mbox{}\verb@ SConnection *pCon);@\\
|
||||
\mbox{}\verb@ int (*GetError)(pHistDriver self, @\\
|
||||
\mbox{}\verb@ int *iCode,@\\
|
||||
\mbox{}\verb@ char *perror,@\\
|
||||
\mbox{}\verb@ int iErrlen);@\\
|
||||
\mbox{}\verb@ int (*TryAndFixIt)(pHistDriver self,@\\
|
||||
\mbox{}\verb@ int iCode);@\\
|
||||
\mbox{}\verb@ int (*GetData)(pHistDriver self,@\\
|
||||
\mbox{}\verb@ SConnection *pCon);@\\
|
||||
\mbox{}\verb@ int (*GetHistogram)(pHistDriver self,@\\
|
||||
\mbox{}\verb@ SConnection *pCon,@\\
|
||||
\mbox{}\verb@ int i,@\\
|
||||
\mbox{}\verb@ int iStart, int iEnd,@\\
|
||||
\mbox{}\verb@ HistInt *pData);@\\
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@ int (*SetHistogram)(pHistDriver self,@\\
|
||||
\mbox{}\verb@ SConnection *pCon,@\\
|
||||
\mbox{}\verb@ int i,@\\
|
||||
\mbox{}\verb@ int iStart, int iEnd,@\\
|
||||
\mbox{}\verb@ HistInt *pData);@\\
|
||||
\mbox{}\verb@ long (*GetMonitor)(pHistDriver self, @\\
|
||||
\mbox{}\verb@ int i,@\\
|
||||
\mbox{}\verb@ SConnection *pCon);@\\
|
||||
\mbox{}\verb@ float (*GetTime)(pHistDriver self,@\\
|
||||
\mbox{}\verb@ SConnection *pCon);@\\
|
||||
\mbox{}\verb@ int (*Preset)(pHistDriver self,@\\
|
||||
\mbox{}\verb@ SConnection *pCon,@\\
|
||||
\mbox{}\verb@ HistInt iVal);@\\
|
||||
\mbox{}\verb@ int (*Pause)(pHistDriver self,@\\
|
||||
\mbox{}\verb@ SConnection *pCon);@\\
|
||||
\mbox{}\verb@ int (*Continue)(pHistDriver self,@\\
|
||||
\mbox{}\verb@ SConnection *pCon);@\\
|
||||
\mbox{}\verb@ int (*FreePrivate)(pHistDriver self);@\\
|
||||
\mbox{}\verb@ void *pPriv;@\\
|
||||
\mbox{}\verb@ } HistDriver;@\\
|
||||
\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}
|
||||
Quite a lot, but a histogram memory is quite a complex piece of equipment.
|
||||
The configuration information is in the elements EhistMode, eOverFlowMode,
|
||||
iRank, iDims and iBinWidth fields. iDim and nDim desribe the logical
|
||||
dimensions of the histogram memory. These may be different from the
|
||||
dimensions used for data transfer. For instance the SANS detector is
|
||||
handled internally as 1600+ numbers where it really is a filed o
|
||||
128*128.
|
||||
Additionally there is an array of
|
||||
floating point values which denote the time binning for time-o-flight
|
||||
operation or the stroboscopic binning axis in stroboscopic mode.
|
||||
|
||||
The fields fPreset and CounterMode hold the counting parameter data.
|
||||
|
||||
Than there are two status fields. The first is iReconfig. This will be set
|
||||
to true, whenever any changes to the configuration to the HM are made. This
|
||||
will be tested against when starting a measurement and will force a
|
||||
configuration call to be issued. A call to the interface function Configure
|
||||
clears this flag. The other flag is iUpdate. This is only useful when an in
|
||||
memory copy of the histogrammed data is maintained on the host computer.
|
||||
This flag is set when a count gets started and gets cleared when counting is
|
||||
finished and all data has been transferred.
|
||||
|
||||
The next part defines the hardware interface functions to the histogram
|
||||
memory. Each of these functions must be defined by any complete
|
||||
implementation of a HM driver. If not stated otherwise these functions
|
||||
return 1 on success and 0 on failure. All functions take a pointer to their
|
||||
HistDriver structure as first parameter. Many functions have a pointer to an
|
||||
SConnection as parameter. This connection will be used for error reporting.
|
||||
|
||||
|
||||
\begin{itemize}
|
||||
\item {\bf 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.
|
||||
\item {\bf Start} starts a counting operation according to the current
|
||||
settings of the counter mode parameters.
|
||||
\item {\bf Halt} implements an emergency stop of a counting operation.
|
||||
\item {\bf 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 {\bf 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 {\bf 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 MOTREDO when the error could be fixed, but the upper level code will
|
||||
need to rerun the command which failed.
|
||||
\item MOTFAIL 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 {\bf GetData} transfers all the data collected in the HM into the
|
||||
host computers memory.
|
||||
\item {\bf GetHistogram} copies the histogram number i into the data space
|
||||
given by the pointer to a long array. A conversion from different binwidth
|
||||
to long is performed as well.
|
||||
\item {\bf SetHistogram} presets the histogram number 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 {\bf GetMonitor} returns the counts in the monitor i. Returns a
|
||||
negative value on error. The error will have been printed to pCon.
|
||||
\item {\bf GetTime} returns the actual counting time.
|
||||
\item {\bf Preset} initializes the histogram memory to the value given by
|
||||
iVal.
|
||||
\item {\bf Pause} pauses data collection.
|
||||
\item {\bf Continue} continues a paused data collection.
|
||||
\item {\bf 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.
|
||||
\end{itemize}
|
||||
|
||||
The last entry in the HistDriver structure is a pointer to void. Rather then use the overlay structure as with motor drivers, histogram
|
||||
memory stores driver specific information in a driver specific sub
|
||||
data structure. This is the pointer to pPrivate. KillPrivate is a
|
||||
function which is able to delete the driver specific data structure
|
||||
properly.
|
||||
|
||||
As all the burden is up to the implementation of the histogram memory driver
|
||||
only these few functions operate on histogram memory drivers in general:
|
||||
|
||||
\begin{flushleft} \small
|
||||
\begin{minipage}{\linewidth} \label{scrap4}
|
||||
$\langle$HistDrivProt {\footnotesize ?}$\rangle\equiv$
|
||||
\vspace{-1ex}
|
||||
\begin{list}{}{} \item
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@ pHistDriver CreateHistDriver(pStringDict pDict);@\\
|
||||
\mbox{}\verb@ void DeleteHistDriver(pHistDriver self);@\\
|
||||
\mbox{}\verb@ int HistDriverConfig(pHistDriver self, pStringDict pOpt,@\\
|
||||
\mbox{}\verb@ SConnection *pCon);@\\
|
||||
\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}
|
||||
CreateHistDriver creates a new HistDriver data structure and returns it. Or
|
||||
NULL when the memory is exhausted. It also initialises the options database
|
||||
in pDict to the apropriate values.
|
||||
|
||||
|
||||
DeleteHistDriver removes a histogram memory driver from memory. It will
|
||||
automatically try and call Freeprivate in order to remove driver specific
|
||||
data. Than an the rest is removed. After this call self will point to
|
||||
rubbish.
|
||||
|
||||
|
||||
\subsubsection{The histogram memory object}
|
||||
Most of the HM data will be held with the driver as it is needed there for
|
||||
performing operations. Accordingly the datastructure associated with the
|
||||
histogram memory object is fairly simple:
|
||||
\begin{flushleft} \small
|
||||
\begin{minipage}{\linewidth} \label{scrap5}
|
||||
$\langle$HistST {\footnotesize ?}$\rangle\equiv$
|
||||
\vspace{-1ex}
|
||||
\begin{list}{}{} \item
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@ typedef struct __HistMem {@\\
|
||||
\mbox{}\verb@ pObjectDescriptor pDes;@\\
|
||||
\mbox{}\verb@ int iAccess;@\\
|
||||
\mbox{}\verb@ int iExponent;@\\
|
||||
\mbox{}\verb@ pHistDriver pDriv;@\\
|
||||
\mbox{}\verb@ int iInit;@\\
|
||||
\mbox{}\verb@ pICountable pCountInt;@\\
|
||||
\mbox{}\verb@ pICallBack pCall;@\\
|
||||
\mbox{}\verb@ pStringDict pOption;@\\
|
||||
\mbox{}\verb@ HistInt *iLocalData;@\\
|
||||
\mbox{}\verb@ int iLocalLength;@\\
|
||||
\mbox{}\verb@ int iLocalUpdate;@\\
|
||||
\mbox{}\verb@ time_t tLocal;@\\
|
||||
\mbox{}\verb@ int iUpdateIntervall;@\\
|
||||
\mbox{}\verb@ } HistMem;@\\
|
||||
\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}
|
||||
According to the general Sics object interface the first field is the object
|
||||
descriptor. Note, that the histogram memory has to adhere to the countable
|
||||
objects interface. iAccess is the access code used to control user
|
||||
interaction with the HM. iExponent is the force of 10 used for calculating
|
||||
the actual preset value for counting in monitor mode.
|
||||
However, note, that all configuration commands will
|
||||
require Manager privilege at least. Then there is a pointer to the
|
||||
driver followed by pointers to the interfaces implemented by the histogram
|
||||
memory. pOption is a string dictionary of configuration options for the
|
||||
histogram memory.
|
||||
|
||||
In order to save network bandwidth and for efficiency the histogram memory
|
||||
object buffers the histogram memory in memory. The histogram itself resides
|
||||
in iLocalData. iLocalLength is the length of iLocalData. iLocalUpdate is a
|
||||
flag which will be set when counting operations (histogram changes ) are
|
||||
going on and cleared when the histogram has been completely read.
|
||||
When counting the local data will be updated only at certain intervalls.
|
||||
This is a configuration option. iUpdateIntervall is that intervall in
|
||||
seconds, tLocal is the time for the next scheduled update.
|
||||
|
||||
|
||||
The interaction with the histogram memory can be classified into four
|
||||
groups: basic initialisation and destruction, configuration, counting and
|
||||
data retrieval. The first group to look at are the basics:
|
||||
|
||||
\begin{flushleft} \small
|
||||
\begin{minipage}{\linewidth} \label{scrap6}
|
||||
$\langle$Protos {\footnotesize ?}$\rangle\equiv$
|
||||
\vspace{-1ex}
|
||||
\begin{list}{}{} \item
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@ pHistMem CreateHistMemory(char *drivername);@\\
|
||||
\mbox{}\verb@ void DeleteHistMemory(void *self);@\\
|
||||
\mbox{}\verb@@$\diamond$
|
||||
\end{list}
|
||||
\vspace{-1ex}
|
||||
\footnotesize\addtolength{\baselineskip}{-1ex}
|
||||
\begin{list}{}{\setlength{\itemsep}{-\parsep}\setlength{\itemindent}{-\leftmargin}}
|
||||
\item Macro defined by scraps ?, ?, ?, ?, ?.
|
||||
\item Macro referenced in scrap ?.
|
||||
\end{list}
|
||||
\end{minipage}\\[4ex]
|
||||
\end{flushleft}
|
||||
CreateHistMem creates a new histogram memory.
|
||||
On error this
|
||||
call returns NULL. On success a pointer to the new histogram memory object.
|
||||
CreateHistMem does NOT configure anything! A driver gets selected according
|
||||
to the driver name.
|
||||
|
||||
DeleteHistMemory removes a histogram memory from computer memory.
|
||||
Any references to self afterwards will
|
||||
point to rubbish.
|
||||
|
||||
The next group of functions refer to configuration.
|
||||
\begin{flushleft} \small
|
||||
\begin{minipage}{\linewidth} \label{scrap7}
|
||||
$\langle$Protos {\footnotesize ?}$\rangle\equiv$
|
||||
\vspace{-1ex}
|
||||
\begin{list}{}{} \item
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@ int HistGetOption(pHistMem self, char *name, char *result, int iResultLen);@\\
|
||||
\mbox{}\verb@ int HistSetOption(pHistMem self, char *name, char *value);@\\
|
||||
\mbox{}\verb@ int HistConfigure(pHistMem self, SConnection *pCon, SicsInterp *pSics);@\\
|
||||
\mbox{}\verb@@$\diamond$
|
||||
\end{list}
|
||||
\vspace{-1ex}
|
||||
\footnotesize\addtolength{\baselineskip}{-1ex}
|
||||
\begin{list}{}{\setlength{\itemsep}{-\parsep}\setlength{\itemindent}{-\leftmargin}}
|
||||
\item Macro defined by scraps ?, ?, ?, ?, ?.
|
||||
\item Macro referenced in scrap ?.
|
||||
\end{list}
|
||||
\end{minipage}\\[4ex]
|
||||
\end{flushleft}
|
||||
HistGetOption caters for the retrieval of the current option given in name.
|
||||
Maximum iResultLen characters of result will be copied into result, or an
|
||||
error message if things go wrong.
|
||||
|
||||
HistSetOption sets the option name to value specified in value. No error
|
||||
checking except availability of the option and permission is done here.
|
||||
|
||||
HistConfigure updates the internal datastructures from the dictionary and
|
||||
does the actual configuration of the HM. Tons of error messages will be
|
||||
printed to pCon.
|
||||
|
||||
Valid names for the options in the dictionary are all the names in the
|
||||
histogram datastructure. Please note, that counting options are handled
|
||||
separately (see below). Additionally there may be driver specific options
|
||||
available. For iDim iRank numbers are expected which represent the
|
||||
dimensions of the HM.
|
||||
|
||||
The functions for counting and manipulation of counting parameters have been
|
||||
separated from the rest of the configuration. The reason is that the main
|
||||
configuration will only be performed by highly privileged users, whereas
|
||||
the counting operations will be accessible by normal users. Counting is
|
||||
controlled by the following functions:
|
||||
\begin{flushleft} \small
|
||||
\begin{minipage}{\linewidth} \label{scrap8}
|
||||
$\langle$Protos {\footnotesize ?}$\rangle\equiv$
|
||||
\vspace{-1ex}
|
||||
\begin{list}{}{} \item
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@ float GetHistPreset(pHistMem self);@\\
|
||||
\mbox{}\verb@ int SetHistPreset(pHistMem self, float fVal);@\\
|
||||
\mbox{}\verb@ CounterMode GetHistCountMode(pHistMem self);@\\
|
||||
\mbox{}\verb@ int SetHistCountMode(pHistMem self, CounterMode eNew);@\\
|
||||
\mbox{}\verb@ long GetHistMonitor(pHistMem self, int i, SConnection *pCon);@\\
|
||||
\mbox{}\verb@ const float *GetHistTimeBin(pHistMem self, int *iLength);@\\
|
||||
\mbox{}\verb@ int GetHistLength(pHistMem self);@\\
|
||||
\mbox{}\verb@ int GetHistDim(pHistMem self, int iDim[MAXDIM], int *nDim);@\\
|
||||
\mbox{}\verb@ float GetHistCountTime(pHistMem self,SConnection *pCon);@\\
|
||||
\mbox{}\verb@ int HistDoCount(pHistMem self, SConnection *pCon);@\\
|
||||
\mbox{}\verb@ int HistBlockCount(pHistMem self, SConnection *pCon);@\\
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@@$\diamond$
|
||||
\end{list}
|
||||
\vspace{-1ex}
|
||||
\footnotesize\addtolength{\baselineskip}{-1ex}
|
||||
\begin{list}{}{\setlength{\itemsep}{-\parsep}\setlength{\itemindent}{-\leftmargin}}
|
||||
\item Macro defined by scraps ?, ?, ?, ?, ?.
|
||||
\item Macro referenced in scrap ?.
|
||||
\end{list}
|
||||
\end{minipage}\\[4ex]
|
||||
\end{flushleft}
|
||||
The first four functions are simple parameter enquiry and manipulation
|
||||
functions. GetHistMonitor returns the count on monitor number i for the
|
||||
histogram memory. This function returns a negative value when the value
|
||||
specified for i is invalid.
|
||||
|
||||
HistDoCount actually starts a counting operation. It will not
|
||||
block and wait for counting to finish. Please note, that many counting
|
||||
manipulation functions are hidden in the functions of the countable
|
||||
interface, which the HM has to implement.
|
||||
|
||||
HistBlockCount also starts counting. But will block until counting has
|
||||
finished.
|
||||
|
||||
Another set of functions is needed for manipulation of the data in the
|
||||
histogram memory:
|
||||
\begin{flushleft} \small
|
||||
\begin{minipage}{\linewidth} \label{scrap9}
|
||||
$\langle$Protos {\footnotesize ?}$\rangle\equiv$
|
||||
\vspace{-1ex}
|
||||
\begin{list}{}{} \item
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@ int SetHistogram(pHistMem self, SConnection *pCon,@\\
|
||||
\mbox{}\verb@ int i,int iStart, int iEnd, HistInt *lData);@\\
|
||||
\mbox{}\verb@ int GetHistogram(pHistMem self, SConnection *pCon,@\\
|
||||
\mbox{}\verb@ int i,int iStart, int iEnd, HistInt *lData, int iDataLen);@\\
|
||||
\mbox{}\verb@ HistInt *GetHistogramPointer(pHistMem self,SConnection *pCon);@\\
|
||||
\mbox{}\verb@ int PresetHistogram(pHistMem self, SConnection *pCon, HistInt lVal);@\\
|
||||
\mbox{}\verb@@$\diamond$
|
||||
\end{list}
|
||||
\vspace{-1ex}
|
||||
\footnotesize\addtolength{\baselineskip}{-1ex}
|
||||
\begin{list}{}{\setlength{\itemsep}{-\parsep}\setlength{\itemindent}{-\leftmargin}}
|
||||
\item Macro defined by scraps ?, ?, ?, ?, ?.
|
||||
\item Macro referenced in scrap ?.
|
||||
\end{list}
|
||||
\end{minipage}\\[4ex]
|
||||
\end{flushleft}
|
||||
For histogram I/O the following aproach has been taken: Histograms are kept
|
||||
as linear arrays of data regardless of the layout of the detector. It is the
|
||||
task of upper level code to map the right histogram to the right position.
|
||||
This aproach was choosen for two reasons: 1.) simplification of interface,
|
||||
2.) easier to retrieve smaller chunks of data at a time.
|
||||
|
||||
With both SetHistogram and GetHistogram the parameter i denotes the
|
||||
histogram to retrieve. A value of -1 retrieves the whole lot. iStart and
|
||||
iEnd allow for extraction of a subset of a histogram. These values get
|
||||
ignored when trying to retrieve a whole HM content. These routines
|
||||
perform conversion to and from long to the binwidth of the HM. SetHistogram
|
||||
initialises the HM from the lData provided. GetHistogram reads an histogram
|
||||
into lData but maximum iDataLen items. PresetHistogram presets the HM to the
|
||||
value lVal. Can be used to clear the HM.
|
||||
|
||||
The histogram memory object buffers the histograms for a adjustable
|
||||
period of time. GetHistogramPointer retrieves a pointer to the local
|
||||
histogram buffer. It also makes sure, that the histogram has been
|
||||
updated if appropriate. This is provided for efficiency and saves some
|
||||
memory copying and duplication of data during operations. Thus memory
|
||||
consumption can be reduced. However, the drawback is that you mess
|
||||
directly with the histogram memory content which is potentially
|
||||
dangerous. Use this method with great care!
|
||||
|
||||
|
||||
A last group of functions are those needed to interface to the Sics
|
||||
interpreter:
|
||||
\begin{flushleft} \small
|
||||
\begin{minipage}{\linewidth} \label{scrap10}
|
||||
$\langle$Protos {\footnotesize ?}$\rangle\equiv$
|
||||
\vspace{-1ex}
|
||||
\begin{list}{}{} \item
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@ int MakeHistMemory(SConnection *pCon, SicsInterp *pSics, void *pData,@\\
|
||||
\mbox{}\verb@ int argc, char *argv[]);@\\
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@ int HistAction(SConnection *pCon, SicsInterp *pSics, void *pData,@\\
|
||||
\mbox{}\verb@ int argc, char *argv[]);@\\
|
||||
\mbox{}\verb@ @\\
|
||||
\mbox{}\verb@@$\diamond$
|
||||
\end{list}
|
||||
\vspace{-1ex}
|
||||
\footnotesize\addtolength{\baselineskip}{-1ex}
|
||||
\begin{list}{}{\setlength{\itemsep}{-\parsep}\setlength{\itemindent}{-\leftmargin}}
|
||||
\item Macro defined by scraps ?, ?, ?, ?, ?.
|
||||
\item Macro referenced in scrap ?.
|
||||
\end{list}
|
||||
\end{minipage}\\[4ex]
|
||||
\end{flushleft}
|
||||
MakeHistMem is supposed to be called with two parameters: name and driver
|
||||
which denote the name of the HM object and the type of driver to use. If all
|
||||
is well, this call will create a command named name. Remember, that
|
||||
the HM is
|
||||
not yet configured!
|
||||
|
||||
HistAction is supposed to be where the action goes. HistAction understands
|
||||
the commands:\begin{itemize}
|
||||
\item {\bf name config option value} sets a configuration option.
|
||||
\item {\bf name init} configures the HM.
|
||||
\item {\bf name Preset val} returns the preset value if val is missing, else
|
||||
it sets it.
|
||||
\item {\bf name Mode val} returns the counting mode if val is missing, else
|
||||
it sets it.
|
||||
\item {\bf name count} starts a counting operation.
|
||||
\item {\bf name get number} gets histogram number. -1 as histogram number
|
||||
gets all.
|
||||
\item {\bf name set number val........} sets histogram number to the values
|
||||
following.
|
||||
\item {\bf name clear val} sets all the HM to val.
|
||||
\end{itemize}
|
||||
|
||||
\begin{flushleft} \small
|
||||
\begin{minipage}{\linewidth} \label{scrap11}
|
||||
\verb@"HistMem.h"@ {\footnotesize ? }$\equiv$
|
||||
\vspace{-1ex}
|
||||
\begin{list}{}{} \item
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@/*--------------------------------------------------------------------------@\\
|
||||
\mbox{}\verb@ H I S T M E M @\\
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@ header for the histogram memory object for SICS.@\\
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@ copyright: see implementation file.@\\
|
||||
\mbox{}\verb@ Mark Koennecke, April 1997@\\
|
||||
\mbox{}\verb@-----------------------------------------------------------------------------*/@\\
|
||||
\mbox{}\verb@#ifndef SICSHISTMEM@\\
|
||||
\mbox{}\verb@#define SICSHISTMEM@\\
|
||||
\mbox{}\verb@#define MAXDIM 3@\\
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@ typedef struct __HistDriver *pHistDriver;@\\
|
||||
\mbox{}\verb@ typedef struct __HistMem *pHistMem;@\\
|
||||
\mbox{}\verb@/*-------------------------------------------------------------------------*/@\\
|
||||
\mbox{}\verb@ typedef int HistInt;@\\
|
||||
\mbox{}\verb@/*@\\
|
||||
\mbox{}\verb@ 32 bit integer on a DigitalUnix@\\
|
||||
\mbox{}\verb@*/@\\
|
||||
\mbox{}\verb@@$\langle$Modes {\footnotesize ?, \ldots\ }$\rangle$\verb@@\\
|
||||
\mbox{}\verb@/*--------------------------------------------------------------------------*/@\\
|
||||
\mbox{}\verb@@$\langle$Protos {\footnotesize ?, \ldots\ }$\rangle$\verb@@\\
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@#endif@\\
|
||||
\mbox{}\verb@@$\diamond$
|
||||
\end{list}
|
||||
\vspace{-2ex}
|
||||
\end{minipage}\\[4ex]
|
||||
\end{flushleft}
|
||||
\begin{flushleft} \small
|
||||
\begin{minipage}{\linewidth} \label{scrap12}
|
||||
\verb@"HistDriv.i"@ {\footnotesize ? }$\equiv$
|
||||
\vspace{-1ex}
|
||||
\begin{list}{}{} \item
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@/*---------------------------------------------------------------------------@\\
|
||||
\mbox{}\verb@ H I S T D R I V@\\
|
||||
\mbox{}\verb@ internal header file which includes the definition of the Histogram memory@\\
|
||||
\mbox{}\verb@ driver structure.@\\
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@ Mark Koennecke, April 1997@\\
|
||||
\mbox{}\verb@----------------------------------------------------------------------------*/@\\
|
||||
\mbox{}\verb@#ifndef SICSHISTDRIV@\\
|
||||
\mbox{}\verb@#define SICSHISTDRIV@\\
|
||||
\mbox{}\verb@#define MAXCHAN 4096@\\
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@@$\langle$HistType {\footnotesize ?}$\rangle$\verb@@\\
|
||||
\mbox{}\verb@@$\langle$HistDrivProt {\footnotesize ?}$\rangle$\verb@@\\
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@#endif@\\
|
||||
\mbox{}\verb@@$\diamond$
|
||||
\end{list}
|
||||
\vspace{-2ex}
|
||||
\end{minipage}\\[4ex]
|
||||
\end{flushleft}
|
||||
\begin{flushleft} \small
|
||||
\begin{minipage}{\linewidth} \label{scrap13}
|
||||
\verb@"HistMem.i"@ {\footnotesize ? }$\equiv$
|
||||
\vspace{-1ex}
|
||||
\begin{list}{}{} \item
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@/*---------------------------------------------------------------------------@\\
|
||||
\mbox{}\verb@ H I S T M E M -- Internal@\\
|
||||
\mbox{}\verb@ internal header file which includes the definition of the Histogram memory@\\
|
||||
\mbox{}\verb@ data structure.@\\
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@ Mark Koennecke, April 1997@\\
|
||||
\mbox{}\verb@----------------------------------------------------------------------------*/@\\
|
||||
\mbox{}\verb@#ifndef SICSHISTMEMINT@\\
|
||||
\mbox{}\verb@#define SICSHISTMEMINT@\\
|
||||
\mbox{}\verb@@$\langle$HistST {\footnotesize ?}$\rangle$\verb@@\\
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@#endif@\\
|
||||
\mbox{}\verb@@$\diamond$
|
||||
\end{list}
|
||||
\vspace{-2ex}
|
||||
\end{minipage}\\[4ex]
|
||||
\end{flushleft}
|
||||
50
doc/programmer/histsim.tex
Normal file
50
doc/programmer/histsim.tex
Normal file
@@ -0,0 +1,50 @@
|
||||
\subsubsection{Simulated histogram memory driver}
|
||||
This is a driver for a simulated histogram memory needed for software
|
||||
testing.
|
||||
|
||||
\begin{flushleft} \small
|
||||
\begin{minipage}{\linewidth} \label{scrap1}
|
||||
$\langle$Protos {\footnotesize ?}$\rangle\equiv$
|
||||
\vspace{-1ex}
|
||||
\begin{list}{}{} \item
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@ pHistDriver CreateSIMHM(pStringDict pOpt);@\\
|
||||
\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 only visible function defined is a creation function. Please note that
|
||||
all the interface functions need to be defined as well. For implementation
|
||||
of the countable interface this thing will use the simulated counter. All
|
||||
data retrieval members will return random numbers in the required amount.
|
||||
The call to configure will actually do nothing.
|
||||
|
||||
\begin{flushleft} \small
|
||||
\begin{minipage}{\linewidth} \label{scrap2}
|
||||
\verb@"histsim.h"@ {\footnotesize ? }$\equiv$
|
||||
\vspace{-1ex}
|
||||
\begin{list}{}{} \item
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@/*--------------------------------------------------------------------------@\\
|
||||
\mbox{}\verb@ H I S T S I M@\\
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@ A simulated histogram memory for software testing.@\\
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@ Mark Koennecke, April 1997@\\
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@ copyright: see implementation file.@\\
|
||||
\mbox{}\verb@---------------------------------------------------------------------------*/@\\
|
||||
\mbox{}\verb@#ifndef SICSHISTSIM@\\
|
||||
\mbox{}\verb@#define SICSHISTSIM@\\
|
||||
\mbox{}\verb@@$\langle$Protos {\footnotesize ?}$\rangle$\verb@@\\
|
||||
\mbox{}\verb@#endif@\\
|
||||
\mbox{}\verb@@$\diamond$
|
||||
\end{list}
|
||||
\vspace{-2ex}
|
||||
\end{minipage}\\[4ex]
|
||||
\end{flushleft}
|
||||
216
doc/programmer/hkl.tex
Normal file
216
doc/programmer/hkl.tex
Normal file
@@ -0,0 +1,216 @@
|
||||
\subsection{Crystallographic Computations}
|
||||
The HKL object performs standard four circle calculations. I.e., given a UB
|
||||
matrix it calculates the four circle diffractometer setting angles required
|
||||
for a reflection with index hkl. The UB must be determined from a set of
|
||||
reflections found manually or automatically. This is done in an offline
|
||||
program. The code in this module is a direct reimplementation of fortran code
|
||||
provided by Jean Allibon, ILL with the MAD four circle diffractometer
|
||||
control program in ANSI-C. For theory, see the contribution by
|
||||
W.C. Hamilton in the International Tables for Crystallography, 1974 edition.
|
||||
|
||||
The object uses the following object data structure:
|
||||
\begin{flushleft} \small
|
||||
\begin{minipage}{\linewidth} \label{scrap1}
|
||||
$\langle$hkldat {\footnotesize ?}$\rangle\equiv$
|
||||
\vspace{-1ex}
|
||||
\begin{list}{}{} \item
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@ typedef struct __HKL {@\\
|
||||
\mbox{}\verb@ pObjectDescriptor pDes;@\\
|
||||
\mbox{}\verb@ double fUB[9];@\\
|
||||
\mbox{}\verb@ MATRIX UBinv;@\\
|
||||
\mbox{}\verb@ double fLambda;@\\
|
||||
\mbox{}\verb@ int iManual;@\\
|
||||
\mbox{}\verb@ double fLastHKL[5];@\\
|
||||
\mbox{}\verb@ int iNOR;@\\
|
||||
\mbox{}\verb@ int iQuad;@\\
|
||||
\mbox{}\verb@ pMotor pTheta;@\\
|
||||
\mbox{}\verb@ pMotor pOmega;@\\
|
||||
\mbox{}\verb@ pMotor pChi;@\\
|
||||
\mbox{}\verb@ pMotor pPhi;@\\
|
||||
\mbox{}\verb@ pMotor pNu;@\\
|
||||
\mbox{}\verb@ pSelVar pMono;@\\
|
||||
\mbox{}\verb@ long lID;@\\
|
||||
\mbox{}\verb@ } HKL;@\\
|
||||
\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 fields are more or less self explaining:
|
||||
\begin{description}
|
||||
\item[pDes] The standard object descriptor.
|
||||
\item[fUB] The UB matrix.
|
||||
\item[iUB] is a flag which spcifies if a UB is specified.
|
||||
\item[fLambda] The wavelength of the neutrons.
|
||||
\item[iManual] A flag which defines if the wavelength has been set manually
|
||||
or is updated automatically from a wavelength variable.
|
||||
\item[fLastHKL] the HKL of the last reflection calculated.
|
||||
\item[iNor] a flag for normal beam calculation mode.
|
||||
\item[pTheta] The two theta motor. All motor are needed for boundary
|
||||
checking.
|
||||
\item[pOmega] The omega axis motor.
|
||||
\item[pChi] The chi axis motor.
|
||||
\item[pPhi] the phi axis motor.
|
||||
\item[pNu] the nu axis motor for normal beam geometry.
|
||||
This is detector tilt.
|
||||
\item[pMono] The selector variable doing the wavelength.
|
||||
\end{description}
|
||||
|
||||
The wavelength is a bit tricky. As it would be to time consuming to read two
|
||||
motors each time a calculation is performed, the lambda variable is updated
|
||||
by registering a callback with the selector variable handling the
|
||||
monochromator wavelength. As TriCS will be run with two monochromators on a
|
||||
lift a means has to be provided to change the selector variable online. An
|
||||
additonal feature is that the wavelength can be manipulated manually. This
|
||||
adresses the issue that automatic wavelength may be inaccurate due to
|
||||
lazy instrument scientists not adjusting their instruments.
|
||||
|
||||
In terms of an interface the following functions will be provided by this
|
||||
module:
|
||||
|
||||
\begin{flushleft} \small
|
||||
\begin{minipage}{\linewidth} \label{scrap2}
|
||||
$\langle$hklint {\footnotesize ?}$\rangle\equiv$
|
||||
\vspace{-1ex}
|
||||
\begin{list}{}{} \item
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@ typedef struct __HKL *pHKL;@\\
|
||||
\mbox{}\verb@/*-------------------------------------------------------------------------*/@\\
|
||||
\mbox{}\verb@ pHKL CreateHKL(pMotor pTheta, pMotor pOmega, @\\
|
||||
\mbox{}\verb@ pMotor pChi, pMotor pPhi, pMotor pNu);@\\
|
||||
\mbox{}\verb@ void DeleteHKL(void *pData);@\\
|
||||
\mbox{}\verb@ @\\
|
||||
\mbox{}\verb@ int HKLFactory(SConnection *pCon, SicsInterp *pSics, void *pData,@\\
|
||||
\mbox{}\verb@ int argc, char *argv[]);@\\
|
||||
\mbox{}\verb@/*------------------------------------------------------------------------*/@\\
|
||||
\mbox{}\verb@ int SetWavelengthVariable(SConnection *pCon, pHKL self, pSelVar pVar);@\\
|
||||
\mbox{}\verb@ int SetWavelengthManual(pHKL self, float fVal);@\\
|
||||
\mbox{}\verb@ int SetUB(pHKL self, float fUB[9]);@\\
|
||||
\mbox{}\verb@ int GetUB(pHKL self, float fUB[9]);@\\
|
||||
\mbox{}\verb@ int SetNOR(pHKL self, int iNOB);@\\
|
||||
\mbox{}\verb@ int GetLambda(pHKL self, float *fVal);@\\
|
||||
\mbox{}\verb@ int GetCurrentHKL(pHKL self, float fVal[3]);@\\
|
||||
\mbox{}\verb@ int GetCurrentPosition(pHKL self, SConnection *pCon, float fPosition[4]);@\\
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@ int CalculateSettings(pHKL self, float fHKL[3], float fPsi, int iHamil,@\\
|
||||
\mbox{}\verb@ float fSet[4],SConnection *pCon);@\\
|
||||
\mbox{}\verb@ int RunHKL(pHKL self, float fHKL[3], float fPsi, int iHamil, SConnection@\\
|
||||
\mbox{}\verb@ *pCon);@\\
|
||||
\mbox{}\verb@ int DriveHKL(pHKL self, float fHKL[3], float fPsi, int iHamil,@\\
|
||||
\mbox{}\verb@ SConnection *pCon);@\\
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@ int DriveSettings(pHKL self, float fSet[4],SConnection *pCon);@\\
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@ int HKLAction(SConnection *pCon, SicsInterp *pSics, void *pData,@\\
|
||||
\mbox{}\verb@ int argc, char *argv[]); @\\
|
||||
\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}
|
||||
All functions return 0 on failure, 1 on success if not stated otherwise.
|
||||
Most functions take a pointer to a HKL data structure as first parameter.
|
||||
The function in more detail:
|
||||
\begin{description}
|
||||
\item[CreateHKL] creates a HKL object. The parameters are pointers to the
|
||||
four four circle motors. Returns NULL on failure, a pointer to the new
|
||||
object on success.
|
||||
\item[DeleteHKL] properly removes an HKL object from the system.
|
||||
\item[HKLFactory] The factory function which initialises an HKL object from
|
||||
the initialisation script.
|
||||
\item[SetWavelengthVariable] sets a new wavelength variable. Installs all
|
||||
necesarry callbacks for automatic update.
|
||||
\item[SetWaveLengthManual] deinstall all callbacks and forces the wavelength
|
||||
to the value specified a second parameter.
|
||||
\item[SetUB] sets the UB matrix.
|
||||
\item[SetNOR] sets the normal beam calculation flag to iNOR.
|
||||
\item[CalculateSettings] is the heart of this all. As the name suggests
|
||||
calculates the settings for a four circle diffractometer. The parameters
|
||||
are:
|
||||
\begin{description}
|
||||
\item[self] A pointer to a HKL data structure.
|
||||
\item[fHKL] The reflection indices to calculate the settings for.
|
||||
\item[fPsi] The psi value for the reflection. For psi scans. Set to 0 if not
|
||||
used.
|
||||
\item[iHamil] The index of the hamilton position to calculate. Can be an
|
||||
integer between 0 to 8. 0 denotes the normal case.
|
||||
\item[fSet] contains the required settings if the function returns with
|
||||
success. 0 = two theta, 1 = omega, 2 = chi, 3 = phi.
|
||||
\end{description}
|
||||
The function returns 1 on success, a negative value on failure. Possible
|
||||
error returns are:
|
||||
\begin{description}
|
||||
\item[HKLIMPOSSIBLE] the calculation was impossible.
|
||||
\item[HKLTHETALIMIT] a setting could be calculated but can not be accessed
|
||||
due to a limit on two theta.
|
||||
\end{description}
|
||||
\item[DriveHKL] calculates a setting and drives to the position. The
|
||||
parameters are the same as with CalculateSettings. With the addition of a
|
||||
pointer to the connection object doing the command for error messages and
|
||||
everything. The error returns are the same as with CalculateSettings
|
||||
well. With the addition of HKJMOTFAIL, which means that a motor failed to
|
||||
drive properly.
|
||||
\item[DriveSettings] drives to the the settings given in fSet.
|
||||
\item[HKLAction] is the interpreter wrapper function for the HKL object.
|
||||
\end{description}
|
||||
|
||||
\begin{flushleft} \small
|
||||
\begin{minipage}{\linewidth} \label{scrap3}
|
||||
\verb@"hkl.i"@ {\footnotesize ? }$\equiv$
|
||||
\vspace{-1ex}
|
||||
\begin{list}{}{} \item
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@/*-------------------------------------------------------------------------@\\
|
||||
\mbox{}\verb@ H K L@\\
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@ Internal data structure description. See hkl.h, c,w for more details.@\\
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@ Mark Koennecke, February 1998@\\
|
||||
\mbox{}\verb@----------------------------------------------------------------------------*/@\\
|
||||
\mbox{}\verb@@$\langle$hkldat {\footnotesize ?}$\rangle$\verb@@\\
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@@$\diamond$
|
||||
\end{list}
|
||||
\vspace{-2ex}
|
||||
\end{minipage}\\[4ex]
|
||||
\end{flushleft}
|
||||
\begin{flushleft} \small
|
||||
\begin{minipage}{\linewidth} \label{scrap4}
|
||||
\verb@"hkl.h"@ {\footnotesize ? }$\equiv$
|
||||
\vspace{-1ex}
|
||||
\begin{list}{}{} \item
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@/*---------------------------------------------------------------------------@\\
|
||||
\mbox{}\verb@ H K L@\\
|
||||
\mbox{}\verb@ This SICS object performs angle setting calculations for a four circle @\\
|
||||
\mbox{}\verb@ diffractometer. The heart of this code is a C transcriptions of routines@\\
|
||||
\mbox{}\verb@ written by Jean Allibon at ILL for the MAD program. Theory is explained in@\\
|
||||
\mbox{}\verb@ the article by W. C. Hamilton in International Tables for Crystallography,@\\
|
||||
\mbox{}\verb@ 1974 edition.@\\
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@ copyright: see copyright.h@\\
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@ Mark Koennecke, February 1998@\\
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@----------------------------------------------------------------------------*/@\\
|
||||
\mbox{}\verb@#ifndef SICSHKL@\\
|
||||
\mbox{}\verb@#define SICSHKL@\\
|
||||
\mbox{}\verb@#include "selector.h"@\\
|
||||
\mbox{}\verb@#include "selvar.h"@\\
|
||||
\mbox{}\verb@@$\langle$hklint {\footnotesize ?}$\rangle$\verb@@\\
|
||||
\mbox{}\verb@#endif @\\
|
||||
\mbox{}\verb@@$\diamond$
|
||||
\end{list}
|
||||
\vspace{-2ex}
|
||||
\end{minipage}\\[4ex]
|
||||
\end{flushleft}
|
||||
111
doc/programmer/hklscan.tex
Normal file
111
doc/programmer/hklscan.tex
Normal file
@@ -0,0 +1,111 @@
|
||||
\subsection{hklscan}
|
||||
hklscan is an object which implements scanning in reciprocal space. It belongs
|
||||
to the four circle diffraction line of commands. It requires the hkl object
|
||||
for doing four circle calculations and a scan object for doing the scanning.
|
||||
The scan object is configured by overloading its WriteScanPoints and
|
||||
ScanDrive functions to do the right thing for this. Thus most of the work
|
||||
is done in scan and hkl.
|
||||
|
||||
hklscan has its own data structure looking like this:
|
||||
|
||||
\begin{flushleft} \small
|
||||
\begin{minipage}{\linewidth} \label{scrap1}
|
||||
$\langle$hklscandat {\footnotesize ?}$\rangle\equiv$
|
||||
\vspace{-1ex}
|
||||
\begin{list}{}{} \item
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@ typedef struct __HKLSCAN {@\\
|
||||
\mbox{}\verb@ pObjectDescriptor pDes;@\\
|
||||
\mbox{}\verb@ pScanData pScan;@\\
|
||||
\mbox{}\verb@ pHKL pCalc; @\\
|
||||
\mbox{}\verb@ float fStart[3];@\\
|
||||
\mbox{}\verb@ float fStep[3];@\\
|
||||
\mbox{}\verb@ float fPos[3];@\\
|
||||
\mbox{}\verb@ } sHklscan;@\\
|
||||
\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}
|
||||
\begin{description}
|
||||
\item[pDes] The standard object descriptor.
|
||||
\item[pScan] The scan object used for scanning.
|
||||
\item[pCalc] The hkl object used for crystallographic computations.
|
||||
\item[fStart] The start values in H, K, L for scanning.
|
||||
\item[fStep] The step width in H, K, L.
|
||||
\item[fPos] The last position in H, K, L.
|
||||
\end{description}
|
||||
|
||||
The hklscan object defines the following external interface:
|
||||
|
||||
\begin{flushleft} \small
|
||||
\begin{minipage}{\linewidth} \label{scrap2}
|
||||
$\langle$hklscanfunc {\footnotesize ?}$\rangle\equiv$
|
||||
\vspace{-1ex}
|
||||
\begin{list}{}{} \item
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@ typedef struct __HKLSCAN *pHklscan;@\\
|
||||
\mbox{}\verb@/*--------------------------------------------------------------------------*/@\\
|
||||
\mbox{}\verb@ int HklScan(pHklscan self, SConnection *pCon, int iNP, int iMode,@\\
|
||||
\mbox{}\verb@ float fPreset);@\\
|
||||
\mbox{}\verb@/*---------------- interpreter functions -----------------------------------*/@\\
|
||||
\mbox{}\verb@ int HklscanFactory(SConnection *pCon, SicsInterp *pSics, void *pData,@\\
|
||||
\mbox{}\verb@ int argc, char *argv[]);@\\
|
||||
\mbox{}\verb@ int HklscanAction(SConnection *pCon, SicsInterp *pSics, void *pData,@\\
|
||||
\mbox{}\verb@ int argc, char *argv[]);@\\
|
||||
\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}
|
||||
\begin{flushleft} \small
|
||||
\begin{minipage}{\linewidth} \label{scrap3}
|
||||
\verb@"hklscan.i"@ {\footnotesize ? }$\equiv$
|
||||
\vspace{-1ex}
|
||||
\begin{list}{}{} \item
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@/*-------------------------------------------------------------------------@\\
|
||||
\mbox{}\verb@ Internal data structure for the hklscan object. DO NOT MODIFY. @\\
|
||||
\mbox{}\verb@ Modifications only in hklscan.i@\\
|
||||
\mbox{}\verb@ @\\
|
||||
\mbox{}\verb@ Mark Koennecke, June 1999@\\
|
||||
\mbox{}\verb@--------------------------------------------------------------------------*/@\\
|
||||
\mbox{}\verb@@$\langle$hklscandat {\footnotesize ?}$\rangle$\verb@@\\
|
||||
\mbox{}\verb@@$\diamond$
|
||||
\end{list}
|
||||
\vspace{-2ex}
|
||||
\end{minipage}\\[4ex]
|
||||
\end{flushleft}
|
||||
\begin{flushleft} \small
|
||||
\begin{minipage}{\linewidth} \label{scrap4}
|
||||
\verb@"hklscan.h"@ {\footnotesize ? }$\equiv$
|
||||
\vspace{-1ex}
|
||||
\begin{list}{}{} \item
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@/*--------------------------------------------------------------------------@\\
|
||||
\mbox{}\verb@ H K L S C A N@\\
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@ A class for doing scans in reciprocal space. This makes only sense at an@\\
|
||||
\mbox{}\verb@ four circle diffractometer. Most of the work is done in the HKL and scan@\\
|
||||
\mbox{}\verb@ objects. This class just adapts and used both objects to do the right thing.@\\
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@ Mark Koennecke, June 1999@\\
|
||||
\mbox{}\verb@---------------------------------------------------------------------------*/@\\
|
||||
\mbox{}\verb@#ifndef HKLSCAN@\\
|
||||
\mbox{}\verb@#define HKLSCAN@\\
|
||||
\mbox{}\verb@@$\langle$hklscanfunc {\footnotesize ?}$\rangle$\verb@@\\
|
||||
\mbox{}\verb@#endif@\\
|
||||
\mbox{}\verb@@$\diamond$
|
||||
\end{list}
|
||||
\vspace{-2ex}
|
||||
\end{minipage}\\[4ex]
|
||||
\end{flushleft}
|
||||
32
doc/programmer/ini.tex
Normal file
32
doc/programmer/ini.tex
Normal file
@@ -0,0 +1,32 @@
|
||||
\subsection{Initialisation file management}
|
||||
This module supports initialisation files with a simple structure.
|
||||
This is used to hold the internal SICS server options which are
|
||||
installed with the SicsOption initialisation commands. All the file
|
||||
handling stuff is dead code not used by SICS as of current. Any line
|
||||
is intended to
|
||||
contain one name value pair separated by an equlity sign. Lines beginning
|
||||
with a \verb+#+ are treated as comments, other lines not conforming to the name =
|
||||
value scheme are ignored. Another option (and the currently preferred one)
|
||||
to get values into the initialisation database is to use a special command
|
||||
SicsOption from the SICS initialisation file.
|
||||
These initialisation files are manipulated through
|
||||
the ifile module, implemented in ifile.h and ifile.c. The class in more
|
||||
detail:
|
||||
|
||||
|
||||
After reading the configuration options are stored in memory as a linked list with entries if the type shown below. \begin{verbatim}
|
||||
typedef struct __IFileE
|
||||
{
|
||||
char *name;
|
||||
char *value;
|
||||
struct __IFileE *pNext;
|
||||
} IPair;
|
||||
\end{verbatim}
|
||||
This datastructure is manipulated using the following functions:\begin{itemize}
|
||||
\item {\bf IPair *IFReadConfigFile(FILE *fp) }, expects as input a pointer to the configuration file. Than the function will read the file and initialise the configuration linked list from the data found in the file. On success a pointer to the head of the linked list is returned which is to be used in further calls to the configuration management functions. On failure NULL is returned.
|
||||
\item {\bf char *IFindOption(IPair *pList,char *name) }. Input is a pointer to a configuration list as returned by IFReadConfigFile and the name of the option requested (case sensitive). If this option exists a pointer to its value will be returned, else NULL. Never, ever, free the returned pointer as it belongs to this module.
|
||||
\item {\bf IPair *IFAddOption(IPair *pList,char *name, char *value) } Adds a name value pair to the list specified as first parameter. Returns a pointer to the new list including the new name value pair on succes, else the old pointer specified as input.
|
||||
\item {\bf int IFSaveOptions(IPair *pList,FILE *fp) }. Saves the options in the list to the file fp.
|
||||
\item {\bf void IFDeleteOptions(IPair *pList) }. Use this to delete the list after use. The list pList is no longer valid after this call. Omission of this call will result in wasted memory.
|
||||
\end{itemize}
|
||||
|
||||
52
doc/programmer/integrate.tex
Normal file
52
doc/programmer/integrate.tex
Normal file
@@ -0,0 +1,52 @@
|
||||
\subsection{Integrate}
|
||||
For four circle diffractometers it is usefull to be able to integrate the
|
||||
intensity of the peak from a collected counting profile. This module does
|
||||
just this. It uses the method as described by Grant \& Gabe in J. Appl. Cryst
|
||||
(1987), 11, 114-120. This method uses a moving window technique for finding
|
||||
the limits of the peak. This method was choosen for reason of its
|
||||
simplicity. The authors state, that the results are comparable to the
|
||||
Lehmann Larsen method used elsewhere. This is a utility module. Just a
|
||||
single function is implemented:
|
||||
|
||||
\begin{flushleft} \small
|
||||
\begin{minipage}{\linewidth} \label{scrap1}
|
||||
\verb@"integrate.h"@ {\footnotesize ? }$\equiv$
|
||||
\vspace{-1ex}
|
||||
\begin{list}{}{} \item
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@/*--------------------------------------------------------------------------@\\
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@ I N T E G R A T E@\\
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@ Peak integration follwing the method described by Grant & Gabe in@\\
|
||||
\mbox{}\verb@ J. Appl. Cryst (1978), 11, 114-120.@\\
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@ Mark Koennecke, March 1998@\\
|
||||
\mbox{}\verb@----------------------------------------------------------------------------*/@\\
|
||||
\mbox{}\verb@#ifndef GABEINTEGRATE@\\
|
||||
\mbox{}\verb@#define GABEINTEGRATE@\\
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@#define INTEGLEFT -1@\\
|
||||
\mbox{}\verb@#define INTEGRIGHT -2@\\
|
||||
\mbox{}\verb@#define INTEGNOPEAK -3@\\
|
||||
\mbox{}\verb@#define INTEGFUNNYBACK -4@\\
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@ int GabePeakIntegrate(int m, int iCounts, long lCounts[], @\\
|
||||
\mbox{}\verb@ float *fIntens, float *fVariance);@\\
|
||||
\mbox{}\verb@#endif@\\
|
||||
\mbox{}\verb@@$\diamond$
|
||||
\end{list}
|
||||
\vspace{-2ex}
|
||||
\end{minipage}\\[4ex]
|
||||
\end{flushleft}
|
||||
Input to this routine is the number of counts and the counts themselves.
|
||||
Then m, the number of lookahead points to use. As a result fIntens will
|
||||
contain the summed Intensity and fVariance the sigma of the summed
|
||||
intensity. The function retusn 1 for success or a negative error code in
|
||||
case of trouble. These error codes are:
|
||||
\begin{description}
|
||||
\item[INTEGLEFT] no left side background found.
|
||||
\item[INTEGRIGHT] nor right side background found.
|
||||
\item[INTEGNOPEAK] The data does not contain a peak.
|
||||
\item[INTEGFUNNYBACK] the data has a strange background.
|
||||
\end{description}
|
||||
69
doc/programmer/inter.tex
Normal file
69
doc/programmer/inter.tex
Normal file
@@ -0,0 +1,69 @@
|
||||
\subsection{The SICS Interpreter}
|
||||
The SicsInterpreter implements a Tcl-look alike command list with each
|
||||
object having a similar wrapper function to those used in Tcl. But
|
||||
augmented with a pointer to a Connection structure in order to enable
|
||||
authorisation checking and providing the I/O context. The object wrapper
|
||||
function has a prototype looking like this:
|
||||
|
||||
|
||||
{\bf int ObjectWrapper(SConnection *pCon, SicsInterp *pInter, void *pData,
|
||||
int argc, char *argv); }
|
||||
|
||||
|
||||
pCon is the connection responsible for this call and holds necessary
|
||||
information for authorisation checking. pInter is the Sics interpreter.
|
||||
pData is a pointer to an object specific datastructure (the struct holding
|
||||
the motor data for instance). Argc and argv hold the arguments as in a C
|
||||
main program. The object wrapper is meant to evaluate the arguments, do the
|
||||
right thing to the object with them and than pass results back. There are
|
||||
two ways to do that. The prefered one is to copy results or error messages
|
||||
into the interpreters result space and associate an output code with the
|
||||
result space. After returning the interpreter will than copy these results
|
||||
to the client. However, a scan routine might want to print status
|
||||
information to the client during a lengthy operation. In this case the
|
||||
object can write directly to the connnection usinfg the provided connection
|
||||
pointer. The object wrapper function returns true or false depending on the
|
||||
success of the operation.
|
||||
|
||||
|
||||
The command list is a doubly linked list holding for each command a record
|
||||
containing: the commands name, a pointer to the objects object function, a
|
||||
pointer to the objects data structure (passed as pData) on invocations and a
|
||||
pointer to a function which is capable to delete the objects data structure.
|
||||
This function will be called when the object/command is removed. In the end
|
||||
the SicsInterpreter implements the following datastrucures an
|
||||
interfaces:\begin{verbatim} typedef struct __Clist {
|
||||
char *pName;
|
||||
ObjectFunc OFunc;
|
||||
KillFunc KFunc;
|
||||
void *pData;
|
||||
struct __Clist *pNext;
|
||||
struct __Clist *pPrevious;
|
||||
} CommandList;
|
||||
\end{verbatim}
|
||||
The structure held in a doubly linked list for each command.\begin{verbatim}
|
||||
typedef struct __SINTER
|
||||
{
|
||||
CommandList *pCList;
|
||||
char *pErrors;
|
||||
int iSpace;
|
||||
OutCode eOut;
|
||||
}SicsInterp;
|
||||
\end{verbatim}
|
||||
The interpreter data structure. Access only through the interface functions given below:\begin{itemize}
|
||||
\item {\bf SicsInterp *InitInterp(void) } creates a new interpreter. Returns a pointer on success, NULL on failure.
|
||||
\item {\bf int AddCommand(SicsInterp *pInterp, char *pName, ObjectFunc pFunc, KillFunc pKFunc, void *pData); } adds a new command to the commandlist of the specified interpreter. Returns True or false depending on success.
|
||||
\item {\bf int RemoveCommand(SicsInterp *pInterp, char *pName) } finds command name and removes it from the list. Returns True on success (command found) and False if it fails.
|
||||
\item {\bf int InterpExecute(SicsInterp *self,pSConnection pCon, char *pCommand) } executes pcommand in the SICS interpreter. Returns -1 if the command did not exist. If ist exists True or False is returned depending on the success of the command.
|
||||
\item {\bf int InterpWriteResult(SicsInterp *self,char *text) } used within object wrapper functions to append result text to the interpreter. Allocating sufficient memory is taken care of by this function.
|
||||
\item {\bf void InterpSetOutCode(SicsInterp *self, OutCode eCode) } does what it says.
|
||||
\item {\bf OutCode InterpGetOutCode(SicsInterp *self) } return the current output code for the interpreters result.
|
||||
\item {\bf CommandList *FindCommand(SicsInterp *pInterp, char *name) } return a pointer to a commandlist structure if the object specified by name exists, NULL else. Used in the definition of interpreter and macro functionality.
|
||||
\item {\bf const char *InterpGetResult(SicsInterp *self) } returns a pointer to the interpreter result space. This space is managed by the interpreter, never ever delete it in client code.
|
||||
\item {\bf void DeleteInterp(SicsInterp *self) } removes the interpreter, his command list etc. Frees all allocated memory for this interpreter.
|
||||
\item {\bf WriteSicsStatus(SicsInterp *pSics, char *file)} opens the file
|
||||
for writing and writes the current status of SICS objects int the file. In
|
||||
order to do so, the SaveStatus function of each object registered in the
|
||||
interpreter is called.
|
||||
\end{itemize}
|
||||
|
||||
497
doc/programmer/interface.tex
Normal file
497
doc/programmer/interface.tex
Normal file
@@ -0,0 +1,497 @@
|
||||
\subsection{Object interfaces}\label{inter}
|
||||
In order to present themselves to the system SICS objects need to adhere to
|
||||
certyain interfaces. These interfaces are described in this
|
||||
section. Thus this section is one of the most important sections of
|
||||
theis document, read carefully!
|
||||
|
||||
A first
|
||||
requirement was that it must be possible to inquire the capabilities of an
|
||||
object at run time. A second one was that the system should be extendable.
|
||||
This means it should be possible to add new interfaces or modify them as the
|
||||
need arises. In order to achieve this the idea of the interface
|
||||
datastructure (INDS) was conceived. An INDS contains all the variables and
|
||||
functions which make up an interface. Then it is possible to create such a
|
||||
datastructure and pass it around. Each object can now be requested to pass
|
||||
an INDS of a certain type on demand. What is still needed is a standard way
|
||||
of asking a SICS object for such a datastructure. This is achieved by the
|
||||
means of the object descriptor. This is a datastructure which contains
|
||||
everything necessary to identify an object to SICS. This requires a
|
||||
convention which is that {\em each SICS objects has to have a pointer to an
|
||||
object descriptor as first element of its own datastructure.} All this
|
||||
probably gets clearer once the actual datastructures have been discussed.
|
||||
|
||||
|
||||
As usual, functions return 1 on success and 0 on failure.
|
||||
|
||||
\subsubsection{The object descriptor}
|
||||
Let's start with the objectdescriptor:
|
||||
|
||||
\begin{flushleft} \small
|
||||
\begin{minipage}{\linewidth} \label{scrap1}
|
||||
$\langle$obdes {\footnotesize ?}$\rangle\equiv$
|
||||
\vspace{-1ex}
|
||||
\begin{list}{}{} \item
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@/*--------------------------------------------------------------------------@\\
|
||||
\mbox{}\verb@ In SICS there is the to find out what an@\\
|
||||
\mbox{}\verb@ object is capable of at runtime. If this has been done a general@\\
|
||||
\mbox{}\verb@ way to access those capabilities is needed. In order to do all@\\
|
||||
\mbox{}\verb@ this each SICS-object is required to carry an object descriptor@\\
|
||||
\mbox{}\verb@ struct as first parameter in its class/object struct. Additionslly@\\
|
||||
\mbox{}\verb@ it is required to initialize this struct to something sensible.@\\
|
||||
\mbox{}\verb@ @\\
|
||||
\mbox{}\verb@ This file defines this struct. Additionally a few functions of@\\
|
||||
\mbox{}\verb@ general use are prototyped.@\\
|
||||
\mbox{}\verb@ @\\
|
||||
\mbox{}\verb@ Mark Koennecke, June, 1997@\\
|
||||
\mbox{}\verb@ @\\
|
||||
\mbox{}\verb@ copyrigth: see implementation file @\\
|
||||
\mbox{}\verb@----------------------------------------------------------------------------*/@\\
|
||||
\mbox{}\verb@#ifndef SICSDESCRIPTOR@\\
|
||||
\mbox{}\verb@#define SICSDESCRIPTOR@\\
|
||||
\mbox{}\verb@#include <stdio.h>@\\
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@ typedef struct {@\\
|
||||
\mbox{}\verb@ char *name;@\\
|
||||
\mbox{}\verb@ int (*SaveStatus)(void *self, char *name,FILE *fd);@\\
|
||||
\mbox{}\verb@ void *(*GetInterface)(void *self, int iInterfaceID);@\\
|
||||
\mbox{}\verb@ } ObjectDescriptor, *pObjectDescriptor;@\\
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@ /*---------------------------------------------------------------------------*/@\\
|
||||
\mbox{}\verb@ pObjectDescriptor CreateDescriptor(char *name);@\\
|
||||
\mbox{}\verb@ void DeleteDescriptor(pObjectDescriptor self);@\\
|
||||
\mbox{}\verb@ @\\
|
||||
\mbox{}\verb@/*============================================================================@\\
|
||||
\mbox{}\verb@ Objects which do not carry data need a dummy descriptor. Otherwise@\\
|
||||
\mbox{}\verb@ drive or scan will protection fault when trying to drive something@\\
|
||||
\mbox{}\verb@ which should not be driven. This is defined below.@\\
|
||||
\mbox{}\verb@*/@\\
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@typedef struct {@\\
|
||||
\mbox{}\verb@ pObjectDescriptor pDescriptor;@\\
|
||||
\mbox{}\verb@ }Dummy, *pDummy;@\\
|
||||
\mbox{}\verb@ @\\
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@ pDummy CreateDummy(char *name);@\\
|
||||
\mbox{}\verb@ void KillDummy(void *pData); @\\
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@ int iHasType(void *pData, char *Type);@\\
|
||||
\mbox{}\verb@ @\\
|
||||
\mbox{}\verb@#endif @\\
|
||||
\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 element of the object descriptor is a {\bf name} which is better
|
||||
described as a type identifier. This specifies the type of the object.
|
||||
|
||||
|
||||
The function {\bf SaveStatus} will be called automatically by SICS when the
|
||||
server is closing down or a status backup is requested. Each object is meant
|
||||
to print the commands necessary to configure it back into its current state
|
||||
into the file passed as a parameter. The idea is that by executing the file
|
||||
thus created the system gets back into the state before closedown.
|
||||
|
||||
The heart of the interface system is the {\bf GetInterface}
|
||||
function. It takes as arguments a pointer to the datastructure on which it
|
||||
is called and an integer ID
|
||||
for the interface. These ID's are defined in the file interface.h. This
|
||||
function is meant to return a pointer to the apropriate interface
|
||||
datastructure after this call. If the object does not implement the interface
|
||||
requested, this function should return NULL. New interfaces can be added
|
||||
into the scheme by defining new ID's, interfaces and objects which implement
|
||||
them.
|
||||
|
||||
It is {\bf important} to note, that the objects themselves are responsible
|
||||
for allocating and freeing memory for the interface structures. Client never
|
||||
should need to worry how to dispose of these structures. Moreover this
|
||||
scheme ensures that changes to the interface due to some command given to
|
||||
the object are immediatetly visible through the whole system.
|
||||
|
||||
Additionally this header file defines a few relatively uninteresting
|
||||
functions for object descriptor maintainance. Slightly more interesting is
|
||||
the Dummy structure, which will be used to find the object descriptor in a
|
||||
given objects data structure.
|
||||
|
||||
|
||||
\subsubsection{The drivable interface}
|
||||
As first example of an interface the drivable interface will be given. This
|
||||
interface is implemented by all devices or varaibles which can be driven to
|
||||
a value. Most notable example are motors, but composite variables and
|
||||
environment controllers fit this bill as well.
|
||||
|
||||
\begin{flushleft} \small
|
||||
\begin{minipage}{\linewidth} \label{scrap2}
|
||||
$\langle$driv {\footnotesize ?}$\rangle\equiv$
|
||||
\vspace{-1ex}
|
||||
\begin{list}{}{} \item
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@ typedef struct {@\\
|
||||
\mbox{}\verb@ int ID;@\\
|
||||
\mbox{}\verb@ int (*Halt)(void *self);@\\
|
||||
\mbox{}\verb@ int (*CheckLimits)(void *self, float fVal, @\\
|
||||
\mbox{}\verb@ char *error, int iErrLen);@\\
|
||||
\mbox{}\verb@ long (*SetValue)(void *self, SConnection *pCon,@\\
|
||||
\mbox{}\verb@ float fVal);@\\
|
||||
\mbox{}\verb@ int (*CheckStatus)(void *self, SConnection *pCon);@\\
|
||||
\mbox{}\verb@ float (*GetValue)(void *self, SConnection *pCon); @\\
|
||||
\mbox{}\verb@ int iErrorCount;@\\
|
||||
\mbox{}\verb@ } IDrivable, *pIDrivable;@\\
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@ pIDrivable GetDrivableInterface(void *pObject); @\\
|
||||
\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 first member of this structure is an ID which can be used in order to
|
||||
check if the right datastructure has been obtained.
|
||||
|
||||
The second field is a pointer to a {\bf Halt} function. This function will be
|
||||
called in an emergency and is meant to send a stop command to the device.
|
||||
|
||||
The third field is a pointer to the {\bf CheckLimits} function. This function is
|
||||
given a float value as second parameter. This is the new value the device
|
||||
should go to. CheckLimits checks if this position is permitted. If so it
|
||||
returns 1 else 0.
|
||||
|
||||
The {\bf SetValue} member is a pointer to a function which actually makes the
|
||||
object start to move to its new position.
|
||||
|
||||
The {\bf CheckStatus} function will be called in order to check for the current
|
||||
status of the device during operation. Possible return values are:
|
||||
\begin{itemize}
|
||||
\item OKOK if everything is OK.
|
||||
\item HWIdle if the device is idle i. e. doing nothing.
|
||||
\item HWFault if the device is in trouble.
|
||||
\item HWBusy if the device is still running.
|
||||
\item HWPosFault when the device is principally OK but has not reached the
|
||||
position specified, for instance because somebody has put a slab of concrete
|
||||
into the instruments way.
|
||||
\end{itemize}
|
||||
|
||||
The last function which makes up this interface is {\bf GetValue} which is meant
|
||||
to return the current position of the device.
|
||||
|
||||
{\bf iErrorCount} is the number of number of failed driving commands on this drivable
|
||||
item. This can be used by motors to check and abort the experiment if there
|
||||
are to many errors. This is to stop a scan command hammer at a blocked motor
|
||||
a hundred times.
|
||||
|
||||
{\bf GetDrivableInterface} is a convenience function which checks object pData for
|
||||
the existence of a drivable interface. If it exists a pointer to it will be
|
||||
returned. NEVER free this pointer. If no drivable interface exists, NULL
|
||||
will be returned.
|
||||
|
||||
\subsubsection{The Countable Interface}
|
||||
This is an interface for interacting with anything which counts.
|
||||
|
||||
|
||||
\begin{flushleft} \small
|
||||
\begin{minipage}{\linewidth} \label{scrap3}
|
||||
$\langle$count {\footnotesize ?}$\rangle\equiv$
|
||||
\vspace{-1ex}
|
||||
\begin{list}{}{} \item
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@ typedef struct {@\\
|
||||
\mbox{}\verb@ int ID;@\\
|
||||
\mbox{}\verb@ int (*Halt)(void *self);@\\
|
||||
\mbox{}\verb@ int (*StartCount)(void *self, SConnection *pCon);@\\
|
||||
\mbox{}\verb@ int (*CheckCountStatus)(void *self, SConnection *pCon);@\\
|
||||
\mbox{}\verb@ int (*Pause)(void *self, SConnection *pCon);@\\
|
||||
\mbox{}\verb@ int (*Continue)(void *self, SConnection *pCon);@\\
|
||||
\mbox{}\verb@ int (*TransferData)(void *self, SConnection *pCon);@\\
|
||||
\mbox{}\verb@ } ICountable, *pICountable;@\\
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@ pICountable GetCountableInterface(void *pObject); @\\
|
||||
\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}
|
||||
{\bf Halt and StartCount} are self explaining, they just do what they say. Please
|
||||
note, that counting configuration must have happened before usage of this
|
||||
interface.
|
||||
|
||||
{\bf Pause} pauses a data aquisition. It does NOT abort it. {\bf Continue}
|
||||
continues a paused data aquisition.
|
||||
|
||||
{\bf CheckCountStatus} works much like CheckStatus in the IDrivable interface
|
||||
described above. However, there is an additional return code: HWNoBeam. This
|
||||
is retuned if a monitor is below a certain threshold, i. e. the beam is off.
|
||||
|
||||
{\bf TransferData} will be called at the end of each counting operation and is
|
||||
meant to update the internal datastructures of the counter. Some counters
|
||||
choose to keep the last count in their own datastructure, some such as
|
||||
histogram memories might choose to leave them in the hardware. This function
|
||||
has been conceived in order to ensure that the first type of counters is
|
||||
supported.
|
||||
|
||||
{\bf GetCountableInterface} is a convenience function which checks object pData for
|
||||
the existence of a countable interface. If it exists a pointer to it will be
|
||||
returned. NEVER free this pointer. If no countable interface exists, NULL
|
||||
will be returned.
|
||||
|
||||
\subsubsection{The Callback Interface}
|
||||
The Callback Interface is SICS suport for component behaviour for objects.
|
||||
Consider objects A and B. A now is able to generate certain events when it's
|
||||
state changes. For instance if A is a variable that its value is changed.
|
||||
B may then choose to register a function with A which gets automatically
|
||||
called whenever A generates the apropriate event. B is thus automatically
|
||||
notified about A's status change and can act accordingly to it. In contrast
|
||||
to the interfaces defined above, this interface is defined in terms of a set
|
||||
of functions which manipulate the interface and not as a data structure of
|
||||
overloadable functions.
|
||||
|
||||
The first thing to define for such an interface is the type of the callback
|
||||
function:
|
||||
\begin{flushleft} \small
|
||||
\begin{minipage}{\linewidth} \label{scrap4}
|
||||
$\langle$callfunc {\footnotesize ?}$\rangle\equiv$
|
||||
\vspace{-1ex}
|
||||
\begin{list}{}{} \item
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@ typedef void (*KillFuncIT)(void *pData);@\\
|
||||
\mbox{}\verb@ typedef int (*SICSCallBack)(int iEvent, void *pEventData, @\\
|
||||
\mbox{}\verb@ void *pUserData);@\\
|
||||
\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 callback function is meant to return 0 for failure or 1 for success.
|
||||
This infomation may be needed by an event invoking object if to continue an
|
||||
operation or not. The first parameter passed to {\bf SICSCallBack} is the id of
|
||||
the generated event. Clearly the communicating objects need to agree on
|
||||
these event. In SICS events types will be held in an header file event.h.
|
||||
The next parameter to SICSCallBack is a pointer to void. The event
|
||||
generating object may choose to pass additional data along with the event.
|
||||
Suitable event datastructures are also defined in event.h. The last
|
||||
parameter to SICSCallBack is a pointer to a datastructure defined by the
|
||||
owner of the callback routine when registering the callback. {\bf pKill} is a
|
||||
function which will be called automatically when the callback is deleted and
|
||||
whose sole task is to delete pUserData properly.
|
||||
|
||||
Then there are the functions needed to interface with the callback
|
||||
interface:
|
||||
|
||||
\begin{flushleft} \small
|
||||
\begin{minipage}{\linewidth} \label{scrap5}
|
||||
$\langle$cifunc {\footnotesize ?}$\rangle\equiv$
|
||||
\vspace{-1ex}
|
||||
\begin{list}{}{} \item
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@ typedef struct __ICallBack *pICallBack;@\\
|
||||
\mbox{}\verb@ @\\
|
||||
\mbox{}\verb@ /* event source side */@\\
|
||||
\mbox{}\verb@ pICallBack CreateCallBackInterface(void);@\\
|
||||
\mbox{}\verb@ void DeleteCallBackInterface(pICallBack self);@\\
|
||||
\mbox{}\verb@ int InvokeCallBack(pICallBack pInterface, int iEvent, void *pEventData); @\\
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@ /* callback client side */@\\
|
||||
\mbox{}\verb@ long RegisterCallback(pICallBack pInterface, int iEvent, SICSCallBack pFunc,@\\
|
||||
\mbox{}\verb@ void *pUserData, KillFuncIT pKill);@\\
|
||||
\mbox{}\verb@ int RemoveCallback(pICallBack pInterface, long iID);@\\
|
||||
\mbox{}\verb@ int RemoveCallback2(pICallBack pInterface, void *pUserData);@\\
|
||||
\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 callback interface has two parts: A part the event generating object has
|
||||
to deal with and a part the interested object has to use. There is no way of
|
||||
enforcing this convention. However, SICS programmers should stick to it,
|
||||
otherwise weird things may happen.
|
||||
|
||||
The first two functions just deal with creating and deleting the callback
|
||||
interface data structure. {\bf CreateCallBackInterface} returns NULL if the
|
||||
request fails, or a pointer on success.
|
||||
|
||||
|
||||
{\bf InvokeCallBack} is responsible for invoking the registered callback functions
|
||||
and will be called only by the source object for the event. This function
|
||||
will scan the list of registered callback function for callback function
|
||||
which are registered for the event ID specified as second parameter. Each of
|
||||
them will be invoked with the event data given as third parameter. If any of
|
||||
the callback functions returns Failure this function will do so as well.
|
||||
Else 1 is returned. The event data structure belongs to the object invoking
|
||||
the callback. It should never be deleted in callback functions.
|
||||
|
||||
The next functions deal with the client side of the callback interface.
|
||||
|
||||
{\bf RegisterCallBack} registers a callback function with the interface. The first
|
||||
parameter is the interface to register the callback with. The second
|
||||
parameter is the event ID for which this callback is defined. pFunc is the
|
||||
pointer to the actual callback function. Finally pUserData is a pointer to
|
||||
some user defined data structure which shall be passed as pUserData when the
|
||||
callback is called. RegisterCallback retuns a long value which server as an
|
||||
identifier for the callback registration. If the registration fails, this
|
||||
function returns 0.
|
||||
|
||||
{\bf RemoveCallBack} is used to delete a registered callback. The first parameter
|
||||
is the interface to act upon, the second is the callback ID as returned by
|
||||
RegisterCallBack.
|
||||
|
||||
{\bf RemoveCallback2} is another variant for removing callbacks. This time the
|
||||
search key for deletion is the pointer to user data. All callbacks related
|
||||
to this user data in the interface specified will be removed.
|
||||
|
||||
All these functions are implemented in the file callback.c.
|
||||
|
||||
\subsubsection{The Environment Interface}
|
||||
This interface is used by the environment monitor in order to monitor
|
||||
the status of a environment controller. The interface looks like this:
|
||||
\begin{flushleft} \small
|
||||
\begin{minipage}{\linewidth} \label{scrap6}
|
||||
$\langle$envir {\footnotesize ?}$\rangle\equiv$
|
||||
\vspace{-1ex}
|
||||
\begin{list}{}{} \item
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@ typedef enum { EVIdle, EVDrive, EVMonitor, EVError } EVMode;@\\
|
||||
\mbox{}\verb@ typedef struct {@\\
|
||||
\mbox{}\verb@ int iID;@\\
|
||||
\mbox{}\verb@ EVMode (*GetMode)(void *self);@\\
|
||||
\mbox{}\verb@ int (*IsInTolerance)(void *self);@\\
|
||||
\mbox{}\verb@ int (*HandleError)(void *self);@\\
|
||||
\mbox{}\verb@ } EVInterface, *pEVInterface;@\\
|
||||
\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 enum {\bf EVMode} describes the mode a environment controller can be in. The
|
||||
default is Idle, no action necessary. EVDrive means that the controller is
|
||||
currently being driven to a new value and the device executor has control.
|
||||
EVMonitor means that the environment monitor has to take care of the
|
||||
controller. EVError is set if the controller is out of tolerances.
|
||||
|
||||
{\bf GetMode} retrieves the current operation mode of the controller.
|
||||
|
||||
{\bf IsInTolerance} returns 1 if the controller is still within tolerances,
|
||||
0 otherwise.
|
||||
|
||||
{\bf HandleError} will be automatically called when IsInTolerance returns 0.
|
||||
Its purpose is to implemnt the error handling startegy for the controller
|
||||
in question.
|
||||
|
||||
|
||||
The environment interface has just one function associated with it:
|
||||
\begin{flushleft} \small
|
||||
\begin{minipage}{\linewidth} \label{scrap7}
|
||||
$\langle$envfunc {\footnotesize ?}$\rangle\equiv$
|
||||
\vspace{-1ex}
|
||||
\begin{list}{}{} \item
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@ pEVInterface CreateEVInterface(void);@\\
|
||||
\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}
|
||||
{\bf CreateEVInterface} just creates an environment interface.
|
||||
|
||||
\begin{flushleft} \small
|
||||
\begin{minipage}{\linewidth} \label{scrap8}
|
||||
\verb@"obdes.h"@ {\footnotesize ? }$\equiv$
|
||||
\vspace{-1ex}
|
||||
\begin{list}{}{} \item
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@@$\langle$obdes {\footnotesize ?}$\rangle$\verb@@\\
|
||||
\mbox{}\verb@@$\diamond$
|
||||
\end{list}
|
||||
\vspace{-2ex}
|
||||
\end{minipage}\\[4ex]
|
||||
\end{flushleft}
|
||||
\begin{flushleft} \small
|
||||
\begin{minipage}{\linewidth} \label{scrap9}
|
||||
\verb@"interface.h"@ {\footnotesize ? }$\equiv$
|
||||
\vspace{-1ex}
|
||||
\begin{list}{}{} \item
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@/*---------------------------------------------------------------------------@\\
|
||||
\mbox{}\verb@ I N T E R F A C E S@\\
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@ Any object in SICS has to adhere to the object descriptor interface (see@\\
|
||||
\mbox{}\verb@ file obdes.h). Furthermore SICS objects may choose to support other@\\
|
||||
\mbox{}\verb@ interfaces as well. These interfaces are defined.@\\
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@ Mark Koennecke, June 1997@\\
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@ For more documentation see interface.w, interface.tex@\\
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@ copyright: see SICS impelementation files@\\
|
||||
\mbox{}\verb@---------------------------------------------------------------------------*/@\\
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@#ifndef SICSINTERFACES@\\
|
||||
\mbox{}\verb@#define SICSINTERFACES@\\
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@/* interface ID's used to recognize an interface */@\\
|
||||
\mbox{}\verb@#define DRIVEID 513@\\
|
||||
\mbox{}\verb@#define COUNTID 713@\\
|
||||
\mbox{}\verb@#define CALLBACKINTERFACE 947@\\
|
||||
\mbox{}\verb@#define ENVIRINTERFACE 949@\\
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@/* ----------------------- The drivable interface -----------------------*/@\\
|
||||
\mbox{}\verb@@$\langle$driv {\footnotesize ?}$\rangle$\verb@@\\
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@ pIDrivable CreateDrivableInterface(void);@\\
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@/* ------------------------ The countable interface ---------------------*/@\\
|
||||
\mbox{}\verb@@$\langle$count {\footnotesize ?}$\rangle$\verb@@\\
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@ pICountable CreateCountableInterface(void);@\\
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@/* ------------------------- The CallBack Interface --------------------*/@\\
|
||||
\mbox{}\verb@@$\langle$callfunc {\footnotesize ?}$\rangle$\verb@@\\
|
||||
\mbox{}\verb@@$\langle$cifunc {\footnotesize ?}$\rangle$\verb@@\\
|
||||
\mbox{}\verb@/*---------------------- The Environment Interface --------------------*/@\\
|
||||
\mbox{}\verb@@$\langle$envir {\footnotesize ?}$\rangle$\verb@@\\
|
||||
\mbox{}\verb@@$\langle$envfunc {\footnotesize ?}$\rangle$\verb@@\\
|
||||
\mbox{}\verb@#endif@\\
|
||||
\mbox{}\verb@@$\diamond$
|
||||
\end{list}
|
||||
\vspace{-2ex}
|
||||
\end{minipage}\\[4ex]
|
||||
\end{flushleft}
|
||||
\subsection{More interfaces}
|
||||
For completeness it should be mentioned that besides these interfaces
|
||||
there exist further important interfaces in SICS. This includes the
|
||||
interface to the SICS interpreter defined in
|
||||
\ref{scinter}. Furthermore the data structures defined for the various
|
||||
types of drivers within SICS may be considered interfaces as
|
||||
well. Then there is the interface to the client as defined by the
|
||||
functions of the connection interface.
|
||||
|
||||
|
||||
53
doc/programmer/interrupt.tex
Normal file
53
doc/programmer/interrupt.tex
Normal file
@@ -0,0 +1,53 @@
|
||||
\subsection{Interrupt Handling}
|
||||
SICS needs a way to interrupt server processsing. This is done
|
||||
with this module.
|
||||
Interrupts may come in through two ways: They may be created
|
||||
internally or they may be user requested. For the last ones
|
||||
the main loop will poll an additional special interrupt
|
||||
port.
|
||||
|
||||
In order to do interrupting a set of interrupt codes are defined:
|
||||
\begin{verbatim}
|
||||
#define eContinue 0
|
||||
#define eAbortOperation 1
|
||||
#define eAbortScan 2
|
||||
#define eAbortBatch 3
|
||||
#define eHaltSystem 4
|
||||
#define eFreeSystem 5
|
||||
#define eEndServer 6
|
||||
\end{verbatim}
|
||||
Their meanings:
|
||||
\begin{description}
|
||||
\item[eContinue] Go on, interrupt nothing.
|
||||
\item[eAbortOperation] stop current hardware operation but no scans or
|
||||
batchfiles.
|
||||
\item[eAbortScan] stop current scan or operation but continue processing of
|
||||
batch files with next command.
|
||||
\item[eAbortBatch] Stop all processing, even batch files.
|
||||
\item[eHaltSystem, eFreeSystem] are currently unused.
|
||||
\item[eEndServer] is used internally by the SicsExitus command to run down
|
||||
the server.
|
||||
\end{description}
|
||||
|
||||
The interrupt module supports the following interface:
|
||||
\begin{description}
|
||||
\item[void ServerStopInterrupt(void)] stops interrupt processing.
|
||||
\item[void SetInterrupt(int iCode)]
|
||||
Send an interrupt to all connections. Use with care! More often an
|
||||
interrupt need to be set on a special connection. This can be done with
|
||||
SCSetInterrupt defined in conman.h.
|
||||
\item[int Interrupt2Text(int iInterrupt, char *text, int iTextLen)] converts
|
||||
iInterrupt to a text. Maximum iTextLen characters will be copied to text.
|
||||
\item[int Text2Interrupt(char *text)] Converts text, when applicable to an
|
||||
interrupt code which is returned. If the text is invalid -1 is returned.
|
||||
\item[int ClientSetupInterrupt(char *host, int iPort)] Creates a client side
|
||||
interrupt UDP port.
|
||||
\item[void ClientStopInterrupt(void)] removes an client side interrupt port
|
||||
created by ClientSetupInterrupt.
|
||||
\item[void SendInterrupt( int iCode)] sends an interrupt through the UDP
|
||||
port.
|
||||
\end{description}
|
||||
|
||||
Please note, that the interrupt implementation is distributed into two
|
||||
files: intserv.c for the server side stuff and intcli.c for the client side
|
||||
part. UDP interrupting is not fully tested.
|
||||
107
doc/programmer/itc4.tex
Normal file
107
doc/programmer/itc4.tex
Normal file
@@ -0,0 +1,107 @@
|
||||
\subsubsection{Oxford Instruments ITC4 Temperature Controllers}
|
||||
SINQ makes heavy use of Oxford Instruments ITC4 temperature controllers. In
|
||||
order to support them the following software components had to be defined in
|
||||
addition to the basic environmet controller interfaces:
|
||||
\begin{itemize}
|
||||
\item ITC4driver, naturally.
|
||||
\item A ITC4-controller object as derivation of environment controller. ITC4
|
||||
's allow you to select a sensor which you read as your standard sensor and a
|
||||
sensor which is used for automatic control. The ITC4 controller object adds
|
||||
just that additional functionality to the statndard environment controller.
|
||||
\end{itemize}
|
||||
The additional data, the selection of sensors, will be kept in the driver.
|
||||
This serves also an example for implementing inheritance without C++.
|
||||
|
||||
The driver interface:
|
||||
\begin{flushleft} \small
|
||||
\begin{minipage}{\linewidth} \label{scrap1}
|
||||
$\langle$itcd {\footnotesize ?}$\rangle\equiv$
|
||||
\vspace{-1ex}
|
||||
\begin{list}{}{} \item
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@ pEVDriver CreateITC4Driver(int argc, char *argv[]);@\\
|
||||
\mbox{}\verb@ int ConfigITC4(pEVDriver self);@\\
|
||||
\mbox{}\verb@ int SetSensorITC4(pEVDriver self, int iSensor);@\\
|
||||
\mbox{}\verb@ int SetControlITC4(pEVDriver self, int iSensor);@\\
|
||||
\mbox{}\verb@ int GetSensorITC4(pEVDriver self);@\\
|
||||
\mbox{}\verb@ int GetControlITC4(pEVDriver self);@\\
|
||||
\mbox{}\verb@ int SetDivisorITC4(pEVDriver self, float iSensor);@\\
|
||||
\mbox{}\verb@ float GetDivisorITC4(pEVDriver self);@\\
|
||||
\mbox{}\verb@ int SetMultITC4(pEVDriver self, float iSensor);@\\
|
||||
\mbox{}\verb@ float GetMultITC4(pEVDriver self);@\\
|
||||
\mbox{}\verb@ int SetTMOITC4(pEVDriver self, int iSensor);@\\
|
||||
\mbox{}\verb@ int GetTMOITC4(pEVDriver self);@\\
|
||||
\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 ConfigITC4 is special. It has to be called to commit changes to the
|
||||
driver read and control parameters.
|
||||
|
||||
The ITC4 object interface:
|
||||
\begin{flushleft} \small
|
||||
\begin{minipage}{\linewidth} \label{scrap2}
|
||||
$\langle$itco {\footnotesize ?}$\rangle\equiv$
|
||||
\vspace{-1ex}
|
||||
\begin{list}{}{} \item
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@ int ITC4Wrapper(SConnection *pCon, SicsInterp *pSics, void *pData,@\\
|
||||
\mbox{}\verb@ int argc, char *argv[]);@\\
|
||||
\mbox{}\verb@ int ITC4SetPar(pEVControl self, char *name, float fNew, @\\
|
||||
\mbox{}\verb@ SConnection *pCon);@\\
|
||||
\mbox{}\verb@ int ITC4GetPar(pEVControl self, char *name, float *fVal);@\\
|
||||
\mbox{}\verb@ int ITCList(pEVControl self, SConnection *pCon);@\\
|
||||
\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 defined are: new parameter handling functions, with just
|
||||
support for the two extra parameters added and a new Wrapper function for
|
||||
SICS. The meaning of all these functions, their parameters and return values
|
||||
are identical to those defined for an environment controller. Additionally,
|
||||
the standard environment controller functions will work as described. The
|
||||
functions described above are just needed to implement the extra parameters.
|
||||
|
||||
\begin{flushleft} \small
|
||||
\begin{minipage}{\linewidth} \label{scrap3}
|
||||
\verb@"itc4.h"@ {\footnotesize ? }$\equiv$
|
||||
\vspace{-1ex}
|
||||
\begin{list}{}{} \item
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@/*-------------------------------------------------------------------------@\\
|
||||
\mbox{}\verb@ ITC 4@\\
|
||||
\mbox{}\verb@ @\\
|
||||
\mbox{}\verb@ Support for Oxford Instruments ITC4 Temperature controllers for SICS.@\\
|
||||
\mbox{}\verb@ The meaning and working of the functions defined is as desribed for a@\\
|
||||
\mbox{}\verb@ general environment controller.@\\
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@ Mark Koennecke, Juli 1997@\\
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@ copyright: see implementation file.@\\
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@-----------------------------------------------------------------------------*/@\\
|
||||
\mbox{}\verb@#ifndef SICSITC4@\\
|
||||
\mbox{}\verb@#define SICSITC4@\\
|
||||
\mbox{}\verb@/*------------------------- The Driver ------------------------------------*/@\\
|
||||
\mbox{}\verb@@$\langle$itcd {\footnotesize ?}$\rangle$\verb@@\\
|
||||
\mbox{}\verb@/*------------------------- The ITC4 object ------------------------------*/@\\
|
||||
\mbox{}\verb@@$\langle$itco {\footnotesize ?}$\rangle$\verb@@\\
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@#endif @\\
|
||||
\mbox{}\verb@ @\\
|
||||
\mbox{}\verb@@$\diamond$
|
||||
\end{list}
|
||||
\vspace{-2ex}
|
||||
\end{minipage}\\[4ex]
|
||||
\end{flushleft}
|
||||
355
doc/programmer/kernelguide.tex
Normal file
355
doc/programmer/kernelguide.tex
Normal file
@@ -0,0 +1,355 @@
|
||||
\chapter{Guide To SICS Kernel Facilities}
|
||||
In this chapter the facilities of the SICS servers kernel will be examined
|
||||
more closely. All the kernel modules and their function will be listed,
|
||||
together with some explanatory information and an overview about the
|
||||
application programmers interfaces (API) provided. This section should
|
||||
answer the questions: WHat is available?, Where to find what?,
|
||||
Why did they do that? Details of
|
||||
the API's mentioned are given in the reference section.
|
||||
|
||||
|
||||
The SICS servers kernel consists of the following objects and modules:
|
||||
\begin{itemize}
|
||||
\item The task manager , Files tasker.*.
|
||||
\item The network reader, Files nread.*.
|
||||
\item The network module, Files network.*.
|
||||
\item The connection object, Files conman.*.
|
||||
\item The SICS interpreter, Files SCinter.*.
|
||||
\item The SICS macro facility, Files macro.*, script.*.
|
||||
\item The device executor, Files devexec.*.
|
||||
\item The environment monitor, Files emon.c.
|
||||
\item The server himself, Files nserver.*
|
||||
\item The serverlog, Files servlog.*.
|
||||
\item A performance monitor, Files perfmon.*.
|
||||
\item The object factory, Files ofac.*.
|
||||
\item The options database, Files ifile.*.
|
||||
\item The password database, Files passwd.*.
|
||||
\item The main program, File SICSmain.c.
|
||||
\end{itemize}
|
||||
|
||||
\section{The Task Manager}
|
||||
The task manager implements cooperative multitasking in SICS. A task in the
|
||||
SICS sense is defined by a function, the task function. It is of the type:
|
||||
\begin{verbatim}
|
||||
int TaskFunction(void *pData);
|
||||
\end{verbatim}
|
||||
When it is time for the task to execute this function is called, with a
|
||||
parameter to a the tasks own data structure. This data structure must have
|
||||
been defined by the user of this module. The task function returns 1, if it
|
||||
shall continue to live, or 0 if it should be deleted from the task list.
|
||||
These task functions are kept in a list. The elements of this list are
|
||||
visited cyclically, when the scheduler runs.
|
||||
|
||||
The API to this object consists of functions for creating a task manager,
|
||||
adding tasks to the task list and to run the task list. Other functions
|
||||
allow to put a task into a wait state. This means that the task will not
|
||||
execute until another task has died (returned 0). Then the waiting task will
|
||||
continue execution at the point where it has called the wait function.
|
||||
For example, consider a task which wants to wait for say 10 seconds. This
|
||||
tasks name shall be BedTask. It does so by starting a second task, called
|
||||
ClockTask which checks if 10 seconds have passed and dies after this.
|
||||
BedTask then waits for this task. This makes BedTask look like this:
|
||||
\begin{verbatim}
|
||||
int BedTask(void *pData)
|
||||
{
|
||||
/* Code block 1.
|
||||
Fill in horrendously complex operations here.
|
||||
*/
|
||||
|
||||
lID = TaskRegister(pTasker, ClockTask,....)
|
||||
TaskWait(pTasker, lID, ....);
|
||||
|
||||
/* Code block 2.
|
||||
More horrendous computations.
|
||||
Will be executed after ClockTask died.
|
||||
*/
|
||||
|
||||
/* Beds never die!!! */
|
||||
return 1;
|
||||
}
|
||||
\end{verbatim}
|
||||
and ClockTask:
|
||||
\begin{verbatim}
|
||||
int ClockTask(void *pData)
|
||||
{
|
||||
if(10 seconds are gone)
|
||||
{
|
||||
/* death is lurking */
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* continue running */
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
\end{verbatim}
|
||||
|
||||
The task manager supports a primitive means of inter task communication as
|
||||
well. Each registered task may not only have a task function associated with
|
||||
it, but also a SignalFunction. When a task feels like it, it may advise the
|
||||
task manager to send a signal and some data to all the other tasks. Signals
|
||||
are identified by integer numbers. The SignalFunction of each task will then
|
||||
be called. It has to check the signal and if it is of meaning to the task,
|
||||
do something appropriate with it. SICS uses this facility to distribute
|
||||
interrupts and broadcast messages to all tasks. Currently defined signal
|
||||
IDs are defined in file event.h.
|
||||
|
||||
\section{The Network Reader and the Network Module}
|
||||
The network module implements the mechanics of network connection. This
|
||||
module is the one which needs heavy reworking if the network protocol for
|
||||
SICS should be changed. For instance to Token--Ring or AppleTalk or
|
||||
whatever.
|
||||
The network reader implements the polling for network message in the SICS
|
||||
server. It is organized as one of the SICS system tasks. Polling in a POSIX
|
||||
environment is all about the select system call. The select system call
|
||||
allows to enquire if an open TCP/IP socket has data pending to be read, can
|
||||
be written to etc. For more details see the unix man pages for the select
|
||||
system call. An earlier version of the SICS server had a list of connection
|
||||
objects and each of them were checked for pending commands with a call to
|
||||
select. This proved to be inefficient with the system spending two thirds
|
||||
of its time in select. Then it was decided to make use of the fact that
|
||||
select can check more then one socket in one call. This gave birth to the
|
||||
network reader. Each network user in the SICS server can register his socket
|
||||
with the network reader. When the network reader tasks executes, it checks
|
||||
all registered sockets for pending data with one central select system call.
|
||||
This scheme improved system performance by a factor of 900.
|
||||
What happens when data is pending on a socket depends on the type of the
|
||||
socket.
|
||||
The network reader currently supports four types of sockets:
|
||||
\begin{itemize}
|
||||
\item Accept type sockets.
|
||||
\item Normal client sockets.
|
||||
\item UDP sockets.
|
||||
\item User sockets.
|
||||
\end{itemize}
|
||||
|
||||
The accept type of socket is the main server port where clients try to
|
||||
connect to. The network reader accepts the connection and tries to read a
|
||||
username/password pair for a specified amount of time.
|
||||
If the username/password is valid, the connection will be accepted,
|
||||
else it will be broken again. The username/password pair will be verified
|
||||
against the data in the password database. If a connection is accepted, a
|
||||
new connection object is created, a new connection task is registered into
|
||||
the system and the network reader registers a new client command port.
|
||||
|
||||
The normal client command ports are accepted connections from a client. The
|
||||
SICS server expects commands to be sent from the clients. Thus any data
|
||||
pending on such a socket will be read, split into single commands at the \\n
|
||||
and put into the connections command stack for execution. At this place
|
||||
there is also the check for the special interrupt string on command
|
||||
connections (see \ref{prot1}).
|
||||
|
||||
The SICS server accepts only interrupts on its UDP port. This will be checked
|
||||
for when handling data pending on the servers UDP port.
|
||||
|
||||
User type sockets are a feature for dealing with extremely slow hardware
|
||||
connections. Some hardware devices require a long time to answer requests.
|
||||
For example the Dornier velocity selector. This would block the SICS server
|
||||
or diminish its performance to unbearable levels. If situations like that
|
||||
occur somewhere in SICS object code, the object may call a special wait
|
||||
function which returns when data is pending on the socket. Thereby, other
|
||||
clients requests would be served, as the task switcher would run.
|
||||
This special wait facility is implemented in the network reader.
|
||||
|
||||
\section{The Connection Object}
|
||||
The connection object holds the execution context of the current client
|
||||
connection. Its data structure holds information about the network channel to
|
||||
the client connection, the command stack which the network reader fills with
|
||||
commands, a list of files where all I/O to and from this connection will be
|
||||
logged, the user rights associated with this client connection, interrupts,
|
||||
and flags which determine if the connection is currently executing in a
|
||||
macro or is busy. Functions exist which allow to interact with this object.
|
||||
Most of them will be discussed in section \ref{gow}. Associated with each
|
||||
connection is a task and a task function. Whenever this task executes, it
|
||||
will pop a command from the command stack and execute it in the
|
||||
interpreter. More details about the usage of the connection object can be
|
||||
found in the next chapter \ref{gow}.
|
||||
|
||||
\section{The SICS Interpreter and Macro Language}
|
||||
In order to understand this section a knowledge of some aspects of the C
|
||||
language interface to the Tcl interpreter helps. Interesting chapters include
|
||||
the sections about defining new commands in Tcl and the Tcl unknown
|
||||
mechanism. For more details see John Ousterhout's book.
|
||||
|
||||
In an earlier stage it was considered to use the Tcl interpreter as the SICS
|
||||
interpreter. This idea was discarded for some reasons: One was the
|
||||
difficulty of transporting the client execution context (i.e. the connection
|
||||
object) through the Tcl interpreter. There is no standard Tcl mechanism for
|
||||
doing that. The second was security: the Tcl
|
||||
interpreter is very powerful and can be abused. It was felt that the system
|
||||
had to be protected against such problems. The third reasons was that the
|
||||
set of user commands should not be cluttered with Tcl commands in order to
|
||||
prevent confusion. Programming macros is anyway something which is done by
|
||||
SICS managers or programmers. However, the SICS interpreter is still modeled
|
||||
very much like the Tcl-interpreter. A Tcl interpreter is still included in
|
||||
order to provide a full featured macro language. The SICS interpreter and the
|
||||
Tcl macro interpreter are still tightly coupled.
|
||||
|
||||
The SICS interpreter must forward commands to the SICS objects. For this the
|
||||
interpreter needs some help from the objects themselves. Each SICS object
|
||||
has to provide a wrapper function of the type:
|
||||
\begin{verbatim}
|
||||
int ObjectWrapper(SConnection *pCon, SicsInterp *pSics, void *pData,
|
||||
int argc, char *argv[]);
|
||||
\end{verbatim}
|
||||
in order to be visible from the interpreter. The parameters to this function
|
||||
are: a pointer to the client connection executing the command,
|
||||
the interpreter in which the command
|
||||
executes, a pointer to the objects data structure and an argc,
|
||||
\verb+argv[]+ pair
|
||||
like for an C language main program. This argc, \verb+argv[]+ pair contains the
|
||||
arguments to the wrapper function. The wrapper function is responsible for
|
||||
evaluating the arguments and do whatever is appropriate. It returns 0 on
|
||||
failure and 1 on success. The SICS interpreter holds a list of such wrapper
|
||||
functions. For each object the list holds:
|
||||
\begin{itemize}
|
||||
\item The name of the SICS object.
|
||||
\item The address of the objects wrapper function.
|
||||
\item The address of the objects data structure.
|
||||
\item The address of a function which can remove the objects data structure
|
||||
from memory cleanly. This is used when deleting an object/command from the
|
||||
interpreter to clean up memory.
|
||||
\end{itemize}
|
||||
Command interpretation then involves the following steps:
|
||||
\begin{enumerate}
|
||||
\item The command is parsed into an argc, \verb+argv[]+ pair.
|
||||
\item Using the first word of the command as a key, the list of objects is
|
||||
searched for a match.
|
||||
\item If a match is found, the objects wrapper function is invoked with the
|
||||
appropriate parameters.
|
||||
\item All the rest of command interpretation is done by the wrapper
|
||||
function.
|
||||
\end{enumerate}
|
||||
The SICS interpreter interface offers functions which allow to add or remove
|
||||
entries to and from the interpreters list of objects. Other functions allow
|
||||
to find objects (and their data structures) in this list. And of course,
|
||||
there is a function which executes a command in this interpreter.
|
||||
|
||||
|
||||
The Tcl macro interpreter is invoked either through the FileEval command or
|
||||
through commands made available through the Publish mechanism. Publish
|
||||
is a SICS manager command which makes a Tcl command or procedure
|
||||
visible in the SICS interpreter. Publish provides a special wrapper for a
|
||||
Tcl command, which first checks the user rights of the client connection which
|
||||
wants to execute the Tcl command. If the user rights are appropriate the
|
||||
command is invoked in the Tcl--interpreter. The Tcl interpreter has access
|
||||
to all normal SICS commands. This is implemented by using the Tcl
|
||||
unknown mechanism. If Tcl cannot find a command it invokes a command named
|
||||
unknown with the missing commands name as a parameter. Unknown is usually
|
||||
implemented as a Tcl script, loaded at Tcl startup time. The unknown function
|
||||
is then responsible for finding the missing command and execute it. The
|
||||
usual Tcl mechanism tries to find the missing command in Tcl libraries and
|
||||
as operating system commands. This mechanism has been modified for SICS such
|
||||
that unknown tries to find missing commands in Tcl libraries or in the SICS
|
||||
interpreter. This last bit is implemented as a special Tcl command
|
||||
SISCUnknown defined in macro.c. In order to invoke SICS command a connection
|
||||
object is needed. A suitable connection object is provided through a stack.
|
||||
Before invoking the Tcl-interpreter, the connection object from which the
|
||||
request has come is put at the bottom of a stack. The SICSUnknown routine
|
||||
then uses the last element of the stack as the connection object for
|
||||
invoking SICS. When control returns from the Tcl-interpreter, the connection
|
||||
is popped from the stack.
|
||||
|
||||
%% Idea: simplify: use Tcl as interpreter, have a wrapper around SICS
|
||||
%% objects which provide the SICS wrapper contexts. Add SICS commands to Tcl
|
||||
%% in a special data structure:
|
||||
%% struct TclSICS {
|
||||
%% (*ObjectWrapper);
|
||||
%% void *ObjectData;
|
||||
%% (*KillObject)
|
||||
%% };
|
||||
%% The Tcl wrapper function gets the connection object from the stack and
|
||||
%% invokes the SICS object function.
|
||||
%% This does not solve the Tcl security issue, though.
|
||||
%%
|
||||
|
||||
\section{The Device Executor}
|
||||
The device executor is responsible for executing and monitoring requests to
|
||||
the actual instrument hardware. In its current form the device executor can
|
||||
do this for any variable which can be driven (motors, temperature, composite
|
||||
variables) and counters (single counters, histogram memory). How this is
|
||||
done is explained in some detail in the section about SICS interfaces (see
|
||||
\ref{inter}) in the object writers guide. The interface to the device
|
||||
executor includes functions for starting, pausing, continuing devices and
|
||||
monitoring their status. Additionally there are some functions and SICS
|
||||
commands which allow to enquire about the status of the executor. If
|
||||
hardware is active, the device executor has a SICS system task running
|
||||
which initiates monitoring of devices. The device executor is built around a
|
||||
list of currently active hardware devices.
|
||||
|
||||
\section{The Environment Monitor}
|
||||
For the SICS concept for handling sample environment devices see
|
||||
\ref{evdev}.
|
||||
|
||||
\section{The Server}
|
||||
The server module defines a server data structure. A pointer to this
|
||||
data structure is the sole global variable in the SICS system. Its name is
|
||||
{\bf {\huge pServ}}. This data structure contains pointers to the most
|
||||
important SICS components: the interpreter, the task switcher, the device
|
||||
executor, the environment monitor and the network reader. This module also
|
||||
contains the code for initializing, running and stopping the server.
|
||||
|
||||
\section{The ServerLog}
|
||||
As part of the SICS kernel there exists a global server log file. This file
|
||||
contains:
|
||||
\begin{itemize}
|
||||
\item All traffic on all client connections. Even messages suppressed by the
|
||||
clients.
|
||||
\item All internal error messages.
|
||||
\item Notifications about important internal status changes.
|
||||
\end{itemize}
|
||||
This server log is meant as an aid in debugging the server. As the SICS
|
||||
server may run for days, weeks and months uninterrupted this log file may
|
||||
become very large. However, only the last thousand or so messages are really
|
||||
of interest when tracking a problem. Therefore a scheme is implemented to
|
||||
limit the disk space used by the server log. The server log writes
|
||||
cyclically into a number of files. A count of the lines is kept which were
|
||||
written to each file. Above a predefined count, a new file is started.
|
||||
As an interface the server log provides a function which allows to write
|
||||
a message to it. This can be used by any object in the system for
|
||||
interesting messages. The number of files to cycle through and the length of
|
||||
each file can be configured by defines at the top of servlog.c.
|
||||
|
||||
\section{The Performance Monitor}
|
||||
This facility provides the data for the Performance (see user documentation)
|
||||
command. The Performance Monitor is a task which increments a counter each
|
||||
time it is executed. After a predefined integration time (20 seconds) a new
|
||||
value cycles/per second is calculated. This is the data retrievable by the
|
||||
Performance command. This facility is not particularly necessary but proved
|
||||
useful for judging the impact of various system conditions on server
|
||||
performance. If at some stage performance needs to be boosted to the utmost
|
||||
and it is no longer the hardware which makes things slow, the performance
|
||||
monitor may well be removed from the system without harm.
|
||||
|
||||
\section{The Object Factory}
|
||||
During SICS initialization the SICS interpreters command list needs to be
|
||||
initialized. This is the task of the object factory. Its function
|
||||
IniIniCommand initializes all fixed, general SICS commands and all object
|
||||
creation commands. Then the server initialization file is processed from the
|
||||
server initialization code. After this is done, the server initialization
|
||||
code calls KillIniCommands which removes the now surplus object creation
|
||||
commands from the SICS interpreter. If new commands get added to SICS the
|
||||
object creation command or (for a permanent command) the object wrapper have
|
||||
to be registered with these two functions.
|
||||
|
||||
\section{SICS Options}
|
||||
Any system needs a way to configure itself. SICS uses options for internal
|
||||
parameters which should or need not be visible from the SICS interpreter. An
|
||||
option is a name value pair. For a definition of currently valid SICS
|
||||
options and how to create them see the SICS manager documentation. In terms
|
||||
of an interface this module allows to retrieve an option from the options
|
||||
database.
|
||||
|
||||
\section{The Password Database}
|
||||
The password database holds a triplet of username password and rights code
|
||||
for each user. This information is currently initialized from the server
|
||||
initialization file. This scheme is not very secure, as anybody with an
|
||||
account on the DAQ computer may view the file and thus the list of valid
|
||||
users. If this becomes a serious concern, this module has to be rewritten.
|
||||
|
||||
\section{The Server Main Function}
|
||||
This does not do much, just initialize the server, run it, and stop it.
|
||||
|
||||
|
||||
|
||||
239
doc/programmer/lantronix_setup.txt
Executable file
239
doc/programmer/lantronix_setup.txt
Executable file
@@ -0,0 +1,239 @@
|
||||
TAS_SRC:[PSI.NOTES]LANTRONIX_SETUP.TXT
|
||||
======================================
|
||||
15-Nov-2000
|
||||
===========
|
||||
The Following setup was made for the
|
||||
|
||||
Lantronix ETS16PR Terminal Server psts240 (129.129.120.240) for POLDI
|
||||
|
||||
define server name "psts240"
|
||||
define server incoming telnet
|
||||
define server incoming nopassword
|
||||
define server domain "psi.ch"
|
||||
define server subnet mask 255.255.0.0
|
||||
|
||||
define protocol ip enable
|
||||
define protocol ip ipaddress 129.129.120.240
|
||||
define protocol ip gateway 129.129.100.2
|
||||
define protocol ip nameserver 129.129.100.1
|
||||
define protocol ip secondary nameserver 129.129.110.10
|
||||
define protocol ip timeserver enable
|
||||
|
||||
define server dhcp disabled
|
||||
define server bootp disabled
|
||||
define server rarp disabled
|
||||
|
||||
define server serial delay 10 # (was 30 msec)
|
||||
define server buffer 256 # (was 2048)
|
||||
define server ident "POLDI Terminal Server"
|
||||
|
||||
define port 2-16 access remote
|
||||
define port 2-16 autobaud disable
|
||||
define port 2-16 break disable
|
||||
define port 2-16 broadcast disable
|
||||
define port 2-16 flow control none
|
||||
define port 2-16 loss notif disable
|
||||
define port 2-16 modem disable
|
||||
define port 2-16 passflow enable
|
||||
define port 2-16 telnet pad disable
|
||||
define port 2-16 verific disable
|
||||
|
||||
init delay 0
|
||||
-------------------------------------------------------------------------------
|
||||
08-Nov-2000
|
||||
===========
|
||||
The following commands:
|
||||
|
||||
define server dhcp disabled
|
||||
define server bootp disabled
|
||||
define server rarp disabled
|
||||
|
||||
were executed on
|
||||
|
||||
psts213 -- Test device in WHGA/247
|
||||
psts216 -- Druechal
|
||||
psts217 -- TASP
|
||||
psts222 -- Loan device for P.Rasmussen
|
||||
psts223 -- SANS
|
||||
psts224 -- AMOR
|
||||
psts225 -- DMC
|
||||
psts227 -- FOCUS
|
||||
psts228 -- TriCS
|
||||
psts229 -- HRPT
|
||||
psts230 -- POLDI (on loan from LNS)
|
||||
|
||||
on the recommendation of Lantronix (Brian Tutor)
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
28-Apr-2000
|
||||
===========
|
||||
The Following setup was made for the
|
||||
|
||||
Lantronix ETS16PR Terminal Server psts225 (129.129.120.225) for DMC
|
||||
and
|
||||
Lantronix ETS16PR Terminal Server psts227 (129.129.120.227) for FOCUS
|
||||
|
||||
Local_18>> define server serial delay 10 (was 30 msec)
|
||||
Local_18>> define server buffer 256 (was 2048)
|
||||
Local_18>> define server ident "DMC/FOCUS Terminal Server"
|
||||
|
||||
Local_18>> define server dhcp disabled \
|
||||
Local_18>> define server bootp disabled > Done on 8-Nov-2000 (see above)
|
||||
Local_18>> define server rarp disabled /
|
||||
|
||||
Local_18>> define port 2-16 access remote
|
||||
Local_18>> define port 2-16 autobaud disable
|
||||
Local_18>> define port 2-16 break disable
|
||||
Local_18>> define port 2-16 broadcast disable
|
||||
Local_18>> define port 2-16 flow control none
|
||||
Local_18>> define port 2-16 loss notif disable
|
||||
Local_18>> define port 2-16 modem disable
|
||||
Local_18>> define port 2-16 passflow enable
|
||||
Local_18>> define port 2-16 telnet pad disable
|
||||
Local_18>> define port 2-16 verific disable
|
||||
|
||||
Local_18>> init delay 0
|
||||
|
||||
Local_18>> show server char
|
||||
|
||||
ETS16PR Version V3.5/7(981112) Uptime: 0:01:57
|
||||
Hardware Addr: 00-80-a3-23-8e-1d Name/Nodenum: ETS_238E1D/ 0
|
||||
Ident String: DMC/FOCUS Terminal Server
|
||||
|
||||
LAT Circuit Timer (msec): 80 Password Limit: 3
|
||||
Inactive Timer (min): 30 Console Port: 1
|
||||
Queue Limit: 32 Retrans Limit: 50
|
||||
Keepalive Timer (sec): 20 Session Limit: 4
|
||||
Multicast Timer (sec): 30 Node/Host Limits: 50/20
|
||||
|
||||
TCP/IP Address: 129.129.120.225 Subnet Mask: 255.255.0.0
|
||||
Nameserver: (undefined) Backup Nameserver: (undefined)
|
||||
TCP/IP Gateway: 129.129.40.151 Backup Gateway: 129.129.100.2
|
||||
Domain Name: (undefined) Daytime Queries: Enabled
|
||||
TCP Keepalives: Enabled
|
||||
DHCP Server: None Lease Time: 0:00
|
||||
|
||||
Serial Delay (msec): 10 Network Buffering: 256
|
||||
Prompt: Local_%n%P>
|
||||
Groups: 0
|
||||
|
||||
Characteristics: Announce Broadcast Lock
|
||||
Incoming Logins: Telnet (No Passwords Required)
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
6-Mar-2000
|
||||
==========
|
||||
The Following setup was made for the
|
||||
|
||||
Lantronix ETS16PR Terminal Server psts223 (129.129.120.223) for SANS
|
||||
|
||||
Local_18>> define server serial delay 10 (was 30 msec)
|
||||
Local_18>> define server buffer 256 (was 2048)
|
||||
Local_18>> define server ident "SANS Terminal Server"
|
||||
|
||||
Local_18>> define server dhcp disabled \
|
||||
Local_18>> define server bootp disabled > Done on 8-Nov-2000 (see above)
|
||||
Local_18>> define server rarp disabled /
|
||||
|
||||
Local_18>> define port 2-16 access remote
|
||||
Local_18>> define port 2-16 autobaud disable
|
||||
Local_18>> define port 2-16 break disable
|
||||
Local_18>> define port 2-16 broadcast disable
|
||||
Local_18>> define port 2-16 flow control none
|
||||
Local_18>> define port 2-16 loss notif disable
|
||||
Local_18>> define port 2-16 modem disable
|
||||
Local_18>> define port 2-16 passflow enable
|
||||
Local_18>> define port 2-16 telnet pad disable
|
||||
Local_18>> define port 2-16 verific disable
|
||||
|
||||
Local_18>> define port 16 speed 4800
|
||||
|
||||
Local_18>> init delay 0
|
||||
|
||||
Local_18>> show server char
|
||||
|
||||
ETS16PR Version V3.5/7(981112) Uptime: 22 Days 20:09
|
||||
Hardware Addr: 00-80-a3-23-8e-4f Name/Nodenum: ETS_238E4F/ 0
|
||||
Ident String: SANS Terminal Server Daytime: 11:31:15
|
||||
|
||||
LAT Circuit Timer (msec): 80 Password Limit: 3
|
||||
Inactive Timer (min): 30 Console Port: 1
|
||||
Queue Limit: 32 Retrans Limit: 50
|
||||
Keepalive Timer (sec): 20 Session Limit: 4
|
||||
Multicast Timer (sec): 30 Node/Host Limits: 50/20
|
||||
|
||||
TCP/IP Address: 129.129.120.223 Subnet Mask: 255.255.0.0
|
||||
Nameserver: (undefined) Backup Nameserver: (undefined)
|
||||
TCP/IP Gateway: 129.129.80.1 Backup Gateway: 129.129.100.2
|
||||
Domain Name: (undefined) Daytime Queries: Enabled
|
||||
TCP Keepalives: Enabled
|
||||
DHCP Server: None Lease Time: 0:00
|
||||
|
||||
Serial Delay (msec): 10 Network Buffering: 256
|
||||
Prompt: Local_%n%P>
|
||||
Groups: 0
|
||||
|
||||
Characteristics: Announce Broadcast Lock
|
||||
Incoming Logins: Telnet (No Passwords Required)
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
19-May-1999
|
||||
===========
|
||||
The Following setup was made for the
|
||||
|
||||
Lantronix ETS8P Terminal Server psts217 (129.129.120.217) for TASP
|
||||
and Lantronix ETS8P Terminal Server psts216 (129.129.120.216) for DRUECHAL
|
||||
|
||||
Local_10>> define server serial delay 10 (was 30 msec)
|
||||
Local_10>> define server buffer 256 (was 2048)
|
||||
Local_10>> define server ident "TASP Terminal Server"
|
||||
|
||||
Local_10>> define server dhcp disabled \
|
||||
Local_10>> define server bootp disabled > Done on 8-Nov-2000 (see above)
|
||||
Local_10>> define server rarp disabled /
|
||||
|
||||
Local_10>> define port 2-8 access remote
|
||||
Local_10>> define port 2-8 autobaud disable
|
||||
Local_10>> define port 2-8 break disable
|
||||
Local_10>> define port 2-8 broadcast disable
|
||||
Local_10>> define port 2-8 flow control none
|
||||
Local_10>> define port 2-8 loss notif disable
|
||||
Local_10>> define port 2-8 modem disable
|
||||
Local_10>> define port 2-8 passflow enable
|
||||
Local_10>> define port 2-8 telnet pad disable
|
||||
Local_10>> define port 2-8 verific disable
|
||||
|
||||
Local_10>> define port 7 stop 2
|
||||
|
||||
Local_10>> init delay 0
|
||||
|
||||
Local_10>> show server char
|
||||
|
||||
ETS8P Version V3.5/5(980529) Uptime: 0:08:00
|
||||
Hardware Addr: 00-80-a3-17-09-7f Name/Nodenum: ETS_17097F/ 0
|
||||
Ident String: TASP Terminal Server
|
||||
|
||||
LAT Circuit Timer (msec): 80 Password Limit: 3
|
||||
Inactive Timer (min): 30 Console Port: 1
|
||||
Queue Limit: 32 Retrans Limit: 50
|
||||
Keepalive Timer (sec): 20 Session Limit: 4
|
||||
Multicast Timer (sec): 30 Node/Host Limits: 50/20
|
||||
|
||||
TCP/IP Address: 129.129.120.202 Subnet Mask: 255.255.0.0
|
||||
Nameserver: 129.129.110.10 Backup Nameserver: (undefined)
|
||||
TCP/IP Gateway: 129.129.100.2 Backup Gateway: 129.129.30.4
|
||||
Domain Name: psi.ch Daytime Queries: Enabled
|
||||
TCP Keepalives: Enabled
|
||||
DHCP Server: None Lease Time: 0:00
|
||||
|
||||
Serial Delay (msec): 10 Network Buffering: 256
|
||||
Prompt: Local_%n%P>
|
||||
Groups: 0
|
||||
|
||||
Characteristics: Announce Broadcast Lock
|
||||
Incoming Logins: Telnet (No Passwords Required)
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
49
doc/programmer/macro.tex
Normal file
49
doc/programmer/macro.tex
Normal file
@@ -0,0 +1,49 @@
|
||||
\subsection{The Macro Interpreter}
|
||||
This module is responsible for splicing the Tcl macro interpreter into
|
||||
the SICS framework. In order to achieve this several problems have to be
|
||||
adressed:
|
||||
\begin{itemize}
|
||||
\item How to make Tcl commands available from within SICS.
|
||||
\item How to call SICS with the correct execution context from Tcl macros.
|
||||
\end{itemize}
|
||||
The first problem is solved by overloading Tcl's unknown mechanism. The Tcl
|
||||
interpreter automatically invokes a procedure {\bf unknown} when it cannot
|
||||
find a command. The usual procedure in this case searches for Tcl procedures
|
||||
in libraries and then tries to invoke the command as a shell command. For
|
||||
SICS the last part has been cut off and replaced by a call to SICSUnknown
|
||||
which tries to find an appropriate SICS command.
|
||||
|
||||
The second problem is solved by maintaing a stack of connection objects.
|
||||
Before a Tcl command is invoked from SICS the current connection object is
|
||||
pushed on the stack. If in due course SICSUnknown needs to find a connection
|
||||
object in order to invoke a SICS object the last object from the stack will
|
||||
be used. If Tcl finishes, the connection object is popped from the stack.
|
||||
This is nicely shown in the TclAction code.
|
||||
All this is implemented in macro.c.
|
||||
|
||||
The macro module presents the following interface to the outside world:\begin{itemize}
|
||||
\item {\bf Tcl\_Interp *MacroInit(SicsInterp *pInter,SConnection *pCon) } initialises a Tcl interpreter with a SICS unknown mechanism. Furthermore deletes some Tcl standard commands which can be harmful in SICS. Returns a pointer to an interpreter on success, NULL else.
|
||||
\item {\bf void MacroDelete(Tcl\_Interp *pInter) } deletes an interpreter.
|
||||
\item {\bf int MacroFileEval(SConnection *pCon, SicsInterp *pInter, void *pData, int argc, char *argv) }, the SICS object wrapper function for script processing.
|
||||
\item {\bf int InternalFileEval(SConnection *pCon, SicsInterp *pInter,
|
||||
void *pData, int argc, char *argv) }, the SICS object wrapper
|
||||
function for script processing. This version suppresses output to the
|
||||
client however. All output goes into the command log only.
|
||||
\item {\bf int ClientPut(SConnection *pCon, SicsInterp *pInter, void *pData, int argc, char *argv) },
|
||||
the SICS object wrapper function for writing datato a client from
|
||||
within a Tcl--script.
|
||||
\item {\bf int MacroWhere(SConnection *pCon, SicsInterp *pInter,
|
||||
void *pData, int argc, char *argv) }, the SICS object wrapper
|
||||
function implementing the filewhere command.
|
||||
\item {\bf int TclPublish(SConnection *pCon, SicsInterp *pSics, void *pData,
|
||||
int argc, char *argv[])} is the implmentation of the Publish command for the
|
||||
interpreter which installs a Tcl command into the system.
|
||||
\item {\bf int TransactAction (SConnection *pCon, SicsInterp *pInter,
|
||||
void *pData, int argc, char *argv) } This Function implements the
|
||||
transact command which executes an command and sends a string
|
||||
``TRANSACTIONFINISHED'' when the command finished executing.
|
||||
\item {\bf MacroPush} pushes a connection onto the Tcl connection
|
||||
stack.
|
||||
\item {\bf MacroPop} removes a connection for the Tcl connection
|
||||
stack.
|
||||
\end{itemize}
|
||||
126
doc/programmer/mesure.tex
Normal file
126
doc/programmer/mesure.tex
Normal file
@@ -0,0 +1,126 @@
|
||||
\subsection{Four Circle Single Counter Measurement Object}
|
||||
This object implements a basic single counter reflection measurement routine
|
||||
for four circle diffractometers. This object is able to read a reflection
|
||||
listing, drive to each reflection in the list, do a scan on it, integrate
|
||||
the scan results and write the results to ASCII files. Nothing sophisticated
|
||||
such as optimised measurement procedures and special background measurement
|
||||
programs. Three files will be created as output: one file with the ending
|
||||
.rfl which contains the reflection profiles for each reflection, a file .asc
|
||||
which contains a summary in form of HKL, I, sigma(I) for each reflection
|
||||
and a file ending .err which contains all the error messages obtained during
|
||||
the run.
|
||||
|
||||
|
||||
The interface to this object consists of these functions:
|
||||
|
||||
\begin{flushleft} \small
|
||||
\begin{minipage}{\linewidth} \label{scrap1}
|
||||
$\langle$mesureint {\footnotesize ?}$\rangle\equiv$
|
||||
\vspace{-1ex}
|
||||
\begin{list}{}{} \item
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@ typedef struct __Mesure *pMesure;@\\
|
||||
\mbox{}\verb@/*--------------------- live & death --------------------------------------*/@\\
|
||||
\mbox{}\verb@ pMesure CreateMesure(pHKL pCryst, pScanData pScanner, @\\
|
||||
\mbox{}\verb@ pMotor pOmega, char *pom, char *po2t,@\\
|
||||
\mbox{}\verb@ char *pFileRoot,pDataNumber pDanu);@\\
|
||||
\mbox{}\verb@ void DeleteMesure(void *pData);@\\
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@ int MesureFactory(SConnection *pCon, SicsInterp *pSics, void *pData,@\\
|
||||
\mbox{}\verb@ int argc, char *argv[]);@\\
|
||||
\mbox{}\verb@/*------------------- object functions -----------------------------------*/@\\
|
||||
\mbox{}\verb@ int MesureReflection(pMesure self, float fHKL[3], SConnection *pCon);@\\
|
||||
\mbox{}\verb@ int MesureGenReflection(pMesure self, float fHKL[3],float fSet[4], SConnection *pCon);@\\
|
||||
\mbox{}\verb@ int MesureStart(pMesure self, SConnection *pCon);@\\
|
||||
\mbox{}\verb@ int MesureReopen(pMesure self, char *filename, SConnection *pCon);@\\
|
||||
\mbox{}\verb@ int MesureClose(pMesure self);@\\
|
||||
\mbox{}\verb@ int MesureFile(pMesure self, char *pFile, int iSkip, SConnection *pCon);@\\
|
||||
\mbox{}\verb@ int MesureGenFile(pMesure self, char *pFile, int iSkip, SConnection *pCon);@\\
|
||||
\mbox{}\verb@ int MesureSetPar(pMesure self, char *name, float fVal);@\\
|
||||
\mbox{}\verb@ int MesureGetPar(pMesure self, char *name, float *fVal);@\\
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@ int MesureAction(SConnection *pCon, SicsInterp *pSics, void *pData,@\\
|
||||
\mbox{}\verb@ int argc, char *argv[]);@\\
|
||||
\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}
|
||||
All functions return 1 on success, 0 on failure.
|
||||
\begin{description}
|
||||
\item[CreateMesure] creates a new pMesure object. Parameters are the HKL
|
||||
object to use for cystallographic conversions and the scan object to use for
|
||||
doing the scans. This is followd by the motor for running omega, its name
|
||||
and the name of the motor for driving omega 2 theta. Finnaly the path to the
|
||||
data directory and the data number object for automatic filename creation is
|
||||
specified.
|
||||
\item[DeleteMesure] wipes the mesure object pData from memory.
|
||||
\item[MesureFactory] is the factory function for mesure which will be used
|
||||
by the interpreter to install mesure into the system.
|
||||
\item[MesureReflection] measures the single reflection fHKL. It drives
|
||||
there, calculates scan borders and performs the scan.
|
||||
\item[MesureGenReflection] measures the single reflection fHKL. It drives
|
||||
there, calculates scan borders and performs the scan. This version uses
|
||||
supplied values for the instrument settings.
|
||||
\item[MesureStart] sets everything up for a new measurement with new file
|
||||
names.
|
||||
\item[MesureReopen] reopens the files belonging to the file name given as
|
||||
base for appending. This is a recovery feature.
|
||||
\item[MesureFile] opens the file specified as second parameter and reads
|
||||
each line. Expected is a reflection to measure. Each reflection is then
|
||||
measured and output written. The last parameter iSkip allows to skip iSkip
|
||||
lines of the reflection file. This facility exists in order to restart work
|
||||
on an reflection file which had been interrupted for some reason.
|
||||
\item[MesureGenFile] opens the file specified as second parameter and reads
|
||||
each line. Expected is a reflection to measure. Each reflection is then
|
||||
measured and output written. The last parameter iSkip allows to skip iSkip
|
||||
lines of the reflection file. This facility exists in order to restart work
|
||||
on an reflection file which had been interrupted for some reason. This
|
||||
version acts upon files created by the program HKLGEN.
|
||||
\item[MesureSetPar] sets the parameter name of Mesure to fVal. A listing of
|
||||
possible parameters is given below.
|
||||
\item[MesureGetPar] returns the value of the parameter name in fVal.
|
||||
\item[MesureAction] implements the interpreter interface to the mesure
|
||||
object.
|
||||
\end{description}
|
||||
Mesure supports the following parameters:
|
||||
\begin{description}
|
||||
\item[np] the number of points per scan.
|
||||
\item[preset] The preset value for counting.
|
||||
\item[countmode] the counting mode, can be 0 for timer or 1 for monitor
|
||||
mode.
|
||||
\item[mode] can be 0 for omega 2theta scans or 1 for omega scans.
|
||||
\item[step] the scan step widths. This is allways in omega, in omega 2theta
|
||||
mode 2theta is always the double of this.
|
||||
\end{description}
|
||||
|
||||
\begin{flushleft} \small
|
||||
\begin{minipage}{\linewidth} \label{scrap2}
|
||||
\verb@"mesure.h"@ {\footnotesize ? }$\equiv$
|
||||
\vspace{-1ex}
|
||||
\begin{list}{}{} \item
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@/*----------------------------------------------------------------------------@\\
|
||||
\mbox{}\verb@ M E S U R E@\\
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@ A SICS object for doing simple four circle measurements with a single@\\
|
||||
\mbox{}\verb@ counter. @\\
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@ copyright: see copyright.h@\\
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@ Mark Koenencke, April 1998@\\
|
||||
\mbox{}\verb@---------------------------------------------------------------------------*/@\\
|
||||
\mbox{}\verb@#ifndef SICSMESURE@\\
|
||||
\mbox{}\verb@#define SICSMESURE@\\
|
||||
\mbox{}\verb@@$\langle$mesureint {\footnotesize ?}$\rangle$\verb@@\\
|
||||
\mbox{}\verb@#endif@\\
|
||||
\mbox{}\verb@@$\diamond$
|
||||
\end{list}
|
||||
\vspace{-2ex}
|
||||
\end{minipage}\\[4ex]
|
||||
\end{flushleft}
|
||||
209
doc/programmer/motor.tex
Normal file
209
doc/programmer/motor.tex
Normal file
@@ -0,0 +1,209 @@
|
||||
\subsection{Motors}
|
||||
Most neutron scattering instruments have lots of motors to drive
|
||||
monochromators, samples and detectors through space.This module implements
|
||||
support for them. As usual for hardware objects in SICS motors are
|
||||
subdivided into a driver and the logical object.
|
||||
|
||||
\subsubsection{The Motor Driver}
|
||||
There is a problem here. There are some data fields and functions
|
||||
which must be present for any motor driver. Then there are fields
|
||||
which are specific just to a special implementation of a mot
|
||||
driver. There are several ways to deal with this. The way choosen for
|
||||
the motor driver is a kind of overlay. The first few fields of a valid
|
||||
motor driver structure MUST be specified in the same order as given
|
||||
below. A special motor driver can add additional fields at the end of
|
||||
the standard list. As an example for this scheme compare the
|
||||
AbstractMoDriv structure with the one for the EL734 motor driver.
|
||||
\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 (*ContinueAfterWarn)(void *self);
|
||||
int (*Halt)(void *self);
|
||||
}
|
||||
MotorDriver;
|
||||
\end{verbatim}
|
||||
All functions return 0 on failure or 1 on success, if not stated otherwise.
|
||||
The first parameter is always a pointer to the motor driver structure.
|
||||
The fields and their meanings: \begin{description}
|
||||
\item[fUpper,fLower] The hardware upper and lower limits for the motor.
|
||||
These are the real hardware limits as implemented by limit switches bolted
|
||||
to the instrument.
|
||||
\item[name] The real motor name.
|
||||
\item[GetPosition] retrieves the current hardware position of the motor into
|
||||
fPos.
|
||||
\item[RunTo] starts the motor to run to fNewVal. This sends a command to the
|
||||
motor and returns immediately.
|
||||
\item[GetStatus] requests the status from the motor. Possible answers are:
|
||||
\begin{description}
|
||||
\item[HWIdle, OKOK] The motor has finished or is idle.
|
||||
\item[HWFault] A fault has been found at the motor.
|
||||
\item[HWBusy] The motor is busy moving.
|
||||
\item[HWWarn] The motor hardware complained but managed to reach the
|
||||
requested position.
|
||||
\item[HWPosFault] The motor could not go where it should go for some reason.
|
||||
However, the motor is intact and ready to move somewhere else. This can
|
||||
happen when there is a concrete block in the instruments way which is not
|
||||
accounted for by a limit switch. This can also happen when the motor hits a
|
||||
limit switch. However, the general idea of SICS is that the limits will be
|
||||
checked for before even starting to run the motor. In order for this to
|
||||
work, the limits SICS knows about must macth those actually implemented.
|
||||
\end{description}
|
||||
\item[GetError] This gets called when an error has been detected during one
|
||||
of the previous operations. The function has to return more information
|
||||
about the error: iCode an driver dependent integer error code and maximum
|
||||
iErrLen characters of problem description in error.
|
||||
\item[TryAndFixIt] takes the integer error code returned in iCode from
|
||||
GetError and tries to solve the problem with the hardware. This function can
|
||||
either return MOTREDO which means the problem has been fixed and the
|
||||
operation needs to be redone, MOTOK when the problem has been fixed and no
|
||||
resending of a command is necessary or MOTFAIL which means that it is not
|
||||
possible to resolve the problem in software.
|
||||
\item[ContinueAfterWarn] will be called after a warning from the motor. This
|
||||
function is supposed to do whatever is needed to clear the warning from the
|
||||
motor and keep him going.
|
||||
\item[Halt] emergency stop the motor, NOW.
|
||||
\end{description}
|
||||
|
||||
As an example for a derived motor driver the SINQ EL734 motor driver is
|
||||
shown below. It add to the general fields the special things for that motor:
|
||||
host, port and channel number of the motor controller and a pointer to the
|
||||
driver communications structure.
|
||||
\begin{verbatim}
|
||||
typedef struct __MoDriv {
|
||||
/* 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 (*ContinueAfterWarn)(void *self);
|
||||
int (*Halt)(void *self);
|
||||
|
||||
|
||||
/* EL-734 specific fields */
|
||||
int iPort;
|
||||
char *hostname;
|
||||
int iChannel;
|
||||
int iMotor;
|
||||
void *EL734struct;
|
||||
int iMSR;
|
||||
} EL734Driv;
|
||||
\end{verbatim}
|
||||
|
||||
Most of the interaction with the motor driver happens through the functions
|
||||
defined in its data structure. The rest is creation and deletion:
|
||||
\begin{description}
|
||||
\item[MotorDriver *CreateEL734(SConnection *pCon, int argc, char
|
||||
*argv[])]
|
||||
creates a EL734 motor driver. The argc, \verb+argv[]+ pair contains the
|
||||
necessary drive parameters.
|
||||
\item[MotorDriver *CreateEL734DC(SConnection *pCon, int argc, char
|
||||
*argv[])]
|
||||
created an EL734 DC motor driver.
|
||||
\item[void KillEL734(void *pData)] deletes a EL734 motor driver.
|
||||
\item[MotorDriver *CreateSIM(SConnection *pCon, int argc, char *argv[])]
|
||||
creates a simulation motor driver.
|
||||
\item[void KillSIM(void *pData)] deletes a simulated motor driver.
|
||||
\end{description}
|
||||
|
||||
\subsubsection{The Motor Logical Object}
|
||||
The motor object represents the motor to SICS. One of its responsabilities
|
||||
is to drive motor operations and error checking. The scheme
|
||||
implemented is that the motor object tries to bring the motor to its
|
||||
position at least three times before a failure is recorded. Also the
|
||||
motor object keeps track of a count of failed operations. If this
|
||||
count gets to high an interrupt is issued to stop the instrument. This
|
||||
was put in after Druechal tried to drive over a slab of concrete for a
|
||||
whole night and subsequently broke a clutch.
|
||||
Motors are represented by the
|
||||
following data structure:
|
||||
\begin{verbatim}
|
||||
typedef struct __Motor {
|
||||
pObjectDescriptor pDescriptor;
|
||||
ObPar *ParArray;
|
||||
pIDrivable pDrivInt;
|
||||
pICallBack pCall;
|
||||
char *drivername;
|
||||
char *name;
|
||||
MotorDriver *pDriver;
|
||||
float fTarget;
|
||||
float fPosition;
|
||||
} Motor;
|
||||
typedef Motor *pMotor;
|
||||
\end{verbatim}
|
||||
The fields: \begin{description}
|
||||
\item[pDescriptor] The usual SICS object descriptor.
|
||||
\item[ParArray] A dictionary of parameter names and float values. This array
|
||||
holds all the different parameters used to operate the motor.
|
||||
\item[pDrivInt] A pointer to the drivable interface implemented by the motor
|
||||
object.
|
||||
\item[pCall] A pointer to the callback interface implemented by the motor
|
||||
object.
|
||||
\item[drivername] The name of the motor driver.
|
||||
\item[name] The name of the motor.
|
||||
\item[pDriver] A pointer to the motor driver to use.
|
||||
\item[fTarget] The target position for the motor.
|
||||
\item[fPosition] The last known position of the motor.
|
||||
\end{description}
|
||||
|
||||
Much of the action of the motor is hidden in the implementation of the
|
||||
drivable interface to the motor. Additionally the functions as given below
|
||||
are defined. All functions take a pointer to the motor object data structure
|
||||
as a parameter. They retun 0 on success or 1 on failure while not stated
|
||||
otherwise.
|
||||
\begin{description}
|
||||
\item[int MotorGetPar(pMotor self, char *name, float *fVal)] retrieves the
|
||||
value of the parameter name in fVal.
|
||||
\item[int MotorSetPar(pMotor self, SConnection *pCon, char *name, float
|
||||
fVal)] tries to write fVal to the parameter name. Errors are written to
|
||||
the connection pCon.
|
||||
\item[long MotorRun(void *self, SConnection *pCon, float fNew)] starts a
|
||||
motor running to fNew. Does not wait for the motor to finish.
|
||||
\item[int MotorCheckBoundary(pMotor self, float fVal, float *fHard,
|
||||
char *error, int iErrLen)] checks if the position
|
||||
fVal violates any of the motors software or hardware limits. In case of
|
||||
success a new hardware position is returned in fHard. fHard is then
|
||||
corrected for possible software zero points. In case of a limit violation
|
||||
maximum iErrLen characters of error information are returned in error.
|
||||
\item[int MotorCheckPosition(void *self, SConnection *pCon)] returns 1 if
|
||||
the motor is at the target position, 0 else, or -1 if the motor could not be
|
||||
read.
|
||||
\item[int MotorGetSoftPosition(pMotor self,SConnection *pCon, float *fVal)]
|
||||
reads the current motor position into fVal. This position is corrected for
|
||||
software zero points.
|
||||
\item[int MotorGetHardPosition(pMotor self,SConnection *pCon, float *fVal)]
|
||||
reads the current position of the motor as returned from the hardware.
|
||||
\item[int MakeMotor(SConnection *pCon, SicsInterp *pSics, void *pData,
|
||||
int argc, char *argv[])] the motor factory function. To
|
||||
be hacked when a new driver needs to be included.
|
||||
\item[pMotor MotorInit(char *drivername,char *name, MotorDriver *pDriv)]
|
||||
creates a new motor object with driver pDriv. Returns NULL on failure.
|
||||
\item[void MotorKill(void *self)] deletes a motor object. Needs to be
|
||||
modified for a new driver in order to clean out the new driver properly.
|
||||
\item[int MotorAction(SConnection *pCon, SicsInterp *pSics, void *pData,
|
||||
int argc, char *argv[])] the object wrapper function for
|
||||
the motor. Implements the user interface.
|
||||
\item[pMotor FindMotor(SicsInterp *pSics, char *name)] finds a motor name in
|
||||
the interpreter pSics. This is a convenience function. Returns NULL if no
|
||||
motor could be found, else a pointer to its data structure.
|
||||
\end{description}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
49
doc/programmer/mumo.tex
Normal file
49
doc/programmer/mumo.tex
Normal file
@@ -0,0 +1,49 @@
|
||||
\subsection{Multiple Motors}
|
||||
Multiple Motors is a module which implements a special syntax for SANS.
|
||||
Motors are collected into a group. For example beamstop and manipulated
|
||||
through them. Furthermore multiple motors support named positions and a
|
||||
special position {\bf back} which is the position before the last movement.
|
||||
Multiple Motors works, but it if larger changes become necessary it might be
|
||||
sensible to drop it and replace it by a work alike in the macro language.
|
||||
Please note, that multiple motors starts motors to run, but does not wait
|
||||
for them to finish.
|
||||
|
||||
Multiple motors are characterized through the following data structure:
|
||||
\begin{verbatim}
|
||||
typedef struct __MULMOT {
|
||||
pObjectDescriptor pDes;
|
||||
char *name;
|
||||
pStringDict pAlias;
|
||||
pStringDict pNamPos;
|
||||
ObPar *pParam;
|
||||
} MulMot;
|
||||
\end{verbatim}
|
||||
The fields are:
|
||||
\begin{description}
|
||||
\item[pDes] A pointer to the usual SICS object descriptor.
|
||||
\item[name] The name of the multi motor.
|
||||
\item[pAlias] A string dictionary which maps group internal motor names to
|
||||
real SICS motor names.
|
||||
\item[pNamPos] A string dictionary which maps named positions to the SICS
|
||||
command necessary to run to that position.
|
||||
\end{description}
|
||||
|
||||
Multiple motors are interfaced to with the following functions:
|
||||
\begin{description}
|
||||
\item[pMulMot MakeMultiMotor(void)] creates multi motors device. Returns a
|
||||
pointer to a new data structure on success, NULL in case of failure.
|
||||
\item[void KillMultiMotor(void *pData)] deletes a multi motor device.
|
||||
\item[int MultiWrapper(SConnection *pCon, SicsInterp *pSics, void *pData, \\
|
||||
int argc, char *argv[])] The object wrapper function for
|
||||
multiple motors.
|
||||
\item[int MakeMulti(SConnection *pCon, SicsInterp *pSics, void *pData,\\
|
||||
int argc, char *argv[])] The object factory function for
|
||||
multiple motors.
|
||||
\item[int ConfigMulti(SConnection *pCon, SicsInterp *pSics, void *pData,\\
|
||||
int argc, char *argv[])] The configuration function for
|
||||
multiple motors.
|
||||
\end{description}
|
||||
|
||||
The implementation of multiple motors can be found in files mumo.c,
|
||||
mumoconf.c, mumo.h and mumo.i.
|
||||
|
||||
1850
doc/programmer/napi.tex
Normal file
1850
doc/programmer/napi.tex
Normal file
File diff suppressed because it is too large
Load Diff
389
doc/programmer/nconman.tex
Normal file
389
doc/programmer/nconman.tex
Normal file
@@ -0,0 +1,389 @@
|
||||
\subsection{The Connection Object}
|
||||
The connection object is a major player in the SICS world. The connection
|
||||
object represents an active connection between the SICS server and a client.
|
||||
There will be one connection object for each client connection. A lot of
|
||||
stuff is associated with a client connection:
|
||||
\begin{itemize}
|
||||
\item A task. This task will read one command from the command fifo and
|
||||
execute it.
|
||||
\item A command fifo which will be filled by the network reader.
|
||||
\item An execution context consisting of user rights for this connection
|
||||
and interrupt status.
|
||||
\item A communication channel to the client.
|
||||
\item A list of log files to which all traffic on the connection will be
|
||||
logged.
|
||||
\item An interface to the SICS interpreter which allows to configure
|
||||
certain aspects of the connection and makes the connection available as
|
||||
a command.
|
||||
\item A list of callbacks registered for the connection. A connection can
|
||||
be automatically notified about changes in system state. These callbacks
|
||||
have to be removed when the client server connection terminates. Otherwise
|
||||
callback code would write to a dead connection causing the program to
|
||||
crash.
|
||||
\end{itemize}
|
||||
|
||||
\subsubsection{Connection I/O}
|
||||
Due to user requirements for features not considered in the design the
|
||||
I/O facilities of connection have become quite involved.
|
||||
|
||||
Incoming commands are printed into client log files if configured, and
|
||||
into the commandlog if the connection has a privilege $\ge$ user
|
||||
privilege. This is implemented in SCInvoke. Also each command is
|
||||
printed to the server log.
|
||||
|
||||
Output is more sophisticated. First of all there are different output
|
||||
codes given as last parameter to SCWrite. The most important of these
|
||||
are:
|
||||
\begin{description}
|
||||
\item[eError] Error messages.
|
||||
\item[Warning] warnings.
|
||||
\item[Value] values requested by the client.
|
||||
\item[Status] status messages.
|
||||
\end{description}
|
||||
Clients can choose to suppress certain types of messages in order to
|
||||
reduce I/O.
|
||||
|
||||
The logic is mostly implemented in the
|
||||
file static function SCNormalWrite. The follwoing conditions are
|
||||
implemented:
|
||||
\begin{itemize}
|
||||
\item Any output is logged to the
|
||||
server log.
|
||||
\item If the privilege of the connection is $\ge$ user the
|
||||
output is printed to the commandlog as well.
|
||||
\item If the command is executing as part of a Tcl--macro script
|
||||
output to the socket is suppressed. The output is copied into the
|
||||
interpreter for further evaluation instead. This is done in order to
|
||||
prevent excessive output during macro evaluation and in order to make
|
||||
SICS results available in the Tcl interpreter. However, messages of
|
||||
type error or warning are printed to the socket even during macro
|
||||
evaluation.
|
||||
\item In the normal case the output is printed to the socket and all
|
||||
log files configured for the connection.
|
||||
\item As of recent the output function can be modified by setting a
|
||||
new function. One sich function exists which supresses all output to
|
||||
the socket. This is done in order to help when the connection gets
|
||||
lost. For instance with the cron command.
|
||||
\end{itemize}
|
||||
This aspect of the connection object could do with a cleanup. A
|
||||
possible cleanup path is the implementation of the different output
|
||||
strategies in different functions and devise a SCsetOutMode function which
|
||||
switches between the various possibilities. Also, it can be argued if
|
||||
the client specific log files are still needed. Then this part of the
|
||||
code can be cleaned out as well.
|
||||
|
||||
|
||||
\subsubsection{Command Execution Path}
|
||||
In the course of the SICS development the path of a command through
|
||||
the system has become more complex as well. This section describes how
|
||||
it works. The incoming command is collected at the socket by the
|
||||
NetReaderTask. This does a little processing and checks for interrupts
|
||||
issued on the connection and invokes them. But any normal command is
|
||||
put into the connections Command-FIFO. Thus ends the business of the
|
||||
NetReaderTask. The connections task function SCTaskFunction is
|
||||
invoked by the task manager in due time and checks for pending
|
||||
commands on the command stack. If a command is pending it is taken
|
||||
from the stack and executed through SCInvoke.
|
||||
|
||||
\subsubsection{Execution context}
|
||||
Each connection has a user right code associated with it. The there is
|
||||
a second protection scheme in SICS with the token system. This system
|
||||
reserves command input to a certain connection. In the connection
|
||||
object this scheme requires the iGrab field which defines if this
|
||||
connection may execute commands or not. This field is modified through
|
||||
the tasks signal handling function. Code implementing a command may
|
||||
call SCMatchRights in order to check for permission. SCMatchRights
|
||||
will also send appropriate error messages.
|
||||
|
||||
Errors are usually signalled by setting an interrupt code on the
|
||||
connection. An additional field, iError allows to give a more detailed
|
||||
error description if required.
|
||||
|
||||
\subsubsection{Callbacks}
|
||||
SICS can be configured to forward notifications about certain state
|
||||
changes to a connection automatically. This is implemented through the
|
||||
callback system. For more details see \ref{inter}. However, it is
|
||||
important that any callback acting on a connection is registered with
|
||||
the connection object. This allows the removal of the callback when
|
||||
the connection is closed. Otherwsie the system gets filled up with
|
||||
dead callbacks which usuallly cause core dumps when it is tried to
|
||||
send a message to a dead connection.
|
||||
|
||||
|
||||
\subsubsection{The Connection Data Structure}
|
||||
Given the plethora of things to take care of, each connection is
|
||||
represented by a rather large data structure.
|
||||
|
||||
\begin{flushleft} \small
|
||||
\begin{minipage}{\linewidth} \label{scrap1}
|
||||
$\langle$condat {\footnotesize ?}$\rangle\equiv$
|
||||
\vspace{-1ex}
|
||||
\begin{list}{}{} \item
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@ typedef struct __SConnection {@\\
|
||||
\mbox{}\verb@ /* object basics */@\\
|
||||
\mbox{}\verb@ pObjectDescriptor pDes;@\\
|
||||
\mbox{}\verb@ char *pName;@\\
|
||||
\mbox{}\verb@ long lMagic;@\\
|
||||
\mbox{}\verb@ @\\
|
||||
\mbox{}\verb@ /* I/O control */@\\
|
||||
\mbox{}\verb@ mkChannel *pSock;@\\
|
||||
\mbox{}\verb@ FILE *pFiles[MAXLOGFILES];@\\
|
||||
\mbox{}\verb@ int iMacro;@\\
|
||||
\mbox{}\verb@ int iTelnet;@\\
|
||||
\mbox{}\verb@ int iOutput; @\\
|
||||
\mbox{}\verb@ int iFiles;@\\
|
||||
\mbox{}\verb@ int (*write)(struct __SConnection *pCon,@\\
|
||||
\mbox{}\verb@ char *pMessage, int iCode);@\\
|
||||
\mbox{}\verb@ mkChannel *pDataSock;@\\
|
||||
\mbox{}\verb@ char *pDataComp;@\\
|
||||
\mbox{}\verb@ int iDataPort;@\\
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@ /* execution context */@\\
|
||||
\mbox{}\verb@ int eInterrupt;@\\
|
||||
\mbox{}\verb@ int iUserRights;@\\
|
||||
\mbox{}\verb@ int inUse;@\\
|
||||
\mbox{}\verb@ int iDummy;@\\
|
||||
\mbox{}\verb@ int iGrab;@\\
|
||||
\mbox{}\verb@ int iErrCode;@\\
|
||||
\mbox{}\verb@ SicsInterp *pSics;@\\
|
||||
\mbox{}\verb@ @\\
|
||||
\mbox{}\verb@ /* a FIFO */@\\
|
||||
\mbox{}\verb@ pCosta pStack;@\\
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@ /* callback registry */@\\
|
||||
\mbox{}\verb@ int iList;@\\
|
||||
\mbox{}\verb@ @\\
|
||||
\mbox{}\verb@ /* Tasking Stuff */@\\
|
||||
\mbox{}\verb@ int iEnd;@\\
|
||||
\mbox{}\verb@ }SConnection;@\\
|
||||
\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 fields are:
|
||||
\begin{description}
|
||||
\item[pDes] The usual object descriptor belonging to any object within the
|
||||
SICS interpreter. See \ref{inter} for details.
|
||||
\item[pName] The automatically generated name of the connection object in the
|
||||
interpreter.
|
||||
\item[lMagic] is a magic number used internally in order to check if
|
||||
the connection object given as a parameter is valid.
|
||||
|
||||
\item[pChannel] A pointer to a network channel structure. This channel
|
||||
will be used for I/O to the client. If thispointer is NULL I/O is done onto
|
||||
stdin/stdout instead.
|
||||
\item[pFiles] An array of file to which all I/O on this connection will be
|
||||
logged.
|
||||
\item[iOutPut] The currently valid output mask. SICS messages are classified
|
||||
into several output classes. If a message is going to be printed it must
|
||||
have a output class above the one configured as the mask. This was made in
|
||||
order to allow clients to suppress certain messages which are not of
|
||||
interest.
|
||||
\item[iFiles] The number of configured log files.
|
||||
\item[write] a pointer to a function which does the actual writing of
|
||||
a message to the connection.
|
||||
\item[iTelnet] is true when I/O is through a telnet connection.
|
||||
\item[iMacro] This flag is set when the connection is executing a Tcl
|
||||
script. In this mode mode all output is written into the Tcl interpreter and
|
||||
not written to the client. Thus a script can execute silently. As always,
|
||||
there is an exception: errors and warning will still be written to the
|
||||
client.
|
||||
|
||||
\item[iGrab] This is 0 when the connection may execute commands. It is 1 if
|
||||
another connection has grabbed the control token and commands may not be
|
||||
executed. For details about the token system, see the token reference.
|
||||
\item[eInterrupt] This is the current interrupt status of the connection.
|
||||
\item[iUserRights] This integer denotes the user rights associated with the
|
||||
connection. This value is initially deducted from the username password pair
|
||||
given at login to SICS. The value can be configured otherwise afterwards.
|
||||
iUserRights will be used to check at object level if a client may perform
|
||||
the requested operation or not.
|
||||
\item[iErrCode] is the last error code. I think this field is no longer
|
||||
used.
|
||||
|
||||
\item[pSics] is a pointer to an SICS interpreter where to invoke commands.
|
||||
\item[pStack] Is the command FIFO.
|
||||
\item[iList] This is the identifier of a lld list which holds the callbacks
|
||||
registered on this connection object.
|
||||
\item[iEnd] iEnd is a flag which is usually 0. It is set by certain
|
||||
interrupts or if the connection is broken and causes the connection task to
|
||||
end and the connection data structure to be removed from the system.
|
||||
\end{description}
|
||||
Quite a few places in SICS refer to this data structure directly,
|
||||
without a function interface. The reason for this is performance. Therefore
|
||||
this data structure is made public in the conman.h file.
|
||||
|
||||
|
||||
\subsubsection{Connection Functions}
|
||||
The interface to this data structure is defined by the following functions:
|
||||
\begin{flushleft} \small
|
||||
\begin{minipage}{\linewidth} \label{scrap2}
|
||||
$\langle$conint {\footnotesize ?}$\rangle\equiv$
|
||||
\vspace{-1ex}
|
||||
\begin{list}{}{} \item
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@/*------------------------------ live & death ----------------------------*/@\\
|
||||
\mbox{}\verb@ SConnection *SCreateConnection(SicsInterp *pSics, mkChannel *pSock,@\\
|
||||
\mbox{}\verb@ int iUserRights);@\\
|
||||
\mbox{}\verb@ SConnection *SCCreateDummyConnection(SicsInterp *pSics);@\\
|
||||
\mbox{}\verb@ void SCDeleteConnection(void *pVictim);@\\
|
||||
\mbox{}\verb@ @\\
|
||||
\mbox{}\verb@/*------------------------------- tasking --------------------------------*/@\\
|
||||
\mbox{}\verb@ int SCTaskFunction(void *pCon);@\\
|
||||
\mbox{}\verb@ void SCSignalFunction(void *pCon, int iSignal, void *pSigData);@\\
|
||||
\mbox{}\verb@/* ***************************** I/O ************************************** */@\\
|
||||
\mbox{}\verb@ int SCAddLogFile(SConnection *self, char *name);@\\
|
||||
\mbox{}\verb@ int SCDelLogFile(SConnection *pCon, int iFile);@\\
|
||||
\mbox{}\verb@ void SCSetOutputClass(SConnection *self, int iClass);@\\
|
||||
\mbox{}\verb@ int SCWrite(SConnection *self, char *pBuffer, int iOut);@\\
|
||||
\mbox{}\verb@ int SCRead(SConnection *self, char *pBuffer, int iBufLen); @\\
|
||||
\mbox{}\verb@ int SCPrompt(SConnection *pCon, char *pPrompt, char *pResult, int iLen);@\\
|
||||
\mbox{}\verb@ int SCSendOK(SConnection *self);@\\
|
||||
\mbox{}\verb@ int SCnoSock(SConnection *pCon);@\\
|
||||
\mbox{}\verb@ int SCWriteUUencoded(SConnection *pCon, char *pName, void *iData, int iLen);@\\
|
||||
\mbox{}\verb@/************************* CallBack *********************************** */@\\
|
||||
\mbox{}\verb@ int SCRegister(SConnection *pCon, SicsInterp *pSics,@\\
|
||||
\mbox{}\verb@ void *pInter, long lID);@\\
|
||||
\mbox{}\verb@ int SCUnregister(SConnection *pCon, void *pInter);@\\
|
||||
\mbox{}\verb@/******************************* Error **************************************/@\\
|
||||
\mbox{}\verb@ void SCSetInterrupt(SConnection *self, int eCode);@\\
|
||||
\mbox{}\verb@ int SCGetInterrupt(SConnection *self); @\\
|
||||
\mbox{}\verb@ void SCSetError(SConnection *pCon, int iCode);@\\
|
||||
\mbox{}\verb@ int SCGetError(SConnection *pCon); @\\
|
||||
\mbox{}\verb@/****************************** Macro ***************************************/@\\
|
||||
\mbox{}\verb@ int SCinMacro(SConnection *pCon);@\\
|
||||
\mbox{}\verb@ int SCsetMacro(SConnection *pCon, int iMode); @\\
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@/* *************************** Info *************************************** */@\\
|
||||
\mbox{}\verb@ int SCGetRights(SConnection *self);@\\
|
||||
\mbox{}\verb@ int SCSetRights(SConnection *pCon, int iNew);@\\
|
||||
\mbox{}\verb@ int SCMatchRights(SConnection *pCon, int iCode);@\\
|
||||
\mbox{}\verb@ int SCGetOutClass(SConnection *self);@\\
|
||||
\mbox{}\verb@ int SCGetGrab(SConnection *pCon);@\\
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@/* **************************** Invocation ******************************** */@\\
|
||||
\mbox{}\verb@ int SCInvoke(SConnection *self,SicsInterp *pInter,char *pCommand);@\\
|
||||
\mbox{}\verb@ @\\
|
||||
\mbox{}\verb@/*************************** User Command **********************************/@\\
|
||||
\mbox{}\verb@ int ConfigCon(SConnection *pCon, SicsInterp *pSics, void *pData,@\\
|
||||
\mbox{}\verb@ int argc, char *argv[]); @\\
|
||||
\mbox{}\verb@ int ConSicsAction(SConnection *pCon, SicsInterp *pSics, void *pData,@\\
|
||||
\mbox{}\verb@ int argc, char *argv[]); @\\
|
||||
\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[SCreateConnection] creates a new connection object. Parameters to this
|
||||
call are a pointer to a server data structure, a pointer to a network
|
||||
connection object and the user rights to use in this connection. This
|
||||
also adds a new task function for this connection to the task object.
|
||||
\item[SCCreateDummyConnection] creates a dummy connection for use during
|
||||
system initialisation. Printing to a socket will be suppressed for such a connection. But the output is printed to stdout.
|
||||
|
||||
\item[SCTaskFunction] is the task function which will be registered with the
|
||||
Tasker. This function reads a new command from the command stack (if
|
||||
available) and executes it in the interpreter.
|
||||
\item[SCSignalFunction] is the signal function for the connection
|
||||
object. This function handles interrupts and the token security
|
||||
system.
|
||||
\item[SCDeleteConnection] deletes a connection object and all its data
|
||||
structures. This function will be automatically called by the tasker when
|
||||
the task function returns with a 0.
|
||||
\item[SCAddLogFile] configures the log file name into the connection object.
|
||||
If this suceeds all I/O to the connection will be logged to this file as
|
||||
well.
|
||||
\item[SCSetOutputClass] sets the output class for the connection.
|
||||
\item[SCGetOutClass] returns the output class of the connection.
|
||||
\item[SCWrite] is the most important function of SConnection. Writes the
|
||||
buffer pBuffer with output code iOut to the client. {\em All output to the
|
||||
client has to be channelled through this function!}
|
||||
\item[SCRead] reads data from the client connection into the buffer pBuffer,
|
||||
but maximum iBufLen bytes.
|
||||
\item[SCPrompt] prompts the client for a reply. But waits only for certain
|
||||
timeout period. pPrompt is the prompt for the client, pResult is the buffer
|
||||
with the client reply. Maximum iLen bytes will be copied to
|
||||
pResult. Returns true (1) on a successfull read, else 0 (false).
|
||||
\item[SCSendOK] A short cut which sends OK to the client.
|
||||
\item[SCRegister] registers a callback with the connection. Parameters are:
|
||||
The interpreter to use, the interface with which the callback was
|
||||
registered and the ID of the callback. All automatic notifications to a
|
||||
client MUST be registered with this call. When the connection is deleted all
|
||||
these callbacks will be removed as well. Otherwise a core dump is bound to
|
||||
happen.
|
||||
\item[SCUnregister] will remove all callbacks on interface pInter for this
|
||||
connection.
|
||||
\item[SCSetInterrupt] sets an interrupt on the connection.
|
||||
\item[SCGetInterrupt] retrives the current interrupt status of the
|
||||
connection.
|
||||
\item[SCSetError] sets an error code in the connection.
|
||||
\item[SCGetError] retreives the current error code on the connection.
|
||||
\item[SCinMacro] returns true if the connection is executing a tcl script,
|
||||
returns false otherwise.
|
||||
\item[SCsetMacro] sets the iMacro flag.
|
||||
\item[SCGetRights] returns the current user rights associated with the
|
||||
connection.
|
||||
\item[SCGetGrab] gets the status of the control token for this connection.
|
||||
This calls returns 0 if the connection may execute commands and 1 if another
|
||||
connection has the control token.
|
||||
\item[SCSetRights] sets the user rights for the connection to a new value.
|
||||
\item[SCMatchRights] return true (1) if the iCode matches with the user
|
||||
rights of the connection, 0 (false) otherwise. SCMatchRights also checks for
|
||||
the status of the control token. Suitable error messages are written to pCon
|
||||
if the user rights do not match.
|
||||
\item[SCInvoke] invokes pCommand in the SICS interpreter pSics for the
|
||||
connection pCon. This function also prints the executed command into
|
||||
logfiles and into the commandlog.
|
||||
\end{description}
|
||||
|
||||
\begin{flushleft} \small
|
||||
\begin{minipage}{\linewidth} \label{scrap3}
|
||||
\verb@"conman.h"@ {\footnotesize ? }$\equiv$
|
||||
\vspace{-1ex}
|
||||
\begin{list}{}{} \item
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@/*--------------------------------------------------------------------------@\\
|
||||
\mbox{}\verb@ C O N N E C T I O N O B J E C T@\\
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@ This file defines the connection object data structure and the interface to@\\
|
||||
\mbox{}\verb@ this data structure. This is one of the most important SICS components.@\\
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@ Substantially revised from a prior version.@\\
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@ Mark Koennecke, September 1997@\\
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@ copyright: see copyright.h@\\
|
||||
\mbox{}\verb@----------------------------------------------------------------------------*/@\\
|
||||
\mbox{}\verb@#ifndef SICSCONNECT@\\
|
||||
\mbox{}\verb@#define SICSCONNECT@\\
|
||||
\mbox{}\verb@#include <stdio.h>@\\
|
||||
\mbox{}\verb@#include "costa.h"@\\
|
||||
\mbox{}\verb@#include "SCinter.h"@\\
|
||||
\mbox{}\verb@#include "network.h"@\\
|
||||
\mbox{}\verb@#include "obdes.h"@\\
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@#define MAXLOGFILES 10@\\
|
||||
\mbox{}\verb@@$\langle$condat {\footnotesize ?}$\rangle$\verb@@\\
|
||||
\mbox{}\verb@#include "nserver.h"@\\
|
||||
\mbox{}\verb@@$\langle$conint {\footnotesize ?}$\rangle$\verb@@\\
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@#endif @\\
|
||||
\mbox{}\verb@@$\diamond$
|
||||
\end{list}
|
||||
\vspace{-2ex}
|
||||
\end{minipage}\\[4ex]
|
||||
\end{flushleft}
|
||||
38
doc/programmer/network.tex
Normal file
38
doc/programmer/network.tex
Normal file
@@ -0,0 +1,38 @@
|
||||
\subsection{The network module}
|
||||
The network class encapsulates the network protocoll used for client server communications in SICS. This is the place to hack if SICS needs porting to other protocols. This class implements:\begin{verbatim}
|
||||
typedef struct {
|
||||
int sockid;
|
||||
int iType;
|
||||
struct sockaddr_in adresse;
|
||||
} mkChannel;
|
||||
\end{verbatim}
|
||||
|
||||
This is the datastructure maintained for each socket. Never deal with it
|
||||
directly but through the functions given below. Wherever a timeout is
|
||||
specified as a parameter below the following rule applies: If timout is
|
||||
greater 0, then timeout means a time in milliseconds to wait with a select
|
||||
system call for data to arrive. If timeout is less or equal then 0 the
|
||||
socket will block on input.
|
||||
\begin{itemize}
|
||||
\item {\bf mkChannel *NETOpenPort(int iPort) }, opens a server port on port number iPort for listening. If successful returns a pointer to a fresh mkChannel datastructure , else NULL.
|
||||
\item {\bf mkChannel *NETAccept(mkChannel *self, int timeout) }, waits timeout microseconds for a client requesting a connection to the server This is done with thke select system call. If a request comes in a new mkChannel structure is created and returned. If not NULL will be returned.
|
||||
\item {\bf mkChannel *NETConnect(char *name, int port) } tries to connect to a server specified by the hostname name and the port number port. Returns a pointer to a new mkChannel structure on success, NULL else.
|
||||
\item {\bf int NETWrite(mkChannel *self, char *buffer, long lLen) } writes lLen bytes from buffer to the socket specified by self. Returns True on succees, else False.
|
||||
\item {\bf long NETRead(mkChannel *self, char *buffer, long lLen, int timeout) } waits timeout microseconds for data to arrive at the socket specified by self. If data is available it will be copied into the buffer, but to a maximum length of lLen. Returns the length of data read, 0 if there is no data and -1 if an EOF occured on the socket (i.e the partner closed the connection).
|
||||
\item {\bf int NETClosePort(mkChannel *self) } If you are done with talking you can use this to close the connection. The socket specified by self can no longer be used after this. You still have to free the mkChannel though, if you want to do it properly. The function returns True on success, False (0) if the call failed.
|
||||
\item {\bf mkChannel *UDPOpen(int iPort) } opens a port for connectionless UDP-connection.
|
||||
\item {\bf mkChannel UDPConnect(int iPort) } connects a client to a UDP port for Data transfer.
|
||||
\item {\bf long UDPRead(mkChannel self, char *buffer, long lLen, int timeout) } reads data from a UDP port inot buffer, but maximum lLen bytes. Waits maximum timeout microseconds for data. Returns the number of bytes read or -1 for end of file.
|
||||
\item {\bf int UDPWrite(mkChannel *self, char *buffer, long lLen); } writes lLen bytes from buffer into an UDP channel.
|
||||
\end{itemize}
|
||||
|
||||
SICS needs I/O multiplexing, that is it needs to be able to handle request
|
||||
from many clients. Instead of spawning more processes or using threads with
|
||||
all the synchronisation problems associated with both of the above, I/O
|
||||
multiplexing is done with the select() system call here. Select uses a
|
||||
funny mask as input which specifies the id of the stream it is interested
|
||||
in. It requires the (stream-number (number, not FILE *) + 1 ) bit of the
|
||||
mask to be set for interest in stream number. This mask is set using macros
|
||||
defined in the apropriate header files.
|
||||
|
||||
|
||||
660
doc/programmer/newsics.eps
Normal file
660
doc/programmer/newsics.eps
Normal file
@@ -0,0 +1,660 @@
|
||||
%!
|
||||
%%BoundingBox: 2 358 358 785
|
||||
%%Title: newsics
|
||||
%%CreationDate: Thu Nov 20 13:43:31 1997
|
||||
%%Creator: Tgif-3.0-p7 by William Chia-Wei Cheng (william@cs.UCLA.edu)
|
||||
|
||||
/tgifdict 4 dict def
|
||||
tgifdict begin
|
||||
|
||||
/tgifarrowtipdict 8 dict def
|
||||
tgifarrowtipdict /mtrx matrix put
|
||||
|
||||
/tgifarrowtip
|
||||
{ tgifarrowtipdict begin
|
||||
/dy exch def
|
||||
/dx exch def
|
||||
/h exch def
|
||||
/w exch def
|
||||
/y exch def
|
||||
/x exch def
|
||||
/savematrix mtrx currentmatrix def
|
||||
x y translate
|
||||
dy dx atan rotate
|
||||
0 0 moveto
|
||||
w neg h lineto
|
||||
w neg h neg lineto
|
||||
savematrix setmatrix
|
||||
end
|
||||
} def
|
||||
|
||||
end
|
||||
|
||||
%%PageBoundingBox: 2 358 358 785
|
||||
tgifdict begin
|
||||
/tgifsavedpage save def
|
||||
|
||||
1 setmiterlimit
|
||||
1 setlinewidth
|
||||
|
||||
0 setgray
|
||||
|
||||
72 0 mul 72 11.00 mul translate
|
||||
72 128 div 100.000 mul 100 div dup neg scale
|
||||
|
||||
gsave
|
||||
|
||||
/tgiforigctm matrix currentmatrix def
|
||||
|
||||
% TEXT
|
||||
0 setgray
|
||||
/Courier-Bold findfont [24 0 0 -24 0 0] makefont setfont
|
||||
gsave
|
||||
192 36 moveto (The Taskloop) show
|
||||
grestore
|
||||
|
||||
% TEXT
|
||||
0 setgray
|
||||
/Courier findfont [17 0 0 -17 0 0] makefont setfont
|
||||
gsave
|
||||
192 94 moveto (Device) show
|
||||
192 111 moveto (Executor) show
|
||||
grestore
|
||||
|
||||
% TEXT
|
||||
0 setgray
|
||||
/Courier findfont [17 0 0 -17 0 0] makefont setfont
|
||||
gsave
|
||||
112 190 moveto (Network) show
|
||||
112 207 moveto (Reader) show
|
||||
grestore
|
||||
|
||||
% TEXT
|
||||
0 setgray
|
||||
/Courier findfont [17 0 0 -17 0 0] makefont setfont
|
||||
gsave
|
||||
224 270 moveto (Client1 ) show
|
||||
grestore
|
||||
|
||||
% TEXT
|
||||
0 setgray
|
||||
/Courier findfont [17 0 0 -17 0 0] makefont setfont
|
||||
gsave
|
||||
352 270 moveto (Client2) show
|
||||
grestore
|
||||
|
||||
% TEXT
|
||||
0 setgray
|
||||
/Courier findfont [17 0 0 -17 0 0] makefont setfont
|
||||
gsave
|
||||
448 222 moveto (Client3) show
|
||||
grestore
|
||||
|
||||
% TEXT
|
||||
0 setgray
|
||||
/Courier findfont [17 0 0 -17 0 0] makefont setfont
|
||||
gsave
|
||||
384 142 moveto (Emon) show
|
||||
grestore
|
||||
|
||||
% RCBOX
|
||||
0 setgray
|
||||
gsave
|
||||
gsave
|
||||
newpath
|
||||
272 80 moveto
|
||||
288 80 288 128 16 arcto 4 {pop} repeat
|
||||
288 112 lineto
|
||||
288 128 176 128 16 arcto 4 {pop} repeat
|
||||
192 128 lineto
|
||||
176 128 176 80 16 arcto 4 {pop} repeat
|
||||
176 96 lineto
|
||||
176 80 288 80 16 arcto 4 {pop} repeat
|
||||
closepath
|
||||
stroke
|
||||
grestore
|
||||
grestore
|
||||
|
||||
% RCBOX
|
||||
0 setgray
|
||||
gsave
|
||||
gsave
|
||||
newpath
|
||||
192 176 moveto
|
||||
208 176 208 224 16 arcto 4 {pop} repeat
|
||||
208 208 lineto
|
||||
208 224 96 224 16 arcto 4 {pop} repeat
|
||||
112 224 lineto
|
||||
96 224 96 176 16 arcto 4 {pop} repeat
|
||||
96 192 lineto
|
||||
96 176 208 176 16 arcto 4 {pop} repeat
|
||||
closepath
|
||||
stroke
|
||||
grestore
|
||||
grestore
|
||||
|
||||
% RCBOX
|
||||
0 setgray
|
||||
gsave
|
||||
gsave
|
||||
newpath
|
||||
432 128 moveto
|
||||
448 128 448 160 16 arcto 4 {pop} repeat
|
||||
448 144 lineto
|
||||
448 160 368 160 16 arcto 4 {pop} repeat
|
||||
384 160 lineto
|
||||
368 160 368 128 16 arcto 4 {pop} repeat
|
||||
368 144 lineto
|
||||
368 128 448 128 16 arcto 4 {pop} repeat
|
||||
closepath
|
||||
stroke
|
||||
grestore
|
||||
grestore
|
||||
|
||||
% RCBOX
|
||||
0 setgray
|
||||
gsave
|
||||
gsave
|
||||
newpath
|
||||
288 240 moveto
|
||||
304 240 304 288 16 arcto 4 {pop} repeat
|
||||
304 272 lineto
|
||||
304 288 208 288 16 arcto 4 {pop} repeat
|
||||
224 288 lineto
|
||||
208 288 208 240 16 arcto 4 {pop} repeat
|
||||
208 256 lineto
|
||||
208 240 304 240 16 arcto 4 {pop} repeat
|
||||
closepath
|
||||
stroke
|
||||
grestore
|
||||
grestore
|
||||
|
||||
% RCBOX
|
||||
0 setgray
|
||||
gsave
|
||||
gsave
|
||||
newpath
|
||||
416 240 moveto
|
||||
432 240 432 288 16 arcto 4 {pop} repeat
|
||||
432 272 lineto
|
||||
432 288 336 288 16 arcto 4 {pop} repeat
|
||||
352 288 lineto
|
||||
336 288 336 240 16 arcto 4 {pop} repeat
|
||||
336 256 lineto
|
||||
336 240 432 240 16 arcto 4 {pop} repeat
|
||||
closepath
|
||||
stroke
|
||||
grestore
|
||||
grestore
|
||||
|
||||
% RCBOX
|
||||
0 setgray
|
||||
gsave
|
||||
gsave
|
||||
newpath
|
||||
512 192 moveto
|
||||
528 192 528 240 16 arcto 4 {pop} repeat
|
||||
528 224 lineto
|
||||
528 240 448 240 16 arcto 4 {pop} repeat
|
||||
464 240 lineto
|
||||
448 240 448 192 16 arcto 4 {pop} repeat
|
||||
448 208 lineto
|
||||
448 192 528 192 16 arcto 4 {pop} repeat
|
||||
closepath
|
||||
stroke
|
||||
grestore
|
||||
grestore
|
||||
|
||||
% POLY/OPEN-SPLINE
|
||||
0 setgray
|
||||
gsave
|
||||
newpath
|
||||
152 224 moveto
|
||||
32 48 atan dup cos 12.000 mul 200 exch sub
|
||||
exch sin 12.000 mul 256 exch sub lineto
|
||||
tgiforigctm setmatrix
|
||||
3 setlinewidth
|
||||
stroke
|
||||
1 setlinewidth
|
||||
grestore
|
||||
gsave
|
||||
tgiforigctm setmatrix
|
||||
newpath
|
||||
200 256 12.000 5.000 48 32 tgifarrowtip
|
||||
1 setgray closepath fill
|
||||
0 setgray
|
||||
newpath
|
||||
200 256 12.000 5.000 48 32 tgifarrowtip
|
||||
closepath fill
|
||||
grestore
|
||||
|
||||
% POLY/OPEN-SPLINE
|
||||
0 setgray
|
||||
gsave
|
||||
newpath
|
||||
304 264 moveto
|
||||
0 24 atan dup cos 12.000 mul 328 exch sub
|
||||
exch sin 12.000 mul 264 exch sub lineto
|
||||
tgiforigctm setmatrix
|
||||
3 setlinewidth
|
||||
stroke
|
||||
1 setlinewidth
|
||||
grestore
|
||||
gsave
|
||||
tgiforigctm setmatrix
|
||||
newpath
|
||||
328 264 12.000 5.000 24 0 tgifarrowtip
|
||||
1 setgray closepath fill
|
||||
0 setgray
|
||||
newpath
|
||||
328 264 12.000 5.000 24 0 tgifarrowtip
|
||||
closepath fill
|
||||
grestore
|
||||
|
||||
% POLY/OPEN-SPLINE
|
||||
0 setgray
|
||||
gsave
|
||||
newpath
|
||||
432 272 moveto
|
||||
-24 32 atan dup cos 12.000 mul 464 exch sub
|
||||
exch sin 12.000 mul 248 exch sub lineto
|
||||
tgiforigctm setmatrix
|
||||
3 setlinewidth
|
||||
stroke
|
||||
1 setlinewidth
|
||||
grestore
|
||||
gsave
|
||||
tgiforigctm setmatrix
|
||||
newpath
|
||||
464 248 12.000 5.000 32 -24 tgifarrowtip
|
||||
1 setgray closepath fill
|
||||
0 setgray
|
||||
newpath
|
||||
464 248 12.000 5.000 32 -24 tgifarrowtip
|
||||
closepath fill
|
||||
grestore
|
||||
|
||||
% POLY/OPEN-SPLINE
|
||||
0 setgray
|
||||
gsave
|
||||
newpath
|
||||
504 192 moveto
|
||||
-40 -48 atan dup cos 12.000 mul 456 exch sub
|
||||
exch sin 12.000 mul 152 exch sub lineto
|
||||
tgiforigctm setmatrix
|
||||
3 setlinewidth
|
||||
stroke
|
||||
1 setlinewidth
|
||||
grestore
|
||||
gsave
|
||||
tgiforigctm setmatrix
|
||||
newpath
|
||||
456 152 12.000 5.000 -48 -40 tgifarrowtip
|
||||
1 setgray closepath fill
|
||||
0 setgray
|
||||
newpath
|
||||
456 152 12.000 5.000 -48 -40 tgifarrowtip
|
||||
closepath fill
|
||||
grestore
|
||||
|
||||
% POLY/OPEN-SPLINE
|
||||
0 setgray
|
||||
gsave
|
||||
newpath
|
||||
368 144 moveto
|
||||
32 -152 atan dup cos 12.000 mul 216 exch sub
|
||||
exch sin 12.000 mul 176 exch sub lineto
|
||||
tgiforigctm setmatrix
|
||||
3 setlinewidth
|
||||
stroke
|
||||
1 setlinewidth
|
||||
grestore
|
||||
gsave
|
||||
tgiforigctm setmatrix
|
||||
newpath
|
||||
216 176 12.000 5.000 -152 32 tgifarrowtip
|
||||
1 setgray closepath fill
|
||||
0 setgray
|
||||
newpath
|
||||
216 176 12.000 5.000 -152 32 tgifarrowtip
|
||||
closepath fill
|
||||
grestore
|
||||
|
||||
% POLY/OPEN-SPLINE
|
||||
0 setgray
|
||||
gsave
|
||||
[4 12] 0 setdash
|
||||
newpath
|
||||
368 136 moveto
|
||||
-32 -64 atan dup cos 10.000 mul 304 exch sub
|
||||
exch sin 10.000 mul 104 exch sub lineto
|
||||
tgiforigctm setmatrix
|
||||
2 setlinewidth
|
||||
stroke
|
||||
[] 0 setdash
|
||||
1 setlinewidth
|
||||
grestore
|
||||
gsave
|
||||
tgiforigctm setmatrix
|
||||
newpath
|
||||
304 104 10.000 4.000 -64 -32 tgifarrowtip
|
||||
1 setgray closepath fill
|
||||
0 setgray
|
||||
newpath
|
||||
304 104 10.000 4.000 -64 -32 tgifarrowtip
|
||||
closepath fill
|
||||
grestore
|
||||
|
||||
% POLY/OPEN-SPLINE
|
||||
0 setgray
|
||||
gsave
|
||||
[4 12] 0 setdash
|
||||
newpath
|
||||
176 104 moveto
|
||||
64 -32 atan dup cos 10.000 mul 144 exch sub
|
||||
exch sin 10.000 mul 168 exch sub lineto
|
||||
tgiforigctm setmatrix
|
||||
2 setlinewidth
|
||||
stroke
|
||||
[] 0 setdash
|
||||
1 setlinewidth
|
||||
grestore
|
||||
gsave
|
||||
tgiforigctm setmatrix
|
||||
newpath
|
||||
144 168 10.000 4.000 -32 64 tgifarrowtip
|
||||
1 setgray closepath fill
|
||||
0 setgray
|
||||
newpath
|
||||
144 168 10.000 4.000 -32 64 tgifarrowtip
|
||||
closepath fill
|
||||
grestore
|
||||
|
||||
% TEXT
|
||||
0 setgray
|
||||
/Courier-Bold findfont [20 0 0 -20 0 0] makefont setfont
|
||||
gsave
|
||||
128 407 moveto (SICS Interpreter and Macro Language) show
|
||||
grestore
|
||||
|
||||
% TEXT
|
||||
0 setgray
|
||||
/Courier-Bold findfont [25 0 0 -25 0 0] makefont setfont
|
||||
gsave
|
||||
136 508 moveto (SICS Object Database) show
|
||||
grestore
|
||||
|
||||
% BOX
|
||||
0 setgray
|
||||
gsave
|
||||
10 setmiterlimit
|
||||
gsave
|
||||
newpath
|
||||
104 472 moveto 536 472 lineto 536 536 lineto 104 536 lineto
|
||||
closepath
|
||||
2 setlinewidth
|
||||
stroke
|
||||
grestore
|
||||
grestore
|
||||
|
||||
% TEXT
|
||||
0 setgray
|
||||
/Courier-Bold findfont [25 0 0 -25 0 0] makefont setfont
|
||||
gsave
|
||||
128 700 moveto (Hardware ) show
|
||||
grestore
|
||||
|
||||
% BOX
|
||||
0 setgray
|
||||
gsave
|
||||
10 setmiterlimit
|
||||
gsave
|
||||
newpath
|
||||
112 664 moveto 576 664 lineto 576 768 lineto 112 768 lineto
|
||||
closepath
|
||||
2 setlinewidth
|
||||
stroke
|
||||
grestore
|
||||
grestore
|
||||
|
||||
% POLY/OPEN-SPLINE
|
||||
0 setgray
|
||||
gsave
|
||||
newpath
|
||||
280 432 moveto
|
||||
40 0 atan dup cos 14.000 mul 280 exch sub
|
||||
exch sin 14.000 mul 472 exch sub lineto
|
||||
tgiforigctm setmatrix
|
||||
4 setlinewidth
|
||||
stroke
|
||||
1 setlinewidth
|
||||
grestore
|
||||
gsave
|
||||
tgiforigctm setmatrix
|
||||
newpath
|
||||
280 472 14.000 6.000 0 40 tgifarrowtip
|
||||
1 setgray closepath fill
|
||||
0 setgray
|
||||
newpath
|
||||
280 472 14.000 6.000 0 40 tgifarrowtip
|
||||
closepath fill
|
||||
grestore
|
||||
|
||||
% POLY/OPEN-SPLINE
|
||||
0 setgray
|
||||
gsave
|
||||
newpath
|
||||
176 536 moveto
|
||||
120 0 atan dup cos 14.000 mul 176 exch sub
|
||||
exch sin 14.000 mul 656 exch sub lineto
|
||||
tgiforigctm setmatrix
|
||||
4 setlinewidth
|
||||
stroke
|
||||
1 setlinewidth
|
||||
grestore
|
||||
gsave
|
||||
tgiforigctm setmatrix
|
||||
newpath
|
||||
176 656 14.000 6.000 0 120 tgifarrowtip
|
||||
1 setgray closepath fill
|
||||
0 setgray
|
||||
newpath
|
||||
176 656 14.000 6.000 0 120 tgifarrowtip
|
||||
closepath fill
|
||||
grestore
|
||||
|
||||
% POLY/OPEN-SPLINE
|
||||
0 setgray
|
||||
gsave
|
||||
newpath
|
||||
320 536 moveto
|
||||
120 -104 atan dup cos 14.000 mul 216 exch sub
|
||||
exch sin 14.000 mul 656 exch sub lineto
|
||||
tgiforigctm setmatrix
|
||||
4 setlinewidth
|
||||
stroke
|
||||
1 setlinewidth
|
||||
grestore
|
||||
gsave
|
||||
tgiforigctm setmatrix
|
||||
newpath
|
||||
216 656 14.000 6.000 -104 120 tgifarrowtip
|
||||
1 setgray closepath fill
|
||||
0 setgray
|
||||
newpath
|
||||
216 656 14.000 6.000 -104 120 tgifarrowtip
|
||||
closepath fill
|
||||
grestore
|
||||
|
||||
% POLY/OPEN-SPLINE
|
||||
0 setgray
|
||||
gsave
|
||||
newpath
|
||||
408 536 moveto
|
||||
120 80 atan dup cos 14.000 mul 488 exch sub
|
||||
exch sin 14.000 mul 656 exch sub lineto
|
||||
tgiforigctm setmatrix
|
||||
4 setlinewidth
|
||||
stroke
|
||||
1 setlinewidth
|
||||
grestore
|
||||
gsave
|
||||
tgiforigctm setmatrix
|
||||
newpath
|
||||
488 656 14.000 6.000 80 120 tgifarrowtip
|
||||
1 setgray closepath fill
|
||||
0 setgray
|
||||
newpath
|
||||
488 656 14.000 6.000 80 120 tgifarrowtip
|
||||
closepath fill
|
||||
grestore
|
||||
|
||||
% POLY/OPEN-SPLINE
|
||||
0 setgray
|
||||
gsave
|
||||
[12 4] 0 setdash
|
||||
newpath
|
||||
248 288 moveto
|
||||
80 0 atan dup cos 8.000 mul 248 exch sub
|
||||
exch sin 8.000 mul 368 exch sub lineto
|
||||
tgiforigctm setmatrix
|
||||
1 setlinewidth
|
||||
stroke
|
||||
[] 0 setdash
|
||||
grestore
|
||||
gsave
|
||||
tgiforigctm setmatrix
|
||||
newpath
|
||||
248 368 8.000 3.000 0 80 tgifarrowtip
|
||||
1 setgray closepath fill
|
||||
0 setgray
|
||||
newpath
|
||||
248 368 8.000 3.000 0 80 tgifarrowtip
|
||||
closepath fill
|
||||
grestore
|
||||
|
||||
% POLY/OPEN-SPLINE
|
||||
0 setgray
|
||||
gsave
|
||||
[12 4] 0 setdash
|
||||
newpath
|
||||
376 288 moveto
|
||||
80 -120 atan dup cos 8.000 mul 256 exch sub
|
||||
exch sin 8.000 mul 368 exch sub lineto
|
||||
tgiforigctm setmatrix
|
||||
1 setlinewidth
|
||||
stroke
|
||||
[] 0 setdash
|
||||
grestore
|
||||
gsave
|
||||
tgiforigctm setmatrix
|
||||
newpath
|
||||
256 368 8.000 3.000 -120 80 tgifarrowtip
|
||||
1 setgray closepath fill
|
||||
0 setgray
|
||||
newpath
|
||||
256 368 8.000 3.000 -120 80 tgifarrowtip
|
||||
closepath fill
|
||||
grestore
|
||||
|
||||
% POLY/OPEN-SPLINE
|
||||
0 setgray
|
||||
gsave
|
||||
[12 4] 0 setdash
|
||||
newpath
|
||||
504 240 moveto
|
||||
496 312 lineto
|
||||
56 -224 atan dup cos 8.000 mul 272 exch sub
|
||||
exch sin 8.000 mul 368 exch sub lineto
|
||||
tgiforigctm setmatrix
|
||||
1 setlinewidth
|
||||
stroke
|
||||
[] 0 setdash
|
||||
grestore
|
||||
gsave
|
||||
tgiforigctm setmatrix
|
||||
newpath
|
||||
272 368 8.000 3.000 -224 56 tgifarrowtip
|
||||
1 setgray closepath fill
|
||||
0 setgray
|
||||
newpath
|
||||
272 368 8.000 3.000 -224 56 tgifarrowtip
|
||||
closepath fill
|
||||
grestore
|
||||
|
||||
% TEXT
|
||||
0 setgray
|
||||
/Courier findfont [17 0 0 -17 0 0] makefont setfont
|
||||
gsave
|
||||
504 310 moveto (send commands) show
|
||||
grestore
|
||||
|
||||
% TEXT
|
||||
0 setgray
|
||||
/Courier findfont [17 0 0 -17 0 0] makefont setfont
|
||||
gsave
|
||||
488 166 moveto (pass execution) show
|
||||
grestore
|
||||
|
||||
% BOX
|
||||
0 setgray
|
||||
gsave
|
||||
10 setmiterlimit
|
||||
gsave
|
||||
newpath
|
||||
96 368 moveto 624 368 lineto 624 432 lineto 96 432 lineto
|
||||
closepath
|
||||
2 setlinewidth
|
||||
stroke
|
||||
grestore
|
||||
grestore
|
||||
|
||||
% POLY/OPEN-SPLINE
|
||||
0 setgray
|
||||
gsave
|
||||
newpath
|
||||
8 16 moveto
|
||||
56 120 lineto
|
||||
64 72 lineto
|
||||
104 168 lineto
|
||||
tgiforigctm setmatrix
|
||||
4 setlinewidth
|
||||
stroke
|
||||
1 setlinewidth
|
||||
grestore
|
||||
|
||||
% POLY/OPEN-SPLINE
|
||||
0 setgray
|
||||
gsave
|
||||
newpath
|
||||
104 168 moveto
|
||||
80 152 lineto
|
||||
tgiforigctm setmatrix
|
||||
4 setlinewidth
|
||||
stroke
|
||||
1 setlinewidth
|
||||
grestore
|
||||
|
||||
% POLY/OPEN-SPLINE
|
||||
0 setgray
|
||||
gsave
|
||||
newpath
|
||||
104 168 moveto
|
||||
112 144 lineto
|
||||
tgiforigctm setmatrix
|
||||
4 setlinewidth
|
||||
stroke
|
||||
1 setlinewidth
|
||||
grestore
|
||||
|
||||
% TEXT
|
||||
0 setgray
|
||||
/Courier findfont [17 0 0 -17 0 0] makefont setfont
|
||||
gsave
|
||||
40 62 moveto (TCP/IP) show
|
||||
grestore
|
||||
|
||||
grestore
|
||||
tgifsavedpage restore
|
||||
end
|
||||
%MatchingCreationDate: Thu Nov 20 13:43:31 1997
|
||||
BIN
doc/programmer/newsics.gif
Normal file
BIN
doc/programmer/newsics.gif
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 7.7 KiB |
160
doc/programmer/nread.tex
Normal file
160
doc/programmer/nread.tex
Normal file
@@ -0,0 +1,160 @@
|
||||
\subsection{The Network Reader}
|
||||
The network readers task is to read incoming messages for the SICS server.
|
||||
These may come in four main forms.
|
||||
\begin{itemize}
|
||||
\item connection requests
|
||||
\item commands
|
||||
\item interrupts
|
||||
through a command channel
|
||||
\item interrupt messages on the UDP port.
|
||||
\end{itemize}
|
||||
A prior
|
||||
version of SICS had a select system call for each of these cases. It was
|
||||
found, that the code spent most of its time in the select system call
|
||||
thus intrdoducing a major performance problem.
|
||||
|
||||
The select system call can handle more then one file descriptor in one call.
|
||||
This is exactly what this module handles. It does a global select on
|
||||
all open sockets and forwards any pending data to approriate handlers.
|
||||
This scheme brought a drastic
|
||||
performance improvement.
|
||||
|
||||
Each of the messages to SICS is handled
|
||||
differently:
|
||||
|
||||
A connection request will be validated, a new connection object will be
|
||||
created and a new task for this connection object will be started.
|
||||
|
||||
A command will be placed in the apropriate command stack for the task
|
||||
belonging to this connection to work on in a later stage. The netreader will
|
||||
also take care that all commands are complete, this is the terminator
|
||||
\verb+\n+ or \verb+\r+ has been sent.
|
||||
|
||||
Both forms of interrupt will be interpreted and a suitable signal
|
||||
will be sent to all runing tasks if the interrupt request is valid.
|
||||
|
||||
In order to perform his tasks the network reader needs to maintain a list of
|
||||
all open sockets and their types. Additionally it needs to know about the
|
||||
SICS tasker.
|
||||
|
||||
The early version of SICS only supported connections on a plain
|
||||
socket. This feauture is not used any more in favour of the Telnet
|
||||
option described below. However, as this may be used to transport
|
||||
binary data, the obsolete code has not been removed.
|
||||
|
||||
Support for the internet TCP/IP standard telnet protocoll has been added in
|
||||
January 1998. Telnet things need to be handled differently, therefore two
|
||||
more socket types have been defined: A telnet listen socket on which
|
||||
requests for telnet connections are listened for, and a telnet command
|
||||
socket which actually process the telnet messages.
|
||||
|
||||
Support for user sockets was added in February 1998. User sockets provides a
|
||||
primitive interface to the network readers monitoring functions. This is
|
||||
part of a solution to one problem which can occur in SICS: The whole server
|
||||
is blocked if one of the serial devices is slow in responding. User sockets
|
||||
now provide a method for client code to register a socket for monitoring
|
||||
with the network reader and find out if data is pending at it. This support
|
||||
is provided by the functions: NetReadRegisterUserSocket,
|
||||
NetReadRemoveUserSocket, NetReadReadable and NetReadResetUser described
|
||||
below. NetReadWait4Data is a special wait function which waits for data to
|
||||
come in on a user socket. This function is problematic with dynamically
|
||||
creates and deleted objects such as environment device objects. Its use is
|
||||
therefore no longer recommended.
|
||||
|
||||
Thus the interface looks like this:
|
||||
|
||||
\begin{flushleft} \small
|
||||
\begin{minipage}{\linewidth} \label{scrap1}
|
||||
$\langle$nrint {\footnotesize ?}$\rangle\equiv$
|
||||
\vspace{-1ex}
|
||||
\begin{list}{}{} \item
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@/*--------------------------------------------------------------------------*/@\\
|
||||
\mbox{}\verb@ typedef struct __netreader *pNetRead;@\\
|
||||
\mbox{}\verb@ typedef enum {naccept, command, udp, user, taccept, tcommand} eNRType;@\\
|
||||
\mbox{}\verb@/*--------------------------------------------------------------------------*/@\\
|
||||
\mbox{}\verb@ pNetRead CreateNetReader(pServer pServ, int iPasswdTimeout,@\\
|
||||
\mbox{}\verb@ int iReadTimeout);@\\
|
||||
\mbox{}\verb@ void DeleteNetReader(void *pData);@\\
|
||||
\mbox{}\verb@/*--------------------------------------------------------------------------*/@\\
|
||||
\mbox{}\verb@ int NetReadRegister(pNetRead self, mkChannel *pSock, eNRType eType,@\\
|
||||
\mbox{}\verb@ SConnection *pCon);@\\
|
||||
\mbox{}\verb@ int NetReadRegisterUserSocket(pNetRead self, int iSocket);@\\
|
||||
\mbox{}\verb@ int NetReadRemove(pNetRead self, mkChannel *pSock);@\\
|
||||
\mbox{}\verb@ int NetReadRemoveUserSocket(pNetRead self, int iSocket);@\\
|
||||
\mbox{}\verb@/*-------------------------------------------------------------------------*/@\\
|
||||
\mbox{}\verb@ int NetReaderTask(void *pReader); @\\
|
||||
\mbox{}\verb@ void NetReaderSignal(void *pUser, int iSignal, void *pSigData);@\\
|
||||
\mbox{}\verb@ int NetReadWait4Data(pNetRead self, int iSocket);@\\
|
||||
\mbox{}\verb@ int NetReadReadable(pNetRead self, int iSocket);@\\
|
||||
\mbox{}\verb@ int NetReadResetUser(pNetRead self, int iSocket);@\\
|
||||
\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}
|
||||
This starts off with the definition of a data type for the net reader and an
|
||||
enum which denotes the possible types of connections.
|
||||
\begin{description}
|
||||
\item[CreateNetReader] sets a new net reader up. Only parameter is a pointer
|
||||
to the task manager to use while creating new connections. iPasswdTimeout
|
||||
is the period in which a client is expected to send his userid/password
|
||||
pair. iReadTimeout is the time to wait on the select statement for a
|
||||
channel to become readable. Both time values are specified in milliseconds.
|
||||
\item[DeleteNetReader] deletes the net reader and all its data structures.
|
||||
Must be called in order to free all memory.
|
||||
\item[NetReadRegister] register the channel pSock of type eType with the net
|
||||
reader self. The parameter pData will only be interpreted for connections
|
||||
of type command. It must point to the command stack belonging to the
|
||||
connection which registers this socket.
|
||||
\item[NetReadRegisterUserSocket] registers a socket from within SICS foth
|
||||
the network reader. The client code to this module may then find out with a
|
||||
call to NetReadReadable if data is pending on this socket. This a
|
||||
convenience wrapper to NetReadRegister.
|
||||
\item[NetReadRemove] removes the socket pSock from the net reader. This must
|
||||
be done when closing the socket, otherwise the net reader will continue
|
||||
checking for pending data on this socket.
|
||||
\item[NetReadRemoveUserSocket] removes a user socket from
|
||||
monitoring. Again, this is a vonvenience wrapper around NetReadRemove.
|
||||
\item[NetReaderTask] is the net reader task function which will be
|
||||
registered with the task manager. This function builds the select
|
||||
mask, does the select and forwards incoming data to the appropriate
|
||||
handler functions. These are not documented here, as they are file
|
||||
static function in nread.c.
|
||||
\item[NetReaderSignal] is the signal handler for the net reader. It
|
||||
just stops the NetReaderTask when the SICS server is run down.
|
||||
\item[NetReadReadable] returns 1 if data is pending at the user socket or 0
|
||||
if not.
|
||||
\item[NetReadResetUser] resets a user socket to not readable.
|
||||
\end{description}
|
||||
|
||||
\begin{flushleft} \small
|
||||
\begin{minipage}{\linewidth} \label{scrap2}
|
||||
\verb@"nread.h"@ {\footnotesize ? }$\equiv$
|
||||
\vspace{-1ex}
|
||||
\begin{list}{}{} \item
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@/*------------------------------------------------------------------------@\\
|
||||
\mbox{}\verb@ N E T R E A D E R@\\
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@ This module will check for pending requests to the SICS server and@\\
|
||||
\mbox{}\verb@ initiate apropriate actions.@\\
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@ Mark Koenencke, September 1997@\\
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@ copyright: see copyright.h@\\
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@----------------------------------------------------------------------------*/@\\
|
||||
\mbox{}\verb@#ifndef SICSNETREADER@\\
|
||||
\mbox{}\verb@#define SICSNETREADER@\\
|
||||
\mbox{}\verb@@$\langle$nrint {\footnotesize ?}$\rangle$\verb@@\\
|
||||
\mbox{}\verb@#endif@\\
|
||||
\mbox{}\verb@@$\diamond$
|
||||
\end{list}
|
||||
\vspace{-2ex}
|
||||
\end{minipage}\\[4ex]
|
||||
\end{flushleft}
|
||||
123
doc/programmer/nserver.tex
Normal file
123
doc/programmer/nserver.tex
Normal file
@@ -0,0 +1,123 @@
|
||||
\subsection{The SICS Server Object}
|
||||
This objects responsability is the proper initialisation and shutdown
|
||||
of the SICS server and the provision of some utility functions.
|
||||
The Server's data structure holds pointers to the most important parts of
|
||||
the system:
|
||||
|
||||
\begin{flushleft} \small
|
||||
\begin{minipage}{\linewidth} \label{scrap1}
|
||||
$\langle$servdat {\footnotesize ?}$\rangle\equiv$
|
||||
\vspace{-1ex}
|
||||
\begin{list}{}{} \item
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@ typedef struct __SicsServer {@\\
|
||||
\mbox{}\verb@ SicsInterp *pSics;@\\
|
||||
\mbox{}\verb@ pTaskMan pTasker;@\\
|
||||
\mbox{}\verb@ pExeList pExecutor;@\\
|
||||
\mbox{}\verb@ pEnvMon pMonitor;@\\
|
||||
\mbox{}\verb@ mkChannel *pServerPort;@\\
|
||||
\mbox{}\verb@ pNetRead pReader;@\\
|
||||
\mbox{}\verb@ } SicsServer;@\\
|
||||
\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 fields are:
|
||||
\begin{description}
|
||||
\item[pSics] is a pointer to the SICS interpreter.
|
||||
\item[pTasker] is a pointer to the task scheduler.
|
||||
\item[pExecutor] is a pointer to the device executor. This module monitors
|
||||
variables during counting and driving operations.
|
||||
\item[pMonitor] is a pointer to an environment device controller monitor.
|
||||
This module monitors sample environment controllers.
|
||||
\item[pServerPort] points to a data structure describing the port at which
|
||||
the SICS server is listening for connections.
|
||||
\item[pReader] points to a data structure which defines the network
|
||||
communication object.
|
||||
\end{description}
|
||||
|
||||
|
||||
In terms of a function interface the server module supplies.
|
||||
|
||||
\begin{flushleft} \small
|
||||
\begin{minipage}{\linewidth} \label{scrap2}
|
||||
$\langle$servint {\footnotesize ?}$\rangle\equiv$
|
||||
\vspace{-1ex}
|
||||
\begin{list}{}{} \item
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@/*----------------------------------------------------------------------*/@\\
|
||||
\mbox{}\verb@ int InitServer(char *file, pServer *pServ);@\\
|
||||
\mbox{}\verb@ void RunServer(pServer self);@\\
|
||||
\mbox{}\verb@ void StopServer(pServer self);@\\
|
||||
\mbox{}\verb@/*----------------------------------------------------------------------*/@\\
|
||||
\mbox{}\verb@ SicsInterp *GetInterpreter(void);@\\
|
||||
\mbox{}\verb@ pExeList GetExecutor(void);@\\
|
||||
\mbox{}\verb@ pTaskMan GetTasker(void);@\\
|
||||
\mbox{}\verb@ void ServerWriteGlobal(char *pMessage, int iCode);@\\
|
||||
\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}
|
||||
For most functions the name already says what it does. {\bf
|
||||
InitServer} initializes the SICS servers data structures. {\bf
|
||||
RunServer} implements the main loop and essentially calls the task
|
||||
modules ScheduleTask function for running all the SICS tasks which
|
||||
will handle the rest of the job. {\bf Stopserver} is responisble for
|
||||
closing the SICS server down in a sensible manner and in a well
|
||||
defined sequence of events.
|
||||
{\bf ServerWriteGlobal}
|
||||
is special. This function sends the message pMessage to all clients
|
||||
currently connected to the SICS server with the output code iCode. iCode has
|
||||
the same meaning as in the connection object.
|
||||
\begin{flushleft} \small
|
||||
\begin{minipage}{\linewidth} \label{scrap3}
|
||||
\verb@"nserver.h"@ {\footnotesize ? }$\equiv$
|
||||
\vspace{-1ex}
|
||||
\begin{list}{}{} \item
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@/*--------------------------------------------------------------------------@\\
|
||||
\mbox{}\verb@ N S E R V E R@\\
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@ The SICS server main data structure and functions.@\\
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@ Restructured: September 1997@\\
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@ Mark Koennecke.@\\
|
||||
\mbox{}\verb@ @\\
|
||||
\mbox{}\verb@ copyright: see copyright.h@\\
|
||||
\mbox{}\verb@----------------------------------------------------------------------------*/@\\
|
||||
\mbox{}\verb@#ifndef SICSNSERVER@\\
|
||||
\mbox{}\verb@#define SICSNSERVER@\\
|
||||
\mbox{}\verb@#include "conman.h"@\\
|
||||
\mbox{}\verb@#include "SCinter.h"@\\
|
||||
\mbox{}\verb@#include "emon.h"@\\
|
||||
\mbox{}\verb@#include "devexec.h"@\\
|
||||
\mbox{}\verb@#include "task.h"@\\
|
||||
\mbox{}\verb@#include "network.h"@\\
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@ typedef struct __SicsServer *pServer;@\\
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@#include "nread.h"@\\
|
||||
\mbox{}\verb@@$\langle$servdat {\footnotesize ?}$\rangle$\verb@@\\
|
||||
\mbox{}\verb@@$\langle$servint {\footnotesize ?}$\rangle$\verb@@\\
|
||||
\mbox{}\verb@ int UserWait(SConnection *pCon, SicsInterp *pSics, void *pData,@\\
|
||||
\mbox{}\verb@ int argc, char *argv[]);@\\
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@ int SicsWait(long lTime);@\\
|
||||
\mbox{}\verb@#endif@\\
|
||||
\mbox{}\verb@@$\diamond$
|
||||
\end{list}
|
||||
\vspace{-2ex}
|
||||
\end{minipage}\\[4ex]
|
||||
\end{flushleft}
|
||||
69
doc/programmer/nxamor.tex
Normal file
69
doc/programmer/nxamor.tex
Normal file
@@ -0,0 +1,69 @@
|
||||
\subsection{AMOR NeXus Routines}
|
||||
This module implements a few functions for writing NeXus data files
|
||||
for the reflectoemter AMOR at SINQ, PSI. Nothing very exciting here:
|
||||
this is mostly boring repetetive code. Three functions are defined:
|
||||
|
||||
\begin{flushleft} \small
|
||||
\begin{minipage}{\linewidth} \label{scrap1}
|
||||
$\langle$namor {\footnotesize ?}$\rangle\equiv$
|
||||
\vspace{-1ex}
|
||||
\begin{list}{}{} \item
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@ int WriteAmorHeader(char *file, SConnection *pCon);@\\
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@ int WriteAmorScan(char *file, SConnection *pCon, pScanData pScan);@\\
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@ int WriteAmorTOF(char *file, SConnection *pCon, pHistMem pHM);@\\
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@ int AmorStore(SConnection *pCon, SicsInterp *pSics, void *pData,@\\
|
||||
\mbox{}\verb@ int argc, char *argv[]);@\\
|
||||
\mbox{}\verb@ int AmorStoreMake(SConnection *pCon, SicsInterp *pSics, void *pData,@\\
|
||||
\mbox{}\verb@ int argc, char *argv[]);@\\
|
||||
\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}
|
||||
\begin{description}
|
||||
\item[WriteAmorHeader] writes all the AMOR header information and the
|
||||
zillions of motors.
|
||||
\item[WriteAmorScan] writes data when AMOR was operated in scanning
|
||||
mode.
|
||||
\item[WriteAmorTOF] writes AMOR data when used with the PSD in
|
||||
time-of-flight mode.
|
||||
\item[AmorStore] the command function implementing the storeamor
|
||||
command.
|
||||
\item[AmorStoreMake] the initialization function which creates the
|
||||
storeamor command.
|
||||
\end{description}
|
||||
|
||||
\begin{flushleft} \small
|
||||
\begin{minipage}{\linewidth} \label{scrap2}
|
||||
\verb@"nxamor.h"@ {\footnotesize ? }$\equiv$
|
||||
\vspace{-1ex}
|
||||
\begin{list}{}{} \item
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@/*------------------------------------------------------------------------@\\
|
||||
\mbox{}\verb@ N X A M O R@\\
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@ Some routines for writing NeXus files for the reflectometer AMOR at@\\
|
||||
\mbox{}\verb@ SINQ.@\\
|
||||
\mbox{}\verb@ @\\
|
||||
\mbox{}\verb@ copyright: see copyright.h@\\
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@ Mark Koennecke, September 1999@\\
|
||||
\mbox{}\verb@----------------------------------------------------------------------*/@\\
|
||||
\mbox{}\verb@#ifndef NXAMOR@\\
|
||||
\mbox{}\verb@#define NXAMOR@\\
|
||||
\mbox{}\verb@@$\langle$namor {\footnotesize ?}$\rangle$\verb@@\\
|
||||
\mbox{}\verb@#endif@\\
|
||||
\mbox{}\verb@@$\diamond$
|
||||
\end{list}
|
||||
\vspace{-2ex}
|
||||
\end{minipage}\\[4ex]
|
||||
\end{flushleft}
|
||||
192
doc/programmer/nxdata.tex
Normal file
192
doc/programmer/nxdata.tex
Normal file
@@ -0,0 +1,192 @@
|
||||
\subsection{NXdata}
|
||||
NXdata is a module for writing Powder Diffraction Data files. The
|
||||
routines here are somewhat obsolete as they refer to NeXus writing
|
||||
using the standard Napi routines which is quite involved. Usually,
|
||||
NeXus files are written from SICS through the NXDICT aware utility
|
||||
routines in NXUTIL.
|
||||
|
||||
If not stated
|
||||
otherwise, all routines return 1 on successful completion and 0 when an
|
||||
error is detected. Please note, that many of these routines expect to find
|
||||
certain data items in the Sics Interpreter. This implies, that any naming
|
||||
changes in the initialisation file might force changes in here as well.
|
||||
|
||||
\begin{flushleft} \small
|
||||
\begin{minipage}{\linewidth} \label{scrap1}
|
||||
$\langle$Protos {\footnotesize ?}$\rangle\equiv$
|
||||
\vspace{-1ex}
|
||||
\begin{list}{}{} \item
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@ char *SNXMakeFileName(SicsInterp *pSics, SConnection *pCon);@\\
|
||||
\mbox{}\verb@@$\diamond$
|
||||
\end{list}
|
||||
\vspace{-1ex}
|
||||
\footnotesize\addtolength{\baselineskip}{-1ex}
|
||||
\begin{list}{}{\setlength{\itemsep}{-\parsep}\setlength{\itemindent}{-\leftmargin}}
|
||||
\item Macro defined by scraps ?, ?, ?, ?, ?, ?, ?.
|
||||
\item Macro referenced in scrap ?.
|
||||
\end{list}
|
||||
\end{minipage}\\[4ex]
|
||||
\end{flushleft}
|
||||
SNXMakeFileName creates a new filename from the SICS variables SicsDataPath,
|
||||
SicsDataPresript, SicsDataNumber and SicsDataEnding. SicsDataNumber will be
|
||||
incremented as well. The function returns a newly allocate buffer with the
|
||||
assembled filename or NULL on error. Note, that the caller is responsible
|
||||
for freeing the memory associated with the filename afterwards.
|
||||
|
||||
\begin{flushleft} \small
|
||||
\begin{minipage}{\linewidth} \label{scrap2}
|
||||
$\langle$Protos {\footnotesize ?}$\rangle\equiv$
|
||||
\vspace{-1ex}
|
||||
\begin{list}{}{} \item
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@ NXhandle SNXStartFile(SConnection *pCon, SicsInterp *pSics); @\\
|
||||
\mbox{}\verb@@$\diamond$
|
||||
\end{list}
|
||||
\vspace{-1ex}
|
||||
\footnotesize\addtolength{\baselineskip}{-1ex}
|
||||
\begin{list}{}{\setlength{\itemsep}{-\parsep}\setlength{\itemindent}{-\leftmargin}}
|
||||
\item Macro defined by scraps ?, ?, ?, ?, ?, ?, ?.
|
||||
\item Macro referenced in scrap ?.
|
||||
\end{list}
|
||||
\end{minipage}\\[4ex]
|
||||
\end{flushleft}
|
||||
First calls SNXMakeFileName in order to get a new Filename.
|
||||
Then a new Nexus file is
|
||||
created and all the standard headings are filled in: Filename, User,
|
||||
instrument, date etc. This routine also installs an error handler which
|
||||
prints errors to pCon.
|
||||
If successful, the SicsDataNumber is incremented and
|
||||
an NXhandle into the new file is returned. If there is a problem, NULL
|
||||
will be returned. The file returned will be positioned at root level.
|
||||
|
||||
\begin{flushleft} \small
|
||||
\begin{minipage}{\linewidth} \label{scrap3}
|
||||
$\langle$Protos {\footnotesize ?}$\rangle\equiv$
|
||||
\vspace{-1ex}
|
||||
\begin{list}{}{} \item
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@ int SNXStartEntry(NXhandle Nfil, int iNew, SicsInterp *pSics);@\\
|
||||
\mbox{}\verb@@$\diamond$
|
||||
\end{list}
|
||||
\vspace{-1ex}
|
||||
\footnotesize\addtolength{\baselineskip}{-1ex}
|
||||
\begin{list}{}{\setlength{\itemsep}{-\parsep}\setlength{\itemindent}{-\leftmargin}}
|
||||
\item Macro defined by scraps ?, ?, ?, ?, ?, ?, ?.
|
||||
\item Macro referenced in scrap ?.
|
||||
\end{list}
|
||||
\end{minipage}\\[4ex]
|
||||
\end{flushleft}
|
||||
\begin{flushleft} \small
|
||||
\begin{minipage}{\linewidth} \label{scrap4}
|
||||
$\langle$Protos {\footnotesize ?}$\rangle\equiv$
|
||||
\vspace{-1ex}
|
||||
\begin{list}{}{} \item
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@ void SNXFormatTime(char *pBuffer, int iBufLen);@\\
|
||||
\mbox{}\verb@@$\diamond$
|
||||
\end{list}
|
||||
\vspace{-1ex}
|
||||
\footnotesize\addtolength{\baselineskip}{-1ex}
|
||||
\begin{list}{}{\setlength{\itemsep}{-\parsep}\setlength{\itemindent}{-\leftmargin}}
|
||||
\item Macro defined by scraps ?, ?, ?, ?, ?, ?, ?.
|
||||
\item Macro referenced in scrap ?.
|
||||
\end{list}
|
||||
\end{minipage}\\[4ex]
|
||||
\end{flushleft}
|
||||
SNXFormatTime formats the current system time in a form compatible to the
|
||||
NeXus standard. Input parameters is a Buffer to hold the string and a
|
||||
length of the buffer. Maximum iBufLen characters will be copied to that
|
||||
buffer.
|
||||
|
||||
SNXStartEntry creates a new entry corresponding to iNew in the Nexus file
|
||||
Nfil. SNXStartEntry will position Nfil in this new entry. Any data items
|
||||
labeled as Comment or intent will be written to the file as well.
|
||||
|
||||
|
||||
\begin{flushleft} \small
|
||||
\begin{minipage}{\linewidth} \label{scrap5}
|
||||
$\langle$Protos {\footnotesize ?}$\rangle\equiv$
|
||||
\vspace{-1ex}
|
||||
\begin{list}{}{} \item
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@ int SNFinishFile(NXhandle Nfil);@\\
|
||||
\mbox{}\verb@@$\diamond$
|
||||
\end{list}
|
||||
\vspace{-1ex}
|
||||
\footnotesize\addtolength{\baselineskip}{-1ex}
|
||||
\begin{list}{}{\setlength{\itemsep}{-\parsep}\setlength{\itemindent}{-\leftmargin}}
|
||||
\item Macro defined by scraps ?, ?, ?, ?, ?, ?, ?.
|
||||
\item Macro referenced in scrap ?.
|
||||
\end{list}
|
||||
\end{minipage}\\[4ex]
|
||||
\end{flushleft}
|
||||
SNFinishFile will end a Nexus file properly.
|
||||
|
||||
\begin{flushleft} \small
|
||||
\begin{minipage}{\linewidth} \label{scrap6}
|
||||
$\langle$Protos {\footnotesize ?}$\rangle\equiv$
|
||||
\vspace{-1ex}
|
||||
\begin{list}{}{} \item
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@ int SNMakeDMC(SConnection *pCon, SicsInterp *pSics);@\\
|
||||
\mbox{}\verb@@$\diamond$
|
||||
\end{list}
|
||||
\vspace{-1ex}
|
||||
\footnotesize\addtolength{\baselineskip}{-1ex}
|
||||
\begin{list}{}{\setlength{\itemsep}{-\parsep}\setlength{\itemindent}{-\leftmargin}}
|
||||
\item Macro defined by scraps ?, ?, ?, ?, ?, ?, ?.
|
||||
\item Macro referenced in scrap ?.
|
||||
\end{list}
|
||||
\end{minipage}\\[4ex]
|
||||
\end{flushleft}
|
||||
SNMakeDMC produces a Nexus DMC data file from the currently valid
|
||||
information. It orchestrates all of the above.
|
||||
|
||||
\begin{flushleft} \small
|
||||
\begin{minipage}{\linewidth} \label{scrap7}
|
||||
$\langle$Protos {\footnotesize ?}$\rangle\equiv$
|
||||
\vspace{-1ex}
|
||||
\begin{list}{}{} \item
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@int SNStoreDMC(SConnection *pCon, SicsInterp *pSics, void *pData, int argc,@\\
|
||||
\mbox{}\verb@ char *argv[]);@\\
|
||||
\mbox{}\verb@@$\diamond$
|
||||
\end{list}
|
||||
\vspace{-1ex}
|
||||
\footnotesize\addtolength{\baselineskip}{-1ex}
|
||||
\begin{list}{}{\setlength{\itemsep}{-\parsep}\setlength{\itemindent}{-\leftmargin}}
|
||||
\item Macro defined by scraps ?, ?, ?, ?, ?, ?, ?.
|
||||
\item Macro referenced in scrap ?.
|
||||
\end{list}
|
||||
\end{minipage}\\[4ex]
|
||||
\end{flushleft}
|
||||
SNStoreData is the wrapper function used to install a DMC data storage
|
||||
command in the Sics interpreter.
|
||||
|
||||
|
||||
\begin{flushleft} \small
|
||||
\begin{minipage}{\linewidth} \label{scrap8}
|
||||
\verb@"nxdata.h"@ {\footnotesize ? }$\equiv$
|
||||
\vspace{-1ex}
|
||||
\begin{list}{}{} \item
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@/*-------------------------------------------------------------------------@\\
|
||||
\mbox{}\verb@ N X D A T A@\\
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@ Some routines for handling Nexus data file writing.@\\
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@ Mark Koennecke, April 1997@\\
|
||||
\mbox{}\verb@ @\\
|
||||
\mbox{}\verb@ copyright: see implementation file.@\\
|
||||
\mbox{}\verb@--------------------------------------------------------------------------*/@\\
|
||||
\mbox{}\verb@#ifndef SICSNXDATA@\\
|
||||
\mbox{}\verb@#define SICSNXDATA@\\
|
||||
\mbox{}\verb@@$\langle$Protos {\footnotesize ?, \ldots\ }$\rangle$\verb@ @\\
|
||||
\mbox{}\verb@#endif @\\
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@@$\diamond$
|
||||
\end{list}
|
||||
\vspace{-2ex}
|
||||
\end{minipage}\\[4ex]
|
||||
\end{flushleft}
|
||||
3053
doc/programmer/nxdict.tex
Normal file
3053
doc/programmer/nxdict.tex
Normal file
File diff suppressed because it is too large
Load Diff
42
doc/programmer/nxsans.tex
Normal file
42
doc/programmer/nxsans.tex
Normal file
@@ -0,0 +1,42 @@
|
||||
\subsection{NXUTIL}
|
||||
Ther are some utility functions for writing NeXus data files from
|
||||
SICS with the NXDICT-API. These are collected in the files nxutil.h
|
||||
and nxutil.c.
|
||||
|
||||
\begin{description}
|
||||
\item[int SNXSPutMotor(SicsInterp *pSics, SConnection *pCon, NXhandle hFil,
|
||||
NXdict pDict, char *pAlias, char *pName)] writes the
|
||||
value of a motor to file. The parameters are: \begin{description}
|
||||
\item[pSics] The SICS interpreter to search for the motor.
|
||||
\item[pCon] The connection object to which to print errors.
|
||||
\item[hFil] The handle of the NeXus file to write.
|
||||
\item[pDict] The handle of the NeXus dictionary to use.
|
||||
\item[pAlias] The alias name to use for writing.
|
||||
\item[pName] The name of the motor.
|
||||
\end{description}
|
||||
\item[SNXSPutMotorNULL] writes the motor zero point. Same parameters
|
||||
as above.
|
||||
\item[int SNXSPutVariable(SicsInterp *pSics, SConnection *pCon,\\
|
||||
NXHandle hFil, NXdict pDict, char *pAlias,\\
|
||||
char *pName)] writes a SICS variable to a NeXus file
|
||||
using the dictionary. Parameters similar to SNXSPutMotor.
|
||||
\item[SNXSPutEVVar(NXhandle hfil,NXdict pDict,char *pName, SConnection
|
||||
*pCon,\\ char *pValAlias, char *pStddevAlias)]
|
||||
This writes an environment variable pName to the file described by hfil,
|
||||
using the dictionary pDict. A warning is printed if the variable is
|
||||
not configured. If a variable is found its value and standard
|
||||
deviation are written to file using the aliases given as parameters.
|
||||
\item[SNXSPutGlobals] writes global data to the file.
|
||||
\item[SNXSFormatTime] returns the current time formatted according to
|
||||
the NeXus specification in buffer. Max iLen characters will be copied
|
||||
to buffer.
|
||||
\item[SNXSMakeFileName] returns a pointer to a buffer containing a new
|
||||
file name for a data file. This function assembles the filename from
|
||||
the DataNUmber and various SICS variables. The caller has to free the
|
||||
buffer containg the name.
|
||||
\item[SNXSPutDrivable] writes any variable adhering to the drivable
|
||||
interface.
|
||||
\end{description}
|
||||
|
||||
|
||||
|
||||
42
doc/programmer/o2t.tex
Normal file
42
doc/programmer/o2t.tex
Normal file
@@ -0,0 +1,42 @@
|
||||
\subsection{Omega 2Theta}
|
||||
This is an example for a simple virtual motor. It uses two motors and runs
|
||||
the second one to exactly the double value of the first one. It can be used
|
||||
to implement omega--two--theta (o2t) scans at reflectometers of four circle
|
||||
diffractometers using the normal scan command.
|
||||
|
||||
The o2t module uses the following data structure:
|
||||
\begin{verbatim}
|
||||
typedef struct __SicsO2T {
|
||||
pObjectDescriptor pDes;
|
||||
pIDrivable pDrivInt;
|
||||
pMotor pOmega;
|
||||
pMotor pTheta;
|
||||
} SicsO2T;
|
||||
|
||||
\end{verbatim}
|
||||
The fields:
|
||||
\begin{description}
|
||||
\item[pDes] A pointer to the usual SICS object descriptor.
|
||||
\item[pDrivInt] A pointer to the drivable interface implemented by this
|
||||
variable.
|
||||
\item[pOmega] A pointer to the first motor to use.
|
||||
\item[pTheta] A pointer to the motor data structure of the second (double)
|
||||
motor to use.
|
||||
\end{description}
|
||||
|
||||
|
||||
Most of this modules action lives in the drivable interface. The rest is
|
||||
achieved through the following functions:
|
||||
\begin{description}
|
||||
\item[pSicsO2T MakeO2T(char *omega, char *theta, SicsInterp *pSics)] creates
|
||||
a new o2t object from motors omega and theta. Returns NULL on failure and a
|
||||
pointer to an o2t data structure on success.
|
||||
\item[void DeleteO2T(void *pData)] deletes an o2t object.
|
||||
\item[int CreateO2T(SConnection *pCon, SicsInterp *pSics, void *pData,\\
|
||||
int argc, char *argv[])] The object factory function for o2t
|
||||
objects.
|
||||
\end{description}
|
||||
|
||||
Please note, that o2t is just a helper variable and can not be manipualted
|
||||
from the SICS interpreter.
|
||||
|
||||
44
doc/programmer/obpar.tex
Normal file
44
doc/programmer/obpar.tex
Normal file
@@ -0,0 +1,44 @@
|
||||
\subsection{SICS Parameter Array}
|
||||
This thing holds an array of floating point numbers, their names and their access codes.
|
||||
It is used in SICS object implementations to hold larger amounts of
|
||||
configurable parameters. It provides functions for simplifying the
|
||||
management of such parameters.
|
||||
|
||||
Each parameter is described by a structure shown below:
|
||||
\begin{verbatim}
|
||||
typedef struct {
|
||||
char *name;
|
||||
float fVal;
|
||||
int iCode;
|
||||
} ObPar;
|
||||
\end{verbatim}
|
||||
The fields are: \begin{description}
|
||||
\item[name] The name of the parameter.
|
||||
\item[fVal] The parameters value.
|
||||
\item[iCode] The access code necessary to modify the parameter.
|
||||
\end{description}
|
||||
|
||||
Parameter arrays are maintained by the functions described below:
|
||||
\begin{description}
|
||||
\item[ float ObVal(ObPar *self, int i)] gets the value of parameter i from
|
||||
the array self. This call is for module internal usage.
|
||||
\item[int ObParLength(ObPar *self)]
|
||||
finds the length of an ObPar array.
|
||||
\item[ObPar *ObParFind(ObPar *self, char *name)]
|
||||
finds a ObPar struct for a name, return NULL if none.
|
||||
\item[int ObParInit(ObPar *self,int i, char *name, float fVal, int iCode)]
|
||||
sets a ObPar entry. self is a pointer to the array.
|
||||
\item[int ObParSet(ObPar *self, char *obname,char *name, float fVal, SConnection
|
||||
*pCon)]
|
||||
checks if the connections permissions are alright and changes value
|
||||
if so. Returns 1 on success, 0 on failure. Prints errors directly to
|
||||
pCon. The parameter obname is the name of the object the parameters belong
|
||||
to. Needed for error printing. name is the parameter name, fVal the new
|
||||
value.
|
||||
\item[void ObParDelete(ObPar *self)]
|
||||
Deletes an ObPar array.
|
||||
\item[ObPar *ObParCreate(int iArrayLong)]
|
||||
creates an array with iASrrayLong entries. Returns NULL on failure, else
|
||||
a pointer to the array.
|
||||
\end{description}
|
||||
|
||||
24
doc/programmer/ofac.tex
Normal file
24
doc/programmer/ofac.tex
Normal file
@@ -0,0 +1,24 @@
|
||||
\subsection{The Object Factory}
|
||||
SICS is a highly configurable system. This module implements
|
||||
the configurable. Configuration is meant to happen via a Tcl-
|
||||
configuration script. This module will initialize commands which
|
||||
create SICS-objects. Than an initialization file is evaluated
|
||||
via the macro facility. As most of the initialization commands
|
||||
will no longer be needed after this, they will be deleted.
|
||||
All this will be run with a higly privileged connection which
|
||||
prints to stdout/stdin. This module contains the file static functions:
|
||||
InitIniCommands and KillIniCommands. {\bf InitIniCommands}
|
||||
intializes all SICS common commands plus the object creation
|
||||
commands. Once a new class has been devised its object
|
||||
creation function needs to be entered into this
|
||||
function. {\bf KillIniCommands} removes all the initialization
|
||||
commands no longer needed after the initialization file has
|
||||
been evaluated. Make sure to add an entry for your new
|
||||
classes creation command here as well.
|
||||
|
||||
The interface consists of a single function: \begin{verbatim}
|
||||
int InitObjectCommands(pServer pServ, char *file);
|
||||
\end{verbatim}
|
||||
Commands will be initialized for the server pServ from the file file.
|
||||
|
||||
|
||||
804
doc/programmer/oguide.tex
Normal file
804
doc/programmer/oguide.tex
Normal file
@@ -0,0 +1,804 @@
|
||||
\chapter{Guide To SICS Object Writers}
|
||||
This chapter describes the necessary steps for adding new objects to the SICS server. In order to live
|
||||
happily within SICS an object is obliged to stick to a set of rules and interfaces already defined. Such
|
||||
interfaces will be described here as well. For the following text it is assumed, that the reader has studied
|
||||
the SICS overview and kernel guide.
|
||||
|
||||
In general the following steps will be necessary in order to introduce a new object into SICS:
|
||||
\begin{enumerate}
|
||||
\item Define a new object data structure.
|
||||
\item Define a function capable of deleting the object from memory.
|
||||
\item Define a set of functions which define the operations on this object.
|
||||
\item Create an object wrapper function which defines the user commands
|
||||
the object can handle.
|
||||
\item Create an object creation function, which is capable of initializing
|
||||
the object and creates a new command in the SICS interpreter.
|
||||
\item Add the new objects creation command into the IniInitCommand and
|
||||
KillIniCommands functions defined in ofac.c.
|
||||
\item Document the new object.
|
||||
\end{enumerate}
|
||||
All these steps will now be discussed together with some additional SICS
|
||||
concepts applicable to writing new objects. Not all of the above mentioned
|
||||
steps will be necessary in all cases. If a new general SICS object is defined,
|
||||
no object creation function may be needed. Then it is sufficient to register
|
||||
the new object/command with the SICS interpreter in IniInitCommands, file ofac.c.
|
||||
In the rare cases where an object needs no data structure, the system will provide a dumb
|
||||
default which will not harm the system. Some objects may have more then one
|
||||
command associated with them. Some more care has to be taken when adding a
|
||||
new piece of hardware into the system. If it is just a variant of an already
|
||||
known type (for instance a new type of motor) it will be sufficient to introduce
|
||||
a new driver into the system. The procedures for doing this will be described
|
||||
in the reference sections for the appropriate device. Otherwise the SICS rule
|
||||
to divide a hardware object into a logical object and a driver should be
|
||||
observed. At minimum two drivers are necessary anyway in the first place:
|
||||
the driver for the actual device and a simulation driver which permits some
|
||||
debugging to take place while the hardware is still unavailable.
|
||||
|
||||
\section{Mapping Object Oriented Concepts into ANSI--C}
|
||||
SICS is in principle an object oriented system. However, it is implemented
|
||||
in ANSI--C. Therefore object oriented concepts must be mapped into C. The
|
||||
three object oriented concepts which need to be mapped are:
|
||||
\begin{itemize}
|
||||
\item Data Encapsulation.
|
||||
\item Polymorphism.
|
||||
\item Inheritance.
|
||||
\end{itemize}
|
||||
|
||||
Of these, data encapsulation is by far the most important concept. Objects
|
||||
in computer science can be understood as little boxes which contain some
|
||||
data describing their state and which understand messages sent by other
|
||||
objects. If such a message comes in, the object performs some action,
|
||||
perhaps changes its internal state or sends new messages to other objects.
|
||||
It is understood that changes to the internal data of the object can be
|
||||
achieved only through messages to the object and not by directly manipulating
|
||||
variables from the outside. In ANSI--C an object maps to a structure holding
|
||||
the objects data and the messages map to functions which act upon the data
|
||||
structure. In order to do this, the functions must take a pointer to the
|
||||
objects data structure as first parameter. In order to prevent messing with
|
||||
an objects data structure, only a pointer to a structure is declared in the
|
||||
header file. The actual definition of the data structure happens only in
|
||||
the implementation file. All functions belonging to an object are defined in that
|
||||
implementation file and have full access to the data structure.
|
||||
Users of the object see only the header file and thus only a pointer to the
|
||||
objects data structure which prevents
|
||||
them from messing with the objects data directly.
|
||||
In order to illustrate the concepts lets look at
|
||||
a primitive integer object defined in such a way.
|
||||
\begin{verbatim}
|
||||
/*-----------------------------------------------------------------------
|
||||
ExampleInt.h
|
||||
------------------------------------------------------------------------*/
|
||||
typedef struct __ExampleInt *pExampleInt;
|
||||
|
||||
int GetInt(pExampleInt self);
|
||||
void SetInt(pExampleInt self, int iNew);
|
||||
/*------------------- EOF ExampleInt.h---------------------------------*/
|
||||
|
||||
/*----------------------------------------------------------------------
|
||||
ExampleInt.c, Implementation file
|
||||
-----------------------------------------------------------------------*/
|
||||
typedef struct __ExampleInt {
|
||||
int iExample;
|
||||
} ExampleInt;
|
||||
/*--------------------------------------------------------------------*/
|
||||
int GetInt(pExampleInt self)
|
||||
{
|
||||
return self->iExample;
|
||||
}
|
||||
/*---------------------------------------------------------------------*/
|
||||
void SetInt(pExampleInt self, int iNew)
|
||||
{
|
||||
self->iExample = iNew;
|
||||
}
|
||||
\end{verbatim}
|
||||
Using this scheme all code changing the internal state of an object lives
|
||||
in one file. Changes to the objects data structure affect only the
|
||||
implementation file and no other files.
|
||||
This scheme is used for almost all SICS objects. A few system objects and
|
||||
older SICS objects define their data structures in header files. This is
|
||||
either a relic or had to be done for performance reasons.
|
||||
|
||||
The next concept is polymorphism. This describes the situation when a group
|
||||
of objects respond to the same message but doing different things. For
|
||||
instance a whole set of objects would implement a write functionality
|
||||
which writes the objects state to a file. Higher level would then not need
|
||||
to know of which type the actual object is, it just can send the write message
|
||||
and the rest is taken care of by the object. This concept is used for all
|
||||
hardware drivers in SICS. Mapping this to C requires to expose the objects
|
||||
data structure and let the data structure include a pointer to that polymorphic
|
||||
function. As an example, the ExampleInteger with a write function:
|
||||
\begin{verbatim}
|
||||
/*-----------------------------------------------------------------------
|
||||
ExampleInt.h
|
||||
------------------------------------------------------------------------*/
|
||||
typedef struct __ExampleInt{
|
||||
int iExample;
|
||||
void (*write)(struct __ExampleInt *self, FILE *fd);
|
||||
} *pExampleInt, ExampleInt;
|
||||
|
||||
pExampleInt MakeInt(int iNew);
|
||||
|
||||
int GetInt(pExampleInt self);
|
||||
void SetInt(pExampleInt self, int iNew);
|
||||
/*------------------- EOF ExampleInt.h---------------------------------*/
|
||||
|
||||
/*----------------------------------------------------------------------
|
||||
ExampleInt.c, Implementation file
|
||||
-----------------------------------------------------------------------*/
|
||||
static void ExampleWrite(struct _-ExampleInt *self, FILE *fd)
|
||||
{
|
||||
fprintf(fd,"INT = %d",self->iExample);
|
||||
}
|
||||
/*---------------------------------------------------------------------*/
|
||||
pExampleInt MakeInt(int iNew)
|
||||
{
|
||||
pExampleInt pNew = NULL;
|
||||
|
||||
pNew = (pExampleInt)malloc(sizeof(ExampleInt));
|
||||
pNew->iExample = iNew;
|
||||
pNew->write = ExampleWrite;
|
||||
return pNew;
|
||||
}
|
||||
.
|
||||
.
|
||||
.
|
||||
\end{verbatim}
|
||||
This can then be called:
|
||||
\begin{verbatim}
|
||||
void SomeFunc()
|
||||
{
|
||||
pExampleInt pTest;
|
||||
|
||||
pTest = MakeInt(25);
|
||||
.
|
||||
.
|
||||
.
|
||||
pTest->write(pTest,fd);
|
||||
}
|
||||
\end{verbatim}
|
||||
This example also illustrates the concept of a special function which creates
|
||||
a new object of the appropriate type and initializes its data structure
|
||||
properly.
|
||||
|
||||
The last concept to discuss is inheritance. Inheritance can be used when
|
||||
an object is a derivative of another object. For instance a truck is a
|
||||
derivative of a motor car. Much of the behavior of a motor car will be the
|
||||
same as for a truck. In order to prevent rewriting of code, the truck
|
||||
should use the same data structures and code as the motor car. And add
|
||||
or modify only what is special. Inheritance is not much used in SICS. It can
|
||||
be implemented by overlaying data structures. This means the derived
|
||||
classes data structure has the same fields in the same order as the parent
|
||||
class and adds its specials at the end. For example:
|
||||
\begin{verbatim}
|
||||
typedef struct __MotorCar {
|
||||
int iWheels;
|
||||
float fSpeed;
|
||||
} *pMotorCar, MotorCar;
|
||||
|
||||
|
||||
typedef struct __Truck {
|
||||
int iWheels;
|
||||
float fSpeed; /* same as MotorCar */
|
||||
double dPayLoad; /* special for Truck */
|
||||
} *pTruck, Truck;
|
||||
|
||||
\end{verbatim}
|
||||
Thus functions defined for motor car can operate on trucks as well.
|
||||
For more details study the relationship between the ITC4 controller and
|
||||
general environment controllers. This is the only place where SICS
|
||||
currently uses inheritance.
|
||||
|
||||
|
||||
\section{The Object Data Structure}
|
||||
Nearly all SICS objects require some data. This data is collected in a
|
||||
C structure typical for the object. This is just a normal C struct with one
|
||||
exception:
|
||||
\begin{center}
|
||||
\rule{9cm}{2mm}
|
||||
\end{center}
|
||||
\leftline{{\huge Rule 1}}
|
||||
The first item in a SICS object data structure MUST be a pointer to a
|
||||
ObjectDescriptor data structure. This looks like:
|
||||
\begin{verbatim}
|
||||
typedef struct __MyObject {
|
||||
pObjectDescriptor pDes;
|
||||
int iMyExtremlyImportantInt;
|
||||
.
|
||||
.
|
||||
.
|
||||
} MyObject;
|
||||
\end{verbatim}
|
||||
\begin{center}
|
||||
\rule{9cm}{2mm}
|
||||
\end{center}
|
||||
|
||||
Otherwise the SICS server will crash on you sooner or later. The reason for
|
||||
this is that SICS needs a means to identify a object and its capabilities
|
||||
from inside its code. For example a user has typed: {\em drive mot1 26} into
|
||||
the server. Now drive needs to verify that mot1 is really a motor or
|
||||
something else which can be driven. This can be done in the following way:
|
||||
\begin{enumerate}
|
||||
\item First find the object in the SICS interpreter
|
||||
(function FindCommand, SCinter.h).
|
||||
\item Get the pointer to the objects data structure.
|
||||
\item Assign this pointer to a dummy data structure (defined in obdes.h)
|
||||
which has a pointer to the ObjectDescriptor as single element.
|
||||
\item Ask the ObjectDescriptor if the object can be driven.
|
||||
\end{enumerate}
|
||||
In object speak this is called run time type information (RTTI).
|
||||
|
||||
It is interesting to look at the object descriptor in more detail. It is
|
||||
again a data structure and a good example for polymorphism:
|
||||
\begin{verbatim}
|
||||
typedef struct {
|
||||
char *name;
|
||||
int (*SaveStatus)(void *self, char *name,FILE *fd);
|
||||
void *(*GetInterface)(void *self, int iInterfaceID);
|
||||
} ObjectDescriptor, *pObjectDescriptor;
|
||||
|
||||
\end{verbatim}
|
||||
The first field contains a string defining a type name. The next field is a
|
||||
pointer to a save function. This function is automatically called for all objects
|
||||
in the SICS interpreter when the server shuts down. This function is supposed to
|
||||
write all SICS commands necessary to reconfigure the object back into its current state
|
||||
into file fd. The middle parameter is the name of the object in the interpreter
|
||||
which must not necessarily be known to the object.
|
||||
|
||||
The next field, a pointer to a function GetInterface is used in order to inquire
|
||||
the capabilities of an object. Object capabilities in SICS are defined in terms of
|
||||
{\bf {\Large Interfaces}}. An Interface in the SICS sense is again a data structure
|
||||
which contains data fields and pointers to functions implementing the capability. As
|
||||
an example see the Drivable interface which is implemented by motors, environment
|
||||
devices and variables such as lambda which can be driven to a new value:
|
||||
\begin{verbatim}
|
||||
typedef struct {
|
||||
int ID;
|
||||
int (*Halt)(void *self);
|
||||
int (*CheckLimits)(void *self, float fVal,
|
||||
char *error, int iErrLen);
|
||||
long (*SetValue)(void *self, SConnection *pCon,
|
||||
float fVal);
|
||||
int (*CheckStatus)(void *self, SConnection *pCon);
|
||||
float (*GetValue)(void *self, SConnection *pCon);
|
||||
} IDrivable, *pIDrivable;
|
||||
|
||||
\end{verbatim}
|
||||
Each SICS interface is identified by an integer ID number (defined in interface.h).
|
||||
GetInterface returns a pointer to an interface data structure for an ID if the object
|
||||
implements that interface. If not a NULL is returned.
|
||||
|
||||
\section{SICS Interfaces}\label{gow}
|
||||
Thus SICS interfaces define the capabilities of an object. The concept of
|
||||
Interfaces is similar to interfaces in the Java programming language
|
||||
or abstract base classes in C++ or other object oriented languages.
|
||||
As can be seen from the example
|
||||
given above, the interface implements the most common operations on an object with
|
||||
capabilities as defined by the interface. Currently, SICS knows four different kinds of
|
||||
Interfaces:
|
||||
\begin{description}
|
||||
\item[Drivable] The Drivable interface for objects such as motors, adjustable parameters
|
||||
and the like. Anything which can be driven to a value.
|
||||
\item[Countable] The Countable interface used for everything which can count: single
|
||||
counters, histogram memories or whatever may creep up.
|
||||
\item[CallBack] The CallBack interface introduces some component programming techniques
|
||||
into SICS. This technique lets an object, name it object A, issue events when its internal
|
||||
state changes. For example if object A is a motor, any time it drives to a new value
|
||||
an event is issued. Then another object, name it object B, can register an interest in
|
||||
such events with object A. It does so by giving A the address of a function to call
|
||||
when such an event occurs. A now calls all functions thus registered when the event
|
||||
occurs. Object B thus gets automatically notified when A changes its state. Currently
|
||||
this scheme is only used for implementing automatic notifications of clients when a
|
||||
SICS object changes its state. But there is a lot of potential in this scheme.
|
||||
\item[Environment] The Environment device is a interface implemented by all devices which
|
||||
need to be regularly monitored by the environment monitor.
|
||||
\end{description}
|
||||
For more details about the SICS interfaces see the reference section: \ref{interref}.
|
||||
The list of SICS interfaces can be extended when a novel abstract capability of an object
|
||||
is needed. This is also the main reason why this sophisticated scheme was chosen.
|
||||
|
||||
The question may arise how to use SICS interfaces. For example consider an object defining
|
||||
a drivable variable. The following steps are necessary:
|
||||
\begin{enumerate}
|
||||
\item Define functions with matching parameters to the ones requested by the interface.
|
||||
Tip: the first parameter, the pointer to void, is always the pointer to the object data
|
||||
structure to operate on. These functions must implement appropriate actions. What these
|
||||
are: see the documentation of the interface.
|
||||
\item Define a GetInterface function which returns a suitable interface
|
||||
data structure when asked for an interface with the Drivable ID. The fields of the interface
|
||||
structure returned must be set to the addresses of the functions you defined in step 1.
|
||||
\item Create an object initialization function.
|
||||
\item In this object initialization function: assign the object descriptors filed GetInterface
|
||||
to the address of your GetInterface function.
|
||||
\end{enumerate}
|
||||
Usually, the interfaces an object implements are made a field in the objects data
|
||||
structure. This interface is then initialized with appropriate function pointers when
|
||||
creating the object. GetInterface then returns this pointer when the interface is
|
||||
requested. Due to this usage a rule exits:
|
||||
\begin{center}
|
||||
\rule{9cm}{2mm}
|
||||
\end{center}
|
||||
\leftline{{\huge Rule 2}}
|
||||
Any interface data structure provided by an object belongs to the object providing
|
||||
it. The owner object is responsible for deleting it. Never free an interface data structure
|
||||
provided by another object.
|
||||
\begin{center}
|
||||
\rule{9cm}{2mm}
|
||||
\end{center}
|
||||
|
||||
Note, that the SICS interfaces are not the only interfaces to take care of. As SICS uses
|
||||
this duality between logical hardware objects and hardware drivers, the interfaces defined
|
||||
by the logical hardware devices can been seen as yet another internal interface. This leads to:
|
||||
\begin{center}
|
||||
\rule{9cm}{2mm}
|
||||
\end{center}
|
||||
\leftline{{\huge Recommendation}}
|
||||
Watch your neighbors! Use the interfaces provided by the logical hardware objects for
|
||||
your objects business, when applicable.
|
||||
\begin{center}
|
||||
\rule{9cm}{2mm}
|
||||
\end{center}
|
||||
|
||||
\section{The Object Deletion Function}
|
||||
When the SICS server exits or when a command is removed from the SICS
|
||||
interpreter the interpreter will call a function which should free the memory
|
||||
associated with the deleted object. This is absolutely necessary in order to
|
||||
prevent memory leakage. Such a function has the form:
|
||||
\begin{verbatim}
|
||||
void ObjectKiller(void *pData);
|
||||
\end{verbatim}
|
||||
with pData being the pointer to the object to delete.
|
||||
|
||||
|
||||
\section{Writing Object Functions}
|
||||
The rules specified in this section apply to all kinds of object functions:
|
||||
those which implement functionality as well as the object wrapper
|
||||
functions. Please note, that any SICS object has two interfaces: an internal
|
||||
C--language interface and a user visible interface defined by the object
|
||||
wrapper functions. There are reasons why those two interfaces might not
|
||||
provide equivalent functionality.
|
||||
|
||||
\subsection{Input and OutPut}
|
||||
\begin{center}
|
||||
\rule{9cm}{2mm}
|
||||
\end{center}
|
||||
\leftline{{\huge Rule 3}}
|
||||
All input and output to the client executing the command must go through the
|
||||
connection object functions SCWrite and SCPrompt.
|
||||
\begin{center}
|
||||
\rule{9cm}{2mm}
|
||||
\end{center}
|
||||
These function will now be inspected in more detail:
|
||||
\begin{verbatim}
|
||||
int SCWrite(SConnection *pCon, char *pText, int eCode);
|
||||
int SCPrompt(SConnection *pCon, char *pPrompt, char *pBuffer, int iBufLen);
|
||||
\end{verbatim}
|
||||
SCWrite writes the data pText to the connection specified by pCon. The
|
||||
parameter eCode denotes the output code of the data in pText. SICS clients
|
||||
can choose to suppress some I/O from the SICS server. For instance a
|
||||
GUI--client might chooses not to receive scan status reports. For this
|
||||
purpose it was necessary to stick an output code onto each message to the
|
||||
client. Possible output codes are: eError, eWarning, eValue, eStatus and
|
||||
some internal codes. The names are self explaining. eValue denotes a value
|
||||
which has been explicitly asked for by the client. The rule specified above
|
||||
becomes understandable and thus bearable when looking at all the things
|
||||
SCWrite does with the message:
|
||||
\begin{itemize}
|
||||
\item It is written to the client connection socket, subject to the output
|
||||
code specified.
|
||||
\item The message is written to all log files configured for the client
|
||||
connection.
|
||||
\item The message is written to the server log together with the socket
|
||||
number of the connection.
|
||||
\item SCWrite stores the message into the Tcl macro interpreter in order to
|
||||
enable processing of data from SICS commands in Tcl scripts.
|
||||
\item SCWrite suppresses all messages to the client while executing a macro.
|
||||
This stops spurious output to appear at the client connection when running a
|
||||
command defined in the macro language. The exception are messages of type
|
||||
eError and eWarning. Such messages are always sent to the client.
|
||||
\end{itemize}
|
||||
|
||||
SCPrompt prompts the user at the client connection for data. The prompt
|
||||
string pPrompt is sent. Data entered by the user is returned in buffer
|
||||
pBuffer. Maximum iBufLen character are returned. While waiting for client to
|
||||
provide data, the SICS task switcher runs.
|
||||
|
||||
There is another convenience function SCSendOK(SConnection *pCon) which is
|
||||
just a wrapper around SCWrite. SCSendOk sends an 'OK' to the client. It is good
|
||||
practice to let the user know that the operation requested had been
|
||||
performed.
|
||||
|
||||
Given the rule stated above, it follows that connection objects have to
|
||||
be passed through the system to nearly everywhere. Especially where
|
||||
reportable errors are found.
|
||||
|
||||
All other I/O, for instance to files sitting at the computer running the
|
||||
SICS server, is not subjected to Rule 3.
|
||||
|
||||
|
||||
\subsection{Error Handling}
|
||||
Error handling is two thirds of the code written. Errors can be caused by
|
||||
faulty users or faulty hardware. In any case, the first thing to do is:
|
||||
report it using SCWrite! The next thing is to get the system into a state
|
||||
that it can continue execution. This is particularly important for a server
|
||||
program which might run for months on end. This means, free all memory used
|
||||
before the error occurred, get system variables into safe values and the
|
||||
like.
|
||||
|
||||
Sometimes error conditions arise in lower level code which should cause all
|
||||
upper level code to finish execution. Such conditions may be the result of a
|
||||
critical hardware fault or may even be requested by a user who wants to
|
||||
abort an operation. A standard method for communicating such conditions
|
||||
through the system is necessary. SICS uses interrupts for such conditions.
|
||||
The current interrupt active interrupt is located at the connection object
|
||||
and can be retrieved with {\bf SCGetInterrupt} and set with {\bf
|
||||
SCSetInterrupt}. Interrupt codes are defined in interrupt.h and are ordered
|
||||
into a hierarchy:
|
||||
\begin{description}
|
||||
\item[eContinue] Everything is just fine.
|
||||
\item[eAbortOperation] Stop the current scan point or whatever is done,
|
||||
but do not stop altogether.
|
||||
\item[eAbortScan] Abort the current scan, but continue processing of further
|
||||
commands in R\"unbuffers or command files.
|
||||
\item[eAbortBatch] Aborts everything, operations, scans and batch processing
|
||||
and leaves the system ready to enter new commands.
|
||||
\item[eHaltSystem] As eAbortBatch, but lock the system.
|
||||
\item[eFreeSystem] Unlocks a system halted with eHaltSystem.
|
||||
\item[eEndServer] Makes the SICS server run down and exit.
|
||||
For internal usage only.
|
||||
\end{description}
|
||||
|
||||
In most cases interrupts shall only effect the client connection executing
|
||||
the command. In such cases user code should use SCSetInterrupt in order to
|
||||
set an interrupt at the connection executing the command only. Very rarely
|
||||
conditions occur when an interrupt should affect the whole system. Then
|
||||
SetInterrupt (defined in intserv.h) should be used. SetInterrupt forwards
|
||||
the interrupt to all running tasks.
|
||||
|
||||
Objects implementing higher level commands such as scan commands might be
|
||||
able to handle interrupt conditions and thus consume an interrupt. Then the
|
||||
interrupt must be released with SCSetInterrupt and setting the interrupt to
|
||||
eContinue. The interrupt on a connection will automatically be set to
|
||||
eContinue when executing a new command from the command stack.
|
||||
|
||||
Objects are responsible for checking for interrupt conditions when
|
||||
applicable. This is specially true for objects performing complex or
|
||||
lengthy
|
||||
operations with hardware. Whenever a hardware operation finishes, the
|
||||
interrupt must be checked for and handled. The called hardware object or
|
||||
the user might have set an interrupt which needs to be honored.
|
||||
|
||||
Thus two new rules can be defined:
|
||||
\begin{center}
|
||||
\rule{9cm}{2mm}
|
||||
\end{center}
|
||||
\leftline{{\huge Rule 4}}
|
||||
Signal critical error conditions with interrupts.
|
||||
\begin{center}
|
||||
\rule{9cm}{2mm}
|
||||
\end{center}
|
||||
\begin{center}
|
||||
\rule{9cm}{2mm}
|
||||
\end{center}
|
||||
\leftline{{\huge Rule 5}}
|
||||
Check for pending interrupts wherever applicable.
|
||||
\begin{center}
|
||||
\rule{9cm}{2mm}
|
||||
\end{center}
|
||||
|
||||
\subsection{Authorisation}
|
||||
Objects are also responsible for checking if the client requesting an
|
||||
operation may actually perform the operation. There are two cases when an
|
||||
operation may be forbidden:
|
||||
\begin{itemize}
|
||||
\item The user is not suitably authorized.
|
||||
\item The user is about to change critical parameters affecting a running
|
||||
measurement.
|
||||
\end{itemize}
|
||||
Both conditions must be checked for by the objects code. Where else then at
|
||||
the object can be known which operations are critical or not? This gives a
|
||||
new rule:
|
||||
\begin{center}
|
||||
\rule{9cm}{2mm}
|
||||
\end{center}
|
||||
\leftline{{\huge Rule 6}}
|
||||
Objects have to check authorisation!
|
||||
\begin{center}
|
||||
\rule{9cm}{2mm}
|
||||
\end{center}
|
||||
|
||||
The user rights code for a client connection can be retrieved with
|
||||
SCGetRights. SCGetGrab finds out if a connection has the control token.
|
||||
A match with a value can be checked for with SCMatchRights which
|
||||
returns true (1) if the connection has a user rights equal or higher then the
|
||||
one necessary. SCMatchRights also checks for the status of the control token
|
||||
and prints messages. SCMatchRights is the recommended function for checking
|
||||
access rights in SICS.
|
||||
|
||||
An object can find out if some hardware operation is running by calling
|
||||
the function isInRunMode prototyped in devexec.h.
|
||||
|
||||
An object can find out, if it is executing in a macro by calling SCinMacro.
|
||||
Might be useful if the code is dependent on this condition. Usually all
|
||||
details associated with running in a macro are dealt with by the system.
|
||||
|
||||
\subsection{Driving Hardware}
|
||||
\begin{center}
|
||||
\rule{9cm}{2mm}
|
||||
\end{center}
|
||||
\leftline{{\huge Rule 7}}
|
||||
Use the device executor!
|
||||
\begin{center}
|
||||
\rule{9cm}{2mm}
|
||||
\end{center}
|
||||
With respect to hardware, there are two different kinds of objects in SICS:
|
||||
some objects represent hardware. Examples are motors, counters. This group
|
||||
also includes drivable variables which implement coordinated movements of
|
||||
hardware. Such objects have to implement the necessary interfaces: either
|
||||
the drivable or the countable interface. The second class are objects which
|
||||
implement commands which use the hardware. For instance a drive command.
|
||||
This second class of commands has to find the necessary hardware objects and
|
||||
then run the actual hardware through the device executor. The function to
|
||||
use is StartDevice or its derivatives, prototyped in devexec.h. After this
|
||||
is done, there are tow options. In a scan command it might be needed to wait for
|
||||
the hardware to finish before continuing your code. In this case use
|
||||
function TaskWait, prototyped in tasker.h.
|
||||
In other cases execution of the function may just
|
||||
continue. The device executor will the take care of the task of monitoring
|
||||
the hardware operation. The following code snippet gives an example how to
|
||||
start a counter properly and wait for it to finish:
|
||||
\begin{verbatim}
|
||||
/*-------------- count */
|
||||
pDum = (pDummy)self->pCounterData;
|
||||
iRet = StartDevice(pServ->pExecutor, /* the executor, from global pServ */
|
||||
"ScanCounter", /* a name */
|
||||
pDum->pDescriptor, /* the descriptor of the cter */
|
||||
self->pCounterData, /* pointer to counter data */
|
||||
self->pCon, /* pointer to connection object */
|
||||
self->fPreset); /* count preset */
|
||||
if(!iRet)
|
||||
{
|
||||
SCWrite(self->pCon,"ERROR: Cannot Count, Scan aborted",eError);
|
||||
return 0;
|
||||
}
|
||||
/* wait for finish */
|
||||
lTask = GetDevexecID(pServ->pExecutor); /* get ID of device
|
||||
executor task */
|
||||
if(lTask > 0);
|
||||
{
|
||||
TaskWait(pServ->pTasker,lTask);
|
||||
}
|
||||
|
||||
/* finished, check for interrupts. Whatever happened, user
|
||||
interrupt or HW interrupt, it will be on our connection
|
||||
*/
|
||||
iInt = SCGetInterrupt(self->pCon);
|
||||
switch(iInt)
|
||||
{
|
||||
case eContinue:
|
||||
break;
|
||||
case eAbortOperation:
|
||||
continue;
|
||||
break;
|
||||
case eAbortScan:
|
||||
SCWrite(self->pCon,"ERROR: Scan aborted",eError);
|
||||
/* eat the interrupt, the requested op has been
|
||||
done
|
||||
*/
|
||||
SCSetInterrupt(self->pCon,eContinue);
|
||||
return 0;
|
||||
break;
|
||||
default: /* all others */
|
||||
SCWrite(self->pCon,"ERROR: Scan aborted",eError);
|
||||
return 0;
|
||||
break;
|
||||
}
|
||||
|
||||
\end{verbatim}
|
||||
The above code (taken from the implementation of the scan command) also
|
||||
shows an example for handling interrupts as a followup to running hardware.
|
||||
Such a procedure is highly recommended.
|
||||
|
||||
\subsection{Working with the CallBack Interface}
|
||||
Working with the callback interface is usually simple: just use the
|
||||
functions as defined in interface.h. Add new event codes to event.h, in
|
||||
order to make them known. A problem arises if an object which has callbacks
|
||||
registered with other objects gets deleted. For the following discussion:
|
||||
let us denote the object registering the callback as the client object and
|
||||
the object which generates the event (where the callback was registered) as
|
||||
source object. A typical example for a client is a
|
||||
connection object which had configured itself to be automatically notified
|
||||
of motor movements, variable changes and the like. Typically this is a
|
||||
status display client. In such cases the client object has to keep
|
||||
track of the callbacks it registered and delete them when the client objects gets
|
||||
deleted. Otherwise the source object would invoke a callback on an non
|
||||
existing client object. This usually results in a lovely core dump. For the
|
||||
connection object this is taken care of automatically. The only thing needed
|
||||
to be done, is to register the callback on the connection object with
|
||||
SCRegister prototyped in conman.h. If user codes removes a callback later on,
|
||||
it may call SCUnregister on the connection object to remove it from the
|
||||
connection objects callback database as well. All registered callback will
|
||||
be properly removed when the connection object is deleted.
|
||||
\begin{center}
|
||||
\rule{9cm}{2mm}
|
||||
\end{center}
|
||||
\leftline{{\huge Rule 8}}
|
||||
Remove registered callbacks when deleting an object. For connection objects:
|
||||
register your callbacks!
|
||||
\begin{center}
|
||||
\rule{9cm}{2mm}
|
||||
\end{center}
|
||||
|
||||
|
||||
\section{The Object Wrapper Function}
|
||||
The object wrapper function makes the SICS object visible as a command in
|
||||
the interpreter. It has to analyze parameters given to the command and act
|
||||
accordingly. The object wrapper function has the following form:
|
||||
\begin{verbatim}
|
||||
int ObjectWrapper(SConnection *pCon, SicsInterp *pSics, void *pData,
|
||||
int argc, char *argv[]);
|
||||
\end{verbatim}
|
||||
The parameters are:
|
||||
\begin{itemize}
|
||||
\item A pointer to the connection object and the client invoking the command.
|
||||
\item A pointer to the SICS interpreter in which the command was executed.
|
||||
As the interpreter also doubles as a database for objects it is often needed
|
||||
to locate other objects.
|
||||
\item A pointer to the objects data structure (pData).
|
||||
\item The number of arguments specified to the command.
|
||||
\item The text of the arguments specified. \verb+argv[0]+ is the name of the
|
||||
command invoked. The argc, \verb+argv[]+ are almost the same as the argc,
|
||||
\verb+argv[]+ pair given to a C main program.
|
||||
\end{itemize}
|
||||
In order to give the macro interpreter a hint if things are okay, the object
|
||||
wrapper function has to return 1 for success and 0 if it fails. The rules
|
||||
stated above for normal object functions apply.
|
||||
|
||||
\section{The Object Creation Function}
|
||||
The object creation function has the same form as the object wrapper
|
||||
function. Its purpose is to analyze parameters and to create the requested
|
||||
object from them. In the end the object creation function will probably
|
||||
create a new command in the SICS interpreter. The function to do this is the
|
||||
AddCommand function. The prototype for AddCommand looks like this:
|
||||
\begin{verbatim}
|
||||
int AddCommand(SicsInterp *pSics,
|
||||
char *name,
|
||||
ObjectFunc pObFunc,
|
||||
KillFunc pKill,
|
||||
void *pData);
|
||||
\end{verbatim}
|
||||
The parameters are:
|
||||
\begin{itemize}
|
||||
\item A pointer to the SICS interpreter into which the new command shall be
|
||||
installed.
|
||||
\item The name of the new command.
|
||||
\item The object function implementing the command.
|
||||
\item An optional function which is able to remove the object data structure
|
||||
given as last parameter from memory. This is mandatory for any object with
|
||||
an own data structure.
|
||||
\item A pointer to the object data structure.
|
||||
\end{itemize}
|
||||
|
||||
\section{Writing Data}
|
||||
For simple ASCII files at instruments doing scans, see the SICS manager
|
||||
documentation for the template file description. Other instruments should
|
||||
use the NeXus data format. Especially the NXDICT implementation. For more
|
||||
documentation see the napi and nxdict documents. An example for using NXDICT
|
||||
is given in the file nxsans.c.
|
||||
|
||||
\section{Hardware Objects}
|
||||
\begin{center}
|
||||
\rule{9cm}{2mm}
|
||||
\end{center}
|
||||
\leftline{{\huge Rule 9}}
|
||||
Obey the division between driver code and logical object for hardware
|
||||
objects.
|
||||
\begin{center}
|
||||
\rule{9cm}{2mm}
|
||||
\end{center}
|
||||
The concept of separating a hardware object in two components: a driver
|
||||
which implements primitive operations and a logical object with which SICS
|
||||
interacts internally has proven very valuable. First of all two drivers are
|
||||
needed anyway: a simulation driver for simulating hardware and a
|
||||
driver for the real hardware. Simulating hardware proved invaluable for
|
||||
debugging of higher level code and can be used later on for testing command
|
||||
files.
|
||||
|
||||
Please note that sample environment devices are handled slightly
|
||||
differently. There exists a more general sample environment object which
|
||||
handles many aspects of such a device. If the logical interface provided by
|
||||
this general sample environment objects suffices, a new sample environment
|
||||
device requires just a new driver. If the sample environment needs some
|
||||
specials the study the relationship between the itc4 object and the general sample
|
||||
environment object. Basically such a derived object implements in its
|
||||
functions just the specials and calls the appropriate functions of the
|
||||
general environment device object at the end. This is a simple form of
|
||||
inheritance by delegation. This scheme has been devised in order to reduce
|
||||
the need for code duplication when introducing new environment devices. For
|
||||
more details see the reference section on environment devices.
|
||||
|
||||
\section{Examples}
|
||||
For a deeper understanding of the concepts explained above it may help to
|
||||
look at some source code. A nice example for the whole SICS object setup
|
||||
including a callback interface is the implementation of the SICS variables
|
||||
in files sicsvar.h and sicvar.c. For the implementation of a hardware object
|
||||
including a drivable interface, the code in motor.h, motor.c and the motor
|
||||
drivers: simdriv.c, el734dc.c and el734driv.c may be a suitable example. The
|
||||
motor object creation function also shows how to handle multiple drivers for
|
||||
a logical object.
|
||||
SICS knows a omega-two-theta variable o2t. This variable coordinates two
|
||||
motors in a way that the second motor has exactly the double value of the
|
||||
first. This was meant to implement a omega-two-theta scan. Anyway, o2t is
|
||||
a good example for implementing a drivable interface and how to handle such
|
||||
coordinated movements. An example for the implementation of a countable
|
||||
interface can be found in counter.h, counter.c for a single counter.
|
||||
|
||||
\section{Documentation}
|
||||
If a new object has been defined two documentation files should be provided:
|
||||
\begin{itemize}
|
||||
\item A html file which describes the user interface to the object.
|
||||
\item A latex file which describes the data structures used to implement the
|
||||
object, the interface to the object and as much internal knowledge about the
|
||||
working of the object as you care to provide. Being generous with
|
||||
information helps maintaining the code later on!
|
||||
\end{itemize}
|
||||
Furthermore it is required to update the SICS managers documentation so that
|
||||
the object creation function is known.
|
||||
|
||||
\section{Introducing a new Hardware Driver}
|
||||
A new hardware driver for an existing objects can be introduced into the
|
||||
system with the following two steps:
|
||||
\begin{itemize}
|
||||
\item Write the new driver. Use an existing driver as template.
|
||||
\item Locate the objects factory function. Modify it so that it knows about
|
||||
the new driver and how to initialise it.
|
||||
\item Depending of the implementation of the object, the object deletion
|
||||
function may need to know about the new driver as well in order to delete it
|
||||
properly.
|
||||
\end{itemize}
|
||||
Do not forget to update the SICS manager documentation to include the new
|
||||
driver!
|
||||
|
||||
\section{Coding Considerations}
|
||||
The header file {\em sics.h} includes all the SICS kernel header files in
|
||||
the right order. It is recommended to include sics.h at the top of
|
||||
your implementation file.
|
||||
|
||||
A server program has to run for times on end. Thus a server program is more
|
||||
sensitive than any other program to memory leakage or memory overwrites.
|
||||
Therefore the current SICS implementation utilizes a memory debugging tool
|
||||
called fortify. It is highly recommended to include fortify.h into your
|
||||
implementation file in order to enable memory debugging. More information
|
||||
about the inner working and usage of fortify can be found in the file fortify.doc in
|
||||
the sics source code directory. Fortify has given some false alarms already
|
||||
but it also helped to eliminate a couple of nasty problems at a very early
|
||||
stage. A nasty feature of fortify is that its header file, fortify.h, has
|
||||
to be included in ALL relevant source files. Otherwise nasty pseudo bugs
|
||||
creep up when fortify is enabled. Please note, that fortify is only enabled
|
||||
when all source files have been compiled with the flag -DFORTIFY. Otherwise
|
||||
fortify compiles to nothing. More information about fortify can be found in
|
||||
file fortify.h.
|
||||
|
||||
Names in the SICS source code are often made up along the following pattern:
|
||||
\begin{itemize}
|
||||
\item Use the full name of the thing or sensible and command abbreviations.
|
||||
Write the variable as one word, with word boundaries being marked by capital
|
||||
letters.
|
||||
\item Most variables are prefixed with a letter denoting type. Letters used
|
||||
are:
|
||||
\begin{itemize}
|
||||
\item p for pointer.
|
||||
\item i for integer.
|
||||
\item f for float.
|
||||
\item d for double.
|
||||
\item l for long.
|
||||
\item s for struct.
|
||||
\end{itemize}
|
||||
Combinations of letters are also possible.
|
||||
\end{itemize}
|
||||
|
||||
Some more general data structure implementations are used in SICS: There is
|
||||
a general linked list package from a dutch men documented in lld.h. There is
|
||||
a dynamical array in dynar.* and a parameter array in obpar.*.
|
||||
|
||||
|
||||
|
||||
196
doc/programmer/optimise.tex
Normal file
196
doc/programmer/optimise.tex
Normal file
@@ -0,0 +1,196 @@
|
||||
\subsection{Optimise}
|
||||
In instrument control the need arises to optimise a peak with respect to
|
||||
several variables. This is usually the case during instrument calibration.
|
||||
Four circle diffractometers however use this facility on a day to day basis
|
||||
for finding and verifying the exact position of reflections. In order to
|
||||
support both usages a more general module has been implemented. The way of
|
||||
operation is like this:
|
||||
\begin{verbatim}
|
||||
while errors > precision and cycles < maxcycles
|
||||
for all variables treated
|
||||
do a scan
|
||||
Try find the maximum, two halfwidth points and the peak center.
|
||||
if failure extend the scan.
|
||||
if success shift the variable, remember last shift.
|
||||
If shift < precicison mark this variable as done
|
||||
end for
|
||||
end while
|
||||
\end{verbatim}
|
||||
Possible outcomes of this procedure are: success, the peak was lost or the
|
||||
maximum number of cycles was reached. This routine requires that the
|
||||
instrument is currently placed somewhere on the peak and not miles away.
|
||||
|
||||
In order to use this scheme some general control variables are required:
|
||||
\begin{description}
|
||||
\item[iMaxCycles] The maximum number of cycles to run.
|
||||
\item[lThreshold] A threshold value used when determining if the peak was
|
||||
lost.
|
||||
\item[eMode] The counter mode to count in.
|
||||
\item[fPreset] The preset to use when counting.
|
||||
\item[iChannel] The channel to use as signal when counting. This is to
|
||||
support this technique on a monitor rather then with a counter. Useful for
|
||||
calibration.
|
||||
\end{description}
|
||||
|
||||
For each variable to optimise we have to hold the following items:
|
||||
\begin{description}
|
||||
\item[name] Variable name.
|
||||
\item[fStep] The step size to use for scanning
|
||||
\item[nStep] The number of steps to go in each direction by default. This
|
||||
parameter and the step size should together encompass somewhat more then the
|
||||
width of the peak.
|
||||
\item[fPrecision] The precision required or expected for this variable.
|
||||
\item[fShift] The shift necessary for the last variable.
|
||||
\end{description}
|
||||
Of this the user is required to enter: name, fStep, nStep and fPrecision.
|
||||
|
||||
For some of its work, this module relies on the scan object (scan.*) and the
|
||||
fitcenter object (fitcenter.*).
|
||||
|
||||
Internally the optimiser uses the following data structures:
|
||||
\begin{verbatim}
|
||||
typedef struct {
|
||||
char *pName;
|
||||
float fStep;
|
||||
int iStep;
|
||||
float fPrecision;
|
||||
float fCenter;
|
||||
float fShift;
|
||||
pIDrivable pDriv;
|
||||
void *pData;
|
||||
int iLost;
|
||||
} OVarEntry, *pOVarEntry;
|
||||
\end{verbatim}
|
||||
This is the data structure for each variable to optimise during an
|
||||
optimser run. The fields are:
|
||||
\begin{description}
|
||||
\item[pName] the name of the variable.
|
||||
\item[fStep] The step width to use for scanning the variable.
|
||||
\item[fPrecision] The precision required for this variable. Used to
|
||||
mark this variable OK if the last shift is less then this precision
|
||||
value.
|
||||
\item[fCenter] The calculated center of this variable.
|
||||
\item[fShift] The last shift calculated for this variable.
|
||||
\item[pDriv] A pointer to the drivable interface of this variable.
|
||||
\item[pData] A pointer to this variables data structure.
|
||||
\item[iLost] A flag which marks if the peak has been lost with respect
|
||||
to this variable.
|
||||
\end{description}
|
||||
|
||||
|
||||
The optimiser itself uses the following data structure:
|
||||
\begin{verbatim}
|
||||
typedef struct __OptimiseStruct {
|
||||
pObjectDescriptor pDes;
|
||||
int iMaxCycles;
|
||||
CounterMode eCount;
|
||||
float fPreset;
|
||||
int iChannel;
|
||||
float fThreshold;
|
||||
int iVar;
|
||||
pDynar pVariables;
|
||||
pScanData pScanner;
|
||||
pFit pPeakFitter;
|
||||
} Optimiser;
|
||||
\end{verbatim}
|
||||
The fields are:
|
||||
\begin{description}
|
||||
\item[pDes]The usual object descriptor.
|
||||
\item[iMaxCycles] The maximum number of cycles to perform.
|
||||
\item[eCount] The countmode to use for scanning.
|
||||
\item[fPreset] The preset to use for scanning.
|
||||
\item[iChannel] The channel to use for scanning.
|
||||
\item[fThreshold] The threshold to use for identifying lost peaks.
|
||||
\item[iVar] The number of variables to optimise.
|
||||
\item[pVariables] A dynamic array of variables to optimise.
|
||||
\item[pScanner] The scan object to use for scanning.
|
||||
\item[pFit] The peak center determination object to use.
|
||||
\end{description}
|
||||
|
||||
|
||||
The interface to this object looks like this:
|
||||
\begin{flushleft} \small
|
||||
\begin{minipage}{\linewidth} \label{scrap1}
|
||||
\verb@"optimise.h"@ {\footnotesize ? }$\equiv$
|
||||
\vspace{-1ex}
|
||||
\begin{list}{}{} \item
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@/*-------------------------------------------------------------------------@\\
|
||||
\mbox{}\verb@ O P T I M I S E@\\
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@ Optimise a peak with respect to several variables.@\\
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@ copyright: see copyright.h@\\
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@ Mark Koennecke, March 1998-1999@\\
|
||||
\mbox{}\verb@-----------------------------------------------------------------------------*/@\\
|
||||
\mbox{}\verb@#ifndef SICSOPTIMISE@\\
|
||||
\mbox{}\verb@#define SICSOPTIMISE@\\
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@ typedef struct __OptimiseStruct *pOptimise;@\\
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@/*------------------- live & death -----------------------------------------*/@\\
|
||||
\mbox{}\verb@ pOptimise CreateOptimiser(pCounter pCount);@\\
|
||||
\mbox{}\verb@ void DeleteOptimiser(void *pData);@\\
|
||||
\mbox{}\verb@ int MakeOptimiser(SConnection *pCon, SicsInterp *pSics,@\\
|
||||
\mbox{}\verb@ void *pData, int argc, char *argv[]);@\\
|
||||
\mbox{}\verb@/*------------------- operation -------------------------------------------*/@\\
|
||||
\mbox{}\verb@#define PEAKLOST -1@\\
|
||||
\mbox{}\verb@#define MAXCYCLE -2@\\
|
||||
\mbox{}\verb@#define SCANERROR -3@\\
|
||||
\mbox{}\verb@#define SCANABORT -4@\\
|
||||
\mbox{}\verb@#define SYSERROR -5@\\
|
||||
\mbox{}\verb@#define DRIVEERROR -6@\\
|
||||
\mbox{}\verb@#define VARREDO -7@\\
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@ void OptimiserClear(pOptimise self);@\\
|
||||
\mbox{}\verb@ int OptimiserAdd(pOptimise self,@\\
|
||||
\mbox{}\verb@ char *pVarName, @\\
|
||||
\mbox{}\verb@ float fStep, @\\
|
||||
\mbox{}\verb@ int nStep, @\\
|
||||
\mbox{}\verb@ float fPrecision);@\\
|
||||
\mbox{}\verb@ int OptimiserSetPar(pOptimise self, char *name, float fVal);@\\
|
||||
\mbox{}\verb@ int OptimiserGetPar(pOptimise self, char *name, float *fVal);@\\
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@ int OptimiserRun(pOptimise self, SConnection *pCon); @\\
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@ int OptimiserAction(SConnection *pCon, SicsInterp *pSics, void *pData,@\\
|
||||
\mbox{}\verb@ int argc, char *argv[]);@\\
|
||||
\mbox{}\verb@#endif@\\
|
||||
\mbox{}\verb@@$\diamond$
|
||||
\end{list}
|
||||
\vspace{-2ex}
|
||||
\end{minipage}\\[4ex]
|
||||
\end{flushleft}
|
||||
All functions except the installation functions take a pointer to the
|
||||
optimiser structure as first parameter. The function reference:
|
||||
\begin{description}
|
||||
\item[CreateOptimiser] creates an optimiser object. Takes a pointer to
|
||||
a counter object as a parameter. Returns a pointer to a nice and good
|
||||
optimiser object on return. Or NULL, if there was some sort of
|
||||
problem.
|
||||
\item[DeleteOptimiser] is the deletion function used in the
|
||||
interpreter for properly removing the optimiser object from the
|
||||
system.
|
||||
\item[MakeOptimiser] is the installation function which configures an
|
||||
optimiser into SICS.
|
||||
\item[OptimiserClear] removes all configured optimisation variables
|
||||
and all remnants of a previous optimiser run.
|
||||
\item[OptimiserAdd] adds a variable to be optimised. Parameter to this
|
||||
call are: pVarName, the name of the variable to optimise, fStep, the
|
||||
step width to use for scanning, nStep, the initial number of steps to
|
||||
use for scanning, fPrecision, the precision to achive for this
|
||||
variable.
|
||||
\item[OptimiserSetPar] sets the configuration parameters for the
|
||||
optimiser. The parameter name is the same name as stated in the
|
||||
command reference.
|
||||
\item[OptimiserGetPar] retrieves the value of a configuration
|
||||
parameters for the
|
||||
optimiser. The parameter name is the same name as stated in the
|
||||
command reference.
|
||||
\item[OptimiserRun] starts the optimser run with the current
|
||||
parameters. Output is sent to the connection pCon.
|
||||
\item[OptimiserAction] is the interpreter interface function for the
|
||||
optimiser.
|
||||
\end{description}
|
||||
437
doc/programmer/overview.tex
Normal file
437
doc/programmer/overview.tex
Normal file
@@ -0,0 +1,437 @@
|
||||
\chapter{SICS Overview}
|
||||
\section{Introduction}
|
||||
At the new spallation source SINQ at PSI a whole set of new neutron
|
||||
scattering instruments are being installed. All these new instruments need a
|
||||
computer instrument control control system. After a review of similar systems
|
||||
out in the market it was found that none fully met the requirements defined
|
||||
for SINQ or could easily be extended to do so. Therefore it was decided to
|
||||
design a new system. This new system SICS, the SINQ Instrument Control
|
||||
System, had to meet the following specifications:
|
||||
\begin{itemize}
|
||||
\item Control the instrument reliably.
|
||||
\item Good remote access to the instrument via the internet.
|
||||
\item Portability across operating system platforms.
|
||||
\item Enhanced portability across instrument hardware. This means that it
|
||||
should be easy to add other types of motors, counters or other hardware to
|
||||
the system.
|
||||
\item Support authorization on the command and variable level. This means
|
||||
that certain instrument settings can be protected against random changes by
|
||||
less knowledgable users.
|
||||
\item Good maintainability and extendability.
|
||||
\item Be capable to acomodate graphical user interfaces (GUI).
|
||||
\item One code base for all instruments.
|
||||
\item Powerful macro language.
|
||||
\end{itemize}
|
||||
A suitable new system was implemented using an object oriented design which
|
||||
matches the above criteria.
|
||||
|
||||
\section{The SINQ Hardware Setup}
|
||||
SICS had to take in account the SINQ hardware setup which had been decided
|
||||
upon earlier on. Most hardware such as motors and counters is controlled via
|
||||
RS--232 interfaces. These devices connect to a Macintosh PC which has a
|
||||
terminal server program running on it. This terminal server program collects
|
||||
request to the hardware from a TCP/IP port and forwards them to the serial
|
||||
device. The instrument control program runs on a workstation running
|
||||
DigitalUnix. Communication with the hardware happens via TCP/IP through the
|
||||
terminal server. Some hardware devices, such as the histogram memory, can handle
|
||||
TCP/IP themselves. With such devices the instrument control program
|
||||
communicates directly through TCP/IP, without a terminal server. All
|
||||
hardware devices take care of their real time needs themselves. Thus the
|
||||
only task of the instrument control program is to orchestrate the hardware
|
||||
devices. SICS is designed with this setup up in mind, but is not restricted
|
||||
to this setup. A schematic view of this setup is given in picture
|
||||
\ref{hard}.
|
||||
\begin{figure}
|
||||
%% \epsfxsize=0.65\textwidth
|
||||
\epsfxsize=160mm
|
||||
\epsffile{hart.eps}
|
||||
\caption{Instrument control hardware setup at SINQ}\label{hard}
|
||||
\end{figure}
|
||||
|
||||
|
||||
\section{SICS Overall Design}
|
||||
In order to achieve the design goals stated above it was decided to divide
|
||||
the system into a client server system. This means that there are at least
|
||||
two programs necessary to run an instrument: a client program and a server
|
||||
program. The server program, the SICS server, does all the work and
|
||||
implements the actual instrument control. The SICS server usually runs on
|
||||
the DAQ computer. The client program may run on any computer on the world
|
||||
and implements the user interface to the instrument. Any numbers of clients
|
||||
can communicate with one SICS server. The SICS server and the clients
|
||||
communicate via a simple ASCII command protocol through TCP/IP sockets.
|
||||
With this design good remote control through the network is easily achieved.
|
||||
As clients can be implemented in any language or system capable of handling
|
||||
TCP/IP the user interface and the functional aspect are well separated. This
|
||||
allows for easy exchange of user interfaces by writing new clients.
|
||||
|
||||
|
||||
\section{SICS Clients}
|
||||
SICS Clients implement the SICS user interface. Current client
|
||||
programs are mostly implemented in Java for platform independence.
|
||||
This is a real concern at SINQ where VMS,
|
||||
Intel-PC, Macintosh and Unix users have to be satisfied.
|
||||
As many instrument scientists still prefer
|
||||
the command line for interacting with instruments, the most used client is a
|
||||
visual command line client. Status displays are another sort of specialized
|
||||
client programs. Graphical user interfaces are under consideration for some
|
||||
instruments. As an example for a client a screen shot of the status display
|
||||
client for a powder diffractometer is given in picture \ref{dmc}
|
||||
\ref{hard}.
|
||||
\begin{figure}
|
||||
%% \epsfxsize=0.65\textwidth
|
||||
\epsfxsize=160mm
|
||||
%% \epsffile{dmc.eps}
|
||||
\caption{Example for a SICS client: Powder Diffractometer Status Display}\label{dmc}
|
||||
\end{figure}
|
||||
|
||||
|
||||
|
||||
\section{The SICS Server}
|
||||
The SICS server is the core component of the SICS system. The SICS server is
|
||||
responsible for doing all the work in instrument control. Additionally the
|
||||
server has to answer the requests of possibly multiple clients.
|
||||
The SICS server can be subdivided into three subsystems: The kernel, a database
|
||||
of SICS objects and an interpreter. The SICS server kernel takes care of
|
||||
client multitasking and the preservation of the proper I/O and error context
|
||||
for each client command executing.
|
||||
SICS objects are software modules which represent all aspects
|
||||
of an instrument: hardware devices, commands, measurement strategies
|
||||
and data storage. This database of objects is initialized at server startup
|
||||
time from an initialization script. The third SICS server component is an
|
||||
interpreter which allows to issue commands to the objects in the objects database.
|
||||
The schematic drawing of the SICS server's structure is given in picture
|
||||
\ref{newsics}.
|
||||
\begin{figure}
|
||||
%% \epsfxsize=0.65\textwidth
|
||||
\epsfxsize=160mm
|
||||
\epsffile{newsics.eps}
|
||||
\caption{Schematic Representation of the SICS server's structure}\label{sicsnew}
|
||||
\end{figure}
|
||||
|
||||
|
||||
\subsection{The SICS Server Kernel}
|
||||
In more detail the SICS server kernel has the following tasks:
|
||||
\begin{itemize}
|
||||
\item Accept and verify client connection requests.
|
||||
\item Read and execute client commands.
|
||||
\item Maintain the I/O and error context for each client connection.
|
||||
\item Serialize data access.
|
||||
\item Serialize hardware access.
|
||||
\item Monitor HW--operations.
|
||||
\item Monitor environment devices.
|
||||
\end{itemize}
|
||||
Any server serving multiple clients has the problem how to organize multiple
|
||||
clients accessing the same server and how to stop one client reading data,
|
||||
which another client is just writing. The approach used for the SICS server
|
||||
is a combination of polling and cooperative multitasking. This scheme is
|
||||
simple and can be implemented in an operating system independent manner. One
|
||||
way to look at the SICS server is as a series of tasks in a circular queue
|
||||
executing one after another. The servers main loop does nothing but
|
||||
executing the tasks in this circular buffer in an endless loop.
|
||||
There are several system tasks and one such
|
||||
task for each living client connection. Thus only one task executes at any
|
||||
given time and data access is efficiently serialized. One of the main system
|
||||
tasks (and the one which will be always there) is the network reader. The
|
||||
network reader has a list of open network connections and checks each of
|
||||
them for pending requests. What happens when a data is pending on an open
|
||||
network port depends on the type of port: If it is the servers main
|
||||
connection port, the network reader will try to accept and verify a new
|
||||
client connection and create the associated data structures. If the port
|
||||
belongs to an open client connection the network reader will read the
|
||||
command pending and put it onto a command stack existing for each client
|
||||
connection. When it is time for a client task to execute, it will fetch a
|
||||
command from its very own command stack and execute it. When the net reader
|
||||
finds an user interrupt pending, the interrupt is executed.
|
||||
This is how the SICS server deals with client requests.
|
||||
|
||||
The scheme described above relies on the fact that most SICS command need
|
||||
only very little time to execute. A command needing time extensive
|
||||
calculations may effectively block the server. Implementations of such
|
||||
commands have to take care that control passes back to the task switching
|
||||
loop at regular intervalls in order to prevent the server from blocking.
|
||||
|
||||
Another problem in a server handling multiple client requests is how to
|
||||
maintain the proper execution context for each client. This includes the
|
||||
clients I/O-context (socket), the authorisation of the client and possible
|
||||
error conditions pending for a
|
||||
client connection. SICS does this via a connection object, a special
|
||||
data structure holding all the above information plus a set of functions
|
||||
operating on this data structure. This connection object is passed along
|
||||
with many calls throughout the whole system.
|
||||
|
||||
Multiple clients issuing commands to the SICS server may mean that multiple
|
||||
clients might try to move motors or access other hardware in conflicting
|
||||
ways. As there is only one set of instrument hardware this needs to be
|
||||
prevented. This is achieved by a convention. No SICS object drives hardware
|
||||
directly but registers it's request with a special object, the device
|
||||
executor. This device executor starts the requested operation and reserves
|
||||
the hardware for the length of the operation. During the execution of such
|
||||
an hardware request all other clients requests to drive the hardware will
|
||||
return an error. The device executor is also responsible for monitoring the
|
||||
progress of an hardware operation. It does so by adding a special task into
|
||||
the system which checks the status of the operation each time this tasks
|
||||
executes. When the hardware operation is finished (one way or another) this
|
||||
device executor task will end. A special system facility allows a client
|
||||
task to wait for the device executor task to end while the rest of the task
|
||||
queue is still executing. In this way time intensive hardware operations can
|
||||
be performed by drive, count or scan commands without blocking the whole
|
||||
system for other clients. \label{devexec}
|
||||
|
||||
The SICS server can be configured to support another security feature, the
|
||||
token system. In this scheme a client can grab control of the instrument.
|
||||
With the control token grabbed, only the client which has the token may
|
||||
control the instrument. Any other client may look at things in the SICS server
|
||||
but does not have permission to change anything. Passing the control token
|
||||
requires that the client which has the token releases the token so that
|
||||
another client may grab it. There exists a password protected back door for
|
||||
SICS managers which allows to force the release of a control token.
|
||||
|
||||
Most experiments do not happen at ambient room conditions but
|
||||
require some special environment for the sample. Mostly this is temperature
|
||||
but it can also be magnetic of electric fields etc. Most of such devices
|
||||
can regulate themselves but the data acquisition program needs to monitor
|
||||
such devices. Within SICS this is done via a special system object, the
|
||||
environment monitor. A environment device, for example a temperature
|
||||
controller, registers it's presence with this object. Then an special system
|
||||
task will control this device when it is executing, check for possible out
|
||||
of range errors and initiates the proper error handling if such a problem is
|
||||
encountered.
|
||||
|
||||
\subsection{The SICS Interpreter}
|
||||
When a task belonging to a client connection executes a command it will pass
|
||||
the command along with the connection object to the SICS interpreter. The
|
||||
SICS interpreter will then analyze the command and forward it to the
|
||||
appropriate SICS object in the object database for further action. The SICS
|
||||
interpreter is very much modeled after the Tcl interpreter as devised by
|
||||
John Ousterhout$^{1}$. For each SICS object visible from the interpreter there is
|
||||
a wrapper function. Using the first word of the command as a key, the
|
||||
interpreter will locate the objects wrapper function. If such a function is
|
||||
found it is passed the command parameters, the interpreter object and the
|
||||
connection object for further processing. An interface exists to add and
|
||||
remove commands to this interpreter very easily. Thus the actual command
|
||||
list can be configured easily to match the instrument in question, sometimes
|
||||
even at run time. Given the closeness of the design of the SICS interpreter
|
||||
to the Tcl interpreter, the reader may not be surprised to learn that the
|
||||
SICS server incorporates Tcl as its internal macro language. The internal
|
||||
macro language may use Tcl commands as well as SICS commands.
|
||||
|
||||
\subsection{SICS Objects}
|
||||
As already said, SICS objects implement the true functionality of SICS
|
||||
instrument control. All hardware, all commands and procedures, all data
|
||||
handling strategies are implemented as SICS objects. Hardware objects, for
|
||||
instance motors deserve some special attention. Such objects are divided
|
||||
into two objects in the SICS system: A logical hardware object and a driver
|
||||
object. The logical object is responsible for implementing all the nuts and
|
||||
bolts of the hardware device, whereas the driver defines a set of primitive
|
||||
operations on the device. The benefit of this scheme is twofold:
|
||||
switching to new hardware, for instance a new type of motor, just requires
|
||||
to incorporate a new driver into the system. Internally, independent from
|
||||
the actual hardware, all hardware object of the same type (for example
|
||||
motors) look the same and can be treated the same by higher level objects.
|
||||
No need to rewrite a scan command because a motor changed.
|
||||
|
||||
In order to live happily within the SICS system SICS object have to adhere
|
||||
to a system of protocols. There are protocols for:
|
||||
\begin{itemize}
|
||||
\item Input/Output to the client.
|
||||
\item Error handling.
|
||||
\item Interaction with the interpreter.
|
||||
\item For identification of the object to the system at run time.
|
||||
\item For interacting with hardware (see device executor above).
|
||||
\item For checking the authorisation of the client who wants to execute the
|
||||
command.
|
||||
\end{itemize}
|
||||
|
||||
SICS uses NeXus$^{2}$, the upcoming standard for data exchange for neutron
|
||||
and x\_ray scattering as its raw data format.
|
||||
|
||||
SICS objects have the ability to notify clients and other objects of
|
||||
internal state changes. For example when a motor is driven, the motor object
|
||||
can be configured to tell SICS clients or other SICS objects about his new
|
||||
position.
|
||||
|
||||
\section{SICS Working Examples}
|
||||
In order to get a better feeling for the internal working of SICS the course
|
||||
of a few different requests through the SICS system is traced in this
|
||||
section. The examples traced will be:
|
||||
\begin{itemize}
|
||||
\item A request for a new client connection.
|
||||
\item A simple command.
|
||||
\item A command to drive a motor in blocking mode.
|
||||
\item A command to drive a motor which got interrupted by the user.
|
||||
\item A command to drive a motor in non blocking mode.
|
||||
\end{itemize}
|
||||
For the whole discussion it is assumed that the main loop is running,
|
||||
executing cyclically each single task registered in the server. Task switching is
|
||||
done by a special system component, the task switcher.
|
||||
|
||||
\subsection{The Request for a new Client Connection}
|
||||
\begin{itemize}
|
||||
\item The network reader recognizes pending data on its main server port.
|
||||
\item The network reader accepts the connection and tries to read a
|
||||
username/password pair.
|
||||
\item If such a username/password pair comes within a suitable time
|
||||
intervals it is checked for validity. On failure the connection is closed
|
||||
again.
|
||||
\item If a valid connection has been found: A new connection object is
|
||||
created, a new task for this client connection is introduced into the
|
||||
system and the network reader registers a new client port to check for
|
||||
pending commands.
|
||||
\item Control is passed back to the task switcher.
|
||||
\end{itemize}
|
||||
|
||||
\subsection{A Simple Command}
|
||||
\begin{itemize}
|
||||
\item The network reader finds data pending at one of the client ports.
|
||||
\item The network reader reads the command, splits it into single lines and
|
||||
put those on the top of the client connections command stack. The network
|
||||
reader passes control to the task switcher.
|
||||
\item In due time the client connection task executes, inspects its command
|
||||
stack, pops the command pending and forwards it together with a pointer to
|
||||
itself to the SICS interpreter.
|
||||
\item The SICS interpreter inspects the first word of the command. Using
|
||||
this key the interpreter finds the objects wrapper function and passes
|
||||
control to that function.
|
||||
\item The object wrapper function will check further arguments, checks the
|
||||
clients authorisation if appropriate for the action requested. Depending on
|
||||
the checks, the wrapper function will create an error message or do its
|
||||
work.
|
||||
\item This done, control passes back through the interpreter and the connection
|
||||
task to the task switcher.
|
||||
\item The next task executes.
|
||||
\end{itemize}
|
||||
|
||||
\subsection{A Drive Command in Blocking Mode}
|
||||
\begin{itemize}
|
||||
\item The network reader finds data pending at one of the client ports.
|
||||
\item The network reader reads the command, splits it into single lines and
|
||||
put those on the top of the client connections command stack. The network
|
||||
reader passes control to the task switcher.
|
||||
\item In due time the client connection task executes, inspects its command
|
||||
stack, pops the command pending and forwards it together with a pointer to
|
||||
itself to the SICS interpreter.
|
||||
\item The SICS interpreter inspects the first word of the command. Using
|
||||
this key the interpreter finds the drive command wrapper function and passes
|
||||
control to that function.
|
||||
\item The drive command wrapper function will check further arguments,
|
||||
checks the
|
||||
clients authorisation if appropriate for the action requested. Depending on
|
||||
the checks, the wrapper function will create an error message or do its
|
||||
work.
|
||||
\item Assuming everything is OK, the motor is located in the system.
|
||||
\item The drive command wrapper function asks the device executor to run the
|
||||
motor.
|
||||
\item The device executor verifies that nobody else is driving, then starts
|
||||
the motor and grabs hardware control. The device executor also starts a task
|
||||
monitoring the activity of the motor.
|
||||
\item The drive command wrapper function now enters a wait state. This means
|
||||
the task switcher will execute other tasks, except the connection task
|
||||
requesting the wait state. The client connection and task executing the drive command
|
||||
will not be able to process further commands.
|
||||
\item The device executor task will keep on monitoring the progress of the motor
|
||||
driving whenever the task switcher allows it to execute.
|
||||
\item In due time the device executor task will find that the motor finished
|
||||
driving. The task will then die. The clients grab of the hardware driving
|
||||
permission will be released.
|
||||
\item At this stage the drive command wrapper function will awake and
|
||||
continue execution. This means inspecting errors and reporting to the client
|
||||
how things worked out.
|
||||
\item This done, control passes back through the interpreter and the connection
|
||||
task to the task switcher. The client connection is free to execute
|
||||
other commands.
|
||||
\item The next task executes.
|
||||
\end{itemize}
|
||||
|
||||
\subsection{A Drive Command Interrupted}
|
||||
\begin{itemize}
|
||||
\item The network reader finds data pending at one of the client ports.
|
||||
\item The network reader reads the command, splits it into single lines and
|
||||
put those on the top of the client connections command stack. The network
|
||||
reader passes control to the task switcher.
|
||||
\item In due time the client connection task executes, inspects its command
|
||||
stack, pops the command pending and forwards it together with a pointer to
|
||||
itself to the SICS interpreter.
|
||||
\item The SICS interpreter inspects the first word of the command. Using
|
||||
this key the interpreter finds the drive command wrapper function and passes
|
||||
control to that function.
|
||||
\item The drive command wrapper function will check further arguments,
|
||||
checks the
|
||||
clients authorisation if appropriate for the action requested. Depending on
|
||||
the checks, the wrapper function will create an error message or do its
|
||||
work.
|
||||
\item Assuming everything is OK, the motor is located in the system.
|
||||
\item The drive command wrapper function asks the device executor to run the
|
||||
motor.
|
||||
\item The device executor verifies that nobody else is driving, then starts
|
||||
the motor and grabs hardware control. The device executor also starts a task
|
||||
monitoring the activity of the motor.
|
||||
\item The drive command wrapper function now enters a wait state. This means
|
||||
the task switcher will execute other tasks, except the connection task
|
||||
requesting the wait state.
|
||||
\item The device executor task will keep on monitoring the progress of the
|
||||
driving of the motor when it is its turn to execute.
|
||||
\item The network reader finds a user interrupt pending. The interrupt will
|
||||
be forwarded to all tasks in the system.
|
||||
\item In due time the device executor task will try to check on the progress
|
||||
of the motor. It will recognize the interrupt. If appropriate the motor will
|
||||
get a halt command. The task will then die.
|
||||
The clients grab of the hardware driving permission will be released.
|
||||
\item At this stage the drive command wrapper function will awake and
|
||||
continue execution. This means it finds the interrupt, tells the user what he
|
||||
already knows: an interrupt was issued.
|
||||
\item This done, control passes back through drive command wrapper,
|
||||
the interpreter and the connection
|
||||
task to the task switcher.
|
||||
\item The next task executes.
|
||||
\end{itemize}
|
||||
|
||||
\subsection{A Run Command in Non Blocking Mode}
|
||||
\begin{itemize}
|
||||
\item The network reader finds data pending at one of the client ports.
|
||||
\item The network reader reads the command, splits it into single lines and
|
||||
put those on the top of the client connections command stack. The network
|
||||
reader passes control to the task switcher.
|
||||
\item In due time the client connection task executes, inspects its command
|
||||
stack, pops the command pending and forwards it together with a pointer to
|
||||
itself to the SICS interpreter.
|
||||
\item The SICS interpreter inspects the first word of the command. Using
|
||||
this key the interpreter finds the drive command wrapper function and passes
|
||||
control to that function.
|
||||
\item The run command wrapper function will check further arguments,
|
||||
checks the
|
||||
clients authorisation if appropriate for the action requested. Depending on
|
||||
the checks, the wrapper function will create an error message or do its
|
||||
work.
|
||||
\item Assuming everything is OK, the motor is located in the system.
|
||||
\item The drive command wrapper function asks the device executor to run the
|
||||
motor.
|
||||
\item The device executor verifies that nobody else is driving, then starts
|
||||
the motor and grabs hardware control. The device executor also starts a task
|
||||
monitoring the activity of the motor.
|
||||
\item The run command wrapper function passes control through the interpreter and
|
||||
the clients task function back to the task switcher. The client connection can handle
|
||||
new commands.
|
||||
\item The device executor task will keep on monitoring the progress of the motor
|
||||
driving whenever the task switcher allows it to execute.
|
||||
\item In due time the device executor task will find that the motor finished
|
||||
driving. The task will then die silently. The clients grab of the hardware driving
|
||||
permission will be released. If errors occurred, however a they will be reported.
|
||||
\item At this stage the drive command wrapper function will awake and
|
||||
continue execution. This means inspecting errors and reporting to the client
|
||||
how things worked out.
|
||||
\item This done, control passes back through the interpreter and the connection
|
||||
task to the task switcher. The client connection is free to execute
|
||||
other commands.
|
||||
\item The next task executes.
|
||||
\end{itemize}
|
||||
|
||||
All this seems to be pretty complex and time consuming. But it is the complexity needed to
|
||||
do so many things, especially the non blocking mode of operation requested
|
||||
by users. Tests have shown that the task switcher manages +900 cycles per second
|
||||
through
|
||||
the task list on a DigitalUnix machine and 50 cycles per second on a pentium 133mhz
|
||||
machine running linux. Both data were obtained with software simulation of
|
||||
hardware devices. With real SINQ hardware these numbers drop 4 cycles per
|
||||
second. This shows clearly that the communication with the hardware is the
|
||||
systems bottleneck and not the task switching scheme.
|
||||
|
||||
20
doc/programmer/passwd.tex
Normal file
20
doc/programmer/passwd.tex
Normal file
@@ -0,0 +1,20 @@
|
||||
\subsection{The Password Database}
|
||||
This is just a simple password database. It keeps for each user an
|
||||
record containing username, password and an integer code. The code
|
||||
is meant to encode the users rights within the system. On
|
||||
initialisation the information is read from a file. Currently there
|
||||
is no encryption in this. Rely on the filesytem protection mechanisms
|
||||
for protecting passwords. Though SICS will have only a limited number
|
||||
of different user levels, the password class is designed to cope with
|
||||
more and stores its data in a linked list. Currently user names and
|
||||
passwords are entered into the database through the SicsUser
|
||||
initialization command.
|
||||
|
||||
The interface:\begin{itemize}
|
||||
\item {\bf int InitPasswd(char *filename) } reads user data from the file specified. Returns True on success, false else.
|
||||
\item {\bf void AddUser(char *name, char *passwd, int iCode) }, adds a new user to the database.
|
||||
\item {\bf int IsValidUser(char *name, char *passwd) }, checks a users authorisation information. Returns a negative value if the user is invalid, the users rights code if he is valid.
|
||||
\item {\bf void KillPasswd(void) }, deletes the password data structures, when it is no longer needed. Omission of this call will result in wasted memory.
|
||||
\end{itemize}
|
||||
|
||||
|
||||
119
doc/programmer/perfmon.tex
Normal file
119
doc/programmer/perfmon.tex
Normal file
@@ -0,0 +1,119 @@
|
||||
\subsection{Performance Monitor}
|
||||
This object implements a performance monitor for SICS. Please note that SICS
|
||||
performance is determined not only by processor speed but by a whole range
|
||||
of factors:
|
||||
\begin{itemize}
|
||||
\item Processor speed and memory.
|
||||
\item Speed of network connctions to hardware devices.
|
||||
\item Number of clients connected.
|
||||
\end{itemize}
|
||||
|
||||
The PerfMonTask is called from the SICS task modules main loop. It will then
|
||||
increment a cycle counter and check if a predefined intergration time has
|
||||
passed. If so a new
|
||||
value for cycle per seconds will be calculated. This is also the main
|
||||
output of PerfMon. PerfMon implements a callback interface in order to allow
|
||||
automatical notification about system performance.
|
||||
|
||||
PerfMon has a little datastructure:
|
||||
\begin{flushleft} \small
|
||||
\begin{minipage}{\linewidth} \label{scrap1}
|
||||
$\langle$pdata {\footnotesize ?}$\rangle\equiv$
|
||||
\vspace{-1ex}
|
||||
\begin{list}{}{} \item
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@ typedef struct __PerfMon {@\\
|
||||
\mbox{}\verb@ pObjectDescriptor pDes;@\\
|
||||
\mbox{}\verb@ pICallBack pCall;@\\
|
||||
\mbox{}\verb@ int iLog; /* flag for@\\
|
||||
\mbox{}\verb@ serverlog writing */ @\\
|
||||
\mbox{}\verb@ float fCPS; /* cycles per seconds */@\\
|
||||
\mbox{}\verb@ int iInteg; /* integration time */@\\
|
||||
\mbox{}\verb@ int iCount;@\\
|
||||
\mbox{}\verb@ time_t tLast; /* last time calculated */@\\
|
||||
\mbox{}\verb@ time_t tTarget; /* next target time */@\\
|
||||
\mbox{}\verb@ int iEnd;@\\
|
||||
\mbox{}\verb@ }PerfMon;@\\
|
||||
\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 interface consists of the following functions:
|
||||
\begin{flushleft} \small
|
||||
\begin{minipage}{\linewidth} \label{scrap2}
|
||||
$\langle$pInter {\footnotesize ?}$\rangle\equiv$
|
||||
\vspace{-1ex}
|
||||
\begin{list}{}{} \item
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@ typedef struct __PerfMon *pPerfMon;@\\
|
||||
\mbox{}\verb@/*---------------------- live and death ----------------------------------*/@\\
|
||||
\mbox{}\verb@ pPerfMon CreatePerfMon(int iInteg);@\\
|
||||
\mbox{}\verb@ void DeletePerfMon(void *pData);@\\
|
||||
\mbox{}\verb@/*---------------------- increment ---------------------------------------*/@\\
|
||||
\mbox{}\verb@ int IncrementPerfMon(pPerfMon self);@\\
|
||||
\mbox{}\verb@/*------------------------------------------------------------------------*/@\\
|
||||
\mbox{}\verb@ float GetPerformance(pPerfMon self);@\\
|
||||
\mbox{}\verb@/*------------------------------------------------------------------------*/@\\
|
||||
\mbox{}\verb@ int PerfMonWrapper(SConnection *pCon, SicsInterp *pSics, void *pData,@\\
|
||||
\mbox{}\verb@ int argc, char *argv[]);@\\
|
||||
\mbox{}\verb@/*-----------------------------------------------------------------------*/@\\
|
||||
\mbox{}\verb@ int PerfMonTask(void *pPerf);@\\
|
||||
\mbox{}\verb@ void PerfMonSignal(void *pPerf, int iSignal, void *pSigData); @\\
|
||||
\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}
|
||||
There is really not much to this.
|
||||
|
||||
\begin{flushleft} \small
|
||||
\begin{minipage}{\linewidth} \label{scrap3}
|
||||
\verb@"perfmon.h"@ {\footnotesize ? }$\equiv$
|
||||
\vspace{-1ex}
|
||||
\begin{list}{}{} \item
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@/*-------------------------------------------------------------------------@\\
|
||||
\mbox{}\verb@ P E R F M O N@\\
|
||||
\mbox{}\verb@ A performance monitor for SICS. Maintains and calculates a value for@\\
|
||||
\mbox{}\verb@ cycles per seconds. @\\
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@ Mark Koennecke, Juli 1997@\\
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@ copyright: see implementation file@\\
|
||||
\mbox{}\verb@---------------------------------------------------------------------------*/@\\
|
||||
\mbox{}\verb@#ifndef SICSPERFMON@\\
|
||||
\mbox{}\verb@#define SICSPERFMON@\\
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@@$\langle$pInter {\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{scrap4}
|
||||
\verb@"perfmon.i"@ {\footnotesize ? }$\equiv$
|
||||
\vspace{-1ex}
|
||||
\begin{list}{}{} \item
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@/*--------------------------------------------------------------------------@\\
|
||||
\mbox{}\verb@ The P E R F M O N datastructure.@\\
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@ Mark Koennecke, Juli 1997@\\
|
||||
\mbox{}\verb@---------------------------------------------------------------------------*/@\\
|
||||
\mbox{}\verb@@$\langle$pdata {\footnotesize ?}$\rangle$\verb@@\\
|
||||
\mbox{}\verb@@$\diamond$
|
||||
\end{list}
|
||||
\vspace{-2ex}
|
||||
\end{minipage}\\[4ex]
|
||||
\end{flushleft}
|
||||
67
doc/programmer/pimotor.tex
Normal file
67
doc/programmer/pimotor.tex
Normal file
@@ -0,0 +1,67 @@
|
||||
\subsubsection{Physik Instrumente DC-Motor Controller}
|
||||
This is a mainly a driver for a C-804 DC-motor Controller as produced by the
|
||||
Company Physik Instrumente. This controller drives up to four high precision
|
||||
motors. These motors do not have reference points and have variable speeds.
|
||||
Therefore some additional code is needed to handle motor specific commands.
|
||||
This problem is solved by handling these specific additional commands in a
|
||||
new wrapper routine which finally calls the main motor wrapper routine for
|
||||
all the other commands. Of course, a special factory method is needed for
|
||||
this device as well.
|
||||
|
||||
The public interface for this motor includes the following functions:
|
||||
|
||||
\begin{flushleft} \small
|
||||
\begin{minipage}{\linewidth} \label{scrap1}
|
||||
$\langle$pimoti {\footnotesize ?}$\rangle\equiv$
|
||||
\vspace{-1ex}
|
||||
\begin{list}{}{} \item
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@ int PIMotorWrapper(SConnection *pCon, SicsInterp *pSics, void *pData,@\\
|
||||
\mbox{}\verb@ int argc, char *argv[]);@\\
|
||||
\mbox{}\verb@ int PIMotorFactory(SConnection *pCon, SicsInterp *pSics, void *pData,@\\
|
||||
\mbox{}\verb@ int argc, char *argv[]);@\\
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@ int PISetSpeed(pMotor self, SConnection *pCon, float fNew);@\\
|
||||
\mbox{}\verb@ int PIGetSpeed(pMotor self, SConnection *pCon, float *fVal);@\\
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@ int PIHome(pMotor self, SConnection *pCon);@\\
|
||||
\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}
|
||||
\begin{flushleft} \small
|
||||
\begin{minipage}{\linewidth} \label{scrap2}
|
||||
\verb@"pimotor.h"@ {\footnotesize ? }$\equiv$
|
||||
\vspace{-1ex}
|
||||
\begin{list}{}{} \item
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@/*--------------------------------------------------------------------------@\\
|
||||
\mbox{}\verb@ P I M O T O R@\\
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@ Driver and add on code for the Physik Instrument Motor Controller C-804.@\\
|
||||
\mbox{}\verb@ @\\
|
||||
\mbox{}\verb@ Mark Koennecke, September 1998@\\
|
||||
\mbox{}\verb@----------------------------------------------------------------------------*/@\\
|
||||
\mbox{}\verb@#ifndef PIMOTOR@\\
|
||||
\mbox{}\verb@#define PIMOTOR@\\
|
||||
\mbox{}\verb@@$\langle$pimoti {\footnotesize ?}$\rangle$\verb@@\\
|
||||
\mbox{}\verb@#endif@\\
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@@$\diamond$
|
||||
\end{list}
|
||||
\vspace{-2ex}
|
||||
\end{minipage}\\[4ex]
|
||||
\end{flushleft}
|
||||
\subsubsection{Physik Instrument Piezo Controller E-255}
|
||||
This is piezo translator. A voltage is set and it elongates. It is
|
||||
handled as a motor because it is going to be scanned. A driver has
|
||||
been implemented in the file pipiezo.c. For
|
||||
the command protocoll, see the documentation coming with the gadget.
|
||||
|
||||
|
||||
47
doc/programmer/progold.data
Normal file
47
doc/programmer/progold.data
Normal file
@@ -0,0 +1,47 @@
|
||||
\chapter{SICS Programmers Reference}
|
||||
This chapter is a boring listing of the interfaces and functions provided by
|
||||
the SICS modules.
|
||||
|
||||
\section{Kernel Objects and Modules}
|
||||
This section describes the objects and modules defining the SICS kernel.
|
||||
\include{nserver}
|
||||
\include{nread}
|
||||
\include{nconman}
|
||||
\include{emonitor}
|
||||
\include{event}
|
||||
\include{interface}
|
||||
\include{devexec}
|
||||
\include{perfmon}
|
||||
\include{ini}
|
||||
\include{inter}
|
||||
\include{macro}
|
||||
\include{network}
|
||||
\include{passwd}
|
||||
|
||||
|
||||
\section{SICS Objects}
|
||||
This section describes the SICS objects implementing commands and hardware
|
||||
objects.
|
||||
\include{velo}
|
||||
\include{velodorn}
|
||||
\include{scan}
|
||||
\include{evcontroller}
|
||||
\include{center}
|
||||
\include{danu}
|
||||
\include{evcontroller}
|
||||
\include{itc4}
|
||||
\include{histogram}
|
||||
\include{histsim}
|
||||
\include{sinqhmdriv}
|
||||
\include{nxdata}
|
||||
|
||||
|
||||
|
||||
\section{Helper Objects}
|
||||
This section describes helper objects which implement useful data
|
||||
structures or utilities.
|
||||
\include{varlog}
|
||||
\include{dynar}
|
||||
\include{costa}
|
||||
\include{stringdict}
|
||||
\include{splitter}
|
||||
37
doc/programmer/programmer.tex
Normal file
37
doc/programmer/programmer.tex
Normal file
@@ -0,0 +1,37 @@
|
||||
% Copyleft (c) 1997-2000 by Mark Koennecke at PSI, Switzerland.
|
||||
%
|
||||
%
|
||||
%
|
||||
|
||||
\documentclass[12pt]{report}
|
||||
\usepackage{epsf}
|
||||
\setlength{\oddsidemargin}{-.1in}
|
||||
\setlength{\evensidemargin}{0in}
|
||||
\setlength{\topmargin}{0in}
|
||||
\addtolength{\topmargin}{-\headheight}
|
||||
\addtolength{\topmargin}{-\headsep}
|
||||
\setlength{\textheight}{8.9in}
|
||||
\setlength{\textwidth}{6.2in}
|
||||
\setlength{\marginparwidth}{0.5in}
|
||||
|
||||
\begin{document}
|
||||
\title{The SICS Programmers Reference}
|
||||
|
||||
\author{Mark K\"onnecke\\
|
||||
Labor f\"ur Neutronenstreuung\\
|
||||
Paul Scherrer Institut\\
|
||||
CH-5232 Villigen PSI\\
|
||||
Switzerland\\
|
||||
Mark.Koennecke@psi.ch \\
|
||||
}
|
||||
|
||||
|
||||
\maketitle
|
||||
\tableofcontents
|
||||
\include{overview}
|
||||
\include{proto}
|
||||
\include{kernelguide}
|
||||
\include{oguide}
|
||||
|
||||
|
||||
\end{document}
|
||||
61
doc/programmer/proto.tex
Normal file
61
doc/programmer/proto.tex
Normal file
@@ -0,0 +1,61 @@
|
||||
\chapter{The SICS Server Client Protocol}
|
||||
This short chapter describes the command protocol between the SICS server
|
||||
and possible SICS clients. All this is very simple.
|
||||
|
||||
\section{Logging in to the SICS Server}
|
||||
In order to log in to the SICS server it needs to be known on which
|
||||
machine the server runs and at which port number the server listens for
|
||||
connection requests. Also needed is a valid username/ password pair for the
|
||||
SICS server in question. Given that the procedure for connecting to a SICS
|
||||
server requires the following steps:
|
||||
\begin{enumerate}
|
||||
\item Open a TCP/IP connection to the SICS server port at the machine
|
||||
where it is running.
|
||||
\item Immediately after opening the connection send the username/password
|
||||
pair. If everything is OK, a string OK is sent. Else the server will break
|
||||
the connection again.
|
||||
\end{enumerate}
|
||||
|
||||
\section{Sending Commands}
|
||||
After login, two means of communications exist. The communication
|
||||
protocoll is choosen through the server port the client connects too.
|
||||
The recommended way is
|
||||
to adhere to the telnet protocoll as described in RFC-854. Just a
|
||||
basic NVT (Network Virtual Terminal) with no options is
|
||||
implemented. Binary communication is not possible on a telnet port.
|
||||
|
||||
The older way of communication is to send commands directly on the
|
||||
TCP/IP port. Commands are strings terminated by a \verb+\n+. Return
|
||||
messages from the server have the same format. This scheme is
|
||||
obsolete but it has been left in because the need for a binary
|
||||
communication may arise and this would help implement such a thing.
|
||||
|
||||
|
||||
|
||||
For a list of possible commands consult the
|
||||
user documentation.
|
||||
|
||||
\section{Issuing Interrupts}
|
||||
In some cases a user might want to stop the operation of the server. In
|
||||
order to do this the client must send an interrupt to the SICS server. There
|
||||
are two ways to do this: through the normal connection socket and through
|
||||
the a special UDP message to the server. Let us first discuss the first
|
||||
method, which uses the normal command socket for sending an interrupt.
|
||||
|
||||
In order to send an interrupt through the normal command socket a special
|
||||
message must be sent, consisting of a special command string. The command
|
||||
string is again all ASCII. The first part of this command string must read:
|
||||
INT1712, followed by a number denoting the interrupt. The meaning of these
|
||||
numbers is resolved in file interrupt.h. For example, the string 'INT1712 2'
|
||||
will abort the current scan. The presence of an interrupt string will be
|
||||
checked for already by the network reader. This means that such interrupts
|
||||
will even be honored when the client connection is waiting for some hardware
|
||||
to finish its job and would not accept normal commands. \label{prot1}
|
||||
|
||||
The SICS server also checks a special TCP/IP port for UDP messages which
|
||||
denote an interrupt. In order to send an interrupt through this channel, a
|
||||
UDP connection to the SICS servers UDP port must be opened. Then an special
|
||||
ASCII string of the form: {\bf SICSINT num} must be sent. num must be
|
||||
replaced by the number of the interrupt to issue. Again interrupt codes are
|
||||
resolved in file interrupt.h.
|
||||
|
||||
346
doc/programmer/pub.tex
Normal file
346
doc/programmer/pub.tex
Normal file
@@ -0,0 +1,346 @@
|
||||
% Copyleft (c) 1997 by Mark Koennecke at PSI, Switzerland.
|
||||
%
|
||||
%
|
||||
%
|
||||
|
||||
\documentclass[12pt]{article}
|
||||
\usepackage{epsf}
|
||||
\setlength{\oddsidemargin}{-.1in}
|
||||
\setlength{\evensidemargin}{0in}
|
||||
\setlength{\topmargin}{0in}
|
||||
\addtolength{\topmargin}{-\headheight}
|
||||
\addtolength{\topmargin}{-\headsep}
|
||||
\setlength{\textheight}{8.9in}
|
||||
\setlength{\textwidth}{6.2in}
|
||||
\setlength{\marginparwidth}{0.5in}
|
||||
\parindent=0pt
|
||||
\parskip=0.3cm
|
||||
|
||||
\begin{document}
|
||||
\title{SICS: SINQ Instrument Control Software}
|
||||
|
||||
\author{Mark K\"onnecke\\
|
||||
Heinz Heer\\
|
||||
Labor f\"ur Neutronenstreuung\\
|
||||
Paul Scherrer Institut\\
|
||||
CH-5232 Villigen PSI\\
|
||||
Switzerland\\
|
||||
Mark.Koennecke@psi.ch \\
|
||||
Heinz.Heer@psi.ch \\
|
||||
}
|
||||
|
||||
|
||||
\maketitle
|
||||
|
||||
\section{Introduction}
|
||||
At the new spallation source SINQ at PSI a whole set of new neutron
|
||||
scattering instruments are being installed. All these new instruments need a
|
||||
instrument control control system. After a review of similar systems
|
||||
out in the market it was found that none fully met the requirements defined
|
||||
for SINQ or could easily be extended to do so. Therefore it was decided to
|
||||
design a new system. This new system SICS, the SINQ Instrument Control
|
||||
System, had to meet the following specifications:
|
||||
\begin{itemize}
|
||||
\item Control the instrument reliably.
|
||||
\item Good remote access to the instrument via the internet.
|
||||
\item Portability across operating system platforms.
|
||||
\item Enhanced portability across instrument hardware. This means that it
|
||||
should be easy to add other types of motors, counters or other hardware to
|
||||
the system.
|
||||
\item Support authorization on the command and variable level. This means
|
||||
that certain instrument settings can be protected against harmful changes by
|
||||
less knowledgable users.
|
||||
\item Good maintainability and extendability.
|
||||
\item Be capable to acomodate graphical user interfaces (GUI).
|
||||
\item Single code base for all instruments.
|
||||
\item Powerful macro language.
|
||||
\end{itemize}
|
||||
A suitable new system was implemented using an object oriented design which
|
||||
matches the above criteria.
|
||||
|
||||
\section{The SINQ Hardware Setup}
|
||||
SICS had to take in account the SINQ hardware setup which had been decided
|
||||
upon earlier on. Most hardware such as motors and counters is controlled via
|
||||
RS--232 interfaces. These devices connect to a Macintosh PC which has a
|
||||
terminal server program running on it. This terminal server program collects
|
||||
request to the hardware from a TCP/IP port and forwards them to the serial
|
||||
device. The instrument control program runs on a workstation running
|
||||
DigitalUnix. Communication with the hardware happens via TCP/IP through the
|
||||
terminal server. Some hardware devices, such as the histogram memory, can handle
|
||||
TCP/IP themselves. With such devices the instrument control program
|
||||
communicates directly through TCP/IP, without a terminal server. All
|
||||
hardware devices take care of their real time needs themselves. Thus the
|
||||
only task of the instrument control program is to orchestrate the hardware
|
||||
devices. SICS is designed with this setup up in mind, but is not restricted
|
||||
to it. A schematic view of the SINQ hardware setup is given in picture
|
||||
\ref{hard}.
|
||||
\begin{figure}
|
||||
\epsfxsize=0.65\textwidth
|
||||
%% \epsfxsize=160mm
|
||||
\epsffile{hart.eps}
|
||||
\caption{Instrument control hardware setup at SINQ}\label{hard}
|
||||
\end{figure}
|
||||
|
||||
|
||||
\section{SICS Overall Design}
|
||||
In order to achieve the design goals stated above it was decided to divide
|
||||
the system into a client server system. This means that there are at least
|
||||
two programs necessary to run an instrument: a client program and a server
|
||||
program. The server program, the SICS server, does all the work and
|
||||
implements the actual instrument control. The SICS server usually runs on
|
||||
the DAQ computer. The client program may run on any computer on the world
|
||||
and implements the user interface to the instrument. Any numbers of clients
|
||||
can communicate with one SICS server. The SICS server and the clients
|
||||
communicate via a simple ASCII command protocol through TCP/IP sockets.
|
||||
With this design good remote control through the network is easily achieved.
|
||||
SICS clients can be implemented in any language or system capable of handling
|
||||
TCP/IP. Thus the user interface and the functional aspect are well separated. This
|
||||
allows for easy exchange of user interfaces by writing new clients.
|
||||
|
||||
|
||||
\section{SICS Clients}
|
||||
SICS Clients implement the SICS user interface. Current client programs have
|
||||
been written in Tcl/TK$^{1}$, but work is under way to recode clients in Java for
|
||||
maximum platform portability. This is a real concern at SINQ where VMS,
|
||||
Intel-PC, Macintosh and Unix users have to be satisfied. As many instrument scientists still prefer
|
||||
the command line for interacting with instruments, the most used client is a
|
||||
visual command line client. Status displays are another sort of specialized
|
||||
client programs. Graphical user interfaces are under consideration for some
|
||||
instruments. As an example for a client a screen shot of the command line
|
||||
client is given in picture \ref{dmc}.
|
||||
\begin{figure}[h]
|
||||
\epsfxsize=0.9\textwidth
|
||||
%% \epsfxsize=160mm
|
||||
\epsffile{dmccom.eps}
|
||||
\caption{Example for a SICS client: The Command line client}\label{dmc}
|
||||
\end{figure}
|
||||
|
||||
|
||||
|
||||
\section{The SICS Server}
|
||||
The SICS server is the core component of the SICS system. The SICS server is
|
||||
responsible for doing all the work in instrument control. Additionally the
|
||||
server has to answer the requests of possibly multiple clients.
|
||||
The SICS server can be subdivided into three subsystems: The kernel, a database
|
||||
of SICS objects and an interpreter. The SICS server kernel takes care of
|
||||
client multitasking and the preservation of the proper I/O and error context
|
||||
for each client command executing.
|
||||
|
||||
SICS objects are software modules which represent all aspects
|
||||
of an instrument: hardware devices, commands, measurement strategies
|
||||
and data storage. The SICS server's database of objects is initialized at server startup
|
||||
time from an initialization script. The third SICS server component is an
|
||||
interpreter which allows to issue commands to the objects in the objects database.
|
||||
A schematic drawing of the SICS server's structure is given in picture
|
||||
\ref{sicsnew}.
|
||||
\begin{figure}
|
||||
\epsfxsize=0.9\textwidth
|
||||
\epsfysize=100mm
|
||||
%% \epsfxsize=160mm
|
||||
\epsffile{newsics.eps}
|
||||
\caption{Schematic Representation of the SICS server's structure}\label{sicsnew}
|
||||
\end{figure}
|
||||
|
||||
|
||||
\subsection{The SICS Server Kernel}
|
||||
Any server-program has the problem how to organize multiple
|
||||
clients accessing the same server and how to stop one client reading data,
|
||||
which another client is just writing. The approach used for the SICS server
|
||||
is a combination of polling and cooperative multitasking. This scheme is
|
||||
simple and can be implemented in an operating system independent manner. One
|
||||
way to look at the SICS server is as a series of tasks in a circular queue
|
||||
executing one after another. There are several system tasks and one
|
||||
task for each living client connection. The servers main loop does nothing but
|
||||
executing the tasks in this circular buffer in an endless loop.
|
||||
Thus only one task executes at any
|
||||
given time and data access is efficiently serialized.
|
||||
|
||||
One of the main system
|
||||
tasks (and the one which will be always there) is the network reader. The
|
||||
network reader has a list of open network connections and checks each of
|
||||
them for pending requests. What happens when data is pending on an open
|
||||
network port depends on the type of port: If it is the servers main
|
||||
connection port, the network reader will try to accept and verify a new
|
||||
client connection and create the associated data structures. If the port
|
||||
belongs to an open client connection the network reader will read the
|
||||
command pending and put it onto a command stack existing for each client
|
||||
connection. When it is time for a client task to execute, it will fetch a
|
||||
command from its very own command stack and execute it. When the net reader
|
||||
finds an user interrupt pending, the interrupt is executed.
|
||||
This is how the SICS server deals with client requests.
|
||||
|
||||
The scheme described above relies on the fact that most SICS command need
|
||||
only very little time to execute. A command needing time extensive
|
||||
calculations may effectively block the server. Implementations of such
|
||||
commands have to take care that control passes back to the task switching
|
||||
loop at regular intervalls in order to prevent the server from blocking.
|
||||
|
||||
Another problem in a server handling multiple client requests is how to
|
||||
maintain the proper execution context for each client. This includes the
|
||||
clients I/O-context (socket), the authorisation of the client and possible
|
||||
error conditions pending for a
|
||||
client connection. SICS does this via a connection object, a special
|
||||
data structure holding all the above information plus a set of functions
|
||||
operating on this data structure. This connection object is passed along
|
||||
with many calls throughout the whole system.
|
||||
|
||||
Multiple clients issuing commands to the SICS server may mean that multiple
|
||||
clients might try to move motors or access other hardware in conflicting
|
||||
ways. As there is only one set of instrument hardware this needs to be
|
||||
prevented. This is achieved by a convention. No SICS object drives hardware
|
||||
directly but registers it's request with a special object, the device
|
||||
executor. This device executor starts the requested operation and reserves
|
||||
the hardware to the client for the length of the operation. During the execution of such
|
||||
an hardware request all other clients requests to drive the hardware will
|
||||
return an error. The device executor is also responsible for monitoring the
|
||||
progress of an hardware operation. It does so by adding a special task into
|
||||
the system which checks the status of the operation each time this tasks
|
||||
executes. When the hardware operation is finished this
|
||||
device executor task will end. A special system facility allows a client
|
||||
task to wait for the device executor task to end while the rest of the task
|
||||
queue is still executing. In this way time intensive hardware operations can
|
||||
be performed by drive, count or scan commands without blocking the whole
|
||||
system for other clients. \label{devexec}
|
||||
|
||||
|
||||
Most experiments do not happen at ambient room conditions but
|
||||
require some special environment for the sample. Mostly this is temperature
|
||||
but it can also be magnetic of electric fields etc. Most of such devices
|
||||
can regulate themselves but the data acquisition program needs to monitor
|
||||
such devices. Within SICS this is done via a special system object, the
|
||||
environment monitor. A environment device, for example a temperature
|
||||
controller, registers it's presence with this object. Then an special system
|
||||
task will control this device when it is executing, check for possible out
|
||||
of range errors and initiates the proper error handling if such a problem is
|
||||
encountered.
|
||||
|
||||
\subsection{The SICS Interpreter}
|
||||
When a task belonging to a client connection executes a command it will pass
|
||||
the command along with the connection object to the SICS interpreter. The
|
||||
SICS interpreter will then analyze the command and forward it to the
|
||||
appropriate SICS object in the object database for further action. The SICS
|
||||
interpreter is very much modeled after the Tcl interpreter as devised by
|
||||
John Ousterhout$^{1}$. For each SICS object visible from the interpreter there is
|
||||
a wrapper function. Using the first word of the command as a key, the
|
||||
interpreter will locate the objects wrapper function. If such a function is
|
||||
found it is passed the command parameters, the interpreter object and the
|
||||
connection object for further processing. An interface exists to add and
|
||||
remove commands to this interpreter very easily. Thus the actual command
|
||||
list can be configured easily to match the instrument in question, sometimes
|
||||
even at run time. Given the closeness of the design of the SICS interpreter
|
||||
to the Tcl interpreter, the reader may not be surprised to learn that the
|
||||
SICS server incorporates Tcl as its internal macro language. The internal
|
||||
macro language may use Tcl commands as well as SICS commands.
|
||||
|
||||
\subsection{SICS Objects}
|
||||
As already said, SICS objects implement the true functionality of SICS
|
||||
instrument control. All hardware, all commands and procedures, all data
|
||||
handling strategies are implemented as SICS objects. Hardware objects, for
|
||||
instance motors deserve some special attention. Such objects are divided
|
||||
into two objects in the SICS system: A logical hardware object and a driver
|
||||
object. The logical object is responsible for implementing all the nuts and
|
||||
bolts of the hardware device, whereas the driver defines a set of primitive
|
||||
operations on the device. The benefit of this scheme is twofold:
|
||||
switching to new hardware, for instance a new type of motor, just requires
|
||||
to incorporate a new driver into the system. Internally, independent from
|
||||
the actual hardware, all hardware object of the same type (for example
|
||||
motors) look the same and can be treated the same by higher level objects.
|
||||
No need to rewrite a scan command because a motor changed.
|
||||
|
||||
In order to live happily within the SICS system SICS object have to adhere
|
||||
to a system of protocols. There are protocols for:
|
||||
\begin{itemize}
|
||||
\item Input/Output to the client.
|
||||
\item Error handling.
|
||||
\item Interaction with the interpreter.
|
||||
\item For identification of the object to the system at run time.
|
||||
\item For interacting with hardware (see device executor above).
|
||||
\item For checking the authorisation of the client who wants to execute the
|
||||
command.
|
||||
\end{itemize}
|
||||
|
||||
SICS uses NeXus$^{2}$, the upcoming standard for data exchange for neutron
|
||||
and X\_ray scattering as its raw data format.
|
||||
|
||||
SICS objects have the ability to notify clients and other objects of
|
||||
internal state changes. For example when a motor is driven, the motor object
|
||||
can be configured to tell SICS clients or other SICS objects about his new
|
||||
position.
|
||||
|
||||
The SICS server has been implemented in ANSI--C for maximum portability.
|
||||
ANSI--C proved powerful enough to support SICS's object oriented programming
|
||||
concepts.
|
||||
|
||||
\section{SICS Working Example}
|
||||
In order to illustrate the inner working of the SICS server a command to
|
||||
drive a motor will be traced through the system.
|
||||
\begin{itemize}
|
||||
\item The network reader finds data pending at one of the client ports.
|
||||
\item The network reader reads the command, splits it into single lines and
|
||||
put those on the top of the client connections command stack. The network
|
||||
reader passes control to the task switcher.
|
||||
\item In due time the client connection task executes, inspects its command
|
||||
stack, pops the command pending and forwards it together with a pointer to
|
||||
itself to the SICS interpreter.
|
||||
\item The SICS interpreter inspects the first word of the command. Using
|
||||
this key the interpreter finds the drive command wrapper function and passes
|
||||
control to that function.
|
||||
\item The drive command wrapper function will check further arguments,
|
||||
checks the
|
||||
clients authorisation if appropriate for the action requested. Depending on
|
||||
the checks, the wrapper function will create an error message or do its
|
||||
work.
|
||||
\item Assuming everything is OK, the motor is located in the system.
|
||||
\item The drive command wrapper function asks the device executor to run the
|
||||
motor.
|
||||
\item The device executor verifies that nobody else is driving, then starts
|
||||
the motor and grabs hardware control. The device executor also starts a task
|
||||
monitoring the activity of the motor.
|
||||
\item The drive command wrapper function now enters a wait state. This means
|
||||
the task switcher will execute other tasks, except the connection task
|
||||
requesting the wait state. The client connection and task executing the drive command
|
||||
will not be able to process further commands.
|
||||
\item The device executor task will keep on monitoring the progress of the motor
|
||||
driving whenever the task switcher allows it to execute.
|
||||
\item In due time the device executor task will find that the motor finished
|
||||
driving. The task will then die. The clients grab of the hardware driving
|
||||
permission will be released.
|
||||
\item At this stage the drive command wrapper function will awake and
|
||||
continue execution. This means inspecting errors and reporting to the client
|
||||
how things worked out.
|
||||
\item This done, control passes back through the interpreter and the connection
|
||||
task to the task switcher. The client connection is free to execute
|
||||
other commands.
|
||||
\item The next task executes.
|
||||
\end{itemize}
|
||||
|
||||
|
||||
\section{Current Status}
|
||||
Currently, SICS is in operation on the powder diffractometer DMC, the two circle
|
||||
diffractometer TOPSI and the small angle scattering diffractometer SANS.
|
||||
First clients have been
|
||||
implemented in Tcl/TK$^{1}$ and ANSI--C for a command line interface and status
|
||||
displays. First experiences with the system were positive. SICS currently
|
||||
supports the following hardware:
|
||||
\begin{itemize}
|
||||
\item SINQ EL734 motor controller.
|
||||
\item SINQ EL737 counter box.
|
||||
\item SINQ Histogram Memory.
|
||||
\item Dornier Velocity Selector.
|
||||
\item Oxford Instruments ITC4 temperature controller.
|
||||
\end{itemize}
|
||||
|
||||
SICS is in
|
||||
ongoing development. Support for the reactor time--of--flight instrument
|
||||
FOCUS, the
|
||||
reflectometer AMOR and the four circle diffractometer TRICS will be added in near
|
||||
future. Support for chopper control and more sample environment devices
|
||||
is on the way. More clients will be written in the Java programming language for
|
||||
optimal portability. Parties interested in using SICS or wishing to
|
||||
collaborate in its development are kindly asked to contact the authors.
|
||||
|
||||
\section{References}
|
||||
\begin{enumerate}
|
||||
\item John K Ousterhout: Tcl and the Tk toolkit, Addison--Wesley, 1994.
|
||||
\end{enumerate}
|
||||
\end{document}
|
||||
313
doc/programmer/reference.tex
Normal file
313
doc/programmer/reference.tex
Normal file
@@ -0,0 +1,313 @@
|
||||
% Copyleft (c) 1997-2000 by Mark Koennecke at PSI, Switzerland.
|
||||
%
|
||||
%
|
||||
% This software is distributed in the hope that it will be useful,
|
||||
% but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
% GNU General Public License for more details.
|
||||
%
|
||||
% You may already have a copy of the GNU General Public License; if
|
||||
% not, write to the Free Software Foundation, Inc., 675 Mass Ave,
|
||||
% Cambridge, MA 02139, USA.
|
||||
%
|
||||
|
||||
\documentclass[12pt]{article}
|
||||
\usepackage{epsf}
|
||||
\setlength{\oddsidemargin}{-.1in}
|
||||
\setlength{\evensidemargin}{0in}
|
||||
\setlength{\topmargin}{0in}
|
||||
\addtolength{\topmargin}{-\headheight}
|
||||
\addtolength{\topmargin}{-\headsep}
|
||||
\setlength{\textheight}{8.9in}
|
||||
\setlength{\textwidth}{6.2in}
|
||||
\setlength{\marginparwidth}{0.5in}
|
||||
|
||||
\begin{document}
|
||||
\title{SICS Reference Manual}
|
||||
|
||||
\author{Mark K\"onnecke\\
|
||||
Labor f\"ur Neutronenstreuung\\
|
||||
Paul Scherrer Institut\\
|
||||
CH-5232 Villigen PSI\\
|
||||
Switzerland\\
|
||||
Mark.Koennecke@psi.ch \\
|
||||
}
|
||||
|
||||
\maketitle
|
||||
\clearpage
|
||||
\tableofcontents
|
||||
|
||||
\clearpage
|
||||
|
||||
\section{SICS Programmers Reference}
|
||||
This document is mostly a boring listing of the interfaces and functions provided by
|
||||
the SICS modules. In order to get an idea of what is going on, please look
|
||||
at the SICS user documentation, the SICS manager documentation, and the SICS
|
||||
programmer guide.
|
||||
|
||||
{\huge Warning} This document serves as
|
||||
internal document for SICS developers only. It has not been proofread to any
|
||||
standards!
|
||||
|
||||
\section{Coding Practicalities}
|
||||
\subsection{Files}
|
||||
Any module or object has at least the following files associated with it:
|
||||
\begin{description}
|
||||
\item[.h] a header file with the external function definitions and
|
||||
often a typedef for the object data structure. The idea is that object
|
||||
data structures are exposed only where absolutely necessary.
|
||||
\item[.c] the implementation file. Often data structures are only
|
||||
defined in here.
|
||||
\item[.tex] a latex file describing the module or object, its data
|
||||
structures and its interface functions. To be included into this document.
|
||||
\end{description}
|
||||
Quite often, there are further files:
|
||||
\begin{description}
|
||||
\item[.i] descriptions of internal data structures.
|
||||
\item[.w] nuweb literate programming files. .w file contain a mixture
|
||||
of latex commands and code. The idea is that the code is embedded with
|
||||
the documentation. There are special commands to craete additional
|
||||
output files suitable for a compiler. The .w files are processed by
|
||||
the nuweb utility which will create tex documentation and code files
|
||||
from it. In SICS this is used to document data structures and
|
||||
interfaces and provide general information about each object. Then
|
||||
.tex, .h and .i files are created by nuweb. The use of this facility is
|
||||
recommended.
|
||||
\end{description}
|
||||
|
||||
\subsection{Building SICS}
|
||||
This document describes how to build the SICS software and where to find it.
|
||||
There are two sections: Building the SICS applications and building the Java
|
||||
clients. For both categories tarballs with all necessary files can be
|
||||
found in the /data/lnslib/src/sics directory. There are two tar files:
|
||||
sics.tar which contains the sources for the SICS server and additional C or
|
||||
F77 applications and java.tar which contains the code for the Java clients.
|
||||
|
||||
\subsubsection{Building the SICS Server and Applications}
|
||||
The first step is to untar the sics.tar file. As a result a directory sics
|
||||
with several subdirectories will be created. These subdirectories are:
|
||||
\begin{description}
|
||||
\item[hardsup] contains David Madens and other hardware drivers.
|
||||
\item[motor] contains the unix version of David Madens el734\_test program.
|
||||
\item[doc/programmer]holds programming documentation for SICS.
|
||||
\item[doc/user] The html sources for the user documentation. Also everything
|
||||
necessary for creating the printed documentation.
|
||||
\item[bin] Holds the final binary files.
|
||||
\item[tcl] Some Tcl helper code.
|
||||
\item[doc/manager]The SICS managers documentation.
|
||||
\item[difrac] The DIFRAC four circle diffraction subsystem.
|
||||
\end{description}
|
||||
For most programs makefiles are provided.
|
||||
Makefiles may need a little editing to correct the location of libraries.
|
||||
All necessary headers should be available in /data/lnslib/include and the
|
||||
libraries in /data/lnslib/lib.
|
||||
Building things within this hierarchy basically require to steps:
|
||||
\begin{enumerate}
|
||||
\item cd into the hardsup and difrac directories and type make in
|
||||
each. This builds required libraries for linking other applications.
|
||||
\item cd into the directory of the program you wish to compile and type make.
|
||||
For instance for building the SICServer, move into the main sics directory and
|
||||
type make.
|
||||
\end{enumerate}
|
||||
|
||||
\subsubsection{Building Java Clients}
|
||||
Again the first step is the untaring of tha java.tar file. This creates a
|
||||
java subdirectory which holds several other subdirectories:
|
||||
\begin{description}
|
||||
\item[focus] contains files special to the FOCUS status display.
|
||||
\item[lnsutil] a number of utility classes used by many SICs Java applications.
|
||||
\item[misc] several older classes kept for the purpose of documentation.
|
||||
\item[param] A package for building parameter displays.
|
||||
\item[ptplot] A XY-plot package.
|
||||
\item[sics] The Java command line client.
|
||||
\item[tablelayout] a special AWT layout manager used in the NeXus network
|
||||
Data Browser.
|
||||
\item[varwatch] Files special to the Varwatcher client.
|
||||
\item[cmapper] A package for mapping 2D-data arrays to colour pictures. Used
|
||||
for SANS.
|
||||
\item[htmlv] A html display package used for the help system.
|
||||
\item[lnet] Special network related utilities for the SICS Java applications.
|
||||
\item[lnswidgets] custom user interface components.
|
||||
\item[nndb] The NeXus Network Data Browser.
|
||||
\item[powder] The powder status display for DMC and HRPT.
|
||||
\item[sans] The SANS status display.
|
||||
\item[spread] Another layout manager package.
|
||||
\item[topsi] The topsi and general scan status display.
|
||||
\item[amor] The AMOR user interface program.
|
||||
\end{description}
|
||||
Furthermore there are some Java source file in the main directory together
|
||||
with some htm files and makefiles. For each of the Java clients a makefile
|
||||
is provided: make.focus, make.nndb, make.sans, make.topsi, make.powder,
|
||||
make.sics, makr.amor and make.watch. The purpose of each makefile can be deduced from
|
||||
its name. Building the Java clients requires two steps each: 1) compiling and
|
||||
2) building the jar file. The jar-file is a container file which contains
|
||||
all the classes necessary for running the application. This is the standard
|
||||
distribution format for the SICS Java clients. The necessary commands are
|
||||
using the powder status display as example:
|
||||
\begin{description}
|
||||
\item[Compiling] make -f make.powder
|
||||
\item[Jar-File] make -f make.powder jar
|
||||
\end{description}
|
||||
|
||||
|
||||
\section{Kernel Objects and Modules}
|
||||
This section describes the modules defining the SICS kernel.
|
||||
\include{task}
|
||||
\include{nserver}
|
||||
\include{ini}
|
||||
\include{passwd}
|
||||
\include{network}
|
||||
\include{nread}
|
||||
\include{telnet}
|
||||
\include{nconman}
|
||||
\include{costa}
|
||||
\include{interface}
|
||||
\include{event}
|
||||
\include{devexec}
|
||||
\include{SCinter}
|
||||
\include{macro}
|
||||
\include{emonitor}
|
||||
\include{perfmon}
|
||||
\include{interrupt}
|
||||
\include{ofac}
|
||||
\include{servlog}
|
||||
\subsection{The commandlog}
|
||||
This is yet another logging facility of SICS. The idea is that all I/O
|
||||
going to connections with user or manager level rights is logged.
|
||||
This allows to figure out what really happened at an instrument. From
|
||||
this base a scheme was introduced to automatically generate command
|
||||
log files for each day. Additionally time stamps can be printed into
|
||||
the commandlog at predefined intervalls. In terms of an external
|
||||
interface the commandlog just has a few functions for installing and
|
||||
configuring the commandlog from the interpreter plus a function for
|
||||
writing to it. The rest is implemented as file statics in commandlog.c.
|
||||
|
||||
|
||||
\section{SICS Core Objects}
|
||||
This section describes the SICS objects implementing commands and objects
|
||||
common to all SICS instruments.
|
||||
\include{scan}
|
||||
\include{center}
|
||||
\include{danu}
|
||||
\include{drive}
|
||||
\include{alias}
|
||||
\include{buffer}
|
||||
\include{ruli}
|
||||
\include{o2t}
|
||||
\include{selector}
|
||||
\include{sicsexit}
|
||||
\include{status}
|
||||
\include{cron}
|
||||
\include{optimise}
|
||||
\include{token}
|
||||
\include{udpquieck}
|
||||
\include{xytable}
|
||||
|
||||
\section{SICS Hardware Objects}
|
||||
This section deals with objects and modules representing instrument
|
||||
hardware. Please be reminded that a hardware object within SICS
|
||||
usually consists of two layers:
|
||||
\begin{itemize}
|
||||
\item The logical layer building the interface to SICS.
|
||||
\item The driver layer actually interfacing to the hardware.
|
||||
\end{itemize}
|
||||
This allows for the easy adaption to new hardware by exchanging
|
||||
drivers.
|
||||
The next thing to note is that most SICS hardware objects implement
|
||||
at least one of the standard SICS interfaces:
|
||||
\begin{itemize}
|
||||
\item The drivable interface
|
||||
\item The countable interface
|
||||
\item The environment interface
|
||||
\item The callback interface.
|
||||
\end{itemize}
|
||||
Please note, that there is some history in SICS hardware access. At
|
||||
first there were no interfaces and objects implemented special
|
||||
functions for themselves. These are still in the code. Some have their
|
||||
right as utility functions. However, the preferred and supported way of
|
||||
accessing SICS hardware objects is through the interface functions.
|
||||
|
||||
\include{velo}
|
||||
\include{velodorn}
|
||||
\include{evcontroller}
|
||||
\include{itc4}
|
||||
\include{bruker}
|
||||
\include{tclev}
|
||||
\include{evdrivers}
|
||||
|
||||
\include{motor}
|
||||
\include{pimotor}
|
||||
|
||||
\include{counter}
|
||||
\include{histogram}
|
||||
\include{sinqhmdriv}
|
||||
\include{histsim}
|
||||
\include{choco}
|
||||
\include{serial}
|
||||
\include{serialwait}
|
||||
\include{sps}
|
||||
|
||||
\section{Powder Diffraction Specific Objects}
|
||||
\include{dmc}
|
||||
\include{nxdata}
|
||||
|
||||
\section{SANS specific Objects}
|
||||
\include{mumo}
|
||||
\subsection{NXSans}
|
||||
The files nxsans.h and nxsans.c implement the NeXus writing functions for SANS. Also interpreter commands for configuring SANS data writing into SICS and for triggering data writing are implemented.
|
||||
\include{sanswave}
|
||||
|
||||
\section{FOCUS Specific Objects}
|
||||
\include{faverage}
|
||||
\include{fowrite}
|
||||
|
||||
\section{AMOR Specific Objects}
|
||||
\include{amor2t}
|
||||
\include{amorscan}
|
||||
\include{amorstat}
|
||||
\include{nxamor}
|
||||
|
||||
\section{Four-Circle Diffraction Specific Objects}
|
||||
\include{hkl}
|
||||
\include{hklscan}
|
||||
\include{integrate}
|
||||
\include{mesure}
|
||||
\include{tricsnex}
|
||||
\include{difrac}
|
||||
|
||||
\section{Helper Objects}
|
||||
This section describes helper objects which implement useful data
|
||||
structures or utilities.
|
||||
\include{serialsinq}
|
||||
\include{varlog}
|
||||
\include{dynar}
|
||||
\include{splitter}
|
||||
\include{obpar}
|
||||
\include{stringdict}
|
||||
\include{fupa}
|
||||
\include{nxsans}
|
||||
|
||||
\subsection{Further Helper Code}
|
||||
Further helper code includes lld.*. This is a general linked list package.
|
||||
It is documented in lld.h. All credits go to its original author. lld.c has
|
||||
been modified slightly to resolve a memory problem.
|
||||
|
||||
napi.* is the NeXus API. This is documented in a separate document.
|
||||
|
||||
nxdict.* is the NeXus dictionary API, which is documented in another
|
||||
separate document.
|
||||
|
||||
strdup.* is a fortified implementation of the standard utility strdup.
|
||||
|
||||
strrepl.c is the implmentation of a string replace.
|
||||
|
||||
uubuffer.* is a utility function which UUencodes a buffer.
|
||||
|
||||
uusend.c is some helper code for sending UUencoded messages.
|
||||
|
||||
scaldate.* is an implementation of some julian date conversion
|
||||
utilities. Is used in commandlog for incrementing date.
|
||||
|
||||
circular.* is the implementation of a circular buffer.
|
||||
|
||||
\end{document}
|
||||
45
doc/programmer/ruli.tex
Normal file
45
doc/programmer/ruli.tex
Normal file
@@ -0,0 +1,45 @@
|
||||
\subsection{The R\"unlist}
|
||||
The R\"unlist is part of the LNS R\"unbuffer system. It is a stack of
|
||||
r\"unbuffers. When started, the last r\"unbuffer of the stack is executed.
|
||||
While this is happening it is
|
||||
possible to modify, delete and add r\"unbuffers to the stack.
|
||||
|
||||
The R\"unlist is characterized by the following data structure:
|
||||
\begin{verbatim}
|
||||
typedef struct {
|
||||
pObjectDescriptor pDes;
|
||||
int iList;
|
||||
} RuenStack, *pRuenStack;
|
||||
\end{verbatim}
|
||||
The fields are:
|
||||
\begin{description}
|
||||
\item[pDes] A pointer to the usual SICS object descriptor.
|
||||
\item[iList] A lld--list of r\"unbuffers.
|
||||
\end{description}
|
||||
|
||||
Interaction with the R\"unlist happens through the interface functions given
|
||||
below. If not stated otherwise functions return 1 on success, 0 on failure.
|
||||
Most functions take as first parameter a pointer to a r\"unlist structure.
|
||||
\begin{description}
|
||||
\item[pRuenStack CreateRuenStack(void)] creates a new r\"unlist. Returns the
|
||||
pointer to a new r\"unlist structure on success, NULL on failure.
|
||||
\item[void DeleteRuenStack(void *self)] deletes a r\"unlist.
|
||||
\item[int RuenStackAdd(pRuenStack self,pRuenBuffer pVictim)] puts
|
||||
r\"unbuffer pVictim on top of the r|'unlist.
|
||||
\item[int RuenStackUnlink(pRuenStack self, int iLine)] removes r\"unbuffer
|
||||
number iLine from the r\"unlist. This command does NOT delete the
|
||||
r\"unbuffer.
|
||||
\item[int RuenStackInsert(pRuenStack self, int iLine, pRuenBuffer pVictim)]
|
||||
inserts r\"unbuffer pVictim after line iLine into the r\"unlist.
|
||||
\item[int RuenStackList(pRuenStack self, SConnection *pCon)] list the
|
||||
contents of the r\"unlist onto the connection pCon.
|
||||
\item[int RuenStackRun(pRuenStack self,SConnection *pCon, SicsInterp
|
||||
*pSics)] executes the r\"unlist. Ends when the r\"unlist is empty.
|
||||
\item[int RuenStackBatch(pRuenStack self,SConnection *pCon, SicsInterp
|
||||
*pSics)] executes the r\"unlist. If the list is empty RuenStackBatch
|
||||
continues and checks for new r\"unbuffers being added to the list.
|
||||
\item[int RuenStackAction(SConnection *pCon, SicsInterp *pSics, void *pData,\\
|
||||
int argc, char *argv[])] The object wrapper function
|
||||
for the R\"unlist.
|
||||
\end{description}
|
||||
|
||||
100
doc/programmer/sanswave.tex
Normal file
100
doc/programmer/sanswave.tex
Normal file
@@ -0,0 +1,100 @@
|
||||
\subsection{SANS Wavelength Calculation}
|
||||
The instrument SANS has a neutron velocity selector. A wavelength is
|
||||
selected by varying tilt angle and rotation speed of the velocity selector.
|
||||
The relation between tilt angle and rotation speed to wavelength is given by
|
||||
a formula: \begin{eqnarray}
|
||||
\lambda & = & A + \frac{B}{rot}\\
|
||||
\lambda & = & wavelength in nm\\
|
||||
rot & = & rotation speed in revolutions per minute.
|
||||
\end{eqnarray}
|
||||
A and B are coefficients which are calculated from fourth degree polynoms.
|
||||
The coefficients of these polynoms have been obtained by fitting them
|
||||
against experimental data. This module now provides for this calculation and
|
||||
the driving of wavelength. This code does not vary tilt angle.
|
||||
|
||||
This object data structure is simple:
|
||||
\begin{flushleft} \small
|
||||
\begin{minipage}{\linewidth} \label{scrap1}
|
||||
$\langle$wavedat {\footnotesize ?}$\rangle\equiv$
|
||||
\vspace{-1ex}
|
||||
\begin{list}{}{} \item
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@ typedef struct __SANSwave {@\\
|
||||
\mbox{}\verb@ pObjectDescriptor pDes;@\\
|
||||
\mbox{}\verb@ pIDrivable pDrivInt;@\\
|
||||
\mbox{}\verb@ pVelSel pSelector;@\\
|
||||
\mbox{}\verb@ };@\\
|
||||
\mbox{}\verb@@$\diamond$
|
||||
\end{list}
|
||||
\vspace{-1ex}
|
||||
\footnotesize\addtolength{\baselineskip}{-1ex}
|
||||
\begin{list}{}{\setlength{\itemsep}{-\parsep}\setlength{\itemindent}{-\leftmargin}}
|
||||
\item Macro never referenced.
|
||||
\end{list}
|
||||
\end{minipage}\\[4ex]
|
||||
\end{flushleft}
|
||||
The fields are:
|
||||
\begin{description}
|
||||
\item[pDes] The standard SICS object descriptor.
|
||||
\item[pDrivInt] A standard drivable interface.
|
||||
\item[pSelector] The velocity selector to act upon.
|
||||
\end{description}
|
||||
|
||||
Most functionality of this module is hidden in the functions comprising the
|
||||
drivable interface. Thus the external functions of this object are limited
|
||||
to:
|
||||
|
||||
\begin{flushleft} \small
|
||||
\begin{minipage}{\linewidth} \label{scrap2}
|
||||
$\langle$sanswaveint {\footnotesize ?}$\rangle\equiv$
|
||||
\vspace{-1ex}
|
||||
\begin{list}{}{} \item
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@ typedef struct __SANSwave *pSANSWave;@\\
|
||||
\mbox{}\verb@/*-----------------------------------------------------------------------*/@\\
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@ int CalculateLambda(float fRot, float fTilt, float *fLambda);@\\
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@ int MakeSANSWave(SConnection *pCon, SicsInterp *pSics, void *pData,@\\
|
||||
\mbox{}\verb@ int argc, char *argv[]);@\\
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@ int SANSWaveAction(SConnection *pCon, SicsInterp *pSics, void *pData,@\\
|
||||
\mbox{}\verb@ int argc, char *argv[]);@\\
|
||||
\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 coefficients for the calculation of A and B are hidden in the module
|
||||
static function CalculateCoefficients.
|
||||
|
||||
\begin{flushleft} \small
|
||||
\begin{minipage}{\linewidth} \label{scrap3}
|
||||
\verb@"sanswave.h"@ {\footnotesize ? }$\equiv$
|
||||
\vspace{-1ex}
|
||||
\begin{list}{}{} \item
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@/*---------------------------------------------------------------------------@\\
|
||||
\mbox{}\verb@ S A N S W A V E@\\
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@ Wavelength calculations for a neutron velocity selector. Allows to drive@\\
|
||||
\mbox{}\verb@ the neutron wavelength directly.@\\
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@ copyright: see copyright.h@\\
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@ Mark Koennecke, October 1998@\\
|
||||
\mbox{}\verb@---------------------------------------------------------------------------*/@\\
|
||||
\mbox{}\verb@#ifndef SANSWAVE@\\
|
||||
\mbox{}\verb@#define SANSWAVE@\\
|
||||
\mbox{}\verb@@$\langle$sanswaveint {\footnotesize ?}$\rangle$\verb@@\\
|
||||
\mbox{}\verb@#endif @\\
|
||||
\mbox{}\verb@@$\diamond$
|
||||
\end{list}
|
||||
\vspace{-2ex}
|
||||
\end{minipage}\\[4ex]
|
||||
\end{flushleft}
|
||||
334
doc/programmer/scan.tex
Normal file
334
doc/programmer/scan.tex
Normal file
@@ -0,0 +1,334 @@
|
||||
\subsection{Scan}
|
||||
The first version of the scan command was implemented in Tcl. This prooved
|
||||
to be inefficient. Therefore the main loop for scan was reimplemented in
|
||||
C. A scan is in principle simple. However some complications are due to the
|
||||
fact that data files need to be written. Disk files need to be updated after
|
||||
each scan point. It must be possible to create derivations of the scan
|
||||
command which create other data formats or scan strategies. This
|
||||
configurability is catered for the function pointers in the ScanData
|
||||
structure. Individual functions can be exchanged and thus differently
|
||||
behaving scans created.
|
||||
|
||||
|
||||
Another complication is, that users might want to interrupt scans and
|
||||
restart from the last safe position. For this purpose
|
||||
there exists the recover option.
|
||||
|
||||
Scan also uses a scheme for creating scan data data files from a
|
||||
template. For more information about the template file see the SICS Managers
|
||||
documentation.
|
||||
|
||||
There are currently two schemes for modifying scans: The first works
|
||||
by implementing different scan handling functions and to assign them
|
||||
to the function pointers in the ScanData structure. The second works
|
||||
by defining a macro which will be called at each scan point and which
|
||||
has to return the a list with the counts and monitors collected.
|
||||
|
||||
This has grown to be overly complex. A path for a redesign might
|
||||
follow the idea of configurable functions to be called at various
|
||||
steps in scan processing which is already partly implemented.
|
||||
|
||||
|
||||
\begin{flushleft} \small
|
||||
\begin{minipage}{\linewidth} \label{scrap1}
|
||||
$\langle$scandata {\footnotesize ?}$\rangle\equiv$
|
||||
\vspace{-1ex}
|
||||
\begin{list}{}{} \item
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@ typedef struct {@\\
|
||||
\mbox{}\verb@ char Name[132];@\\
|
||||
\mbox{}\verb@ pIDrivable pInter;@\\
|
||||
\mbox{}\verb@ pDummy pObject;@\\
|
||||
\mbox{}\verb@ float fStart;@\\
|
||||
\mbox{}\verb@ float fStep;@\\
|
||||
\mbox{}\verb@ float *fData;@\\
|
||||
\mbox{}\verb@ }VarEntry, *pVarEntry;@\\
|
||||
\mbox{}\verb@/*--------------------------------------------------------------------------*/@\\
|
||||
\mbox{}\verb@ typedef struct {@\\
|
||||
\mbox{}\verb@ int i;@\\
|
||||
\mbox{}\verb@ long lCount;@\\
|
||||
\mbox{}\verb@ long Monitors[10];@\\
|
||||
\mbox{}\verb@ float fTime;@\\
|
||||
\mbox{}\verb@ } CountEntry, *pCountEntry;@\\
|
||||
\mbox{}\verb@/*---------------------------------------------------------------------------*/ @\\
|
||||
\mbox{}\verb@ typedef struct __ScanData {@\\
|
||||
\mbox{}\verb@ pObjectDescriptor pDes;@\\
|
||||
\mbox{}\verb@ pICallBack pCall;@\\
|
||||
\mbox{}\verb@ pDynar pScanVar;@\\
|
||||
\mbox{}\verb@ int iScanVar;@\\
|
||||
\mbox{}\verb@ int iNP;@\\
|
||||
\mbox{}\verb@ int iMode;@\\
|
||||
\mbox{}\verb@ float fPreset;@\\
|
||||
\mbox{}\verb@ char pFile[1024];@\\
|
||||
\mbox{}\verb@ char ext[5];@\\
|
||||
\mbox{}\verb@ FILE *fd;@\\
|
||||
\mbox{}\verb@ SicsInterp *pSics;@\\
|
||||
\mbox{}\verb@ SConnection *pCon;@\\
|
||||
\mbox{}\verb@ char pRecover[1024];@\\
|
||||
\mbox{}\verb@ char pHeaderFile[1024];@\\
|
||||
\mbox{}\verb@ int (*WriteHeader)(pScanData self);@\\
|
||||
\mbox{}\verb@ int (*WriteScanPoints)@\\
|
||||
\mbox{}\verb@ (pScanData self, @\\
|
||||
\mbox{}\verb@ int iPoint);@\\
|
||||
\mbox{}\verb@ int (*ScanDrive)(pScanData self, @\\
|
||||
\mbox{}\verb@ int i);@\\
|
||||
\mbox{}\verb@ int (*ScanCount)(pScanData self,@\\
|
||||
\mbox{}\verb@ int i);@\\
|
||||
\mbox{}\verb@ int (*CollectScanData)@\\
|
||||
\mbox{}\verb@ (pScanData self,@\\
|
||||
\mbox{}\verb@ int iP);@\\
|
||||
\mbox{}\verb@ long lPos;@\\
|
||||
\mbox{}\verb@ void *pCounterData;@\\
|
||||
\mbox{}\verb@ char pCounterName[512];@\\
|
||||
\mbox{}\verb@ int iChannel;@\\
|
||||
\mbox{}\verb@ pDynar pCounts;@\\
|
||||
\mbox{}\verb@ int iCounts;@\\
|
||||
\mbox{}\verb@ int iActive;@\\
|
||||
\mbox{}\verb@ int iWindow;@\\
|
||||
\mbox{}\verb@ char *pCommand;@\\
|
||||
\mbox{}\verb@ void *pSpecial;@\\
|
||||
\mbox{}\verb@ } ScanData;@\\
|
||||
\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 VarEntry structure holds the data for each single scan variable.
|
||||
These are its name, its object data structures, the start and step
|
||||
values for the scan and in fData the positions actually reached during
|
||||
the scan.
|
||||
|
||||
The CountEntry structure holds the entries for one counting
|
||||
operations. These are the lCounts collected, up to 10 monitors and the
|
||||
time needed for counting. This is the time read from the counter box.
|
||||
|
||||
The ScanData datastructure contains the following fields:
|
||||
\begin{description}
|
||||
\item[pDes] The standard SICS object descriptor.
|
||||
\item[pCall] A pointer to the standard SICS callback interface. Scan support
|
||||
the SCANPOINT message which will be executed after each
|
||||
scan point.
|
||||
\item[pScanVar, iScanVar] A dynamic array of VarEntry structures which
|
||||
define the variables to drive in the scan. iScanVar is the total number of
|
||||
scan variables. A scan might drive more then one motor or variable.
|
||||
\item[iNP] is the number of scan points.
|
||||
\item[iMode] is the counter mode to use.
|
||||
\item[fPreset] is the preset value for the counter at each scan point. The
|
||||
exponents set for the counter apply.
|
||||
\item[pFile] is the name of the data file to write. This will be created
|
||||
automatically from SICS variables at the start of a scan.
|
||||
\item[fd] is the file descriptor for the open file when writing. fd will
|
||||
be opened by WriteHeader and closed again after WriteScanPoints.
|
||||
\item[pRecover] is the name of the recover file. After each scan point scan
|
||||
writes some data to file which allows to restart an aborted scan.
|
||||
\item[pHeaderFile] is the name of a template file which will be used for
|
||||
generating the scan file header. Its format is simple: Everything except a
|
||||
few keywords will be copied verbatim. The keywords will be replaced by their
|
||||
apropriate values. Valid keywords are: !!DATE!! for the current date,
|
||||
!!VAR(name)!! for the value of a simple Sics variable, !!DRIV(name)!! for a Sics scan
|
||||
variable. The name of the variable is given in parenthesis.
|
||||
!!VAR!! and !!DRIV!! can be distinguished easily: Try a run or
|
||||
drive command on the variable in question. If it works and does not
|
||||
complain, it is the second sort. The second sort are mostly motors or
|
||||
collective variables such as lambda etc. Only one value of such a type per
|
||||
line is permitted.
|
||||
\item[pSics] a pointer to a SICS interpreter to use while running for
|
||||
finding data.
|
||||
\item[pCon] The connection object to use for error reporting during scan
|
||||
execution.
|
||||
\item[WriteHeader] is a pointer to a function which writes the header part
|
||||
of the scan file. Replace this function if another data format is needed.
|
||||
\item[WriteScanPoints] is a pointer to a function which will be called after
|
||||
each scan point to write the scan data to the data file. Replace this
|
||||
function when another data format is needed.
|
||||
\item[ScanDrive] is executed when the next point of a scan has to be reached.
|
||||
i is the point of the scan.
|
||||
\item[ScanCount] is executed when a scan point had been reached and a
|
||||
counting operation has to be performed. i is the scan point where we are.
|
||||
This function together with ScanDrive and the data writing functions allow for
|
||||
customized scans.
|
||||
\item[CollectScanData] reads all the scan data into the scan's data
|
||||
structures after any scan point. Overload this if a different storage
|
||||
scheme is required especiallay for polarising scans.
|
||||
\item[pCounterData] is a pointer to a counter structure. This defines the
|
||||
counter to use and is initialized at creation of the scan data structure.
|
||||
\item[pCountername] is the name of the counter used.
|
||||
\item[iChannel] is the channel to use for counting. 0 is the main counter,
|
||||
everything baove one of the monitors.
|
||||
\item[pCount, iCounts] is a dynamic array containing iCounts sets of
|
||||
counting infomation. For each scan point this array holds the counts
|
||||
measured. iCounts is also the current scan position.
|
||||
\item[iWindow] the width of the window used for peak integration. See
|
||||
integrate.w,c for more details.
|
||||
\item[pCommand] It turned out that a way is needed to define user defined
|
||||
speciality scans. This is implemented by setting the channel number to -10
|
||||
and then have the scan command execute a Tcl script for each scan point.
|
||||
This Tcl script has to return a Tcl list containing the values to enter for
|
||||
counter and monitor for the scan point. pCommand now is the name of the
|
||||
Tcl procedure to invoke.
|
||||
\item[pSpecial] Usually NULL. A entry which allows customized scans to keep
|
||||
some additional data in the scan data structure.
|
||||
\end{description}
|
||||
|
||||
The functional interface to the scan module includes the following
|
||||
functions:
|
||||
|
||||
\begin{flushleft} \small
|
||||
\begin{minipage}{\linewidth} \label{scrap2}
|
||||
$\langle$scaninter {\footnotesize ?}$\rangle\equiv$
|
||||
\vspace{-1ex}
|
||||
\begin{list}{}{} \item
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@/*------------------------- live & death ----------------------------------*/@\\
|
||||
\mbox{}\verb@ pScanData CreateScanObject(char *pRecover, char *pHeader, @\\
|
||||
\mbox{}\verb@ pCounter pCount);@\\
|
||||
\mbox{}\verb@ void DeleteScanObject(void *self);@\\
|
||||
\mbox{}\verb@/*-------------------------------------------------------------------------*/@\\
|
||||
\mbox{}\verb@ int AddScanVar(pScanData self, SicsInterp *pSics, SConnection *pCon, @\\
|
||||
\mbox{}\verb@ char *name, float fStart, float fStep);@\\
|
||||
\mbox{}\verb@ int ClearScanVar(pScanData self);@\\
|
||||
\mbox{}\verb@ @\\
|
||||
\mbox{}\verb@ int DoScan(pScanData self, int iNP, int iMode, float fPreset,@\\
|
||||
\mbox{}\verb@ SicsInterp *pSics, SConnection *pCon);@\\
|
||||
\mbox{}\verb@ int SilentScan(pScanData self, int iNP, int iMode, float fPreset,@\\
|
||||
\mbox{}\verb@ SicsInterp *pSics, SConnection *pCon);@\\
|
||||
\mbox{}\verb@ int RecoverScan(pScanData self, SicsInterp *pSics, SConnection *pCon);@\\
|
||||
\mbox{}\verb@ @\\
|
||||
\mbox{}\verb@ int GetScanCounts(pScanData self, long *lData, int iDataLen);@\\
|
||||
\mbox{}\verb@ int GetScanVar(pScanData self, int iWhich, float *fData, int iDataLen);@\\
|
||||
\mbox{}\verb@ int GetSoftScanVar(pScanData self, int iWhich, float *fData, int iDataLen);@\\
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@ int GetScanVarName(pScanData self, int iWhich, @\\
|
||||
\mbox{}\verb@ char *pName, int iLength);@\\
|
||||
\mbox{}\verb@ int GetScanVarStep(pScanData self, int iWhich, @\\
|
||||
\mbox{}\verb@ float *fStep);@\\
|
||||
\mbox{}\verb@ int GetScanMonitor(pScanData self, int iWhich, @\\
|
||||
\mbox{}\verb@ long *lData, int iDataLen);@\\
|
||||
\mbox{}\verb@ int GetScanNP(pScanData self);@\\
|
||||
\mbox{}\verb@ float GetScanPreset(pScanData self);@\\
|
||||
\mbox{}\verb@ @\\
|
||||
\mbox{}\verb@ int ScanIntegrate(pScanData self, float *fSum, float *fVariance);@\\
|
||||
\mbox{}\verb@ @\\
|
||||
\mbox{}\verb@ int SimScan(pScanData self, float fPos, float FHWM, float fHeight);@\\
|
||||
\mbox{}\verb@ /* @\\
|
||||
\mbox{}\verb@ creates a simulated gaussian shaped peak with the parameters given.@\\
|
||||
\mbox{}\verb@ */@\\
|
||||
\mbox{}\verb@ int ResetScanFunctions(pScanData self);@\\
|
||||
\mbox{}\verb@ /*@\\
|
||||
\mbox{}\verb@ resets the configurable scan functions to their default values.@\\
|
||||
\mbox{}\verb@ */@\\
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@/*------------------------ Interpreter Interface --------------------------*/@\\
|
||||
\mbox{}\verb@ int ScanFactory(SConnection *pCon, SicsInterp *pSics, void *pData,@\\
|
||||
\mbox{}\verb@ int argc, char *argv[]);@\\
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@ int ScanWrapper(SConnection *pCon, SicsInterp *pSics, void *pData,@\\
|
||||
\mbox{}\verb@ int argc, char *argv[]);@\\
|
||||
\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}
|
||||
All functions take a pointer to a ScanData structure as their first
|
||||
parameter. The functions:
|
||||
\begin{description}
|
||||
\item[CreateScanObject] creates a scan object. The parameters are the
|
||||
path to a recovery file, the path to a template file for file
|
||||
generation and a pointer to a counter object.
|
||||
\item[DeleteScanObject] removes the ScanData structure from memory
|
||||
properly.
|
||||
\item[AddScanVar] adds a variable to be scanned. Parameters are the
|
||||
name of the scan variable, the start and step values for the scan and
|
||||
a connection object to which errors shall be printed.
|
||||
\item[ClearScanVar] clears all scan variables.
|
||||
\item[DoScan] performs the actual scan. Parameters are the number of
|
||||
points, the counter mode and preset, the connection object for which
|
||||
the scan is done and the SICS interpreter executing the scan command.
|
||||
\item[SilentScan] does the same as DoScan but suppresses all output to
|
||||
data files. This is good for internal scans as in the optimize or
|
||||
mesure modules.
|
||||
\item[RecoverScan] loads the data about an aborted scan from the
|
||||
recovery file and continues to execute it. This most certainly will
|
||||
not work with custom scans. But is known to work with SICS TOPSI like
|
||||
standard scans.
|
||||
\item[GetScanCounts] allows to retrieve the counts collected in the
|
||||
scan. Max iDatLen entries will be copied into lData.
|
||||
\item[GetScanVar] retrieves the scan positions for the scan variable
|
||||
number i. Max iDatLen entries get copied into fData.
|
||||
\item[GetSoftScanVar] retrieves the scan positions for the scan variable
|
||||
number i. The soft positions are retrieved, not the hard position stored
|
||||
during the scan.
|
||||
\item[GetScanVarName] retrieves the name of scan variable i.
|
||||
\item[GetScanVarStep] gets the step of the scan variable i.
|
||||
\item[GetScanMonitor] allows to retrieve the monitor counts collected
|
||||
in monitor i during the
|
||||
scan. Max iDatLen entries will be copied into lData.
|
||||
\item[GetScanNP] returns the number of points in the scan.
|
||||
\item[GetScanPreset] returns the counter preset value for the scan.
|
||||
\item[ScanIntegrate] integrates the peak after a scan. Returns the
|
||||
summed counts and the variance. See the section on integrate for more
|
||||
details.
|
||||
\item[ResetScanFunctions] reinstalls the default functions for scan
|
||||
processing into the ScanData structure.
|
||||
\item[SimScan] creates a simulated gaussian peak with the given
|
||||
parameters. Used for debugging several things.
|
||||
\item[ScanFactory] is the SICS interpreter object creation function
|
||||
for the scan object.
|
||||
\item[ScanWrapper] is the SICS interpreter object function for
|
||||
interacting with the scan module.
|
||||
\end{description}
|
||||
\begin{flushleft} \small
|
||||
\begin{minipage}{\linewidth} \label{scrap3}
|
||||
\verb@"scan.h"@ {\footnotesize ? }$\equiv$
|
||||
\vspace{-1ex}
|
||||
\begin{list}{}{} \item
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@/*---------------------------------------------------------------------------@\\
|
||||
\mbox{}\verb@ S C A N@\\
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@ Header file for the SICS scan object.@\\
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@ Mark Koennecke, October 1997@\\
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@ copyright: see copyright.h@\\
|
||||
\mbox{}\verb@-----------------------------------------------------------------------------*/@\\
|
||||
\mbox{}\verb@#ifndef SICSSCAN1@\\
|
||||
\mbox{}\verb@#define SICSSCAN1@\\
|
||||
\mbox{}\verb@ typedef struct __ScanData *pScanData;@\\
|
||||
\mbox{}\verb@/*--------------------------------------------------------------------------*/@\\
|
||||
\mbox{}\verb@#include "counter.h"@\\
|
||||
\mbox{}\verb@@$\langle$scaninter {\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{scrap4}
|
||||
\verb@"scan.i"@ {\footnotesize ? }$\equiv$
|
||||
\vspace{-1ex}
|
||||
\begin{list}{}{} \item
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@/*--------------------------------------------------------------------------@\\
|
||||
\mbox{}\verb@ Internal header file holding the definition of the scan objects data@\\
|
||||
\mbox{}\verb@ structure.@\\
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@ Mark Koennecke, October 1997@\\
|
||||
\mbox{}\verb@----------------------------------------------------------------------------*/@\\
|
||||
\mbox{}\verb@#include "sdynar.h"@\\
|
||||
\mbox{}\verb@@$\langle$scandata {\footnotesize ?}$\rangle$\verb@@\\
|
||||
\mbox{}\verb@@$\diamond$
|
||||
\end{list}
|
||||
\vspace{-2ex}
|
||||
\end{minipage}\\[4ex]
|
||||
\end{flushleft}
|
||||
131
doc/programmer/selector.tex
Normal file
131
doc/programmer/selector.tex
Normal file
@@ -0,0 +1,131 @@
|
||||
\subsection{Monochromators}
|
||||
The code in these modules support standard crystal monochromators. The code
|
||||
is divided into two groups: There is the selector module which does most of
|
||||
the monochromator handling. And there are selvars, virtual motors which
|
||||
allow to drive the wavelength or the energy (for those triple axis guys)
|
||||
directly via the drive command. The monochromator module does not only
|
||||
adjust theta and two theta for the monochromator but also horizontal and
|
||||
vertical benders. The formula used for calculating the bending radius is: $b
|
||||
= C1 + \frac{C2}{sin(Theta)}$. This object is implemented in the
|
||||
files selector.h and selector.c.
|
||||
|
||||
As the configuration parameters of this object include the scattering
|
||||
sense, ss, it is also suitable for running the analyzer of a triple
|
||||
axis instrument.
|
||||
|
||||
\subsubsection{The Selector Device}
|
||||
The monochromator is described by the following data structure:
|
||||
\begin{verbatim}
|
||||
typedef struct __SicsSelector {
|
||||
ObjectDescriptor *pDes;
|
||||
ObPar *pParams;
|
||||
char *name;
|
||||
pMotor pTheta;
|
||||
pMotor pTwoTheta;
|
||||
pMotor pBend1;
|
||||
pMotor pBend2;
|
||||
char *pType;
|
||||
} SicsSelector;
|
||||
\end{verbatim}
|
||||
The fields:
|
||||
\begin{description}
|
||||
\item[pDes] A pointer to the usual SICS object descriptor.
|
||||
\item[pParams] A pointer to a SICS parameter array (see helper modules for
|
||||
more details).
|
||||
\item[name] The name of the monochromator.
|
||||
\item[pTheta] A pointer to the data structure for the Theta motor.
|
||||
\item[pTwoTheta] A pointer to the data structure for the Two Theta motor.
|
||||
\item[pBend1] A pointer to the data structure for the first bender motor.
|
||||
\item[pBend2] A pointer to the data structure for the second bender motor.
|
||||
\end{description}
|
||||
Please note, that troughout the code the bender motors are handled as
|
||||
optional.
|
||||
|
||||
The monochromator can be accessed with the following functions:
|
||||
\begin{description}
|
||||
\item[pSicsSelector CreateSelector(char *name, pMotor pTheta, pMotor pTwoTheta,\\
|
||||
pMotor pBend1, pMotor pBend2)]
|
||||
creates a new monochromator name with motors. The bender motors are
|
||||
optional, theta and two theta are required. Returns a pointer to a new
|
||||
monochromator data structure on success or NULL on failure.
|
||||
\item[int MonoInit(SConnection *pCon,SicsInterp *pSics, void *pData, \\
|
||||
int argc, char *argv[])] The monochromator factory function.
|
||||
\item[void DeleteSelector(void *self)] deletes a monochromator.
|
||||
\item[int MonoAction(SConnection *pCon, SicsInterp *pSics, void *pData,\\
|
||||
int argc, char *argv[])] The object wrapper function for
|
||||
the monochromator.
|
||||
\item[int MonoRun(pSicsSelector self, SConnection *pCon, float fWaveLength)]
|
||||
starts the selector to run to wavelength fWaveLength. Does not wait for
|
||||
finish. Eventual error messages are sent to pCon.
|
||||
\item[int MonoLimits(pSicsSelector self, float fWaveLength, char *error, \\
|
||||
int iErrLen)] checks if fWaveLength violates any motor
|
||||
limits. If so maximum iErrLen characters of description are copied to error.
|
||||
\item[int MonoCheck(pSicsSelector self, SConnection *pCon)] does a status
|
||||
check on all the monochromator motors. The result is the worst of the
|
||||
motor status codes as returned from the motors.
|
||||
\item[int MonoHalt(pSicsSelector self)] emergency halts the monochromator.
|
||||
\item[float GetMonoPosition(pSicsSelector self, SConnection *pCon)] get the
|
||||
current wavelength of the monochromator. Possible errors are rported to
|
||||
pcon. On error this function returns -999, else the current wavelength is
|
||||
returned.
|
||||
\item[char *MonoGetType(pSicsSelector self)] gets the type of the
|
||||
monochromator.
|
||||
\item[int GetMonoPositions(pSicsSelector self, SConnection *pCon, \\
|
||||
float *fTheta, float *fTwtTh, float *fB1, float
|
||||
*fB2)] gets the positions for all the monochromators motors.
|
||||
\end{description}
|
||||
|
||||
\subsubsection{The Monochromator Virtual Motors}
|
||||
This module implements the wavelength or energy variable to act upon a
|
||||
monochromator. Both types are represented by a special data structure:
|
||||
\begin{verbatim}
|
||||
typedef struct __SelVar {
|
||||
pObjectDescriptor pDes;
|
||||
pSicsSelector pSel;
|
||||
pIDrivable pDrivInt;
|
||||
float fValue;
|
||||
char *name;
|
||||
} SelVar;
|
||||
|
||||
\end{verbatim}
|
||||
The fields:
|
||||
\begin{description}
|
||||
\item[pDes] A pointer to the usual SICS object descriptor.
|
||||
\item[pSel] A pointer to the monochromator object to use for adjusting.
|
||||
\item[pDrivInt] A pointer to the drivable interface implemented.
|
||||
\item[fValue] The current value of the variable.
|
||||
\item[name] The name of the virtual motor.
|
||||
\end{description}
|
||||
|
||||
Most of the action for these variables is hidden in the drivable interface.
|
||||
This is also where the conversions between energy and wavelength are done.
|
||||
Consequently the interface to this module consists mostly of creation and
|
||||
deletion functions:
|
||||
\begin{description}
|
||||
\item[pSelVar CreateWLVar(char *name, pSicsSelector pSel)] creates a
|
||||
wavelength variable.
|
||||
\item[pSelVar CreateEnergy(char *name, pSicsSelector pSel)] creates an
|
||||
energy variable for monochromator pSel Both functions return NULL on failure
|
||||
and a pointer to a selector variable data structure in case of success.
|
||||
\item[void DeleteSelVar(void *pSelf)] deletes a selector variable.
|
||||
\item[int MakeWaveLengthVar(SConnection *pCon, SicsInterp *pSics, void *pData,\\
|
||||
int argc, char *argv[])] factory function for a
|
||||
wavelength variable.
|
||||
\item[int MakeEnergyVar(SConnection *pCon, SicsInterp *pSics, void *pData,\\
|
||||
int argc, char *argv[])] factory function for a energy
|
||||
variable.
|
||||
\item[float GetSelValue(pSelVar self, SConnection *pCon)] retrieves the
|
||||
current value of the variable. In case of errors -999 is returned and error
|
||||
messages are printed to pCon.
|
||||
\item[int WaveLengthAction(SConnection *pCon, SicsInterp *pSics, void *pData,\\
|
||||
int argc, char *argv[])] The object wrapper function
|
||||
for a wavelength variable.
|
||||
\item[int EnergyAction(SConnection *pCon, SicsInterp *pSics, void *pData,\\
|
||||
int argc, char *argv[])] The object wrapper function
|
||||
for a energy variable.
|
||||
\end{description}
|
||||
|
||||
Please note, that most of the important variables for handling a
|
||||
monochromator reside with the monochromator object and not with the virtual
|
||||
motors.
|
||||
|
||||
37
doc/programmer/serial.tex
Normal file
37
doc/programmer/serial.tex
Normal file
@@ -0,0 +1,37 @@
|
||||
\subsection{Serial Connections}
|
||||
This object allows to send arbitrary strings to a serial port in the SINQ
|
||||
hardware setup system. This means a message is packaged and forwarded to to
|
||||
the Macintosh serving the port. And data is read back again from there. This
|
||||
facility has been devised in order to write environment device drivers in
|
||||
the macro language and as help for SICS instrument managers.
|
||||
|
||||
In contrast to the many SICS objects this object is defined for the Tcl
|
||||
interpreter. This is because it is in use within the psish Tcl interpreter
|
||||
as well. There is only one function, SerialInit, which adds the serial
|
||||
command to the SICS interpreter.
|
||||
|
||||
\begin{flushleft} \small
|
||||
\begin{minipage}{\linewidth} \label{scrap1}
|
||||
\verb@"serial.h"@ {\footnotesize ? }$\equiv$
|
||||
\vspace{-1ex}
|
||||
\begin{list}{}{} \item
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@/*--------------------------------------------------------------------------@\\
|
||||
\mbox{}\verb@ S I C S S E R I A L@\\
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@ This object adds the serial command to the Tcl-interpreter within SICS.@\\
|
||||
\mbox{}\verb@ Furthermore the commands sr1-sr6 are added as predefined names for @\\
|
||||
\mbox{}\verb@ possible connections. @\\
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@ Mark Koennecke, January 1998@\\
|
||||
\mbox{}\verb@----------------------------------------------------------------------------*/@\\
|
||||
\mbox{}\verb@#ifndef SICSERIAL@\\
|
||||
\mbox{}\verb@#define SICSERIAL@\\
|
||||
\mbox{}\verb@ int SerialInit(SConnection *pCon,SicsInterp *pSics, void *pData,@\\
|
||||
\mbox{}\verb@ int argc, char *argv[]);@\\
|
||||
\mbox{}\verb@#endif@\\
|
||||
\mbox{}\verb@@$\diamond$
|
||||
\end{list}
|
||||
\vspace{-2ex}
|
||||
\end{minipage}\\[4ex]
|
||||
\end{flushleft}
|
||||
168
doc/programmer/serialsinq.tex
Normal file
168
doc/programmer/serialsinq.tex
Normal file
@@ -0,0 +1,168 @@
|
||||
\subsection{Command Forwarding Through the Serial Line}
|
||||
This is a set of utility routines which transport commands and
|
||||
responses to and from a serial port connected to a Macintosh terminal
|
||||
server. This is derived from the
|
||||
routines provided by David Maden for the EL734 motor controller. This
|
||||
utility is used by many of the SICS drivers. These
|
||||
functions are implemented in sinqserial.*. The following functions are
|
||||
defined:
|
||||
|
||||
\begin{flushleft} \small
|
||||
\begin{minipage}{\linewidth} \label{scrap1}
|
||||
$\langle$ss {\footnotesize ?}$\rangle\equiv$
|
||||
\vspace{-1ex}
|
||||
\begin{list}{}{} \item
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@ int SerialOpen(void **pData, char *pHost, int iPort, int iChannel);@\\
|
||||
\mbox{}\verb@ int SerialForceOpen(void **pData, char *pHost, int iPort, int iChannel);@\\
|
||||
\mbox{}\verb@ int SerialConfig(void **pData, int iTmo);@\\
|
||||
\mbox{}\verb@ int SerialGetTmo(void **pData);@\\
|
||||
\mbox{}\verb@ int SerialATerm(void **pData, char *pTerm);@\\
|
||||
\mbox{}\verb@ int SerialAGetTerm(void **pData, char *pTerm, int iTermLen);@\\
|
||||
\mbox{}\verb@ int SerialSendTerm(void **pData, char *pTerm);@\\
|
||||
\mbox{}\verb@ int SerialGetSocket(void **pData);@\\
|
||||
\mbox{}\verb@ int SerialClose(void **pData);@\\
|
||||
\mbox{}\verb@ int SerialSend(void **pData, char *pCommand);@\\
|
||||
\mbox{}\verb@ int SerialReceive(void **pData, char *pBuffer, int iBufLen);@\\
|
||||
\mbox{}\verb@ int SerialError(int iError, char *pError, int iErrLen);@\\
|
||||
\mbox{}\verb@ int SerialWriteRead(void **pData, char *pCommand, @\\
|
||||
\mbox{}\verb@ char *pBuffer, int iBufLen); @\\
|
||||
\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}
|
||||
Each of these functions returns 1 on success or a negative value on the
|
||||
likely event of an error. These negative values double as error codes.
|
||||
These error codes can be translated into text with SerialError.
|
||||
|
||||
|
||||
{\bf SerialOpen} opens a connection to a RS--232 at the computer pHost. The
|
||||
terminal server is leistening at port iPort and the serial line is
|
||||
iChannel. pData is a void pointer. It will be initialized with a data
|
||||
structure holding internal connection information. This pointer must be
|
||||
passed along with each of the other functions.
|
||||
|
||||
{\bf SerialNewOpen} is a second form of SerialOpen. The difference is in
|
||||
connection management. SerialOpen uses an existing network connection to the
|
||||
Macintosh, if existing. Thus data transfer is shared between many devices.
|
||||
This is fine as long as the devices reply to messages quick enough. But a
|
||||
slow device may block all communication.
|
||||
SerialNewOpen forces a new socket to be opened. Thereby a new thread is
|
||||
started in the Macintosh serial port server and devices get decoupled.
|
||||
This scheme is recommended for devices which reply slowly to RS--232
|
||||
requests.
|
||||
|
||||
|
||||
{\bf SerialConfig} configure the timeout to iTmo. This is the timeout the
|
||||
terminal server waits for commands to appear. pData is
|
||||
the pointer as initialized by SerialOpen.
|
||||
|
||||
{\bf GetSerialTmo} returns the currently valid timeout value.
|
||||
|
||||
{\bf SerialATerm} sets the expected string terminator to pTerm.
|
||||
{\bf SerialAGetTerm} copies maximum iTermLen characters of teminator
|
||||
information to pTerm.
|
||||
{\bf SerialSendTerm} sets the default terminator to send after each command.
|
||||
{\bf SerialClose} closes the connection to the RS--232 connection. pData is
|
||||
the pointer as initialized by SerialOpen.
|
||||
|
||||
{\bf SerialSend} sends pCommand onto the serial connection. pData is
|
||||
the pointer as initialized by SerialOpen. Please note, that this command
|
||||
clears the receive buffer at the terminal server. This means any answers
|
||||
pending from prior commands are deleted. This function can send only one
|
||||
single command. The Dornier velocity selector cannot handle more, anyway.
|
||||
|
||||
|
||||
{\bf SerialReceive} reads from the RS--232 connection into the buffer
|
||||
pBuffer, but maximum iBufLen characters. This version check with select for
|
||||
pending data and returns NODATA if nothing is available. pData is
|
||||
the pointer as initialized by SerialOpen.
|
||||
|
||||
{\bf SerialError} translates any of the negative error codes into a readable
|
||||
form. The error code is iError. Maximum iErrLen characters of text will
|
||||
be copied to pError. pData is
|
||||
the pointer as initialized by SerialOpen.
|
||||
|
||||
{\bf SerialWriteRead} writes the command pCommand to the port and tries
|
||||
to read a reply during the timeout period. Maximum iBufLen characters of
|
||||
answer will be copied to pBuffer. This function return a positive value
|
||||
on success or a negative error code. In case of an error pBuffer will
|
||||
be filled with an error message instead.
|
||||
|
||||
|
||||
SerialWriteRead loops on SerialReceive until data becomes available. But
|
||||
only for the maximum period specified as time out. In this loop
|
||||
SerialWriteRead calls a function which waits some time. By default this
|
||||
function maps to the system function sleep. However, an application might
|
||||
choose to specify another function instead. For instance a yield in a
|
||||
window system or a SicsWait in a SICS system. This feature may allow an
|
||||
application to do further processing while waiting for data to appear
|
||||
at a serial line. In order to do this the
|
||||
following typedef and function are necessary.
|
||||
|
||||
\begin{flushleft} \small
|
||||
\begin{minipage}{\linewidth} \label{scrap2}
|
||||
$\langle$sf {\footnotesize ?}$\rangle\equiv$
|
||||
\vspace{-1ex}
|
||||
\begin{list}{}{} \item
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@ typedef int (*SerialSleep)(void *pData, int iTime);@\\
|
||||
\mbox{}\verb@ void SetSerialSleep(void **pData, SerialSleep pFunc, void *pUserData);@\\
|
||||
\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 sleep function must take two parameters: A void pointer described below
|
||||
and an integer time value to waist.
|
||||
|
||||
{\bf SetSerialSleep} takes a pointer as returned by SetialOpen as first
|
||||
parameter. The second parameter is the sleep function. The third parameter
|
||||
is a pointer to an application defined data structure which will be passed
|
||||
on as first parameter to the sleep function by the system.
|
||||
|
||||
|
||||
|
||||
|
||||
\begin{flushleft} \small
|
||||
\begin{minipage}{\linewidth} \label{scrap3}
|
||||
\verb@"serialsinq.h"@ {\footnotesize ? }$\equiv$
|
||||
\vspace{-1ex}
|
||||
\begin{list}{}{} \item
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@/*----------------------------------------------------------------------------@\\
|
||||
\mbox{}\verb@ S E R I A L S I N Q@\\
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@ Utility functions for maintaining a connection to a RS--232 port on a@\\
|
||||
\mbox{}\verb@ Macintosh computer running the SINQ terminal server application.@\\
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@ Mark Koennecke, Juli 1997@\\
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@ copyright: see implementation file@\\
|
||||
\mbox{}\verb@------------------------------------------------------------------------------*/@\\
|
||||
\mbox{}\verb@#ifndef SERIALSINQ@\\
|
||||
\mbox{}\verb@#define SERIALSINQ@\\
|
||||
\mbox{}\verb@#define NOREPLY -100@\\
|
||||
\mbox{}\verb@#define NOCONNECTION -121@\\
|
||||
\mbox{}\verb@#define SELECTFAIL -120@\\
|
||||
\mbox{}\verb@#define TIMEOUT -130@\\
|
||||
\mbox{}\verb@#define INTERRUPTED -132;@\\
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@@$\langle$ss {\footnotesize ?}$\rangle$\verb@@\\
|
||||
\mbox{}\verb@/*-------------------------- The sleeperette -----------------------------*/@\\
|
||||
\mbox{}\verb@@$\langle$sf {\footnotesize ?}$\rangle$\verb@@\\
|
||||
\mbox{}\verb@#endif@\\
|
||||
\mbox{}\verb@@$\diamond$
|
||||
\end{list}
|
||||
\vspace{-2ex}
|
||||
\end{minipage}\\[4ex]
|
||||
\end{flushleft}
|
||||
64
doc/programmer/serialwait.tex
Normal file
64
doc/programmer/serialwait.tex
Normal file
@@ -0,0 +1,64 @@
|
||||
\subsection{Serial Wait}
|
||||
This module is a very SINQ specific function. At SINQ, serial devices are
|
||||
controlled through a serial port server program running on a Macintosh PC.
|
||||
This program blocks, if the serial device is very slow. This blocks the
|
||||
Macintosh as well as the SICS server. This module solves this problem. It
|
||||
does so using the following logic:
|
||||
|
||||
The command to execute is sent with a zero timeout.
|
||||
|
||||
A special sics task, the SerialPoller, is started to monitor the device.
|
||||
|
||||
The routine issuing the command waits for the SerialPoller to finish. If
|
||||
somebody issues new commands while this is going on, an error must be
|
||||
returned.
|
||||
|
||||
The SerialPoller sends commands of zero length and with a zero timeout to
|
||||
the Macintosh. Usually the reply will be a ?TMO because no data is
|
||||
available. If data becomes available, two situations have to be handled:
|
||||
In the first case all data was read including the terminator. Then a reply
|
||||
without a ?TMO will be returned. If there is a slight delay in getting all
|
||||
the data, a ?TMO followed by data bytes is returned. In that case the data
|
||||
has to be appended to the data buffer. Then a null command with a sensible
|
||||
timeout is sent. If a new timeout comes in on that onew, there is an error.
|
||||
Else the data is appended to the data already read and we are finished.
|
||||
|
||||
It has been choosen to implement this logic separatly from the serialsinq
|
||||
stuff as it interacts very much with rest of SICS.
|
||||
|
||||
Just one function is exported:
|
||||
\begin{flushleft} \small
|
||||
\begin{minipage}{\linewidth} \label{scrap1}
|
||||
\verb@"serialwait.h"@ {\footnotesize ? }$\equiv$
|
||||
\vspace{-1ex}
|
||||
\begin{list}{}{} \item
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@/*--------------------------------------------------------------------------@\\
|
||||
\mbox{}\verb@ S E R I A L W A I T@\\
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@ Executes a command on a serial port and waits for replies coming@\\
|
||||
\mbox{}\verb@ along by polling with null commands.@\\
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@ copyright: see copyright.h@\\
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@ Mark Koennecke, June 1998@\\
|
||||
\mbox{}\verb@---------------------------------------------------------------------------*/@\\
|
||||
\mbox{}\verb@#ifndef SERIALSICSWAIT@\\
|
||||
\mbox{}\verb@#define SERIALSICSWAIT@\\
|
||||
\mbox{}\verb@#include "sics.h"@\\
|
||||
\mbox{}\verb@#include "hardsup/serialsinq.h"@\\
|
||||
\mbox{}\verb@ int SerialSicsExecute(void **pData, char *pCommand, char *pReply, @\\
|
||||
\mbox{}\verb@ int iBufLen);@\\
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@#endif@\\
|
||||
\mbox{}\verb@@$\diamond$
|
||||
\end{list}
|
||||
\vspace{-2ex}
|
||||
\end{minipage}\\[4ex]
|
||||
\end{flushleft}
|
||||
Parameters and return values are the same as defined for the
|
||||
SerialWriteRead function.
|
||||
|
||||
I am not sure if this facility works as expected. I think there was a
|
||||
problem with crosstalk on the serial line.
|
||||
|
||||
22
doc/programmer/servlog.tex
Normal file
22
doc/programmer/servlog.tex
Normal file
@@ -0,0 +1,22 @@
|
||||
\subsection{The Server Logfile}
|
||||
The SIVS server maintains a server log file. In this log file, all commands
|
||||
and answers are written as well as diagnostic messages from all parts of the
|
||||
system.In order to prevent the log files from growing to endless sizes they
|
||||
are limited in length. When one file is finished the next file is written.
|
||||
This happend for a predefined number of files. Then the first file is
|
||||
reused. This scheme is configured by defines in servlog.c.
|
||||
|
||||
The interface to this module is simple:
|
||||
\begin{description}
|
||||
\item[void SICSLogWrite(char *ptext, OutCode eOut )] writes text with
|
||||
outcode eOut to the server log. The outcodes are the same as used for
|
||||
outpout through SCWrite in conman.h.
|
||||
\item[int LogCapture(SConnection *pCon, SicsInterp *pInter, void *pData,
|
||||
int argc, char *argv[])]
|
||||
Wrapper function which allows the connection pCon to redirect output to the
|
||||
server log file to its socket. For details see the user documentation.
|
||||
\item[int KillCapture(SConnection *pCon)] This function is automatically
|
||||
called when a connection object dies. It releases all LogCapture entries for
|
||||
the connection.
|
||||
\end{description}
|
||||
|
||||
8
doc/programmer/sicsexit.tex
Normal file
8
doc/programmer/sicsexit.tex
Normal file
@@ -0,0 +1,8 @@
|
||||
\subsection{SicsExit}
|
||||
For closing down the SICS server properly.
|
||||
\begin{verbatim}
|
||||
int SicsExit(SConnection *pCon,SicsInterp *pInterp, void *pData, int argc,
|
||||
char *argv[]);
|
||||
\end{verbatim}
|
||||
Just the object wrapper function implementing the command. Does so by
|
||||
sending a signal to all tasks in the task loop.
|
||||
107
doc/programmer/sinqhmdriv.tex
Normal file
107
doc/programmer/sinqhmdriv.tex
Normal file
@@ -0,0 +1,107 @@
|
||||
\subsubsection{SINQ Histogram memory}
|
||||
This is a driver for the SINQ developed histogram memory. This HM can
|
||||
operate in normal, TOF and stroboscopic mode. All the real time processing
|
||||
for this HM is done by an on-board computer in a VME crate. This on board
|
||||
computer also runs TCP/IP and a server program which allows for
|
||||
configuration and communication with the HM. A tricky bit is, that
|
||||
configuration and communication operate differently. For configuration an
|
||||
connection to the main server is installed which handles the configuration
|
||||
requests. For starting data collection and retrieval of information a second
|
||||
connection is needed. This is obtained by sending a request to the main
|
||||
server on the on board computer. This main server will than spawn a second
|
||||
process on the on board computer which is dedicated to serving our requests.
|
||||
The mainserver sends a packet containing the new port number our secondary
|
||||
server is listening to. Than the driver can connect to this secondary server
|
||||
in order to exchange data. More details on this scheme can be found in the
|
||||
manual for the SINQ-histogram memory. A further complication arises from the
|
||||
fact that the actual counting control, such as monitor handling, starting
|
||||
and stopping etc. is handled via a EL737 counter box, which needs to be kept
|
||||
track off as well. All this results in a rather complicated driver. This is
|
||||
already reflected by the driver private data structure:
|
||||
|
||||
\begin{flushleft} \small
|
||||
\begin{minipage}{\linewidth} \label{scrap1}
|
||||
$\langle$SQType {\footnotesize ?}$\rangle\equiv$
|
||||
\vspace{-1ex}
|
||||
\begin{list}{}{} \item
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@ typedef struct __SinqHMDriv {@\\
|
||||
\mbox{}\verb@ pCounter pCounter;@\\
|
||||
\mbox{}\verb@ pSINQHM pMaster;@\\
|
||||
\mbox{}\verb@ int iLastHMError;@\\
|
||||
\mbox{}\verb@ int iLastCTError;@\\
|
||||
\mbox{}\verb@ } SinqHMDriv;@\\
|
||||
\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}
|
||||
pCounter is a pointer to the EL737 counter box to use for count control.
|
||||
pMaster is an internal data structure for the interface functions to the
|
||||
SINQ histogram memory. iLastHMError keeps the last histogram memory error,
|
||||
iLasyCTError is set to 1 when a counter error happened. This is necessary to
|
||||
implement the GetError function.
|
||||
|
||||
Please note that this driver needs some options in the histogram memories
|
||||
database:
|
||||
\begin{itemize}
|
||||
\item Control must have as value a configured EL737 counter box.
|
||||
\item HMComputer is the name of the histogram memory computer.
|
||||
\item HMPort is the port on which the histogram memory computer listens for
|
||||
requests.
|
||||
\end{itemize}
|
||||
|
||||
The driver implements all the functions specified in the driver interface.
|
||||
Please note that these contain functions for the deletion of driver private
|
||||
data structures which will be automatically called form DeleteHistDriver.
|
||||
Therefore the only function to define is CreateSINQDriver which sets things
|
||||
up.
|
||||
|
||||
\begin{flushleft} \small
|
||||
\begin{minipage}{\linewidth} \label{scrap2}
|
||||
$\langle$Protos {\footnotesize ?}$\rangle\equiv$
|
||||
\vspace{-1ex}
|
||||
\begin{list}{}{} \item
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@ pHistDriver CreateSINQDriver(pStringDict pOption);@\\
|
||||
\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}
|
||||
\begin{flushleft} \small
|
||||
\begin{minipage}{\linewidth} \label{scrap3}
|
||||
\verb@"sinqhmdriv.i"@ {\footnotesize ? }$\equiv$
|
||||
\vspace{-1ex}
|
||||
\begin{list}{}{} \item
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@/*--------------------------------------------------------------------------@\\
|
||||
\mbox{}\verb@ S I N Q H M @\\
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@ A driver for the SINQ histogram memory.@\\
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@ Mark Koennecke, April 1997@\\
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@ copyright: see implementation file@\\
|
||||
\mbox{}\verb@----------------------------------------------------------------------------*/@\\
|
||||
\mbox{}\verb@#ifndef SINQHMDRIVER@\\
|
||||
\mbox{}\verb@#define SINQHMDRIVER@\\
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@@$\langle$SQType {\footnotesize ?}$\rangle$\verb@@\\
|
||||
\mbox{}\verb@/*-------------------------------------------------------------------------*/@\\
|
||||
\mbox{}\verb@@$\langle$Protos {\footnotesize ?}$\rangle$\verb@@\\
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@#endif@\\
|
||||
\mbox{}\verb@@$\diamond$
|
||||
\end{list}
|
||||
\vspace{-2ex}
|
||||
\end{minipage}\\[4ex]
|
||||
\end{flushleft}
|
||||
40
doc/programmer/splitter.tex
Normal file
40
doc/programmer/splitter.tex
Normal file
@@ -0,0 +1,40 @@
|
||||
\subsection{The Splitter-Tokenizer}
|
||||
SICS needs some command interpretation for its job. In order to facilitate this a few functions have been devised which decompose a line into its words and figures out if the words are text or numerical values. The words are than put into an ordered linked list which can be scanned by client programs. The interface:
|
||||
|
||||
|
||||
\begin{verbatim}
|
||||
typedef enum {eText, eInt, eFloat, eUndefined } eType;
|
||||
\end{verbatim}
|
||||
The Types a word can have.
|
||||
|
||||
|
||||
\begin{verbatim}
|
||||
typedef struct _TokenEntry {
|
||||
eType Type;
|
||||
char *text;
|
||||
long iVal;
|
||||
float fVal;
|
||||
struct _TokenEntry *pNext;
|
||||
struct _TokenEntry *pPrevious;
|
||||
} TokenList;
|
||||
\end{verbatim}
|
||||
This is the data structure available for each word. This is kept in a doubly linked list as SICS might require to splice a parameter into a given command (i.e a pointer to a connection class).
|
||||
|
||||
|
||||
The interface functions:\begin{itemize}
|
||||
\item {\bf TokenList *SplitText(char *pLine) }, splits a given text into words. Returns a pointer to the head of the list on success, NULL on failure.
|
||||
\item {\bf TokenList *SplitArguments(int argc, char *argv) }, does the same as above for a argc, argv type pairs.
|
||||
\item {\bf Text2Arg(char *text, int argc, cahr *argv) } decomposes a text string into argc, argv paisr as used in command invocation.
|
||||
\item {\bf void DeleteTokenList(TokenList *pList) }. A client uses this
|
||||
to remove the word list when it is done with it. Omission of this call will result in wasted memory.
|
||||
\item {\bf int Text2Arg(char *line, int *argc, char **argv[])} This call
|
||||
converts the text in line into an argc, argv[] pair. Suitable space in
|
||||
memory will be allocated. It is the callers responsability to free the
|
||||
argv[] array after use.
|
||||
\item {\bf int Arg2Text(int argc, char *argv[], char *buf, int iBufLen)}
|
||||
This call converts an argc, argv[] pair back into a text. Maximum iBufLen
|
||||
characters of result will be copied to buf.
|
||||
\item {\bf int GetShellLine(FILE *fd, char *buf, int iBufLen);} reads a line
|
||||
from file fd. Thereby ignoring lines starting with \verb+#+.
|
||||
\end{itemize}
|
||||
|
||||
198
doc/programmer/sps.tex
Normal file
198
doc/programmer/sps.tex
Normal file
@@ -0,0 +1,198 @@
|
||||
\subsection{SPS Controllers}
|
||||
This module is very specific to SINQ. At SINQ there are Siemens SPS
|
||||
controllers which are used to put beam components in, lift air cushions etc.
|
||||
Essentially these are push button devices. There exists a protocoll for
|
||||
pushing buttons through a RS--232 interface. This protocoll is described
|
||||
elsewhere.
|
||||
|
||||
These obscure SPS devices support three types of functionalities:
|
||||
\begin{itemize}
|
||||
\item Bits may be flipped. This correcponds to pushing a button. There are
|
||||
12b bytes of those with 8 bits each.
|
||||
\item Status bits may be read. This allows to figure out if an operation
|
||||
succeeded. 128 status bits are available.
|
||||
\item Furthermore this thing has up to 8 ADC inputs. These can be read as
|
||||
well.
|
||||
\end{itemize}
|
||||
This module implements a means to communicate with SPS devices. It will
|
||||
support the three functionalities in the list above. This is more a module
|
||||
providing a basic functionality. In practice this will and should be wrapped
|
||||
into Tcl wrapper functions. This is the best solution because bit
|
||||
assignements vary between instruments and tend to change all the time. Or at
|
||||
least seem to, as the electricians don't talk to us. As this is no general
|
||||
device the usual SICS division between hardware object and hardware driver
|
||||
will not be upheld.
|
||||
|
||||
There is a problem with pushing buttons. Not all buttons may be pushed
|
||||
remotely, for instance it may not be permitted to operate the beam shutter
|
||||
remotely. Not all of the bits in the SPS actually correspond to a pressable
|
||||
button but are set as consequence of a pushed button. In order to run all
|
||||
this a permission list must be configured for each SPS controller. This list
|
||||
holds the adress of the bit and the privelege required to operate this
|
||||
button. If a bit is not in the list permission is automatically not given to
|
||||
operate it. Each entry in this permission list looks like this:
|
||||
|
||||
\begin{flushleft} \small
|
||||
\begin{minipage}{\linewidth} \label{scrap1}
|
||||
$\langle$permlist {\footnotesize ?}$\rangle\equiv$
|
||||
\vspace{-1ex}
|
||||
\begin{list}{}{} \item
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@ typedef struct {@\\
|
||||
\mbox{}\verb@ int iByte;@\\
|
||||
\mbox{}\verb@ int iBit;@\\
|
||||
\mbox{}\verb@ int iPrivilege;@\\
|
||||
\mbox{}\verb@ }Permission, *pPermission;@\\
|
||||
\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 fields are: the byte we refer to, the bit in the byte and the Privilege
|
||||
required to operate this switch. Entries of this kind will be held in a
|
||||
standard linked list.
|
||||
|
||||
|
||||
|
||||
In order to run the SPS, the following data strucure is required:
|
||||
|
||||
\begin{flushleft} \small
|
||||
\begin{minipage}{\linewidth} \label{scrap2}
|
||||
$\langle$spsdata {\footnotesize ?}$\rangle\equiv$
|
||||
\vspace{-1ex}
|
||||
\begin{list}{}{} \item
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@ typedef struct __SPS {@\\
|
||||
\mbox{}\verb@ pObjectDescriptor pDes;@\\
|
||||
\mbox{}\verb@ int iMode;@\\
|
||||
\mbox{}\verb@ int iLastError;@\\
|
||||
\mbox{}\verb@ char *pHost;@\\
|
||||
\mbox{}\verb@ int iPort;@\\
|
||||
\mbox{}\verb@ int iChannel;@\\
|
||||
\mbox{}\verb@ int lPermissions;@\\
|
||||
\mbox{}\verb@ void *pData;@\\
|
||||
\mbox{}\verb@ } SPS;@\\
|
||||
\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 fields are:
|
||||
\begin{description}
|
||||
\item[pDes] The SICS standard object descriptor.
|
||||
\item[iMode] The SPS can be operated in simulation mode for software
|
||||
testing. This flag denotes that.
|
||||
\item[iLastError] an integer code representing the last error, if any.
|
||||
\item[pHost] The Macintosh computer running the serial port server.
|
||||
\item[iPort] The TCP/IP port number where the Macintosh serial port server
|
||||
is listening.
|
||||
\item[iChannel] The serial port ID to which the SPS controller is connected
|
||||
to.
|
||||
\item[lPermissions] The linked list where the permissions are stored.
|
||||
\item[pData] The private data structure for serial communication with the
|
||||
SPS.
|
||||
\end{description}
|
||||
|
||||
|
||||
The external interface to this module looks like this:
|
||||
|
||||
\begin{flushleft} \small
|
||||
\begin{minipage}{\linewidth} \label{scrap3}
|
||||
$\langle$spshead {\footnotesize ?}$\rangle\equiv$
|
||||
\vspace{-1ex}
|
||||
\begin{list}{}{} \item
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@ typedef struct __SPS *pSPS;@\\
|
||||
\mbox{}\verb@/*-------------------------------------------------------------------------*/@\\
|
||||
\mbox{}\verb@ int SPSSetButton(pSPS self, SConnection *pCon, int iByte, int iBit);@\\
|
||||
\mbox{}\verb@ int SPSGetStatus(pSPS self, int iStatus, int *iSet);@\\
|
||||
\mbox{}\verb@ int SPSGetSANS(pSPS self, float *fVal);@\\
|
||||
\mbox{}\verb@ int SPSGetADC(pSPS self, int iWhich, int *iValue);@\\
|
||||
\mbox{}\verb@ void SPSAddPermission(pSPS self, int iByte, int iBit, int iRight);@\\
|
||||
\mbox{}\verb@/*------------------------------------------------------------------------*/@\\
|
||||
\mbox{}\verb@ int SPSFactory(SConnection *pCon, SicsInterp *pSics, void *pData,@\\
|
||||
\mbox{}\verb@ int argc, char *argv[]);@\\
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@ int SPSAction(SConnection *pCon, SicsInterp *pSics, void *pData,@\\
|
||||
\mbox{}\verb@ int argc, char *argv[]);@\\
|
||||
\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 and their meaning are described below. All function return 1
|
||||
on success and 0 on failure.
|
||||
\begin{description}
|
||||
\item[SPSSetButton] Tries to set the button described by iByte and iBit.
|
||||
pCon is needed to determine user rights associated with the request. Please note that a
|
||||
successful return from this function means that the button has been pressed
|
||||
but not that the SPS has successfully completed the requested action. In
|
||||
order to check for that you have to check the associated status bit.
|
||||
\item[SPSGetStatus] Requests the value of the status bit iStatus. iSet will
|
||||
be set to 1 if the bit is set or 0 if not.
|
||||
\item[SPSGetSANS] is a special function for reading the collimation
|
||||
length from the SANS collimator SPS controller. This requires checking tons
|
||||
of bits. For efficiency this has been put into a separate function.
|
||||
\item[SPSGetADC] requests the value of the ADC channel iWhich. The value is
|
||||
returned in iValue. Please note that this is probably a meaningless integer
|
||||
value which has to be converted to a physically meaningful value.
|
||||
\item[SPSFactory] is the interpreter factory function which will be used to
|
||||
create command in the interpreter representing SPS controllers.
|
||||
\item[SPSAction] implements the actual commands in the SICS interpreter for
|
||||
interacting with the SPS controller.
|
||||
\end{description}
|
||||
|
||||
\begin{flushleft} \small
|
||||
\begin{minipage}{\linewidth} \label{scrap4}
|
||||
\verb@"sps.i"@ {\footnotesize ? }$\equiv$
|
||||
\vspace{-1ex}
|
||||
\begin{list}{}{} \item
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@/*--------------------------------------------------------------------------@\\
|
||||
\mbox{}\verb@ SPS Controller module internal header file. Do not include. Leave @\\
|
||||
\mbox{}\verb@ alone. Is automatically created from another file.@\\
|
||||
\mbox{}\verb@---------------------------------------------------------------------------*/@\\
|
||||
\mbox{}\verb@@$\langle$permlist {\footnotesize ?}$\rangle$\verb@@\\
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@@$\langle$spsdata {\footnotesize ?}$\rangle$\verb@@\\
|
||||
\mbox{}\verb@ @\\
|
||||
\mbox{}\verb@@$\diamond$
|
||||
\end{list}
|
||||
\vspace{-2ex}
|
||||
\end{minipage}\\[4ex]
|
||||
\end{flushleft}
|
||||
\begin{flushleft} \small
|
||||
\begin{minipage}{\linewidth} \label{scrap5}
|
||||
\verb@"sps.h"@ {\footnotesize ? }$\equiv$
|
||||
\vspace{-1ex}
|
||||
\begin{list}{}{} \item
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@/*------------------------------------------------------------------------@\\
|
||||
\mbox{}\verb@ S P S@\\
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@ A module to handle Siemens SPS controllers at SINQ. For more information @\\
|
||||
\mbox{}\verb@ see sps.tex@\\
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@ Mark Koennecke, Juli 1998@\\
|
||||
\mbox{}\verb@----------------------------------------------------------------------------*/@\\
|
||||
\mbox{}\verb@#ifndef SICSSPS@\\
|
||||
\mbox{}\verb@#define SICSSPS@\\
|
||||
\mbox{}\verb@@$\langle$spshead {\footnotesize ?}$\rangle$\verb@@\\
|
||||
\mbox{}\verb@#endif@\\
|
||||
\mbox{}\verb@@$\diamond$
|
||||
\end{list}
|
||||
\vspace{-2ex}
|
||||
\end{minipage}\\[4ex]
|
||||
\end{flushleft}
|
||||
42
doc/programmer/status.tex
Normal file
42
doc/programmer/status.tex
Normal file
@@ -0,0 +1,42 @@
|
||||
\subsection{The Status Object}
|
||||
Again a simple thing which maintains a string describinh what the SICSserver
|
||||
is up to. The codes recognized are:
|
||||
\begin{description}
|
||||
\item[eEager] ready to execute commands.
|
||||
\item[eUserWait] user requested wait.
|
||||
\item[eCounting] counting something.
|
||||
\item[eOutOfBeam] there is no beam.
|
||||
\item[ePaused] paused.
|
||||
\item[eDriving] driving bits around.
|
||||
\item[eRunning] moving somewhere.
|
||||
\item[eScanning] doing a scan.
|
||||
\item[eBatch] processing a batch file.
|
||||
\item[eHalted] halt has been called, not used.
|
||||
\item[eDead] server is dead, not used.
|
||||
\item[eInput] waiting for user input in prompting mode.
|
||||
\end{description}
|
||||
|
||||
Status can be interfaced with:
|
||||
\begin{description}
|
||||
\item[void SetStatus(Status eNew)] sets a new status.
|
||||
\item[int SetStatusFromText(char *text)] sets a new status from text.
|
||||
\item[void KillStatus(void *pData)] deletes status data structures. Status
|
||||
can have callbacks associated with it, these need to be remved by this
|
||||
function.
|
||||
\item[Status GetStatus(void)] retrives the current status.
|
||||
\item[void GetStatusText(char *buf, int iBufLen)] retrieves the status as text.
|
||||
\item[int UserStatus(SConnection *pCon, SicsInterp *pSics, void *pData,\\
|
||||
int argc, char *argv[])] The object wrapper function for
|
||||
the status object.
|
||||
\item[int ResetStatus(SConnection *pCon, SicsInterp *pSics, void *pData,\\
|
||||
int argc, char *argv[])] The wrapper function
|
||||
implementing the reset command.
|
||||
\item[int BackupStatus(SConnection *pCon, SicsInterp *pSics, void *pData,\\
|
||||
int argc, char *argv[])] is the object wrapper function
|
||||
implementing the backup command which saves the server status into a file.
|
||||
This is all of the server. This function does not really belong here.
|
||||
\item[int RestoreStatus(SConnection *pCon, SicsInterp *pSics, void *pData,\\
|
||||
int argc, char *argv[])] complement to BackupStatus. Reads
|
||||
SICS server status back from file.
|
||||
\end{description}
|
||||
|
||||
91
doc/programmer/stringdict.tex
Normal file
91
doc/programmer/stringdict.tex
Normal file
@@ -0,0 +1,91 @@
|
||||
\subsection{Dictionary}
|
||||
This is just a simple implementation of an dictionary of name value strings
|
||||
on top of the LLD linked list package. It is needed in the histogram memory
|
||||
module and several other places. This module provides the following functions:
|
||||
|
||||
\begin{flushleft} \small
|
||||
\begin{minipage}{\linewidth} \label{scrap1}
|
||||
$\langle$Protos {\footnotesize ?}$\rangle\equiv$
|
||||
\vspace{-1ex}
|
||||
\begin{list}{}{} \item
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@ pStringDict CreateStringDict(void);@\\
|
||||
\mbox{}\verb@ void DeleteStringDict(pStringDict self);@\\
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@ int StringDictAddPair(pStringDict self, char *name, char *value);@\\
|
||||
\mbox{}\verb@ int StringDictExists(pStringDict self, char *name);@\\
|
||||
\mbox{}\verb@ int StringDictUpdate(pStringDict self, char *name, char *value);@\\
|
||||
\mbox{}\verb@ int StringDictGet(pStringDict self, char *name, char *pResult, int iLen);@\\
|
||||
\mbox{}\verb@ int StringDictGetAsNumber(pStringDict self, char *name, float *fVal);@\\
|
||||
\mbox{}\verb@ int StringDictDelete(pStringDict self, char *name);@\\
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@ const char *StringDictGetNext(pStringDict self, @\\
|
||||
\mbox{}\verb@ char *pValue, int iValLen);@\\
|
||||
\mbox{}\verb@ void StringDictKillScan(pStringDict self);@\\
|
||||
\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}
|
||||
As usual, all function return 1 on success, 0 if there is a problem.
|
||||
|
||||
CreateStringDict creates and initialises a new string dictionanry.
|
||||
|
||||
DeleteStringDict deletes the whole dictionary and all ist values from
|
||||
memory. self will point to rubbish afterwards.
|
||||
|
||||
StringDictAddPair adds a new name value pair to the dictionary.
|
||||
|
||||
StringDictExists test for the existence of name in the Dictionary.
|
||||
|
||||
StringDictUpdate replaces the value for name with the new one specified.
|
||||
|
||||
StringDictGet copies the value for name into the string pResult, but maximum
|
||||
iLen characters. If pResult is NULL, this function returns the length of the
|
||||
value string.
|
||||
|
||||
StringDictDelete deletes the entry for name from the dictionary.
|
||||
|
||||
StringDictGetNext implements a scan through the whole dictionary. It returns
|
||||
a pointer to the current key or NULL if the dictionary is exhausted.
|
||||
Maximum iValLen characters of value information will be copied into pValue.
|
||||
NEVER, ever delete the pointer passed from StringDictGetNext. A core dump
|
||||
will be your reward. Please note, that each call to the usual search
|
||||
functions will mess up a dictionary traversal.
|
||||
|
||||
StringDictKillScan clears the scan flag in a way that a new one is done
|
||||
with the next call to StringDictGetNext.
|
||||
|
||||
\begin{flushleft} \small
|
||||
\begin{minipage}{\linewidth} \label{scrap2}
|
||||
\verb@"stringdict.h"@ {\footnotesize ? }$\equiv$
|
||||
\vspace{-1ex}
|
||||
\begin{list}{}{} \item
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@/*--------------------------------------------------------------------------@\\
|
||||
\mbox{}\verb@ S T R I N G D I C T@\\
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@ A module which implements a general purpose string dictionary.@\\
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@ copyright: see implementation file@\\
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@ Mark Koennecke, April 1997@\\
|
||||
\mbox{}\verb@---------------------------------------------------------------------------*/@\\
|
||||
\mbox{}\verb@#ifndef SICSSTRINGDICT@\\
|
||||
\mbox{}\verb@#define SICSSTRINGDICT@\\
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@ typedef struct __StringDict *pStringDict;@\\
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@@$\langle$Protos {\footnotesize ?}$\rangle$\verb@@\\
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@#endif@\\
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@@$\diamond$
|
||||
\end{list}
|
||||
\vspace{-2ex}
|
||||
\end{minipage}\\[4ex]
|
||||
\end{flushleft}
|
||||
135
doc/programmer/task.tex
Normal file
135
doc/programmer/task.tex
Normal file
@@ -0,0 +1,135 @@
|
||||
|
||||
\subsection{The Task Switcher}
|
||||
This is a portable task switching module. It effectively implments a form of
|
||||
cooperative multitasking. A task in this context is a function of type
|
||||
TaskFunc which defines the task. The task function looks like this: \\
|
||||
\centerline{int (*TaskFunc)(void *pData)}\\
|
||||
pData is a pointer to a user defined data structure which should contain the
|
||||
data the task is going to need in order to do its job. This function returns
|
||||
1 if it shall continue, or 0 if it is finally ended and should be deleted from
|
||||
the list of tasks. Please note, that the whole task switcher is blocked when
|
||||
a task executes a very lengthy operation. In such cases a task function
|
||||
should call either TaksWait or TaskYield at apropriate
|
||||
places in the code in order to give other tasks a chance to execute.
|
||||
|
||||
This module now keeps a list of such tasks and calls the task functions one
|
||||
after another. Actually, the tasks are kept in a special data structure in a
|
||||
doubly linked list. When the end of this list has been reached, the code
|
||||
jumps to the list head automatically. The data structure for each task looks
|
||||
like this:
|
||||
\begin{verbatim}
|
||||
typedef struct __TaskHead {
|
||||
long lID;
|
||||
int iStatus;
|
||||
long lWait;
|
||||
TaskFunc pRun;
|
||||
SignalFunc pSignal;
|
||||
void *pData;
|
||||
TaskKillFunc pKill;
|
||||
pTaskHead pNext;
|
||||
pTaskHead pPrevious;
|
||||
} TaskHead;
|
||||
|
||||
\end{verbatim}
|
||||
The fields have the following meanings: \begin{description}
|
||||
\item[lID] A unique task ID.
|
||||
\item[iStatus] is a status flag. A task can be READY or WAITING for another task
|
||||
to finish.
|
||||
\item[lWait] If the task is in wait state, lWait denotes the task ID to wait
|
||||
for.
|
||||
\item[pRun] is the tasks task function.
|
||||
\item[pSignal] is the tasks signal function. This implements some form of
|
||||
inter task communication. A signal function looks like this:\\
|
||||
\centerline{typedef void (*SignalFunc)(void *pUser,int iSignal, void
|
||||
*pSigData);}\\
|
||||
pUser is a pointer to the task data structure, iSignal is the ID of a signal
|
||||
sent. It is the applications job to define these signal codes. pSigData is a
|
||||
pointer to a signal data structure. Again it is the applications job to
|
||||
define this data structure for each signal.
|
||||
\item[pData] is the tasks data structure. It will be passed into each call
|
||||
to the task and signal function.
|
||||
\item[pKill] is a pointer to a function capable of deleting the task data
|
||||
structure. This function will be automatically called when the task ends.
|
||||
\item[pNext, pPrevious] are pointers which maintain the doubly linked list
|
||||
of tasks.
|
||||
\end{description}
|
||||
|
||||
|
||||
The other data structure used in the task switching module is the task
|
||||
managers data structure. It looks like this:
|
||||
\begin{verbatim}
|
||||
typedef struct __TaskMan {
|
||||
int iID;
|
||||
int iStop;
|
||||
pTaskHead pCurrent;
|
||||
pTaskHead pHead;
|
||||
} TaskMan;
|
||||
|
||||
\end{verbatim}
|
||||
The fields:
|
||||
\begin{description}
|
||||
\item[iID] a ID to characterize the task manager data structure. Will be
|
||||
used to test if this structure has been corrupted or the user passed in
|
||||
some shit.
|
||||
\item[iStop] is used for stopping the task switcher.
|
||||
\item[pCurrent] denotes the current task executing.
|
||||
\item[pHead] define the head of the task list.
|
||||
\end{description}
|
||||
|
||||
In order to use this module it is needed to provide these items for each
|
||||
task:\begin{itemize}
|
||||
\item A task data structure.
|
||||
\item A data structure removal function if applicable.
|
||||
\item A task function.
|
||||
\item A signal function, if the task is going to react on signals.
|
||||
\end{itemize}
|
||||
|
||||
Interaction with the task switching module happens through the functions
|
||||
defined below. All functions return 0 on failure and 1 on success if not
|
||||
sated otherwise. For encapsulation, the following pointers are defined:
|
||||
\begin{verbatim}
|
||||
typedef struct __TaskHead *pTaskHead;
|
||||
typedef struct __TaskMan *pTaskMan;
|
||||
\end{verbatim}
|
||||
\begin{description}
|
||||
\item[int TaskerInit(pTaskMan *self)]
|
||||
Initalises a Task Manager.
|
||||
\item[int TaskerDelete(pTaskMan *self)]
|
||||
Stops all running tasks and clears all data structures associated with
|
||||
tasks and the TaskManager.
|
||||
\item[long TaskRegister(pTaskMan self, TaskFunc pTaskRun,
|
||||
SignalFunc pSignalFunc, \\
|
||||
TaskKillFunc pKillFunc,
|
||||
void *pData,
|
||||
int iPriority)]
|
||||
This call enter a new task into the system. The caller has to
|
||||
specify:
|
||||
\begin{itemize}
|
||||
\item a TaskFunction [Required]
|
||||
\item a SignalFunction [Optional, can be NULL]
|
||||
\item a KillFunction for task private data.
|
||||
[Optional, can be NULL]
|
||||
\item a pointer to task private data
|
||||
[Optional, can be NULL]
|
||||
\item a priority for this task. This is currently unused.
|
||||
\end{itemize}
|
||||
On Success a positive value denoting the ID of the task is returned.
|
||||
On error a negative value is returned.
|
||||
\item[int TaskSchedule(pTaskMan self)]
|
||||
Starts task switching.
|
||||
\item[int TaskStop(pTaskMan self)]
|
||||
Interrupts task switching all together
|
||||
\item[int TaskContinue(pTaskMan self)]
|
||||
Continues an task switching session interrupted by TaskStop. After this
|
||||
the apopriate TaskYield, TaskSchedule or whatever has to be called.
|
||||
\item[int TaskWait(pTaskMan self, long lID)]
|
||||
Waits until the task specified by lID has finished. lID is obtained from
|
||||
a call to TaskRegister.
|
||||
\item[int TaskYield(pTaskman self)] does one cycle through the main loop.
|
||||
Should be called by tasks performing lengthy operations now and then in
|
||||
order to allow other tasks to execute. This is not yet implemented.
|
||||
\item[int TaskSignal(pTaskMan self, int iSignal, void *pSigData)]
|
||||
Invokes each Task's signal function with parameters iSignal and
|
||||
pSigData.
|
||||
\end{description}
|
||||
|
||||
169
doc/programmer/tclev.tex
Normal file
169
doc/programmer/tclev.tex
Normal file
@@ -0,0 +1,169 @@
|
||||
\subsubsection{The Tcl Environment Driver}
|
||||
Sometimes a quick way for defining an environment
|
||||
device driver is needed. A suitable way for doing this
|
||||
is to define the device driver in the SICS servers Tcl macro language. Then
|
||||
a device driver can even be developed and tested offline from a psish before
|
||||
inclusion in the server. Clearly a means of communication between SICs and
|
||||
the actual device is needed. Usually this communication happens via
|
||||
a RS--232 serial port. Such a communication is catered for by the SICS
|
||||
serialport command. This section describes the environment device driver
|
||||
which links the SICS C code with Tcl. For each of the device drivers
|
||||
functions a C language wrapper function is provided, which in turn calls
|
||||
the Tcl interpreter with some parameters. This scheme is initialised by
|
||||
providing the Tcl environment device driver with the name of a Tcl array
|
||||
which has to hold Tcl implementations for all the necessary driver functions.
|
||||
The name of this array will also be passed to each of the Tcl procedures as
|
||||
first parameter. The Tcl procedures to define for a Tcl driver are:
|
||||
\begin{description}
|
||||
\item[Init] to be called at initialisation of the driver. This Tcl procedure must connect
|
||||
to the device and prepare it for accepting further commands. The parameters to
|
||||
init are all the parameters still left in the command line after the name
|
||||
of the Tcl array in the EVFactory command line.
|
||||
\item[Close] should close down the connection to the device after bringing the
|
||||
device into a clean state.
|
||||
\item[SetValue] will be called with a float value as second parameter. It
|
||||
should issue a command to set the device to a new value. The return value is an
|
||||
integer error code, defined by the driver. Error returns use the normal Tcl mechanism
|
||||
with the Tcl error command. On errors a negative error code defined by the driver
|
||||
must be returned.
|
||||
\item[GetValue] reads the current value from the device. The return value is
|
||||
either the floating point value of the current control variable or the
|
||||
string pending if the request is still pending. In case of failure an error
|
||||
is returned with a negative integer error code.
|
||||
\item[Send] should concatenate all parameters and send them down to the
|
||||
device. Returns error codes as described above.
|
||||
\item[GetError] gets as a parameter the negative error code possibly returned
|
||||
from one of the calls above. GetError should return a textual description
|
||||
of the error.
|
||||
\item[TryFixIt] gets as a parameter a negative error code as returned from one
|
||||
of the calls described above. TryFixIt should do everything possible in
|
||||
software to get the device working again: perhaps send some commands,
|
||||
reopen the connection or whatever apropriate. Depending on the success
|
||||
of this TryFixIt returns either DEVREDO if the command shall be resend or
|
||||
DEVFAIL if the problem cannot be fixed without human intervention.
|
||||
\item[Wrapper] This function will will be called by the environment variable
|
||||
interpreter wrapper function before the general part of the wrapper
|
||||
function gets executed. Its purpose is the handling of subcommands special
|
||||
to the specific environment device. For instance modifying its mode of
|
||||
operation or setting special variables not covered in the general
|
||||
environment device setup. It has to return 1 on success, 0 on failure. On
|
||||
failure it has to print error messages as well.
|
||||
\end{description}
|
||||
|
||||
In order to do all this a new driver must be defined. This driver needs the
|
||||
following data structure:
|
||||
|
||||
\begin{flushleft} \small
|
||||
\begin{minipage}{\linewidth} \label{scrap1}
|
||||
$\langle$tclevdat {\footnotesize ?}$\rangle\equiv$
|
||||
\vspace{-1ex}
|
||||
\begin{list}{}{} \item
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@ typedef struct __TclEv {@\\
|
||||
\mbox{}\verb@ char *pArray;@\\
|
||||
\mbox{}\verb@ char *pInit;@\\
|
||||
\mbox{}\verb@ char *pClose;@\\
|
||||
\mbox{}\verb@ char *pSetValue;@\\
|
||||
\mbox{}\verb@ char *pGetValue;@\\
|
||||
\mbox{}\verb@ char *pSend;@\\
|
||||
\mbox{}\verb@ char *pGetError;@\\
|
||||
\mbox{}\verb@ char *pTryFixIt;@\\
|
||||
\mbox{}\verb@ char *pWrapper;@\\
|
||||
\mbox{}\verb@ char *pName;@\\
|
||||
\mbox{}\verb@ Tcl_Interp *pTcl;@\\
|
||||
\mbox{}\verb@ int iLastError;@\\
|
||||
\mbox{}\verb@ } TclEv, *pTclEv;@\\
|
||||
\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 fields correspond to the names of the Tcl functions to call for each of the
|
||||
functions specified above. Plus the name of a Tcl array used for storing
|
||||
driver special data in Tcl. iLastError will be used to keep the last error code.
|
||||
pName is the name of the device in SICS. This will be copied into the
|
||||
Tcl-array describing the device as MyName. May be used to set general
|
||||
evcontroller parameters from within driver code and for error messages.
|
||||
|
||||
SICS sees this driver through the following interface:
|
||||
\begin{flushleft} \small
|
||||
\begin{minipage}{\linewidth} \label{scrap2}
|
||||
$\langle$tclevint {\footnotesize ?}$\rangle\equiv$
|
||||
\vspace{-1ex}
|
||||
\begin{list}{}{} \item
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@ pEVDriver CreateTclDriver(int argc, char *argv[],char *pName, SConnection *pCon);@\\
|
||||
\mbox{}\verb@ int UpdateTclVariable(pEVDriver self, char *name, float fVal);@\\
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@ int TclEnvironmentWrapper(SConnection *pCon, SicsInterp *pSics, @\\
|
||||
\mbox{}\verb@ void *pData, int argc, char *argv[]);@\\
|
||||
\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}
|
||||
\begin{description}
|
||||
\item[CreateTclDriver] creates the Tcl driver and initialises it.
|
||||
\item[UpdateTclVariable] will be called from the general environment
|
||||
variable parameter update code in order to allow updating of Tcl variables
|
||||
as well.
|
||||
\item[TclEnvironmentWrapper] is the interpreter wrapper function for a Tcl
|
||||
driver.
|
||||
\end{description}
|
||||
|
||||
\begin{flushleft} \small
|
||||
\begin{minipage}{\linewidth} \label{scrap3}
|
||||
\verb@"tclev.h"@ {\footnotesize ? }$\equiv$
|
||||
\vspace{-1ex}
|
||||
\begin{list}{}{} \item
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@/*---------------------------------------------------------------------------@\\
|
||||
\mbox{}\verb@ T C L E N V I R O N M E N T@\\
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@ This is the header file for an environment device driver defined in @\\
|
||||
\mbox{}\verb@ the Tcl macro language. Dor more details see tclev.tex@\\
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@ copyright: see copyright.h@\\
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@ Mark Koennecke, February 1998@\\
|
||||
\mbox{}\verb@------------------------------------------------------------------------------*/@\\
|
||||
\mbox{}\verb@#ifndef SICSTCLEV@\\
|
||||
\mbox{}\verb@#define SICSTCLEV@\\
|
||||
\mbox{}\verb@ @\\
|
||||
\mbox{}\verb@@$\langle$tclevint {\footnotesize ?}$\rangle$\verb@ @\\
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@#endif@\\
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@@$\diamond$
|
||||
\end{list}
|
||||
\vspace{-2ex}
|
||||
\end{minipage}\\[4ex]
|
||||
\end{flushleft}
|
||||
\begin{flushleft} \small
|
||||
\begin{minipage}{\linewidth} \label{scrap4}
|
||||
\verb@"tclev.i"@ {\footnotesize ? }$\equiv$
|
||||
\vspace{-1ex}
|
||||
\begin{list}{}{} \item
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@/*---------------------------------------------------------------------------@\\
|
||||
\mbox{}\verb@ Tcl environment device driver data structure definition file. @\\
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@ No general usable header file.@\\
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@ Mark Koenencke, February 1998@\\
|
||||
\mbox{}\verb@----------------------------------------------------------------------------*/@\\
|
||||
\mbox{}\verb@@$\langle$tclevdat {\footnotesize ?}$\rangle$\verb@@\\
|
||||
\mbox{}\verb@@$\diamond$
|
||||
\end{list}
|
||||
\vspace{-2ex}
|
||||
\end{minipage}\\[4ex]
|
||||
\end{flushleft}
|
||||
108
doc/programmer/telnet.tex
Normal file
108
doc/programmer/telnet.tex
Normal file
@@ -0,0 +1,108 @@
|
||||
\subsection{SICS Telnet Connection}
|
||||
SICS support communication through the standard TCP/IP telnet protocoll as
|
||||
described in RFC-854. SICS implements telnet in the most primitive way: i.e.
|
||||
no options are supported. In a later stage binary data transfer and
|
||||
authentication options may be supported. But not in its first
|
||||
implementation. After a telnet connection has been accepted a SICS task is
|
||||
installed. In the first stage this task will answer any commands with a
|
||||
'Fuck--off' message. Only if a special login command is given, the
|
||||
connection will be verified and finally opened for commands or rejected.
|
||||
If no login command has been sent within a reasonable intervall of time the
|
||||
connection will be closed as well. This logic is implemented into a special
|
||||
task function associated with a telnet connection. The rest of the telnet
|
||||
logic is so tightly integrated with the network reading, that it has to live
|
||||
in the network reader module. This section describes the special task
|
||||
function and its associated data structure.
|
||||
|
||||
\begin{flushleft} \small
|
||||
\begin{minipage}{\linewidth} \label{scrap1}
|
||||
$\langle$teldat {\footnotesize ?}$\rangle\equiv$
|
||||
\vspace{-1ex}
|
||||
\begin{list}{}{} \item
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@ typdef struct __TelTask {@\\
|
||||
\mbox{}\verb@ SConnection *pCon;@\\
|
||||
\mbox{}\verb@ int iLogin;@\\
|
||||
\mbox{}\verb@ char pLoginWord[132];@\\
|
||||
\mbox{}\verb@ time_t tStart;@\\
|
||||
\mbox{}\verb@ } TelTask;@\\
|
||||
\mbox{}\verb@@$\diamond$
|
||||
\end{list}
|
||||
\vspace{-1ex}
|
||||
\footnotesize\addtolength{\baselineskip}{-1ex}
|
||||
\begin{list}{}{\setlength{\itemsep}{-\parsep}\setlength{\itemindent}{-\leftmargin}}
|
||||
\item Macro never referenced.
|
||||
\end{list}
|
||||
\end{minipage}\\[4ex]
|
||||
\end{flushleft}
|
||||
The fields are: \begin{description}
|
||||
\item[pCon] The connection object to act upon.
|
||||
\item[iLogin] If the connection is logged in or not.
|
||||
\item[pLoginWord] The login word to use. This word will be set as a SICS
|
||||
server option.
|
||||
\item[tStart] The start time of the telnet connection. Used to check for
|
||||
timeout on the connection.
|
||||
\end{description}
|
||||
|
||||
The interface to this module looks like this:
|
||||
\begin{flushleft} \small
|
||||
\begin{minipage}{\linewidth} \label{scrap2}
|
||||
$\langle$telint {\footnotesize ?}$\rangle\equiv$
|
||||
\vspace{-1ex}
|
||||
\begin{list}{}{} \item
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@ typedef struct __TelTask *pTelTask;@\\
|
||||
\mbox{}\verb@/*--------------------------------------------------------------------------*/@\\
|
||||
\mbox{}\verb@ pTelTask CreateTelnet(SConnection *pCon);@\\
|
||||
\mbox{}\verb@ void DeleteTelnet(void *pData);@\\
|
||||
\mbox{}\verb@/*---------------------------------------------------------------------------*/@\\
|
||||
\mbox{}\verb@ int TelnetTask(void *pData);@\\
|
||||
\mbox{}\verb@ void TelnetSignal(void *pData, int iSignal, void *pSigData);@\\
|
||||
\mbox{}\verb@/*--------------------------------------------------------------------------*/@\\
|
||||
\mbox{}\verb@ void InstallTelnet(void);@\\
|
||||
\mbox{}\verb@ void KillTelnet(void);@\\
|
||||
\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}
|
||||
\begin{description}
|
||||
\item[CreateTelnet] creates a new telnet task object. Returns NULL on
|
||||
failure, else apointer to a new data structure.
|
||||
\item[DeleteTelnet] The deletion function for a telnet task.
|
||||
\item[TelnetTask] The telnet task function.
|
||||
\item[TelnetSignal] The telnet signal function.
|
||||
\item[InstallTelnet] installs a telnet server port into the SICS system.
|
||||
\item[KillTelnet] deletes the telnet server port from the system.
|
||||
\end{description}
|
||||
|
||||
\begin{flushleft} \small
|
||||
\begin{minipage}{\linewidth} \label{scrap3}
|
||||
\verb@"telnet.h"@ {\footnotesize ? }$\equiv$
|
||||
\vspace{-1ex}
|
||||
\begin{list}{}{} \item
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@/*-------------------------------------------------------------------------@\\
|
||||
\mbox{}\verb@ S I C S T E L N E T S U P P O R T@\\
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@ This file defines the telnet task function and its associated data@\\
|
||||
\mbox{}\verb@ structures. The body of the telnet handling code lives in the network@\\
|
||||
\mbox{}\verb@ reader module.@\\
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@ Mark Koennecke, January 1998@\\
|
||||
\mbox{}\verb@---------------------------------------------------------------------------*/@\\
|
||||
\mbox{}\verb@#ifndef SICSTELNET@\\
|
||||
\mbox{}\verb@#define SICSTELNET@\\
|
||||
\mbox{}\verb@@$\langle$telint {\footnotesize ?}$\rangle$\verb@@\\
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@#endif@\\
|
||||
\mbox{}\verb@ @\\
|
||||
\mbox{}\verb@@$\diamond$
|
||||
\end{list}
|
||||
\vspace{-2ex}
|
||||
\end{minipage}\\[4ex]
|
||||
\end{flushleft}
|
||||
44
doc/programmer/template.tex
Normal file
44
doc/programmer/template.tex
Normal file
@@ -0,0 +1,44 @@
|
||||
% Copyleft (c) 1997 by Mark Koennecke at PSI, Switzerland.
|
||||
%
|
||||
%
|
||||
% This software is distributed in the hope that it will be useful,
|
||||
% but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
% GNU General Public License for more details.
|
||||
%
|
||||
% You may already have a copy of the GNU General Public License; if
|
||||
% not, write to the Free Software Foundation, Inc., 675 Mass Ave,
|
||||
% Cambridge, MA 02139, USA.
|
||||
%
|
||||
|
||||
\documentclass[12pt]{article}
|
||||
\usepackage[dvips]
|
||||
|
||||
\setlength{\oddsidemargin}{-.1in}
|
||||
\setlength{\evensidemargin}{0in}
|
||||
\setlength{\topmargin}{0in}
|
||||
\addtolength{\topmargin}{-\headheight}
|
||||
\addtolength{\topmargin}{-\headsep}
|
||||
\setlength{\textheight}{8.9in}
|
||||
\setlength{\textwidth}{6.2in}
|
||||
\setlength{\marginparwidth}{0.5in}
|
||||
|
||||
\begin{document}
|
||||
\title{The NeXus Application Programmer's Interface}
|
||||
|
||||
\author{Mark K\"onnecke\\
|
||||
Labor f\"ur Neutronenstreuung\\
|
||||
Paul Scherrer Institut\\
|
||||
CH-5232 Villigen PSI\\
|
||||
Switzerland\\
|
||||
Mark.Koennecke@psi.ch \\
|
||||
Przemek K\l{}osowski\\
|
||||
U. of Maryland \& NIST \\
|
||||
przemek.klosowski@nist.gov
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
\maketitle
|
||||
\tableofcontents
|
||||
\end{document}
|
||||
82
doc/programmer/token.tex
Normal file
82
doc/programmer/token.tex
Normal file
@@ -0,0 +1,82 @@
|
||||
\subsection{Token Management}
|
||||
In SICS any client can issue commands to the SICS server. This
|
||||
is a potential cause for trouble with users issuing conflicting
|
||||
commands without knowing. In order to deal with this problem a
|
||||
token mechanism has been developed. A connection can grab a
|
||||
token and then has full control over the SICS server. Any other
|
||||
connection will not be priviledged to do anything useful, except
|
||||
looking at things. A token can be released manually with a
|
||||
special command or is automatically released when the connection
|
||||
dies. Another command exists which allows a SICS manager to
|
||||
force his way into the SICS server.
|
||||
|
||||
This token scheme is implemented using the signal system of the
|
||||
task management facility and the connection object. The connection
|
||||
object has a field called iGrap which is true if the connection is the
|
||||
ultimate and only control connection. This field will be modified
|
||||
either directly through commands or via the signal system of the SICS
|
||||
task manager. This must be so as all connections need to be notified
|
||||
if one connection has grabbed control.
|
||||
|
||||
This object implements the user interface to the token system.
|
||||
It checks privileges and issues the necessary signals. No own
|
||||
data structure is needed. Just a wrapper function is
|
||||
implemented.
|
||||
|
||||
\begin{flushleft} \small
|
||||
\begin{minipage}{\linewidth} \label{scrap1}
|
||||
\verb@"token.h"@ {\footnotesize ? }$\equiv$
|
||||
\vspace{-1ex}
|
||||
\begin{list}{}{} \item
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@/*---------------------------------------------------------------@\\
|
||||
\mbox{}\verb@ S I C S T O K E N@\\
|
||||
\mbox{}\verb@ @\\
|
||||
\mbox{}\verb@ This is the header file for the SICS token management@\\
|
||||
\mbox{}\verb@ functions. It implements the token command.@\\
|
||||
\mbox{}\verb@ @\\
|
||||
\mbox{}\verb@ Mark Koenencke, January 1998@\\
|
||||
\mbox{}\verb@ @\\
|
||||
\mbox{}\verb@ copyright: see copyright.h@\\
|
||||
\mbox{}\verb@ @\\
|
||||
\mbox{}\verb@----------------------------------------------------------------*/@\\
|
||||
\mbox{}\verb@#ifndef SICSTOKEN@\\
|
||||
\mbox{}\verb@#define SICSTOKEN@\\
|
||||
\mbox{}\verb@ int TokenInit(SConnection *pCon, SicsInterp *pSics, @\\
|
||||
\mbox{}\verb@ void *pData, int argc, char *argv[]);@\\
|
||||
\mbox{}\verb@ /*@\\
|
||||
\mbox{}\verb@ The Token Factory function.@\\
|
||||
\mbox{}\verb@ */ @\\
|
||||
\mbox{}\verb@ int TokenWrapper(SConnection *pCon, SicsInterp *pSics, @\\
|
||||
\mbox{}\verb@ void *pData, int argc, char *argv[]);@\\
|
||||
\mbox{}\verb@ @\\
|
||||
\mbox{}\verb@ /* @\\
|
||||
\mbox{}\verb@ The wrapper function for the token command.@\\
|
||||
\mbox{}\verb@ */ @\\
|
||||
\mbox{}\verb@ @\\
|
||||
\mbox{}\verb@ int TokenGrabActive(void);@\\
|
||||
\mbox{}\verb@ /*@\\
|
||||
\mbox{}\verb@ Returns 1, if a token grab is active, else 0@\\
|
||||
\mbox{}\verb@ */ @\\
|
||||
\mbox{}\verb@ @\\
|
||||
\mbox{}\verb@ void TokenRelease(void);@\\
|
||||
\mbox{}\verb@ /* @\\
|
||||
\mbox{}\verb@ Releases a Token Grab@\\
|
||||
\mbox{}\verb@ */ @\\
|
||||
\mbox{}\verb@#endif @\\
|
||||
\mbox{}\verb@@$\diamond$
|
||||
\end{list}
|
||||
\vspace{-2ex}
|
||||
\end{minipage}\\[4ex]
|
||||
\end{flushleft}
|
||||
The functions are:
|
||||
\begin{description}
|
||||
\item[TokenInit] is the installation routine which configures the
|
||||
token system into SICS. Called from the initialisation script.
|
||||
\item[TokenWrapper] is the interpreter interface function for the
|
||||
token system. Implements the active run time commands.
|
||||
\item[TokenGrapActive] returns true (1) if a connection has grabbed
|
||||
control or false (0) otherwise.
|
||||
\item[TokenRelease] releases the current control token.
|
||||
\end{description}
|
||||
|
||||
100
doc/programmer/tricsnex.tex
Normal file
100
doc/programmer/tricsnex.tex
Normal file
@@ -0,0 +1,100 @@
|
||||
\subsection{TRICS NeXus Data Files}
|
||||
This section describes the data file handling for the four circle
|
||||
diffractometer TRICS at SinQ. TRICS collects a lot of detector frames in
|
||||
time intervalls of days or weeks. The data writing scheme has to adress the
|
||||
issue, that the HDF routines cannot ensure that there is no data corruption
|
||||
when writing data files.
|
||||
|
||||
Thus the following scheme is implemented: With a special command, the user
|
||||
enforces a new file. At that time header information is written. After that
|
||||
the file is closed. With another command, the file is reopened and a frame
|
||||
is added to it. Each frame data group will hold a flag which decides if the
|
||||
frame is valid or not. After writing the frame, the file is closed again.
|
||||
This scheme minimises the danger of data corruption.
|
||||
|
||||
The current frame number is kept in a non NeXus standard field in the data file
|
||||
itself. This allows to reopen files and append data to it.
|
||||
|
||||
The interface to this object looks like this:
|
||||
|
||||
\begin{flushleft} \small
|
||||
\begin{minipage}{\linewidth} \label{scrap1}
|
||||
$\langle$nxtrics {\footnotesize ?}$\rangle\equiv$
|
||||
\vspace{-1ex}
|
||||
\begin{list}{}{} \item
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@ typedef struct __NexTrics *pNexTrics;@\\
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@/*----------------------------- live & death -----------------------------*/@\\
|
||||
\mbox{}\verb@ pNexTrics CreateNexTrics(pDataNumber pNum, char *pRoot, char *pDict,@\\
|
||||
\mbox{}\verb@ SicsInterp *pSics);@\\
|
||||
\mbox{}\verb@ void DeleteNexTrics(void *pData);@\\
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@ int NexTricsFactory(SConnection *pCon, SicsInterp *pSics, void *pData,@\\
|
||||
\mbox{}\verb@ int argc, char *argv[]);@\\
|
||||
\mbox{}\verb@/*----------------------------- interaction ------------------------------*/@\\
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@ int StartFile(pNexTrics self, SConnection *pCon);@\\
|
||||
\mbox{}\verb@ @\\
|
||||
\mbox{}\verb@ int ReopenFile(pNexTrics self, char *filename);@\\
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@ int DumpFrame(pNexTrics self, SConnection *pCon);@\\
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@ int NexTricsAction(SConnection *pCon, SicsInterp *pSics, void *pData,@\\
|
||||
\mbox{}\verb@ int argc, char *argv[]);@\\
|
||||
\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}
|
||||
\begin{description}
|
||||
\item[CreateNexTrics] creates a new TRICS NeXus data file writing object.
|
||||
Parameters are a data number object for the automatic creation of file names
|
||||
and the directory name where the data files ought to live. The next
|
||||
parameter is the name of the NeXus dictionary file to use for writing.
|
||||
\item[DeleteNexTrics] deletes a NexTrics object. The last parameter is the
|
||||
name of the SICS interpreter to search for objects. NexTrics will maintain a
|
||||
cache of frequently used SICS objects for writing.
|
||||
\item[NexTricsFactory] is the interpreter wrapper function for the command
|
||||
to install the nexus data writing object for Trics into the system.
|
||||
\item[StartFile] will automatically create a new file and write the header
|
||||
information to it.
|
||||
\item[DumpFrame] will dump a frame worth of data to the file. Thereby
|
||||
reopening and closing it. This will be called for each detector shot, i.e.
|
||||
in the end three frames will be written when all three detectors have been
|
||||
installed at TRICS.
|
||||
\item[NexTricsAction] is the command interface to the TRICS NeXus data file
|
||||
writing object.
|
||||
\end{description}
|
||||
|
||||
\begin{flushleft} \small
|
||||
\begin{minipage}{\linewidth} \label{scrap2}
|
||||
\verb@"nextrics.h"@ {\footnotesize ? }$\equiv$
|
||||
\vspace{-1ex}
|
||||
\begin{list}{}{} \item
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@/*----------------------------------------------------------------------------@\\
|
||||
\mbox{}\verb@ N E X T R I C S@\\
|
||||
\mbox{}\verb@ @\\
|
||||
\mbox{}\verb@ An object for writing NeXus data files for the four ciclre diffractometer@\\
|
||||
\mbox{}\verb@ TRICS at PSI. Can be used as basis for writing files for other four@\\
|
||||
\mbox{}\verb@ circles equiped with a PSD as well.@\\
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@ copyright: see copyright.h@\\
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@ Mark Koennecke, April 1998@\\
|
||||
\mbox{}\verb@------------------------------------------------------------------------------*/@\\
|
||||
\mbox{}\verb@#ifndef NEXTRICS@\\
|
||||
\mbox{}\verb@#define NEXTRICS@\\
|
||||
\mbox{}\verb@@$\langle$nxtrics {\footnotesize ?}$\rangle$\verb@@\\
|
||||
\mbox{}\verb@#endif@\\
|
||||
\mbox{}\verb@@$\diamond$
|
||||
\end{list}
|
||||
\vspace{-2ex}
|
||||
\end{minipage}\\[4ex]
|
||||
\end{flushleft}
|
||||
94
doc/programmer/udpquieck.tex
Normal file
94
doc/programmer/udpquieck.tex
Normal file
@@ -0,0 +1,94 @@
|
||||
\subsection{UDPquieck}
|
||||
At SinQ a requirement is that newly created data files are automatically
|
||||
copied to another computer. This is for data safety. To have this done by
|
||||
the instrument control program would raise stability problems: what to do
|
||||
when the remote computer fails, when transfers are to slow or all data has
|
||||
to be transferred again. Therefore the copying of files was delegated to a
|
||||
second process. Now a a means is needed to tell the second process, that a
|
||||
new data file has been created. This means is this module. It sends a UDP
|
||||
message on a predefined port. The data copying process can receive or not
|
||||
and act accordingly. Furthermore this scheme can be used to have other
|
||||
processes act upon a new data file as well. The message sent is simple: it
|
||||
consists of the string QUIECK/ followed by the filename. A new command is
|
||||
implemented with the name udpquieck. This shall be a hidden command. As only
|
||||
one such facility is needed for a given SICS server, all necessary data is
|
||||
held in the implementation file udpquieck.c. Anyway, there is only one
|
||||
structure holding network data.
|
||||
The configuration of the udpport is done via a special server
|
||||
option QuieckPort.
|
||||
|
||||
Laater on this facility may be extended to send arbitrary messages to
|
||||
the UDP port for further coordination tasks. This is catered for by
|
||||
having different message types. However, as of now only file messages
|
||||
are supported.
|
||||
|
||||
Needless to say, that the second process must be able to interpret the
|
||||
uDP messages sent by the SICS server.
|
||||
|
||||
|
||||
|
||||
The following interface is implemented:
|
||||
|
||||
\begin{flushleft} \small
|
||||
\begin{minipage}{\linewidth} \label{scrap1}
|
||||
$\langle$quieck {\footnotesize ?}$\rangle\equiv$
|
||||
\vspace{-1ex}
|
||||
\begin{list}{}{} \item
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@#define QUIECK 1@\\
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@ void KillQuieck(void *pData);@\\
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@ int SendQuieck(int iType, char *filename);@\\
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@ int QuieckAction(SConnection *pCon, SicsInterp *pSics, void *pData,@\\
|
||||
\mbox{}\verb@ int argc, char *argv[]);@\\
|
||||
\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}
|
||||
\begin{flushleft} \small
|
||||
\begin{minipage}{\linewidth} \label{scrap2}
|
||||
\verb@"udpquieck.h"@ {\footnotesize ? }$\equiv$
|
||||
\vspace{-1ex}
|
||||
\begin{list}{}{} \item
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@/*------------------------------------------------------------------------@\\
|
||||
\mbox{}\verb@ U D P Q U I E C K@\\
|
||||
\mbox{}\verb@ @\\
|
||||
\mbox{}\verb@ udpquieck sends a notification message on a UDP port when a new data@\\
|
||||
\mbox{}\verb@ file has been created. @\\
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@ Mark Koennecke, August 1998@\\
|
||||
\mbox{}\verb@---------------------------------------------------------------------------*/@\\
|
||||
\mbox{}\verb@#ifndef UDPQUIECK@\\
|
||||
\mbox{}\verb@#define UDPQUIECK@\\
|
||||
\mbox{}\verb@@$\langle$quieck {\footnotesize ?}$\rangle$\verb@@\\
|
||||
\mbox{}\verb@#endif@\\
|
||||
\mbox{}\verb@@$\diamond$
|
||||
\end{list}
|
||||
\vspace{-2ex}
|
||||
\end{minipage}\\[4ex]
|
||||
\end{flushleft}
|
||||
The functions:
|
||||
\begin{description}
|
||||
\item[KillQuieck] closes the network port at shutdown. Is the
|
||||
KillFunction used in the SICS interpreter command structure.
|
||||
\item[SendQuieck] sends a message of type iType and the text filename
|
||||
to the UDP port. The only supported iType value is QUIECK as defined
|
||||
in udpquieck.h. Further message types can be supported by adding more
|
||||
support in this function.
|
||||
\item[QuieckAction] is the interpreter interface function to this
|
||||
facility. Yes, messages may be issued by a commadn from the
|
||||
interpreter for instance within scripts. Again, this seems more useful
|
||||
when this facility has been extended.
|
||||
\end{description}
|
||||
|
||||
|
||||
91
doc/programmer/varlog.tex
Normal file
91
doc/programmer/varlog.tex
Normal file
@@ -0,0 +1,91 @@
|
||||
\subsection{VarLog}
|
||||
This is a lillte helper class which can be used to keep a log of a
|
||||
variable. A variables value is stored together with time information in a
|
||||
list. Various functions allow to interact with this list and retrieve the
|
||||
log. For the list the lld package is used again. Thus the only data
|
||||
required by this module is the integer ID of the list.
|
||||
|
||||
The following functions are provided:
|
||||
|
||||
\begin{flushleft} \small
|
||||
\begin{minipage}{\linewidth} \label{scrap1}
|
||||
$\langle$logint {\footnotesize ?}$\rangle\equiv$
|
||||
\vspace{-1ex}
|
||||
\begin{list}{}{} \item
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@/*---------------------------- birth and death ----------------------------*/ @\\
|
||||
\mbox{}\verb@ typedef struct __VarLog *pVarLog;@\\
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@ int VarlogInit(pVarLog *self);@\\
|
||||
\mbox{}\verb@ int VarlogDelete(pVarLog self);@\\
|
||||
\mbox{}\verb@/*----------------------------- operation -------------------------------*/@\\
|
||||
\mbox{}\verb@ int VarlogClear(pVarLog self);@\\
|
||||
\mbox{}\verb@ int VarlogAdd(pVarLog self, float fVal);@\\
|
||||
\mbox{}\verb@/*------------------------------ data recovery -------------------------*/@\\
|
||||
\mbox{}\verb@ int VarlogLength(pVarLog self, int *iLength);@\\
|
||||
\mbox{}\verb@ int VarlogGetTime(pVarLog self, time_t *tTime);@\\
|
||||
\mbox{}\verb@ int VarlogGetVal(pVarLog self, float *fValues);@\\
|
||||
\mbox{}\verb@ int VarlogGetMean(pVarLog self, float *fMean, float *fStdDev);@\\
|
||||
\mbox{}\verb@/*------------------------------ interpreter ---------------------------*/@\\
|
||||
\mbox{}\verb@ int VarlogWrapper(pVarLog self, int *iSwitch, SConnection *pCon, @\\
|
||||
\mbox{}\verb@ char *subcommand, char *sub2,char *pVarName);@\\
|
||||
\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}
|
||||
All functions return 1 on success, 0 on failure if not mentioned otherwise.
|
||||
|
||||
\begin{description}
|
||||
\item [ValogInit] creates a new varlog and prepares for data collection.
|
||||
Only parameter is a pointer to an int which will be initialised to the list
|
||||
ID to use.
|
||||
\item [VarlogDelete] deletes a varlog and frees the list. Single parameter
|
||||
is a pointer to an int holding the ID of the list to kill.
|
||||
\item [VarlogClear] clears old logged data but keeps the varlog alive for
|
||||
further data collection.
|
||||
\item [VarlogAdd] adds the float value fVal to the log denoted by iList. The
|
||||
time stamp will be generated automatically.
|
||||
\item [VarlogLength] retrieves the length of the current log.
|
||||
\item [VarlogGetTime] retrieves the array of time stamps as provided by the
|
||||
system function time from the log.
|
||||
\item [VarlogGetVal] retrieves the array of values from the log.
|
||||
\item [VarlogGetMean] retrieves the mean value of the values from the log
|
||||
denoted by iList and their standard deviation.
|
||||
\item [VarlogWrapper] is a function which may be invoked from an object
|
||||
wrapper function in order to interpret and handle the var logs subcommands.
|
||||
Parameters are: the varlog list, a switch variable which will be set to 1
|
||||
if logging is enabled and to 0 if not, a connection object to which data
|
||||
will be written and finally the subcommand to evaluate.
|
||||
\end{description}
|
||||
|
||||
\begin{flushleft} \small
|
||||
\begin{minipage}{\linewidth} \label{scrap2}
|
||||
\verb@"varlog.h"@ {\footnotesize ? }$\equiv$
|
||||
\vspace{-1ex}
|
||||
\begin{list}{}{} \item
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@/*--------------------------------------------------------------------------@\\
|
||||
\mbox{}\verb@ V A R L O G@\\
|
||||
\mbox{}\verb@ @\\
|
||||
\mbox{}\verb@ A module which keeps a log of a variable.@\\
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@ Mark Koennecke, September 1997@\\
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@ copyright: see implementation file@\\
|
||||
\mbox{}\verb@ @\\
|
||||
\mbox{}\verb@----------------------------------------------------------------------------*/@\\
|
||||
\mbox{}\verb@#ifndef SICSVARLOG@\\
|
||||
\mbox{}\verb@#define SICSVARLOG@\\
|
||||
\mbox{}\verb@#include <time.h>@\\
|
||||
\mbox{}\verb@@$\langle$logint {\footnotesize ?}$\rangle$\verb@@\\
|
||||
\mbox{}\verb@#endif@\\
|
||||
\mbox{}\verb@@$\diamond$
|
||||
\end{list}
|
||||
\vspace{-2ex}
|
||||
\end{minipage}\\[4ex]
|
||||
\end{flushleft}
|
||||
412
doc/programmer/velo.tex
Normal file
412
doc/programmer/velo.tex
Normal file
@@ -0,0 +1,412 @@
|
||||
\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:
|
||||
|
||||
\begin{flushleft} \small
|
||||
\begin{minipage}{\linewidth} \label{scrap1}
|
||||
$\langle$data {\footnotesize ?}$\rangle\equiv$
|
||||
\vspace{-1ex}
|
||||
\begin{list}{}{} \item
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@/*------------------ The velocity selector datastructure -----------------*/ @\\
|
||||
\mbox{}\verb@ @\\
|
||||
\mbox{}\verb@ typedef struct __VelSel {@\\
|
||||
\mbox{}\verb@ pObjectDescriptor pDes;@\\
|
||||
\mbox{}\verb@ char *pName;@\\
|
||||
\mbox{}\verb@ pIDrivable pDrivInt;@\\
|
||||
\mbox{}\verb@ pICallBack pCall;@\\
|
||||
\mbox{}\verb@ int iForbidden;@\\
|
||||
\mbox{}\verb@ ObPar *pPar;@\\
|
||||
\mbox{}\verb@ pMotor pTilt;@\\
|
||||
\mbox{}\verb@ float fRot;@\\
|
||||
\mbox{}\verb@ float fTilt;@\\
|
||||
\mbox{}\verb@ pEVControl pMonitor;@\\
|
||||
\mbox{}\verb@ pVelSelDriv pDriv;@\\
|
||||
\mbox{}\verb@ } VelSel; @\\
|
||||
\mbox{}\verb@/*----------------- Forbidden region single item -------------------------*/@\\
|
||||
\mbox{}\verb@ typedef struct __Verbot {@\\
|
||||
\mbox{}\verb@ float fMin;@\\
|
||||
\mbox{}\verb@ float fMax;@\\
|
||||
\mbox{}\verb@ } Verbot, *pVerbot;@\\
|
||||
\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 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.
|
||||
|
||||
\begin{flushleft} \small
|
||||
\begin{minipage}{\linewidth} \label{scrap2}
|
||||
$\langle$proto1 {\footnotesize ?}$\rangle\equiv$
|
||||
\vspace{-1ex}
|
||||
\begin{list}{}{} \item
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@ typedef struct __VelSel *pVelSel;@\\
|
||||
\mbox{}\verb@ typedef struct __VelSelDriv *pVelSelDriv;@\\
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@ pVelSel VSCreate(pMotor pTilt, pVelSelDriv pDriv);@\\
|
||||
\mbox{}\verb@ void VSDestroy(void *self);@\\
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@ int VSAddVerbot(pVelSel self, float fMin, float fMax);@\\
|
||||
\mbox{}\verb@ int VSSetPar(pVelSel self,SConnection *pCon, char *name, float fVal);@\\
|
||||
\mbox{}\verb@ int VSGetPar(pVelSel self,char *name, float *fVal);@\\
|
||||
\mbox{}\verb@ int VSGetRotation(pVelSel self, float *fRot);@\\
|
||||
\mbox{}\verb@ int VSGetTilt(pVelSel self, float *fTilt);@\\
|
||||
\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}
|
||||
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}
|
||||
|
||||
\begin{flushleft} \small
|
||||
\begin{minipage}{\linewidth} \label{scrap3}
|
||||
$\langle$protos2 {\footnotesize ?}$\rangle\equiv$
|
||||
\vspace{-1ex}
|
||||
\begin{list}{}{} \item
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@/*@\\
|
||||
\mbox{}\verb@ int VSSetRotation(pVelSel self, SConnection *pCon, float fNew);@\\
|
||||
\mbox{}\verb@ int VSSetTilt(pVelSel self, SConnection *pCon, float FNewTilt);@\\
|
||||
\mbox{}\verb@*/@\\
|
||||
\mbox{}\verb@ int VSSetTiltRot(pVelSel self, SConnection *pCon,@\\
|
||||
\mbox{}\verb@ float fNewRot, float fNewTilt);@\\
|
||||
\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}
|
||||
\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.
|
||||
|
||||
\begin{flushleft} \small
|
||||
\begin{minipage}{\linewidth} \label{scrap4}
|
||||
$\langle$protos4 {\footnotesize ?}$\rangle\equiv$
|
||||
\vspace{-1ex}
|
||||
\begin{list}{}{} \item
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@ int VSGetLossCurrent(pVelSel self, SConnection *pCon, float *fLoss);@\\
|
||||
\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}
|
||||
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.
|
||||
|
||||
\begin{flushleft} \small
|
||||
\begin{minipage}{\linewidth} \label{scrap5}
|
||||
$\langle$protos3 {\footnotesize ?}$\rangle\equiv$
|
||||
\vspace{-1ex}
|
||||
\begin{list}{}{} \item
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@ int VelSelFactory(SConnection *pCon, SicsInterp *pSics, void *pData,@\\
|
||||
\mbox{}\verb@ int argc, char *argv[]);@\\
|
||||
\mbox{}\verb@ int VelSelAction(SConnection *pCon, SicsInterp *pSics, void *pData,@\\
|
||||
\mbox{}\verb@ int argc, char *argv[]);@\\
|
||||
\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}
|
||||
\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.
|
||||
\begin{flushleft} \small
|
||||
\begin{minipage}{\linewidth} \label{scrap6}
|
||||
$\langle$Driver {\footnotesize ?}$\rangle\equiv$
|
||||
\vspace{-1ex}
|
||||
\begin{list}{}{} \item
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@ typedef struct __VelSelDriv {@\\
|
||||
\mbox{}\verb@ void *pPrivate;@\\
|
||||
\mbox{}\verb@ void (*DeletePrivate)(void *pData);@\\
|
||||
\mbox{}\verb@ float fTolerance;@\\
|
||||
\mbox{}\verb@ int (*Halt)(pVelSelDriv self);@\\
|
||||
\mbox{}\verb@ int (*GetError)(pVelSelDriv self,@\\
|
||||
\mbox{}\verb@ int *iCode, char *pError,@\\
|
||||
\mbox{}\verb@ int iErrlen);@\\
|
||||
\mbox{}\verb@ int (*TryAndFixIt)(pVelSelDriv self,@\\
|
||||
\mbox{}\verb@ int iCode);@\\
|
||||
\mbox{}\verb@ int (*GetRotation)(pVelSelDriv self,@\\
|
||||
\mbox{}\verb@ float *fRot);@\\
|
||||
\mbox{}\verb@ int (*SetRotation)(pVelSelDriv self,@\\
|
||||
\mbox{}\verb@ float fRot);@\\
|
||||
\mbox{}\verb@ int (*GetStatus)(pVelSelDriv self, @\\
|
||||
\mbox{}\verb@ int *iCall, float *fCur);@\\
|
||||
\mbox{}\verb@ int (*GetDriverText)(pVelSelDriv self,@\\
|
||||
\mbox{}\verb@ char *pText, @\\
|
||||
\mbox{}\verb@ int iTextLen);@\\
|
||||
\mbox{}\verb@ int (*GetLossCurrent)(pVelSelDriv self,@\\
|
||||
\mbox{}\verb@ float *fLoss);@\\
|
||||
\mbox{}\verb@ int (*Init)(pVelSelDriv self, @\\
|
||||
\mbox{}\verb@ SConnection *pCon);@\\
|
||||
\mbox{}\verb@ }VelSelDriv; @\\
|
||||
\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}
|
||||
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.
|
||||
|
||||
\begin{flushleft} \small
|
||||
\begin{minipage}{\linewidth} \label{scrap7}
|
||||
\verb@"velo.h"@ {\footnotesize ? }$\equiv$
|
||||
\vspace{-1ex}
|
||||
\begin{list}{}{} \item
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@/*-------------------------------------------------------------------------@\\
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@ V E L O C I T Y S E L E C T O R@\\
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@ Header file for the SICS velocity selector module. For documentation@\\
|
||||
\mbox{}\verb@ see velo.w.@\\
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@ Mark Koennecke, Juli 1997@\\
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@ copyright: see implementation file@\\
|
||||
\mbox{}\verb@-----------------------------------------------------------------------------*/@\\
|
||||
\mbox{}\verb@#ifndef SICSVELO@\\
|
||||
\mbox{}\verb@#define SICSVELO@\\
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@/*------------------------- live & death & shape ------------------------*/@\\
|
||||
\mbox{}\verb@@$\langle$proto1 {\footnotesize ?}$\rangle$\verb@@\\
|
||||
\mbox{}\verb@/*------------------------- drive around -----------------------------------*/@\\
|
||||
\mbox{}\verb@@$\langle$protos2 {\footnotesize ?}$\rangle$\verb@@\\
|
||||
\mbox{}\verb@@$\langle$protos4 {\footnotesize ?}$\rangle$\verb@@\\
|
||||
\mbox{}\verb@/*------------------------- Interpreter interface ------------------------*/@\\
|
||||
\mbox{}\verb@@$\langle$protos3 {\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{scrap8}
|
||||
\verb@"velo.i"@ {\footnotesize ? }$\equiv$
|
||||
\vspace{-1ex}
|
||||
\begin{list}{}{} \item
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@/*--------------------------------------------------------------------------@\\
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@ Internal header file describing the velocity selector data structure.@\\
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@ Mark Koennecke, Juli, 1997@\\
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@----------------------------------------------------------------------------*/@\\
|
||||
\mbox{}\verb@#ifndef VELOINTERNAL@\\
|
||||
\mbox{}\verb@#define VELOINTERNAL@\\
|
||||
\mbox{}\verb@@$\langle$data {\footnotesize ?}$\rangle$\verb@@\\
|
||||
\mbox{}\verb@#define VELOREDO 2@\\
|
||||
\mbox{}\verb@#define VELOFAIL 0@\\
|
||||
\mbox{}\verb@#define VELOOK 1@\\
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@#define VSNOCON 0@\\
|
||||
\mbox{}\verb@#define VSOK 1@\\
|
||||
\mbox{}\verb@#define VSACCEL -7@\\
|
||||
\mbox{}\verb@#define VSFAIL -2@\\
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@#endif@\\
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@@$\diamond$
|
||||
\end{list}
|
||||
\vspace{-2ex}
|
||||
\end{minipage}\\[4ex]
|
||||
\end{flushleft}
|
||||
\begin{flushleft} \small
|
||||
\begin{minipage}{\linewidth} \label{scrap9}
|
||||
\verb@"velodriv.h"@ {\footnotesize ? }$\equiv$
|
||||
\vspace{-1ex}
|
||||
\begin{list}{}{} \item
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@/*--------------------------------------------------------------------------@\\
|
||||
\mbox{}\verb@ V E L O C I T Y S E L E C T O R D R I V E R@\\
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@ Header file for the velocity selector driver and its related functions.@\\
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@ Mark Koennecke, Juli 1997@\\
|
||||
\mbox{}\verb@ copyright: see implementation file@\\
|
||||
\mbox{}\verb@-----------------------------------------------------------------------------*/@\\
|
||||
\mbox{}\verb@#ifndef VELODRIV@\\
|
||||
\mbox{}\verb@#define VELODRIV@\\
|
||||
\mbox{}\verb@#include <tcl.h>@\\
|
||||
\mbox{}\verb@@$\langle$Driver {\footnotesize ?}$\rangle$\verb@@\\
|
||||
\mbox{}\verb@/*-------------------- live & death ----------------------------------------*/@\\
|
||||
\mbox{}\verb@ pVelSelDriv VSCreateSim(void);@\\
|
||||
\mbox{}\verb@ pVelSelDriv VSCreateDornierSINQ(char *name,Tcl_Interp *pTcl);@\\
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@ void VSDeleteDriver(pVelSelDriv self);@\\
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@#endif @\\
|
||||
\mbox{}\verb@@$\diamond$
|
||||
\end{list}
|
||||
\vspace{-2ex}
|
||||
\end{minipage}\\[4ex]
|
||||
\end{flushleft}
|
||||
113
doc/programmer/velodorn.tex
Normal file
113
doc/programmer/velodorn.tex
Normal file
@@ -0,0 +1,113 @@
|
||||
\subsection{The hardware driver for the Dornier velocity selector at SINQ}
|
||||
SANS uses a velocity selector provided by Dornier, Germany. This velocity
|
||||
selector comes with a IBM--compatible PC for control. On this PC there is a
|
||||
control program for the velocity selector. This program can be operated from
|
||||
the PC's monitor and keyboard or remotely, from a host computer,
|
||||
through a RS--232 connection. The protocoll on this RS--232 connection is a
|
||||
simple ASCII command protocoll detailed in the documentation delivered by
|
||||
Dornier. At SINQ this velocity selcector control PC is connected via the
|
||||
RS--232 connection to a Macintosh computer. This Mac is connected to the
|
||||
network by TCP/IP. The Mac runs a terminal server program. This program
|
||||
forwards commands sent by TCP/IP to the apropriate RS--232 port. Due to this
|
||||
complicated setup, the hardware driver for the Dornier velocity selector has
|
||||
three layers:
|
||||
\begin{itemize}
|
||||
\item A command forwarding layer, which sends command to the selector via
|
||||
TCP/IP, the MAC and RS--232 and collects answers. This is fairly general
|
||||
code, used for many SICS hardware drivers.
|
||||
\item A primitive operations layer which implements simple command on the
|
||||
selector. This layer is based on code provided by Dr. Emmelmann, HMI.
|
||||
\item At the end, there is the actual SICS hardware driver which builds the
|
||||
interface to the SICS system.
|
||||
\end{itemize}
|
||||
|
||||
The implementation of the Dornier velocity selector driver is further
|
||||
complicated by the fact that it is very slow in responding to commands
|
||||
and moreover due to the fact that it has different modes:
|
||||
\begin{itemize}
|
||||
\item Starting is just after starting the velocity selector
|
||||
\item regel is the normal mode.
|
||||
\item halting is the mode when the velocity selector has been asked to
|
||||
stop.
|
||||
\end{itemize}
|
||||
Unfortunately the actions necessary to run a Dornier velocity
|
||||
selector to a desired speed depend on those modes. For instance if the
|
||||
Dornier velocity
|
||||
selector is stopped it first needs to be started and then, when a
|
||||
certain speed has been reached, the command to set the desired
|
||||
rotation speed can be sent. The necessary mode dependent switching is
|
||||
done in the DornierStat function.
|
||||
|
||||
\begin{flushleft} \small
|
||||
\begin{minipage}{\linewidth} \label{scrap1}
|
||||
$\langle$dh {\footnotesize ?}$\rangle\equiv$
|
||||
\vspace{-1ex}
|
||||
\begin{list}{}{} \item
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@ int GetDornierStatus(void **pData, pDornierStatus pDornier);@\\
|
||||
\mbox{}\verb@ int DornierSend(void **pData, char *pCommand, char *pReply, int iLen);@\\
|
||||
\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}
|
||||
\begin{flushleft} \small
|
||||
\begin{minipage}{\linewidth} \label{scrap2}
|
||||
\verb@"velodorn.h"@ {\footnotesize ? }$\equiv$
|
||||
\vspace{-1ex}
|
||||
\begin{list}{}{} \item
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@/*---------------------------------------------------------------------------@\\
|
||||
\mbox{}\verb@ V E L O D O R N@\\
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@ a set of utility functions needed in order to communicate with a @\\
|
||||
\mbox{}\verb@ Dornier velocity selector through the SINQ system. @\\
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@ Mark Koennecke, Juli 1997@\\
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@ copyright: see implementation file.@\\
|
||||
\mbox{}\verb@------------------------------------------------------------------------------*/@\\
|
||||
\mbox{}\verb@#ifndef VELODORN@\\
|
||||
\mbox{}\verb@#define VELODORN@\\
|
||||
\mbox{}\verb@/*-------------------- a data structure for status analysis ---------------*/@\\
|
||||
\mbox{}\verb@ typedef struct {@\\
|
||||
\mbox{}\verb@ char echo[30]; /* echo of command */@\\
|
||||
\mbox{}\verb@ char rm[10]; /* operation status: REG == adjusting, STB == idle, @\\
|
||||
\mbox{}\verb@ BRE == braking */@\\
|
||||
\mbox{}\verb@ int nom_rpm; /* envisaged rotation */@\\
|
||||
\mbox{}\verb@ int cur_rpm; /* actual rotation speed */ @\\
|
||||
\mbox{}\verb@ int pwr; /* loss current, only valid after check */@\\
|
||||
\mbox{}\verb@ float curr; /* electircal current */@\\
|
||||
\mbox{}\verb@ int rot_temp; /* temperature of rotor */@\\
|
||||
\mbox{}\verb@ int cont_temp; /* temperature of housing */@\\
|
||||
\mbox{}\verb@ int inl_temp; /* in temperature of cooling water */@\\
|
||||
\mbox{}\verb@ int outl_temp; /* temperature of cooling water after @\\
|
||||
\mbox{}\verb@ velocity selector */@\\
|
||||
\mbox{}\verb@ float cool_wat; /* cooling water flow (l/minute) */@\\
|
||||
\mbox{}\verb@ float vacuum; /* vacuum (mbar) */@\\
|
||||
\mbox{}\verb@ float accel; /* rotation acceleration (g) */@\\
|
||||
\mbox{}\verb@ int komm; /* communication status PC-Host,@\\
|
||||
\mbox{}\verb@ 0 = enabled, 1 = disabled @\\
|
||||
\mbox{}\verb@ */@\\
|
||||
\mbox{}\verb@ int iHz;@\\
|
||||
\mbox{}\verb@ } DornierStatus, *pDornierStatus; @\\
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@/*--------- error codes */@\\
|
||||
\mbox{}\verb@#define NOCOMMAND -300@\\
|
||||
\mbox{}\verb@#define ECHOMISSING -302@\\
|
||||
\mbox{}\verb@#define BADANALYSIS -303@\\
|
||||
\mbox{}\verb@#define STARTTIMEOUT -304@\\
|
||||
\mbox{}\verb@#define INVALIDSTATUS -305@\\
|
||||
\mbox{}\verb@/*------ functions */@\\
|
||||
\mbox{}\verb@@$\langle$dh {\footnotesize ?}$\rangle$\verb@@\\
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@#endif@\\
|
||||
\mbox{}\verb@@$\diamond$
|
||||
\end{list}
|
||||
\vspace{-2ex}
|
||||
\end{minipage}\\[4ex]
|
||||
\end{flushleft}
|
||||
129
doc/programmer/xytable.tex
Normal file
129
doc/programmer/xytable.tex
Normal file
@@ -0,0 +1,129 @@
|
||||
\subsection{Xytable}
|
||||
Xytable is an object which holds a list of x-y values. This can be used as a
|
||||
tool for doing very special scans or storing interesting data from command
|
||||
files. This class allows to retrieve the data in uuencoded form which
|
||||
is understood and displayed by the variable watcher SICS client. Furthermore
|
||||
data can be written to a file. The table entries are kept in a linked
|
||||
list in the following data structure.
|
||||
|
||||
The following data structures will be used:
|
||||
\begin{flushleft} \small
|
||||
\begin{minipage}{\linewidth} \label{scrap1}
|
||||
$\langle$xydata {\footnotesize ?}$\rangle\equiv$
|
||||
\vspace{-1ex}
|
||||
\begin{list}{}{} \item
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@ typedef struct {@\\
|
||||
\mbox{}\verb@ float x;@\\
|
||||
\mbox{}\verb@ float y;@\\
|
||||
\mbox{}\verb@ } TableEntry, *pTableEntry;@\\
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@ typedef struct __XYTABLE {@\\
|
||||
\mbox{}\verb@ pObjectDescriptor pDes;@\\
|
||||
\mbox{}\verb@ int iList; @\\
|
||||
\mbox{}\verb@ int iCount;@\\
|
||||
\mbox{}\verb@ }XYTable;@\\
|
||||
\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 entries in the TableEntry are self explianing: just the
|
||||
values. The XYTable structure holds the following fields:
|
||||
\begin{description}
|
||||
\item[pDes] The standard object descriptor.
|
||||
\item[iList] the handle for the lld-list holding the table entries.
|
||||
\item[iCount] The number of entries in the table.
|
||||
\end{description}
|
||||
|
||||
|
||||
|
||||
The following functions are defined:
|
||||
\begin{flushleft} \small
|
||||
\begin{minipage}{\linewidth} \label{scrap2}
|
||||
$\langle$xyfunc {\footnotesize ?}$\rangle\equiv$
|
||||
\vspace{-1ex}
|
||||
\begin{list}{}{} \item
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@ typedef struct __XYTABLE *pXYTable;@\\
|
||||
\mbox{}\verb@/*------------------------------------------------------------------------*/@\\
|
||||
\mbox{}\verb@ int XYClear(pXYTable self);@\\
|
||||
\mbox{}\verb@ int XYAdd(pXYTable self, float x, float y);@\\
|
||||
\mbox{}\verb@ int XYWrite(pXYTable self, FILE *fd);@\\
|
||||
\mbox{}\verb@ int XYSendUU(pXYTable self, SConnection *pCon);@\\
|
||||
\mbox{}\verb@ int XYList(pXYTable self, SConnection *pCon);@\\
|
||||
\mbox{}\verb@/*----------------------- interpreter interface --------------------------*/@\\
|
||||
\mbox{}\verb@ int XYFactory(SConnection *pCon, SicsInterp *pSics, void *pData,@\\
|
||||
\mbox{}\verb@ int argc, char *argv[]);@\\
|
||||
\mbox{}\verb@ int XYAction(SConnection *pCon, SicsInterp *pSics, void *pData,@\\
|
||||
\mbox{}\verb@ int argc, char *argv[]);@\\
|
||||
\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}
|
||||
Most functions take a pointer to an XYTbale data structure as fist
|
||||
parameter and return 1 on success and 0 on failure. The functions are:
|
||||
\begin{description}
|
||||
\item[XYClear] clears all entries.
|
||||
\item[XYAdd] appends a new pair of x and y values to the list.
|
||||
\item[XYWrite] writes the XY-list to the file fd. This file must
|
||||
already have been opened for writing by the calling routine.
|
||||
[item[XYSendUU] sends the XY-table in uuencoded form compatible with
|
||||
the SICS variabel watcher to connection pCon.
|
||||
\item[XYList] prints the content of the XY-table to connection pCon.
|
||||
\item[XYFactory] is the implentation of the installation command for
|
||||
the SICS initialisation process.
|
||||
\item[XYAction] implements the interface to the SICS interpreter for
|
||||
the xytable command.
|
||||
\end{description}
|
||||
|
||||
|
||||
\begin{flushleft} \small
|
||||
\begin{minipage}{\linewidth} \label{scrap3}
|
||||
\verb@"xytable.i"@ {\footnotesize ? }$\equiv$
|
||||
\vspace{-1ex}
|
||||
\begin{list}{}{} \item
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@/*----------------------------------------------------------------------@\\
|
||||
\mbox{}\verb@ Internal data structures for the XYTable class. Do not modify@\\
|
||||
\mbox{}\verb@------------------------------------------------------------------------*/@\\
|
||||
\mbox{}\verb@@$\langle$xydata {\footnotesize ?}$\rangle$\verb@@\\
|
||||
\mbox{}\verb@@$\diamond$
|
||||
\end{list}
|
||||
\vspace{-2ex}
|
||||
\end{minipage}\\[4ex]
|
||||
\end{flushleft}
|
||||
\begin{flushleft} \small
|
||||
\begin{minipage}{\linewidth} \label{scrap4}
|
||||
\verb@"xytable.h"@ {\footnotesize ? }$\equiv$
|
||||
\vspace{-1ex}
|
||||
\begin{list}{}{} \item
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@/*------------------------------------------------------------------------@\\
|
||||
\mbox{}\verb@ X Y T A B L E @\\
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@ a helper class for holding an X-Y list of values.@\\
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@ copyright: see copyright.h@\\
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@ Mark Koennecke, June 1999@\\
|
||||
\mbox{}\verb@----------------------------------------------------------------------------*/@\\
|
||||
\mbox{}\verb@#ifndef XYTABLE@\\
|
||||
\mbox{}\verb@#define XYTABLE@\\
|
||||
\mbox{}\verb@@$\langle$xyfunc {\footnotesize ?}$\rangle$\verb@@\\
|
||||
\mbox{}\verb@#endif@\\
|
||||
\mbox{}\verb@@$\diamond$
|
||||
\end{list}
|
||||
\vspace{-2ex}
|
||||
\end{minipage}\\[4ex]
|
||||
\end{flushleft}
|
||||
Reference in New Issue
Block a user