diff --git a/.cdtproject b/.cdtproject index 784922d7..0fc98cfb 100644 --- a/.cdtproject +++ b/.cdtproject @@ -3,7 +3,13 @@ - + + + + + + + diff --git a/HistDriv.i b/HistDriv.i index ae5e646d..1e033d86 100644 --- a/HistDriv.i +++ b/HistDriv.i @@ -1,5 +1,5 @@ -#line 462 "histogram.w" +#line 465 "histogram.w" /*--------------------------------------------------------------------------- H I S T D R I V @@ -58,6 +58,9 @@ SConnection *pCon); float (*GetTime)(pHistDriver self, SConnection *pCon); + HistInt *(*SubSample)(pHistDriver self, + SConnection *pCon,int bank, + char *command); int (*Preset)(pHistDriver self, SConnection *pCon, HistInt iVal); @@ -69,17 +72,17 @@ void *pPriv; } HistDriver; -#line 474 "histogram.w" +#line 477 "histogram.w" -#line 229 "histogram.w" +#line 232 "histogram.w" pHistDriver CreateHistDriver(pStringDict pDict); void DeleteHistDriver(pHistDriver self); int HistDriverConfig(pHistDriver self, pStringDict pOpt, SConnection *pCon); -#line 475 "histogram.w" +#line 478 "histogram.w" #endif diff --git a/HistMem.h b/HistMem.h index a05cb32f..b0872505 100644 --- a/HistMem.h +++ b/HistMem.h @@ -1,5 +1,5 @@ -#line 435 "histogram.w" +#line 438 "histogram.w" /*-------------------------------------------------------------------------- H I S T M E M @@ -42,22 +42,22 @@ eReflect } OverFlowMode; -#line 455 "histogram.w" +#line 458 "histogram.w" /*--------------------------------------------------------------------------*/ -#line 287 "histogram.w" +#line 290 "histogram.w" pHistMem CreateHistMemory(char *drivername); void DeleteHistMemory(void *self); -#line 303 "histogram.w" +#line 306 "histogram.w" int HistGetOption(pHistMem self, char *name, char *result, int iResultLen); int HistSetOption(pHistMem self, char *name, char *value); int HistConfigure(pHistMem self, SConnection *pCon, SicsInterp *pSics); -#line 331 "histogram.w" +#line 334 "histogram.w" float GetHistPreset(pHistMem self); int SetHistPreset(pHistMem self, float fVal); @@ -73,7 +73,7 @@ void HistDirty(pHistMem self); -#line 361 "histogram.w" +#line 364 "histogram.w" int SetHistogram(pHistMem self, SConnection *pCon, int i,int iStart, int iEnd, HistInt *lData); @@ -85,7 +85,7 @@ HistInt *lData, int iDataLen); int PresetHistogram(pHistMem self, SConnection *pCon, HistInt lVal); -#line 404 "histogram.w" +#line 407 "histogram.w" int MakeHistMemory(SConnection *pCon, SicsInterp *pSics, void *pData, int argc, char *argv[]); @@ -94,7 +94,7 @@ int argc, char *argv[]); -#line 457 "histogram.w" +#line 460 "histogram.w" #endif diff --git a/HistMem.i b/HistMem.i index c3bc4a22..8ff674ed 100644 --- a/HistMem.i +++ b/HistMem.i @@ -1,5 +1,5 @@ -#line 480 "histogram.w" +#line 483 "histogram.w" /*--------------------------------------------------------------------------- H I S T M E M -- Internal @@ -11,7 +11,7 @@ #ifndef SICSHISTMEMINT #define SICSHISTMEMINT -#line 251 "histogram.w" +#line 254 "histogram.w" typedef struct __HistMem { pObjectDescriptor pDes; @@ -23,7 +23,7 @@ pICallBack pCall; } HistMem; -#line 490 "histogram.w" +#line 493 "histogram.w" #endif diff --git a/conman.c b/conman.c index c341ec79..d4b6ab55 100644 --- a/conman.c +++ b/conman.c @@ -39,6 +39,8 @@ fields. Mark Koennecke, December 2004 + Aded buffering support, Mark Koennecke, July 2006 + Copyright: see copyright.h -----------------------------------------------------------------------------*/ #include "fortify.h" @@ -457,6 +459,11 @@ extern pServer pServ; DeleteCommandStack(pVictim->pStack); } + /* remove possible buffers */ + if(pVictim->data != NULL) + { + DeleteDynString(pVictim->data); + } pVictim->lMagic=0; /* make a write to a freed connection harmless */ /* finally free pVictim*/ @@ -809,6 +816,52 @@ static void writeToLogFiles(SConnection *self, char *buffer) free(bufPtr); return 1; } +/*-------------------------------------------------------------------------*/ +static int SCBufferWrite(SConnection *self, char *buffer, int iOut) +{ + if(!VerifyConnection(self)) + { + return 0; + } + assert(self->data != NULL); + DynStringConcat(self->data,buffer); + if(strchr(buffer,'\n') == NULL){ + DynStringConcat(self->data,"\n"); + } + return 1; +} +/*-------------------------------------------------------------------------*/ +int SCStartBuffering(SConnection *pCon) +{ + if(!VerifyConnection(pCon)) + { + return 0; + } + if(pCon->data != NULL) + { + DeleteDynString(pCon->data); + } + pCon->data = CreateDynString(128,128); + if(pCon->data == NULL) + { + return 0; + } + pCon->oldWriteFunc = pCon->write; + pCon->write = SCBufferWrite; + return 1; +} +/*-------------------------------------------------------------------------*/ +pDynString SCEndBuffering(SConnection *pCon) +{ + if(!VerifyConnection(pCon)) + { + return 0; + } + assert(pCon->oldWriteFunc != NULL); + pCon->write = pCon->oldWriteFunc; + pCon->oldWriteFunc = NULL; + return pCon->data; +} /*--------------------------------------------------------------------------*/ int SCOnlySockWrite(SConnection *self, char *buffer, int iOut) { diff --git a/conman.h b/conman.h index 17928a5b..af9fd299 100644 --- a/conman.h +++ b/conman.h @@ -24,6 +24,7 @@ #include "network.h" #include "obdes.h" #include "commandcontext.h" +#include "dynstring.h" #define MAXLOGFILES 10 @@ -59,6 +60,12 @@ typedef int (*writeFunc)(struct __SConnection *pCon, int iGrab; /* grab flag for token*/ int parameterChange; int sicsError; + + /* + * for I/O Buffering + */ + pDynString data; + writeFunc oldWriteFunc; /* stuff supporting the sycamore protocol and a @@ -116,6 +123,9 @@ typedef int (*writeFunc)(struct __SConnection *pCon, int SCNotWrite(SConnection *self, char *buffer, int iOut); int SCNormalWrite(SConnection *self, char *buffer, int iOut); int SCWriteWithOutcode(SConnection *self, char *buffer, int iOut); +/*********************** I/O Buffering ***********************************/ + int SCStartBuffering(SConnection *pCon); + pDynString SCEndBuffering(SConnection *pCon); /************************* CallBack *********************************** */ int SCRegister(SConnection *pCon, SicsInterp *pSics, void *pInter, long lID); diff --git a/devexec.c b/devexec.c index d539c6e0..45967987 100644 --- a/devexec.c +++ b/devexec.c @@ -200,6 +200,7 @@ typedef struct { pRes->lTask = -1; pRes->iLock = 0; pRes->drivePrint = 0; + pRes->paused = 0; pRes->pCall = CreateCallBackInterface(); pRes->lastRun = time(NULL); return pRes; diff --git a/devexec.h b/devexec.h index 9c0bd015..028d5e37 100644 --- a/devexec.h +++ b/devexec.h @@ -118,6 +118,8 @@ #line 259 "devexec.w" /*-------------------------- Commands ------------------------------------*/ + int DevexecAction(SConnection *pCon, SicsInterp *pSics, void *pData, + int argc, char *argv[]); int StopCommand(SConnection *pCon, SicsInterp *pSics, void *pData, int argc, char *argv[]); /* @@ -161,7 +163,7 @@ void UnlockDeviceExecutor(pExeList self); -#line 297 "devexec.w" +#line 299 "devexec.w" /* -------------------------- Executor management -------------------------*/ diff --git a/devexec.tex b/devexec.tex index 20dd2e56..6ebd2463 100644 --- a/devexec.tex +++ b/devexec.tex @@ -312,6 +312,8 @@ to the global SICS device executor. \mbox{}\verb@/*-------------------------------------------------------------------------*/@\\ \mbox{}\verb@@$\langle$devstop {\footnotesize ?}$\rangle$\verb@@\\ \mbox{}\verb@/*-------------------------- Commands ------------------------------------*/@\\ +\mbox{}\verb@ int DevexecAction(SConnection *pCon, SicsInterp *pSics, void *pData,@\\ +\mbox{}\verb@ int argc, char *argv[]);@\\ \mbox{}\verb@ int StopCommand(SConnection *pCon, SicsInterp *pSics, void *pData,@\\ \mbox{}\verb@ int argc, char *argv[]);@\\ \mbox{}\verb@ /*@\\ diff --git a/devexec.w b/devexec.w index f97023f3..12acf662 100644 --- a/devexec.w +++ b/devexec.w @@ -258,6 +258,8 @@ to the global SICS device executor. /*-------------------------------------------------------------------------*/ @ /*-------------------------- Commands ------------------------------------*/ + int DevexecAction(SConnection *pCon, SicsInterp *pSics, void *pData, + int argc, char *argv[]); int StopCommand(SConnection *pCon, SicsInterp *pSics, void *pData, int argc, char *argv[]); /* diff --git a/hipadaba.c b/hipadaba.c index 3ec67b0f..29390248 100644 --- a/hipadaba.c +++ b/hipadaba.c @@ -270,9 +270,9 @@ hdbValue makeHdbValue(int datatype, int length){ case HIPINTAR: case HIPINTVARAR: val.arrayLength = length; - val.v.intArray = malloc(length*sizeof(long)); + val.v.intArray = malloc(length*sizeof(int)); if(val.v.intArray != NULL){ - memset(val.v.intArray,0,length*sizeof(long)); + memset(val.v.intArray,0,length*sizeof(int)); } break; case HIPFLOATAR: @@ -285,6 +285,7 @@ hdbValue makeHdbValue(int datatype, int length){ break; case HIPTEXT: val.v.text = strdup("UNKNOWN"); + val.arrayLength = length; break; } return val; @@ -311,10 +312,11 @@ hdbValue MakeHdbText(char *initText){ result.dataType = HIPTEXT; result.v.text = initText; + result.arrayLength = strlen(initText); return result; } /*-------------------------------------------------------------------------*/ -hdbValue MakeHdbIntArray(int length, long *data){ +hdbValue MakeHdbIntArray(int length, int *data){ hdbValue result; result.dataType = HIPINTAR; @@ -438,11 +440,11 @@ pHdb MakeHipadabaNode(char *name, int datatype, int length){ case HIPINTAR: case HIPINTVARAR: pNew->value.arrayLength = length; - pNew->value.v.intArray = malloc(length*sizeof(long)); + pNew->value.v.intArray = malloc(length*sizeof(int)); if(pNew->value.v.intArray == NULL){ return NULL; } - memset(pNew->value.v.intArray,0,length*sizeof(long)); + memset(pNew->value.v.intArray,0,length*sizeof(int)); break; case HIPFLOATAR: case HIPFLOATVARAR: @@ -454,6 +456,7 @@ pHdb MakeHipadabaNode(char *name, int datatype, int length){ memset(pNew->value.v.floatArray,0,length*sizeof(double)); break; case HIPTEXT: + pNew->value.arrayLength = length; pNew->value.v.text = strdup("UNKNOWN"); break; } @@ -463,7 +466,10 @@ pHdb MakeHipadabaNode(char *name, int datatype, int length){ void AddHipadabaChild(pHdb parent, pHdb child){ pHdb current = NULL, prev = NULL; - assert(parent != NULL && child != NULL); + assert(parent != NULL); + if(child == NULL){ + return; + } current = parent->child; child->mama = parent; @@ -745,11 +751,11 @@ int copyHdbValue(hdbValue *source, hdbValue *target){ if(target->v.intArray != NULL){ free(target->v.intArray); } - target->v.intArray = malloc(source->arrayLength * sizeof(long)); + target->v.intArray = malloc(source->arrayLength * sizeof(int)); if(target->v.intArray == NULL){ return 0; } - memset(target->v.intArray,0,source->arrayLength * sizeof(long)); + memset(target->v.intArray,0,source->arrayLength * sizeof(int)); target->arrayLength = source->arrayLength; } for(i = 0; i < source->arrayLength; i++){ @@ -812,4 +818,3 @@ int GetHipadabaPar(pHdb node, hdbValue *v, void *callData){ copyHdbValue(&node->value,v); return 1; } - diff --git a/hipadaba.h b/hipadaba.h index bc0f4e99..b7218aae 100644 --- a/hipadaba.h +++ b/hipadaba.h @@ -42,10 +42,10 @@ typedef struct __hdbValue { int dataType; int arrayLength; union __value { - long intValue; + int intValue; double doubleValue; char *text; - long *intArray; + int *intArray; double *floatArray; }v; }hdbValue; @@ -107,7 +107,7 @@ hdbValue MakeHdbText(char *initText); * data points to dynamically allocated memory. * @return: A properly initialized hdbValue structure */ -hdbValue MakeHdbIntArray(int length, long *data); +hdbValue MakeHdbIntArray(int length, int *data); /** * wrap a float array as an hdbValue * @param length The length of the int array diff --git a/histmem.c b/histmem.c index 11123427..71d1a739 100644 --- a/histmem.c +++ b/histmem.c @@ -1373,11 +1373,16 @@ static int checkHMEnd(pHistMem self, char *text){ iStart = 0; } - if(argc > 4){ - iEnd = checkHMEnd(self,argv[4]); - } else { - iEnd = checkHMEnd(self,NULL); - } + if(argc > 4){ + iEnd = checkHMEnd(self,argv[4]); + } else { + iEnd = checkHMEnd(self,NULL); + } + + if(iNum != 0 && argc > 4) + { + iEnd = atoi(argv[4]); + } /* allocate data storage and get it */ lData = (HistInt *)malloc(iEnd*sizeof(HistInt)); @@ -1387,8 +1392,14 @@ static int checkHMEnd(pHistMem self, char *text){ return 0; } memset(lData,0,iEnd*sizeof(HistInt)); - iRet = GetHistogram(self,pCon,iNum,iStart,iEnd, - lData,iEnd*sizeof(long)); + if(iNum == 0) + { + iRet = GetHistogram(self,pCon,iNum,iStart,iEnd, + lData,iEnd*sizeof(long)); + } else { + iRet = GetHistogramDirect(self,pCon,iNum,iStart, iEnd, + lData, iEnd*sizeof(long)); + } if(!iRet) { sprintf(pBueffel,"ERROR: cannot retrieve histogram %d",iNum); diff --git a/histogram.tex b/histogram.tex index e5911e74..ce8e30ab 100644 --- a/histogram.tex +++ b/histogram.tex @@ -163,6 +163,9 @@ $\langle$HistType {\footnotesize ?}$\rangle\equiv$ \mbox{}\verb@ SConnection *pCon);@\\ \mbox{}\verb@ float (*GetTime)(pHistDriver self,@\\ \mbox{}\verb@ SConnection *pCon);@\\ +\mbox{}\verb@ HistInt *(*SubSample)(pHistDriver self, @\\ +\mbox{}\verb@ SConnection *pCon,int bank,@\\ +\mbox{}\verb@ char *command); @\\ \mbox{}\verb@ int (*Preset)(pHistDriver self,@\\ \mbox{}\verb@ SConnection *pCon,@\\ \mbox{}\verb@ HistInt iVal);@\\ diff --git a/histogram.w b/histogram.w index f529081f..d59edabf 100644 --- a/histogram.w +++ b/histogram.w @@ -130,6 +130,9 @@ definition: SConnection *pCon); float (*GetTime)(pHistDriver self, SConnection *pCon); + HistInt *(*SubSample)(pHistDriver self, + SConnection *pCon,int bank, + char *command); int (*Preset)(pHistDriver self, SConnection *pCon, HistInt iVal); diff --git a/hmdata.c b/hmdata.c index b9201f66..3bf42ed0 100644 --- a/hmdata.c +++ b/hmdata.c @@ -46,7 +46,7 @@ void clearHMData(pHMdata self){ size *= self->iDim[i]; } if(self->tofMode){ - size *= self->nTimeChan; + size *= getNoOfTimebins(self); } memset(self->localBuffer,0,size*sizeof(HistInt)); } @@ -60,7 +60,7 @@ static int resizeBuffer(pHMdata self){ size *= self->iDim[i]; } if(self->tofMode){ - size *= self->nTimeChan; + size *= getNoOfTimebins(self); } if(self->localBuffer != NULL){ free(self->localBuffer); @@ -80,6 +80,7 @@ int configureHMdata(pHMdata self, pStringDict pOpt, int status, i; float fVal; char pValue[80]; + pHistMem master = NULL; if(self->nTimeChan > 2) { self->tofMode = 1; @@ -111,6 +112,18 @@ int configureHMdata(pHMdata self, pStringDict pOpt, self->updateIntervall = (int)rint(fVal); } + status = StringDictGet(pOpt,"timeslave",pValue, 79); + if(status == 1) { + master = (pHistMem)FindCommandData(pServ->pSics,pValue,"HistMem"); + if(master == NULL){ + SCWrite(pCon,"ERROR: timeslave requested, but master HM not found", + eError); + } else { + self->timeslave = master->pDriv->data; + self->tofMode = 1; + } + } + /* invalidate buffer */ @@ -138,7 +151,7 @@ int configureHMdata(pHMdata self, pStringDict pOpt, int genTimeBinning(pHMdata self, float start, float step, int noSteps){ int i; - if(noSteps >= MAXCHAN){ + if(noSteps >= MAXCHAN || self->timeslave != NULL){ return 0; } for(i = 0; i < noSteps; i++){ @@ -150,6 +163,10 @@ int genTimeBinning(pHMdata self, float start, float step, int noSteps){ } /*----------------------------------------------------------------------*/ int setTimeBin(pHMdata self, int index, float value){ + if(self->timeslave != NULL){ + return 0; + } + if(index >= 0 && index < MAXCHAN){ self->timeBinning[index] = value; } else { @@ -157,7 +174,7 @@ int setTimeBin(pHMdata self, int index, float value){ } self->tofMode = 1; if(index > self->nTimeChan){ - self->nTimeChan = index; + self->nTimeChan = index+1; return resizeBuffer(self); } return 1; @@ -168,17 +185,27 @@ int isInTOFMode(pHMdata self){ } /*---------------------------------------------------------------------*/ int getNoOfTimebins(pHMdata self){ - return self->nTimeChan; + if(self->timeslave != NULL){ + return getNoOfTimebins(self->timeslave); + } else { + return self->nTimeChan; + } } /*---------------------------------------------------------------------*/ float *getTimeBinning(pHMdata self){ - return self->timeBinning; + if(self->timeslave != NULL){ + return getTimeBinning(self->timeslave); + } else { + return self->timeBinning; + } } /*-------------------------------------------------------------------*/ void clearTimeBinning(pHMdata self){ - self->nTimeChan = 1; - self->tofMode = 0; - resizeBuffer(self); + if(self->timeslave == NULL){ + self->nTimeChan = 1; + self->tofMode = 0; + resizeBuffer(self); + } } /*--------------------------------------------------------------------*/ void getHMDataDim(pHMdata self, int iDim[MAXDIM], int *rank){ @@ -193,7 +220,7 @@ long getHMDataLength(pHMdata self){ length *= self->iDim[i]; } if(self->tofMode){ - length *= self->nTimeChan; + length *= getNoOfTimebins(self); } return length; } @@ -227,6 +254,10 @@ static int updateHMbuffer(pHistMem hist, int bank, SConnection *pCon){ assert(self); + if(self->timeslave != NULL){ + resizeBuffer(self); + } + for(i = 0; i < 3; i++){ status = hist->pDriv->GetHistogram(hist->pDriv,pCon, bank,0,getHMDataLength(self), @@ -292,7 +323,7 @@ HistInt *getHMDataBufferPointer(pHistMem hist,SConnection *pCon){ assert(self); - if(self->localBuffer == NULL){ + if(self->localBuffer == NULL || self->timeslave != NULL){ resizeBuffer(self); } /* diff --git a/hmdata.h b/hmdata.h index c7f9f097..28bfedb4 100644 --- a/hmdata.h +++ b/hmdata.h @@ -16,7 +16,7 @@ #define MAXDIM 3 - typedef struct { + typedef struct __hmdata{ int rank; int iDim[MAXDIM]; int nTimeChan; @@ -26,6 +26,7 @@ int updateIntervall; int updateFlag; HistInt *localBuffer; + struct __hmdata *timeslave; } HMdata, *pHMdata; diff --git a/hmdata.w b/hmdata.w index bdce46fe..8d818e0d 100644 --- a/hmdata.w +++ b/hmdata.w @@ -11,7 +11,7 @@ display clients gone mad. This task is also handled through this class. In order to do this, the following data structure is needed: @d hmdatadat @{ - typedef struct { + typedef struct __hmdata{ int rank; int iDim[MAXDIM]; int nTimeChan; @@ -21,6 +21,7 @@ In order to do this, the following data structure is needed: int updateIntervall; int updateFlag; HistInt *localBuffer; + struct __hmdata *timeslave; } HMdata, *pHMdata; @} diff --git a/make_gen b/make_gen index 5bcbf35a..7840ac06 100644 --- a/make_gen +++ b/make_gen @@ -30,7 +30,8 @@ SOBJ = network.o ifile.o conman.o SCinter.o splitter.o passwd.o \ s_rnge.o sig_die.o gpibcontroller.o $(NIOBJ) mcreader.o mccontrol.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 + sinfox.o sicslist.o cone.o hipadaba.o sicshipadaba.o statistics.o \ + moregress.o MOTOROBJ = motor.o simdriv.o COUNTEROBJ = countdriv.o simcter.o counter.o diff --git a/modriv.h b/modriv.h index 536243bd..2b7cd1b9 100644 --- a/modriv.h +++ b/modriv.h @@ -73,5 +73,6 @@ /* ----------------------- Simulation -----------------------------------*/ MotorDriver *CreateSIM(SConnection *pCon, int argc, char *argv[]); void KillSIM(void *pData); + MotorDriver *RGMakeMotorDriver(void); #endif diff --git a/moregress.c b/moregress.c new file mode 100644 index 00000000..de86e59b --- /dev/null +++ b/moregress.c @@ -0,0 +1,258 @@ +/** + * This is a regression testing motor driver for SICS. + * A parameter can be set which makes this driver cause + * various error conditions. This can then be used to + * verify and debug the working of upper level code + * + * copyright: see file COPYRIGHT + * + * Mark Koennecke, July 2007 + */ +#include +#include +#include + +/*===================== supported errors ======================*/ +#define NONE 0 +#define STARTFAIL 1 +#define BADPOS 2 /* positioning problem */ +#define FAIL 3 /* failure */ +#define OFFPOS 4 /* off pos by .2 */ +#define READFAIL 5 +#define RUN 6 /* keep running; for interrupt testing */ +/*=============================================================*/ +typedef struct __RGMoDriv{ + /* general motor driver interface + fields. REQUIRED! + */ + float fUpper; /* upper limit */ + float fLower; /* lower limit */ + char *name; + int (*GetPosition)(void *self, float *fPos); + int (*RunTo)(void *self,float fNewVal); + int (*GetStatus)(void *self); + void (*GetError)(void *self, int *iCode, char *buffer, int iBufLen); + int (*TryAndFixIt)(void *self, int iError,float fNew); + int (*Halt)(void *self); + int (*GetDriverPar)(void *self, char *name, + float *value); + int (*SetDriverPar)(void *self,SConnection *pCon, + char *name, float newValue); + void (*ListDriverPar)(void *self, char *motorName, + SConnection *pCon); + void (*KillPrivate)(void *self); + /* your drivers private fields follow below */ + float target; + int errorType; + int recover; + int counter; + } RGMotorDriver; + +/*================================================================ + GetPos returns OKOK on success, HWFault on failure +------------------------------------------------------------------*/ +static int RGGetPos(void *data, float *fPos){ + RGMotorDriver *self = NULL; + + self = (RGMotorDriver *)data; + if(self->errorType == READFAIL){ + return HWFault; + } + if(self->errorType > 1 && self->errorType < 6){ + *fPos = self->target - .2; + } else { + *fPos = self->target; + } + return OKOK; +} +/*---------------------------------------------------------------- + RunTo starts the motor running. Returns OKOK on success, HWfault + on Errors +------------------------------------------------------------------*/ +static int RGRunTo(void *data, float newValue){ + RGMotorDriver *self = NULL; + + self = (RGMotorDriver *)data; + self->target = newValue; + if(self->errorType == STARTFAIL){ + return HWFault; + } + return OKOK; +} +/*----------------------------------------------------------------- + CheckStatus queries the sattus of a running motor. Possible return + values can be: + HWBusy : motor still running + HWFault : motor error detected + HWPosFault : motor finished, but position not reached + HWIdle : motor finished OK + HWWarn : motor issued warning +--------------------------------------------------------------------*/ +static int RGCheckStatus(void *data){ + RGMotorDriver *self = NULL; + + self = (RGMotorDriver *)data; + switch(self->errorType){ + case BADPOS: + return HWPosFault; + break; + case FAIL: + return HWFault; + break; + case RUN: + return HWBusy; + break; + } + return HWIdle; +} +/*------------------------------------------------------------------ + GetError gets more information about error which occurred + *iCode is an integer error code to be used in TryFixIt as indicator + buffer is a buffer for a text description of the problem + iBufLen is the length of buffer +--------------------------------------------------------------------*/ +static void RGGetError(void *data, int *iCode, char *buffer, + int iBufLen){ + RGMotorDriver *self = NULL; + + self = (RGMotorDriver *)data; + *iCode = self->errorType; + switch(self->errorType){ + case NONE: + strncpy(buffer,"No error found",iBufLen); + break; + case BADPOS: + strncpy(buffer,"Position not reached",iBufLen); + break; + case FAIL: + strncpy(buffer,"Hardware is mad",iBufLen); + break; + case STARTFAIL: + strncpy(buffer,"Failed to start motor",iBufLen); + break; + case READFAIL: + strncpy(buffer,"Failed to read motor",iBufLen); + break; + + } +} +/*------------------------------------------------------------------ + TryAndFixIt tries everything which is possible in software to fix + a problem. iError is the error code from GetError, newValue is + the target value for the motor + Possible retrun values are: + MOTOK : everything fixed + MOTREDO : try again + MOTFAIL : cannot fix this +--------------------------------------------------------------------*/ +static int RGFixIt(void *data, int iError, float newValue){ + RGMotorDriver *self = NULL; + + self = (RGMotorDriver *)data; + if(self->recover == 1){ + self->errorType = NONE; + return MOTREDO; + } + return MOTFAIL; +} +/*------------------------------------------------------------------- + Halt tries to stop the motor. Halt errors are ignored +---------------------------------------------------------------------*/ +static int RGHalt(void *data){ + RGMotorDriver *self = NULL; + + self = (RGMotorDriver *)data; + self->errorType = NONE; + return 1; +} +/*-------------------------------------------------------------------- + GetDriverPar retrieves the value of a driver parameter. + Name is the name of the parameter, fValue the value when found. + Returns 0 on success, 0 else +-----------------------------------------------------------------------*/ +static int RGGetDriverPar(void *data, char *name, float *value){ + RGMotorDriver *self = NULL; + + self = (RGMotorDriver *)data; + if(strcmp(name,"errortype") == 0){ + *value = (float)self->errorType; + return 1; + } else if (strcmp(name,"recover") == 0){ + *value = self->recover; + return 1; + } + + return 0; +} +/*---------------------------------------------------------------------- + SetDriverPar sets a driver parameter. Returns 0 on failure, 1 on + success. Name is the parameter name, pCon the connection to report + errors too, value the new value +------------------------------------------------------------------------*/ +static int RGSetDriverPar(void *data, SConnection *pCon, + char *name, float value){ + RGMotorDriver *self = NULL; + + self = (RGMotorDriver *)data; + if(strcmp(name,"errortype") == 0){ + self->errorType = (int)value; + return 1; + } else if (strcmp(name,"recover") == 0){ + self->recover = (int)value; + return 1; + } + return 0; +} +/*----------------------------------------------------------------------- + ListDriverPar lists the names and values of driver parameters to + pCon. Motorname is the name of the motor ro prefix to the listing. +-------------------------------------------------------------------------*/ +static void RGListDriverPar(void *data, char *motorname, + SConnection *pCon){ + RGMotorDriver *self = NULL; + char buffer[256]; + + self = (RGMotorDriver *)data; + snprintf(buffer,255,"%s errortype = %d", motorname, + self->errorType); + SCWrite(pCon,buffer,eValue); + + snprintf(buffer,255,"%s recover = %d", motorname, + self->recover); + SCWrite(pCon,buffer,eValue); +} +/*----------------------------------------------------------------------- + KillPrivate has the task to delete possibly dynamically allocated + memory in the private part of the driver structure +------------------------------------------------------------------------*/ +static void RGKillPrivate(void *data){ + RGMotorDriver *self = NULL; + + self = (RGMotorDriver *)data; +} +/*=======================================================================*/ +MotorDriver *RGMakeMotorDriver(void) { + RGMotorDriver *pNew = NULL; + + pNew = malloc(sizeof(RGMotorDriver)); + if(pNew == NULL){ + return NULL; + } + memset(pNew,0,sizeof(RGMotorDriver)); + + pNew->GetPosition = RGGetPos; + pNew->RunTo = RGRunTo; + pNew->GetStatus = RGCheckStatus; + pNew->GetError = RGGetError; + pNew->TryAndFixIt = RGFixIt; + pNew->Halt = RGHalt; + pNew->GetDriverPar = RGGetDriverPar; + pNew->SetDriverPar = RGSetDriverPar; + pNew->ListDriverPar = RGListDriverPar; + pNew->KillPrivate = RGKillPrivate; + pNew->fLower = -180.; + pNew->fUpper = 180.; + + return (MotorDriver *)pNew; +} + diff --git a/motor.c b/motor.c index 6a1bc665..2df8bf79 100644 --- a/motor.c +++ b/motor.c @@ -4,48 +4,18 @@ This file implements the SICS motor handling. This is the logical level, the nitty gritty hardware interface is in the driver. - 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. - + This is a totally revamped version which uses the Hipadaba for + data storage. + + copyright: see file COPYRIGHT + + Mark Koennecke, July 2006 -----------------------------------------------------------------------------*/ #include #include #include #include #include -#include "fortify.h" #include "sics.h" #include "devexec.h" #include "motor.h" @@ -54,6 +24,8 @@ #include "servlog.h" #include "tclmotdriv.h" #include "site.h" +#include "sicshipadaba.h" +#include "stptok.h" /*------------------------------------------------------------------------- some lokal defines */ @@ -62,20 +34,7 @@ #define INTSCAN 1. #define INTBATCH 2. #define INTHALT 3. - -#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 - +#define ABS(x) (x < 0 ? -(x) : (x)) /*------------------------------------------------------------------------ a tiny structure used in CallBack work */ @@ -83,27 +42,21 @@ 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); @@ -121,11 +74,9 @@ 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; @@ -134,24 +85,22 @@ 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]; @@ -160,57 +109,27 @@ self= (pMotor)pData; fprintf(fd,"# Motor %s\n",name); - 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); + strncpy(pBueffel,name,511); + strncat(pBueffel," ",511); + SaveSICSHipadaba(fd,self->pDescriptor->parNode,pBueffel); return 1; - } +} /*-------------------------------------------------------------------------*/ - static float absf(float f) - { - if(f < 0.) - { - return -f; - } - else - { - return f; - } - } -/*-------------------------------------------------------------------------*/ - static void MotorInterrupt(SConnection *pCon, int iVal) - { - if(SCGetInterrupt(pCon) < iVal) - { +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 >= ObVal(self->ParArray,POSCOUNT)) + if(self->retryCount >= (int)posCount) { snprintf(pBueffel,255,"ERROR: aborting motor %s after %d retries", self->name, self->retryCount); @@ -230,26 +149,26 @@ static int statusRunTo(pMotor self, SConnection *pCon) /*--------------------------------------------------------------------*/ static int checkPosition(pMotor self, SConnection *pCon) { - float fHard; + float fHard, precision; char pBueffel[132]; int status; + assert(SICSHdbGetFloat(self->pDescriptor->parNode,pCon, + "precision",&precision) == 1); + MotorGetHardPosition(self,pCon,&fHard); self->fPosition = fHard; - if(absf(fHard - self->fTarget) > ObVal(self->ParArray,PREC)) - { - if (SCGetInterrupt(pCon) != eContinue) - { + if(ABS(fHard - self->fTarget) > precision){ + 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, absf(fHard - self->fTarget)); + self->name, ABS(fHard - self->fTarget)); SCWrite(pCon,pBueffel, eWarning); status = statusRunTo(self,pCon); return status; @@ -257,24 +176,23 @@ 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); @@ -300,25 +218,25 @@ static int reportAndFixError(pMotor self, SConnection *pCon) } return newStatus; } -/*--------------------------------------------------------------------- - New version, refactored October 2003 - -----------------------------------------------------------------------*/ -static int evaluateStatus(pMotor self, SConnection *pCon) -{ +/*---------------------------------------------------------------------*/ +static int evaluateStatus(pMotor self, SConnection *pCon){ int iRet, iCode, newStatus; MotCallback sCall; char pBueffel[256], pError[132]; - float fHard; + float fHard, ignorefault, interrupt; + + assert(SICSHdbGetFloat(self->pDescriptor->parNode,pCon, + "ignorefault",&ignorefault) == 1); + assert(SICSHdbGetFloat(self->pDescriptor->parNode,pCon, + "interruptmode",&interrupt) == 1); 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; @@ -327,16 +245,13 @@ static int evaluateStatus(pMotor self, SConnection *pCon) break; case HWPosFault: newStatus = reportAndFixError(self,pCon); - if(newStatus == HWFault && ObVal(self->ParArray,IGNOREFAULT) < 1) - { + if(newStatus == HWFault && 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; @@ -355,30 +270,32 @@ static int evaluateStatus(pMotor self, SConnection *pCon) eWarning); break; } - if(newStatus == HWFault) - { - MotorInterrupt(pCon,ObVal(self->ParArray,INT)); + if(newStatus == HWFault){ + MotorInterrupt(pCon,(int)interrupt); 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 >= ObVal(self->ParArray,MOVECOUNT)) - { + if(self->posCount >= (int)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; @@ -392,16 +309,218 @@ static void handleMoveCallback(pMotor self, SConnection *pCon) SCWrite(pCon, "", eEvent); self->pDrivInt->drivableStatus=status; } - if(status == HWBusy) - { + if(status == HWBusy){ handleMoveCallback(self,pCon); } return status; - } +} /*---------------------------------------------------------------------------*/ - pMotor MotorInit(char *drivername, char *name, MotorDriver *pDriv) - { +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 pM = NULL; + pHdb node = NULL, child = NULL; assert(drivername); assert(pDriv); @@ -409,58 +528,100 @@ static void handleMoveCallback(pMotor self, SConnection *pCon) /* 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) - { - ObParDelete(pM->ParArray); + if(!pM->pDescriptor){ 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; } @@ -472,8 +633,7 @@ static void handleMoveCallback(pMotor self, SConnection *pCon) /* initialise callback interface */ pM->pCall = CreateCallBackInterface(); - if(!pM->pCall) - { + if(!pM->pCall){ MotorKill(pM); return NULL; } @@ -485,8 +645,7 @@ static void handleMoveCallback(pMotor self, SConnection *pCon) extern void KillPiPiezo(void *pData); - void MotorKill(void *self) - { +void MotorKill(void *self){ pMotor pM; assert(self); @@ -497,165 +656,51 @@ extern void KillPiPiezo(void *pData); 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->pDriver->name != NULL) - { - free(pM->pDriver->name); - } - free(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); 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) - { - 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 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) - { - 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); - +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; - } - - 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; - } + } else { + return 0; + } +} /*--------------------------------------------------------------------------- MotorCheckBoundary checks for violation of boundary conditions and transforms from SoftCoordinates to hard coordinates. @@ -665,53 +710,59 @@ extern void KillPiPiezo(void *pData); char *pError, int iErrLen) { float fHard; - float fZero; + float fZero, fixed, lowerlim, upperlim, sign; 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(ObVal(self->ParArray,FIX) >= 0) - { + if(fixed >= 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 > ObVal(self->ParArray,SUPP)) - { + if(fVal > upperlim){ sprintf(pBueffel,"%f violates upper software limit %f on %s", - fVal, ObVal(self->ParArray,SUPP),self->name); + fVal, upperlim,self->name); strncpy(pError,pBueffel,iErrLen); return 0; } - if(fVal < ObVal(self->ParArray,SLOW)) - { + if(fVal < lowerlim){ sprintf(pBueffel,"%f violates lower software limit %f on %s", - fVal,ObVal(self->ParArray,SLOW),self->name ); + fVal,lowerlim,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*ObVal(self->ParArray,SIGN); + fHard = fHard*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); @@ -720,11 +771,10 @@ extern void KillPiPiezo(void *pData); *fNew = fHard; return 1; - } +} /*---------------------------------------------------------------------------*/ - long MotorRun(void *sulf, SConnection *pCon, float fNew) - { - float fHard; +long MotorRun(void *sulf, SConnection *pCon, float fNew){ + float fHard, rights, ignore, maxerr, interrupt; int i, iRet, iCode; char pBueffel[512]; char pError[132]; @@ -736,9 +786,18 @@ extern void KillPiPiezo(void *pData); 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)ObVal(self->ParArray,USRIGHTS))) - { + if(!SCMatchRights(pCon,(int)rights)){ sprintf(pBueffel,"ERROR: You are not authorised to move motor %s", self->name); SCWrite(pCon,pBueffel,eError); @@ -748,16 +807,14 @@ extern void KillPiPiezo(void *pData); /* check boundaries first */ iRet = MotorCheckBoundary(self,fNew,&fHard,pBueffel,511); - if(!iRet) - { + if(!iRet){ SCWrite(pCon,pBueffel,eStatus); SCSetInterrupt(pCon,eAbortOperation); return 0; } /* check if the bad motor flag is set */ - if((int)ObVal(self->ParArray,IGNOREFAULT) > 0) - { + if((int)ignore > 0){ snprintf(pBueffel,511,"WARNING: motor %s is unreliable", self->name); SCWrite(pCon,pBueffel,eWarning); @@ -765,9 +822,7 @@ extern void KillPiPiezo(void *pData); } /* check our error count and interrupt if to much */ - iCode = (int)ObVal(self->ParArray,ECOUNT); - if(self->pDrivInt->iErrorCount > iCode) - { + if(self->pDrivInt->iErrorCount > (int)maxerr){ /* big alarm */ ServerWriteGlobal("ERROR: !!! MOTOR ALARM !!! MOTOR ALARM !!!",eError); sprintf(pBueffel, @@ -786,25 +841,22 @@ extern void KillPiPiezo(void *pData); 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)ObVal(self->ParArray,INT)); + SCSetInterrupt(pCon,(int)interrupt); return HWFault; case MOTREDO: iRet = self->pDriver->RunTo(self->pDriver,fHard); - if(iRet == OKOK) - { + if(iRet == OKOK){ return OKOK; } break; @@ -816,82 +868,82 @@ extern void KillPiPiezo(void *pData); /* tried three times, refuses to work */ SCWrite(pCon,pError,eError); SCWrite(pCon,"\n",eError); - SCSetInterrupt(pCon,(int)ObVal(self->ParArray,INT)); + SCSetInterrupt(pCon,(int)interrupt); 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; + float fVal, interrupt, sign; 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) /* all went well, the exception */ - { + if(iRet == OKOK) { *fHard = fVal; return 1; - } - else /* a problem, the usual case: try fix the problem */ - { /* no point in trying this three times */ + } else { + /* 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)ObVal(self->ParArray,INT)); + SCSetInterrupt(pCon,(int)interrupt); *fHard = fVal; return 0; case MOTOK: case MOTREDO: iRet = self->pDriver->GetPosition(self->pDriver,&fVal); - if(iRet) - { - *fHard = fVal*ObVal(self->ParArray,SIGN); + if(iRet){ + *fHard = fVal*sign; return 1; - } - else - { + } else{ sprintf(pBueffel,"ERROR: cannot fix motor %s", self->name); - SCSetInterrupt(pCon,(int)ObVal(self->ParArray,INT)); + SCSetInterrupt(pCon,(int)interrupt); SCWrite(pCon,pBueffel,eError); *fHard = fVal; return 0; } } } - *fHard = fVal*ObVal(self->ParArray,SIGN); + *fHard = fVal*sign; return 0; } /*------------------------------------------------------------------------*/ - float MotorHardToSoftPosition(pMotor self, float fValue) - { +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); + /* apply zeropoint */ - if(ObVal(self->ParArray,SIGN) < 0.) - { - fValue += ObVal(self->ParArray,SZERO); - } - else - { - fValue -= ObVal(self->ParArray,SZERO); + if(sign < 0.){ + fValue += zero; + }else { + fValue -= zero; } /* apply sign */ - return fValue*ObVal(self->ParArray,SIGN); + return fValue*sign; } /* ------------------------------------------------------------------------*/ - int MotorGetSoftPosition(pMotor self, SConnection *pCon, float *fVal) - { +int MotorGetSoftPosition(pMotor self, SConnection *pCon, float *fVal){ int iRet; float fValue; @@ -900,33 +952,16 @@ extern void KillPiPiezo(void *pData); /* get the hard position */ iRet = MotorGetHardPosition(self,pCon,&fValue); - if(!iRet) - { + if(!iRet){ *fVal = fValue; return 0; } - /* 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); - + *fVal = MotorHardToSoftPosition(self,fValue); return 1; } /*---------------------------------------------------------------------------*/ - int MotorCheckPosition(void *sulf, SConnection *pCon) - { - float fHard; +int MotorCheckPosition(void *sulf, SConnection *pCon){ + float fHard, precision; int i, iRet, iCode; char pBueffel[512]; pMotor self; @@ -934,29 +969,26 @@ extern void KillPiPiezo(void *pData); 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) - { - if(absf(fHard - self->fTarget) < ObVal(self->ParArray,PREC)) - { - self->fPosition = fHard; + if(iRet) { + self->fPosition = fHard; + if(ABS(fHard - self->fTarget) < precision){ return 1; - } - else - { + } else { /* Oooopppsss error */ return 0; } - } - else /* error getting hold of position, MotorGetHard already tried to - solve the problem and FAILED, the fucking bastard - even messaged the connection accordingly */ - { + } else { + /* error getting hold of position, MotorGetHard already tried to + solve the problem and FAILED, client already knows...*/ return -1; } - } +} /* -------------------------------------------------------------------------- The Factory function for creating a motor. Usage: MotorCreate name DriverName. @@ -1024,7 +1056,22 @@ extern MotorDriver *MakePiPiezo(Tcl_Interp *pTcl, char *pArray); SCWrite(pCon,pBueffel,eError); return 0; } - } + } else if(strcmp(argv[2],"regress") == 0) + { + pDriver = RGMakeMotorDriver(); + if(!pDriver) + { + return 0; + } + /* create the motor */ + pNew = MotorInit("regress",argv[1],pDriver); + if(!pNew) + { + sprintf(pBueffel,"Failure to create motor %s",argv[1]); + SCWrite(pCon,pBueffel,eError); + return 0; + } + } else { site = getSite(); @@ -1054,45 +1101,24 @@ extern MotorDriver *MakePiPiezo(Tcl_Interp *pTcl, char *pArray); /* ----------------- some private functions used in MotorAction -------------*/ void MotorListLL(pMotor self, SConnection *pCon) { - char pBueffel[512]; - int i, iLen; + char pBueffel[256]; - iLen = ObParLength(self->ParArray); - sprintf(pBueffel,"Parameter Listing for motor %s",self->name); + snprintf(pBueffel,255,"Parameter Listing for motor %s",self->name); SCWrite(pCon,pBueffel,eValue); - 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); - } + snprintf(pBueffel,255,"%s ",self->name); + PrintSICSParList(self->pDescriptor->parNode,pCon,pBueffel); } /*--------------------------------------------------------------------------*/ void MotorReset(pMotor pM) { - 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); + 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.); } /*------------------------------------------------------------------------*/ typedef struct { @@ -1303,81 +1329,17 @@ extern MotorDriver *MakePiPiezo(Tcl_Interp *pTcl, char *pArray); } else /* one of the parameter commands or error left now */ { - 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); + 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 - { - 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); + } else if(iRet < -1) { 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 67d61d74..7c0ec1f4 100644 --- a/motor.h +++ b/motor.h @@ -16,7 +16,6 @@ typedef struct __Motor { pObjectDescriptor pDescriptor; - ObPar *ParArray; pIDrivable pDrivInt; pICallBack pCall; char *drivername; diff --git a/nxscript.c b/nxscript.c index 06146906..6a2869e3 100644 --- a/nxscript.c +++ b/nxscript.c @@ -373,6 +373,31 @@ static void putSicsData(SConnection *pCon, SicsInterp *pSics, } } /*----------------------------------------------------------------------*/ +static void putAttribute(SConnection *pCon, SicsInterp *pSics, + pNXScript self, int argc, char *argv[]){ + int status, type = NX_CHAR; + char buffer[256]; + + if(argc < 5){ + SCWrite(pCon,"ERROR: insufficient number of arguments to putAttribute", + eError); + return; + } + + status = NXDopenalias(self->fileHandle,self->dictHandle,argv[2]); + if(status != NX_OK){ + sprintf(buffer,"ERROR: failed to open alias %s", argv[2]); + SCWrite(pCon,buffer,eError); + return; + } + status = NXputattr(self->fileHandle,argv[3],(void *)argv[4], + strlen(argv[4])+1, type); + if(status != NX_OK){ + sprintf(buffer,"ERROR: failed to write attribute %s", argv[3]); + SCWrite(pCon,buffer,eError); + } +} +/*----------------------------------------------------------------------*/ static void updateHMDim(NXScript *self, pHistMem mem){ int iDim[MAXDIM]; int i, rank, timeLength, status; @@ -412,7 +437,7 @@ static void putHistogramMemory(SConnection *pCon, SicsInterp *pSics, pNXScript self, int argc, char *argv[]){ pHistMem mem = NULL; - int status, start, length, i, subset = 0; + int status, start, length, i, subset = 0, bank = 0; HistInt *iData = NULL; char buffer[256]; @@ -460,6 +485,19 @@ static void putHistogramMemory(SConnection *pCon, SicsInterp *pSics, return; } } + + /* + * check for additional bank number + */ + if(argc > 6){ + status = Tcl_GetInt(InterpGetTcl(pSics),argv[6],&bank); + if(status != TCL_OK){ + sprintf(buffer,"ERROR: failed to convert %s to integer", + argv[6]); + SCWrite(pCon,buffer,eError); + return; + } + } /* read HM @@ -472,7 +510,7 @@ static void putHistogramMemory(SConnection *pCon, SicsInterp *pSics, return; } memset(iData,0,length*sizeof(HistInt)); - status = GetHistogramDirect(mem,pCon,0,start,start+length,iData, + status = GetHistogramDirect(mem,pCon,bank,start,start+length,iData, length*sizeof(HistInt)); }else{ /* @@ -980,6 +1018,9 @@ static int handlePut(SConnection *pCon, SicsInterp *pSics, pNXScript self, }else if(strcmp(argv[1],"putsicsdata") == 0){ /*===============*/ putSicsData(pCon,pSics,self,argc,argv); + }else if(strcmp(argv[1],"putattribute") == 0){ + /*===============*/ + putAttribute(pCon,pSics,self,argc,argv); } else { SCWrite(pCon,"ERROR: put command not recognised",eError); } diff --git a/nxutil.c b/nxutil.c index 6ad7596f..82a4edc4 100644 --- a/nxutil.c +++ b/nxutil.c @@ -28,8 +28,9 @@ int iRet; /* Find the motor */ - strtolower(pName); - pMot = FindMotor(pSics,pName); + strncpy(pBueffel,pName,511); + strtolower(pBueffel); + pMot = FindMotor(pSics,pBueffel); if(!pMot) { sprintf(pBueffel,"WARNING: cannot find motor %s",pName); @@ -58,8 +59,9 @@ int iRet; /* Find the motor */ - strtolower(pName); - pMot = FindMotor(pSics,pName); + strncpy(pBueffel,pName,511); + strtolower(pBueffel); + pMot = FindMotor(pSics,pBueffel); if(!pMot) { sprintf(pBueffel,"WARNING: cannot find motor %s",pName); @@ -95,8 +97,9 @@ char *pText = NULL; /* find it */ - strtolower(pName); - pVar = FindVariable(pSics,pName); + strncpy(pBueffel,pName,511); + strtolower(pBueffel); + pVar = FindVariable(pSics,pBueffel); if(!pVar) { sprintf(pBueffel,"WARNING: cannot find variable %s",pName); diff --git a/optimise.c b/optimise.c index 7b507cf7..226f5001 100644 --- a/optimise.c +++ b/optimise.c @@ -519,38 +519,13 @@ static int ClimbDrive(SConnection *pCon,char *name, float value) } return 1; } -/*-------------------------------------------------------------------------*/ - static int ClimbVariable(pOptimise self, SConnection *pCon, int i) - { - pOVarEntry pOvar; - void *pData; - int status, direction = 1; - long oneCount, twoCount, lastCount, currentCount; - float varValue, startValue; - char buffer[256]; - int (*CollectFunc)(pScanData self, int iPoint) = NULL; - - assert(self); - assert( (i >= 0) && (i < self->iVar)); - assert(pCon); - - /* get variable data */ - DynarGet(self->pVariables,i,&pData); - pOvar = (pOVarEntry)pData; - startValue = pOvar->fCenter; - - /* - * prepare scan object - */ - self->pScanner->pCon = pCon; - self->pScanner->pSics = pServ->pSics; - self->pScanner->iNP = 1; - self->pScanner->iMode = self->eCount; - self->pScanner->fPreset = self->fPreset; - - /* - * test for upwards direction - */ +/*------------------------------------------------------------------------*/ +static int findDirection(pOptimise self, pOVarEntry pOvar, SConnection *pCon) +{ + int status, direction; + float varValue; + long oneCount, twoCount; + varValue = pOvar->fCenter + pOvar->fStep; status = ClimbDrive(pCon,pOvar->pName,varValue); if(!status) @@ -584,14 +559,46 @@ static int ClimbDrive(SConnection *pCon,char *name, float value) if(oneCount > twoCount) { direction = 1; - lastCount = oneCount; } else { direction = -1; - lastCount = twoCount; } - + return direction; +} +/*-------------------------------------------------------------------------*/ + static int ClimbVariable(pOptimise self, SConnection *pCon, int i) + { + pOVarEntry pOvar; + void *pData; + int status, direction = 1; + long oneCount, twoCount, lastCount, currentCount; + float varValue, startValue; + char buffer[256]; + int (*CollectFunc)(pScanData self, int iPoint) = NULL; + + assert(self); + assert( (i >= 0) && (i < self->iVar)); + assert(pCon); + + /* get variable data */ + DynarGet(self->pVariables,i,&pData); + pOvar = (pOVarEntry)pData; + startValue = pOvar->fCenter; + + /* + * prepare scan object + */ + self->pScanner->pCon = pCon; + self->pScanner->pSics = pServ->pSics; + self->pScanner->iNP = 1; + self->pScanner->iMode = self->eCount; + self->pScanner->fPreset = self->fPreset; + + direction = findDirection(self,pOvar, pCon); + if(direction < 0){ + return direction; + } /* * drive to the last best position */ @@ -600,7 +607,12 @@ static int ClimbDrive(SConnection *pCon,char *name, float value) if(!status) { return DRIVEERROR; - } + } + lastCount = ClimbCount(self,pCon); + if(lastCount < 0) + { + return SCANERROR; + } currentCount = lastCount; /* diff --git a/scan.c b/scan.c index 4911cef9..89567c4e 100644 --- a/scan.c +++ b/scan.c @@ -1540,7 +1540,7 @@ static int PrintCountsOrMonitors(pScanData self, SConnection *pCon, if(iWhich < 0) { GetScanCounts(self,lData,self->iNP); - snprintf(pBueffel,59,"%s.counts = {", name); + snprintf(pBueffel,59,"%s.Counts = {", name); } else { diff --git a/sicsdata.c b/sicsdata.c index 417415e5..7c972f8d 100644 --- a/sicsdata.c +++ b/sicsdata.c @@ -17,7 +17,7 @@ #include "scan.h" #include "HistMem.h" #include "sicsdata.h" - +#define ABS(x) (x < 0 ? -(x) : (x)) /*--------------------------------------------------------------------*/ static void KillSICSData(void *pData){ pSICSData self = NULL; @@ -236,6 +236,74 @@ static int putFloat(pSICSData self, int argc, char *argv[], SCSendOK(pCon); return 1; } +/*------------------------------------------------------------------*/ +static int getPos(pSICSData self, char *name, + SConnection *pCon, int pos){ + char pBueffel[512]; + float value; + + if(pos >= self->dataUsed){ + SCWrite(pCon,"ERROR: requested position out of range",eError); + return 0; + } + if(self->dataType[pos] == FLOATTYPE){ + memcpy(&value,&self->data[pos],sizeof(float)); + snprintf(pBueffel,511,"%s = %f", name, value); + SCWrite(pCon,pBueffel,eValue); + return 1; + } + if(self->dataType[pos] == INTTYPE){ + snprintf(pBueffel,511,"%s = %d", name, self->data[pos]); + SCWrite(pCon,pBueffel,eValue); + return 1; + } + return 0; +} +/*------------------------------------------------------------------*/ +static float getDataPos(pSICSData self, int pos){ + float value; + + assert(pos < self->dataUsed); + if(self->dataType[pos] == FLOATTYPE){ + memcpy(&value,&self->data[pos],sizeof(float)); + } else { + value = (float)self->data[pos]; + } + return value; +} +/*------------------------------------------------------------------*/ +static int divideSicsData(pSICSData self, SicsInterp *pSics, + SConnection *pCon, char *name){ + int i; + pSICSData other = NULL; + float val, div; + + other = (pSICSData)FindCommandData(pSics,name,"SICSData"); + if(other == NULL){ + SCWrite(pCon,"ERROR: requested SICSData object to divide not found", + eError); + return 0; + } + if(other->dataUsed < self->dataUsed){ + SCWrite(pCon,"ERROR: not enough data in SICSData for division", + eError); + return 0; + } + for(i = 0; i < self->dataUsed; i++){ + div = getDataPos(other,i); + if(ABS(div) > .00001){ + val = getDataPos(self,i)/div; + } else { + val = .0; + } + if(self->dataType[i] == INTTYPE){ + self->data[i] = (int)val; + } else { + memcpy(&self->data[i],&val,sizeof(float)); + } + } + return 1; +} /*-------------------------------------------------------------------*/ static int copyScanCounts(pSICSData self, int argc, char *argv[], SConnection *pCon, SicsInterp *pSics){ @@ -482,6 +550,7 @@ int SICSDataAction(SConnection *pCon, SicsInterp *pSics, void *pData, int argc, char *argv[]){ pSICSData self = NULL; char pBueffel[132]; + int pos; self = (pSICSData)pData; assert(self); @@ -509,6 +578,19 @@ int SICSDataAction(SConnection *pCon, SicsInterp *pSics, void *pData, return 0; } return dumpSICSData(self,argv[2],pCon); + } else if(strcmp(argv[1],"get") == 0){ + if(argc < 3){ + SCWrite(pCon,"ERROR: need a position to read",eError); + return 0; + } + pos = atoi(argv[2]); + return getPos(self,argv[0],pCon,pos); + } else if(strcmp(argv[1],"divideby") == 0){ + if(argc < 3){ + SCWrite(pCon,"ERROR: need a SICSdata to divide by",eError); + return 0; + } + return divideSicsData(self,pSics,pCon,argv[2]); } else if(strcmp(argv[1],"putint") == 0){ /*---------- putint */ return putInt(self,argc-2,&argv[2],pCon, pSics); diff --git a/sicshipadaba.c b/sicshipadaba.c index 564c037e..c5a54ae7 100644 --- a/sicshipadaba.c +++ b/sicshipadaba.c @@ -54,6 +54,7 @@ pHdbCallback MakeCheckPermissionCallback(int priv){ if(testPriv == NULL){ return NULL; } + *testPriv = priv; return MakeHipadabaCallback(SICSCheckPermissionCallback, testPriv,free,-1,-1); } /*-------------------------------------------------------------------------------------*/ @@ -352,6 +353,117 @@ pHdbCallback MakeFloatRangeCallback(double min, double max){ return MakeHipadabaCallback(SICSFloatRangeCallback, range, free,-1,-1); } +/*-------------------------------------------------------------------------*/ +static int MemReadCallback(void *userData, void *callData, pHdb node, + hdbValue v){ + float *value = NULL; + + value = (float *)userData; + if(value != NULL){ + v.dataType = HIPFLOAT; + v.v.doubleValue = (float) *value; + node->value.v.doubleValue = (double)*value; + } + return 1; +} +/*------------------------------------------------------------------------*/ +static int MemGenReadCallback(void *userData, void *callData, pHdb node, + hdbValue v){ + switch(node->value.dataType){ + case HIPINT: + node->value.v.intValue = *(int *)userData; + break; + case HIPFLOAT: + node->value.v.doubleValue = *(double *)userData; + break; + case HIPTEXT: + if(node->value.v.text != NULL){ + free(node->value.v.text); + } + node->value.v.text = strdup((char *)userData); + break; + case HIPINTAR: + memcpy(&node->value.v.intArray,userData, + node->value.arrayLength *sizeof(int)); + break; + case HIPFLOATAR: + memcpy(&node->value.v.floatArray,userData, + node->value.arrayLength *sizeof(double)); + break; + default: + assert(0); + break; + } + return 1; +} +/*-------------------------------------------------------------------------*/ +pHdbCallback MakeMemGenReadCallback(void *address){ + return MakeHipadabaCallback(MemReadCallback, address, + NULL,-1,-1); +} +/*-------------------------------------------------------------------------*/ +pHdbCallback MakeMemReadCallback(float *address){ + return MakeHipadabaCallback(MemReadCallback, address, + NULL,-1,-1); +} +/*-------------------------------------------------------------------------*/ +static int MemSetCallback(void *userData, void *callData, pHdb node, + hdbValue v){ + float *value = NULL; + + value = (float *)userData; + if(value != NULL){ + *value = (float)v.v.doubleValue; + } + UpdateHipadabaPar(node,v,callData); + return 1; +} +/*-------------------------------------------------------------------------*/ +static int MemGenSetCallback(void *userData, void *callData, pHdb node, + hdbValue v){ + const char *pPtr = NULL; + + if(v.dataType != node->value.dataType){ + assert(0); + return 0; + } + + switch(node->value.dataType){ + case HIPINT: + memcpy(userData,&v.v.intValue,sizeof(int)); + break; + case HIPFLOAT: + memcpy(userData,&v.v.doubleValue,sizeof(double)); + break; + case HIPTEXT: + strncpy((char *)userData,(const char *)v.v.text, + node->value.arrayLength); + break; + case HIPINTAR: + memcpy(userData,&v.v.intArray,node->value.arrayLength*sizeof(int)); + break; + case HIPFLOATAR: + memcpy(userData,&v.v.floatArray, + node->value.arrayLength*sizeof(double)); + break; + default: + assert(0); + return 0; + break; + } + UpdateHipadabaPar(node,v,callData); + return 1; +} +/*-------------------------------------------------------------------------*/ +pHdbCallback MakeMemSetCallback(float *address){ + return MakeHipadabaCallback(MemSetCallback, address, + NULL,-1,-1); +} +/*-------------------------------------------------------------------------*/ +pHdbCallback MakeMemGenSetCallback(void *address){ + return MakeHipadabaCallback(MemSetCallback, address, + NULL,-1,-1); +} /*--------------------------------------------------------------------------*/ static void killHdbValue(void *pData){ hdbValue *v = NULL; @@ -384,7 +496,7 @@ static int SICSIntFixedCallback(void *userData, void *callData, pHdb node, return SICSCBBADFIXED; } /*---------------------------------------------------------------------------*/ -pHdbCallback MakeIntFixedCallback(long *data, int length){ +pHdbCallback MakeIntFixedCallback(int *data, int length){ pHdbCallback result = NULL; hdbValue *v = NULL; @@ -394,11 +506,11 @@ pHdbCallback MakeIntFixedCallback(long *data, int length){ } v->dataType = HIPINTAR; v->arrayLength = length; - v->v.intArray = malloc(length*sizeof(long)); + v->v.intArray = malloc(length*sizeof(int)); if(v->v.intArray == NULL){ return NULL; } - memcpy(v->v.intArray,data,length*sizeof(long)); + memcpy(v->v.intArray,data,length*sizeof(int)); return MakeHipadabaCallback(SICSIntFixedCallback, v, killHdbValue,-1,-1); } @@ -462,6 +574,39 @@ pHdb MakeSICSHdbDriv(char *name, int priv, void *sicsObject, int dataType){ return result; } +/*---------------------------------------------------------------------------*/ +pHdb MakeSICSMemPar(char *name, int priv, float *address){ + pHdb result = NULL; + pHdbCallback pHcb = NULL; + + result = MakeHipadabaNode(name,HIPFLOAT,1); + if(result == NULL){ + return NULL; + } + + pHcb = MakeCheckPermissionCallback(priv); + if(pHcb == NULL){ + DeleteHipadabaNode(result); + return NULL; + } + AppendHipadabaCallback(result,HCBSET,pHcb); + + pHcb = MakeMemSetCallback(address); + if(pHcb == NULL){ + DeleteHipadabaNode(result); + return NULL; + } + AppendHipadabaCallback(result,HCBSET,pHcb); + + pHcb = MakeMemReadCallback(address); + if(pHcb == NULL){ + DeleteHipadabaNode(result); + return NULL; + } + AppendHipadabaCallback(result,HCBREAD,pHcb); + + return result; +} /*----------------------------------------------------------------------------*/ pHdb MakeSICSROPar(char *name, hdbValue v){ pHdb result = NULL; @@ -566,6 +711,68 @@ void RemoveSICSPar(pHdb node){ SICSDeleteNodeData(node); } +/*===================== add functions =======================================*/ +int AddSICSHdbPar(pHdb node, char *name, int priv, hdbValue v){ + pHdb child = NULL; + + child = MakeSICSHdbPar(name,priv,v); + if(child == NULL){ + return 0; + } + AddHipadabaChild(node,child); + return 1; +} +/*---------------------------------------------------------------------------*/ +int AddSICSHdbROPar(pHdb node, char *name, hdbValue v){ + pHdb child = NULL; + + child = MakeSICSROPar(name,v); + if(child == NULL){ + return 0; + } + AddHipadabaChild(node,child); + return 1; +} +/*--------------------------------------------------------------------------*/ +int AddSICSHdbMemPar(pHdb node, char *name, int priv, + void *data, int datalength, int type, int length){ + pHdb child = NULL; + pHdbCallback pHcb = NULL; + + if(type == HIPINTVARAR || type == HIPFLOATVARAR){ + assert(0); + return 0; + } + + child = MakeHipadabaNode(name,type,length); + if(child == NULL){ + return 0; + } + + pHcb = MakeCheckPermissionCallback(priv); + if(pHcb == NULL){ + DeleteHipadabaNode(child); + return 0; + } + AppendHipadabaCallback(child,HCBSET,pHcb); + + pHcb = MakeMemGenSetCallback(data); + if(pHcb == NULL){ + DeleteHipadabaNode(child); + return 0; + } + AppendHipadabaCallback(child,HCBSET,pHcb); + + pHcb = MakeMemGenReadCallback(data); + if(pHcb == NULL){ + DeleteHipadabaNode(child); + return 0; + } + AppendHipadabaCallback(child,HCBREAD,pHcb); + AddHipadabaChild(node,child); + + return 1; +} /*==================== access suport functions ==============================*/ int SICSHdbGetFloat(pHdb parent, SConnection *pCon, char *path, float *value){ @@ -620,7 +827,7 @@ int SICSHdbSetFloat(pHdb parent, SConnection *pCon, if(v.dataType == HIPFLOAT){ v.v.doubleValue = (double)value; } else if(v.dataType == HIPINT){ - v.v.intValue = (long)value; + v.v.intValue = (int)value; } else { /* * it is an error to call this for array dada types @@ -668,7 +875,7 @@ int ProcessSICSHdbPar(pHdb root, SConnection *pCon, assert(root != NULL && pCon != NULL); if(argc < 1){ - SCWrite(pCon,"ERROR: nor parameter to treat specified",eError); + SCWrite(pCon,"ERROR: no parameter to treat specified",eError); return -1; } @@ -705,6 +912,10 @@ int ProcessSICSHdbPar(pHdb root, SConnection *pCon, DeleteDynString(parData); status = SetHipadabaPar(parNode,input,pCon); ReleaseHdbValue(&input); + if(status == 1){ + SCSendOK(pCon); + SCparChange(pCon); + } return status; } else { /* @@ -730,6 +941,65 @@ int ProcessSICSHdbPar(pHdb root, SConnection *pCon, return 1; } } +/*--------------------------------------------------------------------------*/ +void PrintSICSParList(pHdb node, SConnection *pCon, char *prefix){ + char childPrefix[1024]; + pHdb child = NULL; + pDynString value = NULL; + hdbValue v; + + child = node->child; + while(child != NULL){ + if(child->value.dataType != HIPNONE){ + GetHipadabaPar(child,&v,pCon); + value = formatValue(child->value); + if(value != NULL){ + SCPrintf(pCon,eValue,"%s%s = %s", prefix, child->name, + GetCharArray(value)); + DeleteDynString(value); + } + } + if(child->child != NULL){ + strncpy(childPrefix,prefix,1024); + strncat(childPrefix,child->name, 1024); + strncat(childPrefix,"/",1024); + PrintSICSParList(child, pCon,prefix); + } + child = child->next; + } +} +/*---------------------------------------------------------------------------*/ +void SaveSICSHipadaba(FILE *fd, pHdb node, char *prefix){ + pHdb currentChild = NULL; + pDynString data = NULL; + hdbValue v; + + currentChild = node->child; + while(currentChild != NULL){ + if(currentChild->value.dataType != HIPNONE && !isSICSHdbRO(currentChild)){ + GetHipadabaPar(currentChild,&v,NULL); + data = formatValue(currentChild->value); + if(data != NULL){ + fprintf(fd,"%s%s %s\n", prefix, currentChild->name, GetCharArray(data)); + DeleteDynString(data); + } + } + if(currentChild->child != NULL){ + /* + * build a new prefix string and recurse + */ + data = CreateDynString(64,64); + if(data != NULL){ + DynStringCopy(data,prefix); + DynStringConcat(data,currentChild->name); + DynStringConcat(data,"/"); + SaveSICSHipadaba(fd,currentChild,GetCharArray(data)); + DeleteDynString(data); + } + } + currentChild = currentChild->next; + } +} /*---------------------------------------------------------------------------*/ int SICSHipadabaTask(void *pData){ pHdbUpdateTask self = NULL; @@ -798,7 +1068,7 @@ pDynString formatValue(hdbValue v){ case HIPNONE: break; case HIPINT: - snprintf(number,30,"%ld", v.v.intValue); + snprintf(number,30,"%d", v.v.intValue); DynStringCopy(result,number); break; case HIPFLOAT: @@ -811,7 +1081,7 @@ pDynString formatValue(hdbValue v){ case HIPINTAR: case HIPINTVARAR: for(i = 0; i < v.arrayLength; i++){ - snprintf(number,30," %ld", v.v.intArray[i]); + snprintf(number,30," %d", v.v.intArray[i]); DynStringConcat(result,number); } break; @@ -861,11 +1131,11 @@ static int adjustDataLength(hdbValue *v, char *data){ if(v->v.intArray != NULL){ free(v->v.intArray); } - v->v.intArray = malloc(count*sizeof(long)); + v->v.intArray = malloc(count*sizeof(int)); if(v->v.intArray == NULL){ return 0; } - memset(v->v.intArray,0,count*sizeof(long)); + memset(v->v.intArray,0,count*sizeof(int)); } if(v->dataType == HIPFLOATVARAR){ if(v->v.floatArray != NULL){ @@ -883,7 +1153,7 @@ static int adjustDataLength(hdbValue *v, char *data){ /*---------------------------------------------------------------------------------*/ int readHdbValue(hdbValue *v, char *data, char *error, int errlen){ int i, status; - long lValue; + int lValue; double dValue; char number[80]; char *pPtr = NULL; @@ -893,7 +1163,7 @@ int readHdbValue(hdbValue *v, char *data, char *error, int errlen){ break; case HIPINT: getNextHdbNumber(data,number); - status = sscanf(number,"%ld", &v->v.intValue); + status = sscanf(number,"%d", &v->v.intValue); if(status != 1){ snprintf(error,errlen,"Failed to convert %s to integer", data); @@ -928,7 +1198,7 @@ int readHdbValue(hdbValue *v, char *data, char *error, int errlen){ i); return 0; } - status = sscanf(number,"%ld", &lValue); + status = sscanf(number,"%d", &lValue); if(status != 1){ snprintf(error,errlen,"Failed to convert %s to integer", data); @@ -1286,6 +1556,90 @@ static int GetHdbNode(SConnection *pCon, SicsInterp *pSics, void *pData, return 1; } +/*--------------------------------------------------------------------------*/ +static int countChildren(pHdb node){ + pHdb current = NULL; + int count = 0; + + current = node->child; + while(current != NULL){ + count++; + current = current->next; + } + return count; +} +/*---------------------------------------------------------------------------*/ +static int HdbNodeInfo(SConnection *pCon, SicsInterp *pSics, void *pData, + int argc, char *argv[]){ + pHdb targetNode = NULL; + char error[512], oriPath[512], info[512]; + int i, status, length; + + if(argc < 2) { + SCWrite(pCon,"ERROR: need path to node to get info",eError); + return 0; + } + + strncpy(oriPath,argv[1], 511); + targetNode = locateSICSNode(pSics,pCon,argv[1]); + if(targetNode == NULL){ + return 0; + } + length = targetNode->value.arrayLength; + if(length == 0){ + length = 1; + } + snprintf(info,511,"%s,%d,%d",hdbTypeToText(targetNode->value.dataType), + countChildren(targetNode), length); + SCWrite(pCon,info,eValue); + + return 1; +} +/*---------------------------------------------------------------------------*/ +static int HdbNodeVal(SConnection *pCon, SicsInterp *pSics, void *pData, + int argc, char *argv[]){ + pHdb targetNode = NULL; + hdbValue newValue; + pDynString parData = NULL; + char error[512]; + int i, status; + + if(argc < 2) { + SCWrite(pCon,"ERROR: need path to node to print",eError); + return 0; + } + + targetNode = locateSICSNode(pSics,pCon,argv[1]); + if(targetNode == NULL){ + return 0; + } + memset(&newValue,0,sizeof(hdbValue)); + GetHipadabaPar(targetNode, &newValue, pCon); + parData = formatValue(newValue); + if(parData == NULL){ + SCWrite(pCon,"ERROR: out of memory formatting data",eError); + return 0; + } + SCWrite(pCon,GetCharArray(parData),eValue); + DeleteDynString(parData); + ReleaseHdbValue(&newValue); + + return 1; +} + +/*---------------------------------------------------------------------------*/ +int isSICSHdbRO(pHdb node){ + pHdbCallback current = NULL; + + current = node->writeCallbacks; + while(current != NULL){ + if(current->userCallback == SICSReadOnlyCallback) { + return 1; + } + current = current->next; + } + return 0; +} /*---------------------------------------------------------------------------*/ static pDynString formatPlainList(pHdb node){ pHdb current; @@ -1317,30 +1671,20 @@ static pDynString formatListWithVal(pHdb node){ current = node->child; while(current != NULL){ - DynStringConcat(result,current->name); - data = formatValue(current->value); - if(data != NULL){ - DynStringConcat(result," = "); - DynStringConcat(result,GetCharArray(data)); - DeleteDynString(data); + if(current->value.dataType != HIPNONE){ + DynStringConcat(result,current->name); + data = formatValue(current->value); + if(data != NULL){ + DynStringConcat(result," = "); + DynStringConcat(result,GetCharArray(data)); + DeleteDynString(data); + } + DynStringConcat(result,"\n"); } - DynStringConcat(result,"\n"); current = current->next; } return result; } -/*--------------------------------------------------------------------------*/ -static int countChildren(pHdb node){ - pHdb current = NULL; - int count = 0; - - current = node->child; - while(current != NULL){ - count++; - current = current->next; - } - return count; -} /*---------------------------------------------------------------------------*/ static pDynString formatClientList(pHdb node){ pHdb current; @@ -1375,7 +1719,7 @@ static pDynString formatClientList(pHdb node){ case HIPNONE: break; case HIPINT: - snprintf(number,50,"%ld",current->value.v.intValue); + snprintf(number,50,"%d",current->value.v.intValue); DynStringConcat(result,number); break; case HIPFLOAT: @@ -1388,7 +1732,7 @@ static pDynString formatClientList(pHdb node){ case HIPINTAR: case HIPINTVARAR: for(i = 0; i < length; i++){ - snprintf(number,50,"%ld",current->value.v.intArray[i]); + snprintf(number,50,"%d",current->value.v.intArray[i]); DynStringConcat(result,number); if(i > length -1){ DynStringConcat(result,","); @@ -1495,6 +1839,66 @@ static int RemoveHdbCallback(SConnection *pCon, SicsInterp *pSics, void *pData, return 1; } /*---------------------------------------------------------------------------*/ +static int LinkHdbNode(SConnection *pCon, SicsInterp *pSics, void *pData, + int argc, char *argv[]){ + pHdb node = NULL; + char buffer[256]; + CommandList *pCom = NULL; + pDummy pDum = NULL; + + + if(argc < 3) { + SCWrite(pCon,"ERROR: need path and object name to link", + eError); + return 0; + } + if(!SCMatchRights(pCon,usMugger)){ + return 0; + } + + node = GetHipadabaNode(root,argv[1]); + if(node == NULL){ + snprintf(buffer,255,"ERROR: path %s NOT found!", argv[1]); + SCWrite(pCon,buffer,eError); + return 0; + } + + pCom = FindCommand(pSics,argv[2]); + if(pCom == NULL){ + snprintf(buffer,255,"ERROR: failed to find object %s", argv[2]); + SCWrite(pCon,buffer,eError); + return 0; + } + pDum = pCom->pData; + if(pDum == NULL || pDum->pDescriptor->parNode == NULL){ + snprintf(buffer,255, + "ERROR: Object %s does not use Hipadaba natively and thus cannot be linked", + argv[2]); + SCWrite(pCon,buffer,eError); + return 0; + } + + if(pDum->pDescriptor->parNode->mama != NULL){ + snprintf(buffer,255, + "ERROR: Object %s is already linked somewhere else", + argv[2]); + SCWrite(pCon,buffer,eError); + return 0; + } + + AddHipadabaChild(node,pDum->pDescriptor->parNode); + + if(argc > 3){ + if(pDum->pDescriptor->parNode->name != NULL){ + free(pDum->pDescriptor->parNode->name); + } + pDum->pDescriptor->parNode->name = strdup(argv[3]); + } + + SCSendOK(pCon); + return 1; +} +/*---------------------------------------------------------------------------*/ void killSICSHipadaba(){ if(root != NULL){ DeleteHipadabaNode(root); @@ -1535,6 +1939,9 @@ int InstallSICSHipadaba(SConnection *pCon, SicsInterp *pSics, void *pData, AddCommand(pSics,"hlist", ListHdbNode, NULL, NULL); AddCommand(pSics,"hnotify", AutoNotifyHdbNode, NULL, NULL); AddCommand(pSics,"hdelcb", RemoveHdbCallback, NULL, NULL); + AddCommand(pSics,"hlink", LinkHdbNode, NULL, NULL); + AddCommand(pSics,"hinfo", HdbNodeInfo, NULL, NULL); + AddCommand(pSics,"hval", HdbNodeVal, NULL, NULL); return 1; } diff --git a/sicshipadaba.h b/sicshipadaba.h index 83f0bf5f..9c172e71 100644 --- a/sicshipadaba.h +++ b/sicshipadaba.h @@ -81,7 +81,7 @@ pHdbCallback MakeIntRangeCallback(int min, int max); * @return a suitably configured callback or NULL * when out of memory */ -pHdbCallback MakeIntFixedCallback(long *data, int length); +pHdbCallback MakeIntFixedCallback(int *data, int length); /** * make a callback for checking if a parameter is within a given * range of floats @@ -91,6 +91,22 @@ pHdbCallback MakeIntFixedCallback(long *data, int length); * when out of memory */ pHdbCallback MakeFloatRangeCallback(double min, double max); +/** + * make a callback which reads a memory address (perhaps in a + * data structure) which is a float value + * @param address The address of the parameter + * @return a suitable callback for reading this parameter. + */ +pHdbCallback MakeMemReadCallback(float *address); +/** + * make a callback which sets a memory address (perhaps in a + * data structure) which is a float value. It is assumed that + * this is a direct parameter, i.e, UpdateHipadabaPar is + * automatically called. + * @param address The address of the parameter + * @return a suitable callback for setting this parameter. + */ +pHdbCallback MakeMemSetCallback(float *address); /*======================== parameter creation ===================================*/ /** * make a simple SICS hdb parameter. Setting it will call update immediately. Use @@ -111,8 +127,15 @@ pHdb MakeSICSHdbPar(char *name, int priv, hdbValue v); * @param dataType The datatype of this variable * @return A new suitably configured Hdb parameter or NULL when out of memory. */ - pHdb MakeSICSHdbDriv(char *name, int priv,void *sicsObject, int datatype); +/** + * make SICS hdb variable which is connected to a memory location, perhaps in + * an objects data structure. + * @param name The name of the variable + * @param priv The privilege required to set this parameter + * @param address A pointer to the memory location of the variable. + */ +pHdb MakeSICSMemPar(char *name, int priv, float *address); /** * makes a SICS Hdb read only parameter. Setting such a parameter causes an error. * @param name The name of the parameter @@ -137,6 +160,38 @@ pHdb MakeSICSScriptPar(char *name, char *setScript, char *readScript, hdbValue v * @param node The node to delete */ void RemoveSICSPar(pHdb node); +/*=============== Add par functions =======================================*/ +/** + * add a new simple hdb parameter as child to node + * @param node The node to add the new node too. + * @param priv The privilege required to change that parameter + * @param v The initial value and datatype of this parameter + * @return 1 on success, 0 else + */ +int AddSICSHdbPar(pHdb node, char *name, int priv, hdbValue v); +/** + * add a new read only hdb parameter as child to node + * @param node The node to add the new node too. + * @param v The initial value and datatype of this parameter + * @return 1 on success, 0 else + */ +int AddSICSHdbROPar(pHdb node, char *name, hdbValue v); +/** + * Add a new hdb parameter as child to node. Updates are synced + * to the memory location data. This works for simple variables, fixed size + * arrays and fixed sized strings. This does not work for dynamically sized + * arrays or strings. + * @param node The node to add the new node too. + * @param priv The privilege required to change that parameter + * @param data The pointer to map this parameter too. This must be in + * dynamically allocated memory. + * @param datalength The length of the data area pointed to by data. + * @param type The data type of the parameter + * @param length The length of the type. Used for array types. + * @return 1 on success, 0 else + */ +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 @@ -160,6 +215,12 @@ int SICSHdbGetFloat(pHdb parent, SConnection *pCon, */ int SICSHdbSetFloat(pHdb parent, SConnection *pCon, char *path, float value); +/** + * query function if a parameter is read only. + * @param node The ndoe to query + * @return 1 when RO, 0 else + */ +int isSICSHdbRO(pHdb node); /*============= common SICS Interactions ===================================*/ /** * Install a SICS automatic notification callback on the node. This is @@ -187,6 +248,23 @@ int InstallSICSNotify(pHdb node, SConnection *pCon, int id, int recurse); */ int ProcessSICSHdbPar(pHdb root, SConnection *pCon, char *printPrefix, int argc, char *argv[]); +/** + * print a listing of the parameters of node to pCon, using the + * specified prefix. + * @param The node to print + * @pCon The connection to print too + * @prefix The prefix to use for printing + */ +void PrintSICSParList(pHdb node, SConnection *pCon, char *prefix); +/** + * save the content of the Hipadaba starting at node into a file. This can + * be used to save the configuration of an instrument. This routine is + * recursive. + * @param fd The file to write to + * @param node The node to print from + * @param prefix A prefix to use for printing. + */ +void SaveSICSHipadaba(FILE *fd, pHdb node, char *prefix); /** * A SICS task which scans a Hipadaba and reads and updates all parameters, * one per invocation. TODO: how to distinguish between automatic pars which diff --git a/sicsstat.tcl b/sicsstat.tcl index 3ebfc9d2..5ce78d00 100644 --- a/sicsstat.tcl +++ b/sicsstat.tcl @@ -1,7 +1,19 @@ -# Counter counter -counter SetPreset 10.000000 -counter SetMode Timer -hm CountMode timer -hm preset 10.000000 -hm genbin 0.000000 10.000000 10000 -hm init +exe batchpath ./ +exe syspath ./ +# Motor brumm +brumm sign 1.0000 +brumm hardlowerlim -180.0000 +brumm hardupperlim 180.0000 +brumm softlowerlim -180.0000 +brumm softupperlim 180.0000 +brumm softzero 0.0000 +brumm fixed -1.0000 +brumm interruptmode 0.0000 +brumm precision 0.2000 +brumm accesscode 2.0000 +brumm failafter 3.0000 +brumm maxretry 3.0000 +brumm ignorefault 0.0000 +brumm movecount 10.0000 +brumm errortype 0.0000 +brumm recover 1.0000 diff --git a/velo.c b/velo.c index 3f8c260c..75c9465d 100644 --- a/velo.c +++ b/velo.c @@ -326,6 +326,7 @@ static void VSListForbidden(pVelSel self, SConnection *pCon){ pVelSel VSCreate(pMotor pTilt, pVelSelDriv pDriv) { pVelSel pNew = NULL; + SConnection *pCon = NULL; assert(pTilt); assert(pDriv); @@ -389,7 +390,12 @@ static void VSListForbidden(pVelSel self, SConnection *pCon){ /* deal with that motor, have him AccessCode Internal */ pNew->pTilt = pTilt; - ObParInit(pTilt->ParArray,8,"accesscode",(float)usInternal,usInternal); + pCon = SCCreateDummyConnection(pServ->pSics); + if(pCon != NULL) + { + MotorSetPar(pTilt,pCon,"accesscode",(float)usInternal); + SCDeleteConnection(pCon); + } /* enter driver */ pNew->pDriv = pDriv;