- 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

View File

@ -1,5 +1,5 @@
#line 478 "histogram.w" #line 461 "histogram.w"
/*--------------------------------------------------------------------------- /*---------------------------------------------------------------------------
H I S T D R I V H I S T D R I V
@ -10,22 +10,13 @@
----------------------------------------------------------------------------*/ ----------------------------------------------------------------------------*/
#ifndef SICSHISTDRIV #ifndef SICSHISTDRIV
#define SICSHISTDRIV #define SICSHISTDRIV
#define MAXCHAN 16834 #include "hmdata.h"
#line 83 "histogram.w" #line 89 "histogram.w"
typedef struct __HistDriver { typedef struct __HistDriver {
/* configuration data */ pHMdata data;
HistMode eHistMode;
OverFlowMode eFlow;
int iRank;
int iDims[MAXDIM];
int nDim;
int iLength;
int iBinWidth;
float fTime[MAXCHAN];
int iTimeChan;
/* counting operations data */ /* counting operations data */
CounterMode eCount; CounterMode eCount;
float fCountPreset; float fCountPreset;
@ -77,17 +68,17 @@
void *pPriv; void *pPriv;
} HistDriver; } HistDriver;
#line 490 "histogram.w" #line 473 "histogram.w"
#line 240 "histogram.w" #line 228 "histogram.w"
pHistDriver CreateHistDriver(pStringDict pDict); pHistDriver CreateHistDriver(pStringDict pDict);
void DeleteHistDriver(pHistDriver self); void DeleteHistDriver(pHistDriver self);
int HistDriverConfig(pHistDriver self, pStringDict pOpt, int HistDriverConfig(pHistDriver self, pStringDict pOpt,
SConnection *pCon); SConnection *pCon);
#line 491 "histogram.w" #line 474 "histogram.w"
#endif #endif

View File

@ -1,5 +1,5 @@
#line 451 "histogram.w" #line 434 "histogram.w"
/*-------------------------------------------------------------------------- /*--------------------------------------------------------------------------
H I S T M E M H I S T M E M
@ -33,7 +33,7 @@
eSANSTOF eSANSTOF
} HistMode; } HistMode;
#line 35 "histogram.w" #line 36 "histogram.w"
typedef enum { typedef enum {
eOIgnore, eOIgnore,
@ -42,22 +42,22 @@
eReflect eReflect
} OverFlowMode; } OverFlowMode;
#line 471 "histogram.w" #line 454 "histogram.w"
/*--------------------------------------------------------------------------*/ /*--------------------------------------------------------------------------*/
#line 304 "histogram.w" #line 287 "histogram.w"
pHistMem CreateHistMemory(char *drivername); pHistMem CreateHistMemory(char *drivername);
void DeleteHistMemory(void *self); void DeleteHistMemory(void *self);
#line 320 "histogram.w" #line 303 "histogram.w"
int HistGetOption(pHistMem self, char *name, char *result, int iResultLen); int HistGetOption(pHistMem self, char *name, char *result, int iResultLen);
int HistSetOption(pHistMem self, char *name, char *value); int HistSetOption(pHistMem self, char *name, char *value);
int HistConfigure(pHistMem self, SConnection *pCon, SicsInterp *pSics); int HistConfigure(pHistMem self, SConnection *pCon, SicsInterp *pSics);
#line 348 "histogram.w" #line 331 "histogram.w"
float GetHistPreset(pHistMem self); float GetHistPreset(pHistMem self);
int SetHistPreset(pHistMem self, float fVal); int SetHistPreset(pHistMem self, float fVal);
@ -72,7 +72,7 @@
int HistBlockCount(pHistMem self, SConnection *pCon); int HistBlockCount(pHistMem self, SConnection *pCon);
#line 377 "histogram.w" #line 360 "histogram.w"
int SetHistogram(pHistMem self, SConnection *pCon, int SetHistogram(pHistMem self, SConnection *pCon,
int i,int iStart, int iEnd, HistInt *lData); int i,int iStart, int iEnd, HistInt *lData);
@ -84,7 +84,7 @@
HistInt *lData, int iDataLen); HistInt *lData, int iDataLen);
int PresetHistogram(pHistMem self, SConnection *pCon, HistInt lVal); int PresetHistogram(pHistMem self, SConnection *pCon, HistInt lVal);
#line 420 "histogram.w" #line 403 "histogram.w"
int MakeHistMemory(SConnection *pCon, SicsInterp *pSics, void *pData, int MakeHistMemory(SConnection *pCon, SicsInterp *pSics, void *pData,
int argc, char *argv[]); int argc, char *argv[]);
@ -93,7 +93,7 @@
int argc, char *argv[]); int argc, char *argv[]);
#line 473 "histogram.w" #line 456 "histogram.w"
#endif #endif

View File

@ -1,5 +1,5 @@
#line 496 "histogram.w" #line 479 "histogram.w"
/*--------------------------------------------------------------------------- /*---------------------------------------------------------------------------
H I S T M E M -- Internal H I S T M E M -- Internal
@ -11,7 +11,7 @@
#ifndef SICSHISTMEMINT #ifndef SICSHISTMEMINT
#define SICSHISTMEMINT #define SICSHISTMEMINT
#line 262 "histogram.w" #line 250 "histogram.w"
typedef struct __HistMem { typedef struct __HistMem {
pObjectDescriptor pDes; pObjectDescriptor pDes;
@ -22,14 +22,9 @@
pICountable pCountInt; pICountable pCountInt;
pICallBack pCall; pICallBack pCall;
pStringDict pOption; pStringDict pOption;
HistInt *iLocalData;
int iLocalLength;
int iLocalUpdate;
time_t tLocal;
int iUpdateIntervall;
} HistMem; } HistMem;
#line 506 "histogram.w" #line 489 "histogram.w"
#endif #endif

View File

@ -59,7 +59,7 @@ SOBJ = network.o ifile.o conman.o SCinter.o splitter.o passwd.o \
hmcontrol.o userscan.o slsmagnet.o rs232controller.o lomax.o \ hmcontrol.o userscan.o slsmagnet.o rs232controller.o lomax.o \
polterwrite.o fourlib.o motreg.o motreglist.o anticollider.o \ polterwrite.o fourlib.o motreg.o motreglist.o anticollider.o \
s_rnge.o sig_die.o gpibcontroller.o $(NIOBJ) ecb.o ecbdriv.o \ s_rnge.o sig_die.o gpibcontroller.o $(NIOBJ) ecb.o ecbdriv.o \
ecbcounter.o ecbcounter.o hmdata.o tdchm.o
MOTOROBJ = motor.o el734driv.o simdriv.o el734dc.o pipiezo.o pimotor.o MOTOROBJ = motor.o el734driv.o simdriv.o el734dc.o pipiezo.o pimotor.o
COUNTEROBJ = countdriv.o simcter.o counter.o COUNTEROBJ = countdriv.o simcter.o counter.o

View File

@ -105,7 +105,7 @@ static long ColliderSetValue(void *pData, SConnection *pCon, float fTarget){
*/ */
LLDdelete(self->sequenceList); LLDdelete(self->sequenceList);
self->sequenceList = LLDcreate(sizeof(Sequence)); self->sequenceList = LLDcreate(sizeof(Sequence));
self->level = 0; self->level = -1; /* otherwise level 0 will not be started */
/* /*
evaluate colliderScript evaluate colliderScript

View File

@ -85,5 +85,4 @@
returns the current length of the dynamic string. returns the current length of the dynamic string.
*/ */
#endif #endif

36
ecb.c
View File

