diff --git a/HistDriv.i b/HistDriv.i index aba84ffa..08ff93c0 100644 --- a/HistDriv.i +++ b/HistDriv.i @@ -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 diff --git a/HistMem.h b/HistMem.h index 3463f60e..7e5ea964 100644 --- a/HistMem.h +++ b/HistMem.h @@ -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 diff --git a/HistMem.i b/HistMem.i index 27781143..6bd675e4 100644 --- a/HistMem.i +++ b/HistMem.i @@ -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 diff --git a/Makefile b/Makefile index 929a3d63..80e124c7 100644 --- a/Makefile +++ b/Makefile @@ -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 diff --git a/anticollider.c b/anticollider.c index 70c58f94..b4f51aad 100644 --- a/anticollider.c +++ b/anticollider.c @@ -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 diff --git a/dynstring.h b/dynstring.h index 8f1e4298..e159f7db 100644 --- a/dynstring.h +++ b/dynstring.h @@ -85,5 +85,4 @@ returns the current length of the dynamic string. */ -#endif - \ No newline at end of file +#endif diff --git a/ecb.c b/ecb.c index 7bb05a9e..4173d560 100644 --- a/ecb.c +++ b/ecb.c @@ -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; diff --git a/ecb.h b/ecb.h index 40ce4160..dd5b861e 100644 --- a/ecb.h +++ b/ecb.h @@ -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, diff --git a/ecb.w b/ecb.w index dca243ee..ae471d98 100644 --- a/ecb.w +++ b/ecb.w @@ -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: diff --git a/ecbdriv.c b/ecbdriv.c index 0387df35..0d3c53ed 100644 --- a/ecbdriv.c +++ b/ecbdriv.c @@ -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! */ } /*------------------------------------------------------------------------*/ diff --git a/histdriv.c b/histdriv.c index 7252dde1..6e27586b 100644 --- a/histdriv.c +++ b/histdriv.c @@ -63,18 +63,16 @@ return NULL; } 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); } diff --git a/histmem.c b/histmem.c index 84f883ce..8d7bd5b5 100644 --- a/histmem.c +++ b/histmem.c @@ -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 ) @@ -1513,21 +1249,12 @@ 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*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 ) @@ -1599,22 +1317,13 @@ 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)); if(!lData) @@ -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,25 +1378,17 @@ /* 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)); if(!lData) @@ -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 @@ - - diff --git a/histogram.tex b/histogram.tex index 507b292d..ab301442 100644 --- a/histogram.tex +++ b/histogram.tex @@ -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@@\\ diff --git a/histogram.w b/histogram.w index 8b45399b..ac29bd47 100644 --- a/histogram.w +++ b/histogram.w @@ -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 @> diff --git a/histsim.c b/histsim.c index 410e541f..5acacba1 100644 --- a/histsim.c +++ b/histsim.c @@ -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; } /* diff --git a/hmdata.c b/hmdata.c new file mode 100644 index 00000000..fb564c8e --- /dev/null +++ b/hmdata.c @@ -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 +#include +#include +#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; + } diff --git a/hmdata.h b/hmdata.h new file mode 100644 index 00000000..6823d3b0 --- /dev/null +++ b/hmdata.h @@ -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 + diff --git a/hmdata.w b/hmdata.w new file mode 100644 index 00000000..14c44c9d --- /dev/null +++ b/hmdata.w @@ -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 + +@ + +@ + +#endif + +@} \ No newline at end of file diff --git a/motreg.c b/motreg.c index 7fbeb0be..c6c93214 100644 --- a/motreg.c +++ b/motreg.c @@ -95,7 +95,8 @@ 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); pDriv = GetDrivableInterface(self->motorData); @@ -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; diff --git a/sicsstat.tcl b/sicsstat.tcl index e8ac652a..060930d9 100644 --- a/sicsstat.tcl +++ b/sicsstat.tcl @@ -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 diff --git a/sinqhmdriv.c b/sinqhmdriv.c index 54faa6d4..5ffb2a4a 100644 --- a/sinqhmdriv.c +++ b/sinqhmdriv.c @@ -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,7 +1108,10 @@ 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)); if(!pInternal) @@ -999,7 +1121,11 @@ 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; pNew->Start = SQStart; diff --git a/sinqhmdriv.i b/sinqhmdriv.i index f928d003..045f7d7d 100644 --- a/sinqhmdriv.i +++ b/sinqhmdriv.i @@ -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 diff --git a/sinqhmdriv.tex b/sinqhmdriv.tex index e597de6c..79ecc1dc 100644 --- a/sinqhmdriv.tex +++ b/sinqhmdriv.tex @@ -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} diff --git a/sinqhmdriv.w b/sinqhmdriv.w index 23219a3f..09e8c343 100644 --- a/sinqhmdriv.w +++ b/sinqhmdriv.w @@ -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; @} diff --git a/tdchm.c b/tdchm.c new file mode 100644 index 00000000..b7f874a0 --- /dev/null +++ b/tdchm.c @@ -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 +#include +#include +#include +#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; +} diff --git a/tdchm.h b/tdchm.h new file mode 100644 index 00000000..1490d5da --- /dev/null +++ b/tdchm.h @@ -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