\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}