@ -20,8 +20,9 @@
#include "ecb.i" #include "ecb.i"
/*------------- private defines and error codes ------------------------*/ /*------------- private defines and error codes ------------------------*/
#define ACKN ('\6') /* Acknowledge character */ #define ACKN ('\6') /* Acknowledge character */
#define READ_BYTES 3 #define READ_BYTES 3
#define WRITE_BYTES 4 #define WRITE_BYTES 4
#define DMAREAD 5
#define ECB_BYTES 65536L #define ECB_BYTES 65536L
typedef union /* Used to swap bytes in 'address' and 'byte_count' */ typedef union /* Used to swap bytes in 'address' and 'byte_count' */
@ -179,6 +180,33 @@ int ecbRead(pECB self, unsigned short address,
return 1; return 1;
} }
/*----------------------------------------------------------------------*/ /*----------------------------------------------------------------------*/
int ecbDMARead(pECB self, unsigned short address, void *buffer,
unsigned short byteCount){
int status, count;
assert(self != NULL);
assert(self->gpib != NULL);
self->lastError = 0;
status = ecbPrepareIO(self,DMAREAD,address,(unsigned short)byteCount);
if(status <= 0){
return 0;
}
usleep(20*1000);
/*
actual read
*/
status = GPIBread(self->gpib,self->ecbDeviceID, buffer, byteCount);
if(status < 0){
self->lastError = status;
return 0;
}
return 1;
}
/*----------------------------------------------------------------------*/
int ecbWrite(pECB self, unsigned short address, int ecbWrite(pECB self, unsigned short address,
void *buffer, int byteCount){ void *buffer, int byteCount){
@ -317,9 +345,13 @@ int ECBAction(SConnection *pCon, SicsInterp *pSics, void *pData,
return 0; return 0;
} }
sprintf(pBuffer,"%x %x %x %x", sprintf(pBuffer,"%x %x %x %x",
out.d, out.e, out.c, out.c); out.d, out.e, out.b, out.c);
SCWrite(pCon,pBuffer,eValue); SCWrite(pCon,pBuffer,eValue);
return 1; return 1;
} else if(strcmp(argv[1],"clear") == 0){
ecbClear(self);
SCSendOK(pCon);
return 1;
} else { } else {
SCWrite(pCon,"ERROR: ECB does not understand keyword", eError); SCWrite(pCon,"ERROR: ECB does not understand keyword", eError);
return 0; return 0;

2
ecb.h
View File

@ -32,6 +32,8 @@ typedef struct {
void *buffer, int byteCount); void *buffer, int byteCount);
int ecbWrite(pECB self, unsigned short address, int ecbWrite(pECB self, unsigned short address,
void *buffer, int byteCount); void *buffer, int byteCount);
int ecbDMARead(pECB self, unsigned short address, void *buffer,
unsigned short byteCount);
void ecbClear(pECB self); void ecbClear(pECB self);
int fixECBError(pECB self); int fixECBError(pECB self);
void ecbErrorDescription(pECB self, char *buffer, void ecbErrorDescription(pECB self, char *buffer,

7
ecb.w
View File

@ -72,6 +72,8 @@ The function interface then looks like:
void *buffer, int byteCount); void *buffer, int byteCount);
int ecbWrite(pECB self, unsigned short address, int ecbWrite(pECB self, unsigned short address,
void *buffer, int byteCount); void *buffer, int byteCount);
int ecbDMARead(pECB self, unsigned short address, void *buffer,
unsigned short byteCount);
void ecbClear(pECB self); void ecbClear(pECB self);
int fixECBError(pECB self); int fixECBError(pECB self);
void ecbErrorDescription(pECB self, char *buffer, void ecbErrorDescription(pECB self, char *buffer,
@ -89,6 +91,9 @@ content is in in, on success the outpt registers are stored in out.
\item[ecbRead] reads byteCount bytes from the ECB address address into \item[ecbRead] reads byteCount bytes from the ECB address address into
buffer. Please note that address in this contest is an address in the buffer. Please note that address in this contest is an address in the
ECB's memory space and not the GPIB address. ECB's memory space and not the GPIB address.
\item[ecbDMARead] reads byteCount bytes from the ECB DMA address address into
buffer. Please note that address in this contest is an address in the
ECB's memory space and not the GPIB address.
\item[ecbWrite] writes byteCount bytes from buffer to the ECB address \item[ecbWrite] writes byteCount bytes from buffer to the ECB address
address. Please note that address in this contest is an address in the address. Please note that address in this contest is an address in the
ECB's memory space and not the GPIB address. ECB's memory space and not the GPIB address.
@ -102,7 +107,7 @@ ECB problem. Max maxBytes of description are copied into buffer.
There is also an interface to the SICS interpreter for the ECB. This There is also an interface to the SICS interpreter for the ECB. This
can be useful for debugging and testing and as a tool for scripting can be useful for debugging and testing and as a tool for scriptingy
auxiliary equipment controlled through the ECB. The interface to the auxiliary equipment controlled through the ECB. The interface to the
SICS interpreter for the ECB is represented through the ECB Factory SICS interpreter for the ECB is represented through the ECB Factory
function: function:

View File

@ -67,8 +67,9 @@ Parameter indexes in ObPar array and meanings
#define STEPS2DEG 13 /* conversion factor motor steps to Degree */ #define STEPS2DEG 13 /* conversion factor motor steps to Degree */
#define DEG2STEP 14 /* conversion factor from degree to encoder digits */ #define DEG2STEP 14 /* conversion factor from degree to encoder digits */
#define BACKLASH 15 /* motor backlash */ #define BACKLASH 15 /* motor backlash */
#define PORT 17 /* ECB port when multiplexed */
#define MAXPAR 18 /* 1 extra for the sentinel, do not forget to initialize! */ #define MAXPAR 19 /* 1 extra for the sentinel, do not forget to initialize! */
/*------------------------------ ECB defines -------------------------*/ /*------------------------------ ECB defines -------------------------*/
#define MAX_ENCODER 40 #define MAX_ENCODER 40
@ -411,7 +412,8 @@ static int loadMulti(pECBMotDriv self){
mult_chan = (unsigned char)rint(ObVal(self->driverPar,MULTCHAN)); mult_chan = (unsigned char)rint(ObVal(self->driverPar,MULTCHAN));
in.b = -1; /* SET_PORT */ in.b = -1; /* SET_PORT */
in.d = (unsigned char)(multi + (mult_chan << 4)); in.d = (unsigned char)(multi + (mult_chan << 4));
in.e = self->ecbIndex; in.e = (unsigned char)rint(ObVal(self->driverPar,PORT));
in.c = self->ecbIndex;
status = ecbExecute(self->ecb,MOPARA,in,&out); status = ecbExecute(self->ecb,MOPARA,in,&out);
if(status != 1){ if(status != 1){
self->errorCode = COMMERROR; self->errorCode = COMMERROR;
@ -557,7 +559,7 @@ static int controlMotor(pECBMotDriv self, int enable){
*/ */
in.e = 8; in.e = 8;
in.b = 11; /* set control signal */ in.b = 11; /* set control signal */
in.c = -self->ecbIndex; in.c = self->ecbIndex;
status = ecbExecute(self->ecb,MOPARA,in,&out); status = ecbExecute(self->ecb,MOPARA,in,&out);
if(status != 1){ if(status != 1){
self->errorCode = COMMERROR; self->errorCode = COMMERROR;
@ -698,9 +700,6 @@ static int checkStatusResponse(pECBMotDriv self, Z80_reg out){
return HWFault; return HWFault;
} else if(out.b & 32){ } else if(out.b & 32){
return HWBusy; return HWBusy;
} else if(out.b & 64){
self->errorCode = ECBINHIBIT;
return HWFault;
} else if(out.b & 16){ } else if(out.b & 16){
self->errorCode = ECBLIMIT; self->errorCode = ECBLIMIT;
return HWFault; return HWFault;
@ -1142,6 +1141,7 @@ static void initializeParameters(pECBMotDriv self){
ObParInit(self->driverPar,STEPS2DEG,"step2deg",1,usMugger); ObParInit(self->driverPar,STEPS2DEG,"step2deg",1,usMugger);
ObParInit(self->driverPar,DEG2STEP,"step2dig",0,usMugger); ObParInit(self->driverPar,DEG2STEP,"step2dig",0,usMugger);
ObParInit(self->driverPar,BACKLASH,"backlash",0,usMugger); ObParInit(self->driverPar,BACKLASH,"backlash",0,usMugger);
ObParInit(self->driverPar,PORT,"port",0,usMugger);
ObParInit(self->driverPar,MAXPAR-1,"tueet",-100,-100); /* sentinel! */ ObParInit(self->driverPar,MAXPAR-1,"tueet",-100,-100); /* sentinel! */
} }
/*------------------------------------------------------------------------*/ /*------------------------------------------------------------------------*/

View File

@ -63,18 +63,16 @@
return NULL; return NULL;
} }
memset(pNew,0,sizeof(HistDriver)); memset(pNew,0,sizeof(HistDriver));
pNew->data = makeHMData();
if(!pNew->data)
{
free(pNew);
return NULL;
}
/* initialise defaults */ /* initialise defaults */
pNew->eHistMode = eHNormal;
StringDictAddPair(pOption,"histmode","normal");
pNew->eFlow = eOCeil;
StringDictAddPair(pOption,"overflowmode","ceil");
pNew->iRank = 1;
StringDictAddPair(pOption,"rank","1"); StringDictAddPair(pOption,"rank","1");
pNew->iLength = 412;
StringDictAddPair(pOption,"length","412");
pNew->iBinWidth = 16;
StringDictAddPair(pOption,"binwidth","16");
for(i = 0; i < MAXDIM; i++) for(i = 0; i < MAXDIM; i++)
{ {
sprintf(pDim,"dim%1.1d",i); sprintf(pDim,"dim%1.1d",i);
@ -84,8 +82,6 @@
pNew->eCount = eTimer; pNew->eCount = eTimer;
pNew->iReconfig = 1; pNew->iReconfig = 1;
pNew->iUpdate = 0; pNew->iUpdate = 0;
pNew->iTimeChan = 1;
return pNew; return pNew;
} }
@ -98,59 +94,12 @@
{ {
self->FreePrivate(self); self->FreePrivate(self);
} }
if(self->data)
{
killHMData(self->data);
}
free(self); free(self);
} }
/*------------------------------------------------------------------------*/
static char *pHistMode[] = {
"transparent",
"normal",
"tof",
"strobo",
"hrpt",
"psd",
"sanstof",
NULL
};
static HistMode Text2Mode(char *text)
{
int i = 0;
while(pHistMode[i] != NULL)
{
if(strcmp(pHistMode[i],text) == 0)
{
return i;
}
i++;
}
/* not found */
return -1;
}
/*------------------------------------------------------------------------*/
static char *pFlowMode[] = {
"ignore",
"ceil",
"count",
"reflect",
NULL
};
static OverFlowMode Text2Flow(char *text)
{
int i = 0;
while(pFlowMode[i] != NULL)
{
if(strcmp(pFlowMode[i],text) == 0)
{
return i;
}
i++;
}
/* not found */
return -1;
}
/*------------------------------------------------------------------------*/ /*------------------------------------------------------------------------*/
int HistDriverConfig(pHistDriver self, pStringDict pOpt, SConnection *pCon) int HistDriverConfig(pHistDriver self, pStringDict pOpt, SConnection *pCon)
{ {
@ -166,138 +115,5 @@
assert(pOpt); assert(pOpt);
assert(pCon); assert(pCon);
/* enter histmode */ return configureHMdata(self->data,pOpt,pCon);
iRet = StringDictGet(pOpt,"histmode",pValue,79);
if(!iRet)
{
SCWrite(pCon,"ERROR: internal Value not found!",eError);
return 0;
}
strtolower(pValue);
iRet = Text2Mode(pValue);
if(iRet < 0)
{
sprintf(pBueffel,"ERROR: Invalid parameter %s to HistMode",pValue);
SCWrite(pCon,pBueffel,eError);
return 0;
}
self->eHistMode = iRet;
/* handle overflowmode */
iRet = StringDictGet(pOpt,"overflowmode",pValue,79);
if(!iRet)
{
SCWrite(pCon,"ERROR: internal Value not found!",eError);
return 0;
}
strtolower(pValue);
iRet = Text2Flow(pValue);
if(iRet < 0)
{
sprintf(pBueffel,"ERROR: Invalid parameter %s to OverflowMode",pValue);
SCWrite(pCon,pBueffel,eError);
return 0;
}
self->eFlow = iRet;
/* no of hist */
iRet = StringDictGetAsNumber(pOpt,"rank",&fVal);
if(!iRet)
{
iRet = StringDictGet(pOpt,"rank",pValue,79);
if(iRet)
{
sprintf(pBueffel,"ERROR: %s not valid for Rank ",pValue);
SCWrite(pCon,pBueffel,eError);
return 0;
}
else
{
SCWrite(pCon,"ERROR: internal Value not found!",eError);
return 0;
}
}
if(fVal < 0)
{
sprintf(pBueffel,"ERROR: %f is invalid for rank",fVal);
SCWrite(pCon,pBueffel,eError);
return 0;
}
self->iRank = (int)fVal;
/* length */
iRet = StringDictGetAsNumber(pOpt,"length",&fVal);
if(!iRet)
{
iRet = StringDictGet(pOpt,"length",pValue,79);
if(iRet)
{
sprintf(pBueffel,"ERROR: %s not valid for Length ",pValue);
SCWrite(pCon,pBueffel,eError);
return 0;
}
else
{
SCWrite(pCon,"ERROR: internal Value not found!",eError);
return 0;
}
}
if(fVal < 1)
{
sprintf(pBueffel,"ERROR: %f is invalid for Length",fVal);
SCWrite(pCon,pBueffel,eError);
return 0;
}
self->iLength = (int)fVal;
/* BinWidth */
iRet = StringDictGetAsNumber(pOpt,"binwidth",&fVal);
if(!iRet)
{
iRet = StringDictGet(pOpt,"binwidth",pValue,79);
if(iRet)
{
sprintf(pBueffel,"ERROR: %s not valid for BinWidth ",pValue);
SCWrite(pCon,pBueffel,eError);
return 0;
}
else
{
SCWrite(pCon,"ERROR: internal Value not found!",eError);
return 0;
}
}
if(fVal < 1)
{
sprintf(pBueffel,"ERROR: %f is invalid for BinWidth",fVal);
SCWrite(pCon,pBueffel,eError);
return 0;
}
self->iBinWidth = (int)fVal;
/* dimensions */
self->nDim = 0;
for(i = 0; i < MAXDIM; i++)
{
sprintf(pValue,"dim%1.1d",i);
iRet = StringDictGetAsNumber(pOpt,pValue,&fVal);
if(!iRet)
{
if(i < self->iRank)
{
sprintf(pBueffel,"WARNING: dimension %s NOT found",pValue);
SCWrite(pCon,pBueffel,eWarning);
}
}
else
{
if(fVal > 0.)
{
self->nDim++;
self->iDims[i] = (int)fVal;
}
}
}
return 1;
} }

506
histmem.c
View File

@ -62,6 +62,7 @@
#include "dynstring.h" #include "dynstring.h"
#include "event.h" #include "event.h"
#include "status.h" #include "status.h"
#include "tdchm.h"
/* /*
#define LOADDEBUG 1 #define LOADDEBUG 1
*/ */
@ -106,12 +107,13 @@
fprintf(fd,"%s preset %f\n",name,fVal); fprintf(fd,"%s preset %f\n",name,fVal);
/* time binning if TOF */ /* time binning if TOF */
if(self->pDriv->eHistMode == eHTOF) if(isInTOFMode(self->pDriv->data))
{ {
fprintf(fd,"%s genbin %f %f %d\n", fprintf(fd,"%s genbin %f %f %d\n",
name, self->pDriv->fTime[0], name, self->pDriv->data->timeBinning[0],
self->pDriv->fTime[1] - self->pDriv->fTime[0], self->pDriv->data->timeBinning[1] -
self->pDriv->iTimeChan); self->pDriv->data->timeBinning[0],
self->pDriv->data->nTimeChan);
fprintf(fd,"%s init\n",name); fprintf(fd,"%s init\n",name);
} }
@ -167,9 +169,7 @@
iRet = self->pDriv->Start(self->pDriv, pCon); iRet = self->pDriv->Start(self->pDriv, pCon);
if(iRet == OKOK) if(iRet == OKOK)
{ {
self->pDriv->iUpdate = 1; updateHMData(self->pDriv->data);
self->iLocalUpdate = 1;
self->tLocal = time(NULL) + self->iUpdateIntervall;
return iRet; return iRet;
} }
else else
@ -214,7 +214,7 @@
iRet = self->pDriv->Pause(self->pDriv, pCon); iRet = self->pDriv->Pause(self->pDriv, pCon);
if(iRet == OKOK) if(iRet == OKOK)
{ {
self->pDriv->iUpdate = 1; updateHMData(self->pDriv->data);
return iRet; return iRet;
} }
else else
@ -259,7 +259,7 @@
iRet = self->pDriv->Continue(self->pDriv, pCon); iRet = self->pDriv->Continue(self->pDriv, pCon);
if(iRet == OKOK) if(iRet == OKOK)
{ {
self->pDriv->iUpdate = 1; updateHMData(self->pDriv->data);
return iRet; return iRet;
} }
else else
@ -312,20 +312,19 @@
} }
else else
{ {
self->iLocalUpdate = 1; updateHMData(self->pDriv->data);
return HWBusy; return HWBusy;
} }
} }
if(eCt == HWBusy) if(eCt == HWBusy)
self->iLocalUpdate = 1; updateHMData(self->pDriv->data);
if(eCt == HWIdle) if(eCt == HWIdle)
{ {
/* force an update of local histogram data with next /* force an update of local histogram data with next
GetHistogram GetHistogram
*/ */
self->iLocalUpdate = 1; updateHMData(self->pDriv->data);
self->tLocal = 0;
} }
return eCt; return eCt;
@ -426,11 +425,6 @@
pNew->pCountInt->Halt = HistHalt; pNew->pCountInt->Halt = HistHalt;
pNew->pCountInt->Pause = HistPause; pNew->pCountInt->Pause = HistPause;
pNew->pCountInt->Continue = HistContinue; pNew->pCountInt->Continue = HistContinue;
pNew->iLocalData = NULL;
pNew->iLocalLength = 0;
pNew->iUpdateIntervall = 0;
pNew->iLocalUpdate = 1;
pNew->tLocal = 0;
/* initialise options dictionary */ /* initialise options dictionary */
pNew->pOption = CreateStringDict(); pNew->pOption = CreateStringDict();
@ -451,6 +445,10 @@
{ {
pNew->pDriv = CreateSINQDriver(pNew->pOption); pNew->pDriv = CreateSINQDriver(pNew->pOption);
} }
else if(strcmp(driver,"tdc") == 0)
{
pNew->pDriv = MakeTDCHM(pNew->pOption);
}
else /* no driver found */ else /* no driver found */
{ {
DeleteDescriptor(pNew->pDes); DeleteDescriptor(pNew->pDes);
@ -494,10 +492,6 @@
{ {
DeleteStringDict(self->pOption); DeleteStringDict(self->pOption);
} }
if(self->iLocalData)
{
free(self->iLocalData);
}
free(self); free(self);
} }
/*-------------------------------------------------------------------------*/ /*-------------------------------------------------------------------------*/
@ -568,22 +562,6 @@
assert(self); assert(self);
assert(pCon); assert(pCon);
/* handle update intervall */
iRet = StringDictGet(self->pOption,"update",pValue,79);
assert(iRet); /* this is a programming error, we added it
when creating the histogram memory object
*/
iRet = Tcl_GetInt(pSics->pTcl,pValue,&iVal);
if(iRet != TCL_OK)
{
SCWrite(pCon,"WARNING: invalid value for update ignored",
eWarning);
}
else
{
self->iUpdateIntervall = iVal;
}
iRet = HistDriverConfig(self->pDriv,self->pOption,pCon); iRet = HistDriverConfig(self->pDriv,self->pOption,pCon);
if(!iRet) if(!iRet)
{ {
@ -596,8 +574,6 @@
SCWrite(pCon,"ERROR: failed to configure histogram memory",eError); SCWrite(pCon,"ERROR: failed to configure histogram memory",eError);
return 0; return 0;
} }
self->iLocalUpdate = 1;
self->tLocal = 0;
return 1; return 1;
} }
/*--------------------------------------------------------------------------*/ /*--------------------------------------------------------------------------*/
@ -642,124 +618,23 @@
/*--------------------------------------------------------------------------*/ /*--------------------------------------------------------------------------*/
int GetHistDim(pHistMem self, int iDim[MAXDIM], int *nDim) int GetHistDim(pHistMem self, int iDim[MAXDIM], int *nDim)
{ {
int i, myDim;
assert(self); assert(self);
for(i = 0, myDim = 0; i < self->pDriv->nDim; i++) getHMDataDim(self->pDriv->data,iDim,nDim);
if(isInTOFMode(self->pDriv->data))
{ {
if(self->pDriv->iDims[i] > 0) iDim[*nDim] = getNoOfTimebins(self->pDriv->data);
{ *nDim ++;
iDim[i] = self->pDriv->iDims[i];
myDim++;
}
} }
if(self->pDriv->eHistMode == eHTOF
|| self->pDriv->eHistMode == ePSD
|| self->pDriv->eHistMode == eSANSTOF)
{
iDim[myDim] = self->pDriv->iTimeChan;
myDim++;
}
*nDim = myDim;
return 1; return 1;
} }
/*------------------------------------------------------------------------*/
static long SumRow(int *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 HistSum(pHistMem self, SConnection *pCon, long HistSum(pHistMem self, SConnection *pCon,
int iStart[MAXDIM], int iEnd[MAXDIM]) int iStart[MAXDIM], int iEnd[MAXDIM])
{ {
int i, iDataDim[MAXDIM], nDim, iIndex;
long lSum;
char pBueffel[132];
HistInt *iData = NULL;
int iHistLength, iRet;
assert(self); assert(self);
return sumHMDataRectangle(self,pCon,iStart,iEnd);
/* do some serious error checking */
GetHistDim(self,iDataDim,&nDim);
if(nDim <= 0)
{
SCWrite(pCon,"ERROR: Now data dimensions specified, cannot sum",eError);
return -1;
}
for(i = 0; i < nDim; i++)
{
if( (iStart[i] < 0) || (iStart[i] > iDataDim[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] > iDataDim[i]) )
{
sprintf(pBueffel,"ERROR: %d is out of data dimension range",
iEnd[i]);
SCWrite(pCon,pBueffel,eError);
return -1;
}
}
/* get histogram data */
iHistLength = GetHistLength(self);
iData = (HistInt *)malloc(iHistLength*sizeof(HistInt));
if(!iData)
{
SCWrite(pCon,"ERROR: Failed to allocate data in sum", eError);
return -1;
}
iRet = GetHistogram(self,pCon,0,0,iHistLength,iData,
iHistLength*sizeof(HistInt));
if(!iRet)
{
SCWrite(pCon,"ERROR: could not get hold of data to sum",eError);
return -1;
}
/* actually sum */
switch(nDim)
{
case 1:
lSum = SumRow(iData, iHistLength, iStart[0], iEnd[0]);
break;
case 2:
lSum = 0;
for(i = iStart[0]; i < iEnd[0]; i++)
{
iIndex = i*iDataDim[1];
lSum += SumRow(iData,iHistLength,
iIndex+iStart[1], iIndex+iEnd[1]);
}
break;
default:
sprintf(pBueffel,
"ERROR: summing in %d dimensions not yet implemented",
nDim);
SCWrite(pCon,pBueffel,eError);
lSum = -1;
break;
}
free(iData);
return lSum;
} }
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
CounterMode GetHistCountMode(pHistMem self) CounterMode GetHistCountMode(pHistMem self)
@ -806,15 +681,15 @@
const float *GetHistTimeBin(pHistMem self, int *iLength) const float *GetHistTimeBin(pHistMem self, int *iLength)
{ {
assert(self); assert(self);
*iLength = self->pDriv->iTimeChan; *iLength = getNoOfTimebins(self->pDriv->data);
return self->pDriv->fTime; return getTimeBinning(self->pDriv->data);
} }
/*-------------------------------------------------------------------------*/ /*-------------------------------------------------------------------------*/
int GetHistLength(pHistMem self) int GetHistLength(pHistMem self)
{ {
assert(self); assert(self);
return self->pDriv->iRank*self->pDriv->iLength; return getHMDataLength(self->pDriv->data);
} }
/*--------------------------------------------------------------------------*/ /*--------------------------------------------------------------------------*/
float GetHistCountTime(pHistMem self, SConnection *pCon) float GetHistCountTime(pHistMem self, SConnection *pCon)
@ -898,9 +773,7 @@
i,iStart,iEnd,lData); i,iStart,iEnd,lData);
if(iRet == OKOK) if(iRet == OKOK)
{ {
self->iLocalUpdate = 1; updateHMData(self->pDriv->data);
self->tLocal = 0;
self->pDriv->iUpdate = 0;
return 1; return 1;
} }
else else
@ -921,87 +794,20 @@
int GetHistogram(pHistMem self, SConnection *pCon, int GetHistogram(pHistMem self, SConnection *pCon,
int i, int iStart, int iEnd, HistInt *lData, int iDataLen) int i, int iStart, int iEnd, HistInt *lData, int iDataLen)
{ {
int ii, iErr, iRet, iCopy;
char pBueffel[512], pError[80];
HistInt *lHist = NULL;
assert(self); assert(self);
if(!self->iInit) if(!self->iInit)
{ {
SCWrite(pCon,"ERROR: histogram memory not initialised",eError); SCWrite(pCon,"ERROR: histogram memory not initialised",eError);
return 0; return 0;
} }
/* get the full histogram if an update is needed */ if(iEnd > iDataLen/sizeof(HistInt))
if( (self->iLocalUpdate) && (time(NULL) > self->tLocal) ) {
{ SCWrite(pCon,"WARNING: truncating request to fit data space",eWarning);
#ifdef LOADDEBUG iEnd = (iDataLen/sizeof(HistInt)) - 1;
fprintf(stdout,"Getting new histogram from HM\n"); }
#endif return getHMDataHistogram(self,pCon,i,iStart,iEnd,lData);
/* check data allocation */
if(self->iLocalLength != self->pDriv->iLength)
{
if(self->iLocalData)
{
free(self->iLocalData);
self->iLocalData = NULL;
}
self->iLocalData = (HistInt *)malloc(
self->pDriv->iLength*sizeof(HistInt));
if(!self->iLocalData)
{
SCWrite(pCon,"ERROR: failed to allocate data in GetHistogram",
eError);
return 0;
}
self->iLocalLength = self->pDriv->iLength;
memset(self->iLocalData,0,self->iLocalLength*sizeof(HistInt));
}
/* try at least three times */
for(ii = 0; ii < 3; ii++)
{
iRet = self->pDriv->GetHistogram(self->pDriv,pCon,
i,0,self->iLocalLength,
self->iLocalData);
if(iRet == OKOK)
{
self->iLocalUpdate = 0;
self->tLocal = time(NULL) + self->iUpdateIntervall;
break;
}
else
{
iRet = self->pDriv->GetError(self->pDriv,&iErr,pError,79);
sprintf(pBueffel,"ERROR: %s ",pError);
SCWrite(pCon,pBueffel,eError);
iRet = self->pDriv->TryAndFixIt(self->pDriv,iErr);
if(iRet == COTERM)
{
return 0;
}
}
}
}
/* copy from buffer if there and updated */
if(self->iLocalData)
{
#ifdef LOADDEBUG
fprintf(stdout,"Copying histogram data from memory\n");
#endif
lHist = self->iLocalData + iStart;
if(iEnd*sizeof(HistInt) < iDataLen)
{
iCopy = iEnd;
}
else
{
iCopy = iDataLen/sizeof(HistInt);
}
memcpy(lData,lHist,iCopy*sizeof(HistInt));
}
return 1;
} }
/*-------------------------------------------------------------------------*/ /*-------------------------------------------------------------------------*/
int GetHistogramDirect(pHistMem self, SConnection *pCon, int GetHistogramDirect(pHistMem self, SConnection *pCon,
@ -1048,10 +854,6 @@
/*-----------------------------------------------------------------------*/ /*-----------------------------------------------------------------------*/
HistInt *GetHistogramPointer(pHistMem self, SConnection *pCon) HistInt *GetHistogramPointer(pHistMem self, SConnection *pCon)
{ {
int ii, iErr, iRet, iCopy;
char pBueffel[512], pError[80];
HistInt *lHist = NULL;
assert(self); assert(self);
if(!self->iInit) if(!self->iInit)
@ -1060,67 +862,7 @@
return NULL; return NULL;
} }
if(self->iLocalData == NULL) return getHMDataBufferPointer(self,pCon);
{
self->iLocalUpdate = 1;
self->tLocal = 0;
}
/* get the full histogram if an update is needed */
if( (self->iLocalUpdate) && (time(NULL) > self->tLocal) )
{
#ifdef LOADDEBUG
fprintf(stdout,"Getting new histogram from HM\n");
#endif
/* check data allocation */
if(self->iLocalLength != self->pDriv->iLength)
{
if(self->iLocalData)
{
free(self->iLocalData);
self->iLocalData = NULL;
}
self->iLocalData = (HistInt *)malloc(
self->pDriv->iLength*sizeof(HistInt));
if(!self->iLocalData)
{
SCWrite(pCon,"ERROR: failed to allocate data in GetHistogram",
eError);
return NULL;
}
self->iLocalLength = self->pDriv->iLength;
memset(self->iLocalData,0,self->iLocalLength*sizeof(HistInt));
}
/* try at least three times */
for(ii = 0; ii < 3; ii++)
{
iRet = self->pDriv->GetHistogram(self->pDriv,pCon,
0,0,self->iLocalLength,
self->iLocalData);
if(iRet == OKOK)
{
self->iLocalUpdate = 0;
self->tLocal = time(NULL) + self->iUpdateIntervall;
break;
}
else
{
iRet = self->pDriv->GetError(self->pDriv,&iErr,pError,79);
sprintf(pBueffel,"ERROR: %s ",pError);
SCWrite(pCon,pBueffel,eError);
iRet = self->pDriv->TryAndFixIt(self->pDriv,iErr);
if(iRet == COTERM)
{
return NULL;
}
}
}
}
#ifdef LOADDEBUG
fprintf(stdout,"Copying histogram data from memory\n");
#endif
return self->iLocalData;
} }
/*--------------------------------------------------------------------------*/ /*--------------------------------------------------------------------------*/
int PresetHistogram(pHistMem self, SConnection *pCon, HistInt lVal) int PresetHistogram(pHistMem self, SConnection *pCon, HistInt lVal)
@ -1142,9 +884,7 @@
iRet = self->pDriv->Preset(self->pDriv,pCon,lVal); iRet = self->pDriv->Preset(self->pDriv,pCon,lVal);
if(iRet == OKOK) if(iRet == OKOK)
{ {
self->pDriv->iUpdate = 0; updateHMData(self->pDriv->data);
self->iLocalUpdate = 1;
self->tLocal = 0;
return 1; return 1;
} }
else else
@ -1161,6 +901,7 @@
} }
return 0; return 0;
} }
/*----------------------------------------------------------------------*/
/*-----------------------------------------------------------------------*/ /*-----------------------------------------------------------------------*/
static int HMCountInterest(int iEvent, void *pEvent, void *pUser) static int HMCountInterest(int iEvent, void *pEvent, void *pUser)
{ {
@ -1183,6 +924,22 @@
} }
return 0; return 0;
} }
/*----------------------------------------------------------------------*/
static int checkHMEnd(pHistMem self, char *text){
int iTest, iEnd;
iEnd = getHMDataLength(self->pDriv->data);
if(text == NULL){
return iEnd;
} else {
iTest = atoi(text);
if(iTest > iEnd){
return iEnd;
} else {
return iTest;
}
}
}
/*--------------------------------------------------------------------------*/ /*--------------------------------------------------------------------------*/
int HistAction(SConnection *pCon, SicsInterp *pSics, void *pData, int HistAction(SConnection *pCon, SicsInterp *pSics, void *pData,
int argc, char *argv[]) int argc, char *argv[])
@ -1276,7 +1033,8 @@
/* authorise */ /* authorise */
if(!SCMatchRights(pCon,usMugger)) if(!SCMatchRights(pCon,usMugger))
{ {
sprintf(pBueffel,"ERROR: you need to be manager in order to configure %s", sprintf(pBueffel,
"ERROR: you need to be manager in order to configure %s",
argv[0]); argv[0]);
SCWrite(pCon,pBueffel,eError); SCWrite(pCon,pBueffel,eError);
return 0; return 0;
@ -1304,7 +1062,6 @@
fVal = atof(argv[2]); fVal = atof(argv[2]);
if(!SCMatchRights(pCon,self->iAccess)) if(!SCMatchRights(pCon,self->iAccess))
{ {
SCWrite(pCon,"ERROR: you are not priviledged for attempted operation",eError);
return 0; return 0;
} }
iRet = SetHistPreset(self,fVal); iRet = SetHistPreset(self,fVal);
@ -1324,7 +1081,6 @@
{ {
if(!SCMatchRights(pCon,self->iAccess)) if(!SCMatchRights(pCon,self->iAccess))
{ {
SCWrite(pCon,"ERROR: you are not priviledged for attempted operation",eError);
return 0; return 0;
} }
self->iExponent = atoi(argv[2]); self->iExponent = atoi(argv[2]);
@ -1346,7 +1102,6 @@
strtolower(argv[2]); strtolower(argv[2]);
if(!SCMatchRights(pCon,self->iAccess)) if(!SCMatchRights(pCon,self->iAccess))
{ {
SCWrite(pCon,"ERROR: you are not priviledged for attempted operation",eError);
return 0; return 0;
} }
if(strcmp(argv[2],"timer") == 0) if(strcmp(argv[2],"timer") == 0)
@ -1386,8 +1141,6 @@
} }
else else
{ {
SCWrite(pCon,
"ERROR: you are not privileged for attempted operation",eError);
return 0; return 0;
} }
} }
@ -1410,8 +1163,6 @@
} }
else else
{ {
SCWrite(pCon,
"ERROR: you are not privileged for attempted operation",eError);
return 0; return 0;
} }
} }
@ -1429,8 +1180,6 @@
} }
else else
{ {
SCWrite(pCon,
"ERROR: you are not privileged for attempted operation",eError);
return 0; return 0;
} }
} }
@ -1448,8 +1197,6 @@
} }
else else
{ {
SCWrite(pCon,
"ERROR: you are not privileged for attempted operation",eError);
return 0; return 0;
} }
} }
@ -1458,8 +1205,6 @@
/* check user rights */ /* check user rights */
if(!SCMatchRights(pCon,self->iAccess)) if(!SCMatchRights(pCon,self->iAccess))
{ {
SCWrite(pCon,
"ERROR: you are not priviledged for attempted operation",eError);
return 0; return 0;
} }
@ -1491,15 +1236,6 @@
} }
iNum = atoi(argv[2]); iNum = atoi(argv[2]);
/* check iNum */
if( (iNum < 0) || (iNum > self->pDriv->iRank))
{
sprintf(pBueffel,"ERROR: requested histogram no %d out of range",
iNum);
SCWrite(pCon,pBueffel,eError);
return 0;
}
/* optional iStart, default 0 */ /* optional iStart, default 0 */
iStart = 0; iStart = 0;
if(argc > 3 ) if(argc > 3 )
@ -1513,21 +1249,12 @@
SCWrite(pCon,"WARNING: Invalid start position defaulted to 0",eWarning); SCWrite(pCon,"WARNING: Invalid start position defaulted to 0",eWarning);
iStart = 0; iStart = 0;
} }
/* optional iEnd, default to maximum */ if(argc > 4){
iEnd = self->pDriv->iLength; iEnd = checkHMEnd(self,argv[4]);
if(argc > 4) } else {
{ iEnd = checkHMEnd(self,NULL);
iEnd = atoi(argv[4]); }
}
/* check iEnd */
if(iEnd > self->pDriv->iLength)
{
iEnd = self->pDriv->iLength;
SCWrite(pCon,
"WARNING: invalid end parameter reset to max ",eWarning);
}
/* allocate data storage and get it */ /* allocate data storage and get it */
lData = (HistInt *)malloc(iEnd*sizeof(HistInt)); lData = (HistInt *)malloc(iEnd*sizeof(HistInt));
@ -1577,15 +1304,6 @@
} }
iNum = atoi(argv[2]); iNum = atoi(argv[2]);
/* check iNum */
if( (iNum < 0) || (iNum > self->pDriv->iRank))
{
sprintf(pBueffel,"ERROR: requested histogram no %d out of range",
iNum);
SCWrite(pCon,pBueffel,eError);
return 0;
}
/* optional iStart, default 0 */ /* optional iStart, default 0 */
iStart = 0; iStart = 0;
if(argc > 3 ) if(argc > 3 )
@ -1599,22 +1317,13 @@
SCWrite(pCon,"WARNING: Invalid start position defaulted to 0",eWarning); SCWrite(pCon,"WARNING: Invalid start position defaulted to 0",eWarning);
iStart = 0; iStart = 0;
} }
/* optional iEnd, default to maximum */ if(argc > 4){
iEnd = self->pDriv->iLength; iEnd = checkHMEnd(self,argv[4]);
if(argc > 4) } else {
{ iEnd = checkHMEnd(self,NULL);
iEnd = atoi(argv[4]); }
}
/* check iEnd */
if(iEnd > self->pDriv->iLength)
{
iEnd = self->pDriv->iLength;
SCWrite(pCon,
"WARNING: invalid end parameter reset to max ",eWarning);
}
/* allocate data storage and get it */ /* allocate data storage and get it */
lData = (HistInt *)malloc((iEnd+1)*sizeof(HistInt)); lData = (HistInt *)malloc((iEnd+1)*sizeof(HistInt));
if(!lData) if(!lData)
@ -1659,15 +1368,6 @@
} }
iNum = atoi(argv[2]); iNum = atoi(argv[2]);
/* check iNum */
if( (iNum < 0) || (iNum > self->pDriv->iRank))
{
sprintf(pBueffel,"ERROR: requested histogram no %d out of range",
iNum);
SCWrite(pCon,pBueffel,eError);
return 0;
}
/* optional iStart, default 0 */ /* optional iStart, default 0 */
iStart = 0; iStart = 0;
if(argc > 3 ) if(argc > 3 )
@ -1678,25 +1378,17 @@
/* check iStart */ /* check iStart */
if(iStart < 0) if(iStart < 0)
{ {
SCWrite(pCon,"WARNING: Invalid start position defaulted to 0",eWarning); SCWrite(pCon,"WARNING: Invalid start position defaulted to 0",
eWarning);
iStart = 0; iStart = 0;
} }
/* optional iEnd, default to maximum */ if(argc > 4){
iEnd = self->pDriv->iLength; iEnd = checkHMEnd(self,argv[4]);
if(argc > 4) } else {
{ iEnd = checkHMEnd(self,NULL);
iEnd = atoi(argv[4]); }
}
/* check iEnd */
if(iEnd > self->pDriv->iLength)
{
iEnd = self->pDriv->iLength;
SCWrite(pCon,
"WARNING: invalid end parameter reset to max ",eWarning);
}
/* allocate data storage and get it */ /* allocate data storage and get it */
lData = (HistInt *)malloc((iEnd+1)*sizeof(HistInt)); lData = (HistInt *)malloc((iEnd+1)*sizeof(HistInt));
if(!lData) if(!lData)
@ -1731,7 +1423,8 @@
else if(strcmp(argv[1],"notimebin") == 0) else if(strcmp(argv[1],"notimebin") == 0)
{ {
sprintf(pBueffel, sprintf(pBueffel,
"%s.notimebin = %d",argv[0], self->pDriv->iTimeChan); "%s.notimebin = %d",argv[0],
getNoOfTimebins(self->pDriv->data));
SCWrite(pCon,pBueffel,eValue); SCWrite(pCon,pBueffel,eValue);
return 1; return 1;
} }
@ -1740,9 +1433,9 @@
{ {
Tcl_DStringInit(&tResult); Tcl_DStringInit(&tResult);
Tcl_DStringAppend(&tResult,"histogram.timebins = ",-1); Tcl_DStringAppend(&tResult,"histogram.timebins = ",-1);
for(i = 0; i < self->pDriv->iTimeChan; i++) for(i = 0; i < self->pDriv->data->nTimeChan; i++)
{ {
sprintf(pBueffel," %8.2f", self->pDriv->fTime[i]); sprintf(pBueffel," %8.2f", self->pDriv->data->timeBinning[i]);
Tcl_DStringAppend(&tResult,pBueffel,-1); Tcl_DStringAppend(&tResult,pBueffel,-1);
} }
/* Write it */ /* Write it */
@ -1757,7 +1450,6 @@
{ {
if(!SCMatchRights(pCon,usMugger)) if(!SCMatchRights(pCon,usMugger))
{ {
SCWrite(pCon,"ERROR: you are not authorised for this operation",eError);
return 0; return 0;
} }
if(GetStatus() == eCounting) if(GetStatus() == eCounting)
@ -1795,22 +1487,13 @@
/* do it */ /* do it */
if(iNum >= MAXCHAN) if(iNum >= MAXCHAN)
{ {
SCWrite(pCon,"ERROR: number of requested time bins exceeds maximum permissible number", SCWrite(pCon,
"ERROR: number of requested time bins exceeds maximum permissible number",
eError); eError);
return 0; return 0;
} }
for(i = 0; i < iNum; i++) genTimeBinning(self->pDriv->data,
{ (float)dStart,(float)dStep,iNum);
self->pDriv->fTime[i] = dStart + i* dStep;
}
self->pDriv->iTimeChan = iNum;
self->iInit = 0;
self->pDriv->iLength = 1;
for(i = 0; i < self->pDriv->iRank; i++)
{
self->pDriv->iLength *= self->pDriv->iDims[i];
}
self->pDriv->iLength *= self->pDriv->iTimeChan;
SCSendOK(pCon); SCSendOK(pCon);
return 1; return 1;
} }
@ -1819,7 +1502,6 @@
{ {
if(!SCMatchRights(pCon,usMugger)) if(!SCMatchRights(pCon,usMugger))
{ {
SCWrite(pCon,"ERROR: yoy are not authorised for this operation",eError);
return 0; return 0;
} }
if(argc < 4) if(argc < 4)
@ -1843,20 +1525,11 @@
} }
if( (iNum < 0) || (iNum > MAXCHAN) ) if( (iNum < 0) || (iNum > MAXCHAN) )
{ {
SCWrite(pCon,"ERROR: requested time bin out or permissible range",eError); SCWrite(pCon,"ERROR: requested time bin out or permissible range",
eError);
return 0; return 0;
} }
self->pDriv->fTime[iNum] = dStep; setTimeBin(self->pDriv->data,iNum, (float)dStep);
if(iNum > self->pDriv->iTimeChan)
{
self->pDriv->iTimeChan = iNum;
self->pDriv->iLength = 1;
for(i = 0; i < self->pDriv->iRank; i++)
{
self->pDriv->iLength *= self->pDriv->iDims[i];
}
self->pDriv->iLength *= self->pDriv->iTimeChan;
}
self->iInit = 0; self->iInit = 0;
SCSendOK(pCon); SCSendOK(pCon);
return 1; return 1;
@ -1864,8 +1537,7 @@
/* clear time bin info */ /* clear time bin info */
else if(strcmp(argv[1],"clearbin") == 0) else if(strcmp(argv[1],"clearbin") == 0)
{ {
self->pDriv->iTimeChan = 0; clearTimeBinning(self->pDriv->data);
self->iInit = 1;
SCSendOK(pCon); SCSendOK(pCon);
} }
/*-------- sum */ /*-------- sum */
@ -1924,5 +1596,3 @@

View File

@ -31,6 +31,7 @@ $\langle$Modes {\footnotesize ?}$\rangle\equiv$
\end{list} \end{list}
\end{minipage}\\[4ex] \end{minipage}\\[4ex]
\end{flushleft} \end{flushleft}
These modes are specific to the SINQ histogram memory.
A histogram memory can be operated in transparent mode. It has not yet been A histogram memory can be operated in transparent mode. It has not yet been
defined what this means but it is sort of storing raw data from the detector defined what this means but it is sort of storing raw data from the detector
without any summing or processing. Normal mode is better defined, this is without any summing or processing. Normal mode is better defined, this is
@ -101,6 +102,11 @@ command. Then on initialisation first the logical histogram memory
evaluates the general options and then the driver in its Config evaluates the general options and then the driver in its Config
function evaluates the driver specific options. function evaluates the driver specific options.
The histogram memory supports several dimensions, a time binning
option and optional buffering of histogram memory data read from the
actual HM. All this data management stuff is handled in a separate
class, HMdata. See the documentation for HMdata for more details.
\subsubsection{The Histogram memory driver} \subsubsection{The Histogram memory driver}
Adhering to the Sics paradigm of dividing any device into a logical device Adhering to the Sics paradigm of dividing any device into a logical device
@ -115,16 +121,7 @@ $\langle$HistType {\footnotesize ?}$\rangle\equiv$
\begin{list}{}{} \item \begin{list}{}{} \item
\mbox{}\verb@@\\ \mbox{}\verb@@\\
\mbox{}\verb@ typedef struct __HistDriver {@\\ \mbox{}\verb@ typedef struct __HistDriver {@\\
\mbox{}\verb@ /* configuration data */@\\ \mbox{}\verb@ pHMdata data;@\\
\mbox{}\verb@ HistMode eHistMode;@\\
\mbox{}\verb@ OverFlowMode eFlow;@\\
\mbox{}\verb@ int iRank;@\\
\mbox{}\verb@ int iDims[MAXDIM];@\\
\mbox{}\verb@ int nDim;@\\
\mbox{}\verb@ int iLength;@\\
\mbox{}\verb@ int iBinWidth;@\\
\mbox{}\verb@ float fTime[MAXCHAN];@\\
\mbox{}\verb@ int iTimeChan;@\\
\mbox{}\verb@ /* counting operations data */@\\ \mbox{}\verb@ /* counting operations data */@\\
\mbox{}\verb@ CounterMode eCount;@\\ \mbox{}\verb@ CounterMode eCount;@\\
\mbox{}\verb@ float fCountPreset;@\\ \mbox{}\verb@ float fCountPreset;@\\
@ -185,15 +182,6 @@ $\langle$HistType {\footnotesize ?}$\rangle\equiv$
\end{minipage}\\[4ex] \end{minipage}\\[4ex]
\end{flushleft} \end{flushleft}
Quite a lot, but a histogram memory is quite a complex piece of equipment. Quite a lot, but a histogram memory is quite a complex piece of equipment.
The configuration information is in the elements EhistMode, eOverFlowMode,
iRank, iDims and iBinWidth fields. iDim and nDim desribe the logical
dimensions of the histogram memory. These may be different from the
dimensions used for data transfer. For instance the SANS detector is
handled internally as 1600+ numbers where it really is a filed o
128*128.
Additionally there is an array of
floating point values which denote the time binning for time-o-flight
operation or the stroboscopic binning axis in stroboscopic mode.
The fields fPreset and CounterMode hold the counting parameter data. The fields fPreset and CounterMode hold the counting parameter data.
@ -326,11 +314,6 @@ $\langle$HistST {\footnotesize ?}$\rangle\equiv$
\mbox{}\verb@ pICountable pCountInt;@\\ \mbox{}\verb@ pICountable pCountInt;@\\
\mbox{}\verb@ pICallBack pCall;@\\ \mbox{}\verb@ pICallBack pCall;@\\
\mbox{}\verb@ pStringDict pOption;@\\ \mbox{}\verb@ pStringDict pOption;@\\
\mbox{}\verb@ HistInt *iLocalData;@\\
\mbox{}\verb@ int iLocalLength;@\\
\mbox{}\verb@ int iLocalUpdate;@\\
\mbox{}\verb@ time_t tLocal;@\\
\mbox{}\verb@ int iUpdateIntervall;@\\
\mbox{}\verb@ } HistMem;@\\ \mbox{}\verb@ } HistMem;@\\
\mbox{}\verb@@$\diamond$ \mbox{}\verb@@$\diamond$
\end{list} \end{list}
@ -630,7 +613,7 @@ following.
\mbox{}\verb@----------------------------------------------------------------------------*/@\\ \mbox{}\verb@----------------------------------------------------------------------------*/@\\
\mbox{}\verb@#ifndef SICSHISTDRIV@\\ \mbox{}\verb@#ifndef SICSHISTDRIV@\\
\mbox{}\verb@#define SICSHISTDRIV@\\ \mbox{}\verb@#define SICSHISTDRIV@\\
\mbox{}\verb@#define MAXCHAN 16834 @\\ \mbox{}\verb@#include "hmdata.h"@\\
\mbox{}\verb@@\\ \mbox{}\verb@@\\
\mbox{}\verb@@$\langle$HistType {\footnotesize ?}$\rangle$\verb@@\\ \mbox{}\verb@@$\langle$HistType {\footnotesize ?}$\rangle$\verb@@\\
\mbox{}\verb@@$\langle$HistDrivProt {\footnotesize ?}$\rangle$\verb@@\\ \mbox{}\verb@@$\langle$HistDrivProt {\footnotesize ?}$\rangle$\verb@@\\

View File

@ -17,6 +17,7 @@ histograms. Let's discuss these different modes first.
eSANSTOF eSANSTOF
} HistMode; } HistMode;
@} @}
These modes are specific to the SINQ histogram memory.
A histogram memory can be operated in transparent mode. It has not yet been A histogram memory can be operated in transparent mode. It has not yet been
defined what this means but it is sort of storing raw data from the detector defined what this means but it is sort of storing raw data from the detector
without any summing or processing. Normal mode is better defined, this is without any summing or processing. Normal mode is better defined, this is
@ -73,6 +74,11 @@ command. Then on initialisation first the logical histogram memory
evaluates the general options and then the driver in its Config evaluates the general options and then the driver in its Config
function evaluates the driver specific options. function evaluates the driver specific options.
The histogram memory supports several dimensions, a time binning
option and optional buffering of histogram memory data read from the
actual HM. All this data management stuff is handled in a separate
class, HMdata. See the documentation for HMdata for more details.
\subsubsection{The Histogram memory driver} \subsubsection{The Histogram memory driver}
Adhering to the Sics paradigm of dividing any device into a logical device Adhering to the Sics paradigm of dividing any device into a logical device
@ -82,16 +88,7 @@ definition:
@d HistType @{ @d HistType @{
typedef struct __HistDriver { typedef struct __HistDriver {
/* configuration data */ pHMdata data;
HistMode eHistMode;
OverFlowMode eFlow;
int iRank;
int iDims[MAXDIM];
int nDim;
int iLength;
int iBinWidth;
float fTime[MAXCHAN];
int iTimeChan;
/* counting operations data */ /* counting operations data */
CounterMode eCount; CounterMode eCount;
float fCountPreset; float fCountPreset;
@ -145,15 +142,6 @@ definition:
@} @}
Quite a lot, but a histogram memory is quite a complex piece of equipment. Quite a lot, but a histogram memory is quite a complex piece of equipment.
The configuration information is in the elements EhistMode, eOverFlowMode,
iRank, iDims and iBinWidth fields. iDim and nDim desribe the logical
dimensions of the histogram memory. These may be different from the
dimensions used for data transfer. For instance the SANS detector is
handled internally as 1600+ numbers where it really is a filed o
128*128.
Additionally there is an array of
floating point values which denote the time binning for time-o-flight
operation or the stroboscopic binning axis in stroboscopic mode.
The fields fPreset and CounterMode hold the counting parameter data. The fields fPreset and CounterMode hold the counting parameter data.
@ -269,11 +257,6 @@ histogram memory object is fairly simple:
pICountable pCountInt; pICountable pCountInt;
pICallBack pCall; pICallBack pCall;
pStringDict pOption; pStringDict pOption;
HistInt *iLocalData;
int iLocalLength;
int iLocalUpdate;
time_t tLocal;
int iUpdateIntervall;
} HistMem; } HistMem;
@} @}
According to the general Sics object interface the first field is the object According to the general Sics object interface the first field is the object
@ -485,7 +468,7 @@ following.
----------------------------------------------------------------------------*/ ----------------------------------------------------------------------------*/
#ifndef SICSHISTDRIV #ifndef SICSHISTDRIV
#define SICSHISTDRIV #define SICSHISTDRIV
#define MAXCHAN 16834 #include "hmdata.h"
@< HistType@> @< HistType@>
@< HistDrivProt @> @< HistDrivProt @>

