required inclusion of a matrix package. - modified counter error handling to send a Stop when the _BAD_BUSY error is received. - added an environment interface to the general controller stuff in choco.* Also added setting a parameter directly at the controller object. - Added a driver for the ETH High Temperature Furnace to be used at SANS.
1036 lines
30 KiB
C
1036 lines
30 KiB
C
/*-------------------------------------------------------------------------
|
|
|
|
C O U N T E R
|
|
|
|
The SICS Interface to a single detector and his associated
|
|
monitors.
|
|
|
|
|
|
Mark Koennecke, January 1997
|
|
|
|
Copyright:
|
|
|
|
Labor fuer Neutronenstreuung
|
|
Paul Scherrer Institut
|
|
CH-5423 Villigen-PSI
|
|
|
|
|
|
The authors hereby grant permission to use, copy, modify, distribute,
|
|
and license this software and its documentation for any purpose, provided
|
|
that existing copyright notices are retained in all copies and that this
|
|
notice is included verbatim in any distributions. No written agreement,
|
|
license, or royalty fee is required for any of the authorized uses.
|
|
Modifications to this software may be copyrighted by their authors
|
|
and need not follow the licensing terms described here, provided that
|
|
the new terms are clearly indicated on the first page of each file where
|
|
they apply.
|
|
|
|
IN NO EVENT SHALL THE AUTHORS OR DISTRIBUTORS BE LIABLE TO ANY PARTY
|
|
FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
|
|
ARISING OUT OF THE USE OF THIS SOFTWARE, ITS DOCUMENTATION, OR ANY
|
|
DERIVATIVES THEREOF, EVEN IF THE AUTHORS HAVE BEEN ADVISED OF THE
|
|
POSSIBILITY OF SUCH DAMAGE.
|
|
|
|
THE AUTHORS AND DISTRIBUTORS SPECIFICALLY DISCLAIM ANY WARRANTIES,
|
|
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY,
|
|
FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT. THIS SOFTWARE
|
|
IS PROVIDED ON AN "AS IS" BASIS, AND THE AUTHORS AND DISTRIBUTORS HAVE
|
|
NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR
|
|
MODIFICATIONS.
|
|
----------------------------------------------------------------------------*/
|
|
#include <stdlib.h>
|
|
#include <assert.h>
|
|
#include <math.h>
|
|
#include <time.h>
|
|
#include "fortify.h"
|
|
#include <string.h>
|
|
#include "countdriv.h"
|
|
#include "obdes.h"
|
|
#include "conman.h"
|
|
#include "interface.h"
|
|
#include "counter.h"
|
|
#include "fupa.h"
|
|
#include "devexec.h"
|
|
#include "status.h"
|
|
#include "event.h"
|
|
#include "splitter.h"
|
|
/*-------------------------------------------------------------------------*/
|
|
/*
|
|
The monitor callback data structure
|
|
*/
|
|
typedef struct {
|
|
float fPreset;
|
|
float fCurrent;
|
|
char *pName;
|
|
} MonEvent, *pMonEvent;
|
|
|
|
/*--------------------------------------------------------------------------*/
|
|
static int Halt(void *pData)
|
|
{
|
|
pCounter self = NULL;
|
|
|
|
assert(pData);
|
|
self = (pCounter)pData;
|
|
|
|
return self->pDriv->Halt(self->pDriv);
|
|
}
|
|
/*-----------------------------------------------------------------------*/
|
|
static int StartCount(void *pData, SConnection *pCon)
|
|
{
|
|
pCounter self;
|
|
char pBueffel[132];
|
|
char pError[80];
|
|
int iRet;
|
|
int i;
|
|
int iErr;
|
|
time_t tX;
|
|
|
|
self = (pCounter)pData;
|
|
assert(self);
|
|
|
|
/* try at least three times to do it */
|
|
for(i = 0; i < 3; i++)
|
|
{
|
|
iRet = self->pDriv->Start(self->pDriv);
|
|
if(iRet == OKOK)
|
|
{
|
|
self->isUpToDate = 0;
|
|
self->tStart = time(&tX);
|
|
return iRet;
|
|
}
|
|
else
|
|
{
|
|
iRet = self->pDriv->GetError(self->pDriv,&iErr,pError,79);
|
|
sprintf(pBueffel,"WARNING: %s ",pError);
|
|
SCWrite(pCon,pBueffel,eError);
|
|
iRet = self->pDriv->TryAndFixIt(self->pDriv,iErr);
|
|
if(iRet == COTERM)
|
|
{
|
|
SCWrite(pCon,"ERROR: Cannot fix counter problem, aborting",eError);
|
|
SCSetInterrupt(pCon,eAbortBatch);
|
|
return HWFault;
|
|
}
|
|
}
|
|
}
|
|
SCWrite(pCon,"ERROR: Cannot fix counter problem, aborting",eError);
|
|
SCSetInterrupt(pCon,eAbortBatch);
|
|
return HWFault;
|
|
}
|
|
/*-----------------------------------------------------------------------*/
|
|
static int PauseCount(void *pData, SConnection *pCon)
|
|
{
|
|
pCounter self;
|
|
char pBueffel[132];
|
|
char pError[80];
|
|
int iRet;
|
|
int i;
|
|
int iErr;
|
|
|
|
self = (pCounter)pData;
|
|
assert(self);
|
|
|
|
/* try at least three times to do it */
|
|
for(i = 0; i < 3; i++)
|
|
{
|
|
iRet = self->pDriv->Pause(self->pDriv);
|
|
if(iRet == OKOK)
|
|
{
|
|
self->isUpToDate = 0;
|
|
return iRet;
|
|
}
|
|
else
|
|
{
|
|
iRet = self->pDriv->GetError(self->pDriv,&iErr,pError,79);
|
|
sprintf(pBueffel,"WARNING: %s ",pError);
|
|
SCWrite(pCon,pBueffel,eError);
|
|
iRet = self->pDriv->TryAndFixIt(self->pDriv,iErr);
|
|
if(iRet == COTERM)
|
|
{
|
|
SCWrite(pCon,"ERROR: Cannot fix counter problem, aborting",eError);
|
|
SCSetInterrupt(pCon,eAbortBatch);
|
|
return HWFault;
|
|
}
|
|
}
|
|
}
|
|
SCWrite(pCon,"ERROR: Cannot fix counter problem, aborting",eError);
|
|
SCSetInterrupt(pCon,eAbortBatch);
|
|
return HWFault;
|
|
}
|
|
/*-----------------------------------------------------------------------*/
|
|
static int ContinueCount(void *pData, SConnection *pCon)
|
|
{
|
|
pCounter self;
|
|
char pBueffel[132];
|
|
char pError[80];
|
|
int iRet;
|
|
int i;
|
|
int iErr;
|
|
|
|
self = (pCounter)pData;
|
|
assert(self);
|
|
|
|
/* try at least three times to do it */
|
|
for(i = 0; i < 3; i++)
|
|
{
|
|
iRet = self->pDriv->Continue(self->pDriv);
|
|
if(iRet == OKOK)
|
|
{
|
|
self->isUpToDate = 0;
|
|
return iRet;
|
|
}
|
|
else
|
|
{
|
|
iRet = self->pDriv->GetError(self->pDriv,&iErr,pError,79);
|
|
sprintf(pBueffel,"WARNING: %s ",pError);
|
|
SCWrite(pCon,pBueffel,eError);
|
|
iRet = self->pDriv->TryAndFixIt(self->pDriv,iErr);
|
|
if(iRet == COTERM)
|
|
{
|
|
SCWrite(pCon,"ERROR: Cannot fix counter problem, aborting",eError);
|
|
SCSetInterrupt(pCon,eAbortBatch);
|
|
return HWFault;
|
|
}
|
|
}
|
|
}
|
|
SCWrite(pCon,"ERROR: Cannot fix counter problem, aborting",eError);
|
|
SCSetInterrupt(pCon,eAbortBatch);
|
|
return HWFault;
|
|
}
|
|
/*--------------------------------------------------------------------------*/
|
|
static int CheckCountStatus(void *pData, SConnection *pCon)
|
|
{
|
|
pCounter self = NULL;
|
|
int i, iRet;
|
|
int eCt;
|
|
char pError[80], pBueffel[132];
|
|
int iErr;
|
|
float fControl;
|
|
MonEvent sMon;
|
|
|
|
self = (pCounter)pData;
|
|
assert(self);
|
|
assert(pCon);
|
|
|
|
eCt = self->pDriv->GetStatus(self->pDriv,&fControl);
|
|
if(eCt == HWFault)
|
|
{
|
|
iRet = self->pDriv->GetError(self->pDriv,&iErr,pError,79);
|
|
sprintf(pBueffel,"WARNING: %s ",pError);
|
|
SCWrite(pCon,pBueffel,eError);
|
|
iRet = self->pDriv->TryAndFixIt(self->pDriv,iErr);
|
|
if(iRet == COTERM)
|
|
{
|
|
SCWrite(pCon,"ERROR: Cannot fix counter problem, aborting",eError);
|
|
SCSetInterrupt(pCon,eAbortBatch);
|
|
SCSetError(pCon,eCt);
|
|
return eCt;
|
|
}
|
|
else
|
|
{
|
|
return HWBusy;
|
|
}
|
|
}
|
|
sMon.fCurrent = fControl;
|
|
sMon.fPreset = self->pDriv->fPreset;
|
|
sMon.pName = self->name;
|
|
if(self->iCallbackCounter > 20)
|
|
{
|
|
InvokeCallBack(self->pCall,MONITOR,&sMon);
|
|
self->iCallbackCounter = 0;
|
|
}
|
|
else
|
|
{
|
|
self->iCallbackCounter++;
|
|
}
|
|
self->pDriv->fLastCurrent = fControl;
|
|
return eCt;
|
|
}
|
|
/*------------------------------------------------------------------------*/
|
|
static int SaveCounterStatus(void *pData, char *name, FILE *fd)
|
|
{
|
|
pCounter self = NULL;
|
|
char pBueffel[512];
|
|
|
|
assert(pData);
|
|
assert(fd);
|
|
|
|
self = (pCounter)pData;
|
|
|
|
sprintf(pBueffel,"# Counter %s\n",name);
|
|
fputs(pBueffel,fd);
|
|
sprintf(pBueffel,"%s SetPreset %f\n",name, self->pDriv->fPreset);
|
|
fputs(pBueffel,fd);
|
|
if(self->pDriv->eMode == eTimer)
|
|
{
|
|
sprintf(pBueffel,"%s SetMode Timer\n",name);
|
|
}
|
|
else
|
|
{
|
|
sprintf(pBueffel,"%s SetMode Preset\n",name);
|
|
}
|
|
fputs(pBueffel,fd);
|
|
|
|
return 1;
|
|
}
|
|
/*------------------------------------------------------------------------*/
|
|
static int TransferData(void *pData, SConnection *pCon)
|
|
{
|
|
pCounter self = NULL;
|
|
int i, iRet;
|
|
char pError[80];
|
|
char pBueffel[132];
|
|
int iCode;
|
|
|
|
self = (pCounter)pData;
|
|
assert(self);
|
|
assert(pCon);
|
|
|
|
/* try three times */
|
|
for(i = 0; i < 3; i++)
|
|
{
|
|
iRet = self->pDriv->ReadValues(self->pDriv);
|
|
if(iRet)
|
|
{
|
|
self->isUpToDate = 1;
|
|
return OKOK;
|
|
}
|
|
else
|
|
{
|
|
self->pDriv->GetError(self->pDriv,&iCode,pError,79);
|
|
sprintf(pBueffel,"WARNING: %s",pError);
|
|
SCWrite(pCon,pBueffel,eError);
|
|
iRet = self->pDriv->TryAndFixIt(self->pDriv,iCode);
|
|
if(iRet == COTERM)
|
|
{
|
|
SCWrite(pCon,"ERROR: Cannot fix counter problem, aborting",eError);
|
|
SCSetInterrupt(pCon,eAbortBatch);
|
|
return HWFault;
|
|
}
|
|
}
|
|
}
|
|
SCWrite(pCon,"ERROR: Cannot fix counter problem, aborting",eError);
|
|
SCSetInterrupt(pCon,eAbortBatch);
|
|
return HWFault;
|
|
}
|
|
/*------------------------------------------------------------------------*/
|
|
static void *CounterGetInterface(void *pData, int iID)
|
|
{
|
|
pCounter self = NULL;
|
|
|
|
self = (pCounter)pData;
|
|
assert(self);
|
|
if(iID == COUNTID)
|
|
{
|
|
return self->pCountInt;
|
|
}
|
|
else if(iID == CALLBACKINTERFACE)
|
|
{
|
|
return self->pCall;
|
|
}
|
|
return NULL;
|
|
}
|
|
/*------------------------------------------------------------------------*/
|
|
pCounter CreateCounter(char *name, pCounterDriver pDriv)
|
|
{
|
|
pCounter pRes = NULL;
|
|
|
|
assert(pDriv);
|
|
|
|
pRes = (pCounter)malloc(sizeof(Counter));
|
|
if(!pRes)
|
|
{
|
|
return NULL;
|
|
}
|
|
pRes->pDes = CreateDescriptor("SingleCounter");
|
|
if(!pRes->pDes)
|
|
{
|
|
free(pRes);
|
|
return NULL;
|
|
}
|
|
/* initialize Descriptor functions */
|
|
pRes->pDes->GetInterface = CounterGetInterface;
|
|
pRes->pDes->SaveStatus = SaveCounterStatus;
|
|
|
|
/* initialise countable interface */
|
|
pRes->pCountInt = CreateCountableInterface();
|
|
if(!pRes->pCountInt)
|
|
{
|
|
DeleteDescriptor(pRes->pDes);
|
|
free(pRes);
|
|
return NULL;
|
|
}
|
|
pRes->pCountInt->StartCount = StartCount;
|
|
pRes->pCountInt->CheckCountStatus = CheckCountStatus;
|
|
pRes->pCountInt->TransferData = TransferData;
|
|
pRes->pCountInt->Halt = Halt;
|
|
pRes->pCountInt->Pause = PauseCount;
|
|
pRes->pCountInt->Continue = ContinueCount;
|
|
pRes->iCallbackCounter = 20;
|
|
|
|
pRes->pCall = CreateCallBackInterface();
|
|
|
|
pRes->pDriv = pDriv;
|
|
pRes->isUpToDate = 1;
|
|
pRes->iExponent = 0;
|
|
pRes->name = strdup(name);
|
|
return pRes;
|
|
}
|
|
/*---------------------------------------------------------------------------*/
|
|
void DeleteCounter(void *pData)
|
|
{
|
|
pCounter self = NULL;
|
|
|
|
assert(pData);
|
|
self = (pCounter)pData;
|
|
|
|
if(self->pDes)
|
|
{
|
|
DeleteDescriptor(self->pDes);
|
|
}
|
|
|
|
if(self->pCountInt)
|
|
{
|
|
free(self->pCountInt);
|
|
}
|
|
if(self->pCall)
|
|
{
|
|
DeleteCallBackInterface(self->pCall);
|
|
}
|
|
|
|
if(self->name)
|
|
{
|
|
free(self->name);
|
|
}
|
|
if(self->pDriv)
|
|
{
|
|
if(strcmp(self->pDriv->type,"EL737") == 0)
|
|
{
|
|
KillEL737Counter(self->pDriv);
|
|
}
|
|
else if (strcmp(self->pDriv->type,"SIM") == 0)
|
|
{
|
|
KillSIMCounter(self->pDriv);
|
|
}
|
|
else
|
|
{
|
|
assert(0);
|
|
}
|
|
}
|
|
free(self);
|
|
}
|
|
/*-------------------------------------------------------------------------*/
|
|
int DoCount(pCounter self, float fPreset, SConnection *pCon,
|
|
int iBlock)
|
|
{
|
|
int iRet;
|
|
char pBueffel[132];
|
|
Status eOld;
|
|
|
|
assert(self);
|
|
|
|
/* check authorisation */
|
|
if(!SCMatchRights(pCon,usUser))
|
|
{
|
|
sprintf(pBueffel,"ERROR: you are not authorised to count");
|
|
SCWrite(pCon, pBueffel, eError);
|
|
return 0;
|
|
}
|
|
|
|
eOld = GetStatus();
|
|
SetStatus(eCounting);
|
|
|
|
/* set Preset */
|
|
SetCounterPreset(self,fPreset);
|
|
|
|
iRet = StartDevice(GetExecutor(),self->name,self->pDes,self,pCon,
|
|
self->pDriv->fPreset);
|
|
if(!iRet)
|
|
{
|
|
SetStatus(eOld);
|
|
SCWrite(pCon,"Counting aborted",eStatus);
|
|
return 0;
|
|
}
|
|
|
|
/* continue only if in blocking mode */
|
|
if(!iBlock)
|
|
{
|
|
return 1;
|
|
}
|
|
|
|
/* wait forever until done or interrupted */
|
|
iRet = Wait4Success(GetExecutor());
|
|
if(iRet == DEVINT)
|
|
{
|
|
SCWrite(pCon,"Counting aborted due to Interrupt",eStatus);
|
|
}
|
|
else if(iRet == DEVERROR)
|
|
{
|
|
SCWrite(pCon,"Counting finished with Problems",eStatus);
|
|
iRet = 1;
|
|
}
|
|
else
|
|
{
|
|
SCWrite(pCon,"Counting finished",eStatus);
|
|
iRet = 1;
|
|
}
|
|
SetStatus(eOld);
|
|
return iRet;
|
|
}
|
|
|
|
/*-------------------------------------------------------------------------*/
|
|
int MakeCounter(SConnection *pCon, SicsInterp *pSics, void *pData,
|
|
int argc, char *argv[])
|
|
{
|
|
pCounter pNew = NULL;
|
|
pCounterDriver pDriv = NULL;
|
|
int iRet;
|
|
char pBueffel[256];
|
|
char **argx;
|
|
FuPaResult pParse;
|
|
FuncTemplate MakeTemplate[] = {
|
|
{"el737",3,{FUPATEXT,FUPAINT,FUPAINT}},
|
|
{"sim",0,{0.0}}
|
|
};
|
|
|
|
assert(pCon);
|
|
assert(pSics);
|
|
|
|
argtolower(argc,argv);
|
|
/* parse function template */
|
|
argx = &argv[2]; /* 0 = MakeCounter, 1 = counter name */
|
|
iRet = EvaluateFuPa((pFuncTemplate)&MakeTemplate,2,argc-2,argx,&pParse);
|
|
if(iRet < 0) /* I/O error */
|
|
{
|
|
sprintf(pBueffel,"%s",pParse.pError);
|
|
SCWrite(pCon,pBueffel,eError);
|
|
return 0;
|
|
}
|
|
|
|
/* create driver depending on parse result */
|
|
switch(iRet)
|
|
{
|
|
case 0: /* EL737 driver */
|
|
pDriv = NewEL737Counter(argv[1],pParse.Arg[0].text,
|
|
pParse.Arg[1].iVal,pParse.Arg[2].iVal);
|
|
break;
|
|
case 1: /* SIM */
|
|
pDriv = NewSIMCounter(argv[1]);
|
|
break;
|
|
default:
|
|
assert(0); /* internal error */
|
|
}
|
|
if(!pDriv)
|
|
{
|
|
sprintf(pBueffel,"ERROR: cannot create requested driver %s",
|
|
argv[2]);
|
|
SCWrite(pCon,pBueffel,eError);
|
|
return 0;
|
|
}
|
|
|
|
/* create Counter and command */
|
|
pNew = CreateCounter(argv[1],pDriv);
|
|
if(!pNew)
|
|
{
|
|
sprintf(pBueffel,"ERROR: cannot create counter %s",
|
|
argv[1]);
|
|
SCWrite(pCon,pBueffel,eError);
|
|
return 0;
|
|
}
|
|
iRet = AddCommand(pSics,argv[1],CountAction,DeleteCounter,(void *)pNew);
|
|
if(!iRet)
|
|
{
|
|
sprintf(pBueffel,"ERROR: duplicate command %s not created",argv[1]);
|
|
SCWrite(pCon,pBueffel,eError);
|
|
return 0;
|
|
}
|
|
return 1;
|
|
}
|
|
/* --------------------------------------------------------------------------*/
|
|
int SetCounterMode(pCounter self, CounterMode eNew)
|
|
{
|
|
int i;
|
|
|
|
assert(self);
|
|
if(eNew == self->pDriv->eMode)
|
|
{
|
|
return 1;
|
|
}
|
|
|
|
if(eNew == eTimer)
|
|
{
|
|
for(i = 0; i < self->iExponent; i++)
|
|
{
|
|
self->pDriv->fPreset /= 10.;
|
|
}
|
|
}
|
|
if(eNew == ePreset)
|
|
{
|
|
for(i = 0; i < self->iExponent; i++)
|
|
{
|
|
self->pDriv->fPreset *= 10.;
|
|
}
|
|
}
|
|
self->pDriv->eMode = eNew;
|
|
return 1;
|
|
}
|
|
/*--------------------------------------------------------------------------*/
|
|
CounterMode GetCounterMode(pCounter self)
|
|
{
|
|
assert(self);
|
|
return self->pDriv->eMode;
|
|
}
|
|
/*------------------------------------------------------------------------*/
|
|
int GetNMonitor(pCounter self)
|
|
{
|
|
assert(self);
|
|
return self->pDriv->iNoOfMonitors;
|
|
}
|
|
/*------------------------------------------------------------------------*/
|
|
int SetCounterPreset(pCounter self, float fVal)
|
|
{
|
|
int i;
|
|
|
|
assert(self);
|
|
|
|
if(fVal < .0)
|
|
{
|
|
return 0;
|
|
}
|
|
if(GetCounterMode(self) == ePreset)
|
|
{
|
|
for(i = 0; i < self->iExponent;i++)
|
|
{
|
|
fVal *= 10.;
|
|
}
|
|
fVal = nintf(fVal);
|
|
}
|
|
self->pDriv->fPreset = fVal;
|
|
return 1;
|
|
}
|
|
/*------------------------------------------------------------------------*/
|
|
float GetCounterPreset(pCounter self)
|
|
{
|
|
int i;
|
|
float fVal;
|
|
|
|
assert(self);
|
|
|
|
fVal = self->pDriv->fPreset;
|
|
if(self->pDriv->eMode == ePreset)
|
|
{
|
|
for(i = 0; i < self->iExponent; i++)
|
|
{
|
|
fVal /= 10.;
|
|
}
|
|
}
|
|
return fVal;
|
|
}
|
|
/*-----------------------------------------------------------------------*/
|
|
long GetCounts(pCounter self, SConnection *pCon)
|
|
{
|
|
assert(self);
|
|
if(!self->isUpToDate)
|
|
{
|
|
self->pCountInt->TransferData(self,pCon);
|
|
}
|
|
return self->pDriv->lCounts[0];
|
|
}
|
|
/*------------------------------------------------------------------------*/
|
|
long GetMonitor(pCounter self, int iNum, SConnection *pCon)
|
|
{
|
|
assert(self);
|
|
|
|
if(!self->isUpToDate)
|
|
{
|
|
self->pCountInt->TransferData(self,pCon);
|
|
}
|
|
if( (iNum < 0) || (iNum > self->pDriv->iNoOfMonitors) )
|
|
{
|
|
return -1L;
|
|
}
|
|
else
|
|
{
|
|
return self->pDriv->lCounts[iNum];
|
|
}
|
|
}
|
|
/*------------------------------------------------------------------------*/
|
|
float GetCountTime(pCounter self,SConnection *pCon)
|
|
{
|
|
assert(self);
|
|
|
|
if(!self->isUpToDate)
|
|
{
|
|
self->pCountInt->TransferData(self,pCon);
|
|
}
|
|
return self->pDriv->fTime;
|
|
}
|
|
/*----------------------------------------------------------------------*/
|
|
static int isAuthorised(SConnection *pCon, int iCode)
|
|
{
|
|
char pBueffel[132];
|
|
|
|
if(!SCMatchRights(pCon,iCode))
|
|
{
|
|
sprintf(pBueffel,"ERROR: you are not authorised to count");
|
|
SCWrite(pCon, pBueffel, eError);
|
|
return 0;
|
|
}
|
|
return 1;
|
|
}
|
|
/*-----------------------------------------------------------------------*/
|
|
static int CounterInterest(int iEvent, void *pEvent, void *pUser)
|
|
{
|
|
SConnection *pCon = NULL;
|
|
pMonEvent pMon = NULL;
|
|
char pBueffel[512];
|
|
|
|
if(iEvent != MONITOR)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
pCon = (SConnection *)pUser;
|
|
pMon = (pMonEvent)pEvent;
|
|
assert(pCon);
|
|
assert(pMon);
|
|
sprintf(pBueffel,"%s.CountStatus = %f %d",pMon->pName,pMon->fPreset,
|
|
(int)nintf(pMon->fCurrent));
|
|
SCWrite(pCon,pBueffel,eWarning);
|
|
return 1;
|
|
}
|
|
/*-----------------------------------------------------------------------*/
|
|
|
|
int CountAction(SConnection *pCon, SicsInterp *pSics, void *pData,
|
|
int argc, char *argv[])
|
|
{
|
|
pCounter self = NULL;
|
|
int iRet, iRet2;
|
|
FuPaResult PaRes;
|
|
char pBueffel[256], pError[80];
|
|
char **argx;
|
|
float fVal;
|
|
long lVal;
|
|
long lID;
|
|
CounterMode eMode;
|
|
FuncTemplate ActionTemplate[] = {
|
|
{"count",1,{FUPAFLOAT} },
|
|
{"getpreset",0,{0.0} },
|
|
{"setpreset",1,{FUPAFLOAT}},
|
|
{"getmode",0,{0,0}},
|
|
{"setmode",1,{FUPATEXT}},
|
|
{"getcounts",0,{0,0}},
|
|
{"getmonitor",1,{FUPAINT,0}},
|
|
{"setexponent",1,{FUPAINT,0}},
|
|
{"getexponent",0,{0,0}},
|
|
{"interest",0,{0,0}},
|
|
{"uninterest",0,{0,0}},
|
|
{"status",0,{0,0}},
|
|
{"gettime",0,{0,0}},
|
|
{"countnb",1,{FUPAFLOAT} },
|
|
{"getthreshold",1,{FUPAINT}},
|
|
{"setthreshold",2,{FUPAINT,FUPAFLOAT}},
|
|
{"stop",0,{0,0}},
|
|
{"mode",1,{FUPAOPT}},
|
|
{"preset",1,{FUPAOPT}},
|
|
{"send",0,{0,0}}
|
|
};
|
|
char *pMode[] = {
|
|
"timer",
|
|
"monitor",
|
|
NULL
|
|
};
|
|
|
|
self = (pCounter)pData;
|
|
assert(self);
|
|
assert(pCon);
|
|
assert(pSics);
|
|
|
|
/* parse function args */
|
|
argtolower(argc,argv);
|
|
argx = &argv[1];
|
|
iRet = EvaluateFuPa((pFuncTemplate)&ActionTemplate,20,argc-1,argx,&PaRes);
|
|
if(iRet < 0)
|
|
{
|
|
sprintf(pBueffel,"%s",PaRes.pError);
|
|
SCWrite(pCon,pBueffel,eError);
|
|
return 0;
|
|
}
|
|
|
|
/* do something! */
|
|
switch(iRet)
|
|
{
|
|
case 0: /* Count */
|
|
return DoCount(self,PaRes.Arg[0].fVal,pCon,1);
|
|
break;
|
|
case 1: /* GetPreset */
|
|
fVal = GetCounterPreset(self);
|
|
sprintf(pBueffel,"%s.Preset = %f",argv[0],fVal);
|
|
SCWrite(pCon,pBueffel,eValue);
|
|
return 1;
|
|
break;
|
|
case 2: /* Set Preset */
|
|
if(isAuthorised(pCon,usUser))
|
|
{
|
|
iRet2 = SetCounterPreset(self,PaRes.Arg[0].fVal);
|
|
if(iRet2)
|
|
SCSendOK(pCon);
|
|
return iRet2;
|
|
}
|
|
else
|
|
{
|
|
return 0;
|
|
}
|
|
break;
|
|
case 3: /* GetMode */
|
|
eMode = GetCounterMode(self);
|
|
if(eMode == eTimer)
|
|
{
|
|
sprintf(pBueffel,"%s.Mode = Timer",argv[0]);
|
|
}
|
|
else
|
|
{
|
|
sprintf(pBueffel,"%s.Mode = Monitor",argv[0]);
|
|
}
|
|
SCWrite(pCon,pBueffel,eValue);
|
|
return 1;
|
|
break;
|
|
case 4: /* Set Mode */
|
|
if(isAuthorised(pCon,usUser))
|
|
{
|
|
if(strcmp(PaRes.Arg[0].text,"timer") == 0)
|
|
{
|
|
SetCounterMode(self,eTimer);
|
|
SCSendOK(pCon);
|
|
return 1;
|
|
}
|
|
else if(strcmp(PaRes.Arg[0].text,"monitor") == 0)
|
|
{
|
|
SetCounterMode(self,ePreset);
|
|
SCSendOK(pCon);
|
|
return 1;
|
|
}
|
|
else
|
|
{
|
|
sprintf(pBueffel,"ERROR: %s not recognized as valid counter mode",
|
|
PaRes.Arg[0].text);
|
|
SCWrite(pCon,pBueffel,eError);
|
|
return 0;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
return 0;
|
|
}
|
|
case 5: /* GetCounts */
|
|
lVal = GetCounts(self,pCon);
|
|
sprintf(pBueffel,"%s.Counts = %ld",argv[0],lVal);
|
|
SCWrite(pCon,pBueffel,eValue);
|
|
return 1;
|
|
|
|
case 6: /* GetMonitor */
|
|
lVal = GetMonitor(self,PaRes.Arg[0].iVal,pCon);
|
|
if(lVal < 0)
|
|
{
|
|
sprintf(pBueffel,"ERROR: %d out of range for monitors",
|
|
PaRes.Arg[0].iVal);
|
|
SCWrite(pCon,pBueffel,eError);
|
|
return 0;
|
|
}
|
|
sprintf(pBueffel,"%s.Monitor %d = %ld",argv[0],PaRes.Arg[0].iVal,
|
|
lVal);
|
|
SCWrite(pCon,pBueffel,eValue);
|
|
return 1;
|
|
case 7: /* SetExponent */
|
|
self->iExponent = PaRes.Arg[0].iVal;
|
|
SCSendOK(pCon);
|
|
return 1;
|
|
case 8: /* GetExponent */
|
|
sprintf(pBueffel,"%s.Exponent = %d",argv[0], self->iExponent);
|
|
SCWrite(pCon,pBueffel,eValue);
|
|
return 1;
|
|
case 9: /* interest */
|
|
lID = RegisterCallback(self->pCall, MONITOR, CounterInterest,
|
|
pCon, NULL);
|
|
SCRegister(pCon,pSics, self->pCall,lID);
|
|
SCSendOK(pCon);
|
|
return 1;
|
|
case 10: /* uninterest */
|
|
RemoveCallback2(self->pCall,pCon);
|
|
SCSendOK(pCon);
|
|
return 1;
|
|
case 11: /* status */
|
|
if(GetCounterMode(self) == ePreset)
|
|
{
|
|
sprintf(pBueffel,"%s.CountStatus = %d %d Beam: %ld E6",
|
|
argv[0],
|
|
(int)nintf(self->pDriv->fPreset),
|
|
(int)nintf(self->pDriv->fLastCurrent),
|
|
GetMonitor(self,4,pCon)/100000);
|
|
}
|
|
else
|
|
{
|
|
sprintf(pBueffel,"%s.CountStatus = %8.2f %8.2f Beam %ld E6",
|
|
argv[0],
|
|
self->pDriv->fPreset,
|
|
self->pDriv->fLastCurrent,
|
|
GetMonitor(self,4,pCon)/100000);
|
|
}
|
|
SCWrite(pCon,pBueffel,eWarning);
|
|
return 1;
|
|
case 12: /* gettime */
|
|
fVal = GetCountTime(self,pCon);
|
|
sprintf(pBueffel,"%s.CountTime = %f",argv[0],fVal);
|
|
SCWrite(pCon,pBueffel,eValue);
|
|
return 1;
|
|
case 13:
|
|
/* countnb, non blocking count */
|
|
return DoCount(self,PaRes.Arg[0].fVal,pCon,0);
|
|
break;
|
|
case 14:
|
|
/* get threshold value */
|
|
iRet = self->pDriv->Get(self->pDriv,PARTHRESHOLD,
|
|
PaRes.Arg[0].iVal,&fVal);
|
|
if(iRet <= 0)
|
|
{
|
|
self->pDriv->GetError(self->pDriv,&iRet,
|
|
pError,79);
|
|
sprintf(pBueffel,"ERROR: %s",pError);
|
|
SCWrite(pCon,pBueffel,eError);
|
|
return 0;
|
|
}
|
|
else
|
|
{
|
|
sprintf(pBueffel,"%s.threshold%1.1d = %f",
|
|
argv[0],PaRes.Arg[0].iVal,fVal);
|
|
SCWrite(pCon,pBueffel,eValue);
|
|
return 1;
|
|
}
|
|
break;
|
|
case 15:
|
|
if(!SCMatchRights(pCon,usMugger))
|
|
{
|
|
SCWrite(pCon,
|
|
"ERROR: Insufficient privilege to set threshold",eError);
|
|
return 0;
|
|
}
|
|
/* set threshold value */
|
|
iRet = self->pDriv->Set(self->pDriv,PARTHRESHOLD,
|
|
PaRes.Arg[0].iVal,PaRes.Arg[1].fVal);
|
|
if(iRet <= 0)
|
|
{
|
|
self->pDriv->GetError(self->pDriv,&iRet,
|
|
pError,79);
|
|
sprintf(pBueffel,"ERROR: %s",pError);
|
|
SCWrite(pCon,pBueffel,eError);
|
|
return 0;
|
|
}
|
|
else
|
|
{
|
|
SCSendOK(pCon);
|
|
return 1;
|
|
}
|
|
break;
|
|
case 16:
|
|
/* stop */
|
|
if(!SCMatchRights(pCon,usUser))
|
|
{
|
|
return 0;
|
|
}
|
|
self->pCountInt->Halt(self);
|
|
SCSendOK(pCon);
|
|
return 1;
|
|
case 17:
|
|
/* mode */
|
|
if(PaRes.Arg[0].iVal) /* set case */
|
|
{
|
|
if(isAuthorised(pCon,usUser))
|
|
{
|
|
if(strcmp(PaRes.Arg[0].text,"timer") == 0)
|
|
{
|
|
SetCounterMode(self,eTimer);
|
|
SCSendOK(pCon);
|
|
return 1;
|
|
}
|
|
else if(strcmp(PaRes.Arg[0].text,"monitor") == 0)
|
|
{
|
|
SetCounterMode(self,ePreset);
|
|
SCSendOK(pCon);
|
|
return 1;
|
|
}
|
|
else
|
|
{
|
|
sprintf(pBueffel,
|
|
"ERROR: %s not recognized as valid counter mode",
|
|
PaRes.Arg[0].text);
|
|
SCWrite(pCon,pBueffel,eError);
|
|
return 0;
|
|
}
|
|
}
|
|
}
|
|
else /* get case */
|
|
{
|
|
eMode = GetCounterMode(self);
|
|
if(eMode == eTimer)
|
|
{
|
|
sprintf(pBueffel,"%s.Mode = Timer",argv[0]);
|
|
}
|
|
else
|
|
{
|
|
sprintf(pBueffel,"%s.Mode = Monitor",argv[0]);
|
|
}
|
|
SCWrite(pCon,pBueffel,eValue);
|
|
return 1;
|
|
break;
|
|
}
|
|
break;
|
|
case 18: /* preset */
|
|
if(PaRes.Arg[0].iVal) /* set case */
|
|
{
|
|
if(isAuthorised(pCon,usUser))
|
|
{
|
|
iRet2 = SetCounterPreset(self,PaRes.Arg[0].fVal);
|
|
if(iRet2)
|
|
SCSendOK(pCon);
|
|
return iRet2;
|
|
}
|
|
else
|
|
{
|
|
return 0;
|
|
}
|
|
}
|
|
else /* read case */
|
|
{
|
|
fVal = GetCounterPreset(self);
|
|
sprintf(pBueffel,"%s.Preset = %f",argv[0],fVal);
|
|
SCWrite(pCon,pBueffel,eValue);
|
|
return 1;
|
|
}
|
|
break;
|
|
case 19: /* send */
|
|
/* only manager may use this */
|
|
if(!SCMatchRights(pCon,usMugger))
|
|
{
|
|
return;
|
|
}
|
|
Arg2Text(argc-2,&argv[2],pError,79);
|
|
iRet = self->pDriv->Send(self->pDriv,pError,pBueffel,255);
|
|
if(iRet == 1)
|
|
{
|
|
SCWrite(pCon,pBueffel,eValue);
|
|
return 1;
|
|
}
|
|
else
|
|
{
|
|
self->pDriv->GetError(self->pDriv,&iRet,pError,79);
|
|
SCWrite(pCon,pError,eError);
|
|
return 0;
|
|
}
|
|
break;
|
|
default:
|
|
assert(0); /* internal error */
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
|