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

1589 lines
54 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 "1A04"
#ifdef VAXC
#module EL755_Utility ident
#endif
#ifdef __DECC
#pragma module EL755_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 . . . . . . . . : TAS_SRC:[PSI.LIB.SINQ]EL755_Utility.C
**
** Author . . . . . . . . . . : D. Maden
** Date of creation . . . . . . : Sep 1998
**
** To compile this module, use:
$ import tasmad
$ define/group sinq_c_tlb mad_lib:sinq_c.tlb
$ cc /debug /noopt /obj=[]EL755_Utility -
tas_src:[psi.lib.sinq]EL755_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 EL755_Utility debug
$
$ define/group sinq_olb mad_lib:sinq.olb
$ @tasmad_disk:[mad.lib.sinq]sinq_olb EL755_Utility
**
** Updates:
** 1A01 8-Sep-1998 DM. Initial version.
**============================================================================
** The entry points included in this module are described below. Prototypes
** can be defined via:
**
** #include <sinq_prototypes.h>
**
** EL755_AddCallStack - Add a routine name to the call stack.
** EL755_Close - Close a connection to an EL755 controller.
** EL755_Config - Configure a connection to an EL755 controller.
** EL755_ErrInfo - Return detailed status from last operation.
** EL755_GetCurrents - Get the actual settings of the EL755 currents.
** EL755_Open - Open a connection to an EL755 controller.
** EL755_PutOffline - Put the EL755 off-line.
** EL755_PutOnline - Put the EL755 on-line.
** EL755_SendTillSameStr - Repeatedly send a command to EL755 controller
** until the same reply is received twice.
** EL755_SendTillSameVal - Repeatedly send a command to EL755 controller
** until the first token of the reply is the
** same fl.pnt. value twice in succession.
** EL755_SetCurrent - Set the EL755 current.
**---------------------------------------------------------------------
** int EL755_AddCallStack (&info_pntr, &name)
** ------------------
** Input Args:
** struct EL755info *info_pntr - Pointer to structure returned by
** EL755_Open. Note that the type of the pointer
** is "struct EL755info".
** char *name - The name of the routine to be added to the call stack.
** Output Args:
** none
** Modified Args:
** none
** Return status:
** True if no problems detected, otherwise False and EL755_errcode
** is set to indicate the nature of the problem as follows:
** EL755__NOT_OPEN --> there is no connection open to the EL755,
** i.e. info_pntr is NULL.
** EL755__FORCED_CLOSED --> the connection has been force-closed
** (probably as a result of an error
** on another device on the same host).
** EL755__NO_SOCKET --> The connection has no socket - probably
** it was closed after a previous error.
** Note that EL755_errcode may have been set prior to the call to
** EL755_AddCallStack. In this case, the routine simply returns False.
** Routines called:
** None
** Description:
** The routine is designed to simplify the building of the call-stack
** which is available to the user via EL755_ErrInfo if an error occurs.
** It is intended for internal use only.
**
** If an error has aready occurred prior to the call to EL755_AddCallStack
** (i.e. EL755_errcode is non-zero), the routine simply returns False
** to prevent redundant information being added to the stack.
**
** Otherwise, the caller's name is added to the stack and basic checks
** are made of the EL755info structure.
**---------------------------------------------------------------------
** int EL755_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 EL755_Open.
** On return, the pointer is set to NULL.
** Return status:
** True always (error returns from close and free are not checked).
** Routines called:
** Socket library, "close" and memory release routine, "free".
** 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 EL755_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 EL755_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 an AsynSrv routine.
**
** 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.
**-------------------------------------------------------------------------
** void EL755_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 EL755_Open.
** It is used to hold the config info for the connection.
** Return status:
** True if no problems detected, otherwise False and EL755_errcode
** is set to indicate the nature of the problem. Values of Errcode set by
** EL755_Config are (other values may be set by the called routines):
** EL755__BAD_PAR --> Unrecognised par_id or msecTmo < 100 or
** msecTmo > 999'999 or bad eot or ..
** Routines called:
** EL755_AddCallStack
** Description:
** The routine sets values in the EL755info data structure and may modify
** the state of the temperature controller. Values which may be taken by
** par_id (par_id is case-insensitive) and the corresponding variable
** type of par_val are:
**
** "msecTmo" int The time-out response for commands sent to
** the EL755. The valid range is 100 to
** 999'999. Default is 3'000.
** "eot" char* The expected terminators in responses to
** commands sent to the EL755. The first
** character specifies the number of
** terminators (max=3). Default is "1\n".
** "index" int The DAC index in the range 1 to 8 to be
** referenced via this EL755info structure.
**-------------------------------------------------------------------------
** void EL755_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 EL755_GetCurrents (&handle, &soll, &ist)
** -----------------
**
** Input Args:
** void **handle - The pointer to the structure returned by EL755_Open
** Output Args:
** float *soll - the requested current.
** float *ist - the actual current. This may me different to *soll
** since the controller ramps to a new current.
** Modified Args:
** none
** Return status:
** True if no problems detected, otherwise False and EL755_ErrInfo
** can be called to identify the problem. Values of Errcode set by
** EL755_GetCurrents are (other values may be set by the called
** routines):
** EL755__BAD_ASYNSRV --> Call to AsynSrv_SendCmnds failed. Use
** AsynSrv_ErrInfo to get more details.
** EL755__BAD_ILLG --> The response to the "I" command was probably not
** two numbers. This could happen if there is
** noise on the RS232C connection to the EL755.
** EL755__BAD_TMO --> Time-out error ("?TMO" - this gets generated
** by the RS232C server).
** EL755__OFFLINE --> The EL755 is offline ("?OF").
** EL755__TOO_MANY --> The command was repeated too many times
** and never received the same response
** on 2 consecutive occasions.
**
** If an error is detected, *soll and *ist are undefined.
** Routines called:
** EL755_AddCallStack, AsynSrv_SendCmnds
** Description:
** EL755_Getcurrents sends an "I" command to the controller to obtain the
** currents. The command is repeated until the "soll" value is twice the
** same.
** Note: If the power supply is off or not connected (response is
** "?power-supply OFF", then no error is indicated and *soll=*ist=0.0
** is returned.
**-------------------------------------------------------------------------
** int EL755_Open (&handle, host, port, chan, indx)
** ----------
** 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.
** int indx - The DAC index in the range 1 to 8. This selects which
** of the 8 outputs from the EL755 are to be used.
** Output Args:
** void *handle - A pointer to a structure of type EL755info needed for
** subsequent calls to EL755_??? routines.
** Modified Args:
** none
** Return status:
** True if no problems detected, otherwise False. If False, EL755_ErrInfo
** can be called to identify the problem. Values of Errcode set by
** EL755_Open are (other values may be set by the called routines):
** EL755__BAD_MALLOC --> Call to "malloc" failed
** EL755__BAD_SOCKET --> Call to AsynSrv_Open failed. Use
** AsynSrv_ErrInfo to get more details.
** EL755__BAD_TMO --> Time-out error ("?TMO" - this gets
** generated by the RS232C server).
** EL755__BAD_OFL --> Connection to EL755 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.
** EL755__BAD_DEV --> Device doesn't seem to be an EL755. The
** response to the "ID\r" command was bad.
** EL755__BAD_ILLG --> Some other unrecognised response. This
** should never occur, of course!
** EL755__BAD_ASYNSRV --> Call to AsynSrv_SendCmnds failed. Use
** AsynSrv_ErrInfo to get more details.
** Routines called:
** "calloc" - memory allocation routine.
** AsynSrv_Open
** AsynSrv_Close - called if an error detected after connection opened.
** EL755_Config
** EL755_SendTillSameStr
** Description:
** The routine opens a TCP/IP connection to a server offering the
** "RS-232-C" service for an EL755 Controller. "RMT 1", "ECHO 0" and
** "ID" commands are sent to ensure the device is an EL755 controller.
**-------------------------------------------------------------------------
** int EL755_PutOffline (&handle)
** ----------------
** Send "ECHO 1" and "RMT 0" commands to EL755 server.
** Input Args:
** void **handle - The pntr to the structure returned by EL755_Open.
** Output Args:
** none
** Modified Args:
** none
** Return status:
** True if no problems detected, otherwise False and errcode (see
** EL755_ErrInfo) is set to indicate the nature of the problem.
** Values of Errcode set by EL755_PutOffline are (other values may be set
** by the called routines):
** EL755__BAD_ASYNSRV --> An error occurred in AsynSrv_Utility.
** Call AsynSrv_ErrInfo for more info.
** EL755__BAD_ILLG --> an unrecognised response. This
** should never occur, of course!
** Routines called:
** EL755_AddCallStack, AsynSrv_SendCmnds, AsynSrv_GetReply
** Description:
** The routine calls AsynSrv_SendCmnds to execute "RMT 1", "ECHO 1"
** and "RMT 0" commands. The replies are checked.
**-------------------------------------------------------------------------
** int EL755_PutOnline (&handle, echo)
** ---------------
** Send "RMT 1" and "ECHO x" commands to EL755 server.
** Input Args:
** void **handle - The pntr to the structure returned by EL755_Open.
** int echo - The value for the ECHO command.
** Output Args:
** none
** Modified Args:
** none
** Return status:
** True if no problems detected, otherwise False and errcode (see
** EL755_ErrInfo) is set to indicate the nature of the problem.
** Values of Errcode set by EL755_PutOnline are (other values may be set
** by the called routines):
** EL755__BAD_PAR --> "echo" is not 0, 1 or 2.
** EL755__BAD_ASYNSRV --> An error occurred in AsynSrv_Utility.
** Call AsynSrv_ErrInfo for more info.
** EL755__BAD_ILLG --> an unrecognised response. This
** should never occur, of course!
** Routines called:
** EL755_AddCallStack, AsynSrv_SendCmnds, AsynSrv_GetReply
** Description:
** The routine calls AsynSrv_SendCmnds to execute "RMT 1" and "ECHO x"
** commands. The replies are checked.
**-------------------------------------------------------------------------
** int EL755_SendTillSameStr (&handle, &cmnd, &rply, rply_len)
** ---------------------
** Input Args:
** char *cmnd - The command to be sent (incl. terminators).
** int rply_len - The size of <rply>.
** Output Args:
** char *rply - The response to <cmnd>.
** Modified Args:
** void **handle - The pointer to the structure returned by EL755_Open.
** Return status:
** True if no problems detected, otherwise False. If False, EL755_ErrInfo
** can be called to identify the problem. Values of Errcode set by
** EL755_SendTillSameStr are (other values may be set by the called routines):
** EL755__BAD_ASYNSRV --> Call to AsynSrv_SendCmnds failed. Use
** AsynSrv_ErrInfo to get more details.
** EL755__BAD_ILLG --> The response to the "I" command was probably not
** two numbers. This could happen if there is
** noise on the RS232C connection to the EL755.
** EL755__BAD_TMO --> Time-out error ("?TMO" - this gets
** generated by the RS232C server).
** EL755__BAD_CMD --> Bad command ("?syntax failure")
** EL755__BAD_OFL --> Connection to EL755 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.
** EL755__TOO_MANY --> The command was repeated too many times
** and never received the same response
** on 2 consecutive occasions.
** EL755__OFFLINE --> The EL755 is offline ("?OF").
** Routines called:
** EL755_AddCallStack, EL755_ErrorLog, AsynSrv_SendCmnds, AsynSrv_GetReply
** Description:
** The routine sends the specified command to the EL755 Controller and
** reads the response. The command is repeated up to 5 times until the same
** response is received twice in succession.
** Note:
** The error EL755__TOO_MANY could indicate that <rply> is not big enough
** to hold the complete reply.
**-------------------------------------------------------------------------
** int EL755_SendTillSameVal (&handle, &cmnd, &val)
** ---------------------
** Input Args:
** char *cmnd - The command to be sent (incl. terminators).
** Output Args:
** float *val - The response to <cmnd>.
** Modified Args:
** void **handle - The pointer to the structure returned by EL755_Open.
** Return status:
** True if no problems detected, otherwise False. If False, EL755_ErrInfo
** can be called to identify the problem. Values of Errcode set by
** EL755_SendTillSameVal are (other values may be set by the called
** routines):
** EL755__BAD_ASYNSRV --> Call to AsynSrv_SendCmnds failed. Use
** AsynSrv_ErrInfo to get more details.
** EL755__BAD_ILLG --> The response to the "I" command was probably not
** two numbers. This could happen if there is
** noise on the RS232C connection to the EL755.
** EL755__BAD_TMO --> Time-out error ("?TMO" - this gets
** generated by the RS232C server).
** EL755__BAD_CMD --> Bad command ("?syntax failure")
** EL755__BAD_OFL --> Connection to EL755 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.
** EL755__TOO_MANY --> The command was repeated too many times
** and never received the same response
** on 2 consecutive occasions.
** EL755__OFFLINE --> The EL755 is offline ("?OF").
** Routines called:
** EL755_AddCallStack, EL755_ErrorLog, AsynSrv_SendCmnds, AsynSrv_GetReply
** Description:
** The routine sends the specified command to the EL755 Controller and
** reads the response. The command is repeated up to 5 times until the
** first token is the same fl.pnt value twice in succession.
** Note 1:
** The error EL755__TOO_MANY could indicate that <rply> is not big enough
** to hold the complete reply.
** Note 2: If the power supply is off or not connected (response is
** "?power-supply OFF") then a zero value is returned and the
** return status is True
**-------------------------------------------------------------------------
** int EL755_SetCurrent (&handle, soll)
** ----------------
**
** Input Args:
** void **handle - The pointer to the structure returned by EL755_Open
** float soll - the requested current.
** Output Args:
** none
** Modified Args:
** none
** Return status:
** True if no problems detected, otherwise False and EL755_ErrInfo
** can be called to identify the problem. Values of Errcode set by
** EL755_SetCurrent are (other values may be set by the called
** routines):
** EL755__TURNED_OFF --> The EL755 power supply on this channel is
** turned off ("?power-supply OFF").
** EL755__OUT_OF_RANGE --> The set value is out of
** range ("?value out of range").
** EL755__TOO_LARGE --> The set value is too
** large ("?current limitation").
** EL755__BAD_ILLG --> the response to the first "I" command was
** not null (indicating that the command was
** rejected) or the response to the second
** "I" command was probably not two numbers.
** This could happen if there is noise
** on the RS232C connection to the EL755.
** Routines called:
** EL755_SendTillSameStr, EL755_GetCurrests
** Description:
** EL755_SetCurrent sends an "I" command to the controller to set the
** current for the DAC index selected for the handle. An "I" is sent
** to check that the value was sent correctly.
** Note: If the power supply is off or not connected (response is
** "?power-supply OFF") and soll == 0.0, then return status is True.
**============================================================================*/
/*
**---------------------------------------------------------------------------
** Global Definitions
*/
#include <stdlib.h>
#include <stdio.h>
#include <stdarg.h>
#include <errno.h>
#include <math.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>
#endif
/*-----------------------------------------------------------------*/
#include <sinq_prototypes.h>
#include <el755_def.h>
#include <rs232c_def.h>
#define True 1
#define False 0
#define NIL '\0'
/*--------------------------------------------------------------------------
** Global Variables
*/
static int EL755_call_depth = 0;
static char EL755_routine[5][64];
static int EL755_errcode = 0;
static int EL755_errno, EL755_vaxc_errno;
/*
**---------------------------------------------------------------------------
** EL755_AddCallStack: Add a routine name to the call stack.
** This allows EL755_ErrInfo to generate a
** trace-back in case of error.
*/
int EL755_AddCallStack(
/* ==================
*/ struct EL755info *pntr,
char *name)
{
if (EL755_errcode != 0)
return False;
if (EL755_call_depth < 5) {
StrJoin(EL755_routine[EL755_call_depth], sizeof(EL755_routine[0]),
name, "");
EL755_call_depth++;
}
if (pntr == NULL) {
EL755_errcode = EL755__NOT_OPEN;
return False;
}
if (pntr->asyn_info.skt <= 0) {
memset(pntr->from_host.msg_size,
'0', sizeof(pntr->from_host.msg_size));
EL755_errcode = (pntr->asyn_info.skt < 0) ? EL755__FORCED_CLOSED
: EL755__NO_SOCKET;
return False;
}
return True;
}
/*
**---------------------------------------------------------------------------
** EL755_Close: Close a connection to an EL755 controller.
*/
int EL755_Close(
/* ===========
*/ void **handle,
int force_flag)
{
struct EL755info *info_ptr;
char buff[4];
info_ptr = (struct EL755info *) *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;
}
/*
**---------------------------------------------------------------------------
** EL755_Config: Configure a connection to an EL755 controller.
*/
int EL755_Config(
/* ============
*/ void **handle,
...)
{
struct EL755info *info_ptr;
char buff[80], rply[256], my_txt[16];
va_list ap; /* Pointer to variable args */
char *txt_ptr;
int intval, my_txt_l;
/*----------------------------------------------
*/
info_ptr = (struct EL755info *) *handle;
if (!EL755_AddCallStack(info_ptr, "EL755_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) {
my_txt_l = sizeof(my_txt);
StrEdit(my_txt, txt_ptr, "lowercase", &my_txt_l);
/*------------------------------------*/
if (strcmp(my_txt, "msectmo") == 0) {
intval = va_arg(ap, int);
if ((intval < 100) || (intval > 999999)) {
EL755_errcode = EL755__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(my_txt, "eot") == 0) {
txt_ptr = va_arg(ap, char *);
if (txt_ptr == NULL) {
EL755_errcode = EL755__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:
EL755_errcode = EL755__BAD_PAR;
return False;
}
/*------------------------------------*/
} else if (strcmp(txt_ptr, "index") == 0) {
intval = va_arg(ap, int);
if ((intval < 1) || (intval > 8)) {
EL755_errcode = EL755__BAD_PAR;
return False;
}
info_ptr->index = intval;
/*------------------------------------*/
} else {
EL755_errcode = EL755__BAD_PAR;
return False;
}
/*------------------------------------*/
txt_ptr = va_arg(ap, char *); /* Get pntr to next parameter ident */
}
if (EL755_errcode == 0)
EL755_call_depth--;
return True;
}
/*
** -------------------------------------------------------------------------
** EL755_ErrInfo: Return detailed status from last operation.
*/
void EL755_ErrInfo(
/* =============
*/ char **entry_txt,
int *errcode, int *my_errno, int *vaxc_errno)
{
int i, j, k;
char buff[80];
int asyn_errcode, asyn_errno, asyn_vaxerrno;
char *asyn_errtxt;
if (EL755_call_depth <= 0) {
strcpy(EL755_routine[0], "EL755_no_error_detected");
*errcode = 0;
*my_errno = 0;
*vaxc_errno = 0;
} else {
if (EL755_call_depth > 1) { /* Concatenate the names */
for (i = 1; i < EL755_call_depth; i++) {
strcat(EL755_routine[0], "/");
StrJoin(EL755_routine[0], sizeof(EL755_routine),
EL755_routine[0], EL755_routine[i]);
}
}
*errcode = EL755_errcode;
*my_errno = EL755_errno;
*vaxc_errno = EL755_vaxc_errno;
switch (EL755_errcode) {
case EL755__BAD_ASYNSRV:
strcpy(buff, "/EL755__BAD_ASYNSRV");
break;
case EL755__BAD_CMD:
case EL755__BAD_DEV:
strcpy(buff, "/EL755__BAD_DEV");
break;
case EL755__BAD_ILLG:
strcpy(buff, "/EL755__BAD_ILLG");
break;
case EL755__BAD_MALLOC:
strcpy(buff, "/EL755__BAD_MALLOC");
break;
case EL755__BAD_OFL:
strcpy(buff, "/EL755__BAD_OFL");
break;
case EL755__BAD_PAR:
strcpy(buff, "/EL755__BAD_PAR");
break;
case EL755__BAD_SOCKET:
strcpy(buff, "/EL755__BAD_SOCKET");
break;
case EL755__BAD_TMO:
strcpy(buff, "/EL755__BAD_TMO");
break;
case EL755__FORCED_CLOSED:
strcpy(buff, "/EL755__FORCED_CLOSED");
break;
case EL755__NOT_OPEN:
strcpy(buff, "/EL755__NOT_OPEN");
break;
case EL755__NO_SOCKET:
strcpy(buff, "/EL755__NO_SOCKET");
break;
case EL755__OFFLINE:
strcpy(buff, "/EL755__OFFLINE");
break;
case EL755__OUT_OF_RANGE:
strcpy(buff, "/EL755__OUT_OF_RANGE");
break;
case EL755__OVFLOW:
strcpy(buff, "/EL755__OVFLOW");
break;
case EL755__TOO_LARGE:
strcpy(buff, "/EL755__TOO_LARGE");
break;
case EL755__TOO_MANY:
strcpy(buff, "/EL755__TOO_MANY");
break;
case EL755__TURNED_OFF:
strcpy(buff, "/EL755__TURNED_OFF");
break;
default:
sprintf(buff, "/EL755__unknown_err_code: %d", EL755_errcode);
}
StrJoin(EL755_routine[0], sizeof(EL755_routine), EL755_routine[0],
buff);
}
AsynSrv_ErrInfo(&asyn_errtxt, &asyn_errcode, &asyn_errno,
&asyn_vaxerrno);
if (asyn_errcode != 0) {
strcat(EL755_routine[0], "/");
StrJoin(EL755_routine[0], sizeof(EL755_routine),
EL755_routine[0], asyn_errtxt);
}
*entry_txt = EL755_routine[0];
EL755_call_depth = 0;
EL755_errcode = 0;
}
/*
**---------------------------------------------------------------------------
** EL755_GetCurrents: Get currents from EL755.
*/
int EL755_GetCurrents(
/* =================
*/ void **handle,
float *soll, float *ist)
{
int iret;
char cmnd[32];
struct EL755info *info_ptr;
/*----------------------------------------------
*/
*soll = *ist = 0.0;
info_ptr = (struct EL755info *) *handle;
if (!EL755_AddCallStack(info_ptr, "EL755_GetCurrents"))
return False;
/*----------------------------------------------
** Send I command to get EL755 currents. Repeat until
** first value is same 2 times consecutively.
*/
sprintf(cmnd, "I %d\r", info_ptr->index);
iret = EL755_SendTillTwoVals(handle, cmnd, soll, ist);
if (!iret)
return False;
if (EL755_errcode == 0)
EL755_call_depth--;
return True;
}
/*
**---------------------------------------------------------------------------
** EL755_Open: Open a connection to an EL755 controller.
*/
int EL755_Open(
/* ==========
*/ void **handle,
char *host, int port, int chan, int indx)
{
int status, i;
char tmo_save[4];
char *rply_ptr0, *rply_ptr1, *rply_ptr2;
struct EL755info *my_handle;
/*--------------------------------------------------------
** Initialise the error info stack and pre-set the
** routine name (in case of error).
*/
EL755_errcode = EL755_errno = EL755_vaxc_errno = 0;
strcpy(EL755_routine[0], "EL755_Open");
EL755_call_depth = 1;
/*--------------------------------------------------------
** Assume trouble
*/
*handle = NULL;
/*--------------------------------------------------------
** Reserve space for the data we need to store.
*/
my_handle = (struct EL755info *) calloc(1, sizeof(*my_handle));
if (my_handle == NULL) {
EL755_errcode = EL755__BAD_MALLOC; /* calloc failed!! */
return False;
}
/*--------------------------------------------------------
** 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) {
EL755_errcode = EL755__BAD_SOCKET;
GetErrno(&EL755_errno, &EL755_vaxc_errno); /* Save errno info */
EL755_ErrorLog("EL755_Open/AsynSrv_Open",
"Failed to make connection.");
free(my_handle);
return False;
}
memcpy(tmo_save, my_handle->asyn_info.tmo, 4);
status = EL755_Config((void *) &my_handle, "msecTmo", 100, /* Set a short time-out initially since
** there should be no reason for the RMT,
** ECHO or ID commands to take very long.
*/
"eot", "1\r", "index", indx, NULL);
if (!status) {
/* Some error occurred in EL755_Config - should be impossible!
*/
AsynSrv_Close(&my_handle->asyn_info, False);
free(my_handle);
return False;
}
/*
** Now ensure that there's an EL755 connected to the line. The first
** "RMT 1" command can fail due to pending characters in the EL755
** input buffer causing the command to be corrupted. The response is
** ignored for this reason.
*/
status = AsynSrv_SendCmnds(&my_handle->asyn_info, &my_handle->to_host, &my_handle->from_host, "RMT 1\r", /* Try to put EL755 on-line */
"RMT 1\r", /* Try again in case type-ahead chars corrupted ..
** .. the first attempt. */
"ECHO 0\r", /* And turn off echoing */
NULL);
status = AsynSrv_SendCmnds(&my_handle->asyn_info,
&my_handle->to_host, &my_handle->from_host,
"RMT 1\r", "ECHO 0\r", "ID\r", NULL);
if (!status) {
/* Some error occurred in AsynSrv_SendCmnds.
*/
AsynSrv_Close(&my_handle->asyn_info, False);
free(my_handle);
EL755_errcode = EL755__BAD_ASYNSRV;
return False;
}
rply_ptr0 = AsynSrv_GetReply(&my_handle->asyn_info,
&my_handle->from_host, NULL);
rply_ptr1 = AsynSrv_GetReply(&my_handle->asyn_info,
&my_handle->from_host, rply_ptr0);
rply_ptr2 = AsynSrv_GetReply(&my_handle->asyn_info,
&my_handle->from_host, rply_ptr1);
if ((rply_ptr0 == NULL) || (rply_ptr1 == NULL) || (rply_ptr2 == NULL)) {
/* Some error occurred in AsynSrv_GetReply.
*/
EL755_AddCallStack(my_handle, "NULL response");
AsynSrv_Close(&my_handle->asyn_info, False);
EL755_errcode = EL755__BAD_DEV;
free(my_handle);
return False;
}
if (rply_ptr0[0] != '\0') {
EL755_AddCallStack(my_handle, rply_ptr0);
AsynSrv_Close(&my_handle->asyn_info, False); /* Bad response! */
EL755_errcode = EL755__BAD_DEV;
free(my_handle);
return False;
}
if (rply_ptr1[0] != '\0') {
EL755_AddCallStack(my_handle, rply_ptr1);
AsynSrv_Close(&my_handle->asyn_info, False); /* Bad response! */
EL755_errcode = EL755__BAD_DEV;
free(my_handle);
return False;
}
if (strncmp(rply_ptr2, "EL755 MAGST", 11) != 0) {
EL755_AddCallStack(my_handle, rply_ptr2);
AsynSrv_Close(&my_handle->asyn_info, False); /* Bad response! */
EL755_errcode = EL755__BAD_DEV;
free(my_handle);
return False;
}
/* The device seems to be an EL755! */
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 (EL755_errcode == 0)
EL755_call_depth--;
return True;
}
/*
**---------------------------------------------------------------------------
** EL755_PutOffline: put the EL755 off-line
*/
int EL755_PutOffline(
/* ================
*/ void **handle)
{
int status;
struct EL755info *info_ptr;
char *rply_ptr0, *rply_ptr1, *rply_ptr2;
char buff[132];
/*----------------------------------------------
*/
info_ptr = (struct EL755info *) *handle;
if (!EL755_AddCallStack(info_ptr, "EL755_PutOffline"))
return False;
/*----------------------------------------------
** The problem which this routine has is that the EL755
** may already be off-line. The following is, therefore,
** rather pedantic for most cases which occur in practice.
*/
status = AsynSrv_SendCmnds(&info_ptr->asyn_info,
&info_ptr->to_host, &info_ptr->from_host,
"RMT 1\r",
"RMT 1\r", "ECHO 1\r", "RMT 0\r", NULL);
if (!status) {
EL755_errcode = EL755__BAD_ASYNSRV;
return False;
}
status = AsynSrv_SendCmnds(&info_ptr->asyn_info,
&info_ptr->to_host, &info_ptr->from_host,
"RMT\r", "", NULL);
if (!status) {
EL755_errcode = EL755__BAD_ASYNSRV;
return False;
}
rply_ptr0 =
AsynSrv_GetReply(&info_ptr->asyn_info, &info_ptr->from_host, NULL);
rply_ptr1 =
AsynSrv_GetReply(&info_ptr->asyn_info, &info_ptr->from_host,
rply_ptr0);
if ((rply_ptr0 == NULL) || (rply_ptr1 == NULL)) {
EL755_AddCallStack(info_ptr, "NULL response");
EL755_errcode = EL755__BAD_ILLG;
return False;
}
if ((strcmp(rply_ptr0, "RMT") == 0) && (strcmp(rply_ptr1, "\n0") == 0)) {
EL755_call_depth--;
return True;
}
if (strcmp(rply_ptr0, "?OF") == 0) {
EL755_errcode = EL755__OFFLINE;
} else if (strcmp(rply_ptr0, "?OFL") == 0) {
EL755_errcode = EL755__BAD_OFL;
} else if (strcmp(rply_ptr0, "?syntax failure") == 0) {
EL755_errcode = EL755__BAD_CMD;
} else if (strncmp(rply_ptr0, "?TMO", 4) == 0) {
EL755_errcode = EL755__BAD_TMO;
} else {
sprintf(buff, "Cmnd=\"RMT.\" Rply0=\"%.10s\" Rply1=\"%.10s\"",
rply_ptr0, rply_ptr1);
MakePrintable(buff, sizeof(buff), buff);
EL755_AddCallStack(info_ptr, buff);
sprintf(buff, "Unrecognised responses to RMT command: \"%s\" \"%s\"",
rply_ptr0, rply_ptr1);
MakePrintable(buff, sizeof(buff), buff);
EL755_ErrorLog(EL755_routine[EL755_call_depth - 1], buff);
EL755_errcode = EL755__BAD_ILLG;
}
return False;
}
/*
**---------------------------------------------------------------------------
** EL755_PutOnline: put the EL755 on-line
*/
int EL755_PutOnline(
/* ===============
*/ void **handle,
int echo)
{
int status, my_echo;
struct EL755info *info_ptr;
char cmnd0[10], buff[132];
char *rply_ptr;
/*----------------------------------------------
*/
info_ptr = (struct EL755info *) *handle;
if (!EL755_AddCallStack(info_ptr, "EL755_PutOnline"))
return False;
/*----------------------------------------------
*/
if ((echo != 0) && (echo != 1)) {
EL755_errcode = EL755__BAD_PAR;
return False;
}
/*----------------------------------------------
** The problem which this routine has is that the state
** of the EL755 is not known. The following is, therefore,
** rather pedantic for most cases which occur in practice.
*/
sprintf(cmnd0, "ECHO %d\r", echo);
status = AsynSrv_SendCmnds(&info_ptr->asyn_info,
&info_ptr->to_host, &info_ptr->from_host,
"RMT 1\r", "RMT 1\r", cmnd0, NULL);
if (!status) {
EL755_errcode = EL755__BAD_ASYNSRV;
return False;
}
status = AsynSrv_SendCmnds(&info_ptr->asyn_info,
&info_ptr->to_host, &info_ptr->from_host,
"ECHO\r", NULL);
if (!status) {
EL755_errcode = EL755__BAD_ASYNSRV;
return False;
}
rply_ptr =
AsynSrv_GetReply(&info_ptr->asyn_info, &info_ptr->from_host, NULL);
if (rply_ptr == NULL) {
EL755_AddCallStack(info_ptr, "NULL response");
EL755_errcode = EL755__BAD_ILLG;
return False;
}
if ((echo == 1) && (strcmp(rply_ptr, "ECHO") == 0)) {
EL755_call_depth--;
return True;
} else if ((echo == 0) &&
(sscanf(rply_ptr, "%d", &my_echo) == 1) &&
(my_echo == echo)) {
EL755_call_depth--;
return True;
}
if (strcmp(rply_ptr, "?OF") == 0) {
EL755_errcode = EL755__OFFLINE;
} else if (strcmp(rply_ptr, "?OFL") == 0) {
EL755_errcode = EL755__BAD_OFL;
} else if (strcmp(rply_ptr, "?syntax failure") == 0) {
EL755_errcode = EL755__BAD_CMD;
} else if (strncmp(rply_ptr, "?TMO", 4) == 0) {
EL755_errcode = EL755__BAD_TMO;
} else {
sprintf(buff, "Cmnd=\"ECHO.\" Rply=\"%.10s\"", rply_ptr);
MakePrintable(buff, sizeof(buff), buff);
EL755_AddCallStack(info_ptr, buff);
sprintf(buff, "Unrecognised response to ECHO command: \"%s\"",
rply_ptr);
MakePrintable(buff, sizeof(buff), buff);
EL755_ErrorLog(EL755_routine[EL755_call_depth - 1], buff);
EL755_errcode = EL755__BAD_ILLG;
}
return False;
}
/*
**---------------------------------------------------------------------------
** EL755_SendTillSameStr: Repeat a command until we get the same
** response on 2 successive occasions.
**
** This routine is intended for internal use only!
** If too many retries, EL755_errcode is set to EL755__TOO_MANY.
*/
int EL755_SendTillSameStr(
/* =====================
*/ void **handle,
char *cmnd, char *rply, int rply_len)
{
int iret, i, j, n_ovfl;
struct EL755info *info_ptr;
char *rply_ptr;
char buff[132];
char replies[6][64];
/*----------------------------------------------
*/
info_ptr = (struct EL755info *) *handle;
if (!EL755_AddCallStack(info_ptr, "EL755_SendTillSameStr"))
return False;
/*----------------------------------------------
** Send command. Do it in a
** loop until we get the same response twice to guard
** against RS-232-C problems with the EL755.
*/
i = n_ovfl = 0;
StrJoin(rply, rply_len, "#", "");
while (i < 6) {
iret = AsynSrv_SendCmnds(&info_ptr->asyn_info,
&info_ptr->to_host, &info_ptr->from_host,
cmnd, NULL);
if (!iret) {
EL755_errcode = EL755__BAD_ASYNSRV;
return False;
}
rply_ptr =
AsynSrv_GetReply(&info_ptr->asyn_info, &info_ptr->from_host, NULL);
if (rply_ptr == NULL) {
EL755_AddCallStack(info_ptr, "NULL response");
EL755_errcode = EL755__BAD_ILLG;
return False;
}
if (strncmp(rply_ptr, "?TMO", 4) == 0) {
EL755_errcode = EL755__BAD_TMO;
return False;
}
if (strcmp(rply_ptr, "?OF") == 0) {
EL755_errcode = EL755__OFFLINE;
return False;
}
if (strcmp(rply_ptr, "?OFL") == 0) {
EL755_errcode = EL755__BAD_OFL;
return False;
}
if (strcmp(rply_ptr, "?syntax failure") == 0) {
EL755_errcode = EL755__BAD_CMD;
return False;
}
if (strcmp(rply_ptr, "?OV") == 0) { /* Check for overflow. This seems
** to be an EL755 problem which
** needs fixing. In the meantime,
** just force a repeat.
*/
sprintf(buff, "Warning -- \"?OV\" received in response to \"%s\".",
cmnd);
MakePrintable(buff, sizeof(buff), buff);
EL755_ErrorLog(EL755_routine[EL755_call_depth - 1], buff);
n_ovfl++;
if (n_ovfl > 10) {
EL755_errcode = EL755__TOO_MANY;
return False;
}
} else {
n_ovfl = 0;
if (strncmp(rply, rply_ptr, rply_len) == 0)
break;
StrJoin(rply, rply_len, rply_ptr, "");
MakePrintable(replies[i], sizeof(replies[0]), rply_ptr);
i++;
}
}
if (strncmp(rply, rply_ptr, rply_len) != 0) {
EL755_errcode = EL755__TOO_MANY;
return False;
}
if (i > 1) {
sprintf(buff, "Warning -- %d retries needed for Cmnd = \"%s\".",
(i - 1), cmnd);
MakePrintable(buff, sizeof(buff), buff);
EL755_ErrorLog(EL755_routine[EL755_call_depth - 1], buff);
for (j = 0; j < i; j++)
fprintf(stderr, " %d: \"%s\"\n", j, replies[j]);
}
if (EL755_errcode != 0)
return False;
EL755_call_depth--;
return True;
}
/*
**---------------------------------------------------------------------------
** EL755_SendTillSameVal: Repeat a command until we get the same
** response value on 2 successive occasions.
**
** This routine is intended for internal use only!
** If too many retries, EL755_errcode is set to EL755__TOO_MANY.
*/
int EL755_SendTillSameVal(
/* =====================
*/ void **handle,
char *cmnd, float *val)
{
int iret, i, n_ovfl, cnt;
struct EL755info *info_ptr;
float last_val;
char *rply_ptr, *tok;
char buff[132];
/*----------------------------------------------
*/
info_ptr = (struct EL755info *) *handle;
if (!EL755_AddCallStack(info_ptr, "EL755_SendTillSameVal"))
return False;
/*----------------------------------------------
** Send command. Do it in a
** loop until we get the same response twice to guard
** against RS-232-C problems with the EL755.
*/
i = n_ovfl = 0;
*val = 9999.999;
last_val = *val - 1.0;
while (i < 6) {
iret = AsynSrv_SendCmnds(&info_ptr->asyn_info,
&info_ptr->to_host, &info_ptr->from_host,
cmnd, NULL);
if (!iret) {
EL755_errcode = EL755__BAD_ASYNSRV;
return False;
}
rply_ptr =
AsynSrv_GetReply(&info_ptr->asyn_info, &info_ptr->from_host, NULL);
if (rply_ptr == NULL) {
EL755_AddCallStack(info_ptr, "NULL response");
EL755_errcode = EL755__BAD_ILLG;
return False;
}
if (strcmp(rply_ptr, "?OV") == 0) { /* Check for overflow. This seems
** to be an EL755 problem which
** needs fixing. In the meantime,
** just force a repeat.
*/
sprintf(buff, "Warning -- \"?OV\" received in response to \"%s\".",
cmnd);
MakePrintable(buff, sizeof(buff), buff);
EL755_ErrorLog(EL755_routine[EL755_call_depth - 1], buff);
n_ovfl++;
if (n_ovfl > 10) {
EL755_errcode = EL755__TOO_MANY;
return False;
}
} else {
n_ovfl = 0;
if (strcmp(rply_ptr, "?OF") == 0) {
EL755_errcode = EL755__OFFLINE;
return False;
}
if (strcmp(rply_ptr, "?OFL") == 0) {
EL755_errcode = EL755__BAD_OFL;
return False;
}
if (strcmp(rply_ptr, "?syntax failure") == 0) {
EL755_errcode = EL755__BAD_CMD;
return False;
}
if (strcmp(rply_ptr, "?power-supply OFF") == 0) { /* If off, return 0 */
*val = 0.0;
EL755_call_depth--;
return True;
} else {
tok = strtok(rply_ptr, " ");
if ((tok == NULL) ||
(sscanf(tok, "%f%n", val, &cnt) != 1) ||
(cnt != strlen(tok))) {
EL755_AddCallStack(info_ptr, rply_ptr);
EL755_errcode = EL755__BAD_ILLG;
return False;
}
if (*val == last_val)
break;
last_val = *val;
}
i++;
}
}
if (last_val != *val) {
EL755_errcode = EL755__TOO_MANY;
return False;
}
if (i > 1) {
sprintf(buff, "Warning -- %d retries needed for Cmnd = \"%s\".",
(i - 1), cmnd);
MakePrintable(buff, sizeof(buff), buff);
EL755_ErrorLog(EL755_routine[EL755_call_depth - 1], buff);
}
if (EL755_errcode != 0)
return False;
EL755_call_depth--;
return True;
}
/*
**---------------------------------------------------------------------------
** EL755_SendTillTwoVals: Repeat a command until we get 2 fl.pt.
** values and the first is the same on 2
** successive occasions.
**
** This routine is intended for internal use only! It is
** intended to read the Soll- and Ist-currents where the
** Soll-value should be the same but the Ist-value could be
** changing as the power supply ramps to a new value.
** If too many retries, EL755_errcode is set to EL755__TOO_MANY.
*/
int EL755_SendTillTwoVals(
/* =====================
*/ void **handle,
char *cmnd, float *val0, float *val1)
{
int iret, i, n_ovfl, cnt0, cnt1;
struct EL755info *info_ptr;
float last_val;
char *rply_ptr, *tok0, *tok1;
char buff[132];
/*----------------------------------------------
*/
info_ptr = (struct EL755info *) *handle;
if (!EL755_AddCallStack(info_ptr, "EL755_SendTillTwoVals"))
return False;
/*----------------------------------------------
** Send command. Do it in a
** loop until we get the same response twice to guard
** against RS-232-C problems with the EL755.
*/
i = n_ovfl = 0;
*val0 = 9999.999;
last_val = *val0 - 1.0;
while (i < 6) {
iret = AsynSrv_SendCmnds(&info_ptr->asyn_info,
&info_ptr->to_host, &info_ptr->from_host,
cmnd, NULL);
if (!iret) {
EL755_errcode = EL755__BAD_ASYNSRV;
return False;
}
rply_ptr =
AsynSrv_GetReply(&info_ptr->asyn_info, &info_ptr->from_host, NULL);
if (rply_ptr == NULL) {
EL755_AddCallStack(info_ptr, "NULL response");
EL755_errcode = EL755__BAD_ILLG;
return False;
}
if (strcmp(rply_ptr, "?OV") == 0) { /* Check for overflow. This seems
** to be an EL755 problem which
** needs fixing. In the meantime,
** just force a repeat.
*/
sprintf(buff, "Warning -- \"?OV\" received in response to \"%s\".",
cmnd);
MakePrintable(buff, sizeof(buff), buff);
EL755_ErrorLog(EL755_routine[EL755_call_depth - 1], buff);
n_ovfl++;
if (n_ovfl > 10) {
EL755_errcode = EL755__TOO_MANY;
return False;
}
} else {
n_ovfl = 0;
if (strcmp(rply_ptr, "?OF") == 0) {
EL755_errcode = EL755__OFFLINE;
return False;
}
if (strcmp(rply_ptr, "?OFL") == 0) {
EL755_errcode = EL755__BAD_OFL;
return False;
}
if (strcmp(rply_ptr, "?syntax failure") == 0) {
EL755_errcode = EL755__BAD_CMD;
return False;
}
if (strcmp(rply_ptr, "?power-supply OFF") == 0) { /* If off, return 0 */
*val0 = 0.0;
*val1 = 0.0;
EL755_call_depth--;
return True;
} else {
tok0 = strtok(rply_ptr, " ");
tok1 = strtok(NULL, " ");
if ((tok0 == NULL) ||
(tok1 == NULL) ||
(sscanf(tok0, "%f%n", val0, &cnt0) != 1) ||
(sscanf(tok1, "%f%n", val1, &cnt1) != 1) ||
(cnt0 != strlen(tok0)) || (cnt1 != strlen(tok1))) {
EL755_AddCallStack(info_ptr, rply_ptr);
EL755_errcode = EL755__BAD_ILLG;
return False;
}
if (*val0 == last_val)
break;
last_val = *val0;
}
i++;
}
}
if (last_val != *val0) {
EL755_errcode = EL755__TOO_MANY;
return False;
}
if (i > 1) {
sprintf(buff, "Warning -- %d retries needed for Cmnd = \"%s\".",
(i - 1), cmnd);
MakePrintable(buff, sizeof(buff), buff);
EL755_ErrorLog(EL755_routine[EL755_call_depth - 1], buff);
}
if (EL755_errcode != 0)
return False;
EL755_call_depth--;
return True;
}
/*
**---------------------------------------------------------------------------
** EL755_SetCurrent: Sets current via EL755.
*/
int EL755_SetCurrent(
/* ================
*/ void **handle,
float soll)
{
int i, iret;
float my_soll, my_ist;
char cmnd[32], cmnd0[32], buff[132], buff1[132];
struct EL755info *info_ptr;
/*----------------------------------------------
*/
info_ptr = (struct EL755info *) *handle;
if (!EL755_AddCallStack(info_ptr, "EL755_SetCurrent"))
return False;
/*----------------------------------------------
** Send I command to set EL755 current and I command
** to read back the set value.
** Repeat until set value is correct.
*/
sprintf(cmnd, "I %d %.4f\r", info_ptr->index, soll);
sprintf(cmnd0, "I %d\r", info_ptr->index);
i = 0;
my_soll = soll + 1.0;
while ((i < 6) && (fabs(soll - my_soll) > 0.01)) {
iret = EL755_SendTillSameStr(handle, cmnd, buff, sizeof(buff));
if (!iret)
return False;
if (buff[0] == NIL) { /* We should get a null response */
iret = EL755_SendTillSameVal(handle, cmnd0, &my_soll);
if (!iret)
return False;
} else if (strcmp(buff, "?value out of range") == 0) {
EL755_errcode = EL755__OUT_OF_RANGE;
return False;
} else if (strcmp(buff, "?current limitation") == 0) {
EL755_errcode = EL755__TOO_LARGE;
return False;
} else if (strcmp(buff, "?power-supply OFF") == 0) {
if (soll == 0.0) { /* Suppress error if trying to set zero and
.. power supply is off! */
if (EL755_errcode != 0)
return False;
EL755_call_depth--;
return True;
} else {
EL755_errcode = EL755__TURNED_OFF;
return False;
}
} else {
sprintf(buff1, "Cmnd=\"%s\" Rply=\"%.10s\"", cmnd, buff);
MakePrintable(buff1, sizeof(buff1), buff1);
EL755_AddCallStack(info_ptr, buff1);
EL755_errcode = EL755__BAD_ILLG;
return False;
}
i++;
}
if (fabs(soll - my_soll) > 0.01) {
EL755_errcode = EL755__TOO_MANY;
return False;
}
if (i > 1) {
sprintf(buff, "Warning -- %d retries needed for Cmnd = \"%s\".",
(i - 1), cmnd);
MakePrintable(buff, sizeof(buff), buff);
EL755_ErrorLog(EL755_routine[EL755_call_depth - 1], buff);
}
if (EL755_errcode != 0)
return False;
EL755_call_depth--;
return True;
}
/*
**---------------------------------------------------------------------------
** EL755_Send sends a command to the EL755 and gets a reply
**
** This routine is intended for internal use only!
*/
int EL755_Send(
/* =====================
*/ void **handle,
char *cmnd, char *rply, int rply_len)
{
int iret, i, j, n_ovfl;
struct EL755info *info_ptr;
char *rply_ptr;
char buff[132];
char replies[6][64];
/*----------------------------------------------
*/
info_ptr = (struct EL755info *) *handle;
if (!EL755_AddCallStack(info_ptr, "EL755_SendTillSameStr"))
return False;
/*----------------------------------------------
** Send command.
*/
i = n_ovfl = 0;
StrJoin(rply, rply_len, "#", "");
iret = AsynSrv_SendCmnds(&info_ptr->asyn_info,
&info_ptr->to_host, &info_ptr->from_host,
cmnd, NULL);
if (!iret) {
EL755_errcode = EL755__BAD_ASYNSRV;
return False;
}
rply_ptr =
AsynSrv_GetReply(&info_ptr->asyn_info, &info_ptr->from_host, NULL);
if (rply_ptr == NULL) {
EL755_AddCallStack(info_ptr, "NULL response");
EL755_errcode = EL755__BAD_ILLG;
return False;
}
if (strncmp(rply_ptr, "?TMO", 4) == 0) {
EL755_errcode = EL755__BAD_TMO;
return False;
}
if (strcmp(rply_ptr, "?OF") == 0) {
EL755_errcode = EL755__OFFLINE;
return False;
}
if (strcmp(rply_ptr, "?OFL") == 0) {
EL755_errcode = EL755__BAD_OFL;
return False;
}
if (strcmp(rply_ptr, "?syntax failure") == 0) {
EL755_errcode = EL755__BAD_CMD;
return False;
}
if (strcmp(rply_ptr, "?OV") == 0) { /* Check for overflow. This seems
** to be an EL755 problem which
** needs fixing. In the meantime,
** just force a repeat.
*/
sprintf(buff, "Warning -- \"?OV\" received in response to \"%s\".",
cmnd);
MakePrintable(buff, sizeof(buff), buff);
EL755_ErrorLog(EL755_routine[EL755_call_depth - 1], buff);
n_ovfl++;
if (n_ovfl > 10) {
EL755_errcode = EL755__TOO_MANY;
return False;
}
} else {
n_ovfl = 0;
if (strncmp(rply, rply_ptr, rply_len) == 0) {
return False;
}
StrJoin(rply, rply_len, rply_ptr, "");
MakePrintable(replies[i], sizeof(replies[0]), rply_ptr);
i++;
}
if (EL755_errcode != 0)
return False;
EL755_call_depth--;
return True;
}
/*-------------------------------------------- End of EL755_Utility.C =======*/