View File

@ -58,7 +58,7 @@
*/ */
static int iSet = 0; static int iSet = 0;
static HistInt iSetVal = 0; static HistInt iSetVal = 0;
static HistMode eHistMode;
/*--------------------------------------------------------------------------*/ /*--------------------------------------------------------------------------*/
static int SimConfig(pHistDriver self, SConnection *pCon, static int SimConfig(pHistDriver self, SConnection *pCon,
pStringDict pOption, SicsInterp *pSics) pStringDict pOption, SicsInterp *pSics)
@ -67,14 +67,13 @@
char pData[132]; char pData[132];
float fFail; float fFail;
if(self->eHistMode == eHTOF) if(eHistMode == eHTOF)
{ {
for(i = 0; i < self->nDim; i++) for(i = 0; i < self->data->rank; i++)
{ {
iLength *= self->iDims[i]; iLength *= self->data->iDim[i];
} }
iLength *= self->iTimeChan; iLength *= self->data->nTimeChan;
self->iLength = iLength;
} }
/* /*

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;
}

61
hmdata.h Normal file
View File

@ -0,0 +1,61 @@
/*-----------------------------------------------------------------------
This is a data handling class for histogram memory data.
For more information see hmdata.tex.
copyright: see file COPYRIGHT
Mark Koennecke, January 2003
-------------------------------------------------------------------------*/
#ifndef SICSHMDATA
#define SICSHMDATA
#include "sics.h"
#include "HistMem.h"
#include "stringdict.h"
#define MAXCHAN 16834
#define MAXDIM 3
typedef struct {
int rank;
int iDim[MAXDIM];
int nTimeChan;
float timeBinning[MAXCHAN];
int tofMode;
time_t nextUpdate;
int updateIntervall;
int updateFlag;
HistInt *localBuffer;
} HMdata, *pHMdata;
pHMdata makeHMData(void);
void killHMData(pHMdata self);
int configureHMdata(pHMdata self, pStringDict pOpt,
SConnection *pCon);
int genTimeBinning(pHMdata self, float start, float step,
int noSteps);
int setTimeBin(pHMdata self, int index, float value);
int getNoOfTimebins(pHMdata self);
float *getTimeBinning(pHMdata self);
int isInTOFMode(pHMdata self);
void clearTimeBinning(pHMdata self);
void getHMDataDim(pHMdata self, int iDIM[MAXDIM], int *rank);
long getHMDataLength(pHMdata self);
int getHMDataHistogram(pHistMem hist, SConnection *pCon,
int bank, int start, int length,
HistInt *lData);
void updateHMData(pHMdata self);
HistInt *getHMDataBufferPointer(pHistMem hist, SConnection *pCon);
long sumHMDataRectangle(pHistMem self, SConnection *pCon,
int start[MAXDIM], int end[MAXDIM]);
#endif

