1589 lines
54 KiB
C
1589 lines
54 KiB
C
#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 =======*/
|