#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 ** ** 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 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 " command is sent to select counter 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 " 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 " 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 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 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 ||" command is sent ** to the counter to set the threshold for counter ** to the absolute value of . ** Then, if (val >= 0), EL737_EnableThresh is then called ** to select counter 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 #include #include #include #include #include #include #include #include #include #ifdef __VMS #include #else #include #ifdef FORTIFY #include #endif #endif /*-----------------------------------------------------------------*/ #include #include #include #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 " 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 " 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 is zero, simply call EL737_EnableThresh to ** disable threshold monitoring by the counter. */ if (indx == 0) { return EL737_EnableThresh(handle, 0); } /*---------------------------------------------- ** Send "DR ||" cmnd to EL737 to set the ** threshold for counter . */ 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 #define hibernate lib$wait (0.25) #else #include #include 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 =======*/