/*---------------------------------------------------------------------- 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 #include #include #include #include #include #include #include #include "hardsup/sinq_prototypes.h" #include "hardsup/el737_def.h" #include "hardsup/el737fix.h" /*----------------------------- 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) { 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; } 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: 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 %f\r",iCter,fVal); iRet = EL737_SendCmnd(&pEL737->pData,pCommand,pReply,79); if(iRet == 1) { if(pCommand[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); } }