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

2879 lines
94 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 "1D08"
#ifdef VAXC
#module EL734_Utility ident
#endif
#ifdef __DECC
#pragma module EL734_Utility ident
#endif
/*
** +--------------------------------------------------------------+
** | Paul Scherrer Institute |
** | Department ASQ |
** | |
** | This software may be used freely by non-profit organizations.|
** | It may be copied provided that the name of P.S.I. and of the |
** | author is included. Neither P.S.I. nor the author assume any |
** | responsibility for the use of this software outside of P.S.I.|
** +--------------------------------------------------------------+
**
** Module Name . . . . . . . . : [...LIB.SINQ]EL734_Utility.C
**
** Author . . . . . . . . . . : D. Maden
** Date of creation . . . . . . : Nov 1995
**
** To compile this module, use:
$ import tasmad
$ define/group sinq_c_tlb mad_lib:sinq_c.tlb
$ cc /debug /noopt /obj=[]EL734_Utility -
tasmad_disk:[mad.psi.lib.sinq]EL734_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 EL734_Utility debug
$
$ define/group sinq_olb mad_lib:sinq.olb
$ @tasmad_disk:[mad.lib.sinq]sinq_olb EL734_Utility
**
** Updates:
** 1A01 2-Nov-1995 DM. Initial version.
** 1B01 21-Mar-1996 DM. Move from DELTAT.OLB to SINQ.OLB.
** 1C01 3-Mar-1997 DM. Add "Forced-close" capability.
** 1C02 14-Apr-1997 DM. Add EL734__BAD_STP to EL734_MoveNoWait.
** 1C11 18-Jun-1998 DM. Modify EL734_GetZeroPoint.
** 1D01 4-Aug-1998 DM. Put messages into a .MSG file.
**============================================================================
** The entry points included in this module are described below. Prototypes
** can be defined via:
**
** #include <sinq_prototypes.h>
**
** EL734_AddCallStack - Add a routine name to the call stack.
** EL734_Close - Close a connection to a motor.
** EL734_Config - Configure a connection to a motor.
** EL734_EncodeMSR - Encode the MSR status into text.
** EL734_EncodeSS - Encode the SS flags into text.
** EL734_ErrInfo - Return detailed status from last operation.
** EL734_GetAirCush - Get W and AC register values.
** EL734_GetEncGearing - Get FD register values.
** EL734_GetId - Get ID register value.
** EL734_GetLimits - Get H register values.
** EL734_GetMotorGearing - Get FM register values.
** EL734_GetNullPoint - Get V register value.
** EL734_GetPosition - Get U register value = current position.
** EL734_GetPrecision - Get A register value.
** EL734_GetRefMode - Get K register value.
** EL734_GetRefParam - Get Q register value.
** EL734_GetSpeeds - Get G, J and E register values.
** EL734_GetStatus - Get MSR/SS/U register values.
** EL734_GetZeroPoint - Get zero-point of motor.
** EL734_MoveNoWait - Move motor and don't wait for completion.
** EL734_MoveWait - Move motor and wait for completion.
** EL734_Open - Open a connection to a motor.
** EL734_PutOffline - Put the EL734 off-line.
** EL734_PutOnline - Put the EL734 on-line.
** EL734_SendCmnd - Send a command to RS232C server.
** EL734_SetAirCush - Set the air-cushion (AC register).
** EL734_SetErrcode - Set up EL734_errcode.
** EL734_SetHighSpeed - Set the max speed (J register).
** EL734_SetLowSpeed - Set the start/stop speed (G register).
** EL734_SetRamp - Set the start/stop ramp (E register).
** EL734_Stop - Send a stop command to motor.
** EL734_WaitIdle - Wait till MSR goes to zero.
** EL734_ZeroStatus - Zero the "ored-MSR" and fault counters.
**---------------------------------------------------------------------
** int EL734_AddCallStack (&handle, &name)
** ------------------
** Add a routine name to the call stack (internal use).
** Input Args:
** struct EL734info *handle - The pointer to the structure returned by
** EL734_Open.
** char *name - The name to be added to the call stack.
** Output Args:
** none
** Modified Args:
** none
** Return status:
** False if an error is detected, otherwise True.
** Routines called:
** none
** Description:
** If an error has already occurred (EL734_errcode != 0), the routine
** simply returns False. Otherwise, *name is added to the call stack.
** Then *handle is checked.
** If NULL, error EL734__NOT_OPEN is set and False is returned.
** Otherwise, the connection's TCP/IP socket number is checked.
** If zero, error EL734__NO_SOCKET is set and False is returned.
** If negative, error EL734__FORCED_CLOSE is set and False is returned.
** Otherwise, True is returned.
**---------------------------------------------------------------------
** int EL734_Close (&handle, int force_flag)
** -----------
** Close a connection to a motor.
** 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 EL734_Open.
** On return, the pointer is set to NULL.
** Return status:
** True always (error returns from close and free are not checked).
** Routines called:
** AsynSrv_Close
** Description:
** The routine calls AsynSrv_Close to close the connection to the RS232C
** server. If 'force_flag' is non-zero, all other connections to the
** RS232C server which use the same socket will also be closed.
**
** The 'force_flag' can be useful in error recovery situations. The AsynSrv
** utility operates by only opening a socket for each separate combination
** of host/port. Hence, if several connections are open to the
** motors on an EL734, then calling EL734_Close doesn't actually close
** the socket until all connections have been closed. In the situation
** where an error has been detected on a motor, it is often desirable to
** close and re-open the socket as part of the recovery procedure. Calling
** EL734_Close with 'force_flag' non-zero will force the socket to be
** closed and will mark all connections using this socket so that they
** will be informed of the event when they next call an EL734_utility
** 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. EL737 neutron cntr) on the same server.
**-------------------------------------------------------------------------
** int EL734_Config (&handle, &par_id, par_val, ...)
** ------------
** Configure a connection to a motor.
** 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 EL734_Open.
** It is used to hold the config info for the connection.
** Return status:
** True if no problems detected, otherwise False and EL734_errcode
** is set to indicate the nature of the problem as follows:
** EL734__BAD_PAR --> Unrecognised par_id or msecTmo < 100 or
** msecTmo > 999'999 or bad eot or ..
** Routines called:
** none
** Description:
** The routine sets values in the EL734info data structure. Values which
** may be taken by par_id (warning -- par_id is case-sensitive) and the
** corresponding variable type of par_val are:
**
** "msecTmo" int The time-out response for commands sent to
** the EL734. The valid range is 100 to
** 999'999. Default is 10'000.
** "eot" char* The expected terminators in responses to
** commands sent to the EL734. The first
** character specifies the number of
** terminators (max=3). Default is "1\r".
** "motor" int The index of the motor in the range 1-12 to be
** associated with this connection.
** "chan" int The RS-232-C channel number of the EL734
** controller associated with this connection.
**-------------------------------------------------------------------------
** char *EL734_EncodeMSR (&text, text_len, msr, ored_msr, fp_cntr, fr_cntr)
** ---------------
** Encode the MSR status into text.
** Input Args:
** int text_len - The size of text.
** int msr - The current MSR.
** int ored_msr - The 'ored' MSR to be encoded.
** int fp_cntr - The counter of *FP faults.
** int fr_cntr - The counter of *FR faults.
** Output Args:
** char *text - The resulting text string is stored here.
** Modified Args:
** none
** Return status:
** A pointer to "text".
** Routines called:
** none
** Description:
** The routine makes an intelligible message out of the MSR input data.
**-------------------------------------------------------------------------
** char *EL734_EncodeSS (&text, text_len, ss)
** --------------
** Encode the SS flags into text.
** Input Args:
** int text_len - The size of text.
** int ss - The value of SS register.
** Output Args:
** char *text - The resulting text string is stored here.
** Modified Args:
** none
** Return status:
** A pointer to "text".
** Routines called:
** none
** Description:
** The routine makes an intelligible message out of the input SS data.
**-------------------------------------------------------------------------
** void EL734_ErrInfo (&entry_txt_ptr, &errcode, &my_errno, &vaxc_errno)
** -------------
** Return detailed status from last operation.
** 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 EL734_GetAirCush (&handle, &present, &state)
** ----------------
** Get W and AC register values.
** Input Args:
** void **handle - The pointer to the structure returned by EL734_Open.
** Output Args:
** int *present - The W register. If non-zero, motor has an air-cushion.
** int *state - The AC register. If non-zero, air-cushion is up.
** Description:
** The routine is the same as EL734_GetEncGearing except that it issues
** a "W" command and then an "AC" command instead of an "FD" command to
** the controller.
**-------------------------------------------------------------------------
** int EL734_GetEncGearing (&handle, &numerator, &denominator)
** -------------------
** Get FD register values.
** Input Args:
** void **handle - The pointer to the structure returned by EL734_Open.
** Output Args:
** int *numerator - The encoder gearing numerator.
** int *denominator - The encoder gearing denominator.
** Modified Args:
** none
** Return status:
** True if no problems detected, otherwise False and EL734_ErrInfo
** can be called to identify the problem. Values of Errcode set by
** EL734_GetEncGearing are (other values may be set by the called
** routines):
** EL734__BAD_TMO, BAD_LOC, BAD_CMD, BAD_OFL,
** BAD_ADR, EMERG_STOP --> see EL734_Open.
** EL734__BAD_ILLG --> the response was probably not 2 integers.
** This could happen if there is noise on the
** RS232C connection to the EL734.
** If an error is detected, *numerator and *denominator are set to 0.
** Routines called:
** EL734_AddCallStack, AsynSrv_SendCmnds, AsynSrv_GetReply
** Description:
** The routine issues an "FD" command to the controller and analyses
** the result. The two parameters of the "FD" command are the numerator
** and denominator respectively.
**-------------------------------------------------------------------------
** int EL734_GetId (&handle, &id_txt, id_len)
** -----------
** Get ID register value.
** Input Args:
** void **handle - The pointer to the structure returned by EL734_Open.
** int id_len - The size of the <id_txt> buffer in bytes.
** Output Args:
** char *id_txt - The EL734 identifier ("ID" parameter).
** Description:
** The routine is the same as EL734_GetEncGearing except that it issues
** an "ID" command instead of an "H" command to the controller.
**-------------------------------------------------------------------------
** int EL734_GetLimits (&handle, &lo, &hi)
** ---------------
** Get H register values.
** Input Args:
** void **handle - The pointer to the structure returned by EL734_Open.
** Output Args:
** float *lo - The lower software limit.
** float *hi - The higher software limit.
** Description:
** The routine is the same as EL734_GetEncGearing except that it issues
** an "H" command instead of an "FD" command to the controller.
**-------------------------------------------------------------------------
** int EL734_GetMotorGearing (&handle, &numerator, &denominator)
** ---------------------
** Get FM register values.
** Input Args:
** void **handle - The pointer to the structure returned by EL734_Open.
** Output Args:
** int *numerator - The motor gearing numerator.
** int *denominator - The motor gearing denominator.
** Description:
** The routine is the same as EL734_GetEncGearing except that it issues
** an "FM" command instead of an "FD" command to the controller. The
** two parameters of the "FM" command are the numerator and denominator
** respectively.
**-------------------------------------------------------------------------
** int EL734_GetNullPoint (&handle, &null_pt)
** ------------------
** Get V register value.
** Input Args:
** void **handle - The pointer to the structure returned by EL734_Open.
** Output Args:
** int *null_pt - The null point ("V" parameter) of the EL734.
** Description:
** The routine is the same as EL734_GetEncGearing except that it issues
** a "V" command instead of an "FD" command to the controller.
**-------------------------------------------------------------------------
** int EL734_GetPosition (&handle, &ist_posit)
** -----------------
** Get U register value = current position.
** Input Args:
** void **handle - The pointer to the structure returned by EL734_Open.
** Output Args:
** float *ist_posit - The current position (U command) of the motor.
** Description:
** The routine is the same as EL734_GetEncGearing except that it issues
** a "U" command instead of an "FD" command to the controller.
**-------------------------------------------------------------------------
** int EL734_GetPrecision (&handle, &n_dec)
** ------------------
** Get A register value.
** Input Args:
** void **handle - The pointer to the structure returned by EL734_Open.
** Output Args:
** int *n_dec - The precision ("A" parameter) of the EL734.
** Description:
** The routine is the same as EL734_GetEncGearing except that it issues
** a "A" command instead of an "FD" command to the controller.
**-------------------------------------------------------------------------
** int EL734_GetRefMode (&handle, &mode)
** ----------------
** Get K register value.
** Input Args:
** void **handle - The pointer to the structure returned by EL734_Open.
** Output Args:
** int *mode - The reference seek mode ("K" parameter) of the EL734.
** Description:
** The routine is the same as EL734_GetEncGearing except that it issues
** a "K" command instead of an "FD" command to the controller.
**-------------------------------------------------------------------------
** int EL734_GetRefParam (&handle, &param)
** -----------------
** Get Q register value.
** Input Args:
** void **handle - The pointer to the structure returned by EL734_Open.
** Output Args:
** float *param - The reference seek param ("Q" parameter) of the EL734.
** Description:
** The routine is the same as EL734_GetEncGearing except that it issues
** a "Q" command instead of an "FD" command to the controller.
**-------------------------------------------------------------------------
** int EL734_GetSpeeds (&handle, &lo, &hi, &ramp)
** ---------------
** Get G, J and E register values.
** Input Args:
** void **handle - The pointer to the structure returned by EL734_Open.
** Output Args:
** int *lo - The start/stop speed (G register). Units = Steps/sec.
** int *hi - The maximum speed (J register). Units = Steps/sec.
** int *ramp - The start/stop ramp (E register). Units = kHz/sec.
** Description:
** The routine is the same as EL734_GetEncGearing except that it issues
** a "G", "J" and "E" commands instead of an "FD" command to the
** controller.
**-------------------------------------------------------------------------
** int EL734_GetStatus (&handle, &msr, &ored_msr, &fp_cntr, &fr_cntr,
** --------------- &ss, &ist_posit)
** Get MSR/SS/U register values.
** Input Args:
** void **handle - The pointer to the structure returned by EL734_Open.
** Output Args:
** int *msr - The MSR register.
** int *ored_msr - The 'ored'-MSR register. This gets zeroed every time
** a 'positioning' command is executed.
** int *fp_cntr - A counter of the 'Position Faults' (*FP). This gets
** zeroed whenever ored_msr is zeroed.
** int *fr_cntr - A counter of the 'Run Faults' (*FR). This gets
** zeroed whenever ored_msr is zeroed.
** int *ss - The SS register. This will be -1 if the motor is busy.
** float *ist_posit - The current position (U command) of the motor.
** Modified Args:
** none
** Return status:
** True if no problems detected, otherwise False and EL734_ErrInfo
** can be called to identify the problem. Values of Errcode set by
** EL734_GetStatus are (other values may be set by the called routines):
** EL734__BAD_TMO, BAD_LOC, BAD_CMD, BAD_OFL,
** BAD_ADR, EMERG_STOP --> see EL734_Open.
** EL734__BAD_ILLG --> one of the responses could probably not
** be decoded. This could happen if there is noise
** on the RS232C connection to the EL734.
** If an error is detected, ist_posit is set to 0.0 and all other
** arguments to -1.
** Routines called:
** EL734_AddCallStack, AsynSrv_SendCmnds, AsynSrv_GetReply
** Description:
** The routine issues an "MSR", "SS" and "U" command to the controller and
** analyses the result. A count is kept of each time the *FP and *FR bits
** are found to be set and an inclusive-or value of MSR is maintained.
**-------------------------------------------------------------------------
** int EL734_GetZeroPoint (&handle, &zero_pt)
** ------------------
** Get zero-point of motor.
** Input Args:
** void **handle - The pointer to the structure returned by EL734_Open.
** Output Args:
** float *zero_pt - The zero point of the EL734.
** Return status:
** Any of the errors generated by the called routines is possible plus:
** EL734__BAD_OVFL --> The encoder gearing ratio is zero so
** the conversion would overflow.
** Routines called:
** EL734_AddCallStack, EL734_GetEncGearing, EL734_GetNullPoint
** Description:
** This routine returns the zero point of the motor in the same units
** as used by the "P" and "U" commands. In other words, it reads the
** "V" parameter and converts it from "encoder-step" units to physical
** units using the encoder-gearing parameters.
**-------------------------------------------------------------------------
** int EL734_MoveNoWait (&handle, soll_posit)
** ----------------
** Move motor and don't wait for completion.
** Input Args:
** void **handle - The pntr to the structure returned by EL734_Open.
** float soll_posit - The position to which the motor should move.
** Output Args:
** none
** Modified Args:
** none
** Return status:
** True if no problems detected, otherwise False and EL734_ErrInfo
** can be called to identify the problem. Values of Errcode set by
** EL734_MoveNoWait are (other values may be set by the called routines):
** EL734__BAD_TMO, BAD_LOC, BAD_CMD, BAD_OFL,
** BAD_ADR, EMERG_STOP --> see EL734_Open.
** EL734__BAD_RNG --> Destination is out-of-range.
** EL734__BAD_STP --> Motor is disabled via Hardware "Stop"
** signal.
** EL734__BAD_ILLG --> some other response obtained from EL734.
** This could happen if there is noise
** on the RS232C connection to the EL734.
** Routines called:
** EL734_AddCallStack, AsynSrv_SendCmnds, AsynSrv_GetReply
** Description:
** The appropriate "P" command is sent to the motor and the response
** checked to check that it has been accepted. The fields "ored_msr",
** "fp_cntr" and "fr_cntr" in the handle are cleared, if so.
**-------------------------------------------------------------------------
** int EL734_MoveWait (&handle, soll_posit, &ored_msr, &fp_cntr, &fr_cntr,
** -------------- &ist_posit)
** Move motor and wait for completion.
** Input Args:
** void **handle - The pntr to the structure returned by EL734_Open.
** float soll_posit - The position to which the motor should move.
** Output Args:
** int *ored_msr \
** int *fp_cntr \ Same as EL734_WaitIdle.
** int *fr_cntr /
** float *ist_posit /
** none
** Modified Args:
** none
** Return status:
** True if no problems detected, otherwise False. If False, errcode (see
** EL734_ErrInfo) will have been set by EL734_MoveNoWait or EL734_WaitIdle.
** Routines called:
** EL734_AddCallStack, EL734_MoveNoWait, EL734_WaitIdle
** Description:
** The routine calls EL734_MoveNoWait and, if successful, EL734_WaitIdle.
**-------------------------------------------------------------------------
** int EL734_Open (&handle, host, port, chan, motor, id)
** ----------
** Open a connection to a motor.
** 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 motor - The motor to be driven.
** char *id - The expected ID of the device, normally "STPMC EL734".
** If id is NULL, the device ID is not checked.
** Output Args:
** void *handle - A pointer to a structure of type EL734info needed for
** subsequent calls to EL734_... routines. Buffer space
** for the structure is allocated dynamically. It gets
** released via a call to EL734_Close.
** Modified Args:
** none
** Return status:
** True if no problems detected, otherwise False. If False, EL734_ErrInfo
** can be called to identify the problem. Values of Errcode set by
** EL734_Open are (other values may be set by the called routines):
** EL734__BAD_TMO --> Time-out error ("?TMO" - this gets
** generated by the RS232C server).
** EL734__BAD_LOC --> EL734 off-line ("?LOC"). This should not
** happen on calls to EL734_Open since it
** sends an "RMT 1" cmnd.
** EL734__BAD_CMD --> Command error ("?CMD"). This could be
** caused by noise in the RS-232-C
** transmission.
** EL734__BAD_OFL --> Connection to EL734 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.
** EL734__BAD_ILLG --> Some other unrecognised response. This
** should never occur, of course!
** EL734__BAD_SOCKET --> Call to "AsynSrv_Open" failed.
** EL734__BAD_DEV --> Device has wrong ID
** EL734__BAD_MALLOC --> Call to "malloc" failed
** EL734__BAD_ADR --> Bad motor address ("?ADR"). Probably
** a non-existent motor has been addressed.
** EL734__EMERG_STOP --> Emergency stop ("*ES") detected.
** Routines called:
** AsynSrv_Open, the memory alloc routine "malloc", StrJoin,
** EL734_Config, AsynSrv_SendCmnds, AsynSrv_GetReply,
** AsynSrv_Close (if an error is detected).
** Description:
** The routine calls AsynSrv_Open to open a TCP/IP connection to a server
** offering the "RS-232-C" service for an EL734 Motor Controller. "RMT 1"
** and "ECHO 0" commands are sent to ensure the device is on-line, an "ID"
** command is sent (only if 'id' is non-NULL) to ensure that an EL734 is
** being addressed and an "MSR <motor>" command is sent to ensure that
** the motor exists.
** Note:
** For all error status returns, there is no open connection to the server
** and the handle is set to zero.
**-------------------------------------------------------------------------
** int EL734_PutOffline (&handle)
** ----------------
** Send "ECHO 1" and "RMT 0" commands to EL734 server.
** Input Args:
** void **handle - The pntr to the structure returned by EL734_Open.
** Output Args:
** none
** Modified Args:
** none
** Return status:
** True if no problems detected, otherwise False and errcode (see
** EL734_ErrInfo) is set to indicate the nature of the problem.
** Values of Errcode set by EL734_PutOffline are (other values may be set
** by the called routines):
** EL734__BAD_ASYNSRV --> An error occurred in AsynSrv_Utility.
** Call AsynSrv_ErrInfo for more info.
** EL734__BAD_ILLG --> an unrecognised response. This
** should never occur, of course!
** Routines called:
** EL734_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 EL734_PutOnline (&handle, echo)
** ---------------
** Send "RMT 1" and "ECHO x" commands to EL734 server.
** Input Args:
** void **handle - The pntr to the structure returned by EL734_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
** EL734_ErrInfo) is set to indicate the nature of the problem.
** Values of Errcode set by EL734_PutOnline are (other values may be set
** by the called routines):
** EL734__BAD_PAR --> "echo" is not 0, 1 or 2.
** EL734__BAD_ASYNSRV --> An error occurred in AsynSrv_Utility.
** Call AsynSrv_ErrInfo for more info.
** EL734__BAD_ILLG --> an unrecognised response. This
** should never occur, of course!
** Routines called:
** EL734_AddCallStack, AsynSrv_SendCmnds, AsynSrv_GetReply
** Description:
** The routine calls AsynSrv_SendCmnds to execute "RMT 1" and "ECHO x"
** commands. The replies are checked.
**-------------------------------------------------------------------------
** int EL734_SendCmnd (&handle, &cmnd, &rply, rply_size)
** --------------
** Send a command to RS232C server.
** Input Args:
** void **handle - The pntr to the structure returned by EL734_Open.
** char *cmnd - A command, terminated by NULL, for sending to the
** EL734 counter controller. The command must have
** any necessary \r character included.
** int rply_size - the size of the <rply> buffer.
** Output Args:
** char *rply - A buffer for receiving the reply.
** Modified Args:
** none
** Return status:
** True if no problems detected, otherwise False and errcode (see
** EL734_ErrInfo) is set to indicate the nature of the problem.
** Values of Errcode set by EL734_SendCmnd are (other values may be set
** by the called routines):
** EL734__BAD_ASYNSRV --> An error occurred in AsynSrv_Utility.
** Call AsynSrv_ErrInfo for more info.
** Routines called:
** EL734_AddCallStack, AsynSrv_SendCmnds, AsynSrv_GetReply
** Description:
** The command is passed to AsynSrv_SendCmnds and the reply extracted.
**-------------------------------------------------------------------------
** int EL734_SetAirCush (&handle, state)
** ----------------
** Set AC register value.
** Input Args:
** void **handle - The pointer to the structure returned by EL734_Open.
** Input Args:
** int state - The new state of the AC register. 0 --> down
** non-zero --> up
** Output Args:
** none
** Modified Args:
** none
** Return status:
** True if no problems detected, otherwise False and EL734_ErrInfo
** can be called to identify the problem. Values of Errcode set by
** EL734_SetAirCush are (other values may be set by the called
** routines):
** EL734__BAD_TMO, BAD_LOC, BAD_CMD, BAD_OFL,
** BAD_ADR, EMERG_STOP --> see EL734_Open.
** EL734__VFY_ERR --> the value for the AC register returned by the
** call to EL734_GetAirCush was not the value which
** was sent via the AC command. This could happen
** if there is noise on the RS232C connection to
** the EL734.
** Routines called:
** EL734_AddCallStack, AsynSrv_SendCmnds, AsynSrv_GetReply,
** EL734_GetAirCush
** Description:
** The routine issues an "AC" command to the controller to set the air-
** cushions of the motor up or down. It then calls EL734_GetAirCush
** to check that the air-cushions were set correctly.
**-------------------------------------------------------------------------
** int EL734_SetErrcode (&info_ptr, &response, &cmnd)
** ----------------
** Set up EL734_errcode (for internal use only)
** Input Args:
** struct EL734info *info_ptr - The pntr to the structure returned by
** EL734_Open.
** char *response - The response received from a command.
** char *cmnd - The command which was sent.
** Output Args:
** none
** Modified Args:
** none
** Return status:
** The value of EL734_errcode.
** Routines called:
** AsynSrv_SendCmnds
** Description:
** The command checks *response for certain keywords. If not recognised,
** extra action is undertaken to try to see if the emergency stop state
** is active or not.
**-------------------------------------------------------------------------
** int EL734_SetHighSpeed (&handle, hi)
** ------------------
** Set J register value.
** Input Args:
** void **handle - The pointer to the structure returned by EL734_Open.
** Input Args:
** int hi - The maximum speed (J register). Units = Steps/sec.
** Output Args:
** none
** Modified Args:
** none
** Return status:
** True if no problems detected, otherwise False and EL734_ErrInfo
** can be called to identify the problem. Values of Errcode set by
** EL734_SetHighSpeed are (other values may be set by the called
** routines):
** EL734__BAD_TMO, BAD_LOC, BAD_CMD, BAD_OFL,
** BAD_ADR, EMERG_STOP --> see EL734_Open.
** EL734__VFY_ERR --> the value for the J register returned by the call
** to EL734_GetSpeeds was not the value which was
** sent via the J command. This could happen if
** there is noise on the RS232C connection to
** the EL734.
** Routines called:
** EL734_AddCallStack, AsynSrv_SendCmnds, AsynSrv_GetReply, EL734_GetSpeeds
** Description:
** The routine issues a "J" command to the controller to set the max speed
** of the motor. It then calls EL734_GetSpeeds to check that the speed
** was set correctly.
**-------------------------------------------------------------------------
** int EL734_SetLowSpeed (&handle, hi)
** -----------------
** Set G register value.
** Input Args:
** void **handle - The pointer to the structure returned by EL734_Open.
** Input Args:
** int lo - The start/stop speed (G register). Units = Steps/sec.
** Description:
** The routine is identical to the EL734_SetHighSpeed routine except that
** a "G" command rather than a "J" command is issued to the controller to
** set the start/stop speed.
**-------------------------------------------------------------------------
** int EL734_SetRamp (&handle, ramp)
** -------------
** Set E register value.
** Input Args:
** void **handle - The pointer to the structure returned by EL734_Open.
** Input Args:
** int ramp - The start/stop ramp (E register). Units = kHz/sec.
** Description:
** The routine is identical to the EL734_SetHighSpeed routine except that
** an "E" command rather than a "J" command is issued to the controller to
** set the start/stop ramp.
**-------------------------------------------------------------------------
** int EL734_Stop (&handle)
** ----------
** Send a stop command to motor
** Input Args:
** void **handle - The pointer to the structure returned by EL734_Open.
** Output Args:
** None
** Description:
** The routine is similar to EL734_GetEncGearing except that it issues
** a "Q m" command instead of an "FD" command to the controller and
** a null response (rather than parameter values) is expected.
**-------------------------------------------------------------------------
** int EL734_WaitIdle (&handle, &ored_msr, &fp_cntr, &fr_cntr, &ist_posit)
** --------------
** Wait till MSR goes to zero.
** Input Args:
** void **handle - The pntr to the structure returned by EL734_Open.
** Output Args:
** int *ored_msr \
** int *fp_cntr \ Same as EL734_GetStatus.
** int *fr_cntr /
** float *ist_posit /
** none
** Modified Args:
** none
** Return status:
** True if no problems detected, otherwise False and Errcode (see
** EL734_ErrInfo) will have been set by the called routines to indicate
** the nature of the problem.
** Routines called:
** EL734_AddCallStack, EL734_GetStatus
** Description:
** Routine EL734_GetStatus is called repeatedly at a predefined frequency
** until the MSR__BUSY bit in the MSR register is zero.
**-------------------------------------------------------------------------
** void EL734_ZeroStatus (&handle)
** -----------------
** Zero the "ored-MSR" and fault counters.
** Input Args:
** void **handle - The pntr to the structure returned by EL734_Open.
** Output Args:
** none
** Modified Args:
** none
** Return status:
** none
** Routines called:
** none
** Description:
** The "ored-MSR" and fault counters in the handle are zeroed.
**============================================================================*/
/*
**---------------------------------------------------------------------------
** Global Definitions
*/
#include <stdlib.h>
#include <stdio.h>
#include <stdarg.h>
#include <errno.h>
#include <signal.h>
#include <netdb.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <string.h>
#ifdef __VMS
#include <unixio.h>
#else
#include <unistd.h>
#ifdef FORTIFY
#include <fortify.h>
#endif
#endif
/*-----------------------------------------------------------------*/
#include <rs232c_def.h>
#include <asynsrv_def.h>
#include <el734_def.h>
#include <sinq_prototypes.h>
#define True 1
#define False 0
/*--------------------------------------------------------------------------
** Global Variables
*/
static int EL734_call_depth = 0;
static char EL734_routine[5][64];
static int EL734_errcode = 0;
static int EL734_errno, EL734_vaxc_errno;
char EL734_IllgText[256];
/*
**---------------------------------------------------------------------------
** EL734_AddCallStack: Add a routine name to the call stack.
** This allows EL734_ErrInfo to generate a
** trace-back in case of error.
*/
int EL734_AddCallStack(
/* ==================
*/ struct EL734info *pntr,
char *name)
{
if (EL734_errcode != 0)
return False;
if (EL734_call_depth < 5) {
strcpy(EL734_routine[EL734_call_depth], name);
EL734_call_depth++;
}
if (pntr == NULL) {
EL734_errcode = EL734__NOT_OPEN;
return False;
}
if (pntr->asyn_info.skt <= 0) {
memset(pntr->from_host.msg_size,
'0', sizeof(pntr->from_host.msg_size));
EL734_errcode = (pntr->asyn_info.skt < 0) ? EL734__FORCED_CLOSED
: EL734__NO_SOCKET;
return False;
}
return True;
}
/*
**---------------------------------------------------------------------------
** EL734_Close: Close a connection to a motor.
*/
int EL734_Close(
/* ===========
*/ void **handle,
int force_flag)
{
struct EL734info *info_ptr;
char buff[4];
info_ptr = (struct EL734info *) *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;
}
/*
**---------------------------------------------------------------------------
** EL734_Config: Configure a connection to a motor.
*/
int EL734_Config(
/* ============
*/ void **handle,
...)
{
char buff[16];
va_list ap; /* Pointer to variable args */
char *txt_ptr;
int intval;
struct EL734info *info_ptr;
/*----------------------------------------------
*/
info_ptr = (struct EL734info *) *handle;
if (!EL734_AddCallStack(info_ptr, "EL734_Config"))
return False;
/*----------------------------------------------
*/
va_start(ap, handle); /* Set up var arg machinery */
txt_ptr = va_arg(ap, char *); /* Get pntr to first parameter ident */
while (txt_ptr != NULL) {
if (strcmp(txt_ptr, "msecTmo") == 0) {
intval = va_arg(ap, int);
if ((intval < 100) || (intval > 999999)) {
EL734_errcode = EL734__BAD_PAR;
return False;
}
sprintf(buff, "%04d", intval / 100); /* Convert to ASCII as ..
** .. deci-secs */
memcpy(info_ptr->asyn_info.tmo, buff, 4);
} else if (strcmp(txt_ptr, "eot") == 0) {
txt_ptr = va_arg(ap, char *);
if (txt_ptr == NULL) {
EL734_errcode = EL734__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:
EL734_errcode = EL734__BAD_PAR;
return False;
}
} else if (strcmp(txt_ptr, "motor") == 0) {
intval = va_arg(ap, int);
if ((intval < 1) || (intval > 12)) {
EL734_errcode = EL734__BAD_PAR;
return False;
}
info_ptr->motor = intval;
} else if (strcmp(txt_ptr, "chan") == 0) {
intval = va_arg(ap, int);
if ((intval < 0) || (intval > 255)) {
EL734_errcode = EL734__BAD_PAR;
return False;
}
info_ptr->asyn_info.chan = intval;
sprintf(buff, "%04d", intval); /* Convert to ASCII */
memcpy(info_ptr->asyn_info.chan_char, buff, 4);
} else {
EL734_errcode = EL734__BAD_PAR;
return False;
}
txt_ptr = va_arg(ap, char *); /* Get pntr to next parameter ident */
}
if (EL734_errcode != 0)
return False;
EL734_call_depth--;
return True;
}
/*
**---------------------------------------------------------------------------
** EL734_EncodeMSR: Encode the MSR status into text.
*/
char *EL734_EncodeMSR(char *text, int text_len,
/* ===============
*/ int msr,
int ored_msr, int fp_cntr, int fr_cntr)
{
int len;
char my_text[132];
char my_text_0[32];
if (msr == 0) {
ored_msr = ored_msr & ~(MSR__BUSY); /* Zero "Busy" bit */
if (ored_msr == MSR__OK) {
StrJoin(text, text_len, "Status, MSR = Idle. Positioned OK.", "");
} else {
if ((ored_msr & MSR__OK) != 0) {
StrJoin(text, text_len, "Status, MSR = Idle. Positioned OK. ", "");
} else {
StrJoin(text, text_len, "Status, MSR = Idle. ", "");
}
if ((ored_msr & MSR__REF_OK) != 0) {
StrJoin(my_text, sizeof(my_text), text, "");
StrJoin(text, text_len, my_text, "Ref. Pos'n OK. ");
}
if ((ored_msr & MSR__LIM_ERR) != 0) {
StrJoin(my_text, sizeof(my_text), text, "");
StrJoin(text, text_len, my_text, "Limit Switch Problem. ");
}
if ((ored_msr & MSR__AC_FAIL) != 0) {
StrJoin(my_text, sizeof(my_text), text, "");
StrJoin(text, text_len, my_text, "Air-Cushion Error. ");
}
if ((ored_msr & MSR__REF_FAIL) != 0) {
StrJoin(my_text, sizeof(my_text), text, "");
StrJoin(text, text_len, my_text, "Ref. Pos'n Fail. ");
}
if ((ored_msr & MSR__POS_FAIL) != 0) {
StrJoin(my_text, sizeof(my_text), text, "");
StrJoin(text, text_len, my_text, "Pos'n Fail. ");
}
if ((ored_msr & MSR__POS_FAULT) != 0) {
StrJoin(my_text, sizeof(my_text), text, "");
if (fp_cntr == 1) {
StrJoin(text, text_len, my_text, "1 Pos'n Fault. ");
} else {
sprintf(my_text_0, "%d Pos'n Faults. ", fp_cntr);
StrJoin(text, text_len, my_text, my_text_0);
}
}
if ((ored_msr & MSR__RUN_FAIL) != 0) {
StrJoin(my_text, sizeof(my_text), text, "");
StrJoin(text, text_len, my_text, "Run Fail. ");
}
if ((ored_msr & MSR__RUN_FAULT) != 0) {
StrJoin(my_text, sizeof(my_text), text, "");
if (fr_cntr == 1) {
StrJoin(text, text_len, my_text, "1 Run Fault. ");
} else {
sprintf(my_text_0, "%d Run Faults. ", fr_cntr);
StrJoin(text, text_len, my_text, my_text_0);
}
}
if ((ored_msr & MSR__HALT) != 0) {
StrJoin(my_text, sizeof(my_text), text, "");
StrJoin(text, text_len, my_text, "Halt. ");
}
if ((ored_msr & MSR__HI_LIM) != 0) {
StrJoin(my_text, sizeof(my_text), text, "");
StrJoin(text, text_len, my_text, "Hit HiLim. ");
}
if ((ored_msr & MSR__LO_LIM) != 0) {
StrJoin(my_text, sizeof(my_text), text, "");
StrJoin(text, text_len, my_text, "Hit LoLim. ");
}
if ((ored_msr & MSR__STOPPED) != 0) {
StrJoin(my_text, sizeof(my_text), text, "");
StrJoin(text, text_len, my_text, "Stopped. ");
}
}
} else if ((msr & ~(0x2fff)) != 0) {
StrJoin(text, text_len, "Status, MSR = ??", "");
} else {
sprintf(my_text, "%#x ", msr);
StrJoin(text, text_len, "Status, MSR = ", my_text);
if ((msr & MSR__LIM_ERR) != 0) {
StrJoin(my_text, sizeof(my_text), text, "");
StrJoin(text, text_len, my_text, "Limit Switch Problem/");
}
if ((msr & MSR__AC_FAIL) != 0) {
StrJoin(my_text, sizeof(my_text), text, "");
StrJoin(text, text_len, my_text, "Air-Cushion Error/");
}
if ((msr & MSR__REF_FAIL) != 0) {
StrJoin(my_text, sizeof(my_text), text, "");
StrJoin(text, text_len, my_text, "Ref. Pos'n Fail/");
}
if ((msr & MSR__POS_FAIL) != 0) {
StrJoin(my_text, sizeof(my_text), text, "");
StrJoin(text, text_len, my_text, "Pos'n Fail/");
}
if ((msr & MSR__POS_FAULT) != 0) {
StrJoin(my_text, sizeof(my_text), text, "");
StrJoin(text, text_len, my_text, "Pos'n Fault/");
}
if ((msr & MSR__RUN_FAIL) != 0) {
StrJoin(my_text, sizeof(my_text), text, "");
StrJoin(text, text_len, my_text, "Run Fail/");
}
if ((msr & MSR__RUN_FAULT) != 0) {
StrJoin(my_text, sizeof(my_text), text, "");
StrJoin(text, text_len, my_text, "Run Fault/");
}
if ((msr & MSR__HALT) != 0) {
StrJoin(my_text, sizeof(my_text), text, "");
StrJoin(text, text_len, my_text, "Halt/");
}
if ((msr & MSR__HI_LIM) != 0) {
StrJoin(my_text, sizeof(my_text), text, "");
StrJoin(text, text_len, my_text, "Hit HiLim/");
}
if ((msr & MSR__LO_LIM) != 0) {
StrJoin(my_text, sizeof(my_text), text, "");
StrJoin(text, text_len, my_text, "Hit LoLim/");
}
if ((msr & MSR__STOPPED) != 0) {
StrJoin(my_text, sizeof(my_text), text, "");
StrJoin(text, text_len, my_text, "Stopped/");
}
if ((msr & MSR__REF_OK) != 0) {
StrJoin(my_text, sizeof(my_text), text, "");
StrJoin(text, text_len, my_text, "Ref. Pos'n OK/");
}
if ((msr & MSR__OK) != 0) {
StrJoin(my_text, sizeof(my_text), text, "");
StrJoin(text, text_len, my_text, "OK/");
}
if ((msr & MSR__BUSY) != 0) {
StrJoin(my_text, sizeof(my_text), text, "");
StrJoin(text, text_len, my_text, "Busy/");
}
len = strlen(text);
text[len - 1] = '\0';
}
return text;
}
/*
**---------------------------------------------------------------------------
** EL734_EncodeSS: Encode the SS flags into text.
*/
char *EL734_EncodeSS(char *text, int text_len, int ss)
{
/* ==============
*/
int len;
char my_text[132];
char my_text_0[32];
if (ss == 0) {
StrJoin(text, text_len, "Flags, SS = 0", "");
} else if ((ss & ~(0x3f)) != 0) {
StrJoin(text, text_len, "Flags, SS = ??", "");
} else {
sprintf(my_text, "Flags, SS = 0x%02X ", ss);
my_text_0[0] = '\0';
if ((ss & 0x20) != 0)
strcat(my_text_0, "LSX/");
if ((ss & 0x10) != 0)
strcat(my_text_0, "LS2/");
if ((ss & 0x08) != 0)
strcat(my_text_0, "LS1/");
if ((ss & 0x04) != 0)
strcat(my_text_0, "STP/");
if ((ss & 0x02) != 0)
strcat(my_text_0, "CCW/");
if ((ss & 0x01) != 0)
strcat(my_text_0, "HLT/");
len = strlen(my_text_0);
my_text_0[len - 1] = '\0';
StrJoin(text, text_len, my_text, my_text_0);
}
return text;
}
/*
**-------------------------------------------------------------------------
** EL734_ErrInfo: Return detailed status from last operation.
*/
void EL734_ErrInfo(
/* =============
*/ char **entry_txt,
int *errcode, int *my_errno, int *vaxc_errno)
{
int i;
char buff[80], *txt;
int asyn_errcode, asyn_errno, asyn_vaxerrno;
char *asyn_errtxt;
if (EL734_call_depth <= 0) {
strcpy(EL734_routine[0], "EL734_no_error_detected");
*errcode = 0;
*my_errno = 0;
*vaxc_errno = 0;
} else {
if (EL734_call_depth > 1) { /* Concatenate the names */
for (i = 1; i < EL734_call_depth; i++) {
strcat(EL734_routine[0], "/");
StrJoin(EL734_routine[0], sizeof(EL734_routine),
EL734_routine[0], EL734_routine[i]);
}
}
*errcode = EL734_errcode;
*my_errno = EL734_errno;
*vaxc_errno = EL734_vaxc_errno;
switch (EL734_errcode) {
case EL734__BAD_ADR:
txt = "/EL734__BAD_ADR";
break;
case EL734__BAD_ASYNSRV:
txt = "/EL734__BAD_ASYNSRV";
break;
case EL734__BAD_CMD:
txt = "/EL734__BAD_CMD";
break;
case EL734__BAD_DEV:
txt = "/EL734__BAD_DEV";
break;
case EL734__BAD_ILLG:
txt = "/EL734__BAD_ILLG";
break;
case EL734__BAD_LOC:
txt = "/EL734__BAD_LOC";
break;
case EL734__BAD_MALLOC:
txt = "/EL734__BAD_MALLOC";
break;
case EL734__BAD_OFL:
txt = "/EL734__BAD_OFL";
break;
case EL734__BAD_OVFL:
txt = "/EL734__BAD_OVFL";
break;
case EL734__BAD_PAR:
txt = "/EL734__BAD_PAR";
break;
case EL734__BAD_RNG:
txt = "/EL734__BAD_RNG";
break;
case EL734__BAD_SOCKET:
txt = "/EL734__BAD_SOCKET";
break;
case EL734__BAD_STP:
txt = "/EL734__BAD_STP";
break;
case EL734__BAD_TMO:
txt = "/EL734__BAD_TMO";
break;
case EL734__EMERG_STOP:
txt = "/EL734__EMERG_STOP";
break;
case EL734__FORCED_CLOSED:
txt = "/EL734__FORCED_CLOSED";
break;
case EL734__NOT_OPEN:
txt = "/EL734__NOT_OPEN";
break;
case EL734__NO_SOCKET:
txt = "/EL734__NO_SOCKET";
break;
default:
sprintf(buff, "/EL734__unknown_err_code: %d", EL734_errcode);
txt = buff;
}
StrJoin(EL734_routine[0], sizeof(EL734_routine), EL734_routine[0],
txt);
}
AsynSrv_ErrInfo(&asyn_errtxt, &asyn_errcode, &asyn_errno,
&asyn_vaxerrno);
if (asyn_errcode != 0) {
strcat(EL734_routine[0], "/");
StrJoin(EL734_routine[0], sizeof(EL734_routine),
EL734_routine[0], asyn_errtxt);
}
*entry_txt = EL734_routine[0];
EL734_call_depth = 0;
EL734_errcode = 0;
}
/*
**---------------------------------------------------------------------------
** EL734_GetAirCush: Get W and AC register values.
*/
int EL734_GetAirCush(
/* ================
*/ void **handle,
int *present, int *state)
{
int status;
struct EL734info *info_ptr;
char cmnd0[10], cmnd1[10];
char *rply_ptr, *rply_ptr0, *rply_ptr1;
/*----------------------------------------------
*/
*present = *state = 0;
info_ptr = (struct EL734info *) *handle;
if (!EL734_AddCallStack(info_ptr, "EL734_GetAirCush"))
return False;
/*----------------------------------------------
** Send W and AC cmnds to EL734
*/
sprintf(cmnd0, "w %d\r", info_ptr->motor);
sprintf(cmnd1, "ac %d\r", info_ptr->motor);
status = AsynSrv_SendCmnds(&info_ptr->asyn_info,
&info_ptr->to_host, &info_ptr->from_host,
cmnd0, cmnd1, NULL);
if (!status) {
*present = *state = 0;
EL734_errcode = EL734__BAD_ASYNSRV;
return False;
} else {
rply_ptr1 = NULL;
rply_ptr0 =
AsynSrv_GetReply(&info_ptr->asyn_info, &info_ptr->from_host, NULL);
if (rply_ptr0 != NULL)
rply_ptr1 =
AsynSrv_GetReply(&info_ptr->asyn_info, &info_ptr->from_host,
rply_ptr0);
if (rply_ptr0 == NULL)
rply_ptr0 = "?no_response";
if (rply_ptr1 == NULL)
rply_ptr1 = "?no_response";
if ((sscanf(rply_ptr0, "%d", present) != 1) ||
(sscanf(rply_ptr1, "%d", state) != 1)) {
if (*rply_ptr0 == '?') {
rply_ptr = rply_ptr0;
} else if (*rply_ptr1 == '?') {
rply_ptr = rply_ptr1;
} else {
rply_ptr = "?funny_response";
}
*present = *state = 0;
EL734_SetErrcode(info_ptr, rply_ptr, "W\" or \"AC");
return False;
}
}
if (EL734_errcode != 0)
return False;
EL734_call_depth--;
return True;
}
/*
**---------------------------------------------------------------------------
** EL734_GetEncGearing: Get FD register values.
*/
int EL734_GetEncGearing(
/* ===================
*/ void **handle,
int *nominator, int *denominator)
{
int status;
struct EL734info *info_ptr;
char cmnd0[10];
char *rply_ptr0;
/*----------------------------------------------
*/
*nominator = *denominator = 0;
info_ptr = (struct EL734info *) *handle;
if (!EL734_AddCallStack(info_ptr, "EL734_GetEncGearing"))
return False;
/*----------------------------------------------
** Send FD cmnd to EL734
*/
sprintf(cmnd0, "fd %d\r", info_ptr->motor);
status = AsynSrv_SendCmnds(&info_ptr->asyn_info,
&info_ptr->to_host, &info_ptr->from_host,
cmnd0, NULL);
if (!status) {
*nominator = *denominator = 0;
EL734_errcode = EL734__BAD_ASYNSRV;
return False;
} else {
rply_ptr0 =
AsynSrv_GetReply(&info_ptr->asyn_info, &info_ptr->from_host, NULL);
if (rply_ptr0 == NULL)
rply_ptr0 = "?no_response";
if (sscanf(rply_ptr0, "%d %d", nominator, denominator) == 2) {
if (EL734_errcode != 0)
return False;
EL734_call_depth--;
return True;
}
*nominator = *denominator = 0;
EL734_SetErrcode(info_ptr, rply_ptr0, "FD");
return False;
}
}
/*
**---------------------------------------------------------------------------
** EL734_GetId: Get ID register value.
*/
int EL734_GetId(
/* ===========
*/ void **handle,
char *id_txt, int id_len)
{
int status;
struct EL734info *info_ptr;
char *rply_ptr0;
/*----------------------------------------------
*/
*id_txt = '\0';
info_ptr = (struct EL734info *) *handle;
if (!EL734_AddCallStack(info_ptr, "EL734_GetId"))
return False;
/*----------------------------------------------
** Send ID cmnd to EL734
*/
status = AsynSrv_SendCmnds(&info_ptr->asyn_info,
&info_ptr->to_host, &info_ptr->from_host,
"id\r", NULL);
if (!status) {
EL734_errcode = EL734__BAD_ASYNSRV;
return False;
} else {
rply_ptr0 =
AsynSrv_GetReply(&info_ptr->asyn_info, &info_ptr->from_host, NULL);
if ((rply_ptr0 != NULL) && (*rply_ptr0 != '\0') && (*rply_ptr0 != '?')) {
StrJoin(id_txt, id_len, rply_ptr0, "");
if (EL734_errcode != 0)
return False;
EL734_call_depth--;
return True;
}
if (rply_ptr0 == NULL)
rply_ptr0 = "?no_response";
EL734_SetErrcode(info_ptr, rply_ptr0, "ID");
return False;
}
}
/*
**---------------------------------------------------------------------------
** EL734_GetLimits: Get H register values.
*/
int EL734_GetLimits(
/* ===============
*/ void **handle,
float *lo, float *hi)
{
int status;
struct EL734info *info_ptr;
char cmnd0[10];
char *rply_ptr0;
/*----------------------------------------------
*/
*lo = *hi = 0.0;
info_ptr = (struct EL734info *) *handle;
if (!EL734_AddCallStack(info_ptr, "EL734_GetLimits"))
return False;
/*----------------------------------------------
** Send H cmnd to EL734
*/
sprintf(cmnd0, "h %d\r", info_ptr->motor);
status = AsynSrv_SendCmnds(&info_ptr->asyn_info,
&info_ptr->to_host, &info_ptr->from_host,
cmnd0, NULL);
if (!status) {
*lo = *hi = 0.0;
EL734_errcode = EL734__BAD_ASYNSRV;
return False;
} else {
rply_ptr0 =
AsynSrv_GetReply(&info_ptr->asyn_info, &info_ptr->from_host, NULL);
if (rply_ptr0 == NULL)
rply_ptr0 = "?no_response";
if (sscanf(rply_ptr0, "%f %f", lo, hi) == 2) {
if (EL734_errcode != 0)
return False;
EL734_call_depth--;
return True;
}
*lo = *hi = 0.0;
EL734_SetErrcode(info_ptr, rply_ptr0, "H");
return False;
}
}
/*
**---------------------------------------------------------------------------
** EL734_GetMotorGearing: Get FM register values.
*/
int EL734_GetMotorGearing(
/* =====================
*/ void **handle,
int *nominator, int *denominator)
{
int status;
struct EL734info *info_ptr;
char cmnd0[10];
char *rply_ptr0;
/*----------------------------------------------
*/
*nominator = *denominator = 0;
info_ptr = (struct EL734info *) *handle;
if (!EL734_AddCallStack(info_ptr, "EL734_GetMotorGearing"))
return False;
/*----------------------------------------------
** Send FM cmnd to EL734
*/
sprintf(cmnd0, "fm %d\r", info_ptr->motor);
status = AsynSrv_SendCmnds(&info_ptr->asyn_info,
&info_ptr->to_host, &info_ptr->from_host,
cmnd0, NULL);
if (!status) {
*nominator = *denominator = 0;
EL734_errcode = EL734__BAD_ASYNSRV;
return False;
} else {
rply_ptr0 =
AsynSrv_GetReply(&info_ptr->asyn_info, &info_ptr->from_host, NULL);
if (rply_ptr0 == NULL)
rply_ptr0 = "?no_response";
if (sscanf(rply_ptr0, "%d %d", nominator, denominator) == 2) {
if (EL734_errcode != 0)
return False;
EL734_call_depth--;
return True;
}
*nominator = *denominator = 0;
EL734_SetErrcode(info_ptr, rply_ptr0, "FM");
return False;
}
}
/*
**---------------------------------------------------------------------------
** EL734_GetNullPoint: Get V register value.
*/
int EL734_GetNullPoint(
/* ==================
*/ void **handle,
int *null_pt)
{
int status;
struct EL734info *info_ptr;
char cmnd0[10];
char *rply_ptr0;
/*----------------------------------------------
*/
*null_pt = 0;
info_ptr = (struct EL734info *) *handle;
if (!EL734_AddCallStack(info_ptr, "EL734_GetNullPoint"))
return False;
/*----------------------------------------------
** Send V cmnd to EL734
*/
sprintf(cmnd0, "v %d\r", info_ptr->motor);
status = AsynSrv_SendCmnds(&info_ptr->asyn_info,
&info_ptr->to_host, &info_ptr->from_host,
cmnd0, NULL);
if (!status) {
*null_pt = 0;
EL734_errcode = EL734__BAD_ASYNSRV;
return False;
} else {
rply_ptr0 =
AsynSrv_GetReply(&info_ptr->asyn_info, &info_ptr->from_host, NULL);
if (rply_ptr0 == NULL)
rply_ptr0 = "?no_response";
if (sscanf(rply_ptr0, "%d", null_pt) == 1) {
if (EL734_errcode != 0)
return False;
EL734_call_depth--;
return True;
}
*null_pt = 0;
EL734_SetErrcode(info_ptr, rply_ptr0, "V");
return False;
}
}
/*
**---------------------------------------------------------------------------
** EL734_GetPosition: Get U register value, the current position.
*/
int EL734_GetPosition(
/* =================
*/ void **handle,
float *ist_posit)
{
int status;
struct EL734info *info_ptr;
char cmnd0[10];
char *rply_ptr0;
/*----------------------------------------------
*/
*ist_posit = 0.0;
info_ptr = (struct EL734info *) *handle;
if (!EL734_AddCallStack(info_ptr, "EL734_GetPosition"))
return False;
/*----------------------------------------------
** Send U cmnd to EL734
*/
sprintf(cmnd0, "u %d\r", info_ptr->motor);
status = AsynSrv_SendCmnds(&info_ptr->asyn_info,
&info_ptr->to_host, &info_ptr->from_host,
cmnd0, NULL);
if (!status) {
*ist_posit = 0.0;
EL734_errcode = EL734__BAD_ASYNSRV;
return False;
} else {
rply_ptr0 =
AsynSrv_GetReply(&info_ptr->asyn_info, &info_ptr->from_host, NULL);
if (rply_ptr0 == NULL)
rply_ptr0 = "?no_response";
if (sscanf(rply_ptr0, "%f", ist_posit) == 1) {
if (EL734_errcode != 0)
return False;
EL734_call_depth--;
return True;
}
*ist_posit = 0.0;
EL734_SetErrcode(info_ptr, rply_ptr0, "U");
return False;
}
}
/*
**---------------------------------------------------------------------------
** EL734_GetPrecision: Get A register value.
*/
int EL734_GetPrecision(
/* ==================
*/ void **handle,
int *n_dec)
{
int status;
struct EL734info *info_ptr;
char cmnd0[10];
char *rply_ptr0;
/*----------------------------------------------
*/
*n_dec = 3;
info_ptr = (struct EL734info *) *handle;
if (!EL734_AddCallStack(info_ptr, "EL734_GetPrecision"))
return False;
/*----------------------------------------------
** Send A cmnd to EL734
*/
sprintf(cmnd0, "a %d\r", info_ptr->motor);
status = AsynSrv_SendCmnds(&info_ptr->asyn_info,
&info_ptr->to_host, &info_ptr->from_host,
cmnd0, NULL);
if (!status) {
*n_dec = 3;
EL734_errcode = EL734__BAD_ASYNSRV;
return False;
} else {
rply_ptr0 =
AsynSrv_GetReply(&info_ptr->asyn_info, &info_ptr->from_host, NULL);
if (rply_ptr0 == NULL)
rply_ptr0 = "?no_response";
if (sscanf(rply_ptr0, "%d", n_dec) == 1) {
if (EL734_errcode != 0)
return False;
EL734_call_depth--;
return True;
}
*n_dec = 3;
EL734_SetErrcode(info_ptr, rply_ptr0, "A");
return False;
}
}
/*
**---------------------------------------------------------------------------
** EL734_GetRefMode: Get K register value.
*/
int EL734_GetRefMode(
/* ================
*/ void **handle,
int *mode)
{
int status;
struct EL734info *info_ptr;
char cmnd0[10];
char *rply_ptr0;
/*----------------------------------------------
*/
*mode = 0;
info_ptr = (struct EL734info *) *handle;
if (!EL734_AddCallStack(info_ptr, "EL734_GetRefMode"))
return False;
/*----------------------------------------------
** Send K cmnd to EL734
*/
sprintf(cmnd0, "k %d\r", info_ptr->motor);
status = AsynSrv_SendCmnds(&info_ptr->asyn_info,
&info_ptr->to_host, &info_ptr->from_host,
cmnd0, NULL);
if (!status) {
*mode = 0;
EL734_errcode = EL734__BAD_ASYNSRV;
return False;
} else {
rply_ptr0 =
AsynSrv_GetReply(&info_ptr->asyn_info, &info_ptr->from_host, NULL);
if (rply_ptr0 == NULL)
rply_ptr0 = "?no_response";
if (sscanf(rply_ptr0, "%d", mode) == 1) {
if (EL734_errcode != 0)
return False;
EL734_call_depth--;
return True;
}
*mode = 0;
EL734_SetErrcode(info_ptr, rply_ptr0, "K");
return False;
}
}
/*
**---------------------------------------------------------------------------
** EL734_GetRefParam: Get Q register value.
*/
int EL734_GetRefParam(
/* =================
*/ void **handle,
float *param)
{
int status;
struct EL734info *info_ptr;
char cmnd0[10];
char *rply_ptr0;
/*----------------------------------------------
*/
*param = 0.0;
info_ptr = (struct EL734info *) *handle;
if (!EL734_AddCallStack(info_ptr, "EL734_GetRefParam"))
return False;
/*----------------------------------------------
** Send Q cmnd to EL734
*/
sprintf(cmnd0, "q %d\r", info_ptr->motor);
status = AsynSrv_SendCmnds(&info_ptr->asyn_info,
&info_ptr->to_host, &info_ptr->from_host,
cmnd0, NULL);
if (!status) {
*param = 0.0;
EL734_errcode = EL734__BAD_ASYNSRV;
return False;
} else {
rply_ptr0 =
AsynSrv_GetReply(&info_ptr->asyn_info, &info_ptr->from_host, NULL);
if (rply_ptr0 == NULL)
rply_ptr0 = "?no_response";
if (sscanf(rply_ptr0, "%f", param) == 1) {
if (EL734_errcode != 0)
return False;
EL734_call_depth--;
return True;
}
*param = 0.0;
EL734_SetErrcode(info_ptr, rply_ptr0, "Q");
return False;
}
}
/*
**---------------------------------------------------------------------------
** EL734_GetSpeeds: Get G/J/E register values.
*/
int EL734_GetSpeeds(
/* ===============
*/ void **handle,
int *lo, int *hi, int *ramp)
{
int status;
struct EL734info *info_ptr;
char cmnd0[10];
char cmnd1[10];
char cmnd2[10];
char *rply_ptr;
char *rply_ptr0;
char *rply_ptr1;
char *rply_ptr2;
/*----------------------------------------------
*/
*lo = *hi = *ramp = 0;
info_ptr = (struct EL734info *) *handle;
if (!EL734_AddCallStack(info_ptr, "EL734_GetSpeeds"))
return False;
/*----------------------------------------------
** Send G, J and E cmnds to EL734
*/
sprintf(cmnd0, "g %d\r", info_ptr->motor);
sprintf(cmnd1, "j %d\r", info_ptr->motor);
sprintf(cmnd2, "e %d\r", info_ptr->motor);
status = AsynSrv_SendCmnds(&info_ptr->asyn_info,
&info_ptr->to_host, &info_ptr->from_host,
cmnd0, cmnd1, cmnd2, NULL);
if (!status) {
*lo = *hi = *ramp = 0;
EL734_errcode = EL734__BAD_ASYNSRV;
return False;
} else {
rply_ptr1 = rply_ptr2 = NULL;
rply_ptr0 =
AsynSrv_GetReply(&info_ptr->asyn_info, &info_ptr->from_host, NULL);
if (rply_ptr0 != NULL)
rply_ptr1 =
AsynSrv_GetReply(&info_ptr->asyn_info, &info_ptr->from_host,
rply_ptr0);
if (rply_ptr1 != NULL)
rply_ptr2 =
AsynSrv_GetReply(&info_ptr->asyn_info, &info_ptr->from_host,
rply_ptr1);
if (rply_ptr0 == NULL)
rply_ptr0 = "?no_response";
if (rply_ptr1 == NULL)
rply_ptr1 = "?no_response";
if (rply_ptr2 == NULL)
rply_ptr2 = "?no_response";
if ((sscanf(rply_ptr0, "%d", lo) != 1) ||
(sscanf(rply_ptr1, "%d", hi) != 1) ||
(sscanf(rply_ptr2, "%d", ramp) != 1)) {
if (*rply_ptr0 == '?') {
rply_ptr = rply_ptr0;
} else if (*rply_ptr1 == '?') {
rply_ptr = rply_ptr1;
} else if (*rply_ptr2 == '?') {
rply_ptr = rply_ptr2;
} else {
rply_ptr = "?funny_response";
}
*lo = *hi = *ramp = 0;
EL734_SetErrcode(info_ptr, rply_ptr, "G\", \"J\" or \"E");
return False;
}
}
if (EL734_errcode != 0)
return False;
EL734_call_depth--;
return True;
}
/*
**---------------------------------------------------------------------------
** EL734_GetStatus: Get MSR/SS/U register values.
*/
int EL734_GetStatus(
/* ===============
*/ void **handle,
int *msr,
int *ored_msr,
int *fp_cntr, int *fr_cntr, int *ss, float *ist_posit)
{
int status;
struct EL734info *info_ptr;
char cmnd0[10];
char cmnd1[10];
char cmnd2[10];
char *rply_ptr;
char *rply_ptr0;
char *rply_ptr1;
char *rply_ptr2;
/*----------------------------------------------
*/
*msr = *ored_msr = *fp_cntr = *fr_cntr = *ss = -1;
*ist_posit = 0.0;
info_ptr = (struct EL734info *) *handle;
if (!EL734_AddCallStack(info_ptr, "EL734_GetStatus"))
return False;
/*----------------------------------------------
** Send MSR, SS and U cmnds to EL734
*/
sprintf(cmnd0, "msr %d\r", info_ptr->motor);
sprintf(cmnd1, "ss %d\r", info_ptr->motor);
sprintf(cmnd2, "u %d\r", info_ptr->motor);
status = AsynSrv_SendCmnds(&info_ptr->asyn_info,
&info_ptr->to_host, &info_ptr->from_host,
cmnd0, cmnd1, cmnd2, NULL);
if (!status) {
*msr = *ored_msr = *fp_cntr = *fr_cntr = *ss = -1;
*ist_posit = 0.0;
EL734_errcode = EL734__BAD_ASYNSRV;
return False;
} else {
rply_ptr1 = rply_ptr2 = NULL;
rply_ptr0 =
AsynSrv_GetReply(&info_ptr->asyn_info, &info_ptr->from_host, NULL);
if (rply_ptr0 != NULL)
rply_ptr1 =
AsynSrv_GetReply(&info_ptr->asyn_info, &info_ptr->from_host,
rply_ptr0);
if (rply_ptr1 != NULL)
rply_ptr2 =
AsynSrv_GetReply(&info_ptr->asyn_info, &info_ptr->from_host,
rply_ptr1);
if (rply_ptr0 == NULL)
rply_ptr0 = "?no_response";
if (rply_ptr1 == NULL)
rply_ptr1 = "?no_response";
if (rply_ptr2 == NULL)
rply_ptr2 = "?no_response";
if ((sscanf(rply_ptr0, "%x", msr) == 1) &&
(sscanf(rply_ptr2, "%f", ist_posit) == 1)) {
info_ptr->ored_msr = info_ptr->ored_msr | *msr;
if ((*msr & MSR__POS_FAULT) != 0)
info_ptr->fp_cntr++;
if ((*msr & MSR__RUN_FAULT) != 0)
info_ptr->fr_cntr++;
*ored_msr = info_ptr->ored_msr;
*fp_cntr = info_ptr->fp_cntr;
*fr_cntr = info_ptr->fr_cntr;
/* Remember: we may get "?BSY" for SS and
** this should not be treated as an error!
*/
if (sscanf(rply_ptr1, "%x", ss) != 1)
*ss = -1;
} else {
if (*rply_ptr0 == '?') {
rply_ptr = rply_ptr0;
} else if (*rply_ptr1 == '?') {
rply_ptr = rply_ptr1;
} else if (*rply_ptr2 == '?') {
rply_ptr = rply_ptr2;
} else {
rply_ptr = "?funny_response";
}
*msr = *ored_msr = *fp_cntr = *fr_cntr = *ss = -1;
*ist_posit = 0.0;
EL734_SetErrcode(info_ptr, rply_ptr, "MSR\", \"SS\" or \"U");
return False;
}
}
if (EL734_errcode != 0)
return False;
EL734_call_depth--;
return True;
}
/*
**---------------------------------------------------------------------------
** EL734_GetZeroPoint: Get zero point (= converted V register value)
*/
int EL734_GetZeroPoint(
/* ==================
*/ void **handle,
float *zero_pt)
{
int status, null_pt, nom, denom;
struct EL734info *info_ptr;
char cmnd0[10];
char *rply_ptr0;
/*----------------------------------------------
*/
*zero_pt = 0.0;
info_ptr = (struct EL734info *) *handle;
if (!EL734_AddCallStack(info_ptr, "EL734_GetZeroPoint"))
return False;
/*----------------------------------------------
** Get V register value.
*/
status = EL734_GetNullPoint(handle, &null_pt);
if (!status)
return False;
/*----------------------------------------------
** FD register values.
*/
status = EL734_GetEncGearing(handle, &nom, &denom);
if (!status)
return False;
if (nom == 0) {
EL734_errcode = EL734__BAD_OVFL; /* Encoder gearing ratio is zero */
return False;
}
*zero_pt = ((float) denom) / ((float) nom);
*zero_pt *= (float) null_pt;
if (EL734_errcode != 0)
return False;
EL734_call_depth--;
return True;
}
/*
**---------------------------------------------------------------------------
** EL734_MoveNoWait: Move motor and don't wait for completion.
*/
int EL734_MoveNoWait(
/* ================
*/ void **handle,
float soll_posit)
{
int status;
struct EL734info *info_ptr;
char cmnd0[32];
char *rply_ptr0;
/*----------------------------------------------
*/
info_ptr = (struct EL734info *) *handle;
if (!EL734_AddCallStack(info_ptr, "EL734_MoveNoWait"))
return False;
/*----------------------------------------------
** Send P cmnd to EL734
*/
sprintf(cmnd0, "p %d %.3f\r", info_ptr->motor, soll_posit);
status = AsynSrv_SendCmnds(&info_ptr->asyn_info,
&info_ptr->to_host, &info_ptr->from_host,
cmnd0, NULL);
if (!status) {
EL734_errcode = EL734__BAD_ASYNSRV;
return False;
} else {
rply_ptr0 =
AsynSrv_GetReply(&info_ptr->asyn_info, &info_ptr->from_host, NULL);
if (rply_ptr0 == NULL)
rply_ptr0 = "?no_response";
if (*rply_ptr0 == '\0' || *rply_ptr0 == '\r') {
/*
** The command was accepted - so zero the statistics
** fields in the handle and return to caller.
*/
info_ptr->ored_msr = info_ptr->fp_cntr = info_ptr->fr_cntr = 0;
if (EL734_errcode != 0)
return False;
EL734_call_depth--;
return True;
}
EL734_SetErrcode(info_ptr, rply_ptr0, "P");
return False;
}
}
/*
**---------------------------------------------------------------------------
** EL734_MoveWait: Move motor and wait for completion.
*/
int EL734_MoveWait(
/* ==============
*/ void **handle,
float soll_posit,
int *ored_msr,
int *fp_cntr, int *fr_cntr, float *ist_posit)
{
int status;
struct EL734info *info_ptr;
/*----------------------------------------------
*/
*ored_msr = *fp_cntr = *fr_cntr = -1;
*ist_posit = 0.0;
info_ptr = (struct EL734info *) *handle;
if (!EL734_AddCallStack(info_ptr, "EL734_MoveWait"))
return False;
/*----------------------------------------------
** Start the movement.
*/
status = EL734_MoveNoWait(handle, soll_posit);
if (status) {
status = EL734_WaitIdle(handle, ored_msr, fp_cntr, fr_cntr, ist_posit);
}
if (status && (EL734_errcode == 0))
EL734_call_depth--;
if (EL734_errcode != 0)
return False;
return status;
}
/*
**---------------------------------------------------------------------------
** EL734_Open: Open a connection to a motor.
*/
int EL734_Open(
/* ==========
*/ void **handle,
char *host, int port, int chan, int motor, char *device_id)
{
int my_msr, status;
struct EL734info *my_handle;
char tmo_save[4];
char msr_cmnd[20];
char *rply_ptr;
char *rply_ptr0;
char *rply_ptr1;
char *rply_ptr2;
char *rply_ptr3;
/*--------------------------------------------------------
** Initialise the error info stack and pre-set the
** routine name (in case of error).
*/
EL734_errcode = EL734_errno = EL734_vaxc_errno = 0;
strcpy(EL734_routine[0], "EL734_Open");
EL734_call_depth = 1;
/*--------------------------------------------------------
** Assume trouble
*/
*handle = NULL;
/*--------------------------------------------------------
** Reserve space for the data we need to store.
*/
my_handle = (struct EL734info *) malloc(sizeof(*my_handle));
if (my_handle == NULL) {
EL734_errcode = EL734__BAD_MALLOC; /* malloc failed!! */
return False;
}
memset(my_handle, 0, sizeof(*my_handle));
/*--------------------------------------------------------
** Set up the connection
*/
StrJoin(my_handle->asyn_info.host, sizeof(my_handle->asyn_info.host),
host, "");
my_handle->asyn_info.port = port;
my_handle->asyn_info.chan = chan;
status = AsynSrv_Open(&my_handle->asyn_info);
if (!status) {
EL734_errcode = EL734__BAD_SOCKET;
GetErrno(&EL734_errno, &EL734_vaxc_errno); /* Save errno info */
fprintf(stderr, "\nEL734_Open/AsynSrv_Open: "
"Failed to make connection.\n");
free(my_handle);
return False;
}
memcpy(tmo_save, my_handle->asyn_info.tmo, 4); /* Save time-out */
EL734_Config((void *) &my_handle, "msecTmo", 500, /* 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", "motor", motor, NULL);
my_handle->ored_msr = 0;
my_handle->fp_cntr = 0;
my_handle->fr_cntr = 0;
/*
** Now ensure the EL734 is on-line. The first "RMT 1" command can
** fail due to pending characters in the EL734 input buffer causing
** the "RMT 1" to be corrupted. The response of the EL734 to this
** command is ignored for this reason (but the AsynSrv_SendCmnds
** status must be OK otherwise it indicates a network problem).
*/
status = AsynSrv_SendCmnds(&my_handle->asyn_info,
&my_handle->to_host, &my_handle->from_host,
"rmt 1\r", NULL);
sprintf(msr_cmnd, "msr %d\r", motor);
if (status) {
if (device_id != NULL) {
status = AsynSrv_SendCmnds(&my_handle->asyn_info,
&my_handle->to_host,
&my_handle->from_host, "rmt 1\r",
"echo 0\r", "id\r", msr_cmnd, NULL);
} else {
status = AsynSrv_SendCmnds(&my_handle->asyn_info,
&my_handle->to_host,
&my_handle->from_host, "rmt 1\r",
"echo 0\r", "echo 0\r", msr_cmnd, NULL);
}
}
memcpy(my_handle->asyn_info.tmo, tmo_save, 4); /* Restore time-out */
if (!status) {
/* Some error occurred in AsynSrv_SendCmnds */
EL734_errcode = EL734__BAD_ASYNSRV;
AsynSrv_Close(&my_handle->asyn_info, False);
free(my_handle);
return False;
} else {
/* Check the responses carefully. The 3rd response should
** be the device identifier (if to be checked). The 4th
** response should be a hex integer.
** MK: But first we check for *ES, emergency stop.
** The desired behaviour is that we continue in this
** case and hope for the best.
*/
rply_ptr1 = rply_ptr2 = rply_ptr3 = NULL;
rply_ptr0 =
AsynSrv_GetReply(&my_handle->asyn_info, &my_handle->from_host,
NULL);
if (rply_ptr0 != NULL)
rply_ptr1 =
AsynSrv_GetReply(&my_handle->asyn_info, &my_handle->from_host,
rply_ptr0);
if (rply_ptr1 != NULL)
rply_ptr2 =
AsynSrv_GetReply(&my_handle->asyn_info, &my_handle->from_host,
rply_ptr1);
if (rply_ptr2 != NULL)
rply_ptr3 =
AsynSrv_GetReply(&my_handle->asyn_info, &my_handle->from_host,
rply_ptr2);
if (rply_ptr0 == NULL)
rply_ptr0 = "?no_response";
if (rply_ptr1 == NULL)
rply_ptr1 = "?no_response";
if (rply_ptr2 == NULL)
rply_ptr2 = "?no_response";
if (rply_ptr3 == NULL)
rply_ptr3 = "?no_response";
if (strstr(rply_ptr0, "*ES") != NULL) {
*handle = my_handle;
EL734_call_depth--;
return True;
}
if (*rply_ptr1 == '?')
rply_ptr0 = rply_ptr1;
if (*rply_ptr2 == '?')
rply_ptr0 = rply_ptr2;
if (*rply_ptr3 == '?')
rply_ptr0 = rply_ptr3;
if (*rply_ptr0 != '?') {
if (device_id != NULL) { /* Check device ID? */
if (*rply_ptr2 == '\0') { /* Yes. But if response is blank, it
** may be because Emergency Stop is set.
*/
EL734_SetErrcode(my_handle, rply_ptr2, "ID");
AsynSrv_Close(&my_handle->asyn_info, False);
free(my_handle);
return False;
} else {
if (strncmp(rply_ptr2, device_id, strlen(device_id)) != 0) {
EL734_errcode = EL734__BAD_DEV; /* Device has wrong ID */
AsynSrv_Close(&my_handle->asyn_info, False);
free(my_handle);
return False;
}
}
}
if (sscanf(rply_ptr3, "%x", &my_msr) != 1) {
/* MSR response is bad */
EL734_SetErrcode(my_handle, rply_ptr3, msr_cmnd); /* Check for *ES */
if (EL734_errcode != EL734__EMERG_STOP)
EL734_errcode = EL734__BAD_DEV;
AsynSrv_Close(&my_handle->asyn_info, False);
free(my_handle);
return False;
}
/*
** The connection is complete. Pass the data structure
** back to the caller as a handle.
*/
*handle = my_handle;
if (EL734_errcode != 0)
return False;
EL734_call_depth--;
return True;
} else {
EL734_errcode = EL734__BAD_DEV;
if (strcmp(rply_ptr0, "?OFL") == 0)
EL734_errcode = EL734__BAD_OFL;
if (strcmp(rply_ptr0, "?CMD") == 0)
EL734_errcode = EL734__BAD_CMD;
if (strcmp(rply_ptr0, "?LOC") == 0)
EL734_errcode = EL734__BAD_LOC;
if (strcmp(rply_ptr0, "?ADR") == 0)
EL734_errcode = EL734__BAD_ADR;
if (strcmp(rply_ptr0, "*ES") == 0)
EL734_errcode = EL734__EMERG_STOP;
if (strncmp(rply_ptr0, "?TMO", 4) == 0)
EL734_errcode = EL734__BAD_TMO;
if (EL734_errcode == EL734__BAD_DEV)
fprintf(stderr, " Unrecognised initial response: \"%s\"\n",
rply_ptr0);
}
}
AsynSrv_Close(&my_handle->asyn_info, False);
free(my_handle);
return False;
}
/*
**---------------------------------------------------------------------------
** EL734_PutOffline: put the EL734 off-line
*/
int EL734_PutOffline(
/* ================
*/ void **handle)
{
int status;
struct EL734info *info_ptr;
char *rply_ptr0, *rply_ptr1, *rply_ptr2;
/*----------------------------------------------
*/
info_ptr = (struct EL734info *) *handle;
if (!EL734_AddCallStack(info_ptr, "EL734_PutOffline"))
return False;
/*----------------------------------------------
** The problem which this routine has is that the EL734
** 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,
"\r", "rmt 1\r", "echo 1\r", "rmt 0\r", NULL);
if (!status) {
EL734_errcode = EL734__BAD_ASYNSRV;
return False;
}
status = AsynSrv_SendCmnds(&info_ptr->asyn_info,
&info_ptr->to_host, &info_ptr->from_host,
"RMT\r", "", NULL);
if (!status) {
EL734_errcode = EL734__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_ptr0 = "?no_response";
if (rply_ptr1 == NULL)
rply_ptr1 = "?no_response";
if ((strcmp(rply_ptr0, "RMT") == 0) && (strcmp(rply_ptr1, "\n0") == 0)) {
EL734_call_depth--;
return True;
}
EL734_SetErrcode(info_ptr, rply_ptr0, "RMT");
return False;
}
/*
**---------------------------------------------------------------------------
** EL734_PutOnline: put the EL734 on-line
*/
int EL734_PutOnline(
/* ===============
*/ void **handle,
int echo)
{
int status, my_echo;
struct EL734info *info_ptr;
char cmnd0[10];
char *rply_ptr0;
/*----------------------------------------------
*/
info_ptr = (struct EL734info *) *handle;
if (!EL734_AddCallStack(info_ptr, "EL734_PutOnline"))
return False;
/*----------------------------------------------
*/
if ((echo != 0) && (echo != 1) && (echo != 2)) {
EL734_errcode = EL734__BAD_PAR;
return False;
}
/*----------------------------------------------
** The problem which this routine has is that the state
** of the EL734 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,
"\r", "rmt 1\r", cmnd0, NULL);
if (!status) {
EL734_errcode = EL734__BAD_ASYNSRV;
return False;
}
status = AsynSrv_SendCmnds(&info_ptr->asyn_info,
&info_ptr->to_host, &info_ptr->from_host,
"echo\r", NULL);
if (!status) {
EL734_errcode = EL734__BAD_ASYNSRV;
return False;
}
rply_ptr0 =
AsynSrv_GetReply(&info_ptr->asyn_info, &info_ptr->from_host, NULL);
if (rply_ptr0 == NULL)
rply_ptr0 = "?no_response";
if (strcmp(rply_ptr0, "ECHO") == 0) {
rply_ptr0 =
AsynSrv_GetReply(&info_ptr->asyn_info, &info_ptr->from_host,
rply_ptr0);
if (rply_ptr0 == NULL)
rply_ptr0 = "?no_response";
}
if ((sscanf(rply_ptr0, "%d", &my_echo) == 1) && (my_echo == echo)) {
EL734_call_depth--;
return True;
}
EL734_SetErrcode(info_ptr, rply_ptr0, "ECHO");
return False;
}
/*
**---------------------------------------------------------------------------
** EL734_SendCmnd - Send a command to RS232C server.
*/
int EL734_SendCmnd(
/* ==============
*/ void **handle,
char *cmnd, char *rply, int rply_size)
{
struct EL734info *info_ptr;
int my_status;
char *rply_ptr;
/*----------------------------------------------
*/
info_ptr = (struct EL734info *) *handle;
if (!EL734_AddCallStack(info_ptr, "EL734_SendCmnd"))
return False;
/*----------------------------------------------
** Send command to EL734.
*/
my_status = AsynSrv_SendCmnds(&info_ptr->asyn_info,
&info_ptr->to_host, &info_ptr->from_host,
cmnd, NULL);
if (!my_status) {
EL734_errcode = EL734__BAD_ASYNSRV;
return False;
} else {
rply_ptr =
AsynSrv_GetReply(&info_ptr->asyn_info, &info_ptr->from_host, NULL);
if (rply_ptr == NULL)
rply_ptr = "?no_response";
StrJoin(rply, rply_size, rply_ptr, "");
}
if (EL734_errcode != 0)
return False;
EL734_call_depth--;
return True;
}
/*
**---------------------------------------------------------------------------
** EL734_SetAirCush: Set the air-cushion register (AC register)
*/
int EL734_SetAirCush(
/* ================
*/ void **handle,
int state)
{
int status, dum1, my_state;
struct EL734info *info_ptr;
char cmnd0[32];
char *rply_ptr0;
/*----------------------------------------------
*/
info_ptr = (struct EL734info *) *handle;
if (!EL734_AddCallStack(info_ptr, "EL734_SetAirCush"))
return False;
/*----------------------------------------------
** Send AC cmnd to EL734
*/
if (state != 0)
state = 1;
sprintf(cmnd0, "ac %d %d\r", info_ptr->motor, state);
status = AsynSrv_SendCmnds(&info_ptr->asyn_info,
&info_ptr->to_host, &info_ptr->from_host,
cmnd0, NULL);
if (!status) {
EL734_errcode = EL734__BAD_ASYNSRV;
return False;
} else {
rply_ptr0 =
AsynSrv_GetReply(&info_ptr->asyn_info, &info_ptr->from_host, NULL);
if (rply_ptr0 == NULL)
rply_ptr0 = "?no_response";
if (*rply_ptr0 == '\0') {
/*
** The command was accepted - check value is set OK.
*/
status = EL734_GetAirCush(handle, &dum1, &my_state);
if (!status)
return False;
if (state != my_state) {
EL734_errcode = EL734__VFY_ERR;
return False;
}
EL734_call_depth--;
return True;
}
EL734_SetErrcode(info_ptr, rply_ptr0, "AC");
return False;
}
}
/*
**---------------------------------------------------------------------------
** EL734_SetErrcode - Set up EL734_errcode
*/
int EL734_SetErrcode(
/* ================
*/ struct EL734info *info_ptr,
char *response, char *cmnd)
{
int status;
char *rply;
char tmo_save[4];
char eot_save[4];
EL734_errcode = EL734__BAD_ILLG;
if (strcmp(response, "?OFL") == 0)
EL734_errcode = EL734__BAD_OFL;
if (strcmp(response, "?CMD") == 0)
EL734_errcode = EL734__BAD_CMD;
if (strcmp(response, "?LOC") == 0)
EL734_errcode = EL734__BAD_LOC;
if (strcmp(response, "?ADR") == 0)
EL734_errcode = EL734__BAD_ADR;
if (strcmp(response, "?RNG") == 0)
EL734_errcode = EL734__BAD_RNG;
if (strcmp(response, "*ES") == 0)
EL734_errcode = EL734__EMERG_STOP;
if (strcmp(response, "*MS") == 0)
EL734_errcode = EL734__BAD_STP;
if (strncmp(response, "?TMO", 4) == 0)
EL734_errcode = EL734__BAD_TMO;
if (EL734_errcode != EL734__BAD_ILLG)
return EL734_errcode;
/*
** The response is not recognised. Perhaps the emergency stop
** signal is set. To check this, it is necessary to turn off
** terminator checking since the EL734 prefixes its "*ES"
** response with a <Return> character. We also therefore set
** a very short time-out.
*/
memcpy(tmo_save, info_ptr->asyn_info.tmo, 4); /* Save time-out */
memcpy(eot_save, info_ptr->asyn_info.eot, 4); /* Save terminators */
AsynSrv_Config(&info_ptr->asyn_info, "msecTmo", 100, /* Set short time-out */
"eot", "0", /* Set no terminator */
NULL);
status = AsynSrv_SendCmnds(&info_ptr->asyn_info,
&info_ptr->to_host, &info_ptr->from_host,
"ID\r", NULL);
memcpy(info_ptr->asyn_info.eot, eot_save, 4); /* Restore terminators */
memcpy(info_ptr->asyn_info.tmo, tmo_save, 4); /* Restore time-out */
if (status) {
rply =
AsynSrv_GetReply(&info_ptr->asyn_info, &info_ptr->from_host, NULL);
if (rply == NULL)
rply = "?no_response";
} else {
rply = "?no_response";
}
if (strstr(rply, "*ES") != NULL)
EL734_errcode = EL734__EMERG_STOP;
if ((EL734_errcode == EL734__BAD_ILLG) && (cmnd != NULL)) {
fprintf(stderr, " Unrecognised response to \"%s\" command: \"%s\"\n",
cmnd, response);
strcpy(EL734_IllgText, cmnd);
strcat(EL734_IllgText, " : ");
strcat(EL734_IllgText, response);
}
return EL734_errcode;
}
/*
**---------------------------------------------------------------------------
** EL734_SetHighSpeed: Set the max speed (J register)
*/
int EL734_SetHighSpeed(
/* ==================
*/ void **handle,
int hi)
{
int status, my_lo, my_hi, my_ramp;
struct EL734info *info_ptr;
char cmnd0[32];
char *rply_ptr0;
/*----------------------------------------------
*/
info_ptr = (struct EL734info *) *handle;
if (!EL734_AddCallStack(info_ptr, "EL734_SetHighSpeed"))
return False;
/*----------------------------------------------
** Send J cmnd to EL734
*/
sprintf(cmnd0, "j %d %d\r", info_ptr->motor, hi);
status = AsynSrv_SendCmnds(&info_ptr->asyn_info,
&info_ptr->to_host, &info_ptr->from_host,
cmnd0, NULL);
if (!status) {
EL734_errcode = EL734__BAD_ASYNSRV;
return False;
} else {
rply_ptr0 =
AsynSrv_GetReply(&info_ptr->asyn_info, &info_ptr->from_host, NULL);
if (rply_ptr0 == NULL)
rply_ptr0 = "?no_response";
if (*rply_ptr0 == '\0') {
/*
** The command was accepted - check value is set OK.
*/
status = EL734_GetSpeeds(handle, &my_lo, &my_hi, &my_ramp);
if (!status)
return False;
if (hi != my_hi) {
EL734_errcode = EL734__VFY_ERR;
return False;
}
EL734_call_depth--;
return True;
}
EL734_SetErrcode(info_ptr, rply_ptr0, "J");
return False;
}
}
/*
**---------------------------------------------------------------------------
** EL734_SetLowSpeed: Set the start/stop speed (G register)
*/
int EL734_SetLowSpeed(
/* =================
*/ void **handle,
int lo)
{
int status, my_lo, my_hi, my_ramp;
struct EL734info *info_ptr;
char cmnd0[32];
char *rply_ptr0;
/*----------------------------------------------
*/
info_ptr = (struct EL734info *) *handle;
if (!EL734_AddCallStack(info_ptr, "EL734_SetLowSpeed"))
return False;
/*----------------------------------------------
** Send G cmnd to EL734
*/
sprintf(cmnd0, "g %d %d\r", info_ptr->motor, lo);
status = AsynSrv_SendCmnds(&info_ptr->asyn_info,
&info_ptr->to_host, &info_ptr->from_host,
cmnd0, NULL);
if (!status) {
EL734_errcode = EL734__BAD_ASYNSRV;
return False;
} else {
rply_ptr0 =
AsynSrv_GetReply(&info_ptr->asyn_info, &info_ptr->from_host, NULL);
if (rply_ptr0 == NULL)
rply_ptr0 = "?no_response";
if (*rply_ptr0 == '\0') {
/*
** The command was accepted - check value is set OK.
*/
status = EL734_GetSpeeds(handle, &my_lo, &my_hi, &my_ramp);
if (!status)
return False;
if (lo != my_lo) {
EL734_errcode = EL734__VFY_ERR;
return False;
}
EL734_call_depth--;
return True;
}
EL734_SetErrcode(info_ptr, rply_ptr0, "G");
return False;
}
}
/*
**---------------------------------------------------------------------------
** EL734_SetRamp: Set the start/stop ramp (E register)
*/
int EL734_SetRamp(
/* =============
*/ void **handle,
int ramp)
{
int status, my_lo, my_hi, my_ramp;
struct EL734info *info_ptr;
char cmnd0[32];
char *rply_ptr0;
/*----------------------------------------------
*/
info_ptr = (struct EL734info *) *handle;
if (!EL734_AddCallStack(info_ptr, "EL734_SetRamp"))
return False;
/*----------------------------------------------
** Send E cmnd to EL734
*/
sprintf(cmnd0, "e %d %d\r", info_ptr->motor, ramp);
status = AsynSrv_SendCmnds(&info_ptr->asyn_info,
&info_ptr->to_host, &info_ptr->from_host,
cmnd0, NULL);
if (!status) {
EL734_errcode = EL734__BAD_ASYNSRV;
return False;
} else {
rply_ptr0 =
AsynSrv_GetReply(&info_ptr->asyn_info, &info_ptr->from_host, NULL);
if (rply_ptr0 == NULL)
rply_ptr0 = "?no_response";
if (*rply_ptr0 == '\0') {
/*
** The command was accepted - check value is set OK.
*/
status = EL734_GetSpeeds(handle, &my_lo, &my_hi, &my_ramp);
if (!status)
return False;
if (ramp != my_ramp) {
EL734_errcode = EL734__VFY_ERR;
return False;
}
EL734_call_depth--;
return True;
}
EL734_SetErrcode(info_ptr, rply_ptr0, "E");
return False;
}
}
/*
**---------------------------------------------------------------------------
** EL734_Stop: Send a stop command to motor.
*/
int EL734_Stop(
/* ==========
*/ void **handle)
{
int status;
struct EL734info *info_ptr;
char cmnd0[10];
char *rply_ptr0;
/*----------------------------------------------
*/
info_ptr = (struct EL734info *) *handle;
if (!EL734_AddCallStack(info_ptr, "EL734_Stop"))
return False;
/*----------------------------------------------
** Send S cmnd to EL734
*/
sprintf(cmnd0, "s %d\r", info_ptr->motor);
status = AsynSrv_SendCmnds(&info_ptr->asyn_info,
&info_ptr->to_host, &info_ptr->from_host,
cmnd0, NULL);
if (!status) {
EL734_errcode = EL734__BAD_ASYNSRV;
return False;
} else {
rply_ptr0 =
AsynSrv_GetReply(&info_ptr->asyn_info, &info_ptr->from_host, NULL);
if (rply_ptr0 == NULL)
rply_ptr0 = "?no_response";
if (rply_ptr0[0] == '\0') {
if (EL734_errcode != 0)
return False;
EL734_call_depth--;
return True;
}
EL734_SetErrcode(info_ptr, rply_ptr0, "S");
return False;
}
}
/*
**---------------------------------------------------------------------------
** EL734_WaitIdle: Wait till MSR goes to zero.
*/
int EL734_WaitIdle(
/* ==============
*/ void **handle,
int *ored_msr,
int *fp_cntr, int *fr_cntr, float *ist_posit)
{
#ifdef __VMS
#include <lib$routines.h>
#define hibernate lib$wait (0.25)
#else
#include <unistd.h>
#include <time.h>
struct timespec delay = { 0, 250000000 };
struct timespec delay_left;
#ifdef LINUX
#define hibernate nanosleep(&delay, &delay_left)
#else
#define hibernate nanosleep_d9 (&delay, &delay_left)
#endif
#endif
int msr, ss;
struct EL734info *info_ptr;
/*----------------------------------------------
*/
*ored_msr = *fp_cntr = *fr_cntr = -1;
*ist_posit = 0.0;
info_ptr = (struct EL734info *) *handle;
if (!EL734_AddCallStack(info_ptr, "EL734_WaitIdle"))
return False;
/*----------------------------------------------
** Poll the motor status till not moving.
*/
while (EL734_GetStatus(handle,
&msr, ored_msr, fp_cntr, fr_cntr, &ss,
ist_posit)) {
if ((msr & MSR__BUSY) == 0) {
if (EL734_errcode != 0)
return False;
EL734_call_depth--;
return True;
}
hibernate;
}
return False; /* Error detected in EL734_GetStatus */
}
/*
**---------------------------------------------------------------------------
** EL734_ZeroStatus: Zero the "ored-MSR" and fault counters.
*/
void EL734_ZeroStatus(
/* ================
*/ void **handle)
{
struct EL734info *info_ptr;
/*
** Do nothing if no handle!
*/
info_ptr = (struct EL734info *) *handle;
if (info_ptr == NULL)
return;
/*
** Zero the data structure items.
*/
info_ptr->ored_msr = 0;
info_ptr->fp_cntr = 0;
info_ptr->fr_cntr = 0;
memset(info_ptr->from_host.msg_size,
'0', sizeof(info_ptr->from_host.msg_size));
return;
}
/*-------------------------------------------- End of EL734_Utility.C =======*/