Files
sicspsi/el737driv.c
koennecke eb72d5c486 - Adapted indenation to new agreed upon system
- Fixed bad status in poldi zug driver
2009-02-13 09:01:03 +00:00

652 lines
16 KiB
C

/*----------------------------------------------------------------------
This is driver for a standard PSI EL737 counter box as used at
SINQ
copyright: see file COPYRIGHT
extracted from countdriv.c. Mark Koennecke, June 2003
-----------------------------------------------------------------------*/
#include <stdlib.h>
#include <assert.h>
#include <math.h>
#include <fortify.h>
#include <string.h>
#include <sics.h>
#include <countdriv.h>
#include <splitter.h>
#include "hardsup/sinq_prototypes.h"
#include "hardsup/el737_def.h"
#include "hardsup/el737fix.h"
#define BADTRANGE -117766
/*----------------------------- EL737 ------------------------------------*/
typedef struct {
char *host;
int iPort;
int iChannel;
void *pData;
int finishCount;
} EL737st;
/*------------------------------------------------------------------------*/
static int EL737GetStatus(struct __COUNTER *self, float *fControl)
{
int iRet;
int iC1, iC2, iC3, iC4, iRS;
float fTime;
EL737st *pEL737;
assert(self);
pEL737 = (EL737st *) self->pData;
assert(pEL737);
iRet =
EL737_GetStatus(&pEL737->pData, &iC1, &iC2, &iC3, &iC4, &fTime,
&iRS);
if (self->eMode == eTimer) {
*fControl = fTime;
} else {
*fControl = iC1;
}
/* store time */
self->fTime = fTime;
if (iRet != 1) {
return HWFault;
}
self->lCounts[0] = iC2;
self->lCounts[1] = iC1;
self->lCounts[2] = iC3;
self->lCounts[3] = iC4;
/* get extra counters for 8-fold counter boxes */
iRet = EL737_GetStatusExtra(&pEL737->pData, &iC1, &iC2, &iC3, &iC4);
self->lCounts[4] = iC1;
self->lCounts[5] = iC2;
self->lCounts[6] = iC3;
self->lCounts[7] = iC4;
if (iRS == 0) {
pEL737->finishCount++;
if (pEL737->finishCount >= 2) {
return HWIdle;
} else {
return HWBusy;
}
} else if ((iRS == 1) || (iRS == 2)) {
pEL737->finishCount = 0;
return HWBusy;
} else if ((iRS == 5) || (iRS == 6)) {
pEL737->finishCount = 0;
return HWNoBeam;
} else {
pEL737->finishCount = 0;
return HWPause;
}
}
#ifdef NONINTF
extern float nintf(float f);
#endif
/*-------------------------------------------------------------------------*/
static int EL737Start(struct __COUNTER *self)
{
int iRet, iRS;
EL737st *pEL737;
assert(self);
pEL737 = (EL737st *) self->pData;
assert(pEL737);
self->fTime = 0.;
if (self->eMode == ePreset) {
iRet =
EL737_StartCnt(&pEL737->pData, (int) nintf(self->fPreset), &iRS);
if (iRet == 1) {
pEL737->finishCount = 0;
return OKOK;
} else {
return HWFault;
}
} else if (self->eMode == eTimer) {
if (self->fPreset < .1 || self->fPreset > 200000) {
self->iErrorCode = BADTRANGE;
return HWFault;
}
iRet = EL737_StartTime(&pEL737->pData, self->fPreset, &iRS);
if (iRet == 1) {
pEL737->finishCount = 0;
return OKOK;
} else {
return HWFault;
}
}
return 0;
}
/*-------------------------------------------------------------------------*/
static int EL737Pause(struct __COUNTER *self)
{
int iRet, iRS;
EL737st *pEL737;
assert(self);
pEL737 = (EL737st *) self->pData;
assert(pEL737);
iRet = EL737_Pause(&pEL737->pData, &iRS);
if (iRet == 1) {
return OKOK;
} else {
return HWFault;
}
return 0;
}
/*-------------------------------------------------------------------------*/
static int EL737Continue(struct __COUNTER *self)
{
int iRet, iRS;
EL737st *pEL737;
assert(self);
pEL737 = (EL737st *) self->pData;
assert(pEL737);
iRet = EL737_Continue(&pEL737->pData, &iRS);
if (iRet == 1) {
return OKOK;
} else {
return HWFault;
}
return 0;
}
/*--------------------------------------------------------------------------*/
static int EL737Halt(struct __COUNTER *self)
{
int iRet, iC1, iC2, iC3, iC4, iRS;
float fPreset;
EL737st *pEL737;
assert(self);
pEL737 = (EL737st *) self->pData;
assert(pEL737);
iRet =
EL737_Stop(&pEL737->pData, &iC1, &iC2, &iC3, &iC4, &fPreset, &iRS);
if (iRet == 1) {
self->lCounts[0] = iC2;
self->lCounts[1] = iC1;
self->lCounts[2] = iC3;
self->lCounts[3] = iC4;
return OKOK;
}
return HWFault;
}
/*--------------------------------------------------------------------------*/
static int EL737ReadValues(struct __COUNTER *self)
{
int iRet;
int iC1, iC2, iC3, iC4, iRS;
float fTime;
EL737st *pEL737;
assert(self);
pEL737 = (EL737st *) self->pData;
assert(pEL737);
iRet =
EL737_GetStatus(&pEL737->pData, &iC1, &iC2, &iC3, &iC4, &fTime,
&iRS);
if (iRet != 1) {
return HWFault;
}
self->fTime = fTime;
self->lCounts[0] = iC2;
self->lCounts[1] = iC1;
self->lCounts[2] = iC3;
self->lCounts[3] = iC4;
/* get extra counters for 8-fold counter boxes */
iRet = EL737_GetStatusExtra(&pEL737->pData, &iC1, &iC2, &iC3, &iC4);
self->lCounts[4] = iC1;
self->lCounts[5] = iC2;
self->lCounts[6] = iC3;
self->lCounts[7] = iC4;
return OKOK;
}
/*---------------------------------------------------------------------------
EL737Error2Text converts between an EL734 error code to text
-----------------------------------------------------------------------------*/
static void EL737Error2Text(char *pBuffer, int iErr)
{
switch (iErr) {
case EL737__BAD_ADR:
strcpy(pBuffer, "EL737__BAD_ADR");
break;
case EL737__BAD_OVFL:
strcpy(pBuffer, "EL737__BAD_OVFL");
break;
case EL737__BAD_BSY:
strcpy(pBuffer, "EL737__BAD_BSY");
break;
case EL737__BAD_SNTX:
strcpy(pBuffer, "EL737__BAD_SNTX");
break;
case EL737__BAD_CONNECT:
strcpy(pBuffer, "EL737__BAD_CONNECT");
break;
case EL737__BAD_FLUSH:
strcpy(pBuffer, "EL737__BAD_FLUSH");
break;
case EL737__BAD_DEV:
strcpy(pBuffer, "EL734__BAD_DEV");
break;
case EL737__BAD_ID:
strcpy(pBuffer, "EL737__BAD_ID");
break;
case EL737__BAD_ILLG:
strcpy(pBuffer, "EL737__BAD_ILLG");
break;
case EL737__BAD_LOC:
strcpy(pBuffer, "EL737__BAD_LOC");
break;
case EL737__BAD_MALLOC:
strcpy(pBuffer, "EL737__BAD_MALLOC");
break;
case EL737__BAD_NOT_BCD:
strcpy(pBuffer, "EL737__BAD_NOT_BCD");
break;
case EL737__BAD_OFL:
strcpy(pBuffer, "EL737__BAD_OFL");
break;
case EL737__BAD_PAR:
strcpy(pBuffer, "EL737__BAD_PAR");
break;
case EL737__BAD_RECV:
strcpy(pBuffer, "EL737__BAD_RECV");
break;
case EL737__BAD_RECV_NET:
strcpy(pBuffer, "EL737__BAD_RECV_NET");
break;
case EL737__BAD_RECV_PIPE:
strcpy(pBuffer, "EL737__BAD_RECV_PIPE");
break;
case EL737__BAD_RECV_UNKN:
strcpy(pBuffer, "EL737__BAD_RECV_UNKN");
break;
case EL737__BAD_RECVLEN:
strcpy(pBuffer, "EL737__BAD_RECVLEN");
break;
case EL737__BAD_RECV1:
strcpy(pBuffer, "EL737__BAD_RECV1");
break;
case EL737__BAD_RECV1_NET:
strcpy(pBuffer, "EL737__BAD_RECV1_NET");
break;
case EL737__BAD_RECV1_PIPE:
strcpy(pBuffer, "EL737__BAD_RECV1_PIPE");
break;
case EL737__BAD_RNG:
strcpy(pBuffer, "EL737__BAD_RNG");
break;
case EL737__BAD_SEND:
strcpy(pBuffer, "EL737__BAD_SEND");
break;
case EL737__BAD_SEND_PIPE:
strcpy(pBuffer, "EL737__BAD_SEND_PIPE");
break;
case EL737__BAD_SEND_NET:
strcpy(pBuffer, "EL737__BAD_SEND_NET");
break;
case EL737__BAD_SEND_UNKN:
strcpy(pBuffer, "EL737__BAD_SEND_UNKN");
break;
case EL737__BAD_SENDLEN:
strcpy(pBuffer, "EL737__BAD_SENDLEN");
break;
case EL737__BAD_SOCKET:
strcpy(pBuffer, "EL737__BAD_SOCKET");
break;
case EL737__BAD_TMO:
strcpy(pBuffer, "EL737__BAD_TMO");
break;
case EL737__FORCED_CLOSED:
strcpy(pBuffer, "EL737__FORCED_CLOSED");
break;
case EL737__BAD_ASYNSRV:
strcpy(pBuffer, "EL737__BAD_ASYNSRV");
break;
default:
sprintf(pBuffer, "Unknown EL737 error %d", iErr);
break;
}
}
/*--------------------------------------------------------------------------*/
static int EL737GetError(struct __COUNTER *self, int *iCode,
char *error, int iErrLen)
{
char *pErr = NULL;
int iC1, iC2, iC3;
char pBueffel[256];
if (self->iErrorCode == UNKNOWNPAR) {
strncpy(error, "unknown internal parameter code", iErrLen);
*iCode = self->iErrorCode;
self->iErrorCode = 0;
return 1;
} else if (self->iErrorCode == BADCOUNTER) {
strncpy(error, "monitor cannot be selected", iErrLen);
*iCode = self->iErrorCode;
self->iErrorCode = 0;
return 1;
} else if (self->iErrorCode == BADTRANGE) {
strncpy(error, "preset time out of range", iErrLen);
*iCode = self->iErrorCode;
self->iErrorCode = 0;
return 1;
}
EL737_ErrInfo(&pErr, &iC1, &iC2, &iC3);
EL737Error2Text(pBueffel, iC1);
strncpy(error, pBueffel, iErrLen);
*iCode = iC1;
return 1;
}
/*--------------------------------------------------------------------------*/
static int EL737TryAndFixIt(struct __COUNTER *self, int iCode)
{
EL737st *pEL737;
int iRet;
char pCommand[50], pReply[50];
assert(self);
pEL737 = (EL737st *) self->pData;
assert(pEL737);
switch (iCode) {
case EL737__BAD_ILLG:
case EL737__BAD_ADR:
case EL737__BAD_PAR:
case EL737__BAD_TMO:
case EL737__BAD_REPLY:
case EL737__BAD_SNTX:
case EL737__BAD_OVFL:
return COREDO;
break;
case EL737__BAD_BSY:
strcpy(pCommand, "S \r");
iRet = EL737_SendCmnd(&pEL737->pData, pCommand, pReply, 49);
if (iRet < 0) {
return COTERM;
} else {
return COREDO;
}
break;
case EL737__BAD_LOC:
strcpy(pCommand, "rmt 1\r");
iRet = EL737_SendCmnd(&pEL737->pData, pCommand, pReply, 49);
if (iRet < 0) {
return COTERM;
}
strcpy(pCommand, "echo 2\r");
iRet = EL737_SendCmnd(&pEL737->pData, pCommand, pReply, 49);
if (iRet < 0) {
return COTERM;
}
strcpy(pCommand, "ra\r");
iRet = EL737_SendCmnd(&pEL737->pData, pCommand, pReply, 49);
if (iRet < 0) {
return COTERM;
}
return COREDO;
break;
case EL737__BAD_DEV:
case EL737__BAD_ID:
case EL737__BAD_NOT_BCD:
case UNKNOWNPAR:
case BADCOUNTER:
case BADTRANGE:
return COTERM;
break;
case EL737__FORCED_CLOSED:
iRet = EL737_Open(&pEL737->pData, pEL737->host, pEL737->iPort,
pEL737->iChannel);
if (iRet == 1) {
return COREDO;
} else {
return COTERM;
}
break;
case EL737__BAD_OFL:
EL737_Close(&pEL737->pData, 0);
iRet = EL737_Open(&pEL737->pData, pEL737->host, pEL737->iPort,
pEL737->iChannel);
if (iRet == 1) {
return COREDO;
} else {
return COTERM;
}
break;
/* case EL737__BAD_ASYNSRV:
EL737_Close(&pEL737->pData,1);
return COREDO;
*/ default:
/* try to reopen connection */
EL737_Close(&pEL737->pData, 1);
iRet = EL737_Open(&pEL737->pData, pEL737->host, pEL737->iPort,
pEL737->iChannel);
if (iRet == 1) {
return COREDO;
} else {
return COTERM;
}
break;
}
return COTERM;
}
/*-------------------------------------------------------------------------*/
static int EL737Set(struct __COUNTER *self, char *name, int iCter,
float fVal)
{
int iRet;
EL737st *pEL737;
char pCommand[80], pReply[80];
assert(self);
pEL737 = (EL737st *) self->pData;
assert(pEL737);
if (strcmp(name, "threshold") == 0) {
sprintf(pCommand, "DL %1.1d %6.2f\r", iCter, fVal);
iRet = EL737_SendCmnd(&pEL737->pData, pCommand, pReply, 79);
if (iRet == 1) {
if (pReply[0] == '?') {
self->iErrorCode = BADCOUNTER;
return HWFault;
}
} else {
return HWFault;
}
sprintf(pCommand, "DR %1.1d \r", iCter);
iRet = EL737_SendCmnd(&pEL737->pData, pCommand, pReply, 79);
if (iRet == 1) {
if (pCommand[0] == '?') {
self->iErrorCode = BADCOUNTER;
return HWFault;
}
return OKOK;
} else {
return HWFault;
}
} else {
self->iErrorCode = UNKNOWNPAR;
return HWFault;
}
}
/*-------------------------------------------------------------------------*/
static int EL737Get(struct __COUNTER *self, char *name, int iCter,
float *fVal)
{
int iRet;
EL737st *pEL737;
char pCommand[80], pReply[80];
assert(self);
pEL737 = (EL737st *) self->pData;
assert(pEL737);
if (strcmp(name, "threshold") == 0) {
sprintf(pCommand, "DL %1.1d\r", iCter);
iRet = EL737_SendCmnd(&pEL737->pData, pCommand, pReply, 79);
if (iRet == 1) {
if (pReply[0] == '?') {
self->iErrorCode = BADCOUNTER;
return HWFault;
}
sscanf(pReply, "%f", fVal);
return OKOK;
} else {
return HWFault;
}
} else {
self->iErrorCode = UNKNOWNPAR;
return HWFault;
}
}
/*-------------------------------------------------------------------------*/
static int EL737Send(struct __COUNTER *self, char *pText, char *pReply,
int iReplyLen)
{
EL737st *pEL737;
char pBuffer[256];
assert(self);
pEL737 = (EL737st *) self->pData;
assert(pEL737);
/* ensure a \r at the end of the text */
if (strlen(pText) > 254) {
strncpy(pReply, "Command to long", iReplyLen);
return 1;
}
strcpy(pBuffer, pText);
if (strchr(pBuffer, (int) '\r') == NULL) {
strcat(pBuffer, "\r");
}
return EL737_SendCmnd(&pEL737->pData, pBuffer, pReply, iReplyLen);
}
/*-------------------------------------------------------------------------*/
pCounterDriver CreateEL737Counter(SConnection * pCon, char *name,
int argc, char *argv[])
{
char *pHost;
int iPort, iChannel;
if (argc < 3) {
SCWrite(pCon,
"ERROR: insuficient number of arguments to create EL737 counter",
eError);
return NULL;
}
if (!isNumeric(argv[1]) || !isNumeric(argv[2])) {
SCWrite(pCon, "ERROR: expected numeric arguments for port and channel",
eError);
return NULL;
}
iPort = atoi(argv[1]);
iChannel = atoi(argv[2]);
return NewEL737Counter(name, argv[0], iPort, iChannel);
}
/*--------------------------------------------------------------------------*/
pCounterDriver NewEL737Counter(char *name, char *host, int iPort,
int iChannel)
{
pCounterDriver pRes = NULL;
EL737st *pData = NULL;
int iRet;
int iC1, iC2, iC3;
char *pErr;
char pBueffel[132];
pRes = CreateCounterDriver(name, "EL737");
if (!pRes) {
return NULL;
}
/* open connection to counter */
pData = (EL737st *) malloc(sizeof(EL737st));
if (!pData) {
DeleteCounterDriver(pRes);
return NULL;
}
pData->host = strdup(host);
pData->iPort = iPort;
pData->iChannel = iChannel;
pData->pData = NULL;
iRet = EL737_Open(&(pData->pData), host, iPort, iChannel);
if (iRet != 1) {
EL737_ErrInfo(&pErr, &iC1, &iC2, &iC3);
DeleteCounterDriver(pRes);
if (pData->host) {
free(pData->host);
}
return NULL;
}
pRes->pData = (void *) pData;
/* assign functions */
pRes->GetStatus = EL737GetStatus;
pRes->Start = EL737Start;
pRes->Halt = EL737Halt;
pRes->ReadValues = EL737ReadValues;
pRes->GetError = EL737GetError;
pRes->TryAndFixIt = EL737TryAndFixIt;
pRes->Pause = EL737Pause;
pRes->Continue = EL737Continue;
pRes->Set = EL737Set;
pRes->Get = EL737Get;
pRes->Send = EL737Send;
pRes->KillPrivate = KillEL737Counter;
pRes->iNoOfMonitors = 7;
pRes->fTime = 0.;
return pRes;
}
/*--------------------------------------------------------------------------*/
void KillEL737Counter(pCounterDriver self)
{
EL737st *pEL737 = NULL;
assert(self);
pEL737 = (EL737st *) self->pData;
assert(pEL737);
EL737_Close(&pEL737->pData, 0);
if (pEL737->host) {
free(pEL737->host);
}
}