111
hmdata.w Normal file
View File

@ -0,0 +1,111 @@
\subsubsection{HMdata}
This is a data class for histogram memories. This class has the
following tasks:
\begin{itemize}
\item Maintain the dimensions of the histogram memory.
\item Keep track of the time binning, when appropriate.
\item In many cases the histogram memory data is buffered in order to
prevent excessive access to the histogram memory through status
display clients gone mad. This task is also handled through this class.
\end{itemize}
In order to do this, the following data structure is needed:
@d hmdatadat @{
typedef struct {
int rank;
int iDim[MAXDIM];
int nTimeChan;
float timeBinning[MAXCHAN];
int tofMode;
time_t nextUpdate;
int updateIntervall;
int updateFlag;
HistInt *localBuffer;
} HMdata, *pHMdata;
@}
The following functions work on this data structure:
@d hmdatfunc @{
pHMdata makeHMData(void);
void killHMData(pHMdata self);
int configureHMdata(pHMdata self, pStringDict pOpt,
SConnection *pCon);
int genTimeBinning(pHMdata self, float start, float step,
int noSteps);
int setTimeBin(pHMdata self, int index, float value);
int getNoOfTimebins(pHMdata self);
float *getTimeBinning(pHMdata self);
int isInTOFMode(pHMdata self);
void clearTimeBinning(pHMdata self);
void getHMDataDim(pHMdata self, int iDIM[MAXDIM], int *rank);
long getHMDataLength(pHMdata self);
int getHMDataHistogram(pHistMem hist, SConnection *pCon,
int bank, int start, int length,
HistInt *lData);
void updateHMData(pHMdata self);
HistInt *getHMDataBufferPointer(pHistMem hist, SConnection *pCon);
long sumHMDataRectangle(pHistMem self, SConnection *pCon,
int start[MAXDIM], int end[MAXDIM]);
@}
\begin{description}
\item[makeHMData] allocate a new HMdata structure.
\item[killHMData] properly release all memory used by the HMdata
structure.
\item[configureHMdata] configures the HMdata from the configuration
options in pOpt.
\item[getTimeBinning] generate a equidistant time binning starting at
start. Create noSteps time bins of size step.
\item[isInTOFMode] returns true if we are in TOF mode, 0 else.
\item[setTimeBin] sets a single time bin at index to value. Used for
irregular time binnings.
\item[clearTimeBinning] removes all time binnings.
\item[getNoOfTimeBins] returns the number of time bins.
\item[getTimeBinning] returns a pointer to the time binning array. Do
not free or modify in any other form.
\item[getHMDataDim] retrieves the rank and dimensions of histogram
memory data.
\item[getHMDataLength] gets the size of the histogram memory array.
\item[getHMDataHistogram] copies histogram memory data to
lData. Dependent on the status, data is copied either from a local
buffer or retrieved from the histogram memory. lData must have been
allocated large enough to cope with all the data before this works
properly.
\item[forceHMDataUpdate] makes sure that the histogram is read from
the histogram memory and not from the buffer the next time round.
\item[getHMDataBufferPointer] returns a pointer to the internal buffer
pointer of HMdata. Use with extra care!
\item[sumHMDataRectangle] sums a rectangular box delimted by start and end
from the histogram memory.
\end{description}
@o hmdata.h @{
/*-----------------------------------------------------------------------
This is a data handling class for histogram memory data.
For more information see hmdata.tex.
copyright: see file COPYRIGHT
Mark Koennecke, January 2003
-------------------------------------------------------------------------*/
#ifndef SICSHMDATA
#define SICSHMDATA
#include "sics.h"
#include "HistMem.h"
#include "stringdict.h"
#define MAXCHAN 16834
#define MAXDIM 3
@<hmdatadat@>
@<hmdatfunc@>
#endif
@}

