775 lines
23 KiB
C
775 lines
23 KiB
C
/**
|
|
* This is a second generation style counter object. It is supposed to work
|
|
* nicely with a scriptcontext to drive the actual hardware. This is supposed
|
|
* to interface to single counters and histogram memories. This tries to be
|
|
* backwards compatible with the old style counter module; thus some
|
|
* fields in the data structure will not be used.
|
|
*
|
|
* copyright: see file COPYRIGHT
|
|
*
|
|
* Mark Koennecke, February 2009
|
|
*/
|
|
#include <math.h>
|
|
#include <time.h>
|
|
#include <sics.h>
|
|
#include <counter.h>
|
|
#include "sicshipadaba.h"
|
|
|
|
|
|
/*---------------------------------------------------------------------------
|
|
* defines for commmands
|
|
* -------------------------------------------------------------------------*/
|
|
#define START 1000
|
|
#define STOP 1001
|
|
#define PAUSE 1002
|
|
#define CONT 1003
|
|
/*---------------------------------------------------------------------------*/
|
|
typedef struct {
|
|
float fPreset;
|
|
float fCurrent;
|
|
char *pName;
|
|
} MonEvent, *pMonEvent;
|
|
/*-------------------------------------------------------------------------*/
|
|
static void SecCounterSetError(pCounter self, char *text)
|
|
{
|
|
hdbValue v;
|
|
pHdb node;
|
|
|
|
node = GetHipadabaNode(self->pDes->parNode, "error");
|
|
if(node != NULL){
|
|
v = MakeHdbText(strdup(text));
|
|
UpdateHipadabaPar(node,v,NULL);
|
|
Log(VERBOSE,"par","%s:error:%s", self->name,text);
|
|
ReleaseHdbValue(&v);
|
|
}
|
|
}
|
|
/*---------------------------------------------------------------------------*/
|
|
int SecCtrInvokeFunction(pCounter self, SConnection *pCon, int code)
|
|
{
|
|
pHdb node = NULL, status = NULL;
|
|
hdbValue v;
|
|
|
|
node = GetHipadabaNode(self->pDes->parNode, "control");
|
|
status = GetHipadabaNode(self->pDes->parNode, "status");
|
|
assert(node != NULL);
|
|
assert(status != NULL);
|
|
v = MakeHdbFloat(code);
|
|
if(code != START && strcmp(status->value.v.text,"starting") == 0){
|
|
UpdateHipadabaPar(node,MakeHdbText("run"),NULL);
|
|
}
|
|
return SetHipadabaPar(node,v,pCon);
|
|
}
|
|
/*---------------------------------------------------------------------------*/
|
|
static int SecCtrHalt(void *pData)
|
|
{
|
|
pCounter self = (pCounter)pData;
|
|
pHdb node = NULL;
|
|
|
|
assert(self != NULL);
|
|
|
|
SecCtrInvokeFunction(self,pServ->dummyCon, STOP);
|
|
node = GetHipadabaNode(self->pDes->parNode, "status");
|
|
assert(node != NULL);
|
|
if(strcmp(node->value.v.text,"starting") == 0){
|
|
UpdateHipadabaPar(node,MakeHdbText("run"),NULL);
|
|
}
|
|
ReleaseCountLock(self->pCountInt);
|
|
return 1;
|
|
}
|
|
/*---------------------------------------------------------------------------*/
|
|
static int SecStartCount(void *pData, SConnection *pCon)
|
|
{
|
|
pCounter self = (pCounter)pData;
|
|
int status;
|
|
pHdb node, statusNode;
|
|
|
|
assert(self != NULL);
|
|
|
|
if (!GetCountLock(self->pCountInt, pCon)) {
|
|
return 0;
|
|
}
|
|
|
|
statusNode = GetHipadabaNode(self->pDes->parNode, "status");
|
|
UpdateHipadabaPar(statusNode,MakeHdbText("starting"), pCon);
|
|
status = SecCtrInvokeFunction(self,pCon, START);
|
|
self->haltFixFlag = 0;
|
|
if(status == 1){
|
|
self->isUpToDate = 0;
|
|
self->badStatusCount = 0;
|
|
self->tStart = time(NULL);
|
|
node = GetHipadabaNode(self->pDes->parNode, "control");
|
|
UpdateHipadabaPar(node,MakeHdbFloat(.0), pCon);
|
|
Log(VERBOSE,"par","%s:control:%s", self->name,"0");
|
|
SetHdbProperty(node,"geterror", NULL);
|
|
/*
|
|
* set time to 0. Otherwise, if there is a delay,
|
|
* the check for overrun counters in SecCtrCheckStatus
|
|
* may trigger!
|
|
*/
|
|
node = GetHipadabaNode(self->pDes->parNode, "time");
|
|
UpdateHipadabaPar(node,MakeHdbFloat(.0), pCon);
|
|
Log(VERBOSE,"par","%s:time:%s", self->name,"0");
|
|
InvokeCallBack(self->pCall,COUNTSTART, pCon);
|
|
SecCounterSetError(self,"None");
|
|
return 1;
|
|
} else {
|
|
UpdateHipadabaPar(statusNode,MakeHdbText("error"), pCon);
|
|
ReleaseCountLock(self->pCountInt);
|
|
return HWFault;
|
|
}
|
|
}
|
|
/*---------------------------------------------------------------------------*/
|
|
static int SecPause(void *pData, SConnection *pCon)
|
|
{
|
|
pCounter self = (pCounter)pData;
|
|
|
|
assert(self != NULL);
|
|
return SecCtrInvokeFunction(self,pCon, PAUSE);
|
|
}
|
|
/*---------------------------------------------------------------------------*/
|
|
static int SecContinue(void *pData, SConnection *pCon)
|
|
{
|
|
pCounter self = (pCounter)pData;
|
|
|
|
assert(self != NULL);
|
|
return SecCtrInvokeFunction(self,pCon, CONT);
|
|
}
|
|
/*----------------------------------------------------------------------------*/
|
|
static int SecCtrCheckStatus(void *pData, SConnection *pCon)
|
|
{
|
|
pCounter self = (pCounter)pData;
|
|
pHdb node = NULL, control = NULL;
|
|
hdbValue v;
|
|
int status;
|
|
MonEvent sMon;
|
|
float fControl, fPreset;
|
|
char error[132];
|
|
|
|
assert(self != NULL);
|
|
|
|
node = GetHipadabaNode(self->pDes->parNode,"status");
|
|
assert(node != NULL);
|
|
status = GetHipadabaPar(node,&v,pCon);
|
|
|
|
if(status != 1){
|
|
ReleaseCountLock(self->pCountInt);
|
|
return HWFault;
|
|
}
|
|
|
|
if(v.v.text == NULL){
|
|
return HWBusy;
|
|
}
|
|
if (strstr(v.v.text, "idle") != NULL) {
|
|
InvokeCallBack(self->pCall, COUNTEND, NULL);
|
|
ReleaseCountLock(self->pCountInt);
|
|
status = HWIdle;
|
|
} else if (strstr(v.v.text, "run") != NULL) {
|
|
status = HWBusy;
|
|
} else if (strstr(v.v.text, "starting") != NULL) {
|
|
status = HWBusy;
|
|
} else if (strstr(v.v.text, "nobeam") != NULL) {
|
|
status = HWNoBeam;
|
|
} else if (strstr(v.v.text, "pause") != NULL) {
|
|
status = HWPause;
|
|
} else if (strstr(v.v.text, "restart") != NULL) {
|
|
SecStartCount(self, pCon);
|
|
return HWBusy;
|
|
} else if (strstr(v.v.text, "error") != NULL) {
|
|
InvokeCallBack(self->pCall, COUNTEND, NULL);
|
|
ReleaseCountLock(self->pCountInt);
|
|
if(GetHdbProperty(node,"geterror",error,sizeof(error)) == 1){
|
|
SCPrintf(pCon,eError,"ERROR: %s", error);
|
|
SecCounterSetError(self,error);
|
|
} else {
|
|
SecCounterSetError(self,"Undefined counter error: set status geterror");
|
|
SCPrintf(pCon,eError,"ERROR: Unknown counter status error: set status geterror property");
|
|
}
|
|
status = HWFault;
|
|
} else {
|
|
SCPrintf(pCon, eError, "ERROR: unknown counter status %s found",
|
|
v.v.text);
|
|
ReleaseCountLock(self->pCountInt);
|
|
status = HWFault;
|
|
}
|
|
ReleaseHdbValue(&v);
|
|
|
|
|
|
if(self->getMode(self) == eTimer){
|
|
node = GetHipadabaNode(self->pDes->parNode,"time");
|
|
assert(node != NULL);
|
|
GetHipadabaPar(node,&v,pCon);
|
|
fControl = v.v.doubleValue;
|
|
} else {
|
|
node = GetHipadabaNode(self->pDes->parNode,"values");
|
|
if(node != NULL) {
|
|
/*
|
|
This can be NULL if the counter is a HM. The values does not
|
|
exist and fControl is useless
|
|
|
|
The 1 below is only correct for PSI where only the first
|
|
monitor can be the control monitor. Elsewhere this must be the
|
|
control monitor channel
|
|
|
|
This may need to change with the second generation DAQ where the
|
|
count control channel can be changed.
|
|
*/
|
|
fControl = v.v.intArray[1];
|
|
}
|
|
}
|
|
|
|
|
|
node = GetHipadabaNode(self->pDes->parNode,"preset");
|
|
assert(node != NULL);
|
|
GetHipadabaPar(node,&v,pCon);
|
|
fPreset = v.v.doubleValue;
|
|
|
|
sMon.fCurrent = fControl;
|
|
sMon.fPreset = fPreset;
|
|
sMon.pName = self->name;
|
|
self->badStatusCount = 0;
|
|
|
|
/*
|
|
* check for overrun counter boxes
|
|
*/
|
|
if(self->getMode(self) == eTimer &&
|
|
(sMon.fCurrent > sMon.fPreset +1)
|
|
&& self->haltFixFlag == 0){
|
|
SecCtrHalt(self);
|
|
self->haltFixFlag = 1;
|
|
}
|
|
|
|
/*
|
|
* invoke notifiactions, if necessary
|
|
*/
|
|
if (self->iCallbackCounter > 20) {
|
|
InvokeCallBack(self->pCall, MONITOR, &sMon);
|
|
self->iCallbackCounter = 0;
|
|
} else {
|
|
self->iCallbackCounter++;
|
|
}
|
|
|
|
return status;
|
|
}
|
|
/*---------------------------------------------------------------------------
|
|
* Here is an issue: this ought to wait until data has arrived. Callers
|
|
* think now that the data is up to date. With scriptcontext this may not be
|
|
* the case. The update may come later or even never. Perhaps this needs
|
|
* to be emulated:
|
|
* - set a property to some value when starting
|
|
* - add an update callback which deletes the property when done.
|
|
* - Check that property or the geterror property here in a loop
|
|
* until done or we timeout.
|
|
*
|
|
* Nope! Update October 2013:
|
|
* How it is normally done is to read the data through scripcontext when
|
|
* counting is finished and not to finish with counting until this has
|
|
* been done. The code below is only usefule for non scriptcontext
|
|
* drivers.
|
|
* -----------------------------------------------------------------------*/
|
|
static int SecCtrTransferData(void *pData, SConnection *pCon)
|
|
{
|
|
pCounter self = (pCounter)pData;
|
|
assert(self != NULL);
|
|
pHdb node = NULL;
|
|
hdbValue v;
|
|
int status;
|
|
|
|
node = GetHipadabaNode(self->pDes->parNode,"values");
|
|
assert(node != NULL);
|
|
self->isUpToDate = 1;
|
|
status = GetHipadabaPar(node,&v,pCon);
|
|
ReleaseHdbValue(&v);
|
|
return status;
|
|
}
|
|
/*------------------------------------------------------------------------*/
|
|
static void *SecCtrCounterGetInterface(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;
|
|
}
|
|
/*--------------------------------------------------------------------------*/
|
|
static int SecCtrSetMode(pCounter self, CounterMode eNew)
|
|
{
|
|
hdbValue v;
|
|
pHdb node = NULL;
|
|
|
|
node = GetHipadabaNode(self->pDes->parNode,"mode");
|
|
assert(node != NULL);
|
|
switch(eNew){
|
|
case eTimer:
|
|
v = MakeHdbText("timer");
|
|
break;
|
|
case ePreset:
|
|
v = MakeHdbText("monitor");
|
|
break;
|
|
}
|
|
Log(VERBOSE,"par","%s:mode:%s", self->name,v.v.text);
|
|
return SetHipadabaPar(node,v,NULL);
|
|
|
|
}
|
|
/*---------------------------------------------------------------------------*/
|
|
static CounterMode SecCtrGetMode(pCounter self)
|
|
{
|
|
hdbValue v;
|
|
pHdb node = NULL;
|
|
CounterMode mode;
|
|
|
|
node = GetHipadabaNode(self->pDes->parNode,"mode");
|
|
assert(node != NULL);
|
|
GetHipadabaPar(node,&v,NULL);
|
|
assert(v.v.text != NULL);
|
|
if(strcmp(v.v.text,"timer") == 0){
|
|
mode = eTimer;
|
|
} else {
|
|
mode = ePreset;
|
|
}
|
|
ReleaseHdbValue(&v);
|
|
return mode;
|
|
}
|
|
/*--------------------------------------------------------------------------*/
|
|
static int SecCtrSetPreset(pCounter self, float val)
|
|
{
|
|
hdbValue v;
|
|
pHdb node = NULL;
|
|
|
|
node = GetHipadabaNode(self->pDes->parNode,"preset");
|
|
assert(node != NULL);
|
|
v = MakeHdbFloat(val);
|
|
Log(VERBOSE,"par","%s:preset:%f", self->name,v.v.doubleValue);
|
|
return SetHipadabaPar(node,v,NULL);
|
|
}
|
|
/*--------------------------------------------------------------------------*/
|
|
static void SecCtrSetCountParameters(void *pData, float fPreset,
|
|
CounterMode eMode)
|
|
{
|
|
pCounter self = NULL;
|
|
|
|
assert(pData);
|
|
self = (pCounter) pData;
|
|
|
|
SetCounterPreset(self, fPreset);
|
|
SetCounterMode(self, eMode);
|
|
}
|
|
|
|
/*---------------------------------------------------------------------------*/
|
|
static float SecCtrGetPreset(pCounter self)
|
|
{
|
|
hdbValue v;
|
|
pHdb node = NULL;
|
|
|
|
node = GetHipadabaNode(self->pDes->parNode,"preset");
|
|
assert(node != NULL);
|
|
GetHipadabaPar(node,&v,NULL);
|
|
return (float)v.v.doubleValue;
|
|
}
|
|
/*---------------------------------------------------------------------------*/
|
|
static float SecCtrGetControlValue(pCounter self)
|
|
{
|
|
hdbValue v;
|
|
pHdb node = NULL;
|
|
|
|
node = GetHipadabaNode(self->pDes->parNode,"control");
|
|
assert(node != NULL);
|
|
GetHipadabaPar(node,&v,NULL);
|
|
return (float)v.v.doubleValue;
|
|
}
|
|
/*--------------------------------------------------------------------------*/
|
|
static int SecCtrGetNMonitor(pCounter self)
|
|
{
|
|
hdbValue v;
|
|
pHdb node = NULL;
|
|
|
|
node = GetHipadabaNode(self->pDes->parNode,"values");
|
|
assert(node != NULL);
|
|
GetHipadabaPar(node,&v,NULL);
|
|
return v.arrayLength;
|
|
}
|
|
/*--------------------------------------------------------------------------*/
|
|
static long SecCtrGetMonitor(pCounter self, int iNum, SConnection *pCon)
|
|
{
|
|
hdbValue v;
|
|
pHdb node = NULL;
|
|
long val;
|
|
|
|
if (!self->isUpToDate) {
|
|
self->pCountInt->TransferData(self, pCon);
|
|
}
|
|
node = GetHipadabaNode(self->pDes->parNode,"values");
|
|
assert(node != NULL);
|
|
GetHipadabaPar(node,&v,pCon);
|
|
if(iNum >= 0 && iNum < v.arrayLength){
|
|
val = (long)v.v.intArray[iNum];
|
|
} else {
|
|
val = -1L;
|
|
}
|
|
ReleaseHdbValue(&v);
|
|
return val;
|
|
}
|
|
/*--------------------------------------------------------------------------*/
|
|
static long SecCtrGetCounts(pCounter self, SConnection *pCon)
|
|
{
|
|
return SecCtrGetMonitor(self,0,pCon);
|
|
}
|
|
/*--------------------------------------------------------------------------*/
|
|
static void SecCtrSetMonitor(pCounter self, int iNum, long val)
|
|
{
|
|
hdbValue v;
|
|
pHdb node = NULL;
|
|
|
|
node = GetHipadabaNode(self->pDes->parNode,"values");
|
|
assert(node != NULL);
|
|
GetHipadabaPar(node,&v,NULL);
|
|
if(iNum >= 0 && iNum < v.arrayLength){
|
|
v.v.intArray[iNum] = val;
|
|
UpdateHipadabaPar(node,v,NULL);
|
|
}
|
|
}
|
|
/*---------------------------------------------------------------------------*/
|
|
static float SecCtrGetTime(pCounter self, SConnection *pCon)
|
|
{
|
|
hdbValue v;
|
|
pHdb node = NULL;
|
|
|
|
node = GetHipadabaNode(self->pDes->parNode,"time");
|
|
assert(node != NULL);
|
|
GetHipadabaPar(node,&v,pCon);
|
|
return (float)v.v.doubleValue;
|
|
}
|
|
/*--------------------------------------------------------------------------*/
|
|
static int CountCmd(pSICSOBJ ccmd, SConnection * con,
|
|
Hdb * cmdNode, Hdb * par[], int nPar)
|
|
{
|
|
float preset;
|
|
pHdb presetNode = NULL;
|
|
|
|
if(nPar < 1){
|
|
presetNode = GetHipadabaNode(ccmd->objectNode,"preset");
|
|
if(presetNode != NULL){
|
|
preset = presetNode->value.v.doubleValue;
|
|
} else {
|
|
/*
|
|
This can really only happen when the counter is corrupt
|
|
*/
|
|
assert(0);
|
|
}
|
|
} else {
|
|
preset = par[0]->value.v.doubleValue;
|
|
}
|
|
return DoCount((pCounter)ccmd, preset, con, 1);
|
|
}
|
|
/*--------------------------------------------------------------------------*/
|
|
static int GetMonitorCmd(pSICSOBJ ccmd, SConnection * con,
|
|
Hdb * cmdNode, Hdb * par[], int nPar)
|
|
{
|
|
long counts;
|
|
pCounter self = (pCounter)ccmd;
|
|
if(nPar < 1) {
|
|
SCWrite(con,"ERROR: missing monitor no in getmonitor",eError);
|
|
return 0;
|
|
}
|
|
counts = self->getMonitor(self,par[0]->value.v.intValue,con);
|
|
SCPrintf(con,eValue,"%s.monitor.%d = %ld", self->name,
|
|
par[0]->value.v.intValue,counts);
|
|
return 1;
|
|
}
|
|
/*--------------------------------------------------------------------------*/
|
|
static int GetCountsCmd(pSICSOBJ ccmd, SConnection * con,
|
|
Hdb * cmdNode, Hdb * par[], int nPar)
|
|
{
|
|
long counts;
|
|
pCounter self = (pCounter)ccmd;
|
|
counts = self->getCounts(self,con);
|
|
SCPrintf(con,eValue,"%s.counts = %ld", self->name,counts);
|
|
return 1;
|
|
}
|
|
/*--------------------------------------------------------------------------*/
|
|
static int CountNBCmd(pSICSOBJ ccmd, SConnection * con,
|
|
Hdb * cmdNode, Hdb * par[], int nPar)
|
|
{
|
|
float preset;
|
|
pHdb presetNode = NULL;
|
|
|
|
if(nPar < 1){
|
|
presetNode = GetHipadabaNode(ccmd->objectNode,"preset");
|
|
if(presetNode != NULL){
|
|
preset = presetNode->value.v.doubleValue;
|
|
} else {
|
|
/*
|
|
This can really only happen when the counter is corrupt
|
|
*/
|
|
assert(0);
|
|
}
|
|
} else {
|
|
preset = par[0]->value.v.doubleValue;
|
|
}
|
|
return DoCount((pCounter)ccmd, preset, con, 0);
|
|
}
|
|
/*--------------------------------------------------------------------------*/
|
|
static int StopCmd(pSICSOBJ ccmd, SConnection * con,
|
|
Hdb * cmdNode, Hdb * par[], int nPar)
|
|
{
|
|
pCounter self = (pCounter)ccmd;
|
|
return self->pCountInt->Halt(self);
|
|
}
|
|
/*--------------------------------------------------------------------------*/
|
|
static int PauseCmd(pSICSOBJ ccmd, SConnection * con,
|
|
Hdb * cmdNode, Hdb * par[], int nPar)
|
|
{
|
|
pCounter self = (pCounter)ccmd;
|
|
return self->pCountInt->Pause(self,con);
|
|
}
|
|
/*--------------------------------------------------------------------------*/
|
|
static int ContinueCmd(pSICSOBJ ccmd, SConnection * con,
|
|
Hdb * cmdNode, Hdb * par[], int nPar)
|
|
{
|
|
pCounter self = (pCounter)ccmd;
|
|
return self->pCountInt->Continue(self,con);
|
|
}
|
|
/*-------------------------------------------------------------------------*/
|
|
extern int CounterInterest(int iEvent, void *pEvent, void *pUser);
|
|
/*--------------------------------------------------------------------------*/
|
|
static int InterestCmd(pSICSOBJ ccmd, SConnection * con,
|
|
Hdb * cmdNode, Hdb * par[], int nPar)
|
|
{
|
|
long lID;
|
|
pCounter self = (pCounter)ccmd;
|
|
lID = RegisterCallback(self->pCall, MONITOR, CounterInterest,
|
|
SCCopyConnection(con), SCDeleteConnection);
|
|
SCSendOK(con);
|
|
return 1;
|
|
|
|
}
|
|
/*--------------------------------------------------------------------------*/
|
|
static int CountStatusCmd(pSICSOBJ ccmd, SConnection * con,
|
|
Hdb * cmdNode, Hdb * par[], int nPar)
|
|
{
|
|
float preset, done;
|
|
int exponent;
|
|
pHdb node, data;
|
|
|
|
node = GetHipadabaNode(ccmd->objectNode,"preset");
|
|
assert(node != NULL);
|
|
preset = node->value.v.doubleValue;
|
|
|
|
node = GetHipadabaNode(ccmd->objectNode,"mode");
|
|
assert(node != NULL);
|
|
strtolower(node->value.v.text);
|
|
if(strcmp(node->value.v.text,"timer") == 0) {
|
|
data = GetHipadabaNode(ccmd->objectNode,"time");
|
|
assert(data != NULL);
|
|
done = data->value.v.doubleValue;
|
|
} else {
|
|
data = GetHipadabaNode(ccmd->objectNode,"values");
|
|
assert(data != NULL);
|
|
done = data->value.v.intArray[0];
|
|
data = GetHipadabaNode(ccmd->objectNode,"exponent");
|
|
assert(data != NULL);
|
|
exponent = data->value.v.intValue;
|
|
if(exponent != 0){
|
|
done /= pow(10,exponent);
|
|
}
|
|
}
|
|
SCPrintf(con,eValue,"%s.CountStatus = %f %f",
|
|
ccmd->objectNode->name, preset, done);
|
|
|
|
return 1;
|
|
}
|
|
/*--------------------------------------------------------------------------
|
|
Disallows status changes from starting to anything else but run or
|
|
error
|
|
----------------------------------------------------------------------------*/
|
|
static hdbCallbackReturn SecStatusCallback(pHdb node, void *userData,
|
|
pHdbMessage message)
|
|
{
|
|
pHdbDataMessage mm = NULL;
|
|
hdbValue v;
|
|
pCounter self = (pCounter)userData;
|
|
|
|
mm = GetHdbUpdateMessage(message);
|
|
if (mm != NULL) {
|
|
v = *mm->v;
|
|
if(strcmp(node->value.v.text,"starting") == 0) {
|
|
if(strstr(v.v.text,"run") == 0 && strstr(v.v.text,"error") == 0) {
|
|
return hdbAbort;
|
|
}
|
|
}
|
|
if(strcmp(v.v.text,node->value.v.text) != 0){
|
|
Log(VERBOSE,"par","%s:status:%s", self->name,v.v.text);
|
|
}
|
|
}
|
|
|
|
return hdbContinue;
|
|
}
|
|
/*--------------------------------------------------------------------------*/
|
|
pCounter CreateSecCounter(SConnection *pCon, char *type, char *name, int length)
|
|
{
|
|
pCounter pRes = NULL;
|
|
pHdb node = NULL, child = NULL;
|
|
|
|
pRes = (pCounter) malloc(sizeof(Counter));
|
|
if (!pRes) {
|
|
SCWrite(pCon,"ERROR: out of memory in MakeSecCter", eError);
|
|
return NULL;
|
|
}
|
|
memset(pRes,0,sizeof(Counter));
|
|
pRes->pDes = CreateDescriptor(type);
|
|
if (!pRes->pDes) {
|
|
SCWrite(pCon,"ERROR: out of memory in MakeSecCter", eError);
|
|
return 0;
|
|
}
|
|
/* initialize Descriptor functions */
|
|
pRes->pDes->GetInterface = SecCtrCounterGetInterface;
|
|
pRes->pDes->SaveStatus = SaveSICSOBJ;
|
|
|
|
/* initialise countable interface */
|
|
pRes->pCountInt = CreateCountableInterface();
|
|
if (!pRes->pCountInt) {
|
|
DeleteDescriptor(pRes->pDes);
|
|
SCWrite(pCon,"ERROR: out of memory in MakeSecCter", eError);
|
|
return 0;
|
|
}
|
|
pRes->pCountInt->SetCountParameters = SecCtrSetCountParameters;
|
|
pRes->pCountInt->StartCount = SecStartCount;
|
|
pRes->pCountInt->CheckCountStatus = SecCtrCheckStatus;
|
|
pRes->pCountInt->TransferData = SecCtrTransferData;
|
|
pRes->pCountInt->Halt = SecCtrHalt;
|
|
pRes->pCountInt->Pause = SecPause;
|
|
pRes->pCountInt->Continue = SecContinue;
|
|
pRes->iCallbackCounter = 20;
|
|
|
|
pRes->setMode = SecCtrSetMode;
|
|
pRes->getMode = SecCtrGetMode;
|
|
pRes->getNMonitor = SecCtrGetNMonitor;
|
|
pRes->setPreset = SecCtrSetPreset;
|
|
pRes->getPreset = SecCtrGetPreset;
|
|
pRes->getControlValue = SecCtrGetControlValue;
|
|
pRes->getCounts = SecCtrGetCounts;
|
|
pRes->getMonitor = SecCtrGetMonitor;
|
|
pRes->setMonitor = SecCtrSetMonitor;
|
|
pRes->getTime = SecCtrGetTime;
|
|
|
|
pRes->pCall = CreateCallBackInterface();
|
|
|
|
pRes->isUpToDate = 1;
|
|
pRes->iExponent = 0;
|
|
pRes->name = strdup(name);
|
|
|
|
node = MakeHipadabaNode(name,HIPNONE, 0);
|
|
pRes->pDes->parNode = node;
|
|
pRes->objectNode = node;
|
|
|
|
child = MakeSICSHdbPar("time", usInternal, MakeHdbFloat(.0));
|
|
if (child == NULL) {
|
|
return NULL;
|
|
}
|
|
AddHipadabaChild(node, child, NULL);
|
|
|
|
child = MakeSICSHdbPar("preset", usUser, MakeHdbFloat(.0));
|
|
if (child == NULL) {
|
|
return NULL;
|
|
}
|
|
SetHdbProperty(child, "__save", "true");
|
|
AddHipadabaChild(node, child, NULL);
|
|
|
|
child = MakeSICSHdbPar("mode", usUser, MakeHdbText("monitor"));
|
|
if (child == NULL) {
|
|
return NULL;
|
|
}
|
|
SetHdbProperty(child, "__save", "true");
|
|
SetHdbProperty(child, "values", "timer,monitor");
|
|
PrependHipadabaCallback(child,MakeHipadabaCallback(SICSValueCheckCallback,
|
|
NULL,NULL));
|
|
AddHipadabaChild(node, child, NULL);
|
|
|
|
child = MakeSICSHdbPar("status", usInternal, MakeHdbText("idle"));
|
|
if (child == NULL) {
|
|
return NULL;
|
|
}
|
|
AppendHipadabaCallback(child,
|
|
MakeHipadabaCallback(SecStatusCallback, pRes,
|
|
NULL));
|
|
AddHipadabaChild(node, child, NULL);
|
|
|
|
child = MakeSICSHdbPar("error", usInternal, MakeHdbText("None"));
|
|
if (child == NULL) {
|
|
return NULL;
|
|
}
|
|
AddHipadabaChild(node, child, NULL);
|
|
|
|
child = MakeSICSHdbPar("control", usUser, MakeHdbFloat(.0));
|
|
if (child == NULL) {
|
|
return NULL;
|
|
}
|
|
AddHipadabaChild(node, child, NULL);
|
|
|
|
child = MakeSICSHdbPar("values", usInternal,
|
|
makeHdbValue(HIPINTAR, length));
|
|
if (child == NULL) {
|
|
return NULL;
|
|
}
|
|
AddHipadabaChild(node, child, NULL);
|
|
|
|
child = MakeSICSHdbPar("exponent", usUser,
|
|
MakeHdbInt(0));
|
|
if (child == NULL) {
|
|
return NULL;
|
|
}
|
|
SetHdbProperty(child, "__save", "true");
|
|
AddHipadabaChild(node, child, NULL);
|
|
|
|
child = AddSICSHdbPar(node,"count", usUser, MakeSICSFunc(CountCmd));
|
|
AddSICSHdbPar(child, "preset", usUser, MakeHdbFloat(2));
|
|
|
|
child = AddSICSHdbPar(node,"countnb", usUser, MakeSICSFunc(CountNBCmd));
|
|
AddSICSHdbPar(child, "preset", usUser, MakeHdbFloat(2));
|
|
|
|
child = AddSICSHdbPar(node,"getmonitor", usSpy, MakeSICSFunc(GetMonitorCmd));
|
|
AddSICSHdbPar(child, "no", usSpy, MakeHdbInt(1));
|
|
child = AddSICSHdbPar(node,"getcounts", usUser, MakeSICSFunc(GetCountsCmd));
|
|
|
|
child = AddSICSHdbPar(node,"stop", usUser, MakeSICSFunc(StopCmd));
|
|
child = AddSICSHdbPar(node,"pause", usUser, MakeSICSFunc(PauseCmd));
|
|
child = AddSICSHdbPar(node,"continue", usUser, MakeSICSFunc(ContinueCmd));
|
|
child = AddSICSHdbPar(node,"interest", usUser, MakeSICSFunc(InterestCmd));
|
|
child = AddSICSHdbPar(node,"countstatus", usUser, MakeSICSFunc(CountStatusCmd));
|
|
|
|
return pRes;
|
|
}
|
|
/*--------------------------------------------------------------------------*/
|
|
int MakeSecCter(SConnection * pCon, SicsInterp * pSics, void *pData,
|
|
int argc, char *argv[])
|
|
{
|
|
pCounter pRes = NULL;
|
|
int status, length;
|
|
pHdb node, child;
|
|
|
|
if(argc < 3) {
|
|
SCWrite(pCon,"ERROR: need at least a name and length to create a counter",
|
|
eError);
|
|
return 0;
|
|
}
|
|
length = atoi(argv[2]);
|
|
|
|
pRes = CreateSecCounter(pCon,"SingleCounter", argv[1], length);
|
|
if(pRes == NULL){
|
|
return 0;
|
|
}
|
|
|
|
status =
|
|
AddCommand(pSics, argv[1], InterInvokeSICSOBJ, DeleteCounter,
|
|
(void *) pRes);
|
|
if (status != 1) {
|
|
SCPrintf(pCon,eError, "ERROR: duplicate command %s not created", argv[1]);
|
|
return 0;
|
|
}
|
|
return 1;
|
|
}
|