From cb3bf30bbf2e62a7eb4febd5346af36a1caff792 Mon Sep 17 00:00:00 2001 From: koennecke Date: Wed, 13 Sep 2006 07:12:00 +0000 Subject: [PATCH] - Fixes to hkl code - Fixes to make RITA work - tasub extended to calculate UB from cell alone, support for elastic mode - New MultiCounter as abstraction for counting on HM's - regression test driver for counters --- conman.c | 32 +- countdriv.h | 6 + counter.c | 13 +- devexec.c | 5 +- fitcenter.c | 6 + fourlib.c | 24 ++ hipadaba.c | 208 +++++++++- hipadaba.h | 62 ++- histmem.c | 9 +- hkl.c | 87 ++-- hkl.i | 1 - hkl.tex | 1 - hkl.w | 1 - hmdata.c | 6 +- lin2ang.c | 4 +- macro.c | 13 +- make_gen | 2 +- mesure.c | 25 +- motor.c | 1064 +++++++++++++++++++++++++----------------------- motor.h | 1 + multicounter.c | 380 +++++++++++++++++ multicounter.h | 19 + nxscript.c | 15 + ofac.c | 4 + regresscter.c | 262 ++++++++++++ scan.c | 33 +- sicsdata.c | 76 +++- sicsdata.h | 7 + sicsdata.w | 9 + sicshipadaba.c | 105 +++-- sicshipadaba.h | 64 ++- tasdrive.c | 44 +- tasub.c | 44 +- 33 files changed, 1961 insertions(+), 671 deletions(-) create mode 100644 multicounter.c create mode 100644 multicounter.h create mode 100644 regresscter.c diff --git a/conman.c b/conman.c index b034f765..3f4378b1 100644 --- a/conman.c +++ b/conman.c @@ -701,12 +701,21 @@ static void writeToLogFiles(SConnection *self, char *buffer) SICSLogWrite(buffer,iOut); /* write to commandlog if user or manager privilege */ - if(SCGetRights(self) <= usUser && self->iMacro != 1) + if(SCGetRights(self) <= usUser) { - sprintf(pBueffel,"To sock %d :",iRet); - sendingConnection = self; - WriteToCommandLog(pBueffel,buffer); - sendingConnection = NULL; + if(self->iMacro != 1) + { + sprintf(pBueffel,"To sock %d :",iRet); + WriteToCommandLog(pBueffel,buffer); + } + else + { + if(iOut == eError || iOut == eWarning) + { + sprintf(pBueffel,"To sock %d :",iRet); + WriteToCommandLog(pBueffel,buffer); + } + } } /* put it into the interpreter if present */ @@ -1437,9 +1446,16 @@ pDynString SCEndBuffering(SConnection *pCon) { strcat(pBueffel,"CONT or CRON>> "); } - sendingConnection = self; - WriteToCommandLog(pBueffel,pCommand); - sendingConnection = NULL; + /* + * This is a fix to suppress cron messages in the success + * case + */ + if(SCGetWriteFunc(self) != SCNotWrite) + { + sendingConnection = self; + WriteToCommandLog(pBueffel,pCommand); + sendingConnection = NULL; + } } /* invoke */ diff --git a/countdriv.h b/countdriv.h index 4bb86fed..4f7603aa 100644 --- a/countdriv.h +++ b/countdriv.h @@ -88,4 +88,10 @@ * file: mcstascounter.c */ pCounterDriver NewMcStasCounter(char *name); + + /* + * for regression testing + * file: regresscter.c + */ + pCounterDriver NewRegressCounter(char *name); #endif diff --git a/counter.c b/counter.c index a29a443f..1af90206 100644 --- a/counter.c +++ b/counter.c @@ -103,9 +103,9 @@ if(iRet == OKOK) { self->isUpToDate = 0; - self->badStatusCount = 0; + self->badStatusCount = 0; self->tStart = time(&tX); - InvokeCallBack(self->pCall,COUNTSTART,pCon); + InvokeCallBack(self->pCall,COUNTSTART,pCon); return iRet; } else @@ -314,7 +314,7 @@ for(i = 0; i < 3; i++) { iRet = self->pDriv->ReadValues(self->pDriv); - if(iRet) + if(iRet == OKOK) { self->isUpToDate = 1; return OKOK; @@ -529,6 +529,13 @@ } } + /* + * test for regression testing counter + */ + if(strcmp(argv[2],"regress") == 0){ + pDriv = NewRegressCounter(argv[1]); + } + /* * test for McStas simulation counter driver */ diff --git a/devexec.c b/devexec.c index 45967987..2148c7b4 100644 --- a/devexec.c +++ b/devexec.c @@ -668,7 +668,6 @@ static int errorDevice(pCheckContext pCheck){ ExeInterest(pCheck->self, pCheck->pDev, "finished with problem"); DevexecLog("STOP",pCheck->pDev->name); - DeleteDevEntry(pCheck->pDev); LLDnodeDelete(pCheck->self->iList); status = LLDnodePtr2Prev(pCheck->self->iList); SCWrite(pCheck->self->pOwner, "", eFinish); @@ -676,7 +675,9 @@ static int errorDevice(pCheckContext pCheck){ if(pCheck->pDrivInt != NULL) { pCheck->pDrivInt->iErrorCount++; } - return checkInterrupt(pCheck,status); + status = checkInterrupt(pCheck,status); + DeleteDevEntry(pCheck->pDev); + return status; } /*-------------------------------------------------------------------------*/ static int testFinish(pExeList self){ diff --git a/fitcenter.c b/fitcenter.c index ceb37452..dbfeb30d 100644 --- a/fitcenter.c +++ b/fitcenter.c @@ -421,6 +421,7 @@ pFit self = NULL; int iRet; char pBueffel[256]; + pDynString buf = NULL; self = (pFit)pData; assert(self); @@ -470,6 +471,7 @@ } /* print results */ + SCStartBuffering(pCon); sprintf(pBueffel,"Estimated Peak Center: %f, StdDev: %f \n", self->fCenter,self->fStddev); SCWrite(pCon,pBueffel,eValue); @@ -477,6 +479,10 @@ SCWrite(pCon,pBueffel,eValue); sprintf(pBueffel,"Approximate FWHM: %f\n",self->FWHM); SCWrite(pCon,pBueffel,eValue); + buf = SCEndBuffering(pCon); + if(buf != NULL){ + SCWrite(pCon,GetCharArray(buf),eValue); + } return 1; } diff --git a/fourlib.c b/fourlib.c index 96bffda1..f954f322 100644 --- a/fourlib.c +++ b/fourlib.c @@ -625,6 +625,10 @@ int findAllowedBisecting(double lambda, MATRIX z1, float fSet[4], return 0; } + if(testFunc(userData, fSet, mask) == 1){ + return 1; + } + for(psi = .0; psi < 360.; psi += .5){ rotatePsi(om,chi,phi,psi,&ompsi,&chipsi,&phipsi); fTest[0] = stt; @@ -638,6 +642,26 @@ int findAllowedBisecting(double lambda, MATRIX z1, float fSet[4], } return 1; } + /* + * if chi close to 0, or 180, try to wrap phi onto om + */ + if(ABS(fTest[2] - .0) < .1 || ABS(fTest[2] - 180.) < .1){ + fTest[1] -= fTest[3]; + fTest[3] = .0; + if(fTest[1] < 0.){ + fTest[1] += 360.; + } + if(fTest[1] > 360.0){ + fTest[1] -= 360.; + } + status = testFunc(userData,fTest,mask); + if(status == 1){ + for(i = 0; i < 4; i++){ + fSet[i] = fTest[i]; + } + return 1; + } + } if(mask[0] == 0) { /* * useless: when two theta problem there is no solution diff --git a/hipadaba.c b/hipadaba.c index 29390248..05d49179 100644 --- a/hipadaba.c +++ b/hipadaba.c @@ -290,6 +290,60 @@ hdbValue makeHdbValue(int datatype, int length){ } return val; } +/*------------------------------------------------------------------------*/ +hdbValue makeHdbData(int datatype, int length, void *data){ + hdbValue val; + + memset(&val,0,sizeof(hdbValue)); + val.dataType = datatype; + + switch(datatype){ + case HIPINT: + if(data != NULL){ + memcpy(&val.v.intValue,data,sizeof(int)); + } + break; + case HIPFLOAT: + if(data != NULL){ + memcpy(&val.v.doubleValue,data,sizeof(double)); + } + break; + case HIPINTAR: + case HIPINTVARAR: + val.arrayLength = length; + val.v.intArray = malloc(length*sizeof(int)); + if(val.v.intArray != NULL){ + memset(val.v.intArray,0,length*sizeof(int)); + } + if(data != NULL){ + memcpy(val.v.intArray,data,length*sizeof(int)); + } + break; + case HIPFLOATAR: + case HIPFLOATVARAR: + val.arrayLength = length; + val.v.floatArray = malloc(length*sizeof(double)); + if(val.v.floatArray != NULL){ + memset(val.v.floatArray,0,length*sizeof(double)); + } + if(data != NULL){ + memcpy(val.v.floatArray,data,length*sizeof(double)); + } + break; + case HIPTEXT: + if(data != NULL){ + val.v.text = strdup((char *)data); + } else { + val.v.text = strdup("UNKNOWN"); + } + val.arrayLength = strlen(val.v.text); + break; + case HIPOBJ: + val.v.obj = data; + break; + } + return val; +} /*-------------------------------------------------------------------------*/ hdbValue MakeHdbInt(int initValue){ hdbValue result; @@ -411,6 +465,13 @@ int compareHdbValue(hdbValue v1, hdbValue v2){ } return 1; break; + case HIPOBJ: + if(v2.v.obj == v1.v.obj) { + return 1; + } else { + return 0; + } + break; default: assert(0); break; @@ -424,6 +485,35 @@ int cloneHdbValue(hdbValue *source, hdbValue *clone){ clone->dataType = source->dataType; return copyHdbValue(source, clone); } +/*-------------------------------------------------------------------------*/ +int getHdbValueLength(hdbValue v){ + int length = 0; + switch(v.dataType){ + case HIPNONE: + break; + case HIPINT: + length = sizeof(int); + break; + case HIPFLOAT: + length = sizeof(double); + break; + case HIPINTAR: + case HIPINTVARAR: + length = v.arrayLength * sizeof(int); + break; + case HIPFLOATAR: + case HIPFLOATVARAR: + length = v.arrayLength * sizeof(double); + break; + case HIPTEXT: + length = strlen(v.v.text); + break; + case HIPOBJ: + length = sizeof(void *); + break; + } + return length; +} /*================= node functions ========================================*/ pHdb MakeHipadabaNode(char *name, int datatype, int length){ pHdb pNew = NULL; @@ -655,7 +745,6 @@ void AppendHipadabaCallback(pHdb node, int type, pHdbCallback newCB){ newCB->previous = current; } } -/*-------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/ void PrependHipadabaCallback(pHdb node, int type, pHdbCallback newCB){ switch(type){ @@ -779,6 +868,9 @@ int copyHdbValue(hdbValue *source, hdbValue *target){ target->v.floatArray[i] = source->v.floatArray[i]; } break; + case HIPOBJ: + target->v.obj = source->v.obj; + break; default: /* * unknown data type @@ -818,3 +910,117 @@ int GetHipadabaPar(pHdb node, hdbValue *v, void *callData){ copyHdbValue(&node->value,v); return 1; } +/*----------------------------------------------------------------------------*/ +static int calcDataLength(pHdb node, int testLength){ + int length = 0; + + length = getHdbValueLength(node->value); + if(node->value.dataType == HIPFLOATVARAR || + node->value.dataType == HIPINTVARAR || + node->value.dataType == HIPTEXT){ + length = testLength; + } + return length; +} +/*--------------------------------------------------------------------------*/ +int SetHdbPar(pHdb node, int dataType, void *data, int length, + void *callData){ + int status; + hdbValue v; + + if(node->value.dataType == HIPNONE){ + return 1; + } + + if(dataType != node->value.dataType){ + return HDBTYPEMISMATCH; + } + if(length != calcDataLength(node,length)){ + return HDBLENGTHMISMATCH; + } + + v = makeHdbData(dataType, length, data); + status = InvokeCallbackChain(node->writeCallbacks, node, callData, v); + if(status == 1) { + copyHdbValue(&v,&node->value); + } + return status; +} +/*--------------------------------------------------------------------------*/ +int UpdateHdbPar(pHdb node, int dataType, void *data, int length, + void *callData){ + int status; + hdbValue v; + + if(node->value.dataType == HIPNONE){ + return 1; + } + + if(dataType != node->value.dataType){ + return HDBTYPEMISMATCH; + } + if(length != calcDataLength(node,length)){ + return HDBLENGTHMISMATCH; + } + + v = makeHdbData(dataType,length,data); + + status = InvokeCallbackChain(node->updateCallbacks, node, callData, v); + if(status == 1) { + copyHdbValue(&v,&node->value); + } + return status; +} +/*-----------------------------------------------------------------------------*/ +int GetHdbPar(pHdb node, int dataType, void *data, int length, + void *callData){ + int status, toCopy; + hdbValue v; + + if(dataType != node->value.dataType){ + return HDBTYPEMISMATCH; + } + + if(length != calcDataLength(node,length)){ + return HDBLENGTHMISMATCH; + } + + status = InvokeCallbackChain(node->readCallbacks, node, callData, v); + if(status != 1 ){ + return status; + } + switch(dataType){ + case HIPNONE: + break; + case HIPINT: + memcpy(data,&node->value.v.intValue,sizeof(int)); + break; + case HIPFLOAT: + memcpy(data,&node->value.v.doubleValue,sizeof(double)); + break; + case HIPINTAR: + case HIPINTVARAR: + memcpy(data,node->value.v.intArray, + node->value.arrayLength*sizeof(int)); + break; + case HIPTEXT: + toCopy = strlen(node->value.v.text); + if(toCopy > length){ + toCopy = length; + } + memcpy(data,&node->value.v.text, toCopy); + break; + case HIPFLOATAR: + case HIPFLOATVARAR: + memcpy(data,node->value.v.floatArray, + node->value.arrayLength*sizeof(double)); + break; + case HIPOBJ: + memcpy(data,&node->value.v.obj,sizeof(void *)); + break; + default: + assert(0); + break; + } + return 1; +} diff --git a/hipadaba.h b/hipadaba.h index b7218aae..e51a5f24 100644 --- a/hipadaba.h +++ b/hipadaba.h @@ -33,10 +33,14 @@ #define HIPFLOATAR 4 #define HIPINTVARAR 5 #define HIPFLOATVARAR 6 +#define HIPOBJ 7 /* -------- callback types */ #define HCBSET 0 #define HCBUPDATE 1 #define HCBREAD 2 +/*--------- error codes */ +#define HDBTYPEMISMATCH -7701 +#define HDBLENGTHMISMATCH -7702 /*===================== structure definitions ===================================*/ typedef struct __hdbValue { int dataType; @@ -47,6 +51,7 @@ typedef struct __hdbValue { char *text; int *intArray; double *floatArray; + void *obj; }v; }hdbValue; /*------------------------------------------------------------------------------*/ @@ -77,6 +82,15 @@ typedef struct __hdbcallback { }hdbCallback, *pHdbCallback; /*======================== Function protoypes: hdbData ========================*/ hdbValue makeHdbValue(int datatype, int length); +/** + * make a hdbValue and initailize it with the data in the void + * pointer. Do not initialise when data = NULL. + * @param dataType The datatype of the hdbValue + * @param The array length of the hdbValue + * @param data Initialisation data for hdbValue + * @return a suitably defined hdbValue + */ +hdbValue makeHdbData(int datatype, int length, void *data); /** * wrap an integer as an hdbValue * @param initValue the initial value of the int @@ -147,6 +161,12 @@ int compareHdbValue(hdbValue v1, hdbValue v2); * @return 1 on success, 0 on when out of memory */ int cloneHdbValue(hdbValue *source, hdbValue *clone); +/** + * get the length of the hdbValue in bytes. + * @param v The hdbValue to calculate the length for + * @return the number of data bytes + */ +int getHdbValueLength(hdbValue v); /*========================== function protoypes: Nodes =======================*/ /** * make a new hipadaba node @@ -156,7 +176,7 @@ int cloneHdbValue(hdbValue *source, hdbValue *clone); */ pHdb MakeHipadabaNode(char *name, int datatype, int length); /** - * add a child to a node + * add a child to a node at the end of the child list. * @param parent The node to which to add the child * @param child The node to add */ @@ -250,8 +270,8 @@ void InternalRemoveHipadabaCallback(pHdb root, int internalID); */ int SetHipadabaPar(pHdb node, hdbValue v, void *callData); /** - * Update a hipadaba parameter. This is an internal update of a parameter, during - * driving etc. + * Update a hipadaba parameter. This is an internal update of a parameter, + * during driving etc. * @param node The node for which to update the parameter * @param v The new value for the node * @param callData Additonal context data to be passed to the callback functions @@ -266,5 +286,41 @@ int UpdateHipadabaPar(pHdb node, hdbValue v, void *callData); * @return 0 on failure, 1 on success */ int GetHipadabaPar(pHdb node, hdbValue *v, void *callData); +/** + * Set a hipadaba parameter. This is an external set for a parameter. It may cause + * motors to start driving etc. + * @param node The node for which to set the parameter + * param dataType The datatype the value ought to have + * @param data A pointer to the data to set. + * @param length The length of data + * @param callData Additonal context data to be passed to the callback functions + * @return 0 on failure, a negative error code on failure + */ +int SetHdbPar(pHdb node, int dataType, void *data, int length, + void *callData); +/** + * Updates a hipadaba parameter. This does not cause an active parameter to + * start driving but invokes all nitifications which may be regsitered on + * this parameter. + * @param node The node for which to set the parameter + * param dataType The datatype the value ought to have + * @param data A pointer to the data to set. + * @param length The length of data + * @param callData Additonal context data to be passed to the callback functions + * @return 0 on failure, a negative error code on failure + */ +int UpdateHdbPar(pHdb node, int dataType, void *data, int length, + void *callData); +/** + * Read a hipadaba parameter + * @param node The node for which to read the parameter + * @param dataType The expected type of the data + * @param data A pointer to which data will be copied + * @param length The length of data. + * @param callData Additonal context data to be passed to the callback functions + * @return 0 on failure, a negative error code on failures. + */ +int GetHdbPar(pHdb node, int dataType, void *data, int length, + void *callData); #endif diff --git a/histmem.c b/histmem.c index 71d1a739..d29de6a1 100644 --- a/histmem.c +++ b/histmem.c @@ -171,7 +171,9 @@ iRet = self->pDriv->Start(self->pDriv, pCon); if(iRet == OKOK) { - updateHMData(self->pDriv->data); + /* send a COUNTSTART event */ + InvokeCallBack(self->pCall,COUNTSTART,pCon); + updateHMData(self->pDriv->data); return iRet; } else @@ -721,8 +723,6 @@ void HistDirty(pHistMem self) { assert(self); - /* send a COUNTSTART event */ - InvokeCallBack(self->pCall,COUNTSTART,pCon); /* start */ return StartDevice(GetExecutor(),"HistogramMemory", self->pDes, self, @@ -744,9 +744,6 @@ void HistDirty(pHistMem self) return 0; } - /* send a COUNTSTART event */ - InvokeCallBack(self->pCall,COUNTSTART,pCon); - /* wait till end */ iRet = Wait4Success(GetExecutor()); if(iRet == DEVINT) diff --git a/hkl.c b/hkl.c index 8d50deab..64c54a6b 100644 --- a/hkl.c +++ b/hkl.c @@ -61,7 +61,6 @@ fprintf(fd,"%s hm %d\n",name, self->iHM); fprintf(fd,"%s scantolerance %f\n", name,self->scanTolerance); fprintf(fd,"%s nb %d\n", name, self->iNOR); - fprintf(fd,"%s phiom %d\n", name, self->iOMPHI); return 1; } @@ -689,7 +688,7 @@ int hklInRange(void *data, float fSet[4], int mask[4]) fSet[0] = dTheta; /* for omega check against the limits +- SCANBORDER in order to allow for - a omega scan + a omega scan. */ MotorGetPar(self->pOmega,"softlowerlim",&fLimit); if((float)fSet[1] < fLimit + self->scanTolerance){ @@ -721,7 +720,7 @@ static int calculateBisecting(MATRIX z1, pHKL self, SConnection *pCon, float fSet[4], double myPsi, int iRetry) { double stt, om, chi, phi, psi, ompsi, chipsi, phipsi; - int i, test; + int i, test, mask[4]; /* just the plain angle calculation @@ -731,16 +730,31 @@ static int calculateBisecting(MATRIX z1, pHKL self, SConnection *pCon, return 0; } + fSet[0] = stt; + fSet[1] = om; + fSet[2] = chi; + fSet[3] = phi; if(iRetry == 1) { - rotatePsi(om,chi,phi,psi,&ompsi,&chipsi,&phipsi); + rotatePsi(om,chi,phi,myPsi,&ompsi,&chipsi,&phipsi); fSet[1] = ompsi; fSet[2] = circlify(chipsi); fSet[3] = circlify(phipsi); return 1; } else { - return findAllowedBisecting(self->fLambda, z1, fSet, hklInRange,self); + if(hklInRange(self,fSet, mask) == 1){ + return 1; + } else { + if(tryOmegaTweak(self,z1, &stt, &om, &chi, &phi) == 1){ + fSet[0] = stt; + fSet[1] = om; + fSet[2] = chi; + fSet[3] = phi; + return 1; + } else { + return findAllowedBisecting(self->fLambda, z1, fSet, hklInRange,self); + } + } } - } /*-----------------------------------------------------------------------*/ static int calculateNormalBeam(MATRIX z1, pHKL self, SConnection *pCon, @@ -789,7 +803,11 @@ static int calculateNormalBeam(MATRIX z1, pHKL self, SConnection *pCon, if(checkNormalBeam(omnb, &gamma, nu,fSet,pCon,self)){ return 1; } else { - return 0; + if(checkNormalBeam(360. - omnb, &gamma, nu, fSet,pCon,self)){ + return 1; + } else { + return 0; + } } } /*---------------------------------------------------------------------*/ @@ -850,7 +868,7 @@ static int calculateNormalBeamOmega(MATRIX z1, pHKL self, { if(checkNormalBeam(om, &gamma, nu,fSet,pCon,self)) { - return 1; + return 1; } } return 0; @@ -903,31 +921,7 @@ static int calculateNormalBeamOmega(MATRIX z1, pHKL self, if(self->iNOR == 0) { status = calculateBisecting(z1,self,pCon,fSet, myPsi, iRetry); - /* - * Betrand mode: wrap phi rotation into omega - */ - if(self->iOMPHI > 0) { - if(ABS(fSet[2] - .0) < .1 || ABS(fSet[2] - 180.) < .1){ - fSet[1] -= fSet[3]; - /* - fSet[1] = 360. - fSet[3]; - */ - fSet[3] = .0; - if(fSet[1] < 0.){ - fSet[1] += 360.; - } - if(fSet[1] > 360.0){ - fSet[1] -= 360.; - } - } else { - snprintf(pBueffel,511, - "ERROR: for omphi mode chi must be 0 or 180, is %f", - fSet[2]); - SCWrite(pCon,pBueffel,eError); - return 0; - } - } - } + } else if(self->iNOR == 1) { status = calculateNormalBeam(z1,self,pCon,fSet, myPsi, iRetry); @@ -1414,8 +1408,8 @@ ente: if(strcmp(argv[1],"list") == 0 ) { sprintf(pBueffel, - "lambda = %f Normal Beam = %d PHIOM = %d Quadrant = %d HM = %d", - self->fLambda, self->iNOR, self->iOMPHI, + "lambda = %f Normal Beam = %d Quadrant = %d HM = %d", + self->fLambda, self->iNOR, self->iQuad,self->iHM); SCWrite(pCon,pBueffel,eValue); sprintf(pBueffel,"UB = { %f %f %f", @@ -1654,29 +1648,6 @@ ente: SCSendOK(pCon); return 1; } -/*------------- phi omega mode (to be removed) */ - else if(strcmp(argv[1],"phiom") == 0) - { - if(argc < 3) - { - snprintf(pBueffel,511,"%s.phiom = %d",argv[0],self->iOMPHI); - SCWrite(pCon,pBueffel,eValue); - return 1; - } - if(!SCMatchRights(pCon,usUser)) - { - return 0; - } - if(!isNumeric(argv[2])) - { - sprintf(pBueffel,"ERROR: %s was not recognized as a number", argv[2]); - SCWrite(pCon,pBueffel,eError); - return 0; - } - self->iOMPHI = atoi(argv[2]); - SCSendOK(pCon); - return 1; - } /*------------- quadrant */ else if(strcmp(argv[1],"quadrant") == 0) { diff --git a/hkl.i b/hkl.i index 9665a544..14cbaed0 100644 --- a/hkl.i +++ b/hkl.i @@ -15,7 +15,6 @@ int iManual; double fLastHKL[5]; int iNOR; - int iOMPHI; int iQuad; int iHM; pMotor pTheta; diff --git a/hkl.tex b/hkl.tex index e62e69e1..bed73427 100644 --- a/hkl.tex +++ b/hkl.tex @@ -26,7 +26,6 @@ $\langle$hkldat {\footnotesize ?}$\rangle\equiv$ \mbox{}\verb@ int iManual;@\\ \mbox{}\verb@ double fLastHKL[5];@\\ \mbox{}\verb@ int iNOR;@\\ -\mbox{}\verb@ int iOMPHI;@\\ \mbox{}\verb@ int iQuad;@\\ \mbox{}\verb@ int iHM;@\\ \mbox{}\verb@ pMotor pTheta;@\\ diff --git a/hkl.w b/hkl.w index e22bb92c..a1b510d3 100644 --- a/hkl.w +++ b/hkl.w @@ -21,7 +21,6 @@ The object uses the following object data structure: int iManual; double fLastHKL[5]; int iNOR; - int iOMPHI; int iQuad; int iHM; pMotor pTheta; diff --git a/hmdata.c b/hmdata.c index 3bf42ed0..f491540b 100644 --- a/hmdata.c +++ b/hmdata.c @@ -406,10 +406,10 @@ long sumHMDataRectangle(pHistMem hist, SConnection *pCon, break; case 2: lSum = 0; - for(i = iStart[0]; i < iEnd[0]; i++){ - iIndex = i*self->iDim[1]; + for(i = iStart[1]; i < iEnd[1]; i++){ + iIndex = i*self->iDim[0]; lRowSum = SumRow(self->localBuffer,iHistLength, - iIndex+iStart[1], iIndex+iEnd[1]); + iIndex+iStart[0], iIndex+iEnd[0]); lSum += lRowSum; } break; diff --git a/lin2ang.c b/lin2ang.c index 5e5e6063..0c6de052 100644 --- a/lin2ang.c +++ b/lin2ang.c @@ -34,7 +34,7 @@ /*-------------------------- conversion routines -------------------------*/ static float ang2x(pLin2Ang self, float fAngle) { - return self->length*sin((fAngle+self->zero)/RD); + return self->length*tan((fAngle+self->zero)/RD); } /*-----------------------------------------------------------------------*/ static float x2ang(pLin2Ang self, float fX) @@ -44,7 +44,7 @@ assert(self->length > 0.); dt = fX/self->length; - return RD*asin(dt) - self->zero; + return RD*atan(dt) - self->zero; } /*============== functions in the interface ============================*/ static void *Lin2AngGetInterface(void *pData, int iID) diff --git a/macro.c b/macro.c index e98b50f1..92f385f0 100644 --- a/macro.c +++ b/macro.c @@ -2,7 +2,7 @@ All you need to evaluate macros with SICS - The implmentation for the macro stuff is complex and non intuitive. + The implementation for the macro stuff is complex and non intuitive. This is the price to pay for adding the extremly powerful and strong Tcl-interpreter to SICS. The problem is that Tcl does not know anything about connections and our error handling. We have @@ -891,14 +891,9 @@ static int ProtectedExec(ClientData clientData, Tcl_Interp *interp, if (pCommand != pBueffel) free(pCommand); if(iRet == TCL_OK) { - /* we do not now why, but at some time it was found that - we need a copy, and can not use pTcl->result directly - - SCWrite(pCon,pTcl->result,eStatus); - - let us use SCPrintf, which maked always a copy - */ - SCPrintf(pCon, eStatus, "%s", pTcl->result); + if(strlen(pTcl->result) > 0){ + SCPrintf(pCon, eStatus, "%s", pTcl->result); + } return 1; } else diff --git a/make_gen b/make_gen index 7840ac06..6af7f61f 100644 --- a/make_gen +++ b/make_gen @@ -31,7 +31,7 @@ SOBJ = network.o ifile.o conman.o SCinter.o splitter.o passwd.o \ hmdata.o nxscript.o tclintimpl.o sicsdata.o mcstascounter.o \ mcstashm.o initializer.o remob.o tclmotdriv.o protocol.o \ sinfox.o sicslist.o cone.o hipadaba.o sicshipadaba.o statistics.o \ - moregress.o + moregress.o hdbcommand.o multicounter.o regresscter.o MOTOROBJ = motor.o simdriv.o COUNTEROBJ = countdriv.o simcter.o counter.o diff --git a/mesure.c b/mesure.c index 851e5b17..83b0980c 100644 --- a/mesure.c +++ b/mesure.c @@ -445,7 +445,9 @@ static int MesureCalculateSettings(pMesure self, float fHKL[3], float fSet[4], float fPsi, SConnection *pCon) { int status, np; - float step, tolerance; + float step, tolerance, fHard; + char *scanvar = NULL; + char buffer[256]; SetHKLScanTolerance(self->pCryst,.0); status = CalculateSettings(self->pCryst,fHKL,fPsi,0,fSet,pCon); @@ -460,7 +462,26 @@ static int MesureCalculateSettings(pMesure self, float fHKL[3], float fSet[4], np = getMesureNP(self,(double)fSet[0]); tolerance = (step * (float)np)/2. + .2; SetHKLScanTolerance(self->pCryst,tolerance); - return CalculateSettings(self->pCryst,fHKL,fPsi,0,fSet,pCon); + status = CalculateSettings(self->pCryst,fHKL,fPsi,0,fSet,pCon); + if(status != 1){ + return status; + } + scanvar = GetFourCircleScanVar(self->stepTable,fSet[0]); + if(scanvar != NULL && strcmp(scanvar,"om") != 0){ + tolerance *= 2.; + strcpy(buffer,"ERROR: 2theta limit problem:"); + if(!MotorCheckBoundary(self->p2Theta,fSet[0]-tolerance,&fHard, + buffer,256-strlen(buffer))){ + SCWrite(pCon,buffer,eWarning); + return 0; + } + if(!MotorCheckBoundary(self->p2Theta,fSet[0]+tolerance,&fHard, + buffer,256-strlen(buffer))){ + SCWrite(pCon,buffer,eWarning); + return 0; + } + } + return status; } /*--------------------------------------------------------------------------*/ int MesureReflection(pMesure self, float fHKL[3], float fPsi, diff --git a/motor.c b/motor.c index 2df8bf79..ec36c1ac 100644 --- a/motor.c +++ b/motor.c @@ -4,18 +4,48 @@ This file implements the SICS motor handling. This is the logical level, the nitty gritty hardware interface is in the driver. - This is a totally revamped version which uses the Hipadaba for - data storage. - - copyright: see file COPYRIGHT - - Mark Koennecke, July 2006 + Mark Koennecke, November 1996 + revised: Mark Koennecke, June 1997 + callback added: Mark Koennecke, August 1997 + endscript facility added: Mark Koennecke, August 2002 + Modified to support driver parameters, Mark Koennecke, January 2003 + + Copyright: + + Labor fuer Neutronenstreuung + Paul Scherrer Institut + CH-5423 Villigen-PSI + + + The authors hereby grant permission to use, copy, modify, distribute, + and license this software and its documentation for any purpose, provided + that existing copyright notices are retained in all copies and that this + notice is included verbatim in any distributions. No written agreement, + license, or royalty fee is required for any of the authorized uses. + Modifications to this software may be copyrighted by their authors + and need not follow the licensing terms described here, provided that + the new terms are clearly indicated on the first page of each file where + they apply. + + IN NO EVENT SHALL THE AUTHORS OR DISTRIBUTORS BE LIABLE TO ANY PARTY + FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES + ARISING OUT OF THE USE OF THIS SOFTWARE, ITS DOCUMENTATION, OR ANY + DERIVATIVES THEREOF, EVEN IF THE AUTHORS HAVE BEEN ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + + INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT. THIS SOFTWARE + IS PROVIDED ON AN "AS IS" BASIS, AND THE AUTHORS AND DISTRIBUTORS HAVE + NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR + MODIFICATIONS. + -----------------------------------------------------------------------------*/ #include #include #include #include #include +#include "fortify.h" #include "sics.h" #include "devexec.h" #include "motor.h" @@ -24,8 +54,6 @@ #include "servlog.h" #include "tclmotdriv.h" #include "site.h" -#include "sicshipadaba.h" -#include "stptok.h" /*------------------------------------------------------------------------- some lokal defines */ @@ -34,7 +62,20 @@ #define INTSCAN 1. #define INTBATCH 2. #define INTHALT 3. -#define ABS(x) (x < 0 ? -(x) : (x)) + +#define SLOW 0 +#define SUPP 1 +#define SZERO 2 +#define FIX 3 +#define INT 4 +#define PREC 5 +#define USRIGHTS 6 +#define SIGN 7 +#define ECOUNT 8 +#define POSCOUNT 9 +#define IGNOREFAULT 10 +#define MOVECOUNT 11 + /*------------------------------------------------------------------------ a tiny structure used in CallBack work */ @@ -42,21 +83,27 @@ float fVal; char *pName; } MotCallback; + /*-------------------------------------------------------------------------*/ -static void *MotorGetInterface(void *pData, int iID){ + static void *MotorGetInterface(void *pData, int iID) + { pMotor self = NULL; self = (pMotor)pData; assert(self); - if(iID == DRIVEID){ + if(iID == DRIVEID) + { return self->pDrivInt; - } else if(iID == CALLBACKINTERFACE) { + } + else if(iID == CALLBACKINTERFACE) + { return self->pCall; } return NULL; } /*------------------------------------------------------------------------*/ -static int MotorHalt(void *sulf){ + static int MotorHalt(void *sulf) + { pMotor self; assert(sulf); @@ -74,9 +121,11 @@ static int MotorHalt(void *sulf){ self->stopped = 1; return self->pDriver->Halt((void *)self->pDriver); -} + } + /*--------------------------------------------------------------------------*/ -static int MotorLimits(void *sulf, float fVal, char *error, int iErrLen){ + static int MotorLimits(void *sulf, float fVal, char *error, int iErrLen) + { float fHard; pMotor self; @@ -85,22 +134,24 @@ static int MotorLimits(void *sulf, float fVal, char *error, int iErrLen){ self = (pMotor)sulf; return MotorCheckBoundary(self,fVal,&fHard,error,iErrLen); -} -/*-------------------------------------------------------------------------*/ + } /*---------------------------------------------------------------------------*/ -static float MotorGetValue(void *pData, SConnection *pCon){ + static float MotorGetValue(void *pData, SConnection *pCon) + { int iRet; float fVal = 0.; assert(pData); iRet = MotorGetHardPosition((pMotor)pData,pCon,&fVal); - if(iRet != OKOK){ + if(iRet != OKOK) + { fVal = -9999999.99; } return fVal; -} + } /*------------------------------------------------------------------------*/ -static int MotorSaveStatus(void *pData, char *name, FILE *fd){ + static int MotorSaveStatus(void *pData, char *name, FILE *fd) + { pMotor self = NULL; char pBueffel[512]; @@ -109,27 +160,57 @@ static int MotorSaveStatus(void *pData, char *name, FILE *fd){ self= (pMotor)pData; fprintf(fd,"# Motor %s\n",name); - strncpy(pBueffel,name,511); - strncat(pBueffel," ",511); - SaveSICSHipadaba(fd,self->pDescriptor->parNode,pBueffel); + sprintf(pBueffel,"%s sign %f\n",name,ObVal(self->ParArray,SIGN)); + fputs(pBueffel,fd); + sprintf(pBueffel,"%s SoftZero %f\n",name,ObVal(self->ParArray,SZERO)); + fputs(pBueffel,fd); + sprintf(pBueffel,"%s SoftLowerLim %f\n",name,ObVal(self->ParArray,SLOW)); + fputs(pBueffel,fd); + sprintf(pBueffel,"%s SoftUpperLim %f\n",name,ObVal(self->ParArray,SUPP)); + fputs(pBueffel,fd); + sprintf(pBueffel,"%s Fixed %f\n",name,ObVal(self->ParArray,FIX)); + fputs(pBueffel,fd); + sprintf(pBueffel,"%s InterruptMode %f\n",name,ObVal(self->ParArray,INT)); + fputs(pBueffel,fd); + sprintf(pBueffel,"%s precision %f\n",name,ObVal(self->ParArray,PREC)); + fputs(pBueffel,fd); + sprintf(pBueffel,"%s ignorefault %f\n",name,ObVal(self->ParArray,IGNOREFAULT)); + fputs(pBueffel,fd); + sprintf(pBueffel,"%s AccessCode %f\n",name,ObVal(self->ParArray,USRIGHTS)); + fputs(pBueffel,fd); + sprintf(pBueffel,"%s poscount %f\n",name, + ObVal(self->ParArray,POSCOUNT)); + sprintf(pBueffel,"%s movecount %f\n",name, + ObVal(self->ParArray,MOVECOUNT)); + fputs(pBueffel,fd); return 1; -} + } /*-------------------------------------------------------------------------*/ -static void MotorInterrupt(SConnection *pCon, int iVal){ - if(SCGetInterrupt(pCon) < iVal){ + static float absf(float f) + { + if(f < 0.) + { + return -f; + } + else + { + return f; + } + } +/*-------------------------------------------------------------------------*/ + static void MotorInterrupt(SConnection *pCon, int iVal) + { + if(SCGetInterrupt(pCon) < iVal) + { SCSetInterrupt(pCon,iVal); } -} + } /*---------------------------------------------------------------------*/ static int statusRunTo(pMotor self, SConnection *pCon) { char pBueffel[256]; - float posCount; - - assert(SICSHdbGetFloat(self->pDescriptor->parNode,pCon,"maxretry", - &posCount) == 1); - if(self->retryCount >= (int)posCount) + if(self->retryCount >= ObVal(self->ParArray,POSCOUNT)) { snprintf(pBueffel,255,"ERROR: aborting motor %s after %d retries", self->name, self->retryCount); @@ -149,26 +230,26 @@ static int statusRunTo(pMotor self, SConnection *pCon) /*--------------------------------------------------------------------*/ static int checkPosition(pMotor self, SConnection *pCon) { - float fHard, precision; + float fHard; char pBueffel[132]; int status; - assert(SICSHdbGetFloat(self->pDescriptor->parNode,pCon, - "precision",&precision) == 1); - MotorGetHardPosition(self,pCon,&fHard); self->fPosition = fHard; - if(ABS(fHard - self->fTarget) > precision){ - if(SCGetInterrupt(pCon) != eContinue){ + if(absf(fHard - self->fTarget) > ObVal(self->ParArray,PREC)) + { + if (SCGetInterrupt(pCon) != eContinue) + { return HWFault; } - if(self->stopped){ + if(self->stopped) + { snprintf(pBueffel,131,"WARNING: %s stopped", self->name); SCWrite(pCon,pBueffel, eWarning); return HWFault; } snprintf(pBueffel,131,"WARNING: %s off position by %f", - self->name, ABS(fHard - self->fTarget)); + self->name, absf(fHard - self->fTarget)); SCWrite(pCon,pBueffel, eWarning); status = statusRunTo(self,pCon); return status; @@ -176,23 +257,24 @@ static int checkPosition(pMotor self, SConnection *pCon) return HWIdle; } /*--------------------------------------------------------------------*/ -static void finishDriving(pMotor self, SConnection *pCon){ +static void finishDriving(pMotor self, SConnection *pCon) +{ MotCallback sCall; MotorGetSoftPosition(self,pCon,&sCall.fVal); sCall.pName = self->name; InvokeCallBack(self->pCall, MOTDRIVE, &sCall); /* send also very last position */ InvokeCallBack(self->pCall, MOTEND, &sCall); - UpdateHipadabaPar(self->pDescriptor->parNode, - MakeHdbFloat((double)sCall.fVal),pCon); } /*--------------------------------------------------------------------*/ -static int reportAndFixError(pMotor self, SConnection *pCon){ +static int reportAndFixError(pMotor self, SConnection *pCon) +{ char pBueffel[256], pError[131]; int iCode, iRet, newStatus; self->pDriver->GetError(self->pDriver,&iCode, pError,131); iRet = self->pDriver->TryAndFixIt(self->pDriver,iCode, self->fTarget); - switch(iRet){ + switch(iRet) + { case MOTFAIL: snprintf(pBueffel,255,"ERROR: %s on %s",pError,self->name); SCWrite(pCon,pBueffel,eError); @@ -218,25 +300,25 @@ static int reportAndFixError(pMotor self, SConnection *pCon){ } return newStatus; } -/*---------------------------------------------------------------------*/ -static int evaluateStatus(pMotor self, SConnection *pCon){ +/*--------------------------------------------------------------------- + New version, refactored October 2003 + -----------------------------------------------------------------------*/ +static int evaluateStatus(pMotor self, SConnection *pCon) +{ int iRet, iCode, newStatus; MotCallback sCall; char pBueffel[256], pError[132]; - float fHard, ignorefault, interrupt; - - assert(SICSHdbGetFloat(self->pDescriptor->parNode,pCon, - "ignorefault",&ignorefault) == 1); - assert(SICSHdbGetFloat(self->pDescriptor->parNode,pCon, - "interruptmode",&interrupt) == 1); + float fHard; iRet = self->pDriver->GetStatus(self->pDriver); newStatus = iRet; - switch(iRet){ + switch(iRet) + { case OKOK: case HWIdle: newStatus = checkPosition(self,pCon); - if(newStatus != HWBusy){ + if(newStatus != HWBusy) + { finishDriving(self,pCon); } break; @@ -245,13 +327,16 @@ static int evaluateStatus(pMotor self, SConnection *pCon){ break; case HWPosFault: newStatus = reportAndFixError(self,pCon); - if(newStatus == HWFault && ignorefault < 1){ + if(newStatus == HWFault && ObVal(self->ParArray,IGNOREFAULT) < 1) + { newStatus = HWPosFault; } - if(newStatus == HWIdle || newStatus == OKOK){ + if(newStatus == HWIdle || newStatus == OKOK) + { newStatus = checkPosition(self,pCon); - if(newStatus != HWBusy){ - finishDriving(self,pCon); + if(newStatus != HWBusy) + { + finishDriving(self,pCon); } } break; @@ -270,32 +355,30 @@ static int evaluateStatus(pMotor self, SConnection *pCon){ eWarning); break; } - if(newStatus == HWFault){ - MotorInterrupt(pCon,(int)interrupt); + if(newStatus == HWFault) + { + MotorInterrupt(pCon,ObVal(self->ParArray,INT)); self->retryCount = 0; } return newStatus; } /*---------------------------------------------------------------------*/ -static void handleMoveCallback(pMotor self, SConnection *pCon){ +static void handleMoveCallback(pMotor self, SConnection *pCon) +{ MotCallback sCall; - float movecount; - - assert(SICSHdbGetFloat(self->pDescriptor->parNode,pCon, - "movecount",&movecount) == 1); self->posCount++; - if(self->posCount >= (int)movecount){ + if(self->posCount >= ObVal(self->ParArray,MOVECOUNT)) + { MotorGetSoftPosition(self,pCon,&sCall.fVal); sCall.pName = self->name; InvokeCallBack(self->pCall, MOTDRIVE, &sCall); self->posCount = 0; - UpdateHipadabaPar(self->pDescriptor->parNode, - MakeHdbFloat((double)sCall.fVal),pCon); } } /*-----------------------------------------------------------------------*/ -static int MotorStatus(void *sulf, SConnection *pCon){ + static int MotorStatus(void *sulf, SConnection *pCon) + { pMotor self = NULL; int status; @@ -309,218 +392,16 @@ static int MotorStatus(void *sulf, SConnection *pCon){ SCWrite(pCon, "", eEvent); self->pDrivInt->drivableStatus=status; } - if(status == HWBusy){ + if(status == HWBusy) + { handleMoveCallback(self,pCon); } return status; -} + } /*---------------------------------------------------------------------------*/ -static int MotorZeroCallback(void *userData, void *callData, pHdb node, - hdbValue v){ - pMotor self = NULL; - float limit, oldZero, diff; - SConnection *pCon = NULL; - - self = (pMotor)userData; - assert(self != NULL); - pCon = (SConnection *)callData; - - assert(SICSHdbGetFloat(self->pDescriptor->parNode,pCon, - "softzero",&oldZero) == 1); - - diff = v.v.doubleValue - oldZero; - - assert(SICSHdbGetFloat(self->pDescriptor->parNode,pCon, - "softupperlim",&limit) == 1); - limit -= diff; - SICSHdbSetFloat(self->pDescriptor->parNode,(SConnection *)callData, - "softupperlim",limit); - - assert(SICSHdbGetFloat(self->pDescriptor->parNode,pCon, - "softlowerlim",&limit) == 1); - limit -= diff; - SICSHdbSetFloat(self->pDescriptor->parNode,(SConnection *)callData, - "softlowerlim",limit); - - UpdateHipadabaPar(node,v,callData); - return 1; -} -/*--------------------------------------------------------------------------*/ -static int MotorSignCallback(void *userData, void *callData, pHdb node, - hdbValue v){ - pMotor self = NULL; - SConnection *pCon = NULL; - pHdb zero = NULL; - - self = (pMotor)userData; - pCon = (SConnection *)callData; - - if(ABS(v.v.doubleValue - 1.) > .01){ - if(pCon!= NULL){ - SCWrite(pCon,"ERROR: invalid sign value",eError); - return 0; - } - } - SICSHdbSetFloat(self->pDescriptor->parNode,pCon, - "softlowerlim",self->pDriver->fLower*v.v.doubleValue); - SICSHdbSetFloat(self->pDescriptor->parNode,pCon, - "softupperlim",self->pDriver->fUpper*v.v.doubleValue); - zero = GetHipadabaNode(self->pDescriptor->parNode,"softzero"); - if(zero != NULL){ - UpdateHipadabaPar(zero,MakeHdbFloat(.0),pCon); - } - UpdateHipadabaPar(node,v,callData); - return 1; -} -/*--------------------------------------------------------------------------*/ -static int MotorDriverReadCallback(void *userData, void *callData, pHdb node, - hdbValue v){ - pMotor self = NULL; - SConnection *pCon = NULL; - int status; - float value; - - self = (pMotor)userData; - assert(self); - pCon = (SConnection *)callData; - - if(self->pDriver->GetDriverPar != NULL){ - status = self->pDriver->GetDriverPar(self->pDriver,node->name, - &value); - v.dataType = HIPFLOAT; - v.v.doubleValue = (double)value; - node->value.v.doubleValue = (double)value; - return status; - } - return 1; -} -/*--------------------------------------------------------------------------*/ -static int MotorDriverSetCallback(void *userData, void *callData, pHdb node, - hdbValue v){ - pMotor self = NULL; - SConnection *pCon = NULL; - int status; - float value; - - self = (pMotor)userData; - assert(self); - pCon = (SConnection *)callData; - - if(pCon != NULL && self->pDriver->SetDriverPar != NULL){ - status = self->pDriver->SetDriverPar(self->pDriver,pCon, node->name, - (float)v.v.doubleValue); - if(status == 1){ - UpdateHipadabaPar(node,v,callData); - } - return status; - } - return 1; -} -/*--------------------------------------------------------------------------*/ -static pHdb MakeMotorDriverNode(pMotor pM, char *name){ - pHdb node = NULL; - - node = MakeHipadabaNode(name,HIPFLOAT,1); - if(node == NULL){ - return NULL; - } - AppendHipadabaCallback(node,HCBSET, - MakeHipadabaCallback(MotorDriverSetCallback,pM,NULL,-1,-1)); - AppendHipadabaCallback(node,HCBREAD, - MakeHipadabaCallback(MotorDriverReadCallback,pM,NULL,-1,-1)); - return node; -} -/*--------------------------------------------------------------------------*/ -static int MotorHardCallback(void *userData, void *callData, pHdb node, - hdbValue v){ - int status; - pMotor self = NULL; - float value; - SConnection *pCon = NULL; - - self = (pMotor)userData; - pCon = (SConnection *)callData; - assert(self != NULL); - assert(pCon != NULL); - - status = MotorGetHardPosition(self,pCon,&value); - node->value.v.doubleValue = (double)value; - v.v.doubleValue = (double)value; - return status; -} -/*--------------------------------------------------------------------------*/ -static char *getDriverParList(MotorDriver *pDriv){ - SConnection *pCon = NULL; - pDynString list = NULL; - char *listData = NULL; - - if(pDriv->ListDriverPar != NULL){ - pCon = SCCreateDummyConnection(pServ->pSics); - if(pCon == NULL){ - return NULL; - } - SCStartBuffering(pCon); - pDriv->ListDriverPar(pDriv,"test.", pCon); - list = SCEndBuffering(pCon); - if(list != NULL){ - listData = strdup(GetCharArray(list)); - SCDeleteConnection(pCon); - } else { - listData = NULL; - } - return listData; - } - return NULL; -} -/*--------------------------------------------------------------------------*/ -extern char *trim(char *str); -/*--------------------------------------------------------------------------*/ -static char *extractName(char *line){ - char *name = NULL, *pEnd = NULL; - - name = strchr(line,'.'); - assert(name != NULL); - while(*name == '.'){ - name++; - } - pEnd = strchr(name,'='); - assert(pEnd != NULL); - *pEnd = '\0'; - return trim(name); -} -/*--------------------------------------------------------------------------- - * This currently uses the ListDriverPar function of the driver. In - * a later stage this should be modified to test for and use a new - * driver function, CreateDriverNodes. But this scheme allows to use - * existing drivers without a change, at the expense of some complicated - * code. - * --------------------------------------------------------------------------*/ -static int CreateDriverParameters(pMotor pM, pHdb parent){ - char *listPtr = NULL, line[80], *pPtr, *name; - pHdb node = NULL; - - listPtr = getDriverParList(pM->pDriver); - if(listPtr == NULL){ - /* - * no driver parameters - */ - return 1; - } - pPtr = listPtr; - while((pPtr = stptok(pPtr,line,79,"\n")) != NULL){ - name = extractName(line); - node = MakeMotorDriverNode(pM, name); - if(node != NULL){ - AddHipadabaChild(parent,node); - } - } - free(listPtr); - return 1; -} -/*---------------------------------------------------------------------------*/ -pMotor MotorInit(char *drivername, char *name, MotorDriver *pDriv){ + pMotor MotorInit(char *drivername, char *name, MotorDriver *pDriv) + { pMotor pM = NULL; - pHdb node = NULL, child = NULL; assert(drivername); assert(pDriv); @@ -528,100 +409,58 @@ pMotor MotorInit(char *drivername, char *name, MotorDriver *pDriv){ /* get memory */ pM = (pMotor)malloc(sizeof(Motor)); - if(!pM){ + if(!pM) + { return NULL; } + + + /* create and initialize parameters */ + pM->ParArray = ObParCreate(12); + if(!pM->ParArray) + { + free(pM); + return NULL; + } + ObParInit(pM->ParArray,SLOW,"softlowerlim",pDriv->fLower,usUser); + ObParInit(pM->ParArray,SUPP,"softupperlim",pDriv->fUpper,usUser); + ObParInit(pM->ParArray,SZERO,"softzero",ZEROINACTIVE,usUser); + ObParInit(pM->ParArray,FIX,"fixed",-1,usUser); + ObParInit(pM->ParArray,INT,"interruptmode",INTCONT,usMugger); + ObParInit(pM->ParArray,PREC,"precision",0.01,usMugger); + ObParInit(pM->ParArray,USRIGHTS,"accesscode",(float)usUser,usMugger); + ObParInit(pM->ParArray,SIGN,"sign",1.0,usMugger); + ObParInit(pM->ParArray,ECOUNT,"failafter",3.0,usMugger); + ObParInit(pM->ParArray,POSCOUNT,"maxretry",3.0,usMugger); + ObParInit(pM->ParArray,IGNOREFAULT,"ignorefault",0.0,usMugger); + ObParInit(pM->ParArray,MOVECOUNT,"movecount",10.0,usMugger); + pDriv->GetPosition(pDriv,&(pM->fPosition)); + pM->fTarget = pM->fPosition; + pM->endScriptID = 0; + /* copy arguments */ + pM->pDriver = pDriv; + pM->drivername = strdup(drivername); + pM->name = strdup(name); + + /* initialise object descriptor */ pM->pDescriptor = CreateDescriptor("Motor"); - if(!pM->pDescriptor){ + if(!pM->pDescriptor) + { + ObParDelete(pM->ParArray); free(pM); return NULL; } pM->pDescriptor->GetInterface = MotorGetInterface; pM->pDescriptor->SaveStatus = MotorSaveStatus; - /* copy arguments */ - pM->pDriver = pDriv; - pM->drivername = strdup(drivername); - pM->name = strdup(name); - - - /* create and initialize parameters */ - node = MakeSICSHdbDriv(name,usUser,pM,HIPFLOAT); - if(node == NULL){ - free(pM); - return NULL; - } - pM->pDescriptor->parNode = node; - - child = MakeSICSROPar("targetposition",MakeHdbFloat(pM->fPosition)); - AppendHipadabaCallback(child,HCBREAD, - MakeMemReadCallback(&pM->fTarget)); - AddHipadabaChild(node,child); - child = MakeSICSROPar("hardposition",MakeHdbFloat(pM->fPosition)); - AppendHipadabaCallback(child,HCBREAD, - MakeHipadabaCallback(MotorHardCallback,pM,NULL,-1,-1)); - AddHipadabaChild(node,child); - child = MakeHipadabaNode("sign",HIPFLOAT, 1); - AppendHipadabaCallback(child,HCBSET, MakeCheckPermissionCallback(usUser)); - AppendHipadabaCallback(child,HCBSET, - MakeHipadabaCallback(MotorSignCallback,pM,NULL,-1,-1)); - SetHipadabaPar(child,MakeHdbFloat(1.),NULL); - AddHipadabaChild(node,child); - child = MakeHipadabaNode("hardlowerlim",HIPFLOAT, 1); - AppendHipadabaCallback(child,HCBREAD, - MakeMemReadCallback(&pM->pDriver->fLower)); - AppendHipadabaCallback(child,HCBSET, - MakeHipadabaCallback(MotorDriverSetCallback,pM,NULL,-1,-1)); - AddHipadabaChild(node,child); - child = MakeHipadabaNode("hardupperlim",HIPFLOAT, 1); - AppendHipadabaCallback(child,HCBREAD, - MakeMemReadCallback(&pM->pDriver->fUpper)); - AppendHipadabaCallback(child,HCBSET, - MakeHipadabaCallback(MotorDriverSetCallback,pM,NULL,-1,-1)); - AddHipadabaChild(node,child); - AddHipadabaChild(node,MakeSICSHdbPar("softlowerlim",usUser, - MakeHdbFloat(pDriv->fLower))); - AddHipadabaChild(node,MakeSICSHdbPar("softupperlim",usUser, - MakeHdbFloat(pDriv->fUpper))); - child = MakeHipadabaNode("softzero",HIPFLOAT, 1); - AppendHipadabaCallback(child,HCBSET, MakeCheckPermissionCallback(usUser)); - AppendHipadabaCallback(child,HCBSET, - MakeHipadabaCallback(MotorZeroCallback,pM,NULL,-1,-1)); - AddHipadabaChild(node,child); - AddHipadabaChild(node,MakeSICSHdbPar("fixed",usUser, - MakeHdbFloat(-1.))); - AddHipadabaChild(node,MakeSICSHdbPar("interruptmode",usMugger, - MakeHdbFloat(.0))); - AddHipadabaChild(node,MakeSICSHdbPar("precision",usMugger, - MakeHdbFloat(.1))); - AddHipadabaChild(node,MakeSICSHdbPar("accesscode",usMugger, - MakeHdbFloat((double)usUser))); - AddHipadabaChild(node,MakeSICSHdbPar("failafter",usMugger, - MakeHdbFloat((double)3.0))); - AddHipadabaChild(node,MakeSICSHdbPar("maxretry",usMugger, - MakeHdbFloat((double)3.0))); - AddHipadabaChild(node,MakeSICSHdbPar("ignorefault",usMugger, - MakeHdbFloat((double).0))); - AddHipadabaChild(node,MakeSICSHdbPar("movecount",usMugger, - MakeHdbFloat((double)10.0))); - pDriv->GetPosition(pDriv,&(pM->fPosition)); - child = MakeSICSROPar("position",MakeHdbFloat(pM->fPosition)); - AppendHipadabaCallback(child,HCBREAD, - MakeMemReadCallback(&pM->fPosition)); - AddHipadabaChild(node,child); - - - pM->fTarget = pM->fPosition; - pM->endScriptID = 0; - - CreateDriverParameters(pM,pM->pDescriptor->parNode); - /* initialise Drivable interface */ pM->pDrivInt = CreateDrivableInterface(); - if(!pM->pDrivInt){ + if(!pM->pDrivInt) + { DeleteDescriptor(pM->pDescriptor); + ObParDelete(pM->ParArray); free(pM); return NULL; } @@ -633,7 +472,8 @@ pMotor MotorInit(char *drivername, char *name, MotorDriver *pDriv){ /* initialise callback interface */ pM->pCall = CreateCallBackInterface(); - if(!pM->pCall){ + if(!pM->pCall) + { MotorKill(pM); return NULL; } @@ -645,7 +485,8 @@ pMotor MotorInit(char *drivername, char *name, MotorDriver *pDriv){ extern void KillPiPiezo(void *pData); -void MotorKill(void *self){ + void MotorKill(void *self) + { pMotor pM; assert(self); @@ -656,51 +497,165 @@ void MotorKill(void *self){ if(pM->name) free(pM->name); - if(pM->pDrivInt){ + if(pM->pDrivInt) + { free(pM->pDrivInt); } - if(pM->pCall){ + if(pM->pCall) + { DeleteCallBackInterface(pM->pCall); } /* kill driver */ - if(pM->drivername){ - if(pM->pDriver->KillPrivate != NULL){ - pM->pDriver->KillPrivate(pM->pDriver); + if(pM->drivername) + { + if(pM->pDriver->KillPrivate != NULL) + { + pM->pDriver->KillPrivate(pM->pDriver); + if(pM->pDriver->name != NULL) + { + free(pM->pDriver->name); + } + free(pM->pDriver); } - if(pM->pDriver->name != NULL){ - free(pM->pDriver->name); - } - free(pM->pDriver); free(pM->drivername); } + /* get rid of parameter space */ + if(pM->ParArray) + { + ObParDelete(pM->ParArray); + } + /* kill Descriptor */ DeleteDescriptor(pM->pDescriptor); free(pM); -} + + } /*--------------------------------------------------------------------------*/ -int MotorGetPar(pMotor self, char *name, float *fVal){ - char pBueffel[512]; - snprintf(pBueffel,511,"%s ", name); - return SICSHdbGetFloat(self->pDescriptor->parNode,NULL, - pBueffel, fVal); -} -/*---------------------------------------------------------------------------*/ -int MotorSetPar(pMotor self, SConnection *pCon, char *name, float fVal){ - int status; - - status = SICSHdbSetFloat(self->pDescriptor->parNode, - pCon,name,fVal); - if(status == 1){ - SCparChange(pCon); - return 1; - } else { - return 0; + int MotorGetPar(pMotor self, char *name, float *fVal) + { + ObPar *pPar = NULL; + assert(self); + + if(strcmp(name,"hardupperlim") == 0) + { + *fVal = self->pDriver->fUpper; + return 1; } -} + if(strcmp(name,"hardlowerlim") == 0) + { + *fVal = self->pDriver->fLower; + return 1; + } + + pPar = ObParFind(self->ParArray,name); + if(pPar) + { + *fVal = pPar->fVal; + return 1; + } + else + { + /* can still be position */ + if(strcmp(name,"position") == 0) + { + *fVal = self->fPosition; + return 1; + } + else if(strcmp(name,"target") == 0) + { + *fVal = self->fTarget; + return 1; + } + else + { + /* + check for a driver parameter + */ + if(self->pDriver->GetDriverPar != NULL) + { + return self->pDriver->GetDriverPar(self->pDriver,name,fVal); + } + else + { + return 0; + } + } + } + } +/*---------------------------------------------------------------------------*/ + int MotorSetPar(pMotor self, SConnection *pCon, char *name, float fVal) + { + ObPar *pPar = NULL; + char pBueffel[512]; + int iRet; + float fLimit, fOld, fChange; + + assert(self); + assert(pCon); + + /* + try set driver parameters + */ + if(self->pDriver->SetDriverPar != NULL) + { + iRet = self->pDriver->SetDriverPar(self->pDriver,pCon,name,fVal); + if(iRet == 1) + { + SCparChange(pCon); + return iRet; + } + } + + + if(strcmp(name,"softzero") == 0) + { + /* set it first, this also tests the necessary privileges */ + fOld = ObVal(self->ParArray,SZERO); + iRet = ObParSet(self->ParArray,self->name,name,fVal,pCon); + if(!iRet) + { + return iRet; + } + /* shift the limits by the difference between old and new */ + fChange = fVal - fOld; + /* upper limit */ + fLimit = ObVal(self->ParArray,SUPP); + fLimit -= fChange; + ObParSet(self->ParArray,self->name,"softupperlim",fLimit,pCon); + /* lower limit */ + fLimit = ObVal(self->ParArray,SLOW); + fLimit -= fChange; + ObParSet(self->ParArray,self->name,"softlowerlim",fLimit,pCon); + SCparChange(pCon); + + return 1; + } + + iRet = ObParSet(self->ParArray,self->name,name,fVal,pCon); + if(strcmp(name,"sign") == 0) + { + if((absf(fVal)-1.0) > 0.01) + { + SCWrite(pCon,"ERROR: Invalid Sign Value",eError); + return 0; + } + if(fVal < 0.0) + { + ObParInit(self->ParArray,SLOW,"softlowerlim", + self->pDriver->fUpper*fVal,usUser); + ObParInit(self->ParArray,SUPP,"softupperlim", + self->pDriver->fLower*fVal,usUser); + ObParInit(self->ParArray,SZERO,"softzero",ZEROINACTIVE,usUser); + } + } + SCparChange(pCon); + + return iRet; + } /*--------------------------------------------------------------------------- MotorCheckBoundary checks for violation of boundary conditions and transforms from SoftCoordinates to hard coordinates. @@ -710,59 +665,53 @@ int MotorSetPar(pMotor self, SConnection *pCon, char *name, float fVal){ char *pError, int iErrLen) { float fHard; - float fZero, fixed, lowerlim, upperlim, sign; + float fZero; char pBueffel[512]; assert(self); - - assert(SICSHdbGetFloat(self->pDescriptor->parNode,NULL, - "fixed",&fixed) == 1); - assert(SICSHdbGetFloat(self->pDescriptor->parNode,NULL, - "softzero",&fZero) == 1); - assert(SICSHdbGetFloat(self->pDescriptor->parNode,NULL, - "softlowerlim",&lowerlim) == 1); - assert(SICSHdbGetFloat(self->pDescriptor->parNode,NULL, - "softupperlim",&upperlim) == 1); - assert(SICSHdbGetFloat(self->pDescriptor->parNode,NULL, - "sign",&sign) == 1); - /* check for fixed */ - if(fixed >= 0){ + if(ObVal(self->ParArray,FIX) >= 0) + { sprintf(pBueffel,"Motor %s is Fixed",self->name); strncpy(pError,pBueffel,iErrLen); return 0; /* is this an error? */ } /* check against software boundaries */ - if(fVal > upperlim){ + if(fVal > ObVal(self->ParArray,SUPP)) + { sprintf(pBueffel,"%f violates upper software limit %f on %s", - fVal, upperlim,self->name); + fVal, ObVal(self->ParArray,SUPP),self->name); strncpy(pError,pBueffel,iErrLen); return 0; } - if(fVal < lowerlim){ + if(fVal < ObVal(self->ParArray,SLOW)) + { sprintf(pBueffel,"%f violates lower software limit %f on %s", - fVal,lowerlim,self->name ); + fVal,ObVal(self->ParArray,SLOW),self->name ); strncpy(pError,pBueffel,iErrLen); return 0; } /* correct for zero point */ + fZero = ObVal(self->ParArray,SZERO); fZero = -fZero; fHard = fVal - fZero; /* apply sign */ - fHard = fHard*sign; + fHard = fHard*ObVal(self->ParArray,SIGN); /* check for hardware limits */ - if(fHard > self->pDriver->fUpper){ + if(fHard > self->pDriver->fUpper) + { sprintf(pBueffel,"%f violates upper hardware limit %f on %s", fVal,self->pDriver->fUpper,self->name); strncpy(pError,pBueffel,iErrLen); return 0; } - if(fHard < self->pDriver->fLower){ + if(fHard < self->pDriver->fLower) + { sprintf(pBueffel,"%f violates lower hardware limit %f on %s", fVal,self->pDriver->fLower,self->name); strncpy(pError,pBueffel,iErrLen); @@ -771,10 +720,11 @@ int MotorSetPar(pMotor self, SConnection *pCon, char *name, float fVal){ *fNew = fHard; return 1; -} + } /*---------------------------------------------------------------------------*/ -long MotorRun(void *sulf, SConnection *pCon, float fNew){ - float fHard, rights, ignore, maxerr, interrupt; + long MotorRun(void *sulf, SConnection *pCon, float fNew) + { + float fHard; int i, iRet, iCode; char pBueffel[512]; char pError[132]; @@ -786,18 +736,9 @@ long MotorRun(void *sulf, SConnection *pCon, float fNew){ assert(self); assert(pCon); - assert(SICSHdbGetFloat(self->pDescriptor->parNode,NULL, - "accesscode",&rights) == 1); - assert(SICSHdbGetFloat(self->pDescriptor->parNode,NULL, - "ignorefault",&ignore) == 1); - assert(SICSHdbGetFloat(self->pDescriptor->parNode,NULL, - "failafter",&maxerr) == 1); - assert(SICSHdbGetFloat(self->pDescriptor->parNode,NULL, - "interruptmode",&interrupt) == 1); - - /* check if I'am allowed to move this motor */ - if(!SCMatchRights(pCon,(int)rights)){ + if(!SCMatchRights(pCon,(int)ObVal(self->ParArray,USRIGHTS))) + { sprintf(pBueffel,"ERROR: You are not authorised to move motor %s", self->name); SCWrite(pCon,pBueffel,eError); @@ -806,15 +747,18 @@ long MotorRun(void *sulf, SConnection *pCon, float fNew){ } /* check boundaries first */ - iRet = MotorCheckBoundary(self,fNew,&fHard,pBueffel,511); - if(!iRet){ - SCWrite(pCon,pBueffel,eStatus); + iRet = MotorCheckBoundary(self,fNew,&fHard,pError,131); + if(!iRet) + { + snprintf(pBueffel,511,"ERROR: %s",pError); + SCWrite(pCon,pBueffel,eError); SCSetInterrupt(pCon,eAbortOperation); return 0; } /* check if the bad motor flag is set */ - if((int)ignore > 0){ + if((int)ObVal(self->ParArray,IGNOREFAULT) > 0) + { snprintf(pBueffel,511,"WARNING: motor %s is unreliable", self->name); SCWrite(pCon,pBueffel,eWarning); @@ -822,7 +766,9 @@ long MotorRun(void *sulf, SConnection *pCon, float fNew){ } /* check our error count and interrupt if to much */ - if(self->pDrivInt->iErrorCount > (int)maxerr){ + iCode = (int)ObVal(self->ParArray,ECOUNT); + if(self->pDrivInt->iErrorCount > iCode) + { /* big alarm */ ServerWriteGlobal("ERROR: !!! MOTOR ALARM !!! MOTOR ALARM !!!",eError); sprintf(pBueffel, @@ -841,22 +787,25 @@ long MotorRun(void *sulf, SConnection *pCon, float fNew){ self->fTarget = fHard; self->posCount = 0; iRet = self->pDriver->RunTo(self->pDriver,fHard); - if(iRet != OKOK){ - /* try three times to fix it */ - for(i = 0; (i < 3) && (iRet != OKOK); i++){ + if(iRet != OKOK) + { /* try three times to fix it */ + for(i = 0; (i < 3) && (iRet != OKOK); i++) + { self->pDriver->GetError(self->pDriver,&iCode, pError,131); sprintf(pBueffel,"WARNING: Trying to fix: %s",pError); SCWrite(pCon,pBueffel,eWarning); iRet = self->pDriver->TryAndFixIt(self->pDriver,iCode, fHard); - switch(iRet){ + switch(iRet) + { case MOTFAIL: SCWrite(pCon,pError,eError); SCWrite(pCon,"\n",eError); - SCSetInterrupt(pCon,(int)interrupt); + SCSetInterrupt(pCon,(int)ObVal(self->ParArray,INT)); return HWFault; case MOTREDO: iRet = self->pDriver->RunTo(self->pDriver,fHard); - if(iRet == OKOK){ + if(iRet == OKOK) + { return OKOK; } break; @@ -868,82 +817,82 @@ long MotorRun(void *sulf, SConnection *pCon, float fNew){ /* tried three times, refuses to work */ SCWrite(pCon,pError,eError); SCWrite(pCon,"\n",eError); - SCSetInterrupt(pCon,(int)interrupt); + SCSetInterrupt(pCon,(int)ObVal(self->ParArray,INT)); return HWFault; } return OKOK; -} + } /*------------------------------------------------------------------------*/ -int MotorGetHardPosition(pMotor self,SConnection *pCon, float *fHard){ + int MotorGetHardPosition(pMotor self,SConnection *pCon, float *fHard) + { int iRet, iCode; - float fVal, interrupt, sign; + float fVal; char pBueffel[512],pError[256]; assert(self); assert(pCon); - assert(SICSHdbGetFloat(self->pDescriptor->parNode,NULL, - "interruptmode",&interrupt) == 1); - assert(SICSHdbGetFloat(self->pDescriptor->parNode,NULL, - "sign",&sign) == 1); - iRet = self->pDriver->GetPosition(self->pDriver,&fVal); - if(iRet == OKOK) { + if(iRet == OKOK) /* all went well, the exception */ + { *fHard = fVal; return 1; - } else { - /* no point in trying this three times */ + } + else /* a problem, the usual case: try fix the problem */ + { /* no point in trying this three times */ self->pDriver->GetError(self->pDriver,&iCode, pError,255); iRet = self->pDriver->TryAndFixIt(self->pDriver,iCode, fVal); sprintf(pBueffel,"WARNING: Trying to fix %s",pError); SCWrite(pCon,pBueffel,eWarning); - switch(iRet){ + switch(iRet) + { case MOTFAIL: sprintf(pBueffel,"ERROR: cannot fix motor %s", self->name); SCWrite(pCon,pBueffel,eError); - SCSetInterrupt(pCon,(int)interrupt); + SCSetInterrupt(pCon,(int)ObVal(self->ParArray,INT)); *fHard = fVal; return 0; case MOTOK: case MOTREDO: iRet = self->pDriver->GetPosition(self->pDriver,&fVal); - if(iRet){ - *fHard = fVal*sign; + if(iRet) + { + *fHard = fVal*ObVal(self->ParArray,SIGN); return 1; - } else{ + } + else + { sprintf(pBueffel,"ERROR: cannot fix motor %s", self->name); - SCSetInterrupt(pCon,(int)interrupt); + SCSetInterrupt(pCon,(int)ObVal(self->ParArray,INT)); SCWrite(pCon,pBueffel,eError); *fHard = fVal; return 0; } } } - *fHard = fVal*sign; + *fHard = fVal*ObVal(self->ParArray,SIGN); return 0; } /*------------------------------------------------------------------------*/ -float MotorHardToSoftPosition(pMotor self, float fValue){ - float sign, zero; - - assert(SICSHdbGetFloat(self->pDescriptor->parNode,NULL, - "sign",&sign) == 1); - assert(SICSHdbGetFloat(self->pDescriptor->parNode,NULL, - "softzero",&zero) == 1); - + float MotorHardToSoftPosition(pMotor self, float fValue) + { /* apply zeropoint */ - if(sign < 0.){ - fValue += zero; - }else { - fValue -= zero; + if(ObVal(self->ParArray,SIGN) < 0.) + { + fValue += ObVal(self->ParArray,SZERO); + } + else + { + fValue -= ObVal(self->ParArray,SZERO); } /* apply sign */ - return fValue*sign; + return fValue*ObVal(self->ParArray,SIGN); } /* ------------------------------------------------------------------------*/ -int MotorGetSoftPosition(pMotor self, SConnection *pCon, float *fVal){ + int MotorGetSoftPosition(pMotor self, SConnection *pCon, float *fVal) + { int iRet; float fValue; @@ -952,16 +901,33 @@ int MotorGetSoftPosition(pMotor self, SConnection *pCon, float *fVal){ /* get the hard position */ iRet = MotorGetHardPosition(self,pCon,&fValue); - if(!iRet){ + if(!iRet) + { *fVal = fValue; return 0; } - *fVal = MotorHardToSoftPosition(self,fValue); + /* apply zeropoint */ + if(ObVal(self->ParArray,SIGN) < 0.) + { + fValue += ObVal(self->ParArray,SZERO); + } + else + { + fValue -= ObVal(self->ParArray,SZERO); + } + *fVal = fValue; + + /* apply sign */ + /* *fVal = MotorHardToSoftPosition(self,fValue); */ + + *fVal = fValue*ObVal(self->ParArray,SIGN); + return 1; } /*---------------------------------------------------------------------------*/ -int MotorCheckPosition(void *sulf, SConnection *pCon){ - float fHard, precision; + int MotorCheckPosition(void *sulf, SConnection *pCon) + { + float fHard; int i, iRet, iCode; char pBueffel[512]; pMotor self; @@ -969,26 +935,29 @@ int MotorCheckPosition(void *sulf, SConnection *pCon){ self = (pMotor)sulf; assert(self); assert(pCon); - - assert(SICSHdbGetFloat(self->pDescriptor->parNode,NULL, - "precision",&precision) == 1); /* try to find current position */ iRet = MotorGetHardPosition(self,pCon,&fHard); - if(iRet) { - self->fPosition = fHard; - if(ABS(fHard - self->fTarget) < precision){ + if(iRet) + { + if(absf(fHard - self->fTarget) < ObVal(self->ParArray,PREC)) + { + self->fPosition = fHard; return 1; - } else { + } + else + { /* Oooopppsss error */ return 0; } - } else { - /* error getting hold of position, MotorGetHard already tried to - solve the problem and FAILED, client already knows...*/ + } + else /* error getting hold of position, MotorGetHard already tried to + solve the problem and FAILED, the fucking bastard + even messaged the connection accordingly */ + { return -1; } -} + } /* -------------------------------------------------------------------------- The Factory function for creating a motor. Usage: MotorCreate name DriverName. @@ -1056,8 +1025,8 @@ extern MotorDriver *MakePiPiezo(Tcl_Interp *pTcl, char *pArray); SCWrite(pCon,pBueffel,eError); return 0; } - } else if(strcmp(argv[2],"regress") == 0) - { + } else if(strcmp(argv[2],"regress") == 0) + { pDriver = RGMakeMotorDriver(); if(!pDriver) { @@ -1101,24 +1070,45 @@ extern MotorDriver *MakePiPiezo(Tcl_Interp *pTcl, char *pArray); /* ----------------- some private functions used in MotorAction -------------*/ void MotorListLL(pMotor self, SConnection *pCon) { - char pBueffel[256]; + char pBueffel[512]; + int i, iLen; - snprintf(pBueffel,255,"Parameter Listing for motor %s",self->name); + iLen = ObParLength(self->ParArray); + sprintf(pBueffel,"Parameter Listing for motor %s",self->name); SCWrite(pCon,pBueffel,eValue); - snprintf(pBueffel,255,"%s ",self->name); - PrintSICSParList(self->pDescriptor->parNode,pCon,pBueffel); + sprintf(pBueffel,"%s.Position = %f\n", self->name,self->fPosition); + SCWrite(pCon,pBueffel,eStatus); + sprintf(pBueffel,"%s.TargetPosition = %f\n", self->name,self->fTarget); + SCWrite(pCon,pBueffel,eStatus); + + snprintf(pBueffel,511,"%s.hardlowerlim = %f",self->name, + self->pDriver->fLower); + SCWrite(pCon,pBueffel,eValue); + snprintf(pBueffel,511,"%s.hardupperlim = %f",self->name, + self->pDriver->fUpper); + SCWrite(pCon,pBueffel,eValue); + for(i = 0; i < iLen; i++) + { + sprintf(pBueffel,"%s.%s = %f\n",self->name, + self->ParArray[i].name,self->ParArray[i].fVal); + SCWrite(pCon,pBueffel,eStatus); + } + + /* + list driver parameters when appropriate + */ + if(self->pDriver->ListDriverPar != NULL) + { + self->pDriver->ListDriverPar(self->pDriver,self->name, pCon); + } } /*--------------------------------------------------------------------------*/ void MotorReset(pMotor pM) { - SICSHdbSetFloat(pM->pDescriptor->parNode,NULL,"softlowerlim", - pM->pDriver->fLower); - SICSHdbSetFloat(pM->pDescriptor->parNode,NULL,"softupperlim", - pM->pDriver->fUpper); - SICSHdbSetFloat(pM->pDescriptor->parNode,NULL,"softzero", - .0); - SICSHdbSetFloat(pM->pDescriptor->parNode,NULL,"fixed", - -1.); + ObParInit(pM->ParArray,SLOW,"softlowerlim",pM->pDriver->fLower,usUser); + ObParInit(pM->ParArray,SUPP,"softupperlim",pM->pDriver->fUpper,usUser); + ObParInit(pM->ParArray,SZERO,"softzero",ZEROINACTIVE,usUser); + ObParInit(pM->ParArray,FIX,"fixed",-1,usUser); } /*------------------------------------------------------------------------*/ typedef struct { @@ -1329,17 +1319,81 @@ extern MotorDriver *MakePiPiezo(Tcl_Interp *pTcl, char *pArray); } else /* one of the parameter commands or error left now */ { - snprintf(pBueffel,511,"%s ", argv[0]); - iRet = ProcessSICSHdbPar(self->pDescriptor->parNode, - pCon, pBueffel, argc-1, &argv[1]); - if(iRet == -1) { - SCWrite(pCon,"ERROR: subcommand to motor not understood", - eError); - return 0; - } else if(iRet < -1) { + pName = pCurrent; + pCurrent = pCurrent->pNext; + if(!pCurrent) /* no third par: print val */ + { + /* deal with position first */ + if(strcmp(pName->text,"position") == 0) + { + iRet = MotorGetSoftPosition(self,pCon,&fValue); + if(!iRet) + { + sprintf(pBueffel,"Error obtaining position for %s",argv[0]); + SCWrite(pCon,pBueffel,eValue); + DeleteTokenList(pList); + return 0; + } + sprintf(pBueffel,"%s.SoftPosition = %f",argv[0],fValue); + SCWrite(pCon,pBueffel,eValue); + DeleteTokenList(pList); + return 1; + } + else if(strcmp(pName->text,"hardposition") == 0) + { + iRet = MotorGetHardPosition(self,pCon,&fValue); + if(!iRet) { + sprintf(pBueffel,"Error obtaining position for %s",argv[0]); + SCWrite(pCon,pBueffel,eValue); + DeleteTokenList(pList); + return 0; + } + sprintf(pBueffel,"%s.HardPosition = %f",argv[0],fValue); + SCWrite(pCon,pBueffel,eValue); + DeleteTokenList(pList); + return 1; + } + iRet = MotorGetPar(self,pName->text,&fValue); + if(!iRet) + { + sprintf(pBueffel,"Parameter %s not found ",pName->text); + SCWrite(pCon,pBueffel,eValue); + DeleteTokenList(pList); return 0; + } + else + { + sprintf(pBueffel, "%s.%s = %f",self->name,pName->text,fValue); + SCWrite(pCon,pBueffel,eValue); + DeleteTokenList(pList); + return 1; + } + } + else /* set */ + { /* set command */ + /* parameter must be numerical value */ + if(pCurrent->Type == eInt) + { + fValue = (float)pCurrent->iVal; + } + else if(pCurrent->Type == eFloat) + { + fValue = pCurrent->fVal; + } + else + { + sprintf(pBueffel,"Wrong argument type for %s %s set", + argv[0],pName->text); + SCWrite(pCon,pBueffel,eError); + DeleteTokenList(pList); + return 0; + } + iRet = MotorSetPar(self,pCon,pName->text,fValue); + DeleteTokenList(pList); + if(iRet) + SCSendOK(pCon); + return iRet; } - return iRet; } return 0; } diff --git a/motor.h b/motor.h index 7c0ec1f4..67d61d74 100644 --- a/motor.h +++ b/motor.h @@ -16,6 +16,7 @@ typedef struct __Motor { pObjectDescriptor pDescriptor; + ObPar *ParArray; pIDrivable pDrivInt; pICallBack pCall; char *drivername; diff --git a/multicounter.c b/multicounter.c new file mode 100644 index 00000000..a0ccdde6 --- /dev/null +++ b/multicounter.c @@ -0,0 +1,380 @@ +/** + * The MultiCounter is another counter which coordinates multiple + * counting objects, counters and histogram memories. It also calls a + * script function after TransferData which collects counters and monitors. + * The purpose is to have a flexible counter abstraction for upper level + * code such as maximizers and scan functions. The script can deal with + * counting on monitors or on sums of histogram memories. + * + * This is a bit unclean. The counter driver is of no use, therefore its + * private data structure is used to hold the other counters and the name + * of the script. It would have been better to inherit from counter but + * that would have required lost of type casts. I am to lazy for this. + * + * copyright: see file COPYRIGHT + * + * Mark Koennecke, September 2006 + */ +#include +#include +#include +#include +#include "multicounter.h" +#include "counter.h" +#include "HistMem.h" +#include "macro.h" +#include "splitter.h" + +#define MAXSLAVE 16 +/*=============== code for the driver ======================================*/ +typedef struct { + void *slaveData[MAXSLAVE]; + pICountable slaves[MAXSLAVE]; + char *transferScript; + int nSlaves; +}MultiCounter, *pMultiCounter; +/*--------------------------------------------------------------------------*/ +static void KillMultiDriver(struct __COUNTER *data){ + pMultiCounter self = (pMultiCounter)data->pData; + if(self == NULL){ + return; + } + if(self->transferScript != NULL){ + free(self->transferScript); + } + free(self); +} +/*============== countable interface functions ============================*/ +static int MMCCHalt(void *pData){ + int i, retVal = OKOK, status; + pCounter pCount = NULL; + pMultiCounter self = NULL; + + pCount = (pCounter)pData; + if(pCount != NULL){ + self = (pMultiCounter)pCount->pDriv->pData; + } + assert(self); + + for(i = 0; i < self->nSlaves; i++){ + status = self->slaves[i]->Halt(self->slaveData[i]); + if(status != OKOK) + retVal = status; + } + return retVal; +} +/*-------------------------------------------------------------------------*/ +static int MMCCStart(void *pData, SConnection *pCon) +{ + int i, status; + pCounter pCount = NULL; + pMultiCounter self = NULL; + + pCount = (pCounter)pData; + if(pCount != NULL){ + self = (pMultiCounter)pCount->pDriv->pData; + } + assert(self); + + for(i = 0; i < self->nSlaves; i++){ + self->slaves[i]->SetCountParameters(self->slaveData[i], + pCount->pDriv->fPreset, pCount->pDriv->eMode); + status = self->slaves[i]->StartCount(self->slaveData[i],pCon); + if(status != OKOK){ + MMCCHalt(pData); + return status; + } + } + pCount->isUpToDate = 0; + pCount->tStart = time(NULL); + InvokeCallBack(pCount->pCall,COUNTSTART,pCon); + return OKOK; +} +/*-------------------------------------------------------------------------*/ +static int MMCCStatus(void *pData, SConnection *pCon){ + int status,i; + pCounter pCount = NULL; + pMultiCounter self = NULL; + pDummy pDum = NULL; + + pCount = (pCounter)pData; + if(pCount != NULL){ + self = (pMultiCounter)pCount->pDriv->pData; + } + assert(self); + + status = self->slaves[0]->CheckCountStatus(self->slaveData[0],pCon); + if(status == HWIdle || status == HWFault){ + /* + stop counting on slaves when finished or when an error + occurred. + */ + InvokeCallBack(pCount->pCall,COUNTEND,pCon); + MMCCHalt(pCount); + } + for(i = 1; i < MAXSLAVE; i++){ + if(self->slaves[i] != NULL){ + pDum = (pDummy)self->slaveData[i]; + if(strcmp(pDum->pDescriptor->name,"HistMem") == 0){ + HistDirty((pHistMem)self->slaveData[i]); + } + } + } + return status; +} +/*-------------------------------------------------------------------------*/ +static int MMCCPause(void *pData, SConnection *pCon){ + int i, status; + pCounter pCount = NULL; + pMultiCounter self = NULL; + + pCount = (pCounter)pData; + if(pCount != NULL){ + self = (pMultiCounter)pCount->pDriv->pData; + } + assert(self); + + for(i = 0; i < self->nSlaves; i++){ + status = self->slaves[i]->Pause(self->slaveData[i],pCon); + if(status != OKOK){ + MMCCHalt(pCount); + return status; + } + } + return OKOK; +} +/*--------------------------------------------------------------------------*/ +static int MMCCContinue(void *pData, SConnection *pCon){ + int i, status; + pCounter pCount = NULL; + pMultiCounter self = NULL; + + pCount = (pCounter)pData; + if(pCount != NULL){ + self = (pMultiCounter)pCount->pDriv->pData; + } + assert(self); + + for(i = 0; i < self->nSlaves; i++){ + status = self->slaves[i]->Continue(self->slaveData[i],pCon); + if(status != OKOK){ + MMCCHalt(pCount); + return status; + } + } + return OKOK; +} +/*------------------------------------------------------------------------*/ +static char *getNextMMCCNumber(char *pStart, char pNumber[80]){ + int charCount = 0; + pNumber[0] = '\0'; + + /* advance to first digit */ + while(isspace(*pStart) && *pStart != '\0'){ + pStart++; + } + if(*pStart == '\0'){ + return NULL; + } + + /* copy */ + while(!isspace(*pStart) && *pStart != '\0' && charCount < 78){ + pNumber[charCount] = *pStart; + pStart++; + charCount++; + } + pNumber[charCount] = '\0'; + return pStart; +} +/*-------------------------------------------------------------------------*/ +static void loadCountData(pCounter pCount, const char *data){ + char *pPtr = NULL; + char pNumber[80]; + int i = 0; + + pPtr = (char *)data; + pPtr = getNextMMCCNumber(pPtr,pNumber); + pCount->pDriv->fTime = atof(pNumber); + while(pPtr != NULL && i < MAXCOUNT){ + pPtr = getNextMMCCNumber(pPtr,pNumber); + pCount->pDriv->lCounts[i] = atoi(pNumber); + i++; + } +} +/*--------------------------------------------------------------------------*/ +static int MMCCTransfer(void *pData, SConnection *pCon){ + int i, retVal = OKOK, status; + char pBueffel[132]; + pCounter pCount = NULL; + pMultiCounter self = NULL; + int tclStatus; + + pCount = (pCounter)pData; + if(pCount != NULL){ + self = (pMultiCounter)pCount->pDriv->pData; + } + assert(self); + + for(i = 0; i < self->nSlaves; i++){ + status = self->slaves[i]->TransferData(self->slaveData[i], pCon); + if(status != OKOK){ + retVal = status; + sprintf(pBueffel,"WARNING: slave histogram %d failed to transfer data", + i); + SCWrite(pCon,pBueffel,eWarning); + } + } + if(self->transferScript != NULL){ + MacroPush(pCon); + tclStatus = Tcl_Eval(InterpGetTcl(pServ->pSics), self->transferScript); + if(tclStatus != TCL_OK){ + snprintf(pBueffel,131,"ERROR: TransferScript returned: %s", + Tcl_GetStringResult(InterpGetTcl(pServ->pSics))); + SCWrite(pCon,pBueffel,eError); + MacroPop(); + return HWFault; + } + MacroPop(); + loadCountData(pCount,Tcl_GetStringResult(InterpGetTcl(pServ->pSics))); + } + return retVal; +} +/*-------------------------------------------------------------------------*/ +static void MMCCParameter(void *pData, float fPreset, CounterMode eMode ){ + int i; + pCounter pCount = NULL; + pMultiCounter self = NULL; + + pCount = (pCounter)pData; + if(pCount != NULL){ + self = (pMultiCounter)pCount->pDriv->pData; + } + assert(self); + + for(i = 0; i < self->nSlaves; i++){ + self->slaves[i]->SetCountParameters(self->slaveData[i], fPreset, + eMode); + } +} +/*=============== Interpreter Interface ================================ */ +int MultiCounterAction(SConnection *pCon, SicsInterp *pSics, + void *pData, int argc, char *argv[]){ + pMultiCounter self = NULL; + pCounter pCount = NULL; + char buffer[256]; + + if(argc > 1){ + strtolower(argv[1]); + if(strcmp(argv[1],"transferscript") == 0){ + pCount = (pCounter)pData; + self = (pMultiCounter)pCount->pDriv->pData; + if(argc < 3){ + SCPrintf(pCon,eValue,"%s.transferscript = %s", + argv[0],self->transferScript); + return 1; + } else { + if(!SCMatchRights(pCon,usUser)){ + return 0; + } + if(self->transferScript != NULL){ + free(self->transferScript); + } + Arg2Text(argc-2,&argv[2],buffer,255); + self->transferScript = strdup(buffer); + SCSendOK(pCon); + return 1; + } + } + } + return CountAction(pCon,pSics,pData,argc,argv); +} +/*------------------------------------------------------------------------*/ +int MakeMultiCounter(SConnection *pCon, SicsInterp *pSics, + void *pData, int argc, char *argv[]){ + int i, status; + pCounter pNew = NULL; + char pBueffel[132]; + CommandList *pCom; + pICountable pCount; + pMultiCounter self = NULL; + pCounterDriver pDriv = NULL; + + /* + need at least two parameters + */ + if(argc < 3){ + SCWrite(pCon,"ERROR: insufficient number of arguments to MakeMultiCounter", + eError); + return 0; + } + + /* + allocate our data structure + */ + self = malloc(sizeof(MultiCounter)); + pDriv = malloc(sizeof(CounterDriver)); + if(self == NULL || pDriv == NULL){ + SCWrite(pCon,"ERROR: out of memory in MakeMultiCounter",eError); + return 0; + } + memset(self,0,sizeof(MultiCounter)); + memset(pDriv,0,sizeof(CounterDriver)); + pDriv->pData = self; + pDriv->KillPrivate = KillMultiDriver; + pDriv->iNoOfMonitors = MAXCOUNT; + pNew = CreateCounter(argv[1],pDriv); + if(pNew == NULL){ + SCWrite(pCon,"ERROR: out of memory in MakeMultiCounter",eError); + return 0; + } + + /* + assign interface functions + */ + pNew->pCountInt->Halt = MMCCHalt; + pNew->pCountInt->StartCount = MMCCStart; + pNew->pCountInt->CheckCountStatus = MMCCStatus; + pNew->pCountInt->Pause = MMCCPause; + pNew->pCountInt->Continue = MMCCContinue; + pNew->pCountInt->TransferData = MMCCTransfer; + pNew->pCountInt->SetCountParameters = MMCCParameter; + + /* + now loop through the remaining arguments, thereby entering them into + the slave list. + */ + for(i = 2; i < argc; i++){ + pCom = FindCommand(pSics,argv[i]); + if(!pCom){ + sprintf(pBueffel,"ERROR: object %s not found in MakeMultiCounter", + argv[i]); + SCWrite(pCon,pBueffel,eError); + continue; + } + pCount = GetCountableInterface(pCom->pData); + if(!pCount){ + sprintf(pBueffel,"ERROR: object %s is NOT countable", + argv[i]); + SCWrite(pCon,pBueffel,eError); + continue; + } + self->slaves[self->nSlaves] = pCount; + self->slaveData[self->nSlaves] = pCom->pData; + self->nSlaves++; + } + + /* + now install our action command and we are done + */ + status = AddCommand(pSics,argv[1],MultiCounterAction,DeleteCounter, + pNew); + if(!status){ + sprintf(pBueffel,"ERROR: duplicate command %s not created",argv[1]); + SCWrite(pCon,pBueffel,eError); + DeleteCounter(pNew); + return 0; + } + + return 1; +} + diff --git a/multicounter.h b/multicounter.h new file mode 100644 index 00000000..400e36f6 --- /dev/null +++ b/multicounter.h @@ -0,0 +1,19 @@ +/** + * The MultiCounter is another counter which coordinates multiple + * counting objects, counters and histogram memories. It also calls a + * script function after TransferData which collects counters and monitors. + * The purpose is to have a flexible counter abstraction for upper level + * code such as maximizers and scan functions. The script can deal with + * counting on monitors or on sums of histogram memories. + * + * copyright: see file COPYRIGHT + * + * Mark Koennecke, September 2006 + */ +#ifndef MULTICOUNTER_H_ +#define MULTICOUNTER_H_ +#include + +int MakeMultiCounter(SConnection *pCon, SicsInterp *pSics, + void *pData, int argc, char *argv[]); +#endif /*MULTICOUNTER_H_*/ diff --git a/nxscript.c b/nxscript.c index 6a2869e3..3339acff 100644 --- a/nxscript.c +++ b/nxscript.c @@ -1073,6 +1073,7 @@ int NXScriptAction(SConnection *pCon, SicsInterp *pSics, void *pData, pNXScript self = (pNXScript)pData; char *pFile = NULL; int status; + char buffer[132]; /* preliminary checks @@ -1136,6 +1137,20 @@ int NXScriptAction(SConnection *pCon, SicsInterp *pSics, void *pData, return 1; } + if(strcmp(argv[1],"isalias") == 0) { + if(argc < 3) { + SCWrite(pCon,"ERROR: need alias to test",eError); + return 1; + } + if(NXDget(self->dictHandle,argv[2],buffer,131) == NX_OK){ + snprintf(buffer,131,"%s = 1", argv[2]); + } else { + snprintf(buffer,131,"%s = 0", argv[2]); + } + SCWrite(pCon,buffer,eValue); + return 1; + } + if(strcmp(argv[1],"makelink") == 0){ makeLink(pCon,pSics,self,argc,argv); return 1; diff --git a/ofac.c b/ofac.c index 996f7f98..2c2bb4c0 100644 --- a/ofac.c +++ b/ofac.c @@ -119,6 +119,7 @@ #include "sicslist.h" #include "cone.h" #include "sicshipadaba.h" +#include "multicounter.h" /*----------------------- Server options creation -------------------------*/ static int IFServerOption(SConnection *pCon, SicsInterp *pSics, void *pData, int argc, char *argv[]) @@ -328,6 +329,8 @@ InstallSinfox,NULL,NULL); AddCommand(pInter,"MakeCone", MakeCone,NULL,NULL); + AddCommand(pInter,"MakeMultiCounter", + MakeMultiCounter,NULL,NULL); /* install site specific commands @@ -396,6 +399,7 @@ RemoveCommand(pSics,"InstallProtocolHandler"); RemoveCommand(pSics,"InstallSinfox"); RemoveCommand(pSics,"MakeCone"); + RemoveCommand(pSics,"MakeMultiCounter"); /* remove site specific installation commands */ diff --git a/regresscter.c b/regresscter.c new file mode 100644 index 00000000..a0701b50 --- /dev/null +++ b/regresscter.c @@ -0,0 +1,262 @@ +/*-------------------------------------------------------------------------- + This is a counter for use in automated regression tests. + + copyright: see file COPYRIGHT + + Mark Koennecke, September 2006 +----------------------------------------------------------------------------*/ +#include +#include +#include +#include +#include "fortify.h" +#include +#include "sics.h" +#include "countdriv.h" +/*---------------------------------- possible error types ------------------*/ +#define NONE 0 +#define STARTFAIL 1 +#define STATUSFAIL 2 +#define PAUSEFAIL 3 +#define CONTFAIL 4 +#define READFAIL 5 + +#define STATEIDLE 0 +#define STATERUN 1 +#define STATEPAU 2 +/*--------------------------------------------------------------------------*/ +typedef struct { + int errType; + int recover; + int state; + time_t endTime; +} RegressSt; +/*---------------------------------------------------------------------------*/ +static int RegressGetStatus(struct __COUNTER *self, float *fControl){ + RegressSt *pSim = NULL; + time_t tD, tDe; + int iRun; + + assert(self); + pSim = (RegressSt *) self->pData; + assert(pSim); + + if(pSim->errType == STATUSFAIL){ + return HWFault; + } + if(time(NULL) > pSim->endTime){ + pSim->state = STATEIDLE; + } + switch(pSim->state){ + case STATEIDLE: + return HWIdle; + break; + case STATERUN: + return HWBusy; + break; + case STATEPAU: + return HWPause; + break; + } + assert(0); + return HWFault; +} +/*---------------------------------------------------------------------------*/ +static int RegressStart(struct __COUNTER *self){ + RegressSt *pSim = NULL; + time_t tD; + int iRun; + + assert(self); + pSim = (RegressSt *) self->pData; + assert(pSim); + + if(pSim->errType == STARTFAIL){ + return HWFault; + } + pSim->state = STATERUN; + if(self->eMode == eTimer){ + pSim->endTime = time(NULL) + (int)self->fPreset; + } else { + pSim->endTime = time(NULL) + 7; + } + + return OKOK; +} +/*---------------------------------------------------------------------------*/ +static int RegressPause(struct __COUNTER *self){ + RegressSt *pSim = NULL; + time_t tD; + int iRun; + + assert(self); + pSim = (RegressSt *) self->pData; + assert(pSim); + + if(pSim->errType == PAUSEFAIL){ + return HWFault; + } + + pSim->state = STATEPAU; + + return OKOK; +} +/*---------------------------------------------------------------------------*/ +static int RegressContinue(struct __COUNTER *self){ + RegressSt *pSim = NULL; + + assert(self); + pSim = (RegressSt *) self->pData; + assert(pSim); + + if(pSim->errType == CONTFAIL){ + return HWFault; + } + + pSim->state = STATERUN; + + return OKOK; +} +/*--------------------------------------------------------------------------*/ +static int RegressHalt(struct __COUNTER *self){ + RegressSt *pSim = NULL; + + assert(self); + pSim = (RegressSt *) self->pData; + assert(pSim); + + pSim->state = STATEIDLE; + + return OKOK; +} + +/*-------------------------------------------------------------------------*/ +static int RegressReadValues(struct __COUNTER *self){ + RegressSt *pSim = NULL; + int i; + + assert(self); + pSim = (RegressSt *) self->pData; + assert(pSim); + + if(pSim->errType == READFAIL){ + return HWFault; + } + + for (i = 0; i < MAXCOUNT; i++) { + self->lCounts[i] = i*10+5; + } + self->lCounts[1] = self->fPreset; + self->fTime = self->fPreset; + return OKOK; +} +/*-------------------------------------------------------------------------*/ +static int RegressGetError(struct __COUNTER *self, int *iCode, char *error, + int iErrLen){ + strncpy(error, "Regression counter error", iErrLen); + *iCode = 1; + return 1; +} +/*--------------------------------------------------------------------------*/ +static int RegressTryAndFixIt(struct __COUNTER *self, int iCode){ + RegressSt *pSim = NULL; + + assert(self); + pSim = (RegressSt *) self->pData; + assert(pSim); + + if(pSim->recover == 1){ + pSim->errType = NONE; + return COREDO; + } else { + return COTERM; + } +} +/*--------------------------------------------------------------------------*/ +static int RegressSet(struct __COUNTER *self, char *name, int iCter, float FVal){ + RegressSt *pSim = NULL; + + assert(self); + pSim = (RegressSt *) self->pData; + assert(pSim); + + if(strcmp(name,"errortype") == 0){ + pSim->errType = (int)FVal; + return 1; + } + if(strcmp(name,"recover") == 0){ + pSim->recover = (int)FVal; + return 1; + } + if(strcmp(name,"finish") == 0){ + pSim->state = STATEIDLE; + return 1; + } + return 0; +} +/*--------------------------------------------------------------------------*/ +static int RegressGet(struct __COUNTER *self, char *name, + int iCter, float *fVal){ + RegressSt *pSim = NULL; + + assert(self); + pSim = (RegressSt *) self->pData; + assert(pSim); + + if(strcmp(name,"errortype") == 0){ + *fVal = pSim->errType; + return 1; + } + if(strcmp(name,"recover") == 0){ + *fVal = pSim->recover; + return 1; + } + return 0; +} +/*---------------------------------------------------------------------------*/ +static int RegressSend(struct __COUNTER *self, char *pText, + char *pReply, int iReplyLen){ + strncpy(pReply, "Simulated response", iReplyLen); + return 1; +} +/*---------------------------------------------------------------------------*/ +pCounterDriver NewRegressCounter(char *name){ + pCounterDriver pRes = NULL; + RegressSt *pData = NULL; + int iRet; + int iC1, iC2, iC3; + char *pErr; + char pBueffel[132]; + + pRes = CreateCounterDriver(name, "Regress"); + if (!pRes) { + return NULL; + } + + pData = (RegressSt *) malloc(sizeof(RegressSt)); + if (!pData) { + DeleteCounterDriver(pRes); + return NULL; + } + memset(pData,0,sizeof(RegressSt)); + pRes->pData = pData; + + /* + * assign functions + */ + pRes->GetStatus = RegressGetStatus; + pRes->Start = RegressStart; + pRes->Halt = RegressHalt; + pRes->ReadValues = RegressReadValues; + pRes->GetError = RegressGetError; + pRes->TryAndFixIt = RegressTryAndFixIt; + pRes->Pause = RegressPause; + pRes->Continue = RegressContinue; + pRes->Set = RegressSet; + pRes->Get = RegressGet; + pRes->Send = RegressSend; + pRes->KillPrivate = NULL; + pRes->iNoOfMonitors = 8; + + return pRes; +} diff --git a/scan.c b/scan.c index 89567c4e..359e9ba6 100644 --- a/scan.c +++ b/scan.c @@ -385,6 +385,7 @@ int AppendScanLine(pScanData self, char *line) } /*-------------------------------------------------------------------------*/ extern char *stptok(const char *s, char *t, int len, char *brk); +extern char *trim(char *txt); int StoreScanCounts(pScanData self, char *data) { @@ -402,7 +403,7 @@ int StoreScanCounts(pScanData self, char *data) InitCountEntry(&sCount); /* parse the data */ - pPtr = data; + pPtr = trim(data); pPtr = stptok(pPtr,pNumber,29," \t"); if(pPtr != NULL) { @@ -1584,7 +1585,7 @@ static int PrintTimes(pScanData self, SConnection *pCon, snprintf(pBueffel,59,"%s.scantimes = { ",name); DynStringCopy(data,pBueffel); - for(i = 0; i < self->iNP; i++) + for(i = 0; i < self->iCounts; i++) { DynarGet(self->pCounts,i,&pPtr); pData = (pCountEntry)pPtr; @@ -2127,12 +2128,17 @@ static int DumpScan(pScanData self, SConnection *pCon) } /*------------ functions */ else if(strcmp(argv[1],"function") == 0) - { - return InterpretScanFunctions(self, pCon, argc, argv); + { + return InterpretScanFunctions(self, pCon, argc, argv); } /*---------- scan */ else if(strcmp(argv[1],"run") == 0) { + if (argc < 5) { + sprintf(pBueffel,"ERROR: not enough arguments for %s run",argv[0]); + SCWrite(pCon,pBueffel,eError); + return 0; + } /* get NP */ iRet = Tcl_GetInt(InterpGetTcl(pSics),argv[2],&lNP); if(iRet != TCL_OK) @@ -2181,6 +2187,11 @@ static int DumpScan(pScanData self, SConnection *pCon) /*---------- silent */ else if(strcmp(argv[1],"silent") == 0) { + if (argc < 5) { + sprintf(pBueffel,"ERROR: not enough arguments for %s silent",argv[0]); + SCWrite(pCon,pBueffel,eError); + return 0; + } /* get NP */ iRet = Tcl_GetInt(InterpGetTcl(pSics),argv[2],&lNP); if(iRet != TCL_OK) @@ -2404,6 +2415,20 @@ static int DumpScan(pScanData self, SConnection *pCon) } return AppendVarPos(pCon,self,i,(float)fStep); } + else if(strcmp(argv[1],"softpos") == 0){ + if(argc > 2) { + if(!SCMatchRights(pCon,usMugger)){ + return 0; + } + self->posSoft = atoi(argv[2]); + SCSendOK(pCon); + return 1; + } else { + sprintf(pBueffel,"%s.softpos = %d", argv[0],self->posSoft); + SCWrite(pCon,pBueffel,eValue); + return 1; + } + } /*------- savecounter */ else if(strcmp(argv[1],"savecounter") == 0) { diff --git a/sicsdata.c b/sicsdata.c index 7c972f8d..bd01b91d 100644 --- a/sicsdata.c +++ b/sicsdata.c @@ -4,6 +4,8 @@ An attempt to a generic interface to SICS data for all sorts of SICS clients. + WARNING: this code only works when ints and floats are of the same size! + copyright: see file COPYRIGHT Mark Koennecke, June 2003 @@ -60,6 +62,47 @@ pSICSData createSICSData(void){ pNew->dataUsed = 0; return pNew; } +/*---------------------------------------------------------------------------*/ +int getSICSDataInt(pSICSData self, int pos, int *value){ + + if(pos >= self->dataUsed || self->dataType[pos] != INTTYPE){ + return 0; + } + *value = self->data[pos]; + return 1; +} +/*---------------------------------------------------------------------------*/ +int getSICSDataFloat(pSICSData self, int pos, float *value){ + if(pos >= self->dataUsed || self->dataType[pos] != FLOATTYPE){ + return 0; + } + memcpy(value,&self->data[pos],sizeof(float)); + return 1; +} +/*---------------------------------------------------------------------------*/ +int setSICSDataInt(pSICSData self, int pos, int value){ + int *idata = NULL; + + idata = getSICSDataPointer(self,0,pos+1); + if(idata == NULL){ + return 0; + } + idata[pos] = value; + self->dataType[pos] = INTTYPE; + return 1; +} +/*----------------------------------------------------------------------------*/ +int setSICSDataFloat(pSICSData self, int pos, float value){ + int *idata = NULL; + + idata = getSICSDataPointer(self,0,pos+1); + if(idata == NULL){ + return 0; + } + memcpy(&idata[pos],&value,sizeof(float)); + self->dataType[pos] = FLOATTYPE; + return 1; +} /*-------------------------------------------------------------------*/ int *getSICSDataPointer(pSICSData self, int start, int end){ int newSize; @@ -134,7 +177,7 @@ static void netEncode(pSICSData self){ } } /*---------------------------------------------------------------------*/ -static void clearSICSData(pSICSData self){ +void clearSICSData(pSICSData self){ assert(self); self->dataUsed = 0; @@ -543,6 +586,35 @@ static int copyHM(pSICSData self, int argc, char *argv[], SCSendOK(pCon); return 1; } +/*----------------------------------------------------------------------*/ +static int copyData(pSICSData self,SicsInterp *pSics, + SConnection *pCon,int argc, char *argv[]){ + pSICSData other = NULL; + int pos, start, end, i; + + if(argc < 6){ + SCWrite(pCon,"ERROR: Insufficient number of arguments to copydata", + eError); + return 0; + } + pos = atoi(argv[2]); + start = atoi(argv[4]); + end = atoi(argv[5]); + if((other = FindCommandData(pSics,argv[3],"SICSData")) == NULL){ + SCWrite(pCon,"ERROR: invalid SICSData requested",eError); + return 0; + } + if(start > end || end > other->dataUsed){ + SCWrite(pCon,"ERROR: invalid copy range specified",eError); + return 0; + } + getSICSDataPointer(self,pos, pos + (end -start)); + memcpy(&self->data[pos],&other->data[start],(end-start)*sizeof(int)); + memcpy(&self->dataType[pos],&other->dataType[start], + (end-start)*sizeof(char)); + + return 1; +} /*---------------------------------------------------------------------- Look here in order to find out about commands understood ----------------------------------------------------------------------*/ @@ -591,6 +663,8 @@ int SICSDataAction(SConnection *pCon, SicsInterp *pSics, void *pData, return 0; } return divideSicsData(self,pSics,pCon,argv[2]); + } else if(strcmp(argv[1],"copydata") == 0){ + return copyData(self,pSics,pCon,argc, argv); } else if(strcmp(argv[1],"putint") == 0){ /*---------- putint */ return putInt(self,argc-2,&argv[2],pCon, pSics); diff --git a/sicsdata.h b/sicsdata.h index 6c6eaa03..9d3bf8d3 100644 --- a/sicsdata.h +++ b/sicsdata.h @@ -39,5 +39,12 @@ int SICSDataAction(SConnection *pCon, SicsInterp *pSics, void *pData, int argc, char *argv[]); + + void clearSICSData(pSICSData self); + int getSICSDataInt(pSICSData self, int pos, int *value); + int getSICSDataFloat(pSICSData self, int pos, float *value); + int setSICSDataInt(pSICSData self, int pos, int value); + int setSICSDataFloat(pSICSData self, int pos, float value); + #endif diff --git a/sicsdata.w b/sicsdata.w index 7832e9a3..9d5e19f0 100644 --- a/sicsdata.w +++ b/sicsdata.w @@ -6,6 +6,8 @@ sources such as histogram memories or scans. Data assembled in this way, for instance through scripts, can then be forwarded to clients either in UUencoded form or as a zipped array. +WARNING: this code only works right when integers and floats are of the same size! + In a later stage this may be extended to support selected mathematical operations as well. In another stage this may supersede the uuget and zipget methods in the scan, histogram memory and specialized status @@ -48,6 +50,13 @@ This object exports the following functions: int SICSDataAction(SConnection *pCon, SicsInterp *pSics, void *pData, int argc, char *argv[]); + + void clearSICSData(pSICSData self); + int getSICSDataInt(pSICSData self, int pos, int *value); + int getSICSDataFloat(pSICSData self, int pos, float *value); + int setSICSDataInt(pSICSData self, int pos, int value); + int setSICSDataFloat(pSICSData self, int pos, float value); + @} \begin{description} \item[getSICSDataPointer] returns a pointer to the first element of diff --git a/sicshipadaba.c b/sicshipadaba.c index c5a54ae7..e6dec727 100644 --- a/sicshipadaba.c +++ b/sicshipadaba.c @@ -541,6 +541,12 @@ pHdb MakeSICSHdbPar(char *name, int priv, hdbValue v){ return result; } +/*---------------------------------------------------------------------------*/ +pHdb CreateSICSHdbPar(char *name, int priv, int dataType, + int length, void *data){ + return MakeSICSHdbPar(name,priv,makeHdbData(dataType, + length,data)); +} /*----------------------------------------------------------------------------*/ pHdb MakeSICSHdbDriv(char *name, int priv, void *sicsObject, int dataType){ pHdb result = NULL; @@ -659,6 +665,12 @@ pHdb MakeSICSScriptPar(char *name, char *setScript, char *readScript, return result; } +/*-------------------------------------------------------------------------*/ +pHdb CreateSICSScriptPar(char *name, char *setScript, char *readScript, + int dataType, int length, void *data){ + return MakeSICSScriptPar(name,setScript,readScript, + makeHdbData(dataType, length,data)); +} /*--------------------------------------------------------------------------*/ static void removeNodeFromUpdateList(pHdb node){ pHdb current = NULL; @@ -774,14 +786,23 @@ int AddSICSHdbMemPar(pHdb node, char *name, int priv, return 1; } /*==================== access suport functions ==============================*/ -int SICSHdbGetFloat(pHdb parent, SConnection *pCon, - char *path, float *value){ - hdbValue v; +int SICSHdbGetPar(void *obj, SConnection *pCon, + char *path, int dataType, void *data, int length){ pHdb par = NULL; int status; char buffer[256]; + pDummy pDum; - par = GetHipadabaNode(parent,path); + pDum = (pDummy)obj; + if(pDum == NULL || pDum->pDescriptor->parNode == NULL){ + if(pCon != NULL){ + snprintf(buffer,255,"ERROR: parameter %s not found", path); + SCWrite(pCon,buffer,eError); + } + return SICSNOPAR; + } + + par = GetHipadabaNode(pDum->pDescriptor->parNode,path); if(par == NULL){ if(pCon != NULL){ snprintf(buffer,255,"ERROR: parameter %s not found", path); @@ -790,31 +811,31 @@ int SICSHdbGetFloat(pHdb parent, SConnection *pCon, return SICSNOPAR; } - status = GetHipadabaPar(par,&v,pCon); + status = GetHdbPar(par,dataType,data,length,pCon); if(status < 0){ return status; } - if(v.dataType == HIPFLOAT){ - *value = (float)v.v.doubleValue; - } else if(v.dataType == HIPINT){ - *value = (float)v.v.intValue; - } else { - /* - * it is an error to call this for array dada types - */ - assert(0); - } return 1; } /*--------------------------------------------------------------------------*/ -int SICSHdbSetFloat(pHdb parent, SConnection *pCon, - char *path, float value){ +int SICSHdbUpdatePar(void *obj, SConnection *pCon, + char *path, int dataType,void *data, int dataLength ){ hdbValue v; pHdb par = NULL; int status; char buffer[256]; + pDummy pDum; - par = GetHipadabaNode(parent,path); + pDum = (pDummy)obj; + if(pDum == NULL || pDum->pDescriptor->parNode == NULL){ + if(pCon != NULL){ + snprintf(buffer,255,"ERROR: parameter %s not found", path); + SCWrite(pCon,buffer,eError); + } + return SICSNOPAR; + } + + par = GetHipadabaNode(pDum->pDescriptor->parNode,path); if(par == NULL){ if(pCon != NULL){ snprintf(buffer,255,"ERROR: parameter %s not found", path); @@ -822,26 +843,46 @@ int SICSHdbSetFloat(pHdb parent, SConnection *pCon, } return SICSNOPAR; } - - v.dataType = par->value.dataType; - if(v.dataType == HIPFLOAT){ - v.v.doubleValue = (double)value; - } else if(v.dataType == HIPINT){ - v.v.intValue = (int)value; - } else { - /* - * it is an error to call this for array dada types - */ - assert(0); - } - status = SetHipadabaPar(par,v,pCon); + status = UpdateHdbPar(par,dataType,data,dataLength,pCon); + if(status < 0){ + return status; + } + return 1; +} +/*--------------------------------------------------------------------------*/ +int SICSHdbSetPar(void *obj, SConnection *pCon, + char *path, int dataType,void *data, int dataLength ){ + hdbValue v; + pHdb par = NULL; + int status; + char buffer[256]; + pDummy pDum; + + pDum = (pDummy)obj; + if(pDum == NULL || pDum->pDescriptor->parNode == NULL){ + if(pCon != NULL){ + snprintf(buffer,255,"ERROR: parameter %s not found", path); + SCWrite(pCon,buffer,eError); + } + return SICSNOPAR; + } + + par = GetHipadabaNode(pDum->pDescriptor->parNode,path); + if(par == NULL){ + if(pCon != NULL){ + snprintf(buffer,255,"ERROR: parameter %s not found", path); + SCWrite(pCon,buffer,eError); + } + return SICSNOPAR; + } + + status = SetHdbPar(par,dataType,data,dataLength,pCon); if(status < 0){ return status; } return 1; } - /*---------------------------------------------------------------------------*/ int InstallSICSNotify(pHdb node, SConnection *pCon, int id, int recurse){ pHdb currentChild = NULL; diff --git a/sicshipadaba.h b/sicshipadaba.h index 9c172e71..b7d06644 100644 --- a/sicshipadaba.h +++ b/sicshipadaba.h @@ -117,6 +117,19 @@ pHdbCallback MakeMemSetCallback(float *address); * @return A new suitably configured Hdb parameter or NULL when out of memory. */ pHdb MakeSICSHdbPar(char *name, int priv, hdbValue v); +/** + * make a simple SICS hdb parameter. Setting it will call update immediately. Use + * this for program parameters. + * @param name The name of the parameter + * @param priv The privilege required to change that parameter + * @param dataType The datatype for the new parameter. + * @param length The length of any arrays + * @param data Data to initalise the parameter with. Can be NULL, then + * no initialisation takes place. + * @return A new suitably configured Hdb parameter or NULL when out of memory. + */ +pHdb CreateSICSHdbPar(char *name, int priv, int dataType, + int length, void *data); /** * make a SICS hdb drivable parameter. Setting it will start the motor, * virtual motor or environment parameter. This will call StartDevice @@ -153,6 +166,19 @@ pHdb MakeSICSROPar(char *name, hdbValue v); * @return A new suitably configured Hdb parameter or NULL when out of memory. */ pHdb MakeSICSScriptPar(char *name, char *setScript, char *readScript, hdbValue v); +/** + * make a SICS scriptable parameter. I.e. when this parameter is set or read, + * appropriate scripts are invoked. + * @param name The name of the parameter + * @param dataType The datatype for the new parameter. + * @param length The length of any arrays + * @param data Data to initalise the parameter with. Can be NULL, then + * no initialisation takes place. + * @return A new suitably configured Hdb parameter or NULL when out of memory. + */ +pHdb CreateSICSScriptPar(char *name, char *setScript, char *readScript, + int dataType, int length, void *data); + /** * remove a SICS paramameter node and its children. In contrast to the * normal DeletHipadabaNode, this function also takes care of @@ -194,27 +220,41 @@ int AddSICSHdbMemPar(pHdb node, char *name, int priv, void *data, int datalength, int type, int length); /*============== access support functions =================================*/ /** - * SICSHdbGetFloat returns the float value of a parameter. Integers are - * automatically converted. - * @param parent The parent node where to start searching for the parameter + * SICSHdbGetPar returns the value of a parameter. + * @param obj The object for which to get a parameter. * @param pCon The optional connection object to use for reporting errors. * @param path The path to the parameter. - * @param value The value of the parameter + * @param dataType The datatype for the parameter. + * @param data Target pointer to which to copy data too. + * @param length The length of data * @return 1 on success, a negative error code else. */ -int SICSHdbGetFloat(pHdb parent, SConnection *pCon, - char *path, float *value); +int SICSHdbGetPar(void *obj, SConnection *pCon, + char *path, int dataType, void *data, int length); /** - * SICSHdbSetFloat sets the value of a parameter. Integers are - * automatically converted. - * @param parent The parent node where to start searching for the parameter + * SICSHdbUpdatePar updates the value of a parameter. + * @param obj The object for which to get a parameter. * @param pCon The optional connection object to use for reporting errors. * @param path The path to the parameter. - * @param value The new value of the parameter + * @param dataType The datatype for the parameter. + * @param data Pointer from which to copy data. + * @param length The length of data * @return 1 on success, a negative error code else. */ -int SICSHdbSetFloat(pHdb parent, SConnection *pCon, - char *path, float value); +int SICSHdbUpdatePar(void *obj, SConnection *pCon, + char *path, int dataType, void *data, int length); +/** + * SICSHdbSetPar sets the value of a parameter. + * @param obj The object for which to get a parameter. + * @param pCon The optional connection object to use for reporting errors. + * @param path The path to the parameter. + * @param dataType The datatype for the parameter. + * @param data Pointer from which to copy data. + * @param length The length of data + * @return 1 on success, a negative error code else. + */ +int SICSHdbSetPar(void *obj, SConnection *pCon, + char *path, int dataType, void *data, int length); /** * query function if a parameter is read only. * @param node The ndoe to query diff --git a/tasdrive.c b/tasdrive.c index b0211af6..1c0bf6b7 100644 --- a/tasdrive.c +++ b/tasdrive.c @@ -34,6 +34,11 @@ static long TASSetValue(void *pData, SConnection *pCon, ptasMot self = (ptasMot)pData; assert(self); + if(self->code > 5 && self->math->tasMode == ELASTIC){ + SCWrite(pCon,"ERROR: cannot drive this motor in elastic mode", + eError); + return HWFault; + } setTasPar(&self->math->target,self->math->tasMode,self->code,value); self->math->mustDrive = 1; return OKOK; @@ -132,6 +137,10 @@ static float TASGetValue(void *pData, SConnection *pCon){ self->math->mustRecalculate = 0; } val = getTasPar(self->math->current,self->code); + if(self->code > 5 && self->math->tasMode == ELASTIC){ + SCWrite(pCon,"WARNING: value for this motor is meaningless in elastic mode", + eWarning); + } return (float)val; } /*-----------------------------------------------------------------*/ @@ -202,6 +211,13 @@ static void writeMotPos(SConnection *pCon, int silent, char *name, SCWrite(pCon,pBueffel,eWarning); } } +/*--------------------------------------------------------------------------*/ +static float getMotorValue(pMotor mot, SConnection *pCon){ + float val; + + MotorGetSoftPosition(mot,pCon,&val); + return val; +} /*---------------------------------------------------------------------------*/ static int startMotors(ptasMot self, tasAngles angles, SConnection *pCon, int driveQ, int driveTilt){ @@ -213,7 +229,7 @@ static int startMotors(ptasMot self, tasAngles angles, /* monochromator */ - val = self->math->motors[A1]->pDrivInt->GetValue(self->math->motors[A1],pCon); + val = getMotorValue(self->math->motors[A1],pCon); if(ABS(val - angles.monochromator_two_theta/2.) > MOTPREC){ status = self->math->motors[A1]->pDrivInt->SetValue(self->math->motors[A1], pCon, @@ -224,7 +240,7 @@ static int startMotors(ptasMot self, tasAngles angles, } writeMotPos(pCon,silent,"a1",val, angles.monochromator_two_theta/2.); - val = self->math->motors[A2]->pDrivInt->GetValue(self->math->motors[A2],pCon); + val = getMotorValue(self->math->motors[A2],pCon); if(ABS(val - angles.monochromator_two_theta) > MOTPREC){ status = self->math->motors[A2]->pDrivInt->SetValue(self->math->motors[A2], pCon, @@ -238,7 +254,8 @@ static int startMotors(ptasMot self, tasAngles angles, if(self->math->motors[MCV] != NULL){ curve = maCalcVerticalCurvature(self->math->machine.monochromator, angles.monochromator_two_theta); - val = self->math->motors[MCV]->pDrivInt->GetValue(self->math->motors[MCV],pCon); + + val = getMotorValue(self->math->motors[MCV],pCon); if(ABS(val - curve) > MOTPREC){ status = self->math->motors[MCV]->pDrivInt->SetValue(self->math->motors[MCV], pCon, @@ -253,7 +270,8 @@ static int startMotors(ptasMot self, tasAngles angles, if(self->math->motors[MCH] != NULL){ curve = maCalcHorizontalCurvature(self->math->machine.monochromator, angles.monochromator_two_theta); - val = self->math->motors[MCH]->pDrivInt->GetValue(self->math->motors[MCH],pCon); + + val = getMotorValue(self->math->motors[MCH],pCon); if(ABS(val - curve) > MOTPREC){ status = self->math->motors[MCH]->pDrivInt->SetValue(self->math->motors[MCH], pCon, @@ -269,8 +287,7 @@ static int startMotors(ptasMot self, tasAngles angles, analyzer */ if(self->math->tasMode != ELASTIC){ - val = self->math->motors[A5]->pDrivInt->GetValue(self->math->motors[A5], - pCon); + val = getMotorValue(self->math->motors[A5],pCon); if(ABS(val - angles.analyzer_two_theta/2.) > MOTPREC){ status = self->math->motors[A5]->pDrivInt->SetValue(self->math->motors[A5], pCon, @@ -282,7 +299,7 @@ static int startMotors(ptasMot self, tasAngles angles, writeMotPos(pCon,silent,self->math->motors[A5]->name, val, angles.analyzer_two_theta/2.); - val = self->math->motors[A6]->pDrivInt->GetValue(self->math->motors[A6],pCon); + val = getMotorValue(self->math->motors[A6],pCon); if(ABS(val - angles.analyzer_two_theta) > MOTPREC){ status = self->math->motors[A6]->pDrivInt->SetValue(self->math->motors[A6], pCon, @@ -296,7 +313,7 @@ static int startMotors(ptasMot self, tasAngles angles, if(self->math->motors[ACV] != NULL){ curve = maCalcVerticalCurvature(self->math->machine.analyzer, angles.analyzer_two_theta); - val = self->math->motors[ACV]->pDrivInt->GetValue(self->math->motors[ACV],pCon); + val = getMotorValue(self->math->motors[ACV],pCon); if(ABS(val - curve) > MOTPREC){ status = self->math->motors[ACV]->pDrivInt->SetValue(self->math->motors[ACV], pCon, @@ -310,8 +327,7 @@ static int startMotors(ptasMot self, tasAngles angles, if(self->math->motors[ACH] != NULL){ curve = maCalcHorizontalCurvature(self->math->machine.analyzer, angles.analyzer_two_theta); - val = self->math->motors[ACH]->pDrivInt->GetValue(self->math->motors[ACH], - pCon); + val = getMotorValue(self->math->motors[ACH],pCon); if(ABS(val - curve) > MOTPREC){ status = self->math->motors[ACH]->pDrivInt->SetValue(self->math->motors[ACH], pCon, @@ -331,7 +347,7 @@ static int startMotors(ptasMot self, tasAngles angles, /* crystal */ - val = self->math->motors[A3]->pDrivInt->GetValue(self->math->motors[A3],pCon); + val = getMotorValue(self->math->motors[A3],pCon); if(ABS(val - angles.a3) > MOTPREC){ status = self->math->motors[A3]->pDrivInt->SetValue(self->math->motors[A3], pCon, @@ -342,7 +358,7 @@ static int startMotors(ptasMot self, tasAngles angles, } writeMotPos(pCon,silent,"a3",val, angles.a3); - val = self->math->motors[A4]->pDrivInt->GetValue(self->math->motors[A4],pCon); + val = getMotorValue(self->math->motors[A4],pCon); if(ABS(val - angles.sample_two_theta) > MOTPREC){ status = self->math->motors[A4]->pDrivInt->SetValue(self->math->motors[A4], pCon, @@ -354,7 +370,7 @@ static int startMotors(ptasMot self, tasAngles angles, writeMotPos(pCon,silent,"a4",val, angles.sample_two_theta); if(driveTilt == 1){ - val = self->math->motors[SGL]->pDrivInt->GetValue(self->math->motors[SGL],pCon); + val = getMotorValue(self->math->motors[SGL],pCon); if(ABS(val - angles.sgl) > MOTPREC){ status = self->math->motors[SGL]->pDrivInt->SetValue(self->math->motors[SGL], pCon, @@ -365,7 +381,7 @@ static int startMotors(ptasMot self, tasAngles angles, } writeMotPos(pCon,silent,"sgl",val, angles.sgl); - val = self->math->motors[SGU]->pDrivInt->GetValue(self->math->motors[SGU],pCon); + val = getMotorValue(self->math->motors[SGU],pCon); if(ABS(val - angles.sgu) > MOTPREC){ status = self->math->motors[SGU]->pDrivInt->SetValue(self->math->motors[SGU], pCon, diff --git a/tasub.c b/tasub.c index 0db04c9f..e498011b 100644 --- a/tasub.c +++ b/tasub.c @@ -242,7 +242,7 @@ int TasUBFactory(SConnection *pCon,SicsInterp *pSics, void *pData, return 0; } if(argc > 2 && argc < 14){ - SCWrite(pCon,"ERROR: not enough motor names specified form MakeTasUB",eError); + SCWrite(pCon,"ERROR: not enough motor names specified for MakeTasUB",eError); return 0; } pNew = MakeTasUB(); @@ -414,7 +414,7 @@ static int getCrystalParameters(pmaCrystal crystal, SConnection *pCon, SCWrite(pCon,pBueffel,eValue); return 1; }else if(strcmp(argv[2],"vb2") == 0){ - snprintf(pBueffel,131,"%s.%s.vb2 = %f",argv[0],argv[1],crystal->VB1); + snprintf(pBueffel,131,"%s.%s.vb2 = %f",argv[0],argv[1],crystal->VB2); SCWrite(pCon,pBueffel,eValue); return 1; }else if(strcmp(argv[2],"ss") == 0){ @@ -952,6 +952,44 @@ static int calcUB(ptasUB self, SConnection *pCon, SicsInterp *pSics, SCparChange(pCon); return 1; } +/*-----------------------------------------------------------------*/ +static int calcUBFromCell(ptasUB self, SConnection *pCon){ + MATRIX B, U, UB; + int status; + + B = mat_creat(3,3,UNIT_MATRIX); + U = mat_creat(3,3,UNIT_MATRIX); + if(B == NULL || U == NULL){ + SCWrite(pCon,"ERROR: out of memory in calcUBFromCell",eError); + return 0; + } + status = calculateBMatrix(self->cell,B); + if(status == REC_NO_VOLUME){ + SCWrite(pCon,"ERROR: cell has no volume",eError); + return 0; + } + UB = mat_mul(U,B); + if(UB == NULL){ + SCWrite(pCon,"ERROR: matrix multiplication failed",eError); + return 0; + } + if(mat_det(UB) < .000001){ + SCWrite(pCon,"ERROR: invalid UB matrix, check reflections",eError); + return 0; + } + if(self->machine.UB != NULL){ + mat_free(self->machine.UB); + } + self->machine.UB = UB; + self->machine.planeNormal[0][0] = .0; + self->machine.planeNormal[1][0] = .0; + self->machine.planeNormal[2][0] = 1.; + self->ubValid = 1; + SCparChange(pCon); + mat_free(U); + mat_free(B); + return 1; +} /*------------------------------------------------------------------*/ static int calcRefAngles(ptasUB self, SConnection *pCon, SicsInterp *pSics, @@ -1421,6 +1459,8 @@ int TasUBWrapper(SConnection *pCon,SicsInterp *pSics, void *pData, return 1; } else if(strcmp(argv[1],"makeub") == 0){ return calcUB(self,pCon,pSics,argc,argv); + } else if(strcmp(argv[1],"makeubfromcell") == 0){ + return calcUBFromCell(self,pCon); } else if(strcmp(argv[1],"calcang") == 0){ return calcRefAngles(self,pCon,pSics,argc,argv); } else if(strcmp(argv[1],"calcqe") == 0){