View File

@ -95,7 +95,8 @@ int StartRegMot(pMotReg self, SConnection *pCon, float fValue){
int ret; int ret;
long (*oldSet)(void *pmotorData, SConnection *pCon, float fValue); long (*oldSet)(void *pmotorData, SConnection *pCon, float fValue);
pIDrivable pDriv = NULL; pIDrivable pDriv = NULL;
char pBueffel[132];
assert(self); assert(self);
pDriv = GetDrivableInterface(self->motorData); pDriv = GetDrivableInterface(self->motorData);
@ -107,6 +108,9 @@ int StartRegMot(pMotReg self, SConnection *pCon, float fValue){
self->motorData, self->motorData,
pCon, pCon,
fValue); fValue);
sprintf(pBueffel,"anticollision started %s to %f",self->motorName,
fValue);
SCWrite(pCon,pBueffel,eValue);
pDriv->SetValue = oldSet; pDriv->SetValue = oldSet;
self->iActive = 1; self->iActive = 1;

View File

@ -1,22 +1,139 @@
# Counter counter # Motor atz
counter SetPreset 60.000000 atz sign 1.000000
counter SetMode Timer atz SoftZero 0.000000
# Motor a77 atz SoftLowerLim -3900.000000
a77 sign 1.000000 atz SoftUpperLim 0.000000
a77 SoftZero 0.000000 atz Fixed -1.000000
a77 SoftLowerLim -30.000000 atz InterruptMode 0.000000
a77 SoftUpperLim 30.000000 atz AccessCode 2.000000
a77 Fixed -1.000000 # Motor az1
a77 InterruptMode 0.000000 az1 sign 1.000000
a77 AccessCode 2.000000 az1 SoftZero 0.000000
# Motor 2t az1 SoftLowerLim -3900.000000
2t sign 1.000000 az1 SoftUpperLim 0.000000
2t SoftZero 0.000000 az1 Fixed -1.000000
2t SoftLowerLim -120.000000 az1 InterruptMode 0.000000
2t SoftUpperLim 120.000000 az1 AccessCode 2.000000
2t Fixed -1.000000 # Motor dv
2t InterruptMode 0.000000 dv sign 1.000000
2t AccessCode 2.000000 dv SoftZero 0.000000
dv SoftLowerLim -14000.000000
dv SoftUpperLim 25000.000000
dv Fixed -1.000000
dv InterruptMode 0.000000
dv AccessCode 2.000000
# Motor dh
dh sign 1.000000
dh SoftZero 0.000000
dh SoftLowerLim -14000.000000
dh SoftUpperLim 16000.000000
dh Fixed -1.000000
dh InterruptMode 0.000000
dh AccessCode 2.000000
# Motor dz
dz sign 1.000000
dz SoftZero 0.000000
dz SoftLowerLim 1.050000
dz SoftUpperLim 6.000000
dz Fixed -1.000000
dz InterruptMode 0.000000
dz AccessCode 2.000000
# Motor sy
sy sign 1.000000
sy SoftZero 0.000000
sy SoftLowerLim -10000.000000
sy SoftUpperLim 10000.000000
sy Fixed -1.000000
sy InterruptMode 0.000000
sy AccessCode 2.000000
# Motor sx
sx sign 1.000000
sx SoftZero 0.000000
sx SoftLowerLim -10000.000000
sx SoftUpperLim 10000.000000
sx Fixed -1.000000
sx InterruptMode 0.000000
sx AccessCode 2.000000
# Motor sz
sz sign 1.000000
sz SoftZero 0.000000
sz SoftLowerLim -10000.000000
sz SoftUpperLim 10000.000000
sz Fixed -1.000000
sz InterruptMode 0.000000
sz AccessCode 2.000000
# Motor om
om sign 1.000000
om SoftZero 0.000000
om SoftLowerLim -10000.000000
om SoftUpperLim 10000.000000
om Fixed -1.000000
om InterruptMode 0.000000
om AccessCode 2.000000
# Motor tl
tl sign 1.000000
tl SoftZero 0.000000
tl SoftLowerLim -10000.000000
tl SoftUpperLim 10000.000000
tl Fixed -1.000000
tl InterruptMode 0.000000
tl AccessCode 2.000000
# Motor tu
tu sign 1.000000
tu SoftZero 0.000000
tu SoftLowerLim -10000.000000
tu SoftUpperLim 10000.000000
tu Fixed -1.000000
tu InterruptMode 0.000000
tu AccessCode 2.000000
# Motor gl
gl sign 1.000000
gl SoftZero 0.000000
gl SoftLowerLim -10000.000000
gl SoftUpperLim 10000.000000
gl Fixed -1.000000
gl InterruptMode 0.000000
gl AccessCode 2.000000
# Motor gu
gu sign 1.000000
gu SoftZero 0.000000
gu SoftLowerLim -10000.000000
gu SoftUpperLim 10000.000000
gu Fixed -1.000000
gu InterruptMode 0.000000
gu AccessCode 2.000000
# Motor sc
sc sign 1.000000
sc SoftZero 0.000000
sc SoftLowerLim -2000.000000
sc SoftUpperLim 70000.000000
sc Fixed -1.000000
sc InterruptMode 0.000000
sc AccessCode 2.000000
# Motor stz
stz sign 1.000000
stz SoftZero 0.000000
stz SoftLowerLim 6500.000000
stz SoftUpperLim 20000.000000
stz Fixed -1.000000
stz InterruptMode 0.000000
stz AccessCode 2.000000
# Motor stx
stx sign 1.000000
stx SoftZero 0.000000
stx SoftLowerLim -16000.000000
stx SoftUpperLim 16000.000000
stx Fixed -1.000000
stx InterruptMode 0.000000
stx AccessCode 2.000000
# Motor sr
sr sign 1.000000
sr SoftZero 0.000000
sr SoftLowerLim -10000.000000
sr SoftUpperLim 10000.000000
sr Fixed -1.000000
sr InterruptMode 0.000000
sr AccessCode 2.000000
samplename KohlSulfid samplename KohlSulfid
samplename setAccess 2 samplename setAccess 2
comment UNKNOWN comment UNKNOWN

View File

@ -68,6 +68,57 @@
self->iLastHMError = 0; self->iLastHMError = 0;
self->iLastCTError = 0; self->iLastCTError = 0;
} }
/*------------------------------------------------------------------------*/
static char *pHistMode[] = {
"transparent",
"normal",
"tof",
"strobo",
"hrpt",
"psd",
"sanstof",
NULL
};
static HistMode Text2Mode(char *text)
{
int i = 0;
while(pHistMode[i] != NULL)
{
if(strcmp(pHistMode[i],text) == 0)
{
return i;
}
i++;
}
/* not found */
return -1;
}
/*------------------------------------------------------------------------*/
static char *pFlowMode[] = {
"ignore",
"ceil",
"count",
"reflect",
NULL
};
static OverFlowMode Text2Flow(char *text)
{
int i = 0;
while(pFlowMode[i] != NULL)
{
if(strcmp(pFlowMode[i],text) == 0)
{
return i;
}
i++;
}
/* not found */
return -1;
}
/*-------------------------------------------------------------------------- /*--------------------------------------------------------------------------
Configure deconfigures first, in order to have a clean state. Than the HM Configure deconfigures first, in order to have a clean state. Than the HM
is configured and a client connection will be built. Configure requires, is configured and a client connection will be built. Configure requires,
@ -80,14 +131,14 @@
SinqHMDriv *pInternal; SinqHMDriv *pInternal;
int status, iMode; int status, iMode;
char pError[132]; char pError[132];
char pHMComputer[256]; char pHMComputer[256], pValue[80], pBueffel[256];
float fVal; float fVal;
char pcCounter[256]; char pcCounter[256];
CommandList *pCom = NULL; CommandList *pCom = NULL;
int iStart = 0; int iStart = 0;
int iInit = 0, i; int iInit = 0, i, iRet;
int xOff, xFac, yOff, yFac; int xOff, xFac, yOff, yFac;
int iPort; int iPort, iLength;
assert(self); assert(self);
assert(self->pPriv); assert(self->pPriv);
@ -97,9 +148,70 @@
pInternal = (SinqHMDriv *)self->pPriv; pInternal = (SinqHMDriv *)self->pPriv;
ErrInit(pInternal); ErrInit(pInternal);
/* enter histmode */
iRet = StringDictGet(pOpt,"histmode",pValue,79);
if(!iRet)
{
SCWrite(pCon,"ERROR: internal Value not found!",eError);
return 0;
}
strtolower(pValue);
iRet = Text2Mode(pValue);
if(iRet < 0)
{
sprintf(pBueffel,"ERROR: Invalid parameter %s to HistMode",pValue);
SCWrite(pCon,pBueffel,eError);
return 0;
}
pInternal->eHistMode = iRet;
/* handle overflowmode */
iRet = StringDictGet(pOpt,"overflowmode",pValue,79);
if(!iRet)
{
SCWrite(pCon,"ERROR: internal Value not found!",eError);
return 0;
}
strtolower(pValue);
iRet = Text2Flow(pValue);
if(iRet < 0)
{
sprintf(pBueffel,"ERROR: Invalid parameter %s to OverflowMode",pValue);
SCWrite(pCon,pBueffel,eError);
return 0;
}
pInternal->eFlow = iRet;
/* BinWidth */
iRet = StringDictGetAsNumber(pOpt,"binwidth",&fVal);
if(!iRet)
{
iRet = StringDictGet(pOpt,"binwidth",pValue,79);
if(iRet)
{
sprintf(pBueffel,"ERROR: %s not valid for BinWidth ",pValue);
SCWrite(pCon,pBueffel,eError);
return 0;
}
else
{
SCWrite(pCon,"ERROR: internal Value not found!",eError);
return 0;
}
}
if(fVal < 1)
{
sprintf(pBueffel,"ERROR: %f is invalid for BinWidth",fVal);
SCWrite(pCon,pBueffel,eError);
return 0;
}
pInternal->iBinWidth = (int)fVal;
/* check BinWidth */ /* check BinWidth */
if( (self->iBinWidth != 1) && (self->iBinWidth != 2) if( (pInternal->iBinWidth != 1) && (pInternal->iBinWidth != 2)
&& (self->iBinWidth != 4)) && (pInternal->iBinWidth != 4))
{ {
PrintHMError("Unsuported BinWidth specified, 1,2,4 are permissable",pCon); PrintHMError("Unsuported BinWidth specified, 1,2,4 are permissable",pCon);
return 0; return 0;
@ -137,7 +249,7 @@
pCom = FindCommand(pSics,pcCounter); pCom = FindCommand(pSics,pcCounter);
if(!pCom) if(!pCom)
{ {
PrintHMError("WARNING: no EL737 counter for HM found! ", PrintHMError("WARNING: no counter for HM found! ",
pCon); pCon);
pInternal->pCounter = NULL; pInternal->pCounter = NULL;
} }
@ -147,7 +259,7 @@
if(!pInternal->pCounter->pDes->GetInterface(pInternal->pCounter, if(!pInternal->pCounter->pDes->GetInterface(pInternal->pCounter,
COUNTID)) COUNTID))
{ {
PrintHMError("EL737 counter for histogram memory is invalid", PrintHMError("Counter for histogram memory is invalid",
pCon); pCon);
return 0; return 0;
} }
@ -170,8 +282,10 @@
/* in any case let us propagate the state of affairs to /* in any case let us propagate the state of affairs to
SINQHM SINQHM
*/ */
SINQHMSetPar(pInternal->pMaster,self->iRank, self->iLength,
self->iBinWidth); SINQHMSetPar(pInternal->pMaster,self->data->rank,
getHMDataLength(self->data),
pInternal->iBinWidth);
/* actual configuration. On first call, check for flag INIt in /* actual configuration. On first call, check for flag INIt in
@ -205,8 +319,8 @@
return 0; return 0;
} }
if( (self->iBinWidth != 1) && (self->iBinWidth != 2) if( (pInternal->iBinWidth != 1) && (pInternal->iBinWidth != 2)
&& (self->iBinWidth != 4)) && (pInternal->iBinWidth != 4))
{ {
PrintHMError("Unsuported BinWidth specified, 1,2,4 are permissable", PrintHMError("Unsuported BinWidth specified, 1,2,4 are permissable",
pCon); pCon);
@ -215,7 +329,7 @@ pCon);
/* configure */ /* configure */
switch(self->eHistMode) switch(pInternal->eHistMode)
{ {
case eHTransparent: case eHTransparent:
iMode = SQHM__TRANS; iMode = SQHM__TRANS;
@ -226,22 +340,25 @@ pCon);
case eHTOF: case eHTOF:
iMode = SQHM__TOF; iMode = SQHM__TOF;
/* recalculate some parameters */ /* recalculate some parameters */
self->iLength = 1; iLength = 1;
for(i = 0; i < self->iRank; i++) for(i = 0; i < self->data->rank; i++)
{ {
self->iLength *= self->iDims[i]; iLength *= self->data->iDim[i];
} }
self->iLength *= self->iTimeChan; iLength *= self->data->nTimeChan;
SINQHMDefineBank(pInternal->pMaster,0,0,self->iDims[0], SINQHMDefineBank(pInternal->pMaster,0,0,self->data->iDim[0],
self->fTime,self->iTimeChan); self->data->timeBinning,
self->data->nTimeChan);
break; break;
case eSANSTOF: case eSANSTOF:
iMode = SQHM__TOF; iMode = SQHM__TOF;
self->iLength = self->iDims[0]*self->iDims[1]; iLength = self->data->iDim[0]*self->data->iDim[1];
self->iLength *= self->iTimeChan; iLength *= self->data->nTimeChan;
SINQHMDefineBank(pInternal->pMaster,0,0, SINQHMDefineBank(pInternal->pMaster,0,0,
(self->iDims[0]*self->iDims[1]) + 3, (self->data->iDim[0]*self->data->iDim[1])
self->fTime,self->iTimeChan); + 3,
self->data->timeBinning,
self->data->nTimeChan);
break; break;
case eHStrobo: case eHStrobo:
iMode = SQHM__HM_PSD | SQHM__STROBO; iMode = SQHM__HM_PSD | SQHM__STROBO;
@ -256,7 +373,7 @@ pCon);
PrintHMError("Unsupported mode requested",pCon); PrintHMError("Unsupported mode requested",pCon);
return 0; return 0;
} }
switch(self->eFlow) switch(pInternal->eFlow)
{ {
case eOIgnore: case eOIgnore:
iMode = iMode | SQHM__BO_IGN; iMode = iMode | SQHM__BO_IGN;
@ -274,13 +391,13 @@ pCon);
PrintHMError("Unsupported overflowmode requested",pCon); PrintHMError("Unsupported overflowmode requested",pCon);
return 0; return 0;
} }
if(self->eHistMode != ePSD) if(pInternal->eHistMode != ePSD)
{ {
status = SINQHMConfigure(pInternal->pMaster, status = SINQHMConfigure(pInternal->pMaster,
iMode, iMode,
self->iRank, self->data->rank,
self->iLength, getHMDataLength(self->data),
self->iBinWidth, pInternal->iBinWidth,
0,0); 0,0);
} }
else else
@ -320,15 +437,15 @@ pCon);
/* xSize and ySize are supposed to be in dim */ /* xSize and ySize are supposed to be in dim */
status = SINQHMConfigurePSD(pInternal->pMaster, status = SINQHMConfigurePSD(pInternal->pMaster,
iMode, iMode,
self->iDims[0], self->data->iDim[0],
xOff, xOff,
xFac, xFac,
self->iDims[1], self->data->iDim[1],
yOff, yOff,
yFac, yFac,
self->iBinWidth, pInternal->iBinWidth,
self->fTime, self->data->timeBinning,
self->iTimeChan); self->data->nTimeChan);
} }
if(status < 0) if(status < 0)
@ -380,15 +497,17 @@ pCon);
} }
/* first zero the HM */ /* first zero the HM */
if(self->eHistMode == ePSD && self->iTimeChan > 2){ if(pInternal->eHistMode == ePSD && self->data->nTimeChan > 2){
/* /*
this is special for AMOR and should be replaced by -1, -1, -1 this is special for AMOR and should be replaced by -1, -1, -1
logic ASAP logic ASAP
*/ */
nHist = (self->iDims[0]*self->iDims[1] + 2) *self->iTimeChan; nHist = (self->data->iDim[0]*self->data->iDim[1] + 2) *
self->data->nTimeChan;
status = SINQHMZero(pInternal->pMaster,-1,-1,-1); status = SINQHMZero(pInternal->pMaster,-1,-1,-1);
}else{ }else{
status = SINQHMZero(pInternal->pMaster,-1,0,self->iRank*self->iLength); status = SINQHMZero(pInternal->pMaster,-1,0,
self->data->rank*getHMDataLength(self->data));
} }
/* /*
status = SINQHMZero(pInternal->pMaster,-1,-1,-1); status = SINQHMZero(pInternal->pMaster,-1,-1,-1);
@ -745,8 +864,8 @@ pCon);
pInternal = self->pPriv; pInternal = self->pPriv;
/* we do not need to do a lot of copying when datasizes match! */ /* we do not need to do a lot of copying when datasizes match! */
iByte = (iEnd - iStart) * self->iBinWidth; iByte = (iEnd - iStart) * pInternal->iBinWidth;
if(self->iBinWidth == sizeof(HistInt)) if(pInternal->iBinWidth == sizeof(HistInt))
{ {
/* read HM */ /* read HM */
status = SINQHMRead(pInternal->pMaster, status = SINQHMRead(pInternal->pMaster,
@ -779,7 +898,7 @@ pCon);
} }
/* convert to correct datasize */ /* convert to correct datasize */
switch(self->iBinWidth) switch(pInternal->iBinWidth)
{ {
case 1: case 1:
pPtr = (char *)pData; pPtr = (char *)pData;
@ -831,7 +950,7 @@ pCon);
pInternal = self->pPriv; pInternal = self->pPriv;
/* allocate storage */ /* allocate storage */
iByte = iEnd * self->iBinWidth; iByte = iEnd * pInternal->iBinWidth;
pData = (void *)malloc(iByte*sizeof(char)); pData = (void *)malloc(iByte*sizeof(char));
if(!pData) if(!pData)
{ {
@ -841,7 +960,7 @@ pCon);
memset(pData,0,iByte); memset(pData,0,iByte);
/* convert from long to supported binwidth */ /* convert from long to supported binwidth */
switch(self->iBinWidth) switch(pInternal->iBinWidth)
{ {
case 1: case 1:
pPtr = (char *)pData; pPtr = (char *)pData;
@ -926,10 +1045,10 @@ pCon);
pInternal = self->pPriv; pInternal = self->pPriv;
/* get memory */ /* get memory */
if(self->eHistMode == ePSD && self->iTimeChan > 2){ if(pInternal->eHistMode == ePSD && self->data->nTimeChan > 2){
nHist = self->iDims[0]*self->iDims[1]*self->iTimeChan; nHist = self->data->iDim[0]*self->data->iDim[1]*self->data->nTimeChan;
} else { } else {
nHist = self->iRank*self->iLength; nHist = getHMDataLength(self->data);
} }
plData = (HistInt *)malloc(nHist*sizeof(HistInt)); plData = (HistInt *)malloc(nHist*sizeof(HistInt));
if(!plData) if(!plData)
@ -989,7 +1108,10 @@ pCon);
StringDictAddPair(pOption,"yoff","100"); StringDictAddPair(pOption,"yoff","100");
StringDictAddPair(pOption,"yfac","10"); StringDictAddPair(pOption,"yfac","10");
StringDictAddPair(pOption,"init","1"); StringDictAddPair(pOption,"init","1");
StringDictAddPair(pOption,"histmode","normal");
StringDictAddPair(pOption,"overflowmode","ceil");
StringDictAddPair(pOption,"binwidth","4");
/* initialise our private data structure */ /* initialise our private data structure */
pInternal = (SinqHMDriv *)malloc(sizeof(SinqHMDriv)); pInternal = (SinqHMDriv *)malloc(sizeof(SinqHMDriv));
if(!pInternal) if(!pInternal)
@ -999,7 +1121,11 @@ pCon);
} }
memset(pInternal,0,sizeof(SinqHMDriv)); memset(pInternal,0,sizeof(SinqHMDriv));
pNew->pPriv = pInternal; pNew->pPriv = pInternal;
pInternal->eHistMode = eHNormal;
pInternal->eFlow = eOCeil;
pInternal->iBinWidth = 4;
/* configure all those functions */ /* configure all those functions */
pNew->Configure = SQConfigure; pNew->Configure = SQConfigure;
pNew->Start = SQStart; pNew->Start = SQStart;

View File

@ -1,5 +1,5 @@
#line 60 "sinqhmdriv.w" #line 63 "sinqhmdriv.w"
/*-------------------------------------------------------------------------- /*--------------------------------------------------------------------------
S I N Q H M S I N Q H M
@ -21,18 +21,21 @@
pSINQHM pMaster; pSINQHM pMaster;
int iLastHMError; int iLastHMError;
int iLastCTError; int iLastCTError;
HistMode eHistMode;
int iBinWidth;
OverFlowMode eFlow;
} SinqHMDriv; } SinqHMDriv;
#line 73 "sinqhmdriv.w" #line 76 "sinqhmdriv.w"
/*-------------------------------------------------------------------------*/ /*-------------------------------------------------------------------------*/
#line 55 "sinqhmdriv.w" #line 58 "sinqhmdriv.w"
pHistDriver CreateSINQDriver(pStringDict pOption); pHistDriver CreateSINQDriver(pStringDict pOption);
int isSINQHMDriv(pHistDriver test); int isSINQHMDriv(pHistDriver test);
#line 75 "sinqhmdriv.w" #line 78 "sinqhmdriv.w"
#endif #endif

View File

@ -30,6 +30,9 @@ $\langle$SQType {\footnotesize ?}$\rangle\equiv$
\mbox{}\verb@ pSINQHM pMaster;@\\ \mbox{}\verb@ pSINQHM pMaster;@\\
\mbox{}\verb@ int iLastHMError;@\\ \mbox{}\verb@ int iLastHMError;@\\
\mbox{}\verb@ int iLastCTError;@\\ \mbox{}\verb@ int iLastCTError;@\\
\mbox{}\verb@ HistMode eHistMode;@\\
\mbox{}\verb@ int iBinWidth;@\\
\mbox{}\verb@ OverFlowMode eFlow;@\\
\mbox{}\verb@ } SinqHMDriv;@\\ \mbox{}\verb@ } SinqHMDriv;@\\
\mbox{}\verb@@$\diamond$ \mbox{}\verb@@$\diamond$
\end{list} \end{list}

View File

@ -25,6 +25,9 @@ already reflected by the driver private data structure:
pSINQHM pMaster; pSINQHM pMaster;
int iLastHMError; int iLastHMError;
int iLastCTError; int iLastCTError;
HistMode eHistMode;
int iBinWidth;
OverFlowMode eFlow;
} SinqHMDriv; } SinqHMDriv;
@} @}

539
tdchm.c Normal file
View File

@ -0,0 +1,539 @@
/*--------------------------------------------------------------------------
This is a driver for the TDC histogram memory as supplied with the
Risoe instruments. This system uses a Z80 processor internally.
Communication is via a GPIB interface. For more information on this
device consult documentation available from Risoe.
The TDC needs a separate counter for controlling the count operation.
The counter is connected to the TDC and inhibits histogramming when the
counter is not ready. This is alos why many of the functions in this
file chain down to a counter.
copyright: see file COPYRIGHT
Mark Koennecke, February 2003
--------------------------------------------------------------------------*/
#include <string.h>
#include <stdlib.h>
#include <assert.h>
#include <math.h>
#include "fortify.h"
#include "sics.h"
#include "countdriv.h"
#include "counter.h"
#include "HistMem.h"
#include "stringdict.h"
#include "HistDriv.i"
#include "ecb.h"
/*-------------------------- private definitions -----------------------*/
typedef enum {HMX, HMY, HMXY} TDCModes;
#define MAXTDCCHANNELS (128*128)
#define COMMERROR -301
#define MAXEXCEEDED -302
/*------------------------- private data structure ---------------------*/
typedef struct{
TDCModes mode;
int map;
int bank;
unsigned char fillByte;
int range;
int n;
int errorCode;
pCounter counter;
pECB tdc;
} Tdc, *pTdc;
/*=======================================================================*/
static int downloadConfiguration(pTdc self){
int status;
Z80_reg in, out;
int function;
/*
map
*/
in.d = (unsigned char)self->map;
status = ecbExecute(self->tdc,134,in,&out);
if(status != 1){
return status;
}
/*
mode
*/
switch(self->mode){
case HMX:
function = 129;
break;
case HMY:
function = 130;
break;
caseHMXY:
function = 128;
break;
default:
assert(0);
}
status = ecbExecute(self->tdc,function,in,&out);
if(status != 1){
return status;
}
return 1;
}
/*----------------------------------------------------------------------*/
static int TDCConfigure(pHistDriver self, SConnection *pCon,
pStringDict pOpt, SicsInterp *pSics){
pTdc tdc = NULL;
char pValue[80];
float value;
int status;
assert(self);
tdc = (pTdc)self->pPriv;
assert(tdc);
status = StringDictGet(pOpt,"mode",pValue,79);
assert(status); /* defaults should have been set in driver creation*/
if(strcmp(pValue,"HMX") == 0){
tdc->mode = HMX;
}else if(strcmp(pValue,"HMY") == 0){
tdc->mode = HMY;
}else if(strcmp(pValue,"HMXY") == 0){
tdc->mode = HMXY;
} else {
SCWrite(pCon,"ERROR: invalid HM mode defaulted to HMXY",eError);
tdc->mode = HMXY;
}
status = StringDictGetAsNumber(pOpt,"map",&value);
if(!status){
SCWrite(pCon,"ERROR: invalid map value",eError);
} else {
tdc->map = (int)rint(value);
}
status = StringDictGetAsNumber(pOpt,"bank",&value);
if(!status){
SCWrite(pCon,"ERROR: invalid bank value",eError);
} else {
tdc->bank = (int)rint(value);
if(tdc->bank != 0 && tdc->bank != 1){
SCWrite(pCon,"ERROR: invalid bank value defaulted to 0",eError);
tdc->bank = 0;
}
}
status = StringDictGetAsNumber(pOpt,"range",&value);
if(!status){
SCWrite(pCon,"ERROR: invalid range value",eError);
} else {
tdc->range = (int)rint(value);
}
status = StringDictGetAsNumber(pOpt,"n",&value);
if(!status){
SCWrite(pCon,"ERROR: invalid n value",eError);
} else {
tdc->n = (int)rint(value);
}
status = StringDictGet(pOpt,"counter",pValue,79);
/*
ignore errors here, in order to support operations without counter
*/
if(!status){
tdc->counter = NULL;
}
tdc->counter = FindCommandData(pSics,pValue,"SingleCounter");
tdc->fillByte = 0;
status = downloadConfiguration(tdc);
if(!status){
tdc->errorCode = status;
return 0;
}
status = StringDictGet(pOpt,"ecb",pValue,79);
assert(status);
tdc->tdc = FindCommandData(pSics,pValue,"ECB");
if(tdc->tdc == NULL){
SCWrite(pCon,"ERROR: failed to locate ECB system, critical!",eError);
return 0;
}
self->iReconfig = 0;
return 1;
}
/*=======================================================================*/
static int clearTdc(pTdc self, unsigned char fill){
Z80_reg in, out;
in.b = self->bank;
in.c = fill;
in.d = 0;
return ecbExecute(self->tdc,133,in,&out);
}
/*---------------------------------------------------------------------*/
static int enableTdc(pTdc self){
Z80_reg in, out;
/*
range and n are obscure parameters
*/
in.c = 0;
in.b = self->range;
in.d = (char) ((self->n >>8) && 255);
in.e = (char)(self->n && 255);
return ecbExecute(self->tdc,131,in,&out);
}
/*-----------------------------------------------------------------------*/
static int TDCStart(pHistDriver self, SConnection *pCon){
pTdc tdc = NULL;
int status;
assert(self);
tdc = (pTdc)self->pPriv;
assert(tdc);
tdc->errorCode = 0;
status = clearTdc(tdc,0);
if(status != 1){
tdc->errorCode = COMMERROR;
return HWFault;
}
status = enableTdc(tdc);
if(status != 1){
tdc->errorCode = COMMERROR;
return HWFault;
}
/*
start the counter if available
*/
if(tdc->counter != NULL){
tdc->counter->pDriv->fPreset = self->fCountPreset;
tdc->counter->pDriv->eMode = self->eCount;
return tdc->counter->pDriv->Start(tdc->counter->pDriv);
}
return 1;
}
/*=====================================================================*/
static int disableTdc(pTdc self){
Z80_reg in, out;
return ecbExecute(self->tdc,132,in,&out);
}
/*-------------------------------------------------------------------*/
static int TDCHalt(pHistDriver self){
pTdc tdc = NULL;
int status;
assert(self);
tdc = (pTdc)self->pPriv;
assert(tdc);
tdc->errorCode = 0;
status = disableTdc(tdc);
if(status != 1){
tdc->errorCode = COMMERROR;
return HWFault;
}
if(tdc->counter != NULL){
tdc->counter->pDriv->Halt(tdc->counter->pDriv);
}
return 1;
}
/*=====================================================================*/
static int TDCCountStatus(pHistDriver self, SConnection *pCon){
pTdc tdc = NULL;
int status;
float fControl;
assert(self);
tdc = (pTdc)self->pPriv;
assert(tdc);
if(tdc->counter != NULL){
return tdc->counter->pDriv->GetStatus(tdc->counter->pDriv,&fControl);
}
/*
The TDC does not seem to have a means to figure if it is counting or not
or to do some sort of progress report.
*/
return HWIdle;
}
/*=====================================================================*/
static int TDCGetError(pHistDriver self, int *iCode, char *perror,
int iErrlen){
pTdc tdc = NULL;
assert(self);
tdc = (pTdc)self->pPriv;
assert(tdc);
*iCode = tdc->errorCode;
switch(tdc->errorCode){
case COMMERROR:
strncpy(perror,"Communication problem with TDC",iErrlen);
break;
case MAXEXCEEDED:
strncpy(perror,"Requested to many channels for read",iErrlen);
break;
default:
if(tdc->counter != NULL){
tdc->counter->pDriv->GetError(tdc->counter->pDriv,
iCode,perror,iErrlen);
} else{
strncpy(perror,"Undefined error code",iErrlen);
}
break;
}
return 1;
}
/*=====================================================================*/
static int TDCFixIt(pHistDriver self, int iCode){
pTdc tdc = NULL;
int result;
assert(self);
tdc = (pTdc)self->pPriv;
assert(tdc);
switch(iCode){
case COMMERROR:
ecbClear(tdc->tdc);
result = COREDO;
break;
default:
if(tdc->counter != NULL){
result = tdc->counter->pDriv->TryAndFixIt(tdc->counter->pDriv,
iCode);
} else{
result = COTERM;
}
break;
}
return result;
}
/*=====================================================================*/
static int TDCGetData(pHistDriver self, SConnection *pCon){
pTdc tdc = NULL;
assert(self);
tdc = (pTdc)self->pPriv;
assert(tdc);
if(tdc->counter != NULL){
return tdc->counter->pDriv->ReadValues(tdc->counter->pDriv);
}
return 1;
}
/*======================================================================*/
static long TDCGetMonitor(pHistDriver self, int i, SConnection *pCon){
pTdc tdc = NULL;
assert(self);
tdc = (pTdc)self->pPriv;
assert(tdc);
if(tdc->counter != NULL){
return GetMonitor(tdc->counter,i,pCon);
}
return -9999; /* no monitor available */
}
/*======================================================================*/
static float TDCGetTime(pHistDriver self,SConnection *pCon){
pTdc tdc = NULL;
assert(self);
tdc = (pTdc)self->pPriv;
assert(tdc);
if(tdc->counter != NULL){
return GetCountTime(tdc->counter,pCon);
}
return -9999.99; /* no time available */
}
/*=====================================================================*/
static int TDCPause(pHistDriver self, SConnection *pCon){
pTdc tdc = NULL;
int status;
assert(self);
tdc = (pTdc)self->pPriv;
assert(tdc);
status = disableTdc(tdc);
if(status != 1){
tdc->errorCode = COMMERROR;
return HWFault;
}
if(tdc->counter != NULL){
return tdc->counter->pDriv->Pause(tdc->counter->pDriv);
}
return 1;
}
/*=====================================================================*/
static int TDCContinue(pHistDriver self, SConnection *pCon){
pTdc tdc = NULL;
int status;
assert(self);
tdc = (pTdc)self->pPriv;
assert(tdc);
status = enableTdc(tdc);
if(status != 1){
tdc->errorCode = COMMERROR;
return HWFault;
}
if(tdc->counter != NULL){
return tdc->counter->pDriv->Continue(tdc->counter->pDriv);
}
return 1;
}
/*=======================================================================*/
static int TDCFree(pHistDriver self){
free(self->pPriv);
}
/*======================================================================*/
static int TDCSetHistogram(pHistDriver self, SConnection *pCon,
int i, int iStart, int iEnd, HistInt *pData){
pTdc tdc = NULL;
int status;
char pBueffel[256];
Ecb_pack data;
assert(self);
tdc = (pTdc)self->pPriv;
assert(tdc);
sprintf(pBueffel,
"WARNING: SetHistogram can only fill HM with a fill byte %s",
"\n using firts value for that");
SCWrite(pCon,pBueffel,eWarning);
data.result = pData[0];
status = clearTdc(tdc,data.b.byt0);
if(status != 1){
tdc->errorCode = COMMERROR;
return HWFault;
}
return 1;
}
/*======================================================================*/
static int TDCPreset(pHistDriver self, SConnection *pCon, HistInt iVal){
pTdc tdc = NULL;
int status;
char pBueffel[256];
Ecb_pack data;
assert(self);
tdc = (pTdc)self->pPriv;
assert(tdc);
sprintf(pBueffel,
"WARNING: Preset can only fill HM with a fill byte %s",
"\n using first value for that");
SCWrite(pCon,pBueffel,eWarning);
data.result = iVal;
status = clearTdc(tdc,data.b.byt0);
if(status != 1){
tdc->errorCode = COMMERROR;
return HWFault;
}
return 1;
}
/*======================================================================*/
static int TDCGetHistogram(pHistDriver self, SConnection *pCon,
int bank, int iStart, int length,
HistInt *pData){
pTdc tdc = NULL;
int status;
unsigned short address, byteCount;
assert(self);
tdc = (pTdc)self->pPriv;
assert(tdc);
if(length >= MAXTDCCHANNELS){
tdc->errorCode = MAXEXCEEDED;
return HWFault;
}
address = 0;
byteCount = length *4;
status = ecbDMARead(tdc->tdc,address,pData,byteCount);
if(status != 1){
tdc->errorCode = COMMERROR;
return HWFault;
}
return 1;
}
/*====================================================================*/
pHistDriver MakeTDCHM(pStringDict pOption){
pHistDriver pNew = NULL;
pTdc tdc = NULL;
/* create the general driver */
pNew = CreateHistDriver(pOption);
if(!pNew)
{
return NULL;
}
/* add our options */
StringDictAddPair(pOption,"ecb","blub");
StringDictAddPair(pOption,"range","0");
StringDictAddPair(pOption,"n","0");
StringDictAddPair(pOption,"bank","0");
StringDictAddPair(pOption,"mode","HMXY");
StringDictAddPair(pOption,"counter","Gwendolin");
StringDictAddPair(pOption,"map","9");
/* initialise our private data structure */
tdc = (pTdc)malloc(sizeof(Tdc));
if(tdc == NULL){
free(pNew);
return NULL;
}
memset(tdc,0,sizeof(Tdc));
tdc->map = 9;
tdc->mode = HMXY;
pNew->pPriv = tdc;
/* configure all those functions */
pNew->Configure = TDCConfigure;
pNew->Start = TDCStart;
pNew->Halt = TDCHalt;
pNew->GetCountStatus = TDCCountStatus;
pNew->GetError = TDCGetError;
pNew->TryAndFixIt = TDCFixIt;
pNew->GetData = TDCGetData;
pNew->GetHistogram = TDCGetHistogram;
pNew->SetHistogram = TDCSetHistogram;
pNew->GetMonitor = TDCGetMonitor;
pNew->GetTime = TDCGetTime;
pNew->Preset = TDCPreset;
pNew->FreePrivate = TDCFree;
pNew->Pause = TDCPause;
pNew->Continue = TDCContinue;
return pNew;
}

15
tdchm.h Normal file
View File

@ -0,0 +1,15 @@
/*--------------------------------------------------------------------------
This is a driver for the TDC histogram memory as supplied with the
Risoe instruments. This system uses a Z80 processor internally.
Communication is via a GPIB interface. For more information on this
device consult documentation available from Risoe.
copyright: see file COPYRIGHT
Mark Koennecke, February 2003
--------------------------------------------------------------------------*/
#ifndef TDCHM
#define TDCHM
pHistDriver MakeTDCHM(pStringDict pOption);
#endif