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

View File

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

View File

@ -1,5 +1,5 @@
#line 496 "histogram.w"
#line 479 "histogram.w"
/*---------------------------------------------------------------------------
H I S T M E M -- Internal
@ -11,7 +11,7 @@
#ifndef SICSHISTMEMINT
#define SICSHISTMEMINT
#line 262 "histogram.w"
#line 250 "histogram.w"
typedef struct __HistMem {
pObjectDescriptor pDes;
@ -22,14 +22,9 @@
pICountable pCountInt;
pICallBack pCall;
pStringDict pOption;
HistInt *iLocalData;
int iLocalLength;
int iLocalUpdate;
time_t tLocal;
int iUpdateIntervall;
} HistMem;
#line 506 "histogram.w"
#line 489 "histogram.w"
#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 \
polterwrite.o fourlib.o motreg.o motreglist.o anticollider.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
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);
self->sequenceList = LLDcreate(sizeof(Sequence));
self->level = 0;
self->level = -1; /* otherwise level 0 will not be started */
/*
evaluate colliderScript

View File

@ -86,4 +86,3 @@
*/
#endif

36
ecb.c
View File

@ -20,8 +20,9 @@
#include "ecb.i"
/*------------- private defines and error codes ------------------------*/
#define ACKN ('\6') /* Acknowledge character */
#define READ_BYTES 3
#define READ_BYTES 3
#define WRITE_BYTES 4
#define DMAREAD 5
#define ECB_BYTES 65536L
typedef union /* Used to swap bytes in 'address' and 'byte_count' */
@ -179,6 +180,33 @@ int ecbRead(pECB self, unsigned short address,
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,
void *buffer, int byteCount){
@ -317,9 +345,13 @@ int ECBAction(SConnection *pCon, SicsInterp *pSics, void *pData,
return 0;
}
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);
return 1;
} else if(strcmp(argv[1],"clear") == 0){
ecbClear(self);
SCSendOK(pCon);
return 1;
} else {
SCWrite(pCon,"ERROR: ECB does not understand keyword", eError);
return 0;

2
ecb.h
View File

@ -32,6 +32,8 @@ typedef struct {
void *buffer, int byteCount);
int ecbWrite(pECB self, unsigned short address,
void *buffer, int byteCount);
int ecbDMARead(pECB self, unsigned short address, void *buffer,
unsigned short byteCount);
void ecbClear(pECB self);
int fixECBError(pECB self);
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);
int ecbWrite(pECB self, unsigned short address,
void *buffer, int byteCount);
int ecbDMARead(pECB self, unsigned short address, void *buffer,
unsigned short byteCount);
void ecbClear(pECB self);
int fixECBError(pECB self);
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
buffer. Please note that address in this contest is an address in the
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
address. Please note that address in this contest is an address in the
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
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
SICS interpreter for the ECB is represented through the ECB Factory
function:

View File

@ -67,8 +67,9 @@ Parameter indexes in ObPar array and meanings
#define STEPS2DEG 13 /* conversion factor motor steps to Degree */
#define DEG2STEP 14 /* conversion factor from degree to encoder digits */
#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 -------------------------*/
#define MAX_ENCODER 40
@ -411,7 +412,8 @@ static int loadMulti(pECBMotDriv self){
mult_chan = (unsigned char)rint(ObVal(self->driverPar,MULTCHAN));
in.b = -1; /* SET_PORT */
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);
if(status != 1){
self->errorCode = COMMERROR;
@ -557,7 +559,7 @@ static int controlMotor(pECBMotDriv self, int enable){
*/
in.e = 8;
in.b = 11; /* set control signal */
in.c = -self->ecbIndex;
in.c = self->ecbIndex;
status = ecbExecute(self->ecb,MOPARA,in,&out);
if(status != 1){
self->errorCode = COMMERROR;
@ -698,9 +700,6 @@ static int checkStatusResponse(pECBMotDriv self, Z80_reg out){
return HWFault;
} else if(out.b & 32){
return HWBusy;
} else if(out.b & 64){
self->errorCode = ECBINHIBIT;
return HWFault;
} else if(out.b & 16){
self->errorCode = ECBLIMIT;
return HWFault;
@ -1142,6 +1141,7 @@ static void initializeParameters(pECBMotDriv self){
ObParInit(self->driverPar,STEPS2DEG,"step2deg",1,usMugger);
ObParInit(self->driverPar,DEG2STEP,"step2dig",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! */
}
/*------------------------------------------------------------------------*/

View File

@ -64,17 +64,15 @@
}
memset(pNew,0,sizeof(HistDriver));
pNew->data = makeHMData();
if(!pNew->data)
{
free(pNew);
return NULL;
}
/* initialise defaults */
pNew->eHistMode = eHNormal;
StringDictAddPair(pOption,"histmode","normal");
pNew->eFlow = eOCeil;
StringDictAddPair(pOption,"overflowmode","ceil");
pNew->iRank = 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++)
{
sprintf(pDim,"dim%1.1d",i);
@ -84,8 +82,6 @@
pNew->eCount = eTimer;
pNew->iReconfig = 1;
pNew->iUpdate = 0;
pNew->iTimeChan = 1;
return pNew;
}
@ -98,59 +94,12 @@
{
self->FreePrivate(self);
}
if(self->data)
{
killHMData(self->data);
}
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)
{
@ -166,138 +115,5 @@
assert(pOpt);
assert(pCon);
/* 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;
}
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;
return configureHMdata(self->data,pOpt,pCon);
}

498
histmem.c
View File

@ -62,6 +62,7 @@
#include "dynstring.h"
#include "event.h"
#include "status.h"
#include "tdchm.h"
/*
#define LOADDEBUG 1
*/
@ -106,12 +107,13 @@
fprintf(fd,"%s preset %f\n",name,fVal);
/* time binning if TOF */
if(self->pDriv->eHistMode == eHTOF)
if(isInTOFMode(self->pDriv->data))
{
fprintf(fd,"%s genbin %f %f %d\n",
name, self->pDriv->fTime[0],
self->pDriv->fTime[1] - self->pDriv->fTime[0],
self->pDriv->iTimeChan);
name, self->pDriv->data->timeBinning[0],
self->pDriv->data->timeBinning[1] -
self->pDriv->data->timeBinning[0],
self->pDriv->data->nTimeChan);
fprintf(fd,"%s init\n",name);
}
@ -167,9 +169,7 @@
iRet = self->pDriv->Start(self->pDriv, pCon);
if(iRet == OKOK)
{
self->pDriv->iUpdate = 1;
self->iLocalUpdate = 1;
self->tLocal = time(NULL) + self->iUpdateIntervall;
updateHMData(self->pDriv->data);
return iRet;
}
else
@ -214,7 +214,7 @@
iRet = self->pDriv->Pause(self->pDriv, pCon);
if(iRet == OKOK)
{
self->pDriv->iUpdate = 1;
updateHMData(self->pDriv->data);
return iRet;
}
else
@ -259,7 +259,7 @@
iRet = self->pDriv->Continue(self->pDriv, pCon);
if(iRet == OKOK)
{
self->pDriv->iUpdate = 1;
updateHMData(self->pDriv->data);
return iRet;
}
else
@ -312,20 +312,19 @@
}
else
{
self->iLocalUpdate = 1;
updateHMData(self->pDriv->data);
return HWBusy;
}
}
if(eCt == HWBusy)
self->iLocalUpdate = 1;
updateHMData(self->pDriv->data);
if(eCt == HWIdle)
{
/* force an update of local histogram data with next
GetHistogram
*/
self->iLocalUpdate = 1;
self->tLocal = 0;
updateHMData(self->pDriv->data);
}
return eCt;
@ -426,11 +425,6 @@
pNew->pCountInt->Halt = HistHalt;
pNew->pCountInt->Pause = HistPause;
pNew->pCountInt->Continue = HistContinue;
pNew->iLocalData = NULL;
pNew->iLocalLength = 0;
pNew->iUpdateIntervall = 0;
pNew->iLocalUpdate = 1;
pNew->tLocal = 0;
/* initialise options dictionary */
pNew->pOption = CreateStringDict();
@ -451,6 +445,10 @@
{
pNew->pDriv = CreateSINQDriver(pNew->pOption);
}
else if(strcmp(driver,"tdc") == 0)
{
pNew->pDriv = MakeTDCHM(pNew->pOption);
}
else /* no driver found */
{
DeleteDescriptor(pNew->pDes);
@ -494,10 +492,6 @@
{
DeleteStringDict(self->pOption);
}
if(self->iLocalData)
{
free(self->iLocalData);
}
free(self);
}
/*-------------------------------------------------------------------------*/
@ -568,22 +562,6 @@
assert(self);
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);
if(!iRet)
{
@ -596,8 +574,6 @@
SCWrite(pCon,"ERROR: failed to configure histogram memory",eError);
return 0;
}
self->iLocalUpdate = 1;
self->tLocal = 0;
return 1;
}
/*--------------------------------------------------------------------------*/
@ -642,124 +618,23 @@
/*--------------------------------------------------------------------------*/
int GetHistDim(pHistMem self, int iDim[MAXDIM], int *nDim)
{
int i, myDim;
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[i] = self->pDriv->iDims[i];
myDim++;
}
iDim[*nDim] = getNoOfTimebins(self->pDriv->data);
*nDim ++;
}
if(self->pDriv->eHistMode == eHTOF
|| self->pDriv->eHistMode == ePSD
|| self->pDriv->eHistMode == eSANSTOF)
{
iDim[myDim] = self->pDriv->iTimeChan;
myDim++;
}
*nDim = myDim;
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,
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);
/* 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;
return sumHMDataRectangle(self,pCon,iStart,iEnd);
}
/*---------------------------------------------------------------------------*/
CounterMode GetHistCountMode(pHistMem self)
@ -806,15 +681,15 @@
const float *GetHistTimeBin(pHistMem self, int *iLength)
{
assert(self);
*iLength = self->pDriv->iTimeChan;
return self->pDriv->fTime;
*iLength = getNoOfTimebins(self->pDriv->data);
return getTimeBinning(self->pDriv->data);
}
/*-------------------------------------------------------------------------*/
int GetHistLength(pHistMem self)
{
assert(self);
return self->pDriv->iRank*self->pDriv->iLength;
return getHMDataLength(self->pDriv->data);
}
/*--------------------------------------------------------------------------*/
float GetHistCountTime(pHistMem self, SConnection *pCon)
@ -898,9 +773,7 @@
i,iStart,iEnd,lData);
if(iRet == OKOK)
{
self->iLocalUpdate = 1;
self->tLocal = 0;
self->pDriv->iUpdate = 0;
updateHMData(self->pDriv->data);
return 1;
}
else
@ -921,87 +794,20 @@
int GetHistogram(pHistMem self, SConnection *pCon,
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);
if(!self->iInit)
{
if(!self->iInit)
{
SCWrite(pCon,"ERROR: histogram memory not initialised",eError);
return 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 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;
if(iEnd > iDataLen/sizeof(HistInt))
{
SCWrite(pCon,"WARNING: truncating request to fit data space",eWarning);
iEnd = (iDataLen/sizeof(HistInt)) - 1;
}
return getHMDataHistogram(self,pCon,i,iStart,iEnd,lData);
}
/*-------------------------------------------------------------------------*/
int GetHistogramDirect(pHistMem self, SConnection *pCon,
@ -1048,10 +854,6 @@
/*-----------------------------------------------------------------------*/
HistInt *GetHistogramPointer(pHistMem self, SConnection *pCon)
{
int ii, iErr, iRet, iCopy;
char pBueffel[512], pError[80];
HistInt *lHist = NULL;
assert(self);
if(!self->iInit)
@ -1060,67 +862,7 @@
return NULL;
}
if(self->iLocalData == NULL)
{
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;
return getHMDataBufferPointer(self,pCon);
}
/*--------------------------------------------------------------------------*/
int PresetHistogram(pHistMem self, SConnection *pCon, HistInt lVal)
@ -1142,9 +884,7 @@
iRet = self->pDriv->Preset(self->pDriv,pCon,lVal);
if(iRet == OKOK)
{
self->pDriv->iUpdate = 0;
self->iLocalUpdate = 1;
self->tLocal = 0;
updateHMData(self->pDriv->data);
return 1;
}
else
@ -1161,6 +901,7 @@
}
return 0;
}
/*----------------------------------------------------------------------*/
/*-----------------------------------------------------------------------*/
static int HMCountInterest(int iEvent, void *pEvent, void *pUser)
{
@ -1183,6 +924,22 @@
}
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 argc, char *argv[])
@ -1276,7 +1033,8 @@
/* authorise */
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]);
SCWrite(pCon,pBueffel,eError);
return 0;
@ -1304,7 +1062,6 @@
fVal = atof(argv[2]);
if(!SCMatchRights(pCon,self->iAccess))
{
SCWrite(pCon,"ERROR: you are not priviledged for attempted operation",eError);
return 0;
}
iRet = SetHistPreset(self,fVal);
@ -1324,7 +1081,6 @@
{
if(!SCMatchRights(pCon,self->iAccess))
{
SCWrite(pCon,"ERROR: you are not priviledged for attempted operation",eError);
return 0;
}
self->iExponent = atoi(argv[2]);
@ -1346,7 +1102,6 @@
strtolower(argv[2]);
if(!SCMatchRights(pCon,self->iAccess))
{
SCWrite(pCon,"ERROR: you are not priviledged for attempted operation",eError);
return 0;
}
if(strcmp(argv[2],"timer") == 0)
@ -1386,8 +1141,6 @@
}
else
{
SCWrite(pCon,
"ERROR: you are not privileged for attempted operation",eError);
return 0;
}
}
@ -1410,8 +1163,6 @@
}
else
{
SCWrite(pCon,
"ERROR: you are not privileged for attempted operation",eError);
return 0;
}
}
@ -1429,8 +1180,6 @@
}
else
{
SCWrite(pCon,
"ERROR: you are not privileged for attempted operation",eError);
return 0;
}
}
@ -1448,8 +1197,6 @@
}
else
{
SCWrite(pCon,
"ERROR: you are not privileged for attempted operation",eError);
return 0;
}
}
@ -1458,8 +1205,6 @@
/* check user rights */
if(!SCMatchRights(pCon,self->iAccess))
{
SCWrite(pCon,
"ERROR: you are not priviledged for attempted operation",eError);
return 0;
}
@ -1491,15 +1236,6 @@
}
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 */
iStart = 0;
if(argc > 3 )
@ -1514,20 +1250,11 @@
iStart = 0;
}
/* optional iEnd, default to maximum */
iEnd = self->pDriv->iLength;
if(argc > 4)
{
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);
}
if(argc > 4){
iEnd = checkHMEnd(self,argv[4]);
} else {
iEnd = checkHMEnd(self,NULL);
}
/* allocate data storage and get it */
lData = (HistInt *)malloc(iEnd*sizeof(HistInt));
@ -1577,15 +1304,6 @@
}
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 */
iStart = 0;
if(argc > 3 )
@ -1600,20 +1318,11 @@
iStart = 0;
}
/* optional iEnd, default to maximum */
iEnd = self->pDriv->iLength;
if(argc > 4)
{
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);
}
if(argc > 4){
iEnd = checkHMEnd(self,argv[4]);
} else {
iEnd = checkHMEnd(self,NULL);
}
/* allocate data storage and get it */
lData = (HistInt *)malloc((iEnd+1)*sizeof(HistInt));
@ -1659,15 +1368,6 @@
}
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 */
iStart = 0;
if(argc > 3 )
@ -1678,24 +1378,16 @@
/* check iStart */
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;
}
/* optional iEnd, default to maximum */
iEnd = self->pDriv->iLength;
if(argc > 4)
{
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);
}
if(argc > 4){
iEnd = checkHMEnd(self,argv[4]);
} else {
iEnd = checkHMEnd(self,NULL);
}
/* allocate data storage and get it */
lData = (HistInt *)malloc((iEnd+1)*sizeof(HistInt));
@ -1731,7 +1423,8 @@
else if(strcmp(argv[1],"notimebin") == 0)
{
sprintf(pBueffel,
"%s.notimebin = %d",argv[0], self->pDriv->iTimeChan);
"%s.notimebin = %d",argv[0],
getNoOfTimebins(self->pDriv->data));
SCWrite(pCon,pBueffel,eValue);
return 1;
}
@ -1740,9 +1433,9 @@
{
Tcl_DStringInit(&tResult);
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);
}
/* Write it */
@ -1757,7 +1450,6 @@
{
if(!SCMatchRights(pCon,usMugger))
{
SCWrite(pCon,"ERROR: you are not authorised for this operation",eError);
return 0;
}
if(GetStatus() == eCounting)
@ -1795,22 +1487,13 @@
/* do it */
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);
return 0;
}
for(i = 0; i < iNum; i++)
{
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;
genTimeBinning(self->pDriv->data,
(float)dStart,(float)dStep,iNum);
SCSendOK(pCon);
return 1;
}
@ -1819,7 +1502,6 @@
{
if(!SCMatchRights(pCon,usMugger))
{
SCWrite(pCon,"ERROR: yoy are not authorised for this operation",eError);
return 0;
}
if(argc < 4)
@ -1843,20 +1525,11 @@
}
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;
}
self->pDriv->fTime[iNum] = 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;
}
setTimeBin(self->pDriv->data,iNum, (float)dStep);
self->iInit = 0;
SCSendOK(pCon);
return 1;
@ -1864,8 +1537,7 @@
/* clear time bin info */
else if(strcmp(argv[1],"clearbin") == 0)
{
self->pDriv->iTimeChan = 0;
self->iInit = 1;
clearTimeBinning(self->pDriv->data);
SCSendOK(pCon);
}
/*-------- sum */
@ -1924,5 +1596,3 @@

View File

@ -31,6 +31,7 @@ $\langle$Modes {\footnotesize ?}$\rangle\equiv$
\end{list}
\end{minipage}\\[4ex]
\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
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
@ -101,6 +102,11 @@ command. Then on initialisation first the logical histogram memory
evaluates the general options and then the driver in its Config
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}
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
\mbox{}\verb@@\\
\mbox{}\verb@ typedef struct __HistDriver {@\\
\mbox{}\verb@ /* configuration 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@ pHMdata data;@\\
\mbox{}\verb@ /* counting operations data */@\\
\mbox{}\verb@ CounterMode eCount;@\\
\mbox{}\verb@ float fCountPreset;@\\
@ -185,15 +182,6 @@ $\langle$HistType {\footnotesize ?}$\rangle\equiv$
\end{minipage}\\[4ex]
\end{flushleft}
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.
@ -326,11 +314,6 @@ $\langle$HistST {\footnotesize ?}$\rangle\equiv$
\mbox{}\verb@ pICountable pCountInt;@\\
\mbox{}\verb@ pICallBack pCall;@\\
\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@@$\diamond$
\end{list}
@ -630,7 +613,7 @@ following.
\mbox{}\verb@----------------------------------------------------------------------------*/@\\
\mbox{}\verb@#ifndef SICSHISTDRIV@\\
\mbox{}\verb@#define SICSHISTDRIV@\\
\mbox{}\verb@#define MAXCHAN 16834 @\\
\mbox{}\verb@#include "hmdata.h"@\\
\mbox{}\verb@@\\
\mbox{}\verb@@$\langle$HistType {\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
} HistMode;
@}
These modes are specific to the SINQ histogram memory.
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
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
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}
Adhering to the Sics paradigm of dividing any device into a logical device
@ -82,16 +88,7 @@ definition:
@d HistType @{
typedef struct __HistDriver {
/* configuration data */
HistMode eHistMode;
OverFlowMode eFlow;
int iRank;
int iDims[MAXDIM];
int nDim;
int iLength;
int iBinWidth;
float fTime[MAXCHAN];
int iTimeChan;
pHMdata data;
/* counting operations data */
CounterMode eCount;
float fCountPreset;
@ -145,15 +142,6 @@ definition:
@}
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.
@ -269,11 +257,6 @@ histogram memory object is fairly simple:
pICountable pCountInt;
pICallBack pCall;
pStringDict pOption;
HistInt *iLocalData;
int iLocalLength;
int iLocalUpdate;
time_t tLocal;
int iUpdateIntervall;
} HistMem;
@}
According to the general Sics object interface the first field is the object
@ -485,7 +468,7 @@ following.
----------------------------------------------------------------------------*/
#ifndef SICSHISTDRIV
#define SICSHISTDRIV
#define MAXCHAN 16834
#include "hmdata.h"
@< HistType@>
@< HistDrivProt @>

View File

@ -58,7 +58,7 @@
*/
static int iSet = 0;
static HistInt iSetVal = 0;
static HistMode eHistMode;
/*--------------------------------------------------------------------------*/
static int SimConfig(pHistDriver self, SConnection *pCon,
pStringDict pOption, SicsInterp *pSics)
@ -67,14 +67,13 @@
char pData[132];
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;
self->iLength = iLength;
iLength *= self->data->nTimeChan;
}
/*

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

View File

@ -1,22 +1,139 @@
# Counter counter
counter SetPreset 60.000000
counter SetMode Timer
# Motor a77
a77 sign 1.000000
a77 SoftZero 0.000000
a77 SoftLowerLim -30.000000
a77 SoftUpperLim 30.000000
a77 Fixed -1.000000
a77 InterruptMode 0.000000
a77 AccessCode 2.000000
# Motor 2t
2t sign 1.000000
2t SoftZero 0.000000
2t SoftLowerLim -120.000000
2t SoftUpperLim 120.000000
2t Fixed -1.000000
2t InterruptMode 0.000000
2t AccessCode 2.000000
# Motor atz
atz sign 1.000000
atz SoftZero 0.000000
atz SoftLowerLim -3900.000000
atz SoftUpperLim 0.000000
atz Fixed -1.000000
atz InterruptMode 0.000000
atz AccessCode 2.000000
# Motor az1
az1 sign 1.000000
az1 SoftZero 0.000000
az1 SoftLowerLim -3900.000000
az1 SoftUpperLim 0.000000
az1 Fixed -1.000000
az1 InterruptMode 0.000000
az1 AccessCode 2.000000
# Motor dv
dv sign 1.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 setAccess 2
comment UNKNOWN

View File

@ -68,6 +68,57 @@
self->iLastHMError = 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
is configured and a client connection will be built. Configure requires,
@ -80,14 +131,14 @@
SinqHMDriv *pInternal;
int status, iMode;
char pError[132];
char pHMComputer[256];
char pHMComputer[256], pValue[80], pBueffel[256];
float fVal;
char pcCounter[256];
CommandList *pCom = NULL;
int iStart = 0;
int iInit = 0, i;
int iInit = 0, i, iRet;
int xOff, xFac, yOff, yFac;
int iPort;
int iPort, iLength;
assert(self);
assert(self->pPriv);
@ -97,9 +148,70 @@
pInternal = (SinqHMDriv *)self->pPriv;
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 */
if( (self->iBinWidth != 1) && (self->iBinWidth != 2)
&& (self->iBinWidth != 4))
if( (pInternal->iBinWidth != 1) && (pInternal->iBinWidth != 2)
&& (pInternal->iBinWidth != 4))
{
PrintHMError("Unsuported BinWidth specified, 1,2,4 are permissable",pCon);
return 0;
@ -137,7 +249,7 @@
pCom = FindCommand(pSics,pcCounter);
if(!pCom)
{
PrintHMError("WARNING: no EL737 counter for HM found! ",
PrintHMError("WARNING: no counter for HM found! ",
pCon);
pInternal->pCounter = NULL;
}
@ -147,7 +259,7 @@
if(!pInternal->pCounter->pDes->GetInterface(pInternal->pCounter,
COUNTID))
{
PrintHMError("EL737 counter for histogram memory is invalid",
PrintHMError("Counter for histogram memory is invalid",
pCon);
return 0;
}
@ -170,8 +282,10 @@
/* in any case let us propagate the state of affairs to
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
@ -205,8 +319,8 @@
return 0;
}
if( (self->iBinWidth != 1) && (self->iBinWidth != 2)
&& (self->iBinWidth != 4))
if( (pInternal->iBinWidth != 1) && (pInternal->iBinWidth != 2)
&& (pInternal->iBinWidth != 4))
{
PrintHMError("Unsuported BinWidth specified, 1,2,4 are permissable",
pCon);
@ -215,7 +329,7 @@ pCon);
/* configure */
switch(self->eHistMode)
switch(pInternal->eHistMode)
{
case eHTransparent:
iMode = SQHM__TRANS;
@ -226,22 +340,25 @@ pCon);
case eHTOF:
iMode = SQHM__TOF;
/* recalculate some parameters */
self->iLength = 1;
for(i = 0; i < self->iRank; i++)
iLength = 1;
for(i = 0; i < self->data->rank; i++)
{
self->iLength *= self->iDims[i];
iLength *= self->data->iDim[i];
}
self->iLength *= self->iTimeChan;
SINQHMDefineBank(pInternal->pMaster,0,0,self->iDims[0],
self->fTime,self->iTimeChan);
iLength *= self->data->nTimeChan;
SINQHMDefineBank(pInternal->pMaster,0,0,self->data->iDim[0],
self->data->timeBinning,
self->data->nTimeChan);
break;
case eSANSTOF:
iMode = SQHM__TOF;
self->iLength = self->iDims[0]*self->iDims[1];
self->iLength *= self->iTimeChan;
iLength = self->data->iDim[0]*self->data->iDim[1];
iLength *= self->data->nTimeChan;
SINQHMDefineBank(pInternal->pMaster,0,0,
(self->iDims[0]*self->iDims[1]) + 3,
self->fTime,self->iTimeChan);
(self->data->iDim[0]*self->data->iDim[1])
+ 3,
self->data->timeBinning,
self->data->nTimeChan);
break;
case eHStrobo:
iMode = SQHM__HM_PSD | SQHM__STROBO;
@ -256,7 +373,7 @@ pCon);
PrintHMError("Unsupported mode requested",pCon);
return 0;
}
switch(self->eFlow)
switch(pInternal->eFlow)
{
case eOIgnore:
iMode = iMode | SQHM__BO_IGN;
@ -274,13 +391,13 @@ pCon);
PrintHMError("Unsupported overflowmode requested",pCon);
return 0;
}
if(self->eHistMode != ePSD)
if(pInternal->eHistMode != ePSD)
{
status = SINQHMConfigure(pInternal->pMaster,
iMode,
self->iRank,
self->iLength,
self->iBinWidth,
self->data->rank,
getHMDataLength(self->data),
pInternal->iBinWidth,
0,0);
}
else
@ -320,15 +437,15 @@ pCon);
/* xSize and ySize are supposed to be in dim */
status = SINQHMConfigurePSD(pInternal->pMaster,
iMode,
self->iDims[0],
self->data->iDim[0],
xOff,
xFac,
self->iDims[1],
self->data->iDim[1],
yOff,
yFac,
self->iBinWidth,
self->fTime,
self->iTimeChan);
pInternal->iBinWidth,
self->data->timeBinning,
self->data->nTimeChan);
}
if(status < 0)
@ -380,15 +497,17 @@ pCon);
}
/* 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
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);
}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);
@ -745,8 +864,8 @@ pCon);
pInternal = self->pPriv;
/* we do not need to do a lot of copying when datasizes match! */
iByte = (iEnd - iStart) * self->iBinWidth;
if(self->iBinWidth == sizeof(HistInt))
iByte = (iEnd - iStart) * pInternal->iBinWidth;
if(pInternal->iBinWidth == sizeof(HistInt))
{
/* read HM */
status = SINQHMRead(pInternal->pMaster,
@ -779,7 +898,7 @@ pCon);
}
/* convert to correct datasize */
switch(self->iBinWidth)
switch(pInternal->iBinWidth)
{
case 1:
pPtr = (char *)pData;
@ -831,7 +950,7 @@ pCon);
pInternal = self->pPriv;
/* allocate storage */
iByte = iEnd * self->iBinWidth;
iByte = iEnd * pInternal->iBinWidth;
pData = (void *)malloc(iByte*sizeof(char));
if(!pData)
{
@ -841,7 +960,7 @@ pCon);
memset(pData,0,iByte);
/* convert from long to supported binwidth */
switch(self->iBinWidth)
switch(pInternal->iBinWidth)
{
case 1:
pPtr = (char *)pData;
@ -926,10 +1045,10 @@ pCon);
pInternal = self->pPriv;
/* get memory */
if(self->eHistMode == ePSD && self->iTimeChan > 2){
nHist = self->iDims[0]*self->iDims[1]*self->iTimeChan;
if(pInternal->eHistMode == ePSD && self->data->nTimeChan > 2){
nHist = self->data->iDim[0]*self->data->iDim[1]*self->data->nTimeChan;
} else {
nHist = self->iRank*self->iLength;
nHist = getHMDataLength(self->data);
}
plData = (HistInt *)malloc(nHist*sizeof(HistInt));
if(!plData)
@ -989,6 +1108,9 @@ pCon);
StringDictAddPair(pOption,"yoff","100");
StringDictAddPair(pOption,"yfac","10");
StringDictAddPair(pOption,"init","1");
StringDictAddPair(pOption,"histmode","normal");
StringDictAddPair(pOption,"overflowmode","ceil");
StringDictAddPair(pOption,"binwidth","4");
/* initialise our private data structure */
pInternal = (SinqHMDriv *)malloc(sizeof(SinqHMDriv));
@ -999,6 +1121,10 @@ pCon);
}
memset(pInternal,0,sizeof(SinqHMDriv));
pNew->pPriv = pInternal;
pInternal->eHistMode = eHNormal;
pInternal->eFlow = eOCeil;
pInternal->iBinWidth = 4;
/* configure all those functions */
pNew->Configure = SQConfigure;

View File

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

View File

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

View File

@ -25,6 +25,9 @@ already reflected by the driver private data structure:
pSINQHM pMaster;
int iLastHMError;
int iLastCTError;
HistMode eHistMode;
int iBinWidth;
OverFlowMode eFlow;
} 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