diff --git a/amordrive.h b/amordrive.h index dd192d0..d1a53c5 100644 --- a/amordrive.h +++ b/amordrive.h @@ -22,3 +22,4 @@ int AmorDriveAction(SConnection *pCon, SicsInterp *pSics, void *pData, int argc, char *argv[]); #endif + diff --git a/amorset.c b/amorset.c index d49057d..46af797 100644 --- a/amorset.c +++ b/amorset.c @@ -29,11 +29,16 @@ static int readMotors(pamorSet self, SConnection *pCon){ float val; result = LLDcreate(sizeof(MotControl)); - status = addMotorToList(result,"d2t",.0); - if(status != 1){ - SCWrite(pCon,"ERROR: configuration error: d2t not found", eError); - return -1; - } + status = addMotorToList(result,"d1t",.0); + if(status != 1){ + SCWrite(pCon,"ERROR: configuration error: d1t not found", eError); + return -1; + } + status = addMotorToList(result,"d2t",.0); + if(status != 1){ + SCWrite(pCon,"ERROR: configuration error: d2t not found", eError); + return -1; + } status = addMotorToList(result,"d3t",.0); if(status != 1){ SCWrite(pCon,"ERROR: configuration error: d3t not found", eError); @@ -91,21 +96,37 @@ static int calcAmorSettings(pamorSet self,SConnection *pCon){ val = dist*Tand(-self->targetm2t) - self->dspar; addMotorToList(self->driveList,"dbs",val); } + + /* + * slit 1 is before the monochromator and does not need to be + * driven when m2t changes. This is here to make sure that d1b is + * in a feasible position. + */ + if(self->D1.activeFlag == 1){ + mot = getListMotorPosition(readList,"d1t"); + if(mot < -99999){ + SCWrite(pCon,"WARNING: skipping d1 because of bad read on d1t", + eWarning); + } else { + val = - .5 * mot; + addMotorToList(self->driveList,"d1b",val); + } + } - /* - * slit 2 - */ - if(self->D2.activeFlag == 1){ - dist = ABS(calcCompPosition(&self->D2) - calcCompPosition(&self->M)); - mot = getListMotorPosition(readList,"d2t"); - if(mot < -99999){ - SCWrite(pCon,"WARNING: skipping d2 because of bad read on d2t", - eWarning); - } else { - val = dist*Tand(-self->targetm2t) - .5 * mot; - addMotorToList(self->driveList,"d2b",val); - } - } + /* + * slit 2 + */ + if(self->D2.activeFlag == 1){ + dist = ABS(calcCompPosition(&self->D2) - calcCompPosition(&self->M)); + mot = getListMotorPosition(readList,"d2t"); + if(mot < -99999){ + SCWrite(pCon,"WARNING: skipping d2 because of bad read on d2t", + eWarning); + } else { + val = dist*Tand(-self->targetm2t) - .5 * mot; + addMotorToList(self->driveList,"d2b",val); + } + } /* * slit 3 @@ -362,7 +383,8 @@ static int amorSetSave(void *data, char *name,FILE *fd){ saveAmorComp(fd,name,"chopper",&self->chopper); saveAmorComp(fd,name,"mono",&self->M); saveAmorComp(fd,name,"ds",&self->DS); - saveAmorComp(fd,name,"slit2",&self->D2); + saveAmorComp(fd,name,"slit1",&self->D2); + saveAmorComp(fd,name,"slit2",&self->D2); saveAmorComp(fd,name,"slit3",&self->D3); saveAmorComp(fd,name,"sample",&self->S); saveAmorComp(fd,name,"slit4",&self->D4); @@ -423,7 +445,9 @@ static void killAmorSet(void *data){ /*-------------------------------------------------------------------*/ static int testRequiredMotors(SConnection *pCon){ char motList[][20] = {"soz", "com", - "cox","coz","dbs","d2b","d2t", + "cox","coz","dbs", + "d1t", "d1b", + "d2b","d2t", "d3b", "d3t", "d4b","d4t", "d5t", "d5b","aoz", "aom"}; int i = 0, status = 1; @@ -431,7 +455,7 @@ static int testRequiredMotors(SConnection *pCon){ char pBueffel[132]; - for(i = 0; i < 15; i++){ + for(i = 0; i < 17; i++){ pMot = NULL; pMot = FindMotor(pServ->pSics,motList[i]); if(pMot == NULL){ @@ -507,8 +531,10 @@ static pamorComp locateComponent(pamorSet self, char *name){ return &self->M; } else if(strcmp(name,"ds") == 0){ return &self->DS; - }else if(strcmp(name,"slit2") == 0){ - return &self->D2; + }else if(strcmp(name,"slit1") == 0){ + return &self->D1; + }else if(strcmp(name,"slit2") == 0){ + return &self->D2; }else if(strcmp(name,"slit3") == 0){ return &self->D3; }else if(strcmp(name,"sample") == 0){ diff --git a/amorset.h b/amorset.h index f483d59..f772d67 100644 --- a/amorset.h +++ b/amorset.h @@ -19,6 +19,7 @@ typedef struct { amorComp chopper; amorComp M; amorComp DS; + amorComp D1; amorComp D2; amorComp D3; amorComp S; @@ -50,3 +51,4 @@ double amorGetMotor(pamorSet amor, SConnection *pCon, int type); #endif + diff --git a/amorset.tex b/amorset.tex index ca91dd8..d575d02 100644 --- a/amorset.tex +++ b/amorset.tex @@ -70,6 +70,7 @@ $\langle$amorsetint {\footnotesize ?}$\rangle\equiv$ \mbox{}\verb@ amorComp chopper;@\\ \mbox{}\verb@ amorComp M;@\\ \mbox{}\verb@ amorComp DS;@\\ +\mbox{}\verb@ amorComp D1;@\\ \mbox{}\verb@ amorComp D2;@\\ \mbox{}\verb@ amorComp D3;@\\ \mbox{}\verb@ amorComp S;@\\ diff --git a/amorset.w b/amorset.w index 2a7140a..e9e6ff3 100644 --- a/amorset.w +++ b/amorset.w @@ -53,6 +53,7 @@ typedef struct { amorComp chopper; amorComp M; amorComp DS; + amorComp D1; amorComp D2; amorComp D3; amorComp S; diff --git a/amorstat.c b/amorstat.c index 354dbac..54037a7 100644 --- a/amorstat.c +++ b/amorstat.c @@ -593,7 +593,11 @@ { snprintf(hmCommand,255,"sum:2:0:%d",iDim[2]); - data = self->pHM->pDriv->SubSample(self->pHM->pDriv,pCon,0,hmCommand); + if(self->pHM->pDriv->SubSample != NULL){ + data = self->pHM->pDriv->SubSample(self->pHM->pDriv,pCon,0,hmCommand); + } else { + data = NULL; + } if(data == NULL) { SCWrite(pCon,"ERROR: failed to retrieve collapsed data from HM", eError); diff --git a/el737driv.c b/el737driv.c index 92f5aa5..3321cb3 100644 --- a/el737driv.c +++ b/el737driv.c @@ -515,11 +515,11 @@ if(strcmp(name,"threshold") == 0) { - sprintf(pCommand,"DL %1.1d %f\r",iCter,fVal); + sprintf(pCommand,"DL %1.1d %6.2f\r",iCter,fVal); iRet = EL737_SendCmnd(&pEL737->pData,pCommand,pReply,79); if(iRet == 1) { - if(pCommand[0] == '?') + if(pReply[0] == '?') { self->iErrorCode = BADCOUNTER; return HWFault; diff --git a/el737hpdriv.c b/el737hpdriv.c index 1217f07..e7cfe61 100644 --- a/el737hpdriv.c +++ b/el737hpdriv.c @@ -412,6 +412,9 @@ static int EL737GetError(struct __COUNTER *self, int *iCode, case OFFLINE: strncpy(pError,"EL737 is offline",errLen); break; + case OVERFLOW: + strncpy(pError,"EL737 reported overflow, communication problem",errLen); + break; case BADRANGE: strncpy(pError,"EL737 parameter is out of range",errLen); break; @@ -468,6 +471,7 @@ static int EL737FixIt(struct __COUNTER *self, int iCode){ case NOPARAM: case BADRANGE: case BADTRANGE: + case OVERFLOW: return COREDO; break; case BADREPLY: diff --git a/julcho.c b/julcho.c index 852b44a..f8086b6 100644 --- a/julcho.c +++ b/julcho.c @@ -17,6 +17,7 @@ #include #include #include +#include #define CHOCOINTERNAL #include #include @@ -41,6 +42,8 @@ /*--------------------- update flags -------------------------------------*/ #define ALL 1 #define SPEED 2 +/*--------------------- wait after set -----------------------------------*/ +#define STWAIT 5 /*------------------------- chopper internal names -----------------------*/ #define CH1N "snail" #define CH2N "master" @@ -381,6 +384,7 @@ static int ReadJulChoFlags(pJulCho self){ char reply[256]; status = JulChoTransact(self,"RSC",reply,255); +/* fprintf(stdout,"Chopper flags = %s\n", reply);*/ if(status < 0){ self->errorCode = status; return 0; @@ -911,6 +915,12 @@ static int JulChoSetPar2(pCodri pDriv, char *parname, char *pValue){ self->errorCode = status; return 0; } + /* + * The SicsWait is here to allow the chopper to update his status flags. + * There were occurrences where the chopper was still driving but the + * status flag did not reflect this. + */ + SicsWait(STWAIT); self->lastUpdate = 0; return status; } @@ -958,6 +968,12 @@ static int JulChoSetPar(pCodri pDriv, char *parname, float fValue){ self->errorCode = status; return 0; } + /* + * The SicsWait is here to allow the chopper to update his status flags. + * There were occurrences where the chopper was still driving but the + * status flag did not reflect this. + */ + SicsWait(STWAIT); self->lastUpdate = 0; return status; } @@ -1015,8 +1031,8 @@ static int JulChoGetPar(pCodri pDriv, char *parname, /*---------------------------------------------------------------------------*/ static int JulChoCheckPar(pCodri pDriv, char *parname){ pJulCho self = NULL; - int i; - char path[256]; + int i, status; + char path[256], reply[256]; pHdb target = NULL; char *chNames[] = {CH1N, CH2N, @@ -1052,6 +1068,12 @@ static int JulChoCheckPar(pCodri pDriv, char *parname){ return HWBusy; } } + status = JulChoTransact(self,"RSC",reply,255); + if(status < 0){ + self->errorCode = status; + return HWFault; + } +/* fprintf(stdout,"Chopper Flags at finish: %s\n", reply);*/ return HWIdle; } /*---------------------------------------------------------------------------*/ diff --git a/libpsi.a b/libpsi.a index c9c2d54..981de56 100644 Binary files a/libpsi.a and b/libpsi.a differ diff --git a/make_gen b/make_gen index e8c7445..360050f 100644 --- a/make_gen +++ b/make_gen @@ -18,7 +18,7 @@ OBJ=psi.o buffer.o ruli.o dmc.o nxsans.o nextrics.o sps.o pimotor.o \ el737hpv2driv.o swmotor2.o tricssupport.o amorcomp.o \ $(MZOBJ) amordrive.o amorset.o tcpdornier.o sinqhttp.o\ dgrambroadcast.o sinq.o tabledrive.o tcpdocho.o julcho.o \ - ritastorage.o + ritastorage.o poldizug.o MZOBJ=fsm.o logger.o sugar.o pardef.o ease.o strobj.o oxinst.o logreader.o \ ipsdriv.o ilmdriv.o itcdriv.o ighdriv.o euro2kdriv.o modbus.o arrobj.o \ diff --git a/poldizug.c b/poldizug.c new file mode 100644 index 0000000..4365ec7 --- /dev/null +++ b/poldizug.c @@ -0,0 +1,358 @@ +/** + * This is the implementation of a SICS access module for the POLDI + * pull machine for testing mechanical samples. This thing is a one + * of a kind; therefore its implementation does not follow the usual + * SICS distinction between hardware object and driver. The thing can + * operate in two modes: either a force is driven or a position. + * + * copyright: see file COPYRIGHT + * + * Mark Koennecke, October 2006 + */ +#include +#include +#include +/*===============================================================*/ +#define FORCE 0 +#define ZUGPOS 1 +/*---------------------------------------------------------------*/ +typedef struct { + pObjectDescriptor pDes; + pIDrivable pDriv; + prs232 controller; + int iMode; + float maxForce, minForce; + float maxPos, minPos; +}PZR, *pPZR; +/*--------------------------------------------------------------*/ +static int PZRCommand(prs232 controller, SConnection *pCon, + char *command, + char *reply, int replyLen){ + int status, i; + char buffer[512], error[132]; + + /* + * try three times to get our message through... + */ + for(i = 0; i < 3; i++){ + status = transactRS232(controller,command, strlen(command), + reply, replyLen); + if(status == 1){ + return 1; + } + /* + * error processing + */ + memset(error,0,132); + getRS232Error(status,error,131); + status = fixRS232Error(controller,status); + if(pCon != NULL){ + if(status == 1){ + snprintf(buffer,511,"WARNING: trying to fix: %s", + error); + SCWrite(pCon,buffer,eWarning); + } else { + snprintf(buffer,511,"ERROR: %s", + error); + SCWrite(pCon,buffer,eError); + } + } + if(status == 0){ + return HWFault; + } + } + return HWFault; +} +/*===============================================================*/ +static void *PZRGetInterface(void *data, int iD){ + pPZR self = NULL; + + self = (pPZR)data; + if(self != NULL && iD == DRIVEID){ + return self->pDriv; + } else { + return NULL; + } + return NULL; +} +/*---------------------------------------------------------------- + This routine can return either OKOK or HWFault when thing + go wrong. However, the return value of Halt is usually ignored! +------------------------------------------------------------------*/ +static int PZRHalt(void *data) { + pPZR self = NULL; + char buffer[80]; + + self = (pPZR)data; + + PZRCommand(self->controller,NULL,"stop\n",buffer,79); + + return OKOK; +} +/*---------------------------------------------------------------- + This routine can return either 1 or 0. 1 means the position can + be reached, 0 NOT + If 0, error shall contain up to errlen characters of information + about which limit was violated +------------------------------------------------------------------*/ +static int PZRCheckLimits(void *data, float val, + char *error, int errlen){ + pPZR self = NULL; + + self = (pPZR)data; + if(self->iMode == FORCE){ + if(val < self->minForce || val > self->maxForce){ + snprintf(error,errlen,"%f is not within limits %f to %f", + val,self->minForce, self->maxForce); + return 0; + } + } else { + if(val < self->minPos || val > self->maxPos){ + snprintf(error,errlen,"%f is not within limits %f to %f", + val,self->minPos, self->maxPos); + return 0; + } + } + return 1; +} +/*---------------------------------------------------------------- + This routine can return 0 when a limit problem occurred + OKOK when the motor was successfully started + HWFault when a problem occured starting the device + Possible errors shall be printed to pCon + For real motors, this is supposed to try at least three times + to start the motor in question + val is the value to drive the motor too +------------------------------------------------------------------*/ +static long PZRSetValue(void *data, SConnection *pCon, float val){ + pPZR self = NULL; + char command[80], reply[80]; + int status; + + self = (pPZR)data; + + if(self->iMode == FORCE){ + snprintf(command,79,"wr force %f\n", val); + } else { + snprintf(command,79,"wr vel %f\n", val); + } + status = PZRCommand(self->controller, pCon, command, reply, 79); + if(status == 1){ + return OKOK; + } else { + return HWFault; + } + return HWFault; +} +/*---------------------------------------------------------------- + Checks the status of a running motor. Possible return values + HWBusy The motor is still running + OKOK or HWIdle when the motor finished driving + HWFault when a hardware problem ocurred + HWPosFault when the hardware cannot reach a position + Errors are duly to be printed to pCon + For real motors CheckStatus again shall try hard to fix any + issues with the motor +------------------------------------------------------------------*/ +static int PZRCheckStatus(void *data, SConnection *pCon){ + pPZR self = NULL; + int status, code; + char command[80], reply[80], bits[1]; + + self = (pPZR)data; + snprintf(command,79,"rd stat\n"); + status = PZRCommand(self->controller, pCon, command, reply, 79); + if(status != 1){ + return HWFault; + } + sscanf(reply,"%x", &code); + bits[0] = (char)code; + /* + * check for errors + */ + if(BITSET(bits,3)){ + SCWrite(pCon,"ERROR: BANG! Sample broken!",eError); + return HWFault; + } + if(BITSET(bits,4)){ + SCWrite(pCon,"ERROR: hit positive limit switch",eError); + return HWFault; + } + if(BITSET(bits,5)){ + SCWrite(pCon,"ERROR: hit negative limit switch",eError); + return HWFault; + } + if(BITSET(bits,7)){ + SCWrite(pCon,"ERROR: general and overall error",eError); + return HWFault; + } + if(BITSET(bits,2)){ + return HWBusy; + } else { + return HWIdle; + } + + return HWFault; +} +/*---------------------------------------------------------------- + GetValue is supposed to read a motor position + On errors, -99999999.99 is returned and messages printed to pCon +------------------------------------------------------------------*/ +static float PZRGetValue(void *data, SConnection *pCon){ + pPZR self = NULL; + float val = -99999999.99; + int status; + char command[80], reply[80]; + + self = (pPZR)data; + if(self->iMode == FORCE){ + snprintf(command,79,"rd force\n"); + } else { + snprintf(command,79,"rd vel\n"); + } + status = PZRCommand(self->controller, pCon, command, reply, 79); + if(status != 1){ + return HWFault; + } + sscanf(reply,"%f",&val); + return val; +} +/*---------------------------------------------------------------- + returns NULL on failure, a new datastructure else +------------------------------------------------------------------*/ +static pPZR PZRMakeObject(char *host, int port){ + pPZR self = NULL; + + self = malloc(sizeof(PZR)); + if(self == NULL){ + return NULL; + } + self->pDes = CreateDescriptor("PoldiReiss"); + self->pDriv = CreateDrivableInterface(); + self->controller = createRS232(host,port); + if(self->pDes == NULL || self->pDriv == NULL || self->controller == NULL){ + free(self); + return NULL; + } + initRS232(self->controller); + setRS232SendTerminator(self->controller,"\n"); + setRS232ReplyTerminator(self->controller,"\n"); + setRS232Timeout(self->controller,1000); + setRS232Debug(self->controller,1); + + + self->pDes->GetInterface = PZRGetInterface; + self->pDriv->Halt = PZRHalt; + self->pDriv->CheckLimits = PZRCheckLimits; + self->pDriv->SetValue = PZRSetValue; + self->pDriv->CheckStatus = PZRCheckStatus; + self->pDriv->GetValue = PZRGetValue; + + return self; +} +/*--------------------------------------------------------------------------*/ +static void killPoldiZug(void *data){ + pPZR self = (pPZR)data; + + if(self == NULL){ + return; + } + if(self->pDes != NULL){ + DeleteDescriptor(self->pDes); + } + if(self->controller != NULL){ + closeRS232(self->controller); + KillRS232(self->controller); + } + free(self); +} +/*============================================================================*/ +static int PoldiReissAction(SConnection *pCon, SicsInterp *pSics, + void *pData, int argc, char *argv[]){ + pPZR self = NULL; + char command[80], reply[80]; + float val; + int status; + + self = (pPZR)pData; + assert(self != NULL); + + if(argc > 1) { + strtolower(argv[1]); + if(strcmp(argv[1],"mode") == 0) { + if(argc > 2){ + if(!SCMatchRights(pCon,usUser)){ + return 0; + } + strtolower(argv[2]); + if(strcmp(argv[2],"force") == 0) { + status = PZRCommand(self->controller, pCon, + "wr mode 1\n", reply,79); + if(status == 1){ + self->iMode == FORCE; + SCSendOK(pCon); + return 1; + } else { + return 0; + } + } else if(strcmp(argv[2],"pos") == 0) { + status = PZRCommand(self->controller, pCon, + "wr mode 0\n", reply,79); + if(status == 1){ + self->iMode == ZUGPOS; + SCSendOK(pCon); + return 1; + } else { + return 0; + } + } else { + SCWrite(pCon,"ERROR: zug mode unknown, allowed force, pos", + eError); + return 0; + } + } + } else { + if(self->iMode == FORCE){ + snprintf(command,79,"%s.mode = force",argv[0]); + } else { + snprintf(command,79,"%s.mode = pos",argv[0]); + } + SCWrite(pCon,command,eValue); + return 1; + } + } + val = self->pDriv->GetValue(self,pCon); + snprintf(command,79,"%s = %f", argv[0], val); + SCWrite(pCon,command,eValue); + return 1; +} +/*---------------------------------------------------------------------------- + * MakePoldiReiss name host port minForce maxForce minPos maxPos + * ---------------------------------------------------------------------------*/ +int MakePoldiReiss(SConnection *pCon, SicsInterp *pSics, + void *pData, int argc, char *argv[]){ + pPZR self = NULL; + char reply[80]; + + if(argc < 8) { + SCWrite(pCon,"ERROR: not enough arguments to MakePoldiReiss",eError); + return 0; + } + self = PZRMakeObject(argv[2],atoi(argv[3])); + if(self == NULL){ + SCWrite(pCon,"ERROR: out of memory making PoldiReiss",eError); + return 0; + } + self->minForce = atof(argv[4]); + self->maxForce = atof(argv[5]); + self->minPos = atof(argv[6]); + self->maxPos = atof(argv[7]); + PZRCommand(self->controller, pCon, + "wr mode 1\n", reply,79); + + AddCommand(pSics,argv[1], + PoldiReissAction, + killPoldiZug, + self); + return 1; +} diff --git a/poldizug.h b/poldizug.h new file mode 100644 index 0000000..559e013 --- /dev/null +++ b/poldizug.h @@ -0,0 +1,19 @@ +/** + * This is the implementation of a SICS access module for the POLDI + * pull machine for testing mechanical samples. This thing is a one + * of a kind; therefore its implementation does not follow the usual + * SICS distinction between hardware object and driver. The thing can + * operate in two modes: either a force is driven or a position. + * + * There is only the creation function here, everything else is in poldizug.c + * + * copyright: see file COPYRIGHT + * + * Mark Koennecke, October 2006 + */ +#ifndef POLDIZUG_H_ +#define POLDIZUG_H_ +#include +int MakePoldiReiss(SConnection *pCon, SicsInterp *pSics, + void *pData, int argc, char *argv[]); +#endif /*POLDIZUG_H_*/ diff --git a/psi.c b/psi.c index a6063fc..d48fd79 100644 --- a/psi.c +++ b/psi.c @@ -55,6 +55,7 @@ #include "tabledrive.h" #include "amorset.h" #include "sinqhttp.h" +#include "poldizug.h" /* from tcpdornier.c */ @@ -121,6 +122,7 @@ static void AddPsiCommands(SicsInterp *pInter){ AddCommand(pInter,"MakeTCPSelector",VelSelTcpFactory,NULL,NULL); AddCommand(pInter,"MakeJulCho",JulChoFactory,NULL,NULL); AddCommand(pInter,"MakeRitaFix",MakeRitaFix,NULL,NULL); + AddCommand(pInter,"MakePoldiReiss",MakePoldiReiss,NULL,NULL); /* AddCommand(pInter,"MakeDifrac",MakeDifrac,NULL,NULL); */ @@ -143,6 +145,7 @@ static void RemovePsiCommands(SicsInterp *pSics){ RemoveCommand(pSics,"MakeTCPSelector"); RemoveCommand(pSics,"MakeJulCho"); RemoveCommand(pSics,"MakeRitaFix"); + RemoveCommand(pSics,"MakePoldiReiss"); /* RemoveCommand(pSics,"MakeDifrac"); */ diff --git a/sinqhttp.c b/sinqhttp.c index b12db18..17cd186 100644 --- a/sinqhttp.c +++ b/sinqhttp.c @@ -131,7 +131,7 @@ static int sinqHttpGet(pSinqHttp self, char *request){ if(httpStatus != ghttp_done){ ghttp_close(self->syncRequest); sinqHttpGetPrepare(self,request); - ghttp_prepare(self->syncRequest); + ghttp_prepare(self->syncRequest); httpStatus = ghttp_process(self->syncRequest); } if(httpStatus != ghttp_done){ @@ -151,6 +151,7 @@ static int SinqHttpConfigure(pHistDriver self, SConnection *pCon, pSinqHttp pPriv = NULL; int status, iInit; float fVal; + int i; char *confData = NULL; ghttp_status httpStatus; @@ -199,58 +200,69 @@ static int SinqHttpConfigure(pHistDriver self, SConnection *pCon, actually do configure */ if(iInit == 1){ - memset(confCommand,0,512*sizeof(char)); - if(StringDictGet(pOpt,"hmconfigscript",confCommand,511) != 1){ - SCWrite(pCon, - "ERROR: required parameter hmconfigscript not found!", - eError); - return 0; - } - status = Tcl_Eval(pSics->pTcl,confCommand); - if(status != TCL_OK){ - snprintf(confCommand,511, - "ERROR: Tcl reported %s while evaluating hmconfigscript", - Tcl_GetStringResult(pSics->pTcl)); - SCWrite(pCon,confCommand,eError); - return 0; - } else { - /* - uplod new configuration to HM - */ - ghttp_clean(pPriv->syncRequest); - snprintf(url,511,"%s%s",pPriv->hmAddress,configure); - status = ghttp_set_uri(pPriv->syncRequest,url); - if(status < 0){ - SCWrite(pCon,"ERROR: invalid URI for HM request",eError); + for(i = 0; i < 2; i++){ + memset(confCommand,0,512*sizeof(char)); + if(StringDictGet(pOpt,"hmconfigscript",confCommand,511) != 1){ + SCWrite(pCon, + "ERROR: required parameter hmconfigscript not found!", + eError); return 0; } - status = ghttp_set_type(pPriv->syncRequest,ghttp_type_post); - confData = (char *)Tcl_GetStringResult(pSics->pTcl); - /* puts(confData); */ - status = ghttp_set_body(pPriv->syncRequest,confData, - strlen(confData)); - ghttp_set_authinfo(pPriv->syncRequest, pPriv->userName, - pPriv->passWord); - ghttp_set_sync(pPriv->syncRequest,ghttp_sync); - status = ghttp_prepare(pPriv->syncRequest); - httpStatus = ghttp_process(pPriv->syncRequest); - confData = (char *)ghttp_get_body(pPriv->syncRequest); - if(httpStatus != ghttp_done){ - confData = (char *)ghttp_get_error(pPriv->syncRequest); - snprintf(confCommand,511,"ERROR: http error %s occurred", - confData); + status = Tcl_Eval(pSics->pTcl,confCommand); + if(status != TCL_OK){ + snprintf(confCommand,511, + "ERROR: Tcl reported %s while evaluating hmconfigscript", + Tcl_GetStringResult(pSics->pTcl)); SCWrite(pCon,confCommand,eError); return 0; - } else if(confData != NULL){ - if(strstr(confData,"ERROR") != NULL){ - snprintf(confCommand,511,"%s",confData); - SCWrite(pCon,confCommand,eError); + } else { + /* + uplod new configuration to HM + */ + ghttp_clean(pPriv->syncRequest); + snprintf(url,511,"%s%s",pPriv->hmAddress,configure); + status = ghttp_set_uri(pPriv->syncRequest,url); + if(status < 0){ + SCWrite(pCon,"ERROR: invalid URI for HM request",eError); return 0; } - if(strstr(confData,"Authentication Error") != NULL){ - snprintf(confCommand,511,"%s",confData); + status = ghttp_set_type(pPriv->syncRequest,ghttp_type_post); + confData = (char *)Tcl_GetStringResult(pSics->pTcl); + /* puts(confData); */ + status = ghttp_set_body(pPriv->syncRequest,confData, + strlen(confData)); + ghttp_set_authinfo(pPriv->syncRequest, pPriv->userName, + pPriv->passWord); + ghttp_set_sync(pPriv->syncRequest,ghttp_sync); + status = ghttp_prepare(pPriv->syncRequest); + httpStatus = ghttp_process(pPriv->syncRequest); + confData = (char *)ghttp_get_body(pPriv->syncRequest); + if(httpStatus != ghttp_done){ + /* we may need to reconnect..... + */ + if(i == 0){ + ghttp_close(pPriv->syncRequest); + continue; + } + /* + * no we have a real error + */ + confData = (char *)ghttp_get_error(pPriv->syncRequest); + snprintf(confCommand,511,"ERROR: http error %s occurred", + confData); SCWrite(pCon,confCommand,eError); return 0; + } else if(confData != NULL){ + if(strstr(confData,"ERROR") != NULL){ + snprintf(confCommand,511,"%s",confData); + SCWrite(pCon,confCommand,eError); + return 0; + } + if(strstr(confData,"Authentication Error") != NULL){ + snprintf(confCommand,511,"%s",confData); + SCWrite(pCon,confCommand,eError); + return 0; + } } } } diff --git a/slsmagnet.c b/slsmagnet.c index 1aad633..f03a812 100644 --- a/slsmagnet.c +++ b/slsmagnet.c @@ -758,6 +758,12 @@ static void slsdspCodeToText(int code, char *text, int textlen){ int iRet, ival; char msg[6], reply[6]; + assert(self); + pMe = (pSLSDriv )self->pPrivate; + assert(pMe); + + + msg[0] = DSPWRITE; msg[1] = 0x3c; if(strcmp(pCommand,"off") == 0){ @@ -825,9 +831,6 @@ static void slsdspCodeToText(int code, char *text, int textlen){ try to switch device on */ msg[0] = DSPWRITE; - /* old device on - msg[1] = 0x31; - */ msg[1] = 0x3c; /* * ival = 0: ausschalten @@ -869,7 +872,6 @@ static void slsdspCodeToText(int code, char *text, int textlen){ memcpy(msg+2, &ival,4); iRet = communicateSLS(pMe->pSock,msg,reply); */ - NETClosePort(pMe->pSock); pMe->pSock = NULL; return 1; diff --git a/tabledrive.c b/tabledrive.c index fc2505c..90d53f0 100644 --- a/tabledrive.c +++ b/tabledrive.c @@ -10,11 +10,13 @@ #include "../lld.h" #include "tabledrive.h" /*--------------------------------------------------------------------------*/ -#define OUTOFSYNC 100 -#define STARTING 101 -#define STEPPING 102 -#define WAITING 103 +#define OUTOFSYNC 100 +#define STARTING 101 +#define STEPPING 102 +#define WAITING 103 #define WAITFINISH 104 +#define IDLE 105 + #define ABS(x) (x < 0 ? -(x) : (x)) #define SIGN(x) (x < .0 ? (-1) : (1)) extern char *trim(char *txt); @@ -182,6 +184,10 @@ static void checkSync(pTableDrive self, SConnection *pCon, float value){ float motorPosition, targetPosition, tolerance, diff; tdMotor moti; char pBueffel[256]; + + if(self->state != IDLE){ + return; + } status = LLDnodePtr2First(self->motorTable); while(status != 0){ @@ -224,6 +230,36 @@ static float TableDriveGetValue(void *pData, SConnection *pCon){ self->currentPosition = value; return value; } +/*-------------------------------------------------------------------------*/ +static void tableInfo(pTableDrive self, SConnection *pCon){ + int status, test; + float motorPosition, targetPosition, tolerance, diff, value; + tdMotor moti; + char pBueffel[256]; + + value = TableDriveGetValue(self,pCon); + snprintf(pBueffel,255," Triffid Position: %8.2f", value); + SCWrite(pCon,pBueffel,eValue); + + status = LLDnodePtr2First(self->motorTable); + while(status != 0){ + LLDnodeDataTo(self->motorTable,&moti); + test = MotorGetSoftPosition(moti.pMot,pCon,&motorPosition); + if(!test){ + snprintf(pBueffel,255,"ERROR: failed to read motor %s", + moti.motorName); + SCWrite(pCon,pBueffel,eError); + } else { + MotorGetPar(moti.pMot,"precision",&tolerance); + targetPosition = findTarget(moti,value); + snprintf(pBueffel,256,"Motor %10s, should: %8.2f, is %8.2f, diff = %8.2f", + moti.motorName, motorPosition, targetPosition, + ABS(targetPosition - motorPosition)); + SCWrite(pCon,pBueffel,eValue); + } + status = LLDnodePtr2Next(self->motorTable); + } +} /*------------------------------------------------------------------------*/ static void tableSetPar(pMotor pMot, char *name, float value){ ObPar *ob = NULL; @@ -401,6 +437,7 @@ static int TableDriveCheckStatus(void *pData, SConnection *pCon){ if(status != HWBusy){ TableDriveGetValue(self,pCon); closeMotors(self,pCon); + self->state = IDLE; return status; } else { return HWBusy; @@ -408,6 +445,7 @@ static int TableDriveCheckStatus(void *pData, SConnection *pCon){ break; case OUTOFSYNC: SCWrite(pCon,"WARNING: tabledrive out of sync",eWarning); + self->state = IDLE; return HWFault; break; default: @@ -579,6 +617,7 @@ int TableDriveFactory(SConnection *pCon, SicsInterp *pSics, void *pData, killTableDrive(pNew); return 0; } + pNew->state = IDLE; status = AddCommand(pSics,argv[1], TableDriveAction, @@ -599,7 +638,8 @@ int TableDriveAction(SConnection *pCon, SicsInterp *pSics, void *pData, pTableDrive self = (pTableDrive)pData; int status; char pBueffel[1024]; - float value; + float value; + pDynString print = NULL; if(argc < 2){ value = TableDriveGetValue(self,pCon); @@ -626,10 +666,18 @@ int TableDriveAction(SConnection *pCon, SicsInterp *pSics, void *pData, SCSendOK(pCon); } return status; - }else if(strcmp(argv[1],"show") == 0){ - showPositions(self,pCon,pBueffel,1023); - SCWrite(pCon,pBueffel,eValue); - return 1; + }else if(strcmp(argv[1],"show") == 0){ + showPositions(self,pCon,pBueffel,1023); + SCWrite(pCon,pBueffel,eValue); + return 1; + }else if(strcmp(argv[1],"info") == 0){ + SCStartBuffering(pCon); + tableInfo(self,pCon); + print = SCEndBuffering(pCon); + if(print != NULL){ + SCWrite(pCon,GetCharArray(print), eValue); + } + return 1; }else if(strcmp(argv[1],"orient") == 0){ if(argc > 2){ if(!SCMatchRights(pCon,usMugger)){