- Added a multiple histogram memory control module. This required a
tiny change in the countable interface which in turn required updating of header file includes in a lot of files. - Some small fixes to TRICS writing as well.
This commit is contained in:
349
hmcontrol.c
Normal file
349
hmcontrol.c
Normal file
@ -0,0 +1,349 @@
|
||||
/*------------------------------------------------------------------------
|
||||
H M C O N T R O L
|
||||
|
||||
A module for coordinating several counters and histogram
|
||||
memories. One of the counters is the master counter and the rest are
|
||||
slaves which have to be kept in sync with the master in their
|
||||
operations.
|
||||
|
||||
copyright: see copyright.h
|
||||
|
||||
Mark Koennecke, June 2001
|
||||
-------------------------------------------------------------------------*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <assert.h>
|
||||
#include <tcl.h>
|
||||
#include "fortify.h"
|
||||
#include "hmcontrol.h"
|
||||
#include "devexec.h"
|
||||
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
static void *HMCGetInterface(void *pData, int ID)
|
||||
{
|
||||
pHMcontrol self = NULL;
|
||||
|
||||
self = (pHMcontrol)pData;
|
||||
assert(self);
|
||||
|
||||
if(ID == COUNTID)
|
||||
return self->pCount;
|
||||
else
|
||||
return NULL;
|
||||
}
|
||||
/*------------------------------------------------------------------------*/
|
||||
static int HMCHalt(void *pData)
|
||||
{
|
||||
int i, retVal = OKOK, status;
|
||||
pHMcontrol self = NULL;
|
||||
|
||||
self = (pHMcontrol)pData;
|
||||
assert(self);
|
||||
|
||||
for(i = 0; i < self->nSlaves; i++)
|
||||
{
|
||||
status = self->slaves[i]->Halt(self->slaveData[i]);
|
||||
if(status != OKOK)
|
||||
retVal = status;
|
||||
}
|
||||
return retVal;
|
||||
}
|
||||
/*-----------------------------------------------------------------------*/
|
||||
static int HMCStart(void *pData, SConnection *pCon)
|
||||
{
|
||||
int i, status;
|
||||
pHMcontrol self = NULL;
|
||||
|
||||
self = (pHMcontrol)pData;
|
||||
assert(self);
|
||||
|
||||
for(i = 0; i < self->nSlaves; i++)
|
||||
{
|
||||
status = self->slaves[i]->StartCount(self->slaveData[i],pCon);
|
||||
if(status != OKOK)
|
||||
{
|
||||
HMCHalt(self);
|
||||
return status;
|
||||
}
|
||||
}
|
||||
return OKOK;
|
||||
}
|
||||
/*----------------------------------------------------------------------*/
|
||||
static int HMCStatus(void *pData, SConnection *pCon)
|
||||
{
|
||||
int status;
|
||||
pHMcontrol self = NULL;
|
||||
|
||||
self = (pHMcontrol)pData;
|
||||
assert(self);
|
||||
|
||||
status = self->slaves[0]->CheckCountStatus(self->slaveData[0],pCon);
|
||||
if(status == HWIdle || status == HWFault)
|
||||
{
|
||||
/*
|
||||
stop counting on slaves when finished or when an error
|
||||
occurred.
|
||||
*/
|
||||
HMCHalt(self);
|
||||
}
|
||||
return status;
|
||||
}
|
||||
/*-------------------------------------------------------------------------*/
|
||||
static int HMCPause(void *pData, SConnection *pCon)
|
||||
{
|
||||
int i, status;
|
||||
pHMcontrol self = NULL;
|
||||
|
||||
self = (pHMcontrol)pData;
|
||||
assert(self);
|
||||
|
||||
for(i = 0; i < self->nSlaves; i++)
|
||||
{
|
||||
status = self->slaves[i]->Pause(self->slaveData[i],pCon);
|
||||
if(status != OKOK)
|
||||
{
|
||||
HMCHalt(self);
|
||||
return status;
|
||||
}
|
||||
}
|
||||
return OKOK;
|
||||
}
|
||||
/*------------------------------------------------------------------------*/
|
||||
static int HMCContinue(void *pData, SConnection *pCon)
|
||||
{
|
||||
int i, status;
|
||||
pHMcontrol self = NULL;
|
||||
|
||||
self = (pHMcontrol)pData;
|
||||
assert(self);
|
||||
|
||||
for(i = 0; i < self->nSlaves; i++)
|
||||
{
|
||||
status = self->slaves[i]->Continue(self->slaveData[i],pCon);
|
||||
if(status != OKOK)
|
||||
{
|
||||
HMCHalt(self);
|
||||
return status;
|
||||
}
|
||||
}
|
||||
return OKOK;
|
||||
}
|
||||
/*----------------------------------------------------------------------*/
|
||||
static int HMCTransfer(void *pData, SConnection *pCon)
|
||||
{
|
||||
int i, retVal = OKOK, status;
|
||||
pHMcontrol self = NULL;
|
||||
char pBueffel[132];
|
||||
|
||||
self = (pHMcontrol)pData;
|
||||
assert(self);
|
||||
|
||||
for(i = 0; i < self->nSlaves; i++)
|
||||
{
|
||||
status = self->slaves[i]->TransferData(self->slaveData[i], pCon);
|
||||
if(status != OKOK)
|
||||
{
|
||||
retVal = status;
|
||||
sprintf(pBueffel,"WARNING: slave histogram %d failed to transfer data",
|
||||
i);
|
||||
SCWrite(pCon,pBueffel,eWarning);
|
||||
}
|
||||
}
|
||||
return retVal;
|
||||
}
|
||||
/*-----------------------------------------------------------------------*/
|
||||
static void HMCParameter(void *pData, float fPreset, CounterMode eMode )
|
||||
{
|
||||
int i;
|
||||
pHMcontrol self = NULL;
|
||||
|
||||
self = (pHMcontrol)pData;
|
||||
assert(self);
|
||||
|
||||
for(i = 0; i < self->nSlaves; i++)
|
||||
{
|
||||
self->slaves[i]->SetCountParameters(self->slaveData[i], fPreset,
|
||||
eMode);
|
||||
}
|
||||
}
|
||||
/*----------------------------------------------------------------------*/
|
||||
static void KillHMcontrol(void *pData)
|
||||
{
|
||||
pHMcontrol self;
|
||||
|
||||
self = (pHMcontrol)pData;
|
||||
if(!self)
|
||||
return;
|
||||
|
||||
if(self->pDes)
|
||||
DeleteDescriptor(self->pDes);
|
||||
if(self->pCount)
|
||||
free(self->pCount);
|
||||
free(self);
|
||||
}
|
||||
/*-----------------------------------------------------------------------*/
|
||||
int MakeHMControl(SConnection *pCon, SicsInterp *pSics,
|
||||
void *pData, int argc, char *argv[])
|
||||
{
|
||||
int i, status;
|
||||
pHMcontrol pNew = NULL;
|
||||
char pBueffel[132];
|
||||
CommandList *pCom;
|
||||
pICountable pCount;
|
||||
|
||||
/*
|
||||
need at least two parameters
|
||||
*/
|
||||
if(argc < 3)
|
||||
{
|
||||
SCWrite(pCon,"ERROR: insufficient number of arguments to MakeHMControl",
|
||||
eError);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
allocate our data structure
|
||||
*/
|
||||
pNew = (pHMcontrol)malloc(sizeof(HMcontrol));
|
||||
if(!pNew)
|
||||
{
|
||||
SCWrite(pCon,"ERROR: out of memory in MakeHMControl",eError);
|
||||
return 0;
|
||||
}
|
||||
memset(pNew,0,sizeof(HMcontrol));
|
||||
pNew->pDes = CreateDescriptor("HMcontrol");
|
||||
pNew->pCount = CreateCountableInterface();
|
||||
if(!pNew->pDes || ! pNew->pCount)
|
||||
{
|
||||
SCWrite(pCon,"ERROR: out of memory in MakeHMControl",eError);
|
||||
KillHMcontrol(pNew);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
assign interface functions
|
||||
*/
|
||||
pNew->pDes->GetInterface = HMCGetInterface;
|
||||
pNew->pCount->Halt = HMCHalt;
|
||||
pNew->pCount->StartCount = HMCStart;
|
||||
pNew->pCount->CheckCountStatus = HMCStatus;
|
||||
pNew->pCount->Pause = HMCPause;
|
||||
pNew->pCount->Continue = HMCContinue;
|
||||
pNew->pCount->TransferData = HMCTransfer;
|
||||
pNew->pCount->SetCountParameters = HMCParameter;
|
||||
|
||||
/*
|
||||
now loop through the remaining arguments, thereby entering them into
|
||||
the slave list.
|
||||
*/
|
||||
for(i = 2; i < argc; i++)
|
||||
{
|
||||
pCom = FindCommand(pSics,argv[i]);
|
||||
if(!pCom)
|
||||
{
|
||||
sprintf(pBueffel,"ERROR: object %s not found in MakeHMcontrol",
|
||||
argv[i]);
|
||||
SCWrite(pCon,pBueffel,eError);
|
||||
continue;
|
||||
}
|
||||
pCount = GetCountableInterface(pCom->pData);
|
||||
if(!pCount)
|
||||
{
|
||||
sprintf(pBueffel,"ERROR: object %s is NOT countable",
|
||||
argv[i]);
|
||||
SCWrite(pCon,pBueffel,eError);
|
||||
continue;
|
||||
}
|
||||
pNew->slaves[pNew->nSlaves] = pCount;
|
||||
pNew->slaveData[pNew->nSlaves] = pCom->pData;
|
||||
pNew->nSlaves++;
|
||||
}
|
||||
|
||||
/*
|
||||
now install our action command and we are done
|
||||
*/
|
||||
status = AddCommand(pSics,argv[1],HMControlAction,KillHMcontrol,
|
||||
pNew);
|
||||
if(!status)
|
||||
{
|
||||
sprintf(pBueffel,"ERROR: duplicate command %s not created",argv[1]);
|
||||
SCWrite(pCon,pBueffel,eError);
|
||||
KillHMcontrol(pNew);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
/*-----------------------------------------------------------------------
|
||||
Syntax: whatever start preset mode
|
||||
------------------------------------------------------------------------*/
|
||||
int HMControlAction(SConnection *pCon, SicsInterp *pSics,
|
||||
void *pData, int argc, char *argv[])
|
||||
{
|
||||
pHMcontrol self;
|
||||
char pBueffel[132];
|
||||
double dPreset;
|
||||
CounterMode eMode;
|
||||
int status;
|
||||
|
||||
/*
|
||||
checks
|
||||
*/
|
||||
self = (pHMcontrol)pData;
|
||||
assert(self);
|
||||
if(argc < 4)
|
||||
{
|
||||
sprintf("ERROR: Usage %s start preset mode", argv[0]);
|
||||
SCWrite(pCon,pBueffel,eError);
|
||||
return 0;
|
||||
}
|
||||
strtolower(argv[1]);
|
||||
if(strcmp(argv[1],"start") == 0)
|
||||
{
|
||||
/*
|
||||
interpret count parameters
|
||||
*/
|
||||
status = Tcl_GetDouble(pSics->pTcl,argv[2],&dPreset);
|
||||
if(status != TCL_OK)
|
||||
{
|
||||
sprintf(pBueffel,"ERROR: failed to convert %s to number",
|
||||
argv[2]);
|
||||
SCWrite(pCon,pBueffel,eError);
|
||||
return 0;
|
||||
}
|
||||
strtolower(argv[3]);
|
||||
if(strcmp(argv[3],"timer") == 0)
|
||||
eMode = eTimer;
|
||||
else if(strcmp(argv[3],"monitor") == 0)
|
||||
eMode = ePreset;
|
||||
else
|
||||
{
|
||||
sprintf(pBueffel,"ERROR: %s is no recognized count mode",argv[3]);
|
||||
SCWrite(pCon,pBueffel,eError);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
set count parameters and go
|
||||
*/
|
||||
self->pCount->SetCountParameters(self,(float)dPreset,eMode);
|
||||
status = StartDevice(pServ->pExecutor,"hmcontrol",self->pDes,
|
||||
self,pCon,99);
|
||||
if(!status)
|
||||
{
|
||||
SCWrite(pCon,"ERROR: failed to start counting",eError);
|
||||
return 0;
|
||||
}
|
||||
SCSendOK(pCon);
|
||||
}
|
||||
else
|
||||
{
|
||||
SCWrite(pCon,"ERROR: subcommand not recognized",eError);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user