744 lines
19 KiB
C
744 lines
19 KiB
C
/*-----------------------------------------------------------------------
|
|
This is another driver for the EL737 counter box used at SINQ. The hp in
|
|
the name is for high performance, though this only a promise and not yet
|
|
proven. This version connects directly to the RS232 port of the counter
|
|
box on the terminal server rather then working with David Maden's
|
|
SerPortServer program. Other tweaks will be implemented as well, such as
|
|
reading the monitors only now and then and not on all calls.
|
|
|
|
Mark Koennecke, July 2003
|
|
|
|
This is a special version for MORPHEUS which checks the SPS when in
|
|
No Beam state. Because NoBeam can be caused by the shutter being closed
|
|
in order to prevent overloading the 2D detector.
|
|
|
|
Mark Koennecke, March 2007
|
|
-------------------------------------------------------------------------*/
|
|
#include <stdlib.h>
|
|
#include <assert.h>
|
|
#include <math.h>
|
|
#include <time.h>
|
|
#include <fortify.h>
|
|
#include <string.h>
|
|
#include <sics.h>
|
|
#include <rs232controller.h>
|
|
#include <countdriv.h>
|
|
#include <splitter.h>
|
|
#include "sps.h"
|
|
|
|
#define MONTHRESH 20
|
|
|
|
#define STATSEND 0
|
|
#define STATRECEIVE 2
|
|
#define BADTRANGE -117766
|
|
/*-----------------------------------------------------------------------
|
|
our own data struture
|
|
------------------------------------------------------------------------*/
|
|
typedef struct {
|
|
prs232 controller;
|
|
int monitorCount; /* read monitors if this is above MONTHRESH */
|
|
float cachedControl;
|
|
int errorCode;
|
|
int finishCount; /* need RS = 0 2 times before really sure finished */
|
|
int statusMode;
|
|
time_t startRequest;
|
|
int lastStatus; /* need to remember last status, otherwise I get oscillating
|
|
NoBeam and Counting status if the beam goes off
|
|
*/
|
|
char *badReply;
|
|
int readErrorCount; /* need to remember failed reads: on RDOE, upper level
|
|
code will see busy's and thus not catch the case of
|
|
multiple failures
|
|
*/
|
|
pSPS sps;
|
|
} EL737hpsps, *pEL737hpsps;
|
|
/*--------------------- ERROR CODES -------------------------------------*/
|
|
#define OFFLINE -1
|
|
#define BADRANGE -3
|
|
#define BADCOMMAND -4
|
|
#define BADPARAM -5
|
|
#define NOPARAM -7
|
|
#define TOMANYCOUNTS -8
|
|
#define SYSERROR -9
|
|
#define BADREPLY -10
|
|
#define SELECTFAIL -11
|
|
#define TIMEOUT737 -12
|
|
#define TOMANYREADERRORS -23
|
|
#define DETOVERLOAD -24
|
|
/*---------------------------------------------------------------------*/
|
|
static void setBadReply(pEL737hpsps self, char *reply)
|
|
{
|
|
if (self->badReply != NULL) {
|
|
free(self->badReply);
|
|
}
|
|
self->badReply = strdup(reply);
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------
|
|
search errors in a reply from the EL737. Returns 1 on success or a
|
|
negative error code in case of trouble.
|
|
------------------------------------------------------------------------*/
|
|
static int checkEL737Error(char *pReply)
|
|
{
|
|
|
|
/*
|
|
all error start with a ?, if no ? in reply, answer is OK!
|
|
*/
|
|
if (strstr(pReply, "?") == NULL) {
|
|
return 1;
|
|
}
|
|
|
|
/*
|
|
Now there is an error and we have to identify it
|
|
*/
|
|
if (strstr(pReply, "?OF") != NULL) {
|
|
return OFFLINE;
|
|
} else if (strstr(pReply, "?OV") != NULL) {
|
|
return OVERFLOW;
|
|
} else if (strstr(pReply, "?1") != NULL) {
|
|
return BADRANGE;
|
|
} else if (strstr(pReply, "?2") != NULL) {
|
|
return BADCOMMAND;
|
|
} else if (strstr(pReply, "?3") != NULL) {
|
|
return BADPARAM;
|
|
} else if (strstr(pReply, "?4") != NULL) {
|
|
return BADCOUNTER;
|
|
} else if (strstr(pReply, "?5") != NULL) {
|
|
return NOPARAM;
|
|
} else if (strstr(pReply, "?6") != NULL) {
|
|
return TOMANYCOUNTS;
|
|
} else {
|
|
return SYSERROR;
|
|
}
|
|
}
|
|
|
|
/*---------------------------------------------------------------
|
|
fixMode checks if we are in STATRECEIVE mode, reads any pending
|
|
data and sets the mode to STATSEND. This would fix the problem
|
|
if another client wishes to give a command while we are expecting
|
|
a status response
|
|
---------------------------------------------------------------*/
|
|
static void fixMode(pEL737hpsps pPriv)
|
|
{
|
|
char pBuffer[256];
|
|
int len = 255;
|
|
|
|
if (pPriv->statusMode == STATRECEIVE) {
|
|
readRS232TillTerm(pPriv->controller, pBuffer, &len);
|
|
pPriv->statusMode = STATSEND;
|
|
}
|
|
}
|
|
|
|
/*---------------------------------------------------------------*/
|
|
static int EL737SCommand(pEL737hpsps pPriv, char *pCommand,
|
|
char *pReply, int replylen)
|
|
{
|
|
int status;
|
|
|
|
status = transactRS232(pPriv->controller, pCommand, strlen(pCommand),
|
|
pReply, replylen);
|
|
if (status < 0) {
|
|
pPriv->errorCode = status;
|
|
return 0;
|
|
}
|
|
status = checkEL737Error(pReply);
|
|
if (status < 0) {
|
|
pPriv->errorCode = status;
|
|
return 0;
|
|
}
|
|
return 1;
|
|
}
|
|
|
|
/*----------------------------------------------------------------*/
|
|
static int readRS(pEL737hpsps pPriv, int *RS)
|
|
{
|
|
int status, len = 131;
|
|
char reply[132];
|
|
|
|
status = readRS232TillTerm(pPriv->controller, reply, &len);
|
|
if (status < 0) {
|
|
pPriv->readErrorCount++;
|
|
pPriv->errorCode = status;
|
|
return 0;
|
|
}
|
|
status = checkEL737Error(reply);
|
|
if (status < 0) {
|
|
pPriv->readErrorCount++;
|
|
pPriv->errorCode = status;
|
|
return 0;
|
|
}
|
|
status = sscanf(reply, "%d", RS);
|
|
if (status < 1) {
|
|
pPriv->readErrorCount++;
|
|
pPriv->errorCode = BADREPLY;
|
|
setBadReply(pPriv, reply);
|
|
return 0;
|
|
}
|
|
pPriv->readErrorCount = 0;
|
|
return 1;
|
|
}
|
|
|
|
/*-----------------------------------------------------------------*/
|
|
static int decodeRS(pEL737hpsps pPriv, int RS)
|
|
{
|
|
int returnValue;
|
|
|
|
switch (RS) {
|
|
case 0:
|
|
pPriv->finishCount++;
|
|
if (pPriv->finishCount > 2) {
|
|
returnValue = HWIdle;
|
|
} else {
|
|
returnValue = HWBusy;
|
|
}
|
|
break;
|
|
case 1:
|
|
case 2:
|
|
pPriv->finishCount = 0;
|
|
returnValue = HWBusy;
|
|
break;
|
|
case 5:
|
|
case 6:
|
|
pPriv->finishCount = 0;
|
|
returnValue = HWNoBeam;
|
|
break;
|
|
default:
|
|
pPriv->finishCount = 0;
|
|
returnValue = HWPause;
|
|
break;
|
|
}
|
|
return returnValue;
|
|
}
|
|
|
|
/*-----------------------------------------------------------------*/
|
|
static int updateMonitors(struct __COUNTER *self)
|
|
{
|
|
int status;
|
|
int m1, m2, m3, m4, m5, m6, m7, m8;
|
|
float fTime;
|
|
pEL737hpsps pPriv = NULL;
|
|
char reply[132];
|
|
|
|
pPriv = (pEL737hpsps) self->pData;
|
|
|
|
if (!EL737SCommand(pPriv, "RA\r", reply, 131)) {
|
|
return 0;
|
|
}
|
|
|
|
/*
|
|
There are two forms of RA replys: new form with 8 monitors
|
|
*/
|
|
status = sscanf(reply, "%f %d %d %d %d %d %d %d %d",
|
|
&fTime, &m1, &m2, &m3, &m4, &m5, &m6, &m7, &m8);
|
|
if (status != 9) {
|
|
/*
|
|
old form with 4 monitors
|
|
*/
|
|
status = sscanf(reply, "%d %d %d %d %f", &m1, &m2, &m3, &m4, &fTime);
|
|
if (status != 5) {
|
|
pPriv->errorCode = BADREPLY;
|
|
setBadReply(pPriv, reply);
|
|
printf("Bad reply to EL737 RA command: %s\n", reply);
|
|
return 0;
|
|
}
|
|
}
|
|
self->lCounts[0] = m2;
|
|
self->lCounts[1] = m1;
|
|
self->lCounts[2] = m3;
|
|
self->lCounts[3] = m4;
|
|
self->lCounts[4] = m5;
|
|
self->lCounts[5] = m6;
|
|
self->lCounts[6] = m7;
|
|
self->lCounts[7] = m8;
|
|
self->fTime = fTime;
|
|
|
|
if (self->eMode == eTimer) {
|
|
pPriv->cachedControl = fTime;
|
|
} else {
|
|
pPriv->cachedControl = m1;
|
|
}
|
|
return 1;
|
|
}
|
|
|
|
/*------------------------------------------------------------------*/
|
|
static int EL737SStatus(struct __COUNTER *self, float *fControl)
|
|
{
|
|
int status, RS, returnValue;
|
|
pEL737hpsps pPriv = NULL;
|
|
int iBit = 0;
|
|
|
|
assert(self);
|
|
pPriv = (pEL737hpsps) self->pData;
|
|
|
|
/*
|
|
handle STATSEND mode
|
|
*/
|
|
if (pPriv->statusMode == STATSEND) {
|
|
status = writeRS232(pPriv->controller, "RS\r", 3);
|
|
if (status < 0) {
|
|
pPriv->errorCode = status;
|
|
return HWFault;
|
|
}
|
|
pPriv->statusMode = STATRECEIVE;
|
|
pPriv->startRequest = time(NULL);
|
|
*fControl = pPriv->cachedControl;
|
|
return pPriv->lastStatus;
|
|
}
|
|
|
|
/*
|
|
now we are dealing with STATRECEIVE mode.
|
|
Check for timeout first.
|
|
*/
|
|
if (time(NULL) > pPriv->startRequest + 10) {
|
|
pPriv->statusMode = STATSEND;
|
|
pPriv->errorCode = TIMEOUT737;
|
|
pPriv->readErrorCount++;
|
|
return HWFault;
|
|
}
|
|
|
|
/*
|
|
check availability of data
|
|
*/
|
|
status = availableNetRS232(pPriv->controller);
|
|
if (status == 0) {
|
|
*fControl = pPriv->cachedControl;
|
|
return pPriv->lastStatus;
|
|
} else if (status < 0) {
|
|
*fControl = pPriv->cachedControl;
|
|
pPriv->statusMode = STATSEND;
|
|
pPriv->errorCode = SELECTFAIL;
|
|
return HWFault;
|
|
}
|
|
|
|
/*
|
|
The snail in the counter box has replied. Read and process
|
|
the data
|
|
*/
|
|
pPriv->statusMode = STATSEND;
|
|
if (!readRS(pPriv, &RS)) {
|
|
return HWFault;
|
|
}
|
|
|
|
/*
|
|
decode it
|
|
*/
|
|
returnValue = decodeRS(pPriv, RS);
|
|
pPriv->lastStatus = returnValue;
|
|
|
|
/*
|
|
check for excessive failed reads
|
|
*/
|
|
if (pPriv->readErrorCount > 3) {
|
|
pPriv->errorCode = TOMANYREADERRORS;
|
|
return HWFault;
|
|
}
|
|
|
|
/*
|
|
check if we update the monitors and do it
|
|
*/
|
|
pPriv->monitorCount++;
|
|
if (pPriv->monitorCount > MONTHRESH) {
|
|
status = updateMonitors(self);
|
|
pPriv->monitorCount = 0;
|
|
if (!status) {
|
|
return HWFault;
|
|
}
|
|
}
|
|
|
|
*fControl = pPriv->cachedControl;
|
|
|
|
if (returnValue == HWNoBeam) {
|
|
/* ToDo: put in proper bit address when properly known */
|
|
SPSGetStatus(pPriv->sps, 79, &iBit);
|
|
if (iBit == 1) {
|
|
pPriv->errorCode = DETOVERLOAD;
|
|
return HWFault;
|
|
}
|
|
}
|
|
|
|
return returnValue;
|
|
}
|
|
|
|
/*-------------------------------------------------------------------*/
|
|
static int EL737SStart(struct __COUNTER *self)
|
|
{
|
|
pEL737hpsps pPriv = NULL;
|
|
int status;
|
|
char pCommand[50], pReply[30];
|
|
|
|
assert(self);
|
|
pPriv = (pEL737hpsps) self->pData;
|
|
|
|
fixMode(pPriv);
|
|
pPriv->readErrorCount = 0;
|
|
if (self->eMode == ePreset) {
|
|
snprintf(pCommand, 49, "MP %d\r", (int) self->fPreset);
|
|
} else {
|
|
if (self->fPreset < .1 || self->fPreset > 200000) {
|
|
self->iErrorCode = BADTRANGE;
|
|
return HWFault;
|
|
}
|
|
snprintf(pCommand, 49, "TP %.2f\r", self->fPreset);
|
|
}
|
|
if (EL737SCommand(pPriv, pCommand, pReply, 29) != 1) {
|
|
return 0;
|
|
}
|
|
pPriv->finishCount = 0;
|
|
pPriv->lastStatus = HWBusy;
|
|
return 1;
|
|
}
|
|
|
|
/* --------------------------------------------------------------------*/
|
|
static int EL737SPause(struct __COUNTER *self)
|
|
{
|
|
pEL737hpsps pPriv = NULL;
|
|
int status;
|
|
char pCommand[50], pReply[30];
|
|
|
|
assert(self);
|
|
pPriv = (pEL737hpsps) self->pData;
|
|
|
|
fixMode(pPriv);
|
|
pPriv->lastStatus = HWPause;
|
|
return EL737SCommand(pPriv, "PS\r", pReply, 29);
|
|
}
|
|
|
|
/*----------------------------------------------------------------------*/
|
|
static int EL737SContinue(struct __COUNTER *self)
|
|
{
|
|
pEL737hpsps pPriv = NULL;
|
|
int status;
|
|
char pCommand[50], pReply[30];
|
|
|
|
assert(self);
|
|
pPriv = (pEL737hpsps) self->pData;
|
|
|
|
fixMode(pPriv);
|
|
pPriv->lastStatus = HWBusy;
|
|
return EL737SCommand(pPriv, "CO\r", pReply, 29);
|
|
}
|
|
|
|
/*---------------------------------------------------------------------*/
|
|
static int EL737SHalt(struct __COUNTER *self)
|
|
{
|
|
pEL737hpsps pPriv = NULL;
|
|
int status;
|
|
char pCommand[50], pReply[30];
|
|
|
|
assert(self);
|
|
pPriv = (pEL737hpsps) self->pData;
|
|
|
|
fixMode(pPriv);
|
|
pPriv->lastStatus = HWBusy;
|
|
return EL737SCommand(pPriv, "S\r", pReply, 29);
|
|
}
|
|
|
|
/*-------------------------------------------------------------------*/
|
|
static int EL737STransfer(struct __COUNTER *self)
|
|
{
|
|
pEL737hpsps pPriv = NULL;
|
|
assert(self);
|
|
pPriv = (pEL737hpsps) self->pData;
|
|
|
|
fixMode(pPriv);
|
|
return updateMonitors(self);
|
|
}
|
|
|
|
/*--------------------------------------------------------------------*/
|
|
static int EL737SGetError(struct __COUNTER *self, int *iCode,
|
|
char *pError, int errLen)
|
|
{
|
|
pEL737hpsps pPriv = NULL;
|
|
assert(self);
|
|
pPriv = (pEL737hpsps) self->pData;
|
|
|
|
*iCode = pPriv->errorCode;
|
|
switch (pPriv->errorCode) {
|
|
case OFFLINE:
|
|
strlcpy(pError, "EL737 is offline", errLen);
|
|
break;
|
|
case OVERFLOW:
|
|
strlcpy(pError, "EL737 reported overflow, communication problem",
|
|
errLen);
|
|
break;
|
|
case BADRANGE:
|
|
strlcpy(pError, "EL737 parameter is out of range", errLen);
|
|
break;
|
|
case BADTRANGE:
|
|
strlcpy(pError, "preset timer out of range", errLen);
|
|
break;
|
|
case BADCOMMAND:
|
|
strlcpy(pError, "EL737 received unknown command or is busy", errLen);
|
|
break;
|
|
case BADPARAM:
|
|
strlcpy(pError, "EL737 parameter is awful", errLen);
|
|
break;
|
|
case NOPARAM:
|
|
strlcpy(pError, "EL737 parameter missing", errLen);
|
|
break;
|
|
case TOMANYCOUNTS:
|
|
strlcpy(pError, "EL737 counters overflowed", errLen);
|
|
break;
|
|
case SYSERROR:
|
|
strlcpy(pError, "EL737 has an internal system error", errLen);
|
|
break;
|
|
case BADREPLY:
|
|
snprintf(pError, errLen, "EL737 sent an unexpected reply: %s",
|
|
pPriv->badReply);
|
|
break;
|
|
case SELECTFAIL:
|
|
strlcpy(pError, "select system call failed, network trouble", errLen);
|
|
break;
|
|
case TIMEOUT737:
|
|
strlcpy(pError,
|
|
"timeout or network problem while waiting for status repsonse",
|
|
errLen);
|
|
break;
|
|
case TOMANYREADERRORS:
|
|
strlcpy(pError, "Failed more then three times to read counter box",
|
|
errLen);
|
|
break;
|
|
case DETOVERLOAD:
|
|
strlcpy(pError, "Shutter closed due to detector overload", errLen);
|
|
break;
|
|
default:
|
|
getRS232Error(pPriv->errorCode, pError, errLen);
|
|
}
|
|
return 1;
|
|
}
|
|
|
|
/*--------------------------------------------------------------------*/
|
|
static int EL737SFixIt(struct __COUNTER *self, int iCode)
|
|
{
|
|
pEL737hpsps pPriv = NULL;
|
|
int status;
|
|
char pReply[50];
|
|
char buffer[256];
|
|
int dataLen = 255;
|
|
int i;
|
|
|
|
assert(self);
|
|
pPriv = (pEL737hpsps) self->pData;
|
|
|
|
switch (iCode) {
|
|
case BADPARAM:
|
|
case NOPARAM:
|
|
case BADRANGE:
|
|
case BADTRANGE:
|
|
case OVERFLOW:
|
|
return COREDO;
|
|
break;
|
|
case BADREPLY:
|
|
case TIMEOUT737:
|
|
case TIMEOUT:
|
|
for (i = 0; i < 3; i++) {
|
|
status = readRS232TillTerm(pPriv->controller, buffer, &dataLen);
|
|
if (status == 1) {
|
|
return COREDO;
|
|
}
|
|
}
|
|
/*
|
|
If nothing can be read, the only fixable cause is a network breakdown
|
|
Try to fix this. If this does not work: give up
|
|
*/
|
|
closeRS232(pPriv->controller);
|
|
SicsWait(60);
|
|
status = initRS232(pPriv->controller);
|
|
if (status != 1) {
|
|
return COTERM;
|
|
} else {
|
|
return COREDO;
|
|
}
|
|
break;
|
|
case OFFLINE:
|
|
EL737SCommand(pPriv, "RMT 1\r", pReply, 49);
|
|
EL737SCommand(pPriv, "echo 2\r", pReply, 49);
|
|
return COREDO;
|
|
break;
|
|
case BADCOMMAND: /* can be busy, stop it and try again */
|
|
EL737SCommand(pPriv, "S\r", pReply, 49);
|
|
return COREDO;
|
|
break;
|
|
case TOMANYCOUNTS:
|
|
case SYSERROR:
|
|
case DETOVERLOAD:
|
|
return COTERM;
|
|
break;
|
|
default:
|
|
/*
|
|
network problem; try to reopen
|
|
*/
|
|
closeRS232(pPriv->controller);
|
|
SicsWait(60);
|
|
status = initRS232(pPriv->controller);
|
|
if (status != 1) {
|
|
return COTERM;
|
|
} else {
|
|
return COREDO;
|
|
}
|
|
}
|
|
}
|
|
|
|
/*------------------------------------------------------------------------*/
|
|
static int EL737SSet(struct __COUNTER *self, char *name, int iCter,
|
|
float fVal)
|
|
{
|
|
pEL737hpsps pPriv = NULL;
|
|
int status;
|
|
char pCommand[80], pReply[50];
|
|
|
|
assert(self);
|
|
pPriv = (pEL737hpsps) self->pData;
|
|
|
|
fixMode(pPriv);
|
|
if (strcmp(name, "threshold") == 0) {
|
|
sprintf(pCommand, "DL %1.1d %f\r", iCter, fVal);
|
|
if (!EL737SCommand(pPriv, pCommand, pReply, 49)) {
|
|
return 0;
|
|
}
|
|
sprintf(pCommand, "DR %1.1d\r", iCter);
|
|
if (!EL737SCommand(pPriv, pCommand, pReply, 49)) {
|
|
return 0;
|
|
}
|
|
return 1;
|
|
} else {
|
|
self->iErrorCode = UNKNOWNPAR;
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
/*----------------------------------------------------------------------*/
|
|
static int EL737SGet(struct __COUNTER *self, char *name, int iCter,
|
|
float *fVal)
|
|
{
|
|
pEL737hpsps pPriv = NULL;
|
|
int status;
|
|
char pCommand[80], pReply[50];
|
|
|
|
assert(self);
|
|
pPriv = (pEL737hpsps) self->pData;
|
|
|
|
fixMode(pPriv);
|
|
if (strcmp(name, "threshold") == 0) {
|
|
sprintf(pCommand, "DL %1.1d\r", iCter);
|
|
if (!EL737SCommand(pPriv, pCommand, pReply, 49)) {
|
|
return 0;
|
|
}
|
|
sscanf(pReply, "%f", fVal);
|
|
return 1;
|
|
} else {
|
|
self->iErrorCode = UNKNOWNPAR;
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
/*--------------------------------------------------------------------*/
|
|
static int EL737SSend(struct __COUNTER *self, char *pText, char *pReply,
|
|
int iReplyLen)
|
|
{
|
|
pEL737hpsps pPriv = NULL;
|
|
|
|
assert(self);
|
|
pPriv = (pEL737hpsps) self->pData;
|
|
|
|
fixMode(pPriv);
|
|
return EL737SCommand(pPriv, pText, pReply, iReplyLen);
|
|
}
|
|
|
|
/*---------------------------------------------------------------------*/
|
|
static void KillHP(pCounterDriver self)
|
|
{
|
|
pEL737hpsps pPriv = NULL;
|
|
|
|
assert(self);
|
|
pPriv = (pEL737hpsps) self->pData;
|
|
|
|
if (!pPriv) {
|
|
return;
|
|
}
|
|
if (pPriv->controller != NULL) {
|
|
KillRS232(pPriv->controller);
|
|
}
|
|
if (pPriv->badReply != NULL) {
|
|
free(pPriv->badReply);
|
|
}
|
|
free(pPriv);
|
|
}
|
|
|
|
/*-------------------------------------------------------------------*/
|
|
pCounterDriver MakeEL737hpsps(SConnection * pCon, char *name,
|
|
int argc, char *argv[])
|
|
{
|
|
pCounterDriver pNew = NULL;
|
|
pEL737hpsps pPriv = NULL;
|
|
char pHost[132];
|
|
int port, status;
|
|
|
|
/*
|
|
check arguments
|
|
*/
|
|
if (argc < 3) {
|
|
SCWrite(pCon,
|
|
"ERROR: insufficient no af arguments to create EL737HPSPS",
|
|
eError);
|
|
return NULL;
|
|
}
|
|
if (!isNumeric(argv[1])) {
|
|
SCWrite(pCon, "ERROR: expected numeric argument for port number",
|
|
eError);
|
|
return NULL;
|
|
}
|
|
port = atoi(argv[1]);
|
|
strlcpy(pHost, argv[0], 131);
|
|
|
|
/*
|
|
allocate a bank worth of memory ...........
|
|
*/
|
|
pNew = CreateCounterDriver(name, "EL737HPSPS");
|
|
pPriv = (pEL737hpsps) malloc(sizeof(EL737hpsps));
|
|
if (!pNew || !pPriv) {
|
|
return NULL;
|
|
}
|
|
memset(pPriv, 0, sizeof(EL737hpsps));
|
|
pPriv->controller = createRS232(pHost, port);
|
|
if (!pPriv->controller) {
|
|
DeleteCounterDriver(pNew);
|
|
return NULL;
|
|
}
|
|
pPriv->sps = (pSPS) FindCommandData(pServ->pSics, argv[2], "SPS");
|
|
if (pPriv->sps == NULL) {
|
|
SCWrite(pCon, "ERROR: SPS not found", eError);
|
|
DeleteCounterDriver(pNew);
|
|
return NULL;
|
|
}
|
|
|
|
/* assign functions */
|
|
pNew->GetStatus = EL737SStatus;
|
|
pNew->Start = EL737SStart;
|
|
pNew->Halt = EL737SHalt;
|
|
pNew->ReadValues = EL737STransfer;
|
|
pNew->GetError = EL737SGetError;
|
|
pNew->TryAndFixIt = EL737SFixIt;
|
|
pNew->Pause = EL737SPause;
|
|
pNew->Continue = EL737SContinue;
|
|
pNew->Set = EL737SSet;
|
|
pNew->Get = EL737SGet;
|
|
pNew->Send = EL737SSend;
|
|
pNew->KillPrivate = KillHP;
|
|
pNew->iNoOfMonitors = 7;
|
|
pNew->fTime = 0.;
|
|
pNew->pData = pPriv;
|
|
|
|
/*
|
|
initialize connection
|
|
*/
|
|
setRS232Debug(pPriv->controller, 0);
|
|
setRS232ReplyTerminator(pPriv->controller, "\r");
|
|
status = initRS232(pPriv->controller);
|
|
status = EL737SCommand(pPriv, "RMT 1\r", pHost, 131);
|
|
status = EL737SCommand(pPriv, "RMT 1\r", pHost, 131);
|
|
status = EL737SCommand(pPriv, "ECHO 2\r", pHost, 131);
|
|
|
|
return pNew;
|
|
}
|