\documentstyle{report}

\setlength{\oddsidemargin}{0in}
\setlength{\evensidemargin}{0in}
\setlength{\topmargin}{0in}
\addtolength{\topmargin}{-\headheight}
\addtolength{\topmargin}{-\headsep}
\setlength{\textheight}{8.9in}
\setlength{\textwidth}{6.5in}
\setlength{\marginparwidth}{0.5in}
 
\title{SINQHM-Utility\\ Utility functions for the \\
 SINQ Histogram memory}
\author{David Maden, Mark K\"onnecke, April 1997}

\begin{document}
\maketitle
\clearpage

\chapter{Introduction}
This file describes some Utility functions for interfacing with the SinQ
histogram memory server. This device is described in great detail elsewhere
(D. Maden: The SINQ Histogram Memory, Feb. 1997). 
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. 
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. According to this scheme the utility functions
divide into two groups: Master Server commands and data aquisition commands.

\section{Code organisation} 
The code dealing with the SINQ histogram memory is organised in four
files: sinqhm.w, the literate programming file which creates sinqhm.i and
sinqhm.h as well as the LateX documentation for the interface, sinqhm.i is
an internal header file and contains typedefs and function definitions for
relevant for the implementation of the utility functions only. sinqhm.h
defines the public interface functions. sinqhm.c finally is the source file
which implements the utilities.

\section{The SINQHM data structure}
In order to transport the necessary status information around, each function
will take a pointer to the data structure defined below as first parameter.
For TOF mode it is necessary to store some imformation per detector bank.
This information is kept in a bank data structure:

@d  SBank @{
    typedef struct __SBANK {
                            int iStart;
                            int iEnd;
                            int iFlag;
                            int iEdgeLength;
                            int iDelay;
                            unsigned int *iEdges;
                           } SBank, *pSBank;
@}
The fields are:
\begin{description}
\item[iStart] The number of the detector with which this bank starts.
\item[iEnd] The number of the last detector for this bank.
\item[iFlag] A flag which indicates if the bank has a fixed bin widths. 0
denotes fixed bin width, 1 variable time binning.
\item[iEdgeLength] is the length of the edge array.
\item[iEdges] is an array of integer values describing the lower edges of
the bins. Its content depends on the value of iFlag. With a equally spaced
time binning (iFlag = 0) is is sufficient to give values for the first two
bins. If the time binning varies, nBins+1 values are necessary describing
the lower edges of all time bins.
\end{description}

@d SType @{
   typedef struct __SINQHM {
                            char *pHMComputer;
                            int  iMasterPort;
                            int  iMasterSocket;
                            int  iClientPort;
                            int  iClientSocket;
                            int  iBinWidth;
                            int  iLength;
                            int  iRank;
                            int  iPacket;
                            int  iBanks;
                            int xSize, ySize;
                            int  xOff, xFac;
                            int  yOff, yFac;
                            SBank pBank[MAXBANK];
                           } SINQHM;
@}
 
The first item in this structure is the name of the histogram memory
computer, the second the port number at which the master server is
listening. iClientPort defines a port for data communication. If no such
port is open, this value will be 0. iStatus is a status flag. iBanks is the
number of detector banks defined. pSBank is an array of bank data structures
describing the detector banks. 
xOff, xFac and yOff and yFac are the offset and factor values needed for
the PSD calculation for TRICS and AMOR. In order to
maintain this data structure two functions are defined:

\section{Byte swapping}
These utility functions preform byte swapping as needed. In order for this
to work please make sure that the following typedefs represent the correct
types for your compiler and computer.

@d SType @{
/*---------------------------- Type definitions, machine dependent--------*/
  typedef short int   SQint16; /* 16 bit integer */
  typedef int         SQint32; /* 32 bit integer */
@} 

@d Protos @{
  pSINQHM CreateSINQHM(char *pHMComputer, int iMasterPort);
  pSINQHM CopySINQHM(pSINQHM self);
  void    DeleteSINQHM(pSINQHM self); 
  void SINQHMSetPar(pSINQHM self, int iRank, int iLength, int iBinWidth);
  void SINQHMSetPSD(pSINQHM self, int xSize, int xOff, int xFac,
                    int ySize, int yOff, int yFac);
@}

The first function creates a new SINQHM data structure and initialises the
fields with the parameters given. Their meanings correspond to those
mentioned above for the description of the data structure. DeleteSINQHM
frees all memory associated with a SINQHM structure given by self. The
pointer to self is invalid ever afterwards.
CopySINQHM creates a copy of the SINQHM structure passed in with self.
SINQHMSetPar sets time of flight parameters.
SINQHMSetPSD defines PSD parameters for TRICS/AMOR type detectors. 

\section{SINQHM error handling}
If not denoted otherwise all public SINQHM functions return an integer 1 on
success. In the more common case of failure, a negative error code is
returned. This error code can be transformed into a human readable form by a
call to:

@d Protos @{
  int SINQHMError2Text(int iErr, char *pBuffer, int iBufLen);
@}

This function takes as first parameter the error code, as second a pointer
to a text buffer for the error message and as third parameter the length of
the buffer. Maximum iBufLen characters will be copied to pBuffer. 

\section{Master Server command functions}
These functions mainly serve to configure the histogram memory and to obtain
socket-id's for client data aquisition servers. The following functions are
needed:

@d Protos @{
  int SINQHMConfigure(pSINQHM self, int iMode, int iRank, int iLength, 
                      int iBinWidth, int iLowBin, int iCompress);
  int SINQHMConfigurePSD(pSINQHM self, int iMode,
                         int xSize, int xOff, int xFac,
                         int ySize, int yOff, int yFac,
                         int iBinWidth, 
                         float *iEdges, int iEdgeLength);

  int SINQHMDeconfigure(pSINQHM self, int iHarsh);
  int SINQHMGetStatus(pSINQHM self,int *iMode,  int *iDaq,
                      int *iRank, int *iBinWidth,
                      int *iLength, int *iClients);
  int SINQHMDebug(pSINQHM self, int iLevel);
  int SINQHMKill(pSINQHM self);
  
@}

@d IProtos @{
@}

SINQHMConfigure configures the master server for data aquisition. Besides
the pointer to a SINQHM structure it takes the following parameters:
 iMode is the combination of mode and submode bits as defined in
sinqhm_defs.h.  iLength is the length of
the histograms. iBinWidth is the size of the histogram memory bins in bytes.
Currently the values 1,2 and 4 are allowed. iClients is the number of active
clients at the histogram memory computer. iRank is the number of histograms.
iLowBin is the start of the histogram memory. Usually this is 0, but someone
may choose to strat at a different memory location. iCompress is for
compression. All data will be right shifted by iCompress bits before
storage. To my knowledge this feature is currently not implemented.

SINQHMConfigurePSD configures a TRICS/AMOR type detector. The parameters are:
\begin{description}
\item[self] The histogram memory data structure.
\item[iMode] The actual histogram mode with all submask bits.
\item[xSize] The x size of the detector.
\item[xOff] The offset in x for the detector position decoding.
\item[xFac] The factor used in decoding the x detector position. 
\item[ySize] The y size of the detector.
\item[yOff] The offset in y for the detector position decoding.
\item[yFac] The factor used in decoding the y detector position.
\item[iBinWidth] The binwidth of the histograms.
\item[iEdges] An array holding the time binning edges.
\item[iEdgeLength] The length of iEdges.  
\end{description}

SINQHMDeconfigure deconfigures the histogram memory. This is necessary prior
to reconfiguration. The only parameter iHarsh defines how brutal the master
server is with this. There may still be clients active at the histogram
memory. If iHarsh is 0, SINQHMDeconfig returns an error in this case. If
iHarsh is 1, the clients will be killed and the master server returns to a
virgin state.

SINQHMGetStatus allows to query the state of the master server. Parameters
have the same meaning as given with SINQHMConfigure. Except of course
iClients which is the number of currently active clients at the histogram
memory. iDaq show the status of data aquisition: 0 denotes stopped, 1
denotes running and 2 denotes inhibited. 

SINQHMDebug sets the debug level of the histogram memory server. That server
may print messages to its Com 1 port. This command configures the amount of
information available at this channel. This function is of no use for normal
users.

SINQHMKill stops the histogram memory master server and all its children.
WARNING: After this call a manual restart of the histogram memory master
server or a reboot of the histogram memory computer has to be performed. 
Do not use this function unless you are a SINQ histogram memory guru. 

\section{TOF bin description functions}
Configuring the TOF binning of the histogram memory requires two steps. In
the first step you define the binning of all required banks. Then in a
second step, this data is packed up and forwarded to the histogram memory.
Thus the following functions are required:

@d TOFProto @{
   int SINQHMDefineBank(pSINQHM self, int iBankNumber, int iStart, int iEnd,
                        float *iEdges, int iEdgeLength);
@}
@d TOFintern @{
   static int SINQHMTimeBin(pSINQHM self, int iMode);
@}
SINQHDefineBank defines the time binning for a single detector bank.
iBankNumber defines the number of the detector bank to define. iStart and
iEnd select  the range of detectors beloning to this detector bank. iEdges
is the array of time binnings. iEdgeLength is the length of the edges array. 

SINQHMTimeBin actually sends the new time binning to the histogram memory.
SINQHMTimeBin is a static internal function.

 

\section{Data aquisition functions}
These functions allow to do data aquisition and retrieve or set histograms.
Data aquisition is fairly involved. In order for data aquisition to happen
the histogram memory internal filler process must be running. This is
controlled by the StartDAQ/StopDAQ pair. However, any client can inhibit
data processing. This feature is targeted towards clients monitoring
environment devices. Such clients thus can pause data aquisition in order to
allow environment variables to get in the defined range again. This is
controlled by the InhibitDAQ/ContinueDAQ pair of functions. Please note,
that after starting a new data aquisition session the inhibit flag is
cleared by default. 

@d Protos @{
   int SINQHMOpenDAQ(pSINQHM self);
   int SINQHMCloseDAQ(pSINQHM self);

   int SINQHMStartDAQ(pSINQHM self);
   int SINQHMStopDAQ(pSINQHM  self);
   int SINQHMInhibitDAQ(pSINQHM self);
   int SINQHMContinueDAQ(pSINQHM self);
  
   int SINQHMWrite(pSINQHM self, int iNum, int iStart, int iEnd, 
                   void *pData);
   long SINQHMSize(pSINQHM self, int iNum, int iStart, int iEnd);
   int SINQHMRead(pSINQHM self, int iNum, int iStart, int iEnd, 
                  void *pData, int iDataLen); 
   int SINQHMProject(pSINQHM self, int code, int xStart, int nx,
                     int yStart, int ny, void *pData, int iDataLen);
   int SINQHMZero(pSINQHM self, int iNum, int iStart, int iEnd);
@} 

SINQHMOpenDAQ must be the first call and will create the slave server in the
histogram memory server which is than responsible for answereing our further
requests. Without this call any other call will return an error! 

SINQHMCloseDAQ closes a data aquisition session.

SINQHMStartDAQ starts data aquisition.

SINQHMInhibitDAQ causes data aquisition to pause.

SINQHMContinueDAQ causes a paused data aquisition to continue.
 
SINQHMStopDAQ stops data aquisition. 
 
SINQHMWrite is used to initialise the histograms in the histogram memory to
a specific value. The histogram to write is selected by iNum. If iNum is -1
the whole histogram memory area is written. iStart and iEnd define a subset
of the histogram to write. pData is a pointer to a data area which is going
to be copied to the histogram memory.

SINQHMSize returns the necessary size in bytes for a buffer large enough to
hold all the data requested with the following read parameters.

SINQHMRead reads histograms. The parameters iNum, iStart and iEnd have the
same meaning as with SINQHMWrite. Maximum iDataLen bytes of data are copied
to the memory area pointed to by pData.

SINQHMProject requests a projection of the data from the histogram memory. This
 is currently only implemented for AMOR because histograms can get so large
 at this instrument that a transfer for processing would take to long. The
 parameters are:
\begin{description}
\item[code] The operation code for project. Can be PROJECT__COLL for 
 collapsing all time channels onto a 2D array and PROJECT__SAMPLE for
 summing a rectangular region of the histogram memory in time.
\item[xStart, nx] start value in x and number of detectors to sum in x direction
\item[yStart,ny]start value in y and number of detectors to sum in y direction
\item[pData] a pointer to a data array large enough for holding the projected
 data.
\item[iDataLen] The length of pData.
\end{description}

SINQHMZero clears the  histogram iNum from iStart to iEnd to 0. 
A recommended call prior
to any serious data aquisition.

\section{Further internal routines}
@d IProtos @{
   static int OpenMasterConnection(pSINQHM self);
   static int GetMasterReply(pSINQHM self, struct rply_buff_struct *reply,
                             int iBufLen);
   static int SendDAQCommand(pSINQHM self, int iCommand, int *iDaq);
@}
OpenMasterCoonection tries to open a connection to the SINQ histogram memory
master server ready to send data.

GetMasterReply collects the reply from the master server.

SendDAQCommand sends iCommand to the client server. Returns the current
status of the data aquisition flag in iDaq for further analysis. 

@d ErrCode @{
#define HMCOMPUTER_NOT_FOUND -2
#define SOCKET_ERROR         -3
#define BIND_ERROR           -4
#define CONNECT_ERROR        -5
#define RECEIVE_ERROR        -6
#define INSUFFICIENT_DATA    -7
#define BYTE_ORDER_CHAOS     -8
#define HIST_BAD_CREATE      -9
#define HIST_BAD_STATE       -10
#define HIST_BAD_VALUE       -11
#define HIST_BAD_RECV        -12
#define HIST_BAD_ALLOC       -13
#define HIST_BAD_CODE        -14
#define SEND_ERROR           -15
#define CLOSE_ERROR          -16
#define INVALID_HARSH        -17
#define SOFTWARE_ERROR       -18
#define DAQ_INHIBIT          -19
#define DAQ_NOTSTOPPED       -20
@}

@o sinqhm.h -d @{
/*---------------------------------------------------------------------------
	                       S I N Q H M
  Some utility functions for interfacing to the SINQ histogram memory
  server.

  David Maden, Mark Koennecke, April 1997

  copyright: see implementation file.
-----------------------------------------------------------------------------*/
#ifndef SINQHMUTILITY
#define SINQHMUTILITY
#include "sinqhm_def.h"

  typedef struct __SINQHM *pSINQHM;
/*------------------------------ Error codes -----------------------------*/
@< ErrCode @>

/*------------------------------ Prototypes ------------------------------*/
@< Protos @>
@< TOFProto @>
#endif
@}

@o sinqhm.i @{
/*---------------------------------------------------------------------------

  Internal header file for the SINQ histogram memory utility functions.

  David Maden, Mark Koennecke April 1997
----------------------------------------------------------------------------*/
#ifndef SINQHMINTERNAL
#define SINQHMINTERNAL
#define MAXBANK 1
@< SBank @>
@< SType @>
@< IProtos @>
@< TOFintern @>
#endif

@}

\chapter{The SINQ histogram memory Tcl wrapper}
In order to allow for status displays via Tcl/TK, for debugging and general
availability a Tcl wrapper for the SINQ histogram memory functions has been
devised. It works similar to the widget commands as used for TK. On startup
the extra command SINQHM is available. The syntax is: \\ 
\leftline{SINQHM name computer port }\\
This command will create another command called name which symbolises a
connection to the histogram memory at computer listening to port. The new
object created is a control object. This control object understands the
commands listed below. Each command has to be prepended with the name you
specified in the call to SINQHM.
\begin{itemize}
\item {\bf config iMode iOver iRank iLength iBinWidth} configures a histogram
memory. 
\item {\bf status} return a status message of the HM.
\item {\bf deconfig iHarsh} deconfigures the HM.
\item {\bf debug iLevel} sets internal debug level.
\item {\bf exit} do not use this! Kills the HM.
\item {\bf DAQ name } creates a data aquisition client named name.
\item {\bf delDAQ name} kills the data aquisition client named name.
\end{itemize}

After the last call there exists a new command name which represents a data
aquisition client, capabale of reading and writing data. This DAQ client
understands the commands listed below. Again, each command has to prepended
with the name given in the DAQ command above.
\begin{itemize}
\item {\bf read iNum iStart iEnd arname} reads histogram iNum from 
iStart to iEnd. The data will be stored in the array arname.
\item {\bf write iNum iStart iEnd data} writes data to the histogram iNum
from iStart iEnd bins. data must be an Tcl-array with indexes from 0 to
iEnd which contains the values to write. 
\item {\bf zero} zeroes the histogram memory.
\item {\bf start} starts data aquisition.
\item {\bf stop} stops data aquisition.
\item {\bf inhibit} inhibits data aquisition.
\item {\bf continue} continues an inhibited data aquisition session.
\end{itemize}
    
 

\end{document}