- Refactored histogram memory code a little

- motor driver for ECB now fully working
- Fixed an anticollider bug
- Untested version of a driver for the Risoe TDC histogram memory
This commit is contained in:
cvs
2003-01-31 16:23:54 +00:00
parent b1fd8e77ac
commit f51588e2a7
26 changed files with 1602 additions and 784 deletions

361
hmdata.c Normal file
View File

@ -0,0 +1,361 @@
/*-----------------------------------------------------------------------
This is a data handling class for histogram memory data.
For more information see hmdata.tex.
copyright: see file COPYRIGHT
Mark Koennecke, January 2003
-------------------------------------------------------------------------*/
#include <stdlib.h>
#include <assert.h>
#include <math.h>
#include "fortify.h"
#include "hmdata.h"
#include "HistMem.h"
#include "HistMem.i"
#include "HistDriv.i"
#include "countdriv.h"
/*----------------------------------------------------------------------*/
pHMdata makeHMData(void) {
pHMdata self = NULL;
self = (pHMdata)malloc(sizeof(HMdata));
if(self == NULL){
return NULL;
}
memset(self,0,sizeof(HMdata));
self->nTimeChan = 1;
return self;
}
/*---------------------------------------------------------------------*/
void killHMData(pHMdata self){
if(self->localBuffer != NULL){
free(self->localBuffer);
}
free(self);
}
/*----------------------------------------------------------------------*/
static int resizeBuffer(pHMdata self){
long size;
int i;
size = 1;
for(i = 0; i < self->rank; i++){
size *= self->iDim[i];
}
if(self->tofMode){
size *= self->nTimeChan;
}
if(self->localBuffer != NULL){
free(self->localBuffer);
self->localBuffer = NULL;
}
self->localBuffer = (HistInt *)malloc(size*sizeof(HistInt));
if(!self->localBuffer){
return 0;
}
memset(self->localBuffer,0,size*sizeof(HistInt));
return 1;
}
/*-----------------------------------------------------------------------*/
int configureHMdata(pHMdata self, pStringDict pOpt,
SConnection *pCon){
int status, i;
float fVal;
char pValue[80];
self->tofMode = 0;
status = StringDictGetAsNumber(pOpt,"rank",&fVal);
if(!status){
SCWrite(pCon,"ERROR: critical configuration problem: no rank found",
eError);
return 0;
}
self->rank = (int)rint(fVal);
for(i = 0; i < self->rank; i++){
sprintf(pValue,"dim%1.1d",i);
status = StringDictGetAsNumber(pOpt,pValue,&fVal);
if(!status){
sprintf(pValue,"ERROR dimension %d not found!!", i);
return 0;
}
self->iDim[i] = (int)rint(fVal);
}
status = StringDictGetAsNumber(pOpt,"update",&fVal);
if(!status){
self->updateIntervall = 0; /* no buffering */
} else {
self->updateIntervall = (int)rint(fVal);
}
/*
note: remove update request in histmem.c
*/
if(self->updateIntervall > 0){
/*
we do buffer
*/
status = resizeBuffer(self);
if(!status){
SCWrite(pCon,"ERROR: failed to resize buffer",eError);
return 0;
}
}
return 1;
}
/*----------------------------------------------------------------------*/
int genTimeBinning(pHMdata self, float start, float step, int noSteps){
int i;
if(noSteps >= MAXCHAN){
return 0;
}
for(i = 0; i < noSteps; i++){
self->timeBinning[i] = start + i*step;
}
self->tofMode = 1;
self->nTimeChan = noSteps;
return resizeBuffer(self);
}
/*----------------------------------------------------------------------*/
int setTimeBin(pHMdata self, int index, float value){
if(index > 0 || index < MAXCHAN){
self->timeBinning[index] = value;
return 1;
} else {
return 0;
}
self->tofMode = 1;
if(index > self->nTimeChan){
self->nTimeChan = index;
return resizeBuffer(self);
}
return 1;
}
/*-------------------------------------------------------------------*/
int isInTOFMode(pHMdata self){
return self->tofMode;
}
/*---------------------------------------------------------------------*/
int getNoOfTimebins(pHMdata self){
return self->nTimeChan;
}
/*---------------------------------------------------------------------*/
float *getTimeBinning(pHMdata self){
return self->timeBinning;
}
/*-------------------------------------------------------------------*/
void clearTimeBinning(pHMdata self){
self->nTimeChan = 1;
self->tofMode = 0;
resizeBuffer(self);
}
/*--------------------------------------------------------------------*/
void getHMDataDim(pHMdata self, int iDim[MAXDIM], int *rank){
memcpy(iDim,self->iDim,self->rank*sizeof(int));
*rank = self->rank;
}
/*---------------------------------------------------------------------*/
long getHMDataLength(pHMdata self){
long length = 1;
int i;
for(i = 0; i < self->rank; i++){
length *= self->iDim[i];
}
if(self->tofMode){
length *= self->nTimeChan;
}
return length;
}
/*---------------------------------------------------------------------*/
void updateHMData(pHMdata self){
self->updateFlag = 1;
}
/*--------------------------------------------------------------------
The idea here is that upper level code sets the updateFlag through
updateHMData (above) whenever the HM changes (counts). If this flag is set
the next call to get getHMDataHistogram will read a new copy from the HM.
After reading nextUpdate is set to time + updateIntervall. In order to
prevent clients hammering the HM nextUpdate is checked as well.
updateIntervall can be set to a reasonable time intervall between updates in seconds. If updateIntervall is 0, a direct read is always perfomed.
If this system needs to be bypassed altogether (because there is no memory
to buffer all HM) use GetHistogramDirect (histogram.c) instead which acts
on the driver level.
--------------------------------------------------------------------------*/
static int mustUpdate(pHMdata self){
if(self->updateFlag == 1 && time(NULL) >= self->nextUpdate){
return 1;
} else {
return 0;
}
}
/*---------------------------------------------------------------------*/
static int updateHMbuffer(pHistMem hist, int bank, SConnection *pCon){
int status, iErr, i;
char pError[80], pBueffel[256];
pHMdata self = hist->pDriv->data;
assert(self);
for(i = 0; i < 3; i++){
status = hist->pDriv->GetHistogram(hist->pDriv,pCon,
bank,0,getHMDataLength(self),
self->localBuffer);
if(status == OKOK){
self->nextUpdate = time(NULL) + self->updateIntervall;
self->updateFlag = 0;
break;
} else{
status = hist->pDriv->GetError(hist->pDriv,&iErr,pError,79);
sprintf(pBueffel,"ERROR: %s ",pError);
SCWrite(pCon,pBueffel,eError);
status = hist->pDriv->TryAndFixIt(hist->pDriv,iErr);
if(status == COTERM) {
return 0;
}
}
}
if(status == OKOK){
return 1;
} else {
return HWFault;
}
}
/*----------------------------------------------------------------------*/
int getHMDataHistogram(pHistMem hist, SConnection *pCon,
int bank, int start, int length,
HistInt *lData){
int status;
pHMdata self = hist->pDriv->data;
HistInt *lStart;
assert(self);
if(self->localBuffer == NULL){
resizeBuffer(self);
}
/*
update buffer if necessary
*/
if(mustUpdate(self)){
status = updateHMbuffer(hist,bank,pCon);
if(status != OKOK){
return status;
}
}
/*
copy buffered data to lData
*/
lStart = self->localBuffer + start;
if(start + length > getHMDataLength(self)){
length = getHMDataLength(self) - start - 1;
}
memcpy(lData,lStart,length*sizeof(HistInt));
return 1;
}
/*-----------------------------------------------------------------------*/
HistInt *getHMDataBufferPointer(pHistMem hist,SConnection *pCon){
int status;
pHMdata self = hist->pDriv->data;
assert(self);
if(self->localBuffer == NULL){
resizeBuffer(self);
}
/*
update buffer if necessary
*/
if(mustUpdate(self)){
status = updateHMbuffer(hist,0,pCon);
if(status != OKOK){
return NULL;
}
}
return self->localBuffer;
}
/*------------------------------------------------------------------------*/
static long SumRow(HistInt *iData, int iDataLength, int iStart, int iEnd){
int i;
long lSum;
if(iEnd > iDataLength){
return -1;
}
lSum = 0;
for(i = iStart; i < iEnd; i++){
lSum += iData[i];
}
return lSum;
}
/*--------------------------------------------------------------------------*/
long sumHMDataRectangle(pHistMem hist, SConnection *pCon,
int iStart[MAXDIM], int iEnd[MAXDIM]) {
HistInt *iData;
pHMdata self = hist->pDriv->data;
int i, iHistLength, status, iIndex;
char pBueffel[256];
long lSum;
assert(self);
/*
error checking
*/
for(i = 0; i < self->rank; i++){
if( (iStart[i] < 0) || (iStart[i] > self->iDim[i]) ) {
sprintf(pBueffel,"ERROR: %d is out of data dimension range",
iStart[i]);
SCWrite(pCon,pBueffel,eError);
return -1;
}
if( (iEnd[i] < 0) || (iEnd[i] > self->iDim[i]) ){
sprintf(pBueffel,"ERROR: %d is out of data dimension range",
iEnd[i]);
SCWrite(pCon,pBueffel,eError);
return -1;
}
}
/*
get an update of the HM if necessary
*/
if(mustUpdate(self)){
status = updateHMbuffer(hist,0,pCon);
if(status != OKOK){
return -1;
}
}
iHistLength = getHMDataLength(self);
/* actually sum */
switch(self->rank)
{
case 1:
lSum = SumRow(self->localBuffer, iHistLength,
iStart[0], iEnd[0]);
break;
case 2:
lSum = 0;
for(i = iStart[0]; i < iEnd[0]; i++){
iIndex = i*self->iDim[1];
lSum += SumRow(self->localBuffer,iHistLength,
iIndex+iStart[1], iIndex+iEnd[1]);
}
break;
default:
sprintf(pBueffel,
"ERROR: summing in %d dimensions not yet implemented",
self->rank);
SCWrite(pCon,pBueffel,eError);
lSum = -1;
break;
}
return lSum;
}