Files
sicspsi/hardsup/el737_utility.c
2009-02-13 09:01:24 +00:00

1906 lines
63 KiB
C
Raw Permalink Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#define ident "2B03"
#ifdef VAXC
#module EL737_Utility ident
#endif
#ifdef __DECC
#pragma module EL737_Utility ident
#endif
/*
** +--------------------------------------------------------------+
** | Paul Scherrer Institute |
** | Department ASQ |
** | |
** | This software may be used freely by non-profit organizations.|
** | It may be copied provided that the name of P.S.I. and of the |
** | author is included. Neither P.S.I. nor the author assume any |
** | responsibility for the use of this software outside of P.S.I.|
** +--------------------------------------------------------------+
**
** Module Name . . . . . . . . : [...LIB.SINQ]EL737_Utility.C
**
** Author . . . . . . . . . . : D. Maden
** Date of creation . . . . . . : Apr 1996
**
** To compile this module, use:
$ import tasmad
$ define/group sinq_c_tlb mad_lib:sinq_c.tlb
$ cc /debug /noopt /obj=[]EL737_Utility -
tasmad_disk:[mad.psi.lib.sinq]EL737_Utility + -
sinq_c_tlb/lib
** To include this module in SINQ.OLB, use:
$ import tasmad
$ define/group sinq_c_tlb mad_lib:sinq_c.tlb
$
$ define/group sinq_olb mad_lib:sinq_dbg.olb
$ @tasmad_disk:[mad.lib.sinq]sinq_olb EL737_Utility debug
$
$ define/group sinq_olb mad_lib:sinq.olb
$ @tasmad_disk:[mad.lib.sinq]sinq_olb EL737_Utility
**
** Updates:
** 1A01 2-Nov-1995 DM. Initial version.
** 1B01 21-Mar-1996 DM. Move from DELTAT.OLB to SINQ.OLB.
** 1C01 16-Jul-1997 DM. Add code for EL737_Pause
** 2A01 6-Aug-1997 DM. Cope with new RA response format (= timer first)
** Add EL737_GetLongStatus.
** 2B01 5-Aug-1998 DM. Put messages into a .MSG file.
** 2B02 22-Apr-1999 DM. Add EL737_GetThresh and EL737_SetThresh.
**============================================================================
** The entry points included in this module are described below. Prototypes
** can be defined via:
**
** #include <sinq_prototypes.h>
**
** EL737_Close - Close a connection to an EL737 counter.
** EL737_Config - Configure a connection to an EL737 counter.
** EL737_Continue - Continue a measurement with an EL737 counter.
** EL737_EnableThresh - Enable/disable threshold monitoring.
** EL737_ErrInfo - Return detailed status from last operation.
** EL737_GetMonIntegTime - Get Monitor Integration Time (DI register).
** EL737_GetRateIntegTime - Get Rate Integration Time (DT register).
** EL737_GetStatus - Get 4 counters and counter status.
** EL737_GetStatusExtra - Get counters 5 to 8.
** EL737_GetThresh - Get threshold monitoring status.
** EL737_Open - Open a connection to an EL737 counter.
** EL737_Pause - Pause a measurement with an EL737 counter.
** EL737_SendCmnd - Send a command to RS232C server.
** EL737_SetErrcode - Set up EL737_errcode.
** EL737_SetThresh - Set threshold monitoring level.
** EL737_StartCnt - Start a preset cnt measurement with an EL737.
** EL737_StartTime - Start a preset time measurement with an EL737.
** EL737_Stop - Stop a measurement with an EL737 counter.
** EL737_StopFast - Same as EL737_Stop but no registers are returned.
** EL737_WaitIdle - Wait till status goes to zero.
**---------------------------------------------------------------------
** int EL737_Close (&handle, force_flag)
** -----------
** Input Args:
** int force_flag - if non-zero, all connections using the same socket
** will also be closed (this gets AsynSrv_Close to
** actually close the socket and is needed for error
** recovery operations).
** Output Args:
** none
** Modified Args:
** void **handle - The pointer to the structure returned by EL737_Open.
** On return, the pointer is set to NULL.
** Return status:
** True always (error returns from close and free are not checked).
** Routines called:
** AsynSrv_Close
** Description:
** The routine calls AsynSrv_Close to close the connection to the RS232C
** server. If 'force_flag' is non-zero, all other connections to the
** RS232C server which use the same socket will also be closed.
**
** The 'force_flag' can be useful in error recovery situations. The AsynSrv
** utility operates by only opening a socket for each separate combination
** of host/port. Hence, if several connections are open to a server,
** then calling EL737_Close doesn't actually close the socket until all
** connections have been closed. In the situation where an error has been
** detected, it is often desirable to close and re-open the socket as part
** of the recovery procedure. Calling EL737_Close with 'force_flag'
** non-zero will force the socket to be closed and will mark all other
** connections using this socket so that they will be informed of the
** event when they next call try to be used.
**
** Note: The force-close action is effected by the AsynSrv package. A
** force-close will thus also close any connections to other
** RS-232-C devices (e.g. EL734 motors) on the same server.
**-------------------------------------------------------------------------
** int EL737_Config (&handle, &par_id, par_val, ...)
** ------------
** Input Args:
** char* par_id - Text string identifying the next argument (see below).
** NULL indicates the end of the argument list.
** <??> par_val - The value to set for the argument. The type of the
** argument can depend on par_id.
** Output Args:
** none
** Modified Args:
** void **handle - The pointer to the structure returned by EL737_Open.
** It is used to hold the config info for the connection.
** Return status:
** True if no problems detected, otherwise False and EL737_errcode
** is set to indicate the nature of the problem as follows:
** EL737__BAD_PAR --> Unrecognised par_id or msecTmo < 100 or
** msecTmo > 999'999 or bad eot or ..
** Routines called:
** none
** Description:
** The routine sets values in the EL737info data structure. Values which
** may be taken by par_id (warning -- par_id is case-sensitive) and the
** corresponding variable type of par_val are:
**
** "msecTmo" int The time-out response for commands sent to
** the EL737. The valid range is 100 to
** 999'999. Default is 10'000.
** "eot" char* The expected terminators in responses to
** commands sent to the EL737. The first
** character specifies the number of
** terminators (max=3). Default is "1\r".
**-------------------------------------------------------------------------
** int EL737_Continue (&handle, &status)
** --------------
** Input Args:
** void **handle - The pointer to the structure returned by EL737_Open.
** Output Args:
** int *status - The status (RS) of the counter after the CO cmnd.
** Modified Args:
** none
** Return status:
** True if no problems detected, otherwise False and EL737_ErrInfo
** can be called to identify the problem. Values of Errcode set by
** EL737_Continue are (other values may be set by the called routines):
** EL737__OFL, __BAD_CMD, __BAD_TMO, __BAD_ASYNSRV --> see EL737_Open.
** EL737__BAD_ILLG --> the response to the RS command was probably not
** an integer. This could happen if there is noise
** on the RS232C connection to the EL737.
** If an error is detected, *status is set to 0.
** Routines called:
** AsynSrv_SendCmnds
** Description:
** EL737_Continue sends a CO command to the counter to get it to continue
** a paused measurement and then an RS command to read its status.
**-------------------------------------------------------------------------
** int EL737_EnableThresh (&handle, indx)
** ------------------
** Input Args:
** void **handle - The pointer to the structure returned by EL737_Open.
** int indx - The number of the counter to select as the "active"
** threshold monitoring counter. If (indx == 0),
** threshold monitoring is disabled.
** Output Args:
** none
** Modified Args:
** none
** Return status:
** True if no problems detected, otherwise False and EL737_ErrInfo
** can be called to identify the problem. Values of Errcode set by
** EL737_EnableThresh are (other values may be set by the called routines):
** EL737__OFL, __BAD_CMD, __BAD_TMO, __BAD_ASYNSRV --> see EL737_Open.
** EL737__BAD_BSY --> "?2" response received - cntr probably in
** wrong state.
** EL737__BAD_PAR --> Bad parameter. Illegal value for <indx> or "?3"
** or "?4" response received.
** EL737__BAD_ILLG --> the response to the commands was illegal in
** some way. This could happen if there is noise
** on the RS232C connection to the EL737.
** Routines called:
** AsynSrv_SendCmnds
** Description:
** A "DR <indx>" command is sent to select counter <indx> to be the
** "active" threshold monitoring counter. A value of 0 causes
** threshold monitoring to be disabled in the EL737. The threshold
** for the selected counter will not be changed. If it is required
** to set a threshold value as well as enabling monitoring, it is
** simplest to use EL737_SetThresh.
**-------------------------------------------------------------------------
** void EL737_ErrInfo (&entry_txt_ptr, &errcode, &my_errno, &vaxc_errno)
** -------------
** Input Args:
** None
** Output Args:
** char **entry_txt_ptr - Pointer to a text string giving the call stack
** at the time that the error was detected.
** int *errcode - An internal error code indicating the detected error.
** int *my_errno - Saved value of errno.
** int *vaxc_errno - Saved value of vaxc$errno (OpenVMS only).
** Modified Args:
** none
** Return status:
** none
** Routines called:
** none
** Description:
** Returns detailed status of the last operation. Once an error has been
** detected, the error status is frozen until this routine has been called.
**-------------------------------------------------------------------------
** int EL737_GetMonIntegTime (&handle, indx, &mon_integ_time)
** ---------------------
** Input Args:
** void **handle - The pointer to the structure returned by EL737_Open.
** int indx - The counter whose integ time is wanted.
** Output Args:
** float *mon_integ_time - The integration time used for monitoring
** the rate threshold.
** Modified Args:
** none
** Return status:
** True if no problems detected, otherwise False and EL737_ErrInfo
** can be called to identify the problem. Values of Errcode set by
** EL737_GetMonIntegTime are (other values may be set by the called
** routines):
** EL737__BAD_TMO, _LOC, _CMD, _OFL, _ADR, _ASYNSRV --> see EL737_Open.
** EL737__BAD_ILLG --> the response was probably not a floating point
** number. This could happen if there is noise
** on the RS232C connection to the EL737.
** If an error is detected, *mon_integ_time is set to 0.1.
** Routines called:
** AsynSrv_SendCmnds
** Description:
** The routine issues a "DI <indx>" command to the controller and
** analyses the result.
**-------------------------------------------------------------------------
** int EL737_GetRateIntegTime (&handle, &rate_integ_time)
** ----------------------
** Input Args:
** void **handle - The pointer to the structure returned by EL737_Open.
** Output Args:
** float *rate_integ_time - The integration time used for calculating
** the rates.
** Modified Args:
** none
** Return status:
** True if no problems detected, otherwise False and EL737_ErrInfo
** can be called to identify the problem. Values of Errcode set by
** EL737_GetRateIntegTime are (other values may be set by the called
** routines):
** EL737__BAD_TMO, _LOC, _CMD, _OFL, _ADR, _ASYNSRV --> see EL737_Open.
** EL737__BAD_ILLG --> the response was probably not a floating point
** number. This could happen if there is noise
** on the RS232C connection to the EL737.
** If an error is detected, *rate_integ_time is set to 0.1.
** Routines called:
** AsynSrv_SendCmnds
** Description:
** The routine issues a DT command to the controller and
** analyses the result.
**-------------------------------------------------------------------------
** int EL737_GetStatus (&handle, &c1, &c2, &c3, &c4, &timer, &rs)
** ---------------
** Input Args:
** void **handle - The pointer to the structure returned by EL737_Open.
** Output Args:
** int *c1 - Counter 1 (Monitor).
** int *c2 - Counter 2 (Detector).
** int *c3 - Counter 3.
** int *c4 - Counter 4.
** float *timer - The measured time.
** int *rs - The counter status (RS command).
** Modified Args:
** none
** Return status:
** True if no problems detected, otherwise False and EL737_ErrInfo
** can be called to identify the problem. Values of Errcode set by
** EL737_GetStatus are (other values may be set by the called routines):
** EL737__BAD_TMO, _LOC, _CMD, _OFL, _ADR, _ASYNSRV --> see EL737_Open.
** EL737__BAD_ILLG --> one of the responses could probably not be
** decoded. This could happen if there is noise
** on the RS232C connection to the EL737.
** If an error is detected, all arguments are set to 0.
** Routines called:
** AsynSrv_SendCmnds
** Description:
** The routine issues an RA and RS command to the controller and
** analyses the result. If a syntax error is detected in either the RA
** or RS response, the routine tries up to 3 times to get a meaningful
** reply.
**-------------------------------------------------------------------------
** int EL737_GetStatusExtra (&handle, &c5, &c6, &c7, &c8)
** --------------------
** Input Args:
** void **handle - The pointer to the structure returned by EL737_Open.
** Output Args:
** int *c5 - Counter 5.
** int *c6 - Counter 6.
** int *c7 - Counter 7.
** int *c8 - Counter 8.
** Modified Args:
** none
** Return status:
** True always.
** Routines called:
** None
** Description:
** The routine returns values for the counters 5, 6, 7 and 8 from the
** counter's structure. A successful call to any of the routines which
** return values for counters 1, 2, 3 and 4 must precede a call to
** EL737_GetStatusExtra.
**-------------------------------------------------------------------------
** int EL737_GetThresh (&handle, &indx, &val)
** ---------------
** Input Args:
** void **handle - The pointer to the structure returned by EL737_Open.
** Output Args:
** int *indx - The number of the threshold monitor counter. If =0,
** threshold monitoring is disabled.
** float *val - If *indx != 0, the value of the threshold. Otherwise,
** it is zero.
** Modified Args:
** none
** Return status:
** True if no problems detected, otherwise False and EL737_ErrInfo
** can be called to identify the problem. Values of Errcode set by
** EL737_GetThresh are (other values may be set by the called routines):
** EL737__BAD_TMO, _LOC, _CMD, _OFL, _ADR, _ASYNSRV --> see EL737_Open.
** EL737__BAD_ILLG --> one of the responses could probably not be
** decoded. This could happen if there is noise
** on the RS232C connection to the EL737.
** If an error is detected, all arguments are set to 0.
** Routines called:
** AsynSrv_SendCmnds
** Description:
** The routine issues a DR and, if threshold monitoring is enabled,
** a "DL <indx>" command to the controller and analyses the responses.
**-------------------------------------------------------------------------
** int EL737_Open (&handle, &host, port, chan)
** ----------
** Input Args:
** char *host - Name of host offering the TCP/IP service.
** int port - Number of TCP/IP port of TCP/IP server.
** int chan - RS-232-C Channel number on the TCP/IP server.
** Output Args:
** void *handle - A pointer to a structure of type EL737info needed for
** subsequent calls to EL737_... routines. Buffer space
** for the structure is allocated dynamically. It gets
** released via a call to EL737_Close.
** Modified Args:
** none
** Return status:
** True if no problems detected, otherwise False. If False, EL737_ErrInfo
** can be called to identify the problem. Values of Errcode set by
** EL737_Open are (other values may be set by the called routines):
** EL737__BAD_TMO --> Time-out error ("?TMO" - this gets
** generated by the RS232C server).
** EL737__BAD_LOC --> EL737 off-line ("?OF"). This should not
** happen on calls to EL737_Open since it
** sends an "RMT 1" cmnd.
** EL737__BAD_CMD --> Syntax error ("?1"). This could be
** caused by noise in the RS-232-C
** transmission.
** EL737__BAD_OFL --> Connection to EL737 broken ("?OFL").
** This can get generated by RS232C_SRV
** if, for example, the connection is via
** a terminal server and the terminal
** server loses power.
** EL737__BAD_ILLG --> Some other unrecognised response. This
** should never occur, of course!
** EL737__BAD_DEV --> Device doesn't seem to be an EL737. The
** response to the RA command was bad.
** EL737__BAD_MALLOC --> Call to "malloc" failed.
** EL737__BAD_ASYNSRV --> Call to AsynSrv_SendCmnds failed. Use
** AsynSrv_ErrInfo to get more details.
** Routines called:
** AsynSrv_Open, memory allocation routine "malloc" and AsynSrv_SendCmnds.
** Description:
** The routine opens a TCP/IP connection to a server offering the
** "RS-232-C" service for an EL737 Neutron Counter. "RMT 1" and
** "ECHO 2" commands are sent to ensure the device is on-line and an RA
** command is sent to ensure that an EL737 is being addressed.
**-------------------------------------------------------------------------
** int EL737_Pause (&handle, &status)
** -----------
** Input Args:
** void **handle - The pointer to the structure returned by EL737_Open.
** Output Args:
** int *status - The status (RS) of the counter after the PS cmnd.
** Modified Args:
** none
** Return status:
** True if no problems detected, otherwise False and EL737_ErrInfo
** can be called to identify the problem. Values of Errcode set by
** EL737_Pause are (other values may be set by the called routines):
** EL737__OFL, __BAD_CMD, __BAD_TMO, __BAD_ASYNSRV --> see EL737_Open.
** EL737__BAD_ILLG --> the response to the RS command was probably not
** an integer. This could happen if there is noise
** on the RS232C connection to the EL737.
** If an error is detected, *status is set to 0.
** Routines called:
** AsynSrv_SendCmnds
** Description:
** EL737_Pause sends a PS command to the counter to get it to pause
** a measurement and then an RS command to read its status.
**-------------------------------------------------------------------------
** int EL737_SendCmnd (&handle, &cmnd, &rply, rply_size)
** --------------
** Input Args:
** void **handle - The pntr to the structure returned by EL737_Open.
** char *cmnd - A command, terminated by NULL, for sending to the
** EL737 counter controller. The command must have
** any necessary \r character included.
** int rply_size - the size of the <rply> buffer.
** Output Args:
** char *rply - A buffer for receiving the reply.
** Modified Args:
** none
** Return status:
** True if no problems detected, otherwise False and errcode (see
** EL737_ErrInfo) is set to indicate the nature of the problem.
** EL737_errcode may be set as follows:
** EL737__BAD_ASYNSRV --> An error occurred in AsynSrv_Utility.
** Call AsynSrv_ErrInfo for more info.
** Routines called:
** AsynSrv_SendCmnds
** Description:
** The command is passed to AsynSrv_SendCmnds and the reply extracted.
**-------------------------------------------------------------------------
** int EL737_SetErrcode (&info_ptr, &response, &cmnd)
** ----------------
** Set up EL737_errcode (for internal use only)
** Input Args:
** struct EL737info *info_ptr - The pntr to the structure returned by
** EL737_Open.
** char *response - The response received from a command.
** char *cmnd - The command which was sent.
** Output Args:
** none
** Modified Args:
** none
** Return status:
** The value of EL737_errcode.
** Routines called:
** none
** Description:
** The command checks *response for certain keywords and sets EL737_errcode
** accordingly.
**-------------------------------------------------------------------------
** int EL737_SetThresh (&handle, indx, val)
** ---------------
** Input Args:
** void **handle - The pointer to the structure returned by EL737_Open.
** int indx - The number of the counter whose threshold is to
** be set. If (indx == 0), threshold monitoring is
** disabled and val is not used.
** float val - The value of the threshold to be set.
** Output Args:
** none
** Modified Args:
** none
** Return status:
** True if no problems detected, otherwise False and EL737_ErrInfo
** can be called to identify the problem. Values of Errcode set by
** EL737_SetThresh are (other values may be set by the called routines):
** EL737__OFL, __BAD_CMD, __BAD_TMO, __BAD_ASYNSRV --> see EL737_Open.
** EL737__BAD_BSY --> "?2" response received - cntr probably in
** wrong state.
** EL737__BAD_PAR --> Bad parameter. Illegal value for <indx> or "?3"
** or "?4" response received.
** EL737__BAD_ILLG --> the response to the commands was illegal in
** some way. This could happen if there is noise
** on the RS232C connection to the EL737.
** Routines called:
** AsynSrv_SendCmnds, EL737_EnableThresh
** Description:
** a) If (indx == 0): EL737_SetThresh simply calls EL737_EnableThresh to
** send a "DR 0" command which will disable threshold
** monitoring by the counter.
**
** b) If (indx != 0): First of all, a "DL <indx> |<val>|" command is sent
** to the counter to set the threshold for counter <indx>
** to the absolute value of <val>.
** Then, if (val >= 0), EL737_EnableThresh is then called
** to select counter <indx> to be the "active" threshold
** monitoring counter. Otherwise, the "active" counter
** is not changed.
**-------------------------------------------------------------------------
** int EL737_StartCnt (&handle, count, &status)
** --------------
** Input Args:
** void **handle - The pointer to the structure returned by EL737_Open.
** int count - The preset-count for the measurement.
** Output Args:
** int *status - The status (RS) of the counter after the MP cmnd.
** Modified Args:
** none
** Return status:
** True if no problems detected, otherwise False and EL737_ErrInfo
** can be called to identify the problem. Values of Errcode set by
** EL737_StartCnt are (other values may be set by the called routines):
** EL737__OFL, __BAD_CMD, __BAD_TMO, __BAD_ASYNSRV --> see EL737_Open.
** EL737__BAD_BSY --> "?2" response received - cntr probably in
** wrong state.
** EL737__BAD_PAR --> "?3" response received - bad parameter.
** EL737__BAD_ILLG --> the response to the RS command was probably not
** an integer. This could happen if there is noise
** on the RS232C connection to the EL737.
** If an error is detected, *status is set to 0.
** Routines called:
** AsynSrv_SendCmnds
** Description:
** EL737_StartCnt sends a MP command to the counter to get it to start
** a preset-count measurement and then an RS command to read its status.
**-------------------------------------------------------------------------
** int EL737_StartTime (&handle, timer, &status)
** ---------------
** Input Args:
** void **handle - The pointer to the structure returned by EL737_Open.
** float timer - The preset-time for the measurement.
** Output Args:
** int *status - The status (RS) of the counter after the TP cmnd.
** Modified Args:
** none
** Return status:
** True if no problems detected, otherwise False and EL737_ErrInfo
** can be called to identify the problem. Values of Errcode set by
** EL737_StartTime are (other values may be set by the called routines):
** EL737__OFL, __BAD_CMD, __BAD_TMO, __BAD_ASYNSRV --> see EL737_Open.
** EL737__BAD_BSY --> "?2" response received - cntr probably in
** wrong state.
** EL737__BAD_PAR --> "?3" response received - bad parameter.
** EL737__BAD_ILLG --> the response to the RS command was probably not
** an integer. This could happen if there is noise
** on the RS232C connection to the EL737.
** If an error is detected, *status is set to 0.
** Routines called:
** AsynSrv_SendCmnds
** Description:
** EL737_StartTime sends a TP command to the counter to get it to start
** a preset-time measurement and then an RS command to read its status.
**-------------------------------------------------------------------------
** int EL737_Stop (&handle, &c1, &c2, &c3, &c4, &timer, &rs)
** ----------
** Input Args:
** void **handle - The pointer to the structure returned by EL737_Open.
** Output Args:
** int *c1 - Counter 1 (Monitor).
** int *c2 - Counter 2 (Detector).
** int *c3 - Counter 3.
** int *c4 - Counter 4.
** float *timer - The measured time.
** int *rs - The counter status (RS command) after the S cmnd.
** Modified Args:
** none
** Return status:
** True if no problems detected, otherwise False and EL737_ErrInfo
** can be called to identify the problem. Values of Errcode set by
** EL737_Stop are (other values may be set by the called routines):
** EL737__OFL, __BAD_CMD, __BAD_TMO, __BAD_ASYNSRV --> see EL737_Open.
** EL737__BAD_ILLG --> the response to the RA or RS command was
** probably not an integer. This could happen if
** there is noise on the RS232C connection to the
** EL737.
** If an error is detected, all output args are set to 0.
** Routines called:
** AsynSrv_SendCmnds
** Description:
** EL737_Stop sends an S command to the counter to get it to stop
** a measurement. It then calls EL737_GetStatus to read the registers
** and status.
**-------------------------------------------------------------------------
** int EL737_StopFast (&handle)
** --------------
** Input Args:
** void **handle - The pointer to the structure returned by EL737_Open.
** Output Args:
** None
** Modified Args:
** none
** Return status:
** See EL737_Stop
** Routines called:
** AsynSrv_SendCmnds
** Description:
** EL737_StopFast sends an S command to the counter to get it to stop
** a measurement. Unlike EL737_Stop, the registers are not read out.
**-------------------------------------------------------------------------
** int EL737_WaitIdle (&handle, &c1, &c2, &c3, &c4, &timer)
** --------------
** Input Args:
** void **handle - The pntr to the structure returned by EL737_Open.
** Output Args:
** int *c1 \
** int *c2 \
** int *c3 \ Same as EL737_GetStatus.
** int *c4 /
** float *timer /
** Modified Args:
** none
** Return status:
** True if no problems detected, otherwise False and Errcode (see
** EL737_ErrInfo) will have been set by the called routines to indicate
** the nature of the problem.
** Routines called:
** EL737_GetStatus
** Description:
** Routine EL737_GetStatus is called repeatedly at a predefined frequency
** until the RS register is zero.
**============================================================================*/
/*
**---------------------------------------------------------------------------
** Global Definitions
*/
#include <stdlib.h>
#include <stdio.h>
#include <stdarg.h>
#include <math.h>
#include <errno.h>
#include <signal.h>
#include <netdb.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <string.h>
#ifdef __VMS
#include <unixio.h>
#else
#include <unistd.h>
#ifdef FORTIFY
#include <fortify.h>
#endif
#endif
/*-----------------------------------------------------------------*/
#include <sinq_prototypes.h>
#include <el737_def.h>
#include <rs232c_def.h>
#define True 1
#define False 0
/*--------------------------------------------------------------------------
** Global Variables
*/
static int EL737_call_depth = 0;
static char EL737_routine[5][64];
static int EL737_errcode = 0;
static int EL737_errno, EL737_vaxc_errno;
/*
**---------------------------------------------------------------------------
** EL737_AddCallStack: Add a routine name to the call stack.
** This allows EL737_ErrInfo to generate a
** trace-back in case of error.
*/
int EL737_AddCallStack(
/* ==================
*/ struct EL737info *pntr,
char *name)
{
if (EL737_errcode != 0)
return False;
if (EL737_call_depth < 5) {
strcpy(EL737_routine[EL737_call_depth], name);
EL737_call_depth++;
}
if (pntr == NULL) {
EL737_errcode = EL737__NOT_OPEN;
return False;
}
if (pntr->asyn_info.skt <= 0) {
memset(pntr->from_host.msg_size,
'0', sizeof(pntr->from_host.msg_size));
EL737_errcode = (pntr->asyn_info.skt < 0) ? EL737__FORCED_CLOSED
: EL737__NO_SOCKET;
return False;
}
return True;
}
/*
**---------------------------------------------------------------------------
** EL737_Close: Close a connection to an EL737 counter.
*/
int EL737_Close(
/* ===========
*/ void **handle,
int force_flag)
{
struct EL737info *info_ptr;
char buff[4];
info_ptr = (struct EL737info *) *handle;
if (info_ptr == NULL)
return True;
if (info_ptr->asyn_info.skt != 0) {
if (info_ptr->asyn_info.skt > 0) {
AsynSrv_Close(*handle, force_flag);
}
}
free(*handle);
*handle = NULL;
return True;
}
/*
**---------------------------------------------------------------------------
** EL737_Config: Configure a connection to an EL737 counter.
*/
int EL737_Config(
/* ============
*/ void **handle,
...)
{
char buff[16];
va_list ap; /* Pointer to variable args */
char *txt_ptr;
int intval;
struct EL737info *info_ptr;
/*----------------------------------------------
*/
info_ptr = (struct EL737info *) *handle;
if (!EL737_AddCallStack(info_ptr, "EL737_Config"))
return False;
/*----------------------------------------------
*/
va_start(ap, handle); /* Set up var arg machinery */
txt_ptr = va_arg(ap, char *); /* Get pntr to first parameter ident */
while (txt_ptr != NULL) {
if (strcmp(txt_ptr, "msecTmo") == 0) {
intval = va_arg(ap, int);
if ((intval < 100) || (intval > 999999)) {
EL737_errcode = EL737__BAD_PAR;
return False;
}
sprintf(buff, "%04d", intval / 100); /* Convert to ASCII as ..
** .. deci-secs */
memcpy(info_ptr->asyn_info.tmo, buff, 4);
} else if (strcmp(txt_ptr, "eot") == 0) {
txt_ptr = va_arg(ap, char *);
if (txt_ptr == NULL) {
EL737_errcode = EL737__BAD_PAR;
return False;
}
memcpy(info_ptr->asyn_info.eot, "\0\0\0\0", 4);
switch (txt_ptr[0]) {
case '3':
info_ptr->asyn_info.eot[3] = txt_ptr[3];
case '2':
info_ptr->asyn_info.eot[2] = txt_ptr[2];
case '1':
info_ptr->asyn_info.eot[1] = txt_ptr[1];
case '0':
info_ptr->asyn_info.eot[0] = txt_ptr[0];
break;
default:
EL737_errcode = EL737__BAD_PAR;
return False;
}
} else {
EL737_errcode = EL737__BAD_PAR;
return False;
}
txt_ptr = va_arg(ap, char *); /* Get pntr to next parameter ident */
}
if (EL737_errcode != 0)
return False;
EL737_call_depth--;
return True;
}
/*
**---------------------------------------------------------------------------
** EL737_Continue: Continue a measurement with an EL737 counter.
*/
int EL737_Continue(
/* ==============
*/ void **handle,
int *status)
{
int my_status;
struct EL737info *info_ptr;
char *rply_ptr0, *rply_ptr1;
/*----------------------------------------------
*/
*status = 0;
info_ptr = (struct EL737info *) *handle;
if (!EL737_AddCallStack(info_ptr, "EL737_Continue"))
return False;
/*----------------------------------------------
** Send CO and RS cmnds to EL737
*/
my_status = AsynSrv_SendCmnds(&info_ptr->asyn_info,
&info_ptr->to_host, &info_ptr->from_host,
"CO\r", "RS\r", NULL);
if (!my_status) {
EL737_errcode = EL737__BAD_ASYNSRV;
return False;
}
rply_ptr1 = NULL;
rply_ptr0 =
AsynSrv_GetReply(&info_ptr->asyn_info, &info_ptr->from_host, NULL);
if (rply_ptr0 != NULL)
rply_ptr1 =
AsynSrv_GetReply(&info_ptr->asyn_info, &info_ptr->from_host,
rply_ptr0);
if (rply_ptr0 == NULL)
rply_ptr0 = "?";
if (rply_ptr1 == NULL)
rply_ptr1 = "?";
if (((*rply_ptr0 == '\0') || (*rply_ptr0 == '\r')) &&
(sscanf(rply_ptr1, "%d", status) == 1)) {
if (EL737_errcode != 0)
return False;
EL737_call_depth--;
return True;
}
*status = 0;
EL737_SetErrcode(info_ptr, rply_ptr0, "CO\" or \"RS");
return False;
}
/*
**---------------------------------------------------------------------------
** EL737_EnableThresh: Enable/disable Threshold Monitoring.
*/
int EL737_EnableThresh(
/* ==================
*/ void **handle,
int indx)
{
int status;
char cmnd[20];
struct EL737info *info_ptr;
char *rply_ptr0;
/*----------------------------------------------
*/
info_ptr = (struct EL737info *) *handle;
if (!EL737_AddCallStack(info_ptr, "EL737_EnableThresh"))
return False;
if ((indx < 0) || (indx > 8)) {
EL737_errcode = EL737__BAD_PAR;
return False;
}
/*----------------------------------------------
** Send "DR <indx>" cmnd to EL737 to select the
** "active" threshold rate counter.
*/
sprintf(cmnd, "DR %d\r", indx);
status = AsynSrv_SendCmnds(&info_ptr->asyn_info,
&info_ptr->to_host, &info_ptr->from_host,
cmnd, NULL);
if (!status) {
EL737_errcode = EL737__BAD_ASYNSRV;
return False;
}
rply_ptr0 =
AsynSrv_GetReply(&info_ptr->asyn_info, &info_ptr->from_host, NULL);
if (rply_ptr0 == NULL)
rply_ptr0 = "?";
if ((*rply_ptr0 == '\0') || (*rply_ptr0 == '\r')) {
EL737_call_depth--;
return True;
}
EL737_SetErrcode(info_ptr, rply_ptr0, cmnd);
return False;
}
/*
** -------------------------------------------------------------------------
** EL737_ErrInfo: Return detailed status from last operation.
*/
void EL737_ErrInfo(
/* =============
*/ char **entry_txt,
int *errcode, int *my_errno, int *vaxc_errno)
{
int i;
char buff[80];
int asyn_errcode, asyn_errno, asyn_vaxerrno;
char *asyn_errtxt;
if (EL737_call_depth <= 0) {
strcpy(EL737_routine[0], "EL737_no_error_detected");
*errcode = 0;
*my_errno = 0;
*vaxc_errno = 0;
} else {
if (EL737_call_depth > 1) { /* Concatenate the names */
for (i = 1; i < EL737_call_depth; i++) {
strcat(EL737_routine[0], "/");
StrJoin(EL737_routine[0], sizeof(EL737_routine),
EL737_routine[0], EL737_routine[i]);
}
}
*errcode = EL737_errcode;
*my_errno = EL737_errno;
*vaxc_errno = EL737_vaxc_errno;
switch (EL737_errcode) {
case EL737__BAD_ASYNSRV:
strcpy(buff, "/EL737__BAD_ASYNSRV");
break;
case EL737__BAD_BSY:
strcpy(buff, "/EL737__BAD_BSY");
break;
case EL737__BAD_CMD:
strcpy(buff, "/EL737__BAD_CMD");
break;
case EL737__BAD_CNTR:
strcpy(buff, "/EL737__BAD_CNTR");
break;
case EL737__BAD_DEV:
strcpy(buff, "/EL737__BAD_DEV");
break;
case EL737__BAD_ILLG:
strcpy(buff, "/EL737__BAD_ILLG");
break;
case EL737__BAD_LOC:
strcpy(buff, "/EL737__BAD_LOC");
break;
case EL737__BAD_MALLOC:
strcpy(buff, "/EL737__BAD_MALLOC");
break;
case EL737__BAD_OFL:
strcpy(buff, "/EL737__BAD_OFL");
break;
case EL737__BAD_OVFL:
strcpy(buff, "/EL737__BAD_OVFL");
break;
case EL737__BAD_PAR:
strcpy(buff, "/EL737__BAD_PAR");
break;
case EL737__BAD_SOCKET:
strcpy(buff, "/EL737__BAD_SOCKET");
break;
case EL737__BAD_TMO:
strcpy(buff, "/EL737__BAD_TMO");
break;
case EL737__CNTR_OVFL:
strcpy(buff, "/EL737__CNTR_OVFL");
break;
case EL737__FORCED_CLOSED:
strcpy(buff, "/EL737__FORCED_CLOSED");
break;
case EL737__NOT_OPEN:
strcpy(buff, "/EL737__NOT_OPEN");
break;
case EL737__NO_SOCKET:
strcpy(buff, "/EL737__NO_SOCKET");
break;
case EL737__NO_VALUE:
strcpy(buff, "/EL737__NO_VALUE");
break;
default:
sprintf(buff, "/EL737__unknown_err_code: %d", EL737_errcode);
}
StrJoin(EL737_routine[0], sizeof(EL737_routine), EL737_routine[0],
buff);
}
AsynSrv_ErrInfo(&asyn_errtxt, &asyn_errcode, &asyn_errno,
&asyn_vaxerrno);
if (asyn_errcode != 0) {
strcat(EL737_routine[0], "/");
StrJoin(EL737_routine[0], sizeof(EL737_routine),
EL737_routine[0], asyn_errtxt);
}
*entry_txt = EL737_routine[0];
EL737_call_depth = 0;
EL737_errcode = 0;
}
/*
**---------------------------------------------------------------------------
** EL737_GetMonIntegTime: Get DI register value for a counter.
*/
int EL737_GetMonIntegTime(
/* =====================
*/ void **handle,
int indx, float *mon_integ_time)
{
int status;
char cmnd[20];
struct EL737info *info_ptr;
char *rply_ptr0;
/*----------------------------------------------
*/
*mon_integ_time = 0.1;
info_ptr = (struct EL737info *) *handle;
if (!EL737_AddCallStack(info_ptr, "EL737_GetMonIntegTime"))
return False;
/*----------------------------------------------
** Send "DI <indx>" cmnd to EL737
*/
sprintf(cmnd, "DI %d\r", indx);
status = AsynSrv_SendCmnds(&info_ptr->asyn_info,
&info_ptr->to_host, &info_ptr->from_host,
cmnd, NULL);
if (!status) {
EL737_errcode = EL737__BAD_ASYNSRV;
return False;
} else {
rply_ptr0 =
AsynSrv_GetReply(&info_ptr->asyn_info, &info_ptr->from_host, NULL);
if (rply_ptr0 == NULL)
rply_ptr0 = "?";
if (sscanf(rply_ptr0, "%f", mon_integ_time) == 1) {
if (EL737_errcode != 0)
return False;
EL737_call_depth--;
return True;
}
*mon_integ_time = 0.1;
EL737_SetErrcode(info_ptr, rply_ptr0, cmnd);
return False;
}
}
/*
**---------------------------------------------------------------------------
** EL737_GetRateIntegTime: Get DT register value.
*/
int EL737_GetRateIntegTime(
/* ======================
*/ void **handle,
float *rate_integ_time)
{
int status;
struct EL737info *info_ptr;
char *rply_ptr0;
/*----------------------------------------------
*/
*rate_integ_time = 0.1;
info_ptr = (struct EL737info *) *handle;
if (!EL737_AddCallStack(info_ptr, "EL737_GetRateIntegTime"))
return False;
/*----------------------------------------------
** Send DT cmnd to EL737
*/
status = AsynSrv_SendCmnds(&info_ptr->asyn_info,
&info_ptr->to_host, &info_ptr->from_host,
"DT\r", NULL);
if (!status) {
EL737_errcode = EL737__BAD_ASYNSRV;
return False;
} else {
rply_ptr0 =
AsynSrv_GetReply(&info_ptr->asyn_info, &info_ptr->from_host, NULL);
if (rply_ptr0 == NULL)
rply_ptr0 = "?";
if (sscanf(rply_ptr0, "%f", rate_integ_time) == 1) {
if (EL737_errcode != 0)
return False;
EL737_call_depth--;
return True;
}
EL737_SetErrcode(info_ptr, rply_ptr0, "DT");
*rate_integ_time = 0.1;
return False;
}
}
/*
**---------------------------------------------------------------------------
** EL737_GetStatus: Get RA/RS register values.
*/
int EL737_GetStatus(
/* ===============
*/ void **handle,
int *c1,
int *c2, int *c3, int *c4, float *timer, int *rs)
{
int i, status, nvals;
struct EL737info *info_ptr;
char *rply_ptr, *p_cmnd;
/*----------------------------------------------
*/
*c1 = *c2 = *c3 = *c4 = *rs = 0;
*timer = 0.0;
info_ptr = (struct EL737info *) *handle;
if (!EL737_AddCallStack(info_ptr, "EL737_GetStatus"))
return False;
info_ptr->c5 = info_ptr->c6 = info_ptr->c7 = info_ptr->c8 = 0;
/*----------------------------------------------
** Send RA and RS cmnds to EL737. Since this routine gets
** used such a lot, try up to 3 times if a syntax error in
** the reply is detected.
*/
for (i = 0; i < 3; i++) {
status = AsynSrv_SendCmnds(&info_ptr->asyn_info,
&info_ptr->to_host, &info_ptr->from_host,
"RA\r", "RS\r", NULL);
if (!status) {
EL737_errcode = EL737__BAD_ASYNSRV;
return False;
}
p_cmnd = "RA";
rply_ptr =
AsynSrv_GetReply(&info_ptr->asyn_info, &info_ptr->from_host, NULL);
if (rply_ptr != NULL) {
nvals = sscanf(rply_ptr, "%f %d %d %d %d %d %d %d %d",
timer, c1, c2, c3, c4,
&info_ptr->c5, &info_ptr->c6,
&info_ptr->c7, &info_ptr->c8);
if (nvals != 9)
nvals = sscanf(rply_ptr, "%d %d %d %d %f", c1, c2, c3, c4, timer);
if (nvals == 5) {
info_ptr->c5 = info_ptr->c6 = info_ptr->c7 = info_ptr->c8 = 0;
nvals = 9;
}
if (nvals == 9) {
p_cmnd = "RS";
rply_ptr =
AsynSrv_GetReply(&info_ptr->asyn_info, &info_ptr->from_host,
rply_ptr);
if (rply_ptr != NULL) {
if (sscanf(rply_ptr, "%d", rs) == 1) {
EL737_call_depth--;
return True;
}
}
}
}
}
if (rply_ptr == NULL)
rply_ptr = "?";
EL737_SetErrcode(info_ptr, rply_ptr, p_cmnd);
*c1 = *c2 = *c3 = *c4 = *rs = 0;
*timer = 0.0;
return False;
}
/*
**---------------------------------------------------------------------------
** EL737_GetStatusExtra: Get values of extra counters.
*/
int EL737_GetStatusExtra(
/* ====================
*/ void **handle,
int *c5, int *c6, int *c7, int *c8)
{
struct EL737info *info_ptr;
/*----------------------------------------------
*/
*c5 = *c6 = *c7 = *c8 = 0;
info_ptr = (struct EL737info *) *handle;
if (!EL737_AddCallStack(info_ptr, "EL737_GetStatusExtra"))
return False;
*c5 = info_ptr->c5;
*c6 = info_ptr->c6;
*c7 = info_ptr->c7;
*c8 = info_ptr->c8;
if (EL737_errcode != 0)
return False;
EL737_call_depth--;
return True;
}
/*
**---------------------------------------------------------------------------
** EL737_GetThresh: Get threshold monitoring status.
*/
int EL737_GetThresh(
/* ===============
*/ void **handle,
int *indx, float *val)
{
int status, my_indx;
float my_val;
char cmnd[20];
struct EL737info *info_ptr;
char *rply_ptr0;
/*----------------------------------------------
*/
*indx = 0;
*val = 0.0;
info_ptr = (struct EL737info *) *handle;
if (!EL737_AddCallStack(info_ptr, "EL737_GetThresh"))
return False;
/*----------------------------------------------
** Send DR cmnd to EL737 to get the number of the
** "active" threshold rate counter.
*/
status = AsynSrv_SendCmnds(&info_ptr->asyn_info,
&info_ptr->to_host, &info_ptr->from_host,
"DR\r", NULL);
if (!status) {
EL737_errcode = EL737__BAD_ASYNSRV;
return False;
}
rply_ptr0 =
AsynSrv_GetReply(&info_ptr->asyn_info, &info_ptr->from_host, NULL);
if (rply_ptr0 == NULL)
rply_ptr0 = "?";
if ((sscanf(rply_ptr0, "%d", &my_indx) == 1) &&
(my_indx >= 0) && (my_indx <= 8)) {
*indx = my_indx;
if (my_indx != 0) {
/*----------------------------------------------
** Now send DL cmnd to EL737 to get the threshold value.
*/
sprintf(cmnd, "DL %d\r", my_indx);
status = AsynSrv_SendCmnds(&info_ptr->asyn_info,
&info_ptr->to_host, &info_ptr->from_host,
cmnd, NULL);
if (!status) {
EL737_errcode = EL737__BAD_ASYNSRV;
return False;
}
rply_ptr0 =
AsynSrv_GetReply(&info_ptr->asyn_info, &info_ptr->from_host,
NULL);
if (rply_ptr0 == NULL)
rply_ptr0 = "?";
if (sscanf(rply_ptr0, "%f", &my_val) == 1) {
*val = my_val;
EL737_call_depth--;
return True;
}
} else {
*val = 0.0;
EL737_call_depth--;
return True;
}
}
EL737_SetErrcode(info_ptr, rply_ptr0, cmnd);
return False;
}
/*
**---------------------------------------------------------------------------
** EL737_Open: Open a connection to an EL737 counter.
*/
int EL737_Open(
/* ==========
*/ void **handle,
char *host, int port, int chan)
{
int status, c1, c2, c3, c4, nvals;
float timer;
struct EL737info *my_handle;
char tmo_save[4];
char *rply_ptr;
char *rply_ptr0;
char *rply_ptr1;
char *rply_ptr2;
/*--------------------------------------------------------
** Initialise the error info stack and pre-set the
** routine name (in case of error).
*/
EL737_errcode = EL737_errno = EL737_vaxc_errno = 0;
strcpy(EL737_routine[0], "EL737_Open");
EL737_call_depth = 1;
/*--------------------------------------------------------
** Assume trouble
*/
*handle = NULL;
/*--------------------------------------------------------
** Reserve space for the data we need to store.
*/
my_handle = (struct EL737info *) malloc(sizeof(*my_handle));
if (my_handle == NULL) {
EL737_errcode = EL737__BAD_MALLOC; /* malloc failed!! */
return False;
}
memset(my_handle, 0, sizeof(*my_handle));
/*--------------------------------------------------------
** Set up the connection
*/
StrJoin(my_handle->asyn_info.host, sizeof(my_handle->asyn_info.host),
host, "");
my_handle->asyn_info.port = port;
my_handle->asyn_info.chan = chan;
status = AsynSrv_Open(&my_handle->asyn_info);
if (!status) {
EL737_errcode = EL737__BAD_SOCKET;
GetErrno(&EL737_errno, &EL737_vaxc_errno); /* Save errno info */
fprintf(stderr, "\nEL737_Open/AsynSrv_Open: "
"Failed to make connection.\n");
free(my_handle);
return False;
}
memcpy(tmo_save, my_handle->asyn_info.tmo, 4);
EL737_Config((void *) &my_handle, "msecTmo", 500, /* Set a short time-out initially since
** there should be no reason for the RMT,
** ECHO or RA commands to take very long
*/
"eot", "1\r", NULL);
/*
** Now ensure the EL737 is on-line. The first "RMT 1" command can
** fail due to pending characters in the EL737 input buffer causing
** the "RMT 1" to be corrupted. The response of the EL737 to this
** command is ignored for this reason (but the AsynSrv_SendCmnds
** status must be OK otherwise it indicates a network problem).
*/
status = AsynSrv_SendCmnds(&my_handle->asyn_info,
&my_handle->to_host, &my_handle->from_host,
"RMT 1\r", NULL);
if (status) {
status = AsynSrv_SendCmnds(&my_handle->asyn_info,
&my_handle->to_host, &my_handle->from_host,
"RMT 1\r", "ECHO 2\r", "RA\r", NULL);
}
if (!status) {
/* Some error occurred in AsynSrv_SendCmnds */
EL737_errcode = EL737__BAD_ASYNSRV;
AsynSrv_Close(&my_handle->asyn_info, False);
free(my_handle);
return False;
} else {
/* Check the responses carefully.
*/
rply_ptr1 = rply_ptr2 = NULL;
rply_ptr0 =
AsynSrv_GetReply(&my_handle->asyn_info, &my_handle->from_host,
NULL);
if (rply_ptr0 != NULL)
rply_ptr1 =
AsynSrv_GetReply(&my_handle->asyn_info, &my_handle->from_host,
rply_ptr0);
if (rply_ptr1 != NULL)
rply_ptr2 =
AsynSrv_GetReply(&my_handle->asyn_info, &my_handle->from_host,
rply_ptr1);
if (rply_ptr0 == NULL)
rply_ptr0 = "?";
if (rply_ptr1 == NULL)
rply_ptr1 = "?";
if (rply_ptr2 == NULL)
rply_ptr2 = "?";
if (*rply_ptr1 == '?')
rply_ptr0 = rply_ptr1;
if (*rply_ptr2 == '?')
rply_ptr0 = rply_ptr2;
if (*rply_ptr0 != '?') {
nvals = sscanf(rply_ptr2, "%f %d %d %d %d %d %d %d %d",
&timer, &c1, &c2, &c3, &c4,
&my_handle->c5, &my_handle->c6,
&my_handle->c7, &my_handle->c8);
if (nvals != 9)
nvals = sscanf(rply_ptr2, "%d %d %d %d %f",
&c1, &c2, &c3, &c4, &timer);
if (nvals == 5) {
my_handle->c5 = my_handle->c6 = my_handle->c7 = my_handle->c8 = 0;
nvals = 9;
}
if (nvals != 9) {
EL737_errcode = EL737__BAD_DEV; /* Device is not EL737 */
AsynSrv_Close(&my_handle->asyn_info, False);
free(my_handle);
return False;
}
memcpy(my_handle->asyn_info.tmo, tmo_save, 4); /* Restore time-out */
/*
** The connection is complete. Pass the data structure
** back to the caller as a handle.
*/
*handle = my_handle;
if (EL737_errcode != 0)
return False;
EL737_call_depth--;
return True;
} else {
EL737_SetErrcode(my_handle, rply_ptr0, "RMT\", \"ECHO\" or \"RA");
}
}
AsynSrv_Close(&my_handle->asyn_info, False);
free(my_handle);
return False;
}
/*
**---------------------------------------------------------------------------
** EL737_Pause: Pause a measurement with an EL737 counter.
*/
int EL737_Pause(
/* ===========
*/ void **handle,
int *status)
{
int my_status;
struct EL737info *info_ptr;
char *rply_ptr0, *rply_ptr1;
/*----------------------------------------------
*/
*status = 0;
info_ptr = (struct EL737info *) *handle;
if (!EL737_AddCallStack(info_ptr, "EL737_Pause"))
return False;
/*----------------------------------------------
** Send PS and RS cmnds to EL737
*/
my_status = AsynSrv_SendCmnds(&info_ptr->asyn_info,
&info_ptr->to_host, &info_ptr->from_host,
"PS\r", "RS\r", NULL);
if (!my_status) {
EL737_errcode = EL737__BAD_ASYNSRV;
return False;
} else {
rply_ptr1 = NULL;
rply_ptr0 =
AsynSrv_GetReply(&info_ptr->asyn_info, &info_ptr->from_host, NULL);
if (rply_ptr0 != NULL)
rply_ptr1 =
AsynSrv_GetReply(&info_ptr->asyn_info, &info_ptr->from_host,
rply_ptr0);
if (rply_ptr0 == NULL)
rply_ptr0 = "?";
if (rply_ptr1 == NULL)
rply_ptr1 = "?";
if (((*rply_ptr0 == '\0') || (*rply_ptr0 == '\r')) &&
(sscanf(rply_ptr1, "%d", status) == 1)) {
if (EL737_errcode != 0)
return False;
EL737_call_depth--;
return True;
}
EL737_SetErrcode(info_ptr, rply_ptr0, "PS\" or \"RS");
*status = 0;
return False;
}
}
/*
**---------------------------------------------------------------------------
** EL737_SendCmnd - Send a command to RS232C server.
*/
int EL737_SendCmnd(
/* ==============
*/ void **handle,
char *cmnd, char *rply, int rply_size)
{
struct EL737info *info_ptr;
int my_status;
char *rply_ptr;
/*----------------------------------------------
*/
info_ptr = (struct EL737info *) *handle;
if (!EL737_AddCallStack(info_ptr, "EL737_SendCmnd"))
return False;
/*----------------------------------------------
** Send command to EL737.
*/
my_status = AsynSrv_SendCmnds(&info_ptr->asyn_info,
&info_ptr->to_host, &info_ptr->from_host,
cmnd, NULL);
if (!my_status) {
EL737_errcode = EL737__BAD_ASYNSRV;
return False;
} else {
rply_ptr =
AsynSrv_GetReply(&info_ptr->asyn_info, &info_ptr->from_host, NULL);
if (rply_ptr == NULL)
rply_ptr = "?";
StrJoin(rply, rply_size, rply_ptr, "");
}
if (EL737_errcode != 0)
return False;
EL737_call_depth--;
return True;
}
/*
**---------------------------------------------------------------------------
** EL737_SetErrcode - Set up EL737_errcode
*/
int EL737_SetErrcode(
/* ================
*/ struct EL737info *info_ptr,
char *response, char *cmnd)
{
int status, s_len;
char *rply;
char tmo_save[4];
char eot_save[4];
EL737_errcode = EL737__BAD_ILLG;
if (strcmp(response, "?OF") == 0)
EL737_errcode = EL737__BAD_LOC;
if (strcmp(response, "?OFL") == 0)
EL737_errcode = EL737__BAD_OFL;
if (strcmp(response, "?OV") == 0)
EL737_errcode = EL737__BAD_OVFL;
if (strcmp(response, "?1") == 0)
EL737_errcode = EL737__BAD_CMD;
if (strcmp(response, "?2") == 0)
EL737_errcode = EL737__BAD_BSY;
if (strcmp(response, "?3") == 0)
EL737_errcode = EL737__BAD_PAR;
if (strcmp(response, "?4") == 0)
EL737_errcode = EL737__BAD_CNTR;
if (strcmp(response, "?5") == 0)
EL737_errcode = EL737__NO_VALUE;
if (strcmp(response, "?6") == 0)
EL737_errcode = EL737__CNTR_OVFL;
if (strncmp(response, "?TMO", 4) == 0)
EL737_errcode = EL737__BAD_TMO;
if ((EL737_errcode == EL737__BAD_ILLG) && (cmnd != NULL)) {
s_len = strlen(cmnd);
if (cmnd[s_len - 1] == '\r')
s_len--;
fprintf(stderr, " Unrecognised response to \"%.*s\" command: \"%s\"\n",
s_len, cmnd, response);
}
return EL737_errcode;
}
/*
**---------------------------------------------------------------------------
** EL737_SetThresh: Set threshold monitoring level.
*/
int EL737_SetThresh(
/* ===============
*/ void **handle,
int indx, float val)
{
int status;
char cmnd[32];
struct EL737info *info_ptr;
char *rply_ptr0;
/*----------------------------------------------
*/
info_ptr = (struct EL737info *) *handle;
if (!EL737_AddCallStack(info_ptr, "EL737_SetThresh"))
return False;
if ((indx < 0) || (indx > 8)) {
EL737_errcode = EL737__BAD_PAR;
return False;
}
/*----------------------------------------------
** If <indx> is zero, simply call EL737_EnableThresh to
** disable threshold monitoring by the counter.
*/
if (indx == 0) {
return EL737_EnableThresh(handle, 0);
}
/*----------------------------------------------
** Send "DR <indx> |<val>|" cmnd to EL737 to set the
** threshold for counter <indx>.
*/
sprintf(cmnd, "DL %d %.3f\r", indx, fabs(val));
status = AsynSrv_SendCmnds(&info_ptr->asyn_info,
&info_ptr->to_host, &info_ptr->from_host,
cmnd, NULL);
if (!status) {
EL737_errcode = EL737__BAD_ASYNSRV;
return False;
}
rply_ptr0 =
AsynSrv_GetReply(&info_ptr->asyn_info, &info_ptr->from_host, NULL);
if (rply_ptr0 == NULL)
rply_ptr0 = "?";
if ((*rply_ptr0 == '\0') || (*rply_ptr0 == '\r')) {
if (val >= 0)
return EL737_EnableThresh(handle, indx);
EL737_call_depth--;
return True;
}
EL737_SetErrcode(info_ptr, rply_ptr0, cmnd);
return False;
}
/*
**---------------------------------------------------------------------------
** EL737_StartCnt: Start a preset cnt measurement with an EL737.
*/
int EL737_StartCnt(
/* ==============
*/ void **handle,
int count, int *status)
{
int my_status;
char cmnd[20];
struct EL737info *info_ptr;
char *rply_ptr0, *rply_ptr1;
/*----------------------------------------------
*/
*status = 0;
info_ptr = (struct EL737info *) *handle;
if (!EL737_AddCallStack(info_ptr, "EL737_StartCnt"))
return False;
/*----------------------------------------------
** Send MP and RS cmnds to EL737
*/
sprintf(cmnd, "MP %d\r", count); /* Encode an appropriate command */
my_status = AsynSrv_SendCmnds(&info_ptr->asyn_info, /* Send it */
&info_ptr->to_host, &info_ptr->from_host,
cmnd, "RS\r", NULL);
if (!my_status) {
EL737_errcode = EL737__BAD_ASYNSRV;
return False;
} else {
rply_ptr1 = NULL;
rply_ptr0 =
AsynSrv_GetReply(&info_ptr->asyn_info, &info_ptr->from_host, NULL);
if (rply_ptr0 != NULL)
rply_ptr1 =
AsynSrv_GetReply(&info_ptr->asyn_info, &info_ptr->from_host,
rply_ptr0);
if (rply_ptr0 == NULL)
rply_ptr0 = "?";
if (rply_ptr1 == NULL)
rply_ptr1 = "?";
if (((*rply_ptr0 == '\0') || (*rply_ptr0 == '\r')) &&
(sscanf(rply_ptr1, "%d", status) == 1)) {
if (EL737_errcode != 0)
return False;
EL737_call_depth--;
return True;
}
EL737_SetErrcode(info_ptr, rply_ptr0, cmnd);
*status = 0;
return False;
}
}
/*
**---------------------------------------------------------------------------
** EL737_StartTime: Start a preset time measurement with an EL737.
*/
int EL737_StartTime(
/* ===============
*/ void **handle,
float timer, int *status)
{
int my_status;
char cmnd[20];
struct EL737info *info_ptr;
char *rply_ptr0, *rply_ptr1;
/*----------------------------------------------
*/
*status = 0;
info_ptr = (struct EL737info *) *handle;
if (!EL737_AddCallStack(info_ptr, "EL737_StartTime"))
return False;
/*----------------------------------------------
** Send TP and RS cmnds to EL737
*/
sprintf(cmnd, "TP %.2f\r", timer); /* Encode an appropriate command */
my_status = AsynSrv_SendCmnds(&info_ptr->asyn_info, /* Send it */
&info_ptr->to_host, &info_ptr->from_host,
cmnd, "RS\r", NULL);
if (!my_status) {
EL737_errcode = EL737__BAD_ASYNSRV;
return False;
} else {
rply_ptr1 = NULL;
rply_ptr0 =
AsynSrv_GetReply(&info_ptr->asyn_info, &info_ptr->from_host, NULL);
if (rply_ptr0 != NULL)
rply_ptr1 =
AsynSrv_GetReply(&info_ptr->asyn_info, &info_ptr->from_host,
rply_ptr0);
if (rply_ptr0 == NULL)
rply_ptr0 = "?";
if (rply_ptr1 == NULL)
rply_ptr1 = "?";
if (((*rply_ptr0 == '\0') || (*rply_ptr0 == 'r')) &&
(sscanf(rply_ptr1, "%d", status) == 1)) {
if (EL737_errcode != 0)
return False;
EL737_call_depth--;
return True;
}
EL737_SetErrcode(info_ptr, rply_ptr0, cmnd);
*status = 0;
return False;
}
}
/*
**---------------------------------------------------------------------------
** EL737_Stop: stop a measurement with an EL737 counter.
*/
int EL737_Stop(
/* ==========
*/ void **handle,
int *c1, int *c2, int *c3, int *c4, float *timer, int *rs)
{
int my_status, nvals;
struct EL737info *info_ptr;
char *rply_ptr0, *rply_ptr1, *rply_ptr2;
/*----------------------------------------------
*/
*c1 = *c2 = *c3 = *c4 = *rs = 0;
*timer = 0.0;
info_ptr = (struct EL737info *) *handle;
if (!EL737_AddCallStack(info_ptr, "EL737_Stop"))
return False;
/*----------------------------------------------
** Send S, RS and RA cmnds to EL737
*/
my_status = AsynSrv_SendCmnds(&info_ptr->asyn_info,
&info_ptr->to_host, &info_ptr->from_host,
"S\r", "RS\r", "RA\r", NULL);
if (!my_status) {
EL737_errcode = EL737__BAD_ASYNSRV;
return False;
} else {
rply_ptr1 = rply_ptr2 = NULL;
rply_ptr0 =
AsynSrv_GetReply(&info_ptr->asyn_info, &info_ptr->from_host, NULL);
if (rply_ptr0 != NULL)
rply_ptr1 =
AsynSrv_GetReply(&info_ptr->asyn_info, &info_ptr->from_host,
rply_ptr0);
if (rply_ptr1 != NULL)
rply_ptr2 =
AsynSrv_GetReply(&info_ptr->asyn_info, &info_ptr->from_host,
rply_ptr1);
if (rply_ptr0 == NULL)
rply_ptr0 = "?";
if (rply_ptr1 == NULL)
rply_ptr1 = "?";
if (rply_ptr2 == NULL)
rply_ptr2 = "?";
nvals = sscanf(rply_ptr2, "%f %d %d %d %d %d %d %d %d",
timer, c1, c2, c3, c4,
&info_ptr->c5, &info_ptr->c6,
&info_ptr->c7, &info_ptr->c8);
if (nvals != 9)
nvals = sscanf(rply_ptr2, "%d %d %d %d %f", c1, c2, c3, c4, timer);
if (nvals == 5) {
info_ptr->c5 = info_ptr->c6 = info_ptr->c7 = info_ptr->c8 = 0;
nvals = 9;
}
if (((*rply_ptr0 == '\0') || (*rply_ptr0 == '\r')) &&
(sscanf(rply_ptr1, "%d", rs) == 1) && (nvals == 9)) {
if (EL737_errcode != 0)
return False;
EL737_call_depth--;
return True;
}
if (*rply_ptr0 != '?') {
if (*rply_ptr1 == '?')
rply_ptr0 = rply_ptr1;
if (*rply_ptr0 == '?')
rply_ptr0 = rply_ptr2;
}
EL737_SetErrcode(info_ptr, rply_ptr0, "S\", \"RS\" or \"RA");
*c1 = *c2 = *c3 = *c4 = *rs = 0;
*timer = 0.0;
return False;
}
}
/*
**---------------------------------------------------------------------------
** EL737_StopFast: stop a measurement with an EL737 counter.
*/
int EL737_StopFast(
/* ==============
*/ void **handle)
{
int my_status, nvals;
struct EL737info *info_ptr;
char *rply_ptr0;
/*----------------------------------------------
*/
info_ptr = (struct EL737info *) *handle;
if (!EL737_AddCallStack(info_ptr, "EL737_StopFast"))
return False;
/*----------------------------------------------
** Send S cmnd to EL737
*/
my_status = AsynSrv_SendCmnds(&info_ptr->asyn_info,
&info_ptr->to_host, &info_ptr->from_host,
"S\r", NULL);
if (!my_status) {
EL737_errcode = EL737__BAD_ASYNSRV;
return False;
} else {
rply_ptr0 =
AsynSrv_GetReply(&info_ptr->asyn_info, &info_ptr->from_host, NULL);
if (rply_ptr0 == NULL)
rply_ptr0 = "?";
if ((*rply_ptr0 == '\0' || (*rply_ptr0 == '\r'))) {
if (EL737_errcode != 0)
return False;
EL737_call_depth--;
return True;
}
EL737_SetErrcode(info_ptr, rply_ptr0, "S");
return False;
}
}
/*
**---------------------------------------------------------------------------
** EL737_WaitIdle: Wait till RS goes to zero.
*/
int EL737_WaitIdle(
/* ==============
*/ void **handle,
int *c1, int *c2, int *c3, int *c4, float *timer)
{
#ifdef __VMS
#include <lib$routines.h>
#define hibernate lib$wait (0.25)
#else
#include <unistd.h>
#include <time.h>
struct timespec delay = { 0, 250000000 };
struct timespec delay_left;
#ifdef LINUX
#define hibernate nanosleep(&delay, &delay_left)
#else
#define hibernate nanosleep_d9 (&delay, &delay_left)
#endif
#endif
int my_rs;
struct EL737info *info_ptr;
/*----------------------------------------------
*/
*c1 = *c2 = *c3 = *c4 = 0;
*timer = 0.0;
info_ptr = (struct EL737info *) *handle;
if (!EL737_AddCallStack(info_ptr, "EL737_WaitIdle"))
return False;
/*----------------------------------------------
** Keep reading status till idle.
*/
while (EL737_GetStatus(handle, c1, c2, c3, c4, timer, &my_rs)) {
if (my_rs == 0) {
if (EL737_errcode != 0)
return False;
EL737_call_depth--;
return True;
}
hibernate;
}
return False; /* Error detected in EL737_GetStatus */
}
/*-------------------------------------------- End of EL737_Utility.C =======*/