diff --git a/dornier2.c b/dornier2.c new file mode 100644 index 0000000..3ddc58a --- /dev/null +++ b/dornier2.c @@ -0,0 +1,610 @@ +/*------------------------------------------------------------------------ + + Another driver for a Dornier velocity selector. This is for a newer + version of the velocity selector driver as delivered with SANS-2. It + also uses a direct connection to the terminal server without David Maden's + SerPortServer program in between. + + I believe this is for Dornier software version: NGS037 of 2002. + + The protocoll is inconsistent: status messages come back with a , + command responses tend to come back with a \ and no ! + + There is a scheme here: while waiting for status reponses during driving, + the last status read is used for any requests. + + copyright: see file COPYRIGHT + + Mark Koennecke, July 2003 + ---------------------------------------------------------------------------*/ +#include +#include +#include +#include +#include +#include +#include +typedef struct __VelSelDriv *pVelSelDriv; + +#include +#include "velodorn.h" + +/* VELO* MUST be the same as in velo.i!*/ +#define VELOREDO 2 +#define VELOFAIL 0 +#define VELOOK 1 +#define VSNOCON 0 +#define VSOK 1 +#define VSACCEL -7 +#define VSFAIL -2 + +/*--------- special Dornier conditions*/ +#define STARTED -88 +#define HALTREQ -77 + +/*---------- DORNIER status modes */ +#define STATSEND 1 +#define STATREAD 2 +/*----------------------------- The private data structure ---------------*/ + typedef struct{ + prs232 controller; + int iTimeOut; + int iLastError; + time_t t_End; + time_t t_timeout; + float fTarget; + float fLastRPM; + int statusMode; + DornierStatus lastStatus; + int minRPM; /* the minimum control speed of the thing*/ + int haltCount; + } Dornier, *pDornier; +/*------------------------------------------------------------------*/ +static int requestDornierStatus(pDornier pDorn){ + int status; + + status = writeRS232(pDorn->controller,"???\n",4); + if(status < 0){ + pDorn->iLastError = status; + return 0; + } + return 1; +} +/*------------------------------------------------------------------*/ +static int readAndInterpretStatus(pDornier pDorn, DornierStatus *DStatus){ + int status, datalen; + char reply[512]; + + datalen = 512; + status = readRS232TillTerm(pDorn->controller,reply,&datalen); + if(status < 0){ + pDorn->iLastError = status; + return 0; + } + + DecodeNewDornierStatus(reply,DStatus); + return 1; +} +/*--------------------------------------------------------------------*/ + static int GetDornierPos(pVelSelDriv self, float *fPos) + { + pDornier pDorn = NULL; + DornierStatus DStatus; + int status; + + assert(self); + pDorn = (pDornier)self->pPrivate; + + if(pDorn->statusMode == STATSEND){ + if(!requestDornierStatus(pDorn)){ + *fPos = -9999.; + return 0; + } + if(!readAndInterpretStatus(pDorn,&DStatus)){ + *fPos = -9999.; + return 0; + } + pDorn->lastStatus = DStatus; + } + *fPos = pDorn->lastStatus.cur_rpm; + pDorn->fLastRPM = pDorn->lastStatus.cur_rpm; + return 1; + } +/*--------------------------------------------------------------------------*/ + static int DornierHalt(pVelSelDriv self) + { + pDornier pDorn = NULL; + int iRet; + char pCom[50]; + char pAnswer[80]; + + assert(self); + pDorn = (pDornier)self->pPrivate; + + snprintf(pCom,49,"SDR %d\n",pDorn->minRPM); + iRet = transactRS232(pDorn->controller,pCom,strlen(pCom), + pAnswer,79); + if(iRet != 1) + { + pDorn->iLastError = iRet; + return 0; + } + return 1; + } +/*-------------------------------------------------------------------------*/ + static int DornierRun(pVelSelDriv self, float fVal) + { + int iRet; + char pCommand[50], pAnswer[50]; + pDornier pDorn = NULL; + int startFlag = 0; + + assert(self); + pDorn = (pDornier)self->pPrivate; + + /* + less then minRPM, means halt in this case. + Accept this only after three times, see code in GetError as well. + */ + if(fVal < pDorn->minRPM - self->fTolerance) + { + if(pDorn->haltCount < 3){ + pDorn->iLastError = HALTREQ; + return 0; + } + strcpy(pCommand,"HAL\n"); + } else { + if(pDorn->lastStatus.cur_rpm < pDorn->minRPM){ + strcpy(pCommand,"SST\n"); + startFlag = 1; + pDorn->fTarget = pDorn->minRPM; + } else { + snprintf(pCommand,49,"SDR %5u\n",(int)nintf(fVal)); + pDorn->fTarget = fVal; + } + } + + setRS232ReplyTerminator(pDorn->controller,"\\"); + iRet = transactRS232(pDorn->controller,pCommand,strlen(pCommand), + pAnswer,49); + setRS232ReplyTerminator(pDorn->controller,"\r\n"); + if(iRet != 1) + { + pDorn->iLastError = iRet; + return 0; + } + pDorn->statusMode = STATSEND; + if(startFlag){ + pDorn->iLastError = STARTED; + return 0; + } + return 1; + } +/*---------------------------------------------------------------------*/ +static int DornierError(pVelSelDriv self, int *iCode, + char *error, int iErrLen){ + pDornier pDorn = NULL; + + assert(self); + pDorn = (pDornier)self->pPrivate; + + *iCode = pDorn->iLastError; + + switch(pDorn->iLastError){ + case HALTREQ: + strncpy(error,"Repeat command if you really want to HALT selector", + iErrLen); + pDorn->haltCount++; + break; + case STARTED: + strncpy(error, + "Started selector, standby and check manually when ready", + iErrLen); + break; + default: + getRS232Error(pDorn->iLastError,error,iErrLen); + break; + } + return 1; +} +/*-------------------------------------------------------------------*/ +static int DornierFixIt(pVelSelDriv self, int iCode){ + pDornier pDorn = NULL; + int status; + + assert(self); + pDorn = (pDornier)self->pPrivate; + + switch(iCode){ + case NOTCONNECTED: + status = initRS232(pDorn->controller); + if(status){ + return VELOREDO; + } else { + return VELOFAIL; + } + break; + case TIMEOUT: + case INCOMPLETE: + return VELOREDO; + break; + default: + return VELOFAIL; + } +} +/*---------------------------------------------------------------------*/ +static int statusSendHandler(pDornier pDorn){ + int status; + + if(!requestDornierStatus(pDorn)){ + return VSFAIL; + } + pDorn->t_timeout = time(NULL) + pDorn->iTimeOut/1000; + pDorn->statusMode = STATREAD; + return VSACCEL; +} +/*------------------------------------------------------------------*/ +static int evaluateStatus(pVelSelDriv self, int *iCode){ + int status; + DornierStatus sStatus; + char pCommand[80]; + char pAnswer[80]; + float fDelta; + static int iCount = 0; + pDornier pDorn = NULL; + + pDorn = (pDornier)self->pPrivate; + + pDorn->statusMode = STATSEND; + status = readAndInterpretStatus(pDorn,&sStatus); + if(!status){ + return VELOFAIL; + } + + *iCode = ROTMOVE; + /* + This code considers the velocity selector arrived if it reads + four times a difference between requested spped and actual speed + below difference + */ + pDorn->fLastRPM = sStatus.cur_rpm; + fDelta = sStatus.cur_rpm - sStatus.nom_rpm; + if(fDelta < 0){ + fDelta = - fDelta; + } + if(fDelta > self->fTolerance){ + iCount = 0; + return VSACCEL; + } else { + iCount++; + if(iCount > 4){ + return VSOK; + } else { + return VSACCEL; + } + } +} +/*---------------------------------------------------------------------*/ +static int statusReceiveHandler(pVelSelDriv self, int *iCode){ + int status; + pDornier pDorn = NULL; + + pDorn = (pDornier)self->pPrivate; + + status = availableRS232(pDorn->controller); + if(!status){ + if(time(NULL) > pDorn->t_timeout){ + pDorn->iLastError = TIMEOUT; + pDorn->statusMode = STATSEND; + return VELOFAIL; + } else { + return VSACCEL; + } + } + + return evaluateStatus(self, iCode); +} +/*-------------------------------------------------------------------------- + The Dornier takes a long time to answer a status message. In order to keep + SICS responsive the following state machine is implemented: + - a status request is sent. + - next data availability will be checked, if available: process! + ---------------------------------------------------------------------------*/ +static int DornierStatNew(pVelSelDriv self, int *iCode, float *fCur){ + pDornier pDorn = NULL; + int status; + + assert(self); + pDorn = (pDornier)self->pPrivate; + + if(pDorn->statusMode == STATSEND){ + return statusSendHandler(pDorn); + } else { + status = statusReceiveHandler(self,iCode); + *fCur = pDorn->fLastRPM; + return status; + } +} +/*----------------------------------------------------------------------*/ + static int DornierText(pVelSelDriv self, char *pText, int iTextLen) + { + pDornier pDorn = NULL; + int iRet, iErrStat; + DornierStatus sStatus; + char pBueffel[1024]; + char pHelp[80]; + + assert(self); + pDorn = (pDornier)self->pPrivate; + + /* + use cached status while waiting for reply during drive + */ + if(pDorn->statusMode == STATSEND){ + if(!requestDornierStatus(pDorn)){ + return 0; + } + if(!readAndInterpretStatus(pDorn,&sStatus)){ + return 0; + } + pDorn->lastStatus = sStatus; + } else { + sStatus = pDorn->lastStatus; + } + + /* format it to a string */ + sprintf(pHelp,"RPM: %d , should %d\n",sStatus.cur_rpm,sStatus.nom_rpm); + strcpy(pBueffel,pHelp); + sprintf(pHelp,"State: %s\n",sStatus.rm); + strcat(pBueffel,pHelp); + sprintf(pHelp,"Current: %d\n",sStatus.pwr); + strcat(pBueffel,pHelp); + sprintf(pHelp,"Rotor T: %d, Housing T: %d\n",sStatus.rot_temp, + sStatus.cont_temp); + strcat(pBueffel,pHelp); + sprintf(pHelp,"Cooling: In-T: %d, Out-T: %d, Flow: %f\n", + sStatus.inl_temp,sStatus.outl_temp,sStatus.cool_wat); + strcat(pBueffel,pHelp); + sprintf(pHelp,"Vaccum: %f, Accel: %f",sStatus.vacuum, sStatus.accel); + strcat(pBueffel,pHelp); + + strncpy(pText,pBueffel, iTextLen); + return 1; + } +/*------------------------------------------------------------------------*/ + static int DornierLoss(pVelSelDriv self, float *fLoss) + { + pDornier pDorn = NULL; + int iRet, iErrStat, iDelta; + DornierStatus DStatus; + char pCommand[] = {"BRE\n"}; + char pAnswer[80]; + static int iCount; + static int iError; + int i; + + assert(self); + pDorn = (pDornier)self->pPrivate; + + /* send a command */ + iRet = transactRS232(pDorn->controller,pCommand,strlen(pCommand), + pAnswer,79); + if(iRet != 1) + { + pDorn->iLastError = iRet; + return 0; + } + + /* wait 10 seconds before doing anything */ + SicsWait(10); + + /* loop until back to speed again */ + for(i = 0; i < 100; i++ ) + { + if(!requestDornierStatus(pDorn)){ + return 0; + } + if(!readAndInterpretStatus(pDorn,&DStatus)){ + return 0; + } + iError = 0; + iDelta = DStatus.cur_rpm - DStatus.nom_rpm; + if(iDelta < 0) + { + iDelta = -iDelta; + } + if(iDelta < 15) + { + iCount++; + if(iCount > 4) + { + break; + } + } + else + { + iCount = 0; + } + } + *fLoss = DStatus.pwr; + return 1; + } +/*-------------------------------------------------------------------------*/ + static void DornierKill(void *pData) + { + pDornier pDorn = NULL; + char pAns[10]; + + pDorn = (pDornier)pData; + assert(pDorn); + + transactRS232(pDorn->controller,"TTY\n",4,pAns,10); + KillRS232(pDorn->controller); + free(pDorn); + } +/*------------------------------------------------------------------------*/ + static int DornierInit(pVelSelDriv self, SConnection *pCon) + { + pDornier pDorn = NULL; + int iRet, iError; + float fRot; + char pError[80], pBueffel[256]; + + assert(self); + pDorn = (pDornier)self->pPrivate; + assert(pDorn); + + iRet = initRS232(pDorn->controller); + if(iRet < 0){ + return 1; + } + setRS232SendTerminator(pDorn->controller,"\n"); + setRS232Timeout(pDorn->controller,pDorn->iTimeOut); + setRS232Debug(pDorn->controller,1); + + /* + tell him that we want control. + Funny enough no or is sent in the reply to this. + */ + setRS232ReplyTerminator(pDorn->controller,"\\"); + iRet = transactRS232(pDorn->controller,"REM\n",4,pError,79); + setRS232ReplyTerminator(pDorn->controller,"\r\n"); + if(iRet != 1) + { + sprintf(pBueffel, + "ERROR: %s while switching velocity selector to remote", + pError); + SCWrite(pCon,pBueffel,eError); + } + /* + check which status the velo is in + */ + pDorn->statusMode = STATSEND; + GetDornierPos(self,&fRot); + if(fRot < 0){ + GetDornierPos(self,&fRot); + } + + return 1; + } +/*-------------------------------------------------------------------------*/ + pVelSelDriv VSCreateDornier2003(char *name, Tcl_Interp *pTcl) + { + pVelSelDriv pNew = NULL; + pDornier pDorn = NULL; + char *pPtr = NULL; + int iVal, iRet, iPort; + char pHost[132]; + + + /* the most likely error is the parameters specified are wrong! + So check this first. We''ll use Tcl's result for error reporting. + name is the name of an Tcl array which should hold the info + necessary + */ + + /* allocate a Dornier structure */ + pDorn = (pDornier)malloc(sizeof(Dornier)); + if(!pDorn) + { + return NULL; + } + memset(pDorn,0,sizeof(Dornier)); + + /* host name */ + pPtr = Tcl_GetVar2(pTcl,name,"Host",TCL_GLOBAL_ONLY); + if(!pPtr) + { + Tcl_AppendResult(pTcl,"ERROR: no hostname found in",name,NULL); + free(pDorn); + return NULL; + } + strncpy(pHost,pPtr,131); + + /* port number */ + pPtr = Tcl_GetVar2(pTcl,name,"Port",TCL_GLOBAL_ONLY); + if(!pPtr) + { + Tcl_AppendResult(pTcl,"ERROR: no port number found in",name,NULL); + free(pDorn); + return NULL; + } + iRet = Tcl_GetInt(pTcl,pPtr,&iPort); + if(iRet != TCL_OK) + { + free(pDorn); + return NULL; + } + + /* time out. This one gets defaulted when not specified */ + pPtr = Tcl_GetVar2(pTcl,name,"Timeout",TCL_GLOBAL_ONLY); + if(!pPtr) + { + pDorn->iTimeOut = 1000; + } + else + { + iRet = Tcl_GetInt(pTcl,pPtr,&iVal); + if(iRet != TCL_OK) + { + pDorn->iTimeOut = 1000; + } + pDorn->iTimeOut = iVal; + } + + /* minimum control speed */ + pPtr = Tcl_GetVar2(pTcl,name,"MinControl",TCL_GLOBAL_ONLY); + if(!pPtr) + { + pDorn->minRPM = 3100; + } + else + { + iRet = Tcl_GetInt(pTcl,pPtr,&iVal); + if(iRet != TCL_OK) + { + pDorn->minRPM = 3100; + } + pDorn->minRPM = iVal; + } + + + /* business as usual: allocate memory */ + pNew = (pVelSelDriv)malloc(sizeof(VelSelDriv)); + if(!pNew) + { + return NULL; + } + + /* zero the world */ + memset(pNew,0,sizeof(VelSelDriv)); + pNew->pPrivate = pDorn; + pDorn->controller = createRS232(pHost,iPort); + if(!pDorn->controller){ + DornierKill(pNew->pPrivate); + free(pNew); + return NULL; + } + + /* initialise function pointers */ + pNew->DeletePrivate = DornierKill; + pNew->Halt = DornierHalt; + pNew->GetError = DornierError; + pNew->TryAndFixIt = DornierFixIt; + pNew->GetRotation = GetDornierPos; + pNew->SetRotation = DornierRun; + pNew->GetStatus = DornierStatNew; + pNew->GetDriverText = DornierText; + pNew->GetLossCurrent = DornierLoss; + pNew->Init = DornierInit; + + /* done it */ + return pNew; + } + + + + + + + diff --git a/el734hp.c b/el734hp.c new file mode 100644 index 0000000..055eefa --- /dev/null +++ b/el734hp.c @@ -0,0 +1,447 @@ +/*------------------------------------------------------------------------ + This is another driver for the PSI EL734 motor controllers as used + at SINQ. The idea is that this one is performing better then the + other one which uses David Madens SerPortServer program. The + speedup is gained through: + - direct access to the controller + - reduction in the amount of data transferred + - in status: send first, read only when data available. Cannot do this: + up to 8 motors share a controller: I may get a status response for + a wrong motor or overload the controller with to many confusing status + requests. + + copyright: see file COPYRIGHT + + Mark Koennecke, July 2003 + -----------------------------------------------------------------------*/ +#include +#include +#include +#include +#include +#include +#include + + +/*----------------------------------------------------------------------- + The motor driver structure. Please note that the first set of fields has + be identical with the fields of AbstractModriv in ../modriv.h +------------------------------------------------------------------------*/ + typedef struct __MoDriv { + /* 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); + + + /* EL-734 specific fields */ + prs232 controller; + int iMotor; + float lastValue; + int errorCode; + int oredMsr; + } EL734Driv, *pEL734Driv; +/*------------------- error codes ----------------------------------*/ +#define BADADR -1 +#define BADBSY -2 +#define BADCMD -3 +#define BADLOC -4 +#define BADPAR -5 +#define BADRNG -6 +#define BADUNKNOWN -7 +#define BADSTP -8 +#define BADEMERG -9 +#define LOWLIM -10 +#define HILIM -11 +#define RUNFAULT -12 +#define POSFAULT -13 +#define BADCUSHION -14 +/*--------------------------------------------------------------------*/ +static int checkResponse(pEL734Driv self, char *pReply){ + /* + error messages start with ?, if none we are done + */ + if(strstr(pReply,"?") == NULL && strstr(pReply,"*") == NULL){ + return 1; + } + strtolower(pReply); + if(strstr(pReply,"?adr") != NULL){ + self->errorCode = BADADR; + } else if(strstr(pReply,"?bsy") != NULL){ + self->errorCode = BADBSY; + } else if(strstr(pReply,"?cmd") != NULL){ + self->errorCode = BADCMD; + } else if(strstr(pReply,"?loc") != NULL){ + self->errorCode = BADLOC; + } else if(strstr(pReply,"?par") != NULL){ + self->errorCode = BADPAR; + } else if(strstr(pReply,"?rng") != NULL){ + self->errorCode = BADRNG; + }else if(strstr(pReply,"*es") != NULL){ + self->errorCode = BADEMERG; + } else { + self->errorCode = BADUNKNOWN; + } + return 0; +} +/*---------------------------------------------------------------------*/ +static int EL734GetPos(void *pData, float *fPos){ + pEL734Driv self = NULL; + int status; + char pCommand[50],pReply[80]; + + self = (pEL734Driv)pData; + assert(self); + + snprintf(pCommand,79,"u %d\r",self->iMotor); + status = transactRS232(self->controller,pCommand,strlen(pCommand), + pReply,79); + if(status != 1){ + self->errorCode = status; + return HWFault; + } + if(!checkResponse(self,pReply)){ + return HWFault; + } + sscanf(pReply,"%f",fPos); + self->lastValue = *fPos; + return OKOK; +} +/*----------------------------------------------------------------------*/ +static int EL734Run(void *pData,float fValue){ + pEL734Driv self = NULL; + int status; + char pCommand[50],pReply[80]; + + self = (pEL734Driv)pData; + assert(self); + + self->oredMsr = 0; + snprintf(pCommand,79,"p %d %3.f\r",self->iMotor,fValue); + status = transactRS232(self->controller,pCommand,strlen(pCommand), + pReply,79); + if(status != 1){ + self->errorCode = status; + return HWFault; + } + if(!checkResponse(self,pReply)){ + return HWFault; + } + return OKOK; +} +/*-----------------------------------------------------------------------*/ +static int decodeMSR(pEL734Driv self, int msr){ + if(msr == 0){ + /* + we are done: check ored_msr for troubles + */ + if(self->oredMsr & 0x2){ + return HWIdle; + } else if(self->oredMsr & 0x10){ + self->errorCode = LOWLIM; + return HWFault; + } else if(self->oredMsr & 0x20){ + self->errorCode = HILIM; + return HWFault; + } else if(self->oredMsr & 0x80){ + self->errorCode = RUNFAULT; + return HWPosFault; + } else if(self->oredMsr & 0x200){ + self->errorCode = RUNFAULT; + return HWPosFault; + } else if(self->oredMsr & 0x1000){ + self->errorCode = BADCUSHION; + return HWFault; + } else if(self->oredMsr & 0x8){ + self->errorCode = BADSTP; + return HWFault; + } else if(self->oredMsr & 0x40) { + self->errorCode = BADSTP; + return HWFault; + } else if(self->oredMsr & 0x100){ + self->errorCode = POSFAULT; + return HWFault; + } else if(self->oredMsr & 0x400){ + self->errorCode = POSFAULT; + return HWFault; + } + } else { + /* + we are still tugging along ............ + */ + if(msr & 0x10){ + self->errorCode = LOWLIM; + return HWFault; + } else if(msr & 0x20){ + self->errorCode = HILIM; + return HWFault; + } else if(msr & 0x80){ + self->errorCode = RUNFAULT; + return HWPosFault; + } else if(self->oredMsr & 0x200){ + self->errorCode = RUNFAULT; + return HWPosFault; + } else if(msr & 0x1000){ + self->errorCode = BADCUSHION; + return HWFault; + } else if(msr & 0x8){ + self->errorCode = BADSTP; + return HWFault; + } else if(msr & 0x40) { + self->errorCode = BADSTP; + return HWFault; + } else if(msr & 0x100){ + self->errorCode = POSFAULT; + return HWFault; + } else if(msr & 0x400){ + self->errorCode = POSFAULT; + return HWFault; + } else { + return HWBusy; + } + } +} +/*------------------------------------------------------------------------*/ +static int EL734Status(void *pData){ + pEL734Driv self = NULL; + int status, msr; + char pCommand[50],pReply[80]; + + self = (pEL734Driv)pData; + assert(self); + + snprintf(pCommand,79,"msr %d\r",self->iMotor); + status = transactRS232(self->controller,pCommand,strlen(pCommand), + pReply,79); + if(status < 0){ + self->errorCode = status; + return HWFault; + } + if(!checkResponse(self,pReply)){ + return HWFault; + } + sscanf(pReply,"%x",&msr); + self->oredMsr |= msr; + return decodeMSR(self,msr); +} +/*----------------------------------------------------------------------*/ +static void EL734Error(void *pData, int *iCode, char *error, int errLen){ + pEL734Driv self = NULL; + self = (pEL734Driv)pData; + assert(self); + + *iCode = self->errorCode; + switch(*iCode){ + case BADADR: + strncpy(error,"Bad address",errLen); + break; + case BADBSY: + strncpy(error,"Motor still busy",errLen); + break; + case BADCMD: + strncpy(error,"Bad command",errLen); + break; + case BADLOC: + strncpy(error,"Motor controller is on local",errLen); + break; + case BADPAR: + strncpy(error,"Bad parameter",errLen); + break; + case BADRNG: + strncpy(error,"Bad range",errLen); + break; + case BADUNKNOWN: + strncpy(error,"Unknown error condition",errLen); + break; + case BADSTP: + strncpy(error,"Motor is stopped",errLen); + break; + case BADEMERG: + strncpy(error,"Emergency stop is engaged",errLen); + break; + case LOWLIM: + strncpy(error,"Crashed into lower limit switch",errLen); + break; + case HILIM: + strncpy(error,"Crashed into upper limit switch",errLen); + break; + case RUNFAULT: + strncpy(error,"Run fault detected",errLen); + break; + case POSFAULT: + strncpy(error,"Positioning fault detected",errLen); + break; + case BADCUSHION: + strncpy(error,"Air cushion problem",errLen); + break; + default: + getRS232Error(*iCode,error,errLen); + break; + } +} +/*----------------------------------------------------------------------*/ +static int EL734Fix(void *pData, int iCode, float fValue){ + pEL734Driv self = NULL; + int status, msr; + char pCommand[50],pReply[80]; + + self = (pEL734Driv)pData; + assert(self); + + switch(iCode){ + case BADADR: + case BADCMD: + case TIMEOUT: + case BADPAR: + case BADBSY: + return MOTREDO; + case BADLOC: + snprintf(pCommand,49,"RMT 1\r"); + transactRS232(self->controller,pCommand,strlen(pCommand),pReply,79); + return MOTREDO; + case NOTCONNECTED: + initRS232(self->controller); + return MOTREDO; + case RUNFAULT: + return MOTREDO; + } + return MOTFAIL; +} +/*----------------------------------------------------------------------*/ +static int EL734Halt(void *pData){ + pEL734Driv self = NULL; + int status; + char pCommand[50],pReply[80]; + + self = (pEL734Driv)pData; + assert(self); + + snprintf(pCommand,79,"s %d\r",self->iMotor); + status = transactRS232(self->controller,pCommand,strlen(pCommand), + pReply,79); + if(status != 1){ + self->errorCode = status; + return 0; + } + if(!checkResponse(self,pReply)){ + return 0; + } + return 1; +} +/*--------------------------------------------------------------------*/ +static int EL734GetPar(void *self, char *name, + float *fValue){ + return 0; +} +/*--------------------------------------------------------------------*/ +static int EL734SetPar(void *self, SConnection *pCon, + char *name, float newValue){ + return 0; +} +/*--------------------------------------------------------------------*/ +static void EL734List(void *self, char *name, SConnection *pCon){ + return; +} +/*---------------------------------------------------------------------*/ +static void KillEL734(void *pData){ + /* + the controller is owned by the controller object and will be + deleted when that object is removed + */ + return; +} +/*------------------------------------------------------------------*/ +MotorDriver *CreateEL734HP(SConnection *pCon, int argc, char *argv[]){ + pEL734Driv pNew = NULL; + int motor, status; + prs232 controller = NULL; + char pCommand[50],pReply[80]; + + /* + check arguments + */ + if(argc < 2){ + SCWrite(pCon,"ERROR: not enough arguments to create EL734HP driver", + eError); + return NULL; + } + controller = (prs232)FindCommandData(pServ->pSics,argv[0], + "RS232 Controller"); + if(!controller){ + SCWrite(pCon,"ERROR: motor controller not found",eError); + return NULL; + } + + motor = atoi(argv[1]); + if(motor < 0 || motor > 12){ + SCWrite(pCon,"ERROR: invalid motor number",eError); + return NULL; + } + + /* + allocate and initialize data structure + */ + pNew = (pEL734Driv)malloc(sizeof(EL734Driv)); + if(!pNew){ + SCWrite(pCon,"ERROR: no memory to allocate motor driver", + eError); + return NULL; + } + memset(pNew,0,sizeof(EL734Driv)); + pNew->GetPosition = EL734GetPos; + pNew->RunTo = EL734Run; + pNew->GetStatus = EL734Status; + pNew->GetError = EL734Error; + pNew->TryAndFixIt = EL734Fix; + pNew->Halt = EL734Halt; + pNew->GetDriverPar = EL734GetPar; + pNew->SetDriverPar = EL734SetPar; + pNew->ListDriverPar = EL734List; + pNew->KillPrivate = KillEL734; + pNew->controller = controller; + pNew->iMotor = motor; + + /* + connection will already have been set up, read limits + */ + snprintf(pCommand,49,"h %d\r",pNew->iMotor); + status = transactRS232(pNew->controller, pCommand,strlen(pCommand), + pReply,79); + if(!status){ + SCWrite(pCon,"ERROR: failed to read HW limits, defaulting..",eError); + pNew->fLower = -180.; + pNew->fUpper = 180.; + } else { + if(checkResponse(pNew,pReply)){ + sscanf(pReply,"%f %f",&pNew->fLower,&pNew->fUpper); + } else { + SCWrite(pCon, + "ERROR: invalid response when reading HW limits, defaulting..", + eError); + pNew->fLower = -180.; + pNew->fUpper = 180.; + } + } + return (MotorDriver *)pNew; +} + + + + + + diff --git a/el737driv.c b/el737driv.c index b36f99a..923227f 100644 --- a/el737driv.c +++ b/el737driv.c @@ -691,3 +691,13 @@ pCounterDriver CreateEL737Counter(SConnection *pCon, char *name, free(pEL737->host); } } + + + + + + + + + + diff --git a/el737hpdriv.c b/el737hpdriv.c new file mode 100644 index 0000000..44b4353 --- /dev/null +++ b/el737hpdriv.c @@ -0,0 +1,568 @@ +/*----------------------------------------------------------------------- + This is another driver for the EL737 counter box used at SINQ. The hp in + the name is for high performance, though this only a promise and not yet + proven. This version connects directly to the RS232 port of the counter + box on the terminal server rather then working with David Maden's + SerPortServer program. Other tweaks will be implemented as well, such as + reading the monitors only now and then and not on all calls. + + Mark Koennecke, July 2003 + -------------------------------------------------------------------------*/ +#include +#include +#include +#include +#include +#include +#include +#include + +#define MONTHRESH 20 + +#define STATSEND 0 +#define STATRECEIVE 2 +/*----------------------------------------------------------------------- + our own data struture + ------------------------------------------------------------------------*/ +typedef struct { + prs232 controller; + int monitorCount; /* read monitors if this is above MONTHRESH */ + float cachedControl; + int errorCode; + int finishCount; /* need RS = 0 2 times before really sure finished */ + int statusMode; +} EL737hp, *pEL737hp; +/*--------------------- ERROR CODES -------------------------------------*/ +#define OFFLINE -1 +#define BADRANGE -3 +#define BADCOMMAND -4 +#define BADPARAM -5 +#define NOPARAM -7 +#define TOMANYCOUNTS -8 +#define SYSERROR -9 +#define BADREPLY -10 +#define SELECTFAIL -11 +/*----------------------------------------------------------------------- + search errors in a reply from the EL737. Returns 1 on success or a + negative error code in case of trouble. + ------------------------------------------------------------------------*/ +static int checkEL737Error(char *pReply){ + + /* + all error start with a ?, if no ? in reply, answer is OK! + */ + if(strstr(pReply,"?") == NULL){ + return 1; + } + + /* + Now there is an error and we have to identify it + */ + if(strstr(pReply,"?OF") != NULL){ + return OFFLINE; + } else if(strstr(pReply,"?OV") != NULL){ + return OVERFLOW; + } else if(strstr(pReply,"?1") != NULL){ + return BADRANGE; + } else if(strstr(pReply,"?2") != NULL){ + return BADCOMMAND; + } else if(strstr(pReply,"?3") != NULL){ + return BADPARAM; + } else if(strstr(pReply,"?4") != NULL){ + return BADCOUNTER; + } else if(strstr(pReply,"?5") != NULL){ + return NOPARAM; + } else if(strstr(pReply,"?6") != NULL){ + return TOMANYCOUNTS; + } else { + return SYSERROR; + } +} +/*--------------------------------------------------------------- + fixMode checks if we are in STATRECEIVE mode, reads any pending + data and sets the mode to STATSEND. This would fix the problem + if another client wishes to give a command while we are expecting + a status response + ---------------------------------------------------------------*/ +static void fixMode(pEL737hp pPriv){ + char pBuffer[256]; + int len = 255; + + if(pPriv->statusMode == STATRECEIVE){ + readRS232TillTerm(pPriv->controller,pBuffer,&len); + pPriv->statusMode = STATSEND; + } +} +/*---------------------------------------------------------------*/ +static int EL737Command(pEL737hp pPriv, char *pCommand, + char *pReply, int replylen){ + int status; + + status = transactRS232(pPriv->controller,pCommand,strlen(pCommand), + pReply,replylen); + if(status < 0){ + pPriv->errorCode = status; + return 0; + } + status = checkEL737Error(pReply); + if(status < 0){ + pPriv->errorCode = status; + return 0; + } + return 1; +} +/*----------------------------------------------------------------*/ +static int readRS(pEL737hp pPriv, int *RS){ + int status, len = 131; + char reply[132]; + + status = readRS232TillTerm(pPriv->controller, + reply,&len); + if(status < 0) { + pPriv->errorCode = status; + return 0; + } + status = checkEL737Error(reply); + if(status < 0){ + pPriv->errorCode = status; + return 0; + } + status = sscanf(reply,"%d",RS); + if(status < 1){ + pPriv->errorCode = BADREPLY; + return 0; + } + return 1; +} +/*-----------------------------------------------------------------*/ +static int decodeRS(pEL737hp pPriv, int RS){ + int returnValue; + + switch(RS){ + case 0: + pPriv->finishCount++; + if(pPriv->finishCount > 2){ + returnValue = HWIdle; + } else { + returnValue = HWBusy; + } + break; + case 1: + case 2: + pPriv->finishCount = 0; + returnValue = HWBusy; + break; + case 5: + case 6: + pPriv->finishCount = 0; + returnValue = HWNoBeam; + break; + default: + pPriv->finishCount = 0; + returnValue = HWPause; + break; + } + return returnValue; +} +/*-----------------------------------------------------------------*/ +static int updateMonitors(struct __COUNTER *self){ + int status; + int m1,m2,m3,m4,m5,m6,m7,m8; + float fTime; + pEL737hp pPriv = NULL; + char reply[132]; + + pPriv = (pEL737hp)self->pData; + + if(!EL737Command(pPriv,"RA\r",reply,131)){ + return 0; + } + + /* + There are two forms of RA replys: new form with 8 monitors + */ + status = sscanf(reply,"%f %d %d %d %d %d %d %d %d", + &fTime,&m1,&m2,&m3,&m4,&m5,&m6,&m7,&m8); + if(status != 9){ + /* + old form with 4 monitors + */ + status = sscanf(reply,"%d %d %d %d %f",&m1,&m2,&m3,&m4,&fTime); + if(status != 5){ + pPriv->errorCode = BADREPLY; + return 0; + } + } + self->lCounts[0] = m2; + self->lCounts[1] = m1; + self->lCounts[2] = m3; + self->lCounts[3] = m4; + self->lCounts[4] = m5; + self->lCounts[5] = m6; + self->lCounts[6] = m7; + self->lCounts[7] = m8; + self->fTime = fTime; + + if(self->eMode == eTimer){ + pPriv->cachedControl = fTime; + } else { + pPriv->cachedControl = m2; + } + return 1; +} +/*------------------------------------------------------------------*/ +static int EL737Status(struct __COUNTER *self, float *fControl){ + int status, RS, returnValue; + pEL737hp pPriv = NULL; + + assert(self); + pPriv = (pEL737hp)self->pData; + + /* + handle STATSEND mode + */ + if(pPriv->statusMode == STATSEND){ + writeRS232(pPriv->controller,"RS\r",3); + pPriv->statusMode = STATRECEIVE; + *fControl = pPriv->cachedControl; + return HWBusy; + } + + /* + now we are dealing with STATRECEIVE mode. + Check for data availability first. + */ + status = availableNetRS232(pPriv->controller); + if(status == 0){ + *fControl = pPriv->cachedControl; + return HWBusy; + } else if(status < 0) { + *fControl = pPriv->cachedControl; + pPriv->statusMode = STATSEND; + pPriv->errorCode = SELECTFAIL; + return HWFault; + } + + /* + The snail in the counter box has replied. Read and process + the data + */ + pPriv->statusMode = STATSEND; + if(!readRS(pPriv,&RS)){ + return HWFault; + } + + /* + decode it + */ + returnValue = decodeRS(pPriv,RS); + + /* + check if we update the monitors and do it + */ + pPriv->monitorCount++; + if(pPriv->monitorCount > MONTHRESH){ + status = updateMonitors(self); + pPriv->monitorCount = 0; + if(!status){ + return HWFault; + } + } + + *fControl = pPriv->cachedControl; + return returnValue; +} +/*-------------------------------------------------------------------*/ +static int EL737Start(struct __COUNTER *self){ + pEL737hp pPriv = NULL; + int status; + char pCommand[50], pReply[30]; + + assert(self); + pPriv = (pEL737hp)self->pData; + + fixMode(pPriv); + if(self->eMode == ePreset){ + snprintf(pCommand,49,"MP %d\r",(int)nintf(self->fPreset)); + } else { + snprintf(pCommand,49,"TP %.2f\r", self->fPreset); + } + if(EL737Command(pPriv,pCommand,pReply,29) != 1){ + return 0; + } + pPriv->finishCount = 0; + return 1; +} +/* --------------------------------------------------------------------*/ +static int EL737Pause(struct __COUNTER *self){ + pEL737hp pPriv = NULL; + int status; + char pCommand[50], pReply[30]; + + assert(self); + pPriv = (pEL737hp)self->pData; + + fixMode(pPriv); + return EL737Command(pPriv,"PS\r",pReply,29); +} +/*----------------------------------------------------------------------*/ +static int EL737Continue(struct __COUNTER *self){ + pEL737hp pPriv = NULL; + int status; + char pCommand[50], pReply[30]; + + assert(self); + pPriv = (pEL737hp)self->pData; + + fixMode(pPriv); + return EL737Command(pPriv,"CO\r",pReply,29); +} +/*---------------------------------------------------------------------*/ +static int EL737Halt(struct __COUNTER *self){ + pEL737hp pPriv = NULL; + int status; + char pCommand[50], pReply[30]; + + assert(self); + pPriv = (pEL737hp)self->pData; + + fixMode(pPriv); + return EL737Command(pPriv,"S\r",pReply,29); +} +/*-------------------------------------------------------------------*/ +static int EL737Transfer(struct __COUNTER *self){ + pEL737hp pPriv = NULL; + assert(self); + pPriv = (pEL737hp)self->pData; + + fixMode(pPriv); + return updateMonitors(self); +} +/*--------------------------------------------------------------------*/ +static int EL737GetError(struct __COUNTER *self, int *iCode, + char *pError, int errLen){ + pEL737hp pPriv = NULL; + assert(self); + pPriv = (pEL737hp)self->pData; + + *iCode = pPriv->errorCode; + switch(pPriv->errorCode){ + case OFFLINE: + strncpy(pError,"EL737 is offline",errLen); + break; + case BADRANGE: + strncpy(pError,"EL737 parameter is out of range",errLen); + break; + case BADCOMMAND: + strncpy(pError,"EL737 received unknown command or is busy",errLen); + break; + case BADPARAM: + strncpy(pError,"EL737 parameter is awful",errLen); + break; + case NOPARAM: + strncpy(pError,"EL737 parameter missing",errLen); + break; + case TOMANYCOUNTS: + strncpy(pError,"EL737 counters overflowed",errLen); + break; + case SYSERROR: + strncpy(pError,"EL737 has an internal system error",errLen); + break; + case BADREPLY: + strncpy(pError,"EL737 sent an unexpected reply",errLen); + break; + case SELECTFAIL: + strncpy(pError,"select system call failed, network trouble",errLen); + default: + getRS232Error(pPriv->errorCode,pError,errLen); + } + return 1; +} +/*--------------------------------------------------------------------*/ +static int EL737FixIt(struct __COUNTER *self, int iCode){ + pEL737hp pPriv = NULL; + int status; + char pReply[50]; + + assert(self); + pPriv = (pEL737hp)self->pData; + + switch(iCode){ + case TIMEOUT: + case BADREPLY: + case BADPARAM: + case NOPARAM: + case BADRANGE: + return COREDO; + break; + case OFFLINE: + EL737Command(pPriv,"RMT 1\r",pReply,49); + EL737Command(pPriv,"echo 2\r",pReply,49); + return COREDO; + break; + case BADCOMMAND: /* can be busy, stop it and try again */ + EL737Command(pPriv,"S\r",pReply,49); + return COREDO; + break; + case TOMANYCOUNTS: + case SYSERROR: + return COTERM; + break; + default: + /* + network problem; try to reopen + */ + status = initRS232(pPriv->controller); + if(status != 1){ + return COTERM; + } else { + return COREDO; + } + } +} +/*------------------------------------------------------------------------*/ +static int EL737Set(struct __COUNTER *self, char *name, int iCter, + float fVal){ + pEL737hp pPriv = NULL; + int status; + char pCommand[80], pReply[50]; + + assert(self); + pPriv = (pEL737hp)self->pData; + + fixMode(pPriv); + if(strcmp(name,"threshold") == 0){ + sprintf(pCommand,"DL %1.1d %f\r",iCter, fVal); + if(!EL737Command(pPriv,pCommand,pReply,49)){ + return HWFault; + } + sprintf(pCommand,"DR %1.1d\r",iCter); + if(!EL737Command(pPriv,pCommand,pReply,49)){ + return HWFault; + } + return OKOK; + } else { + self->iErrorCode = UNKNOWNPAR; + return HWFault; + } +} +/*----------------------------------------------------------------------*/ +static int EL737Get(struct __COUNTER *self, char *name, int iCter, + float *fVal){ + pEL737hp pPriv = NULL; + int status; + char pCommand[80], pReply[50]; + + assert(self); + pPriv = (pEL737hp)self->pData; + + fixMode(pPriv); + if(strcmp(name,"threshold") == 0){ + sprintf(pCommand,"DL %1.1d\r",iCter); + if(!EL737Command(pPriv,pCommand,pReply,49)){ + return HWFault; + } + sscanf(pReply,"%f", fVal); + return OKOK; + } else { + self->iErrorCode = UNKNOWNPAR; + return HWFault; + } +} +/*--------------------------------------------------------------------*/ +static int EL737Send(struct __COUNTER *self, char *pText, char *pReply, + int iReplyLen){ + pEL737hp pPriv = NULL; + + assert(self); + pPriv = (pEL737hp)self->pData; + + fixMode(pPriv); + return EL737Command(pPriv,pText,pReply,iReplyLen); +} +/*---------------------------------------------------------------------*/ +static void KillHP(pCounterDriver self){ + pEL737hp pPriv = NULL; + + assert(self); + pPriv = (pEL737hp)self->pData; + + if(!pPriv){ + return; + } + if(pPriv->controller != NULL){ + KillRS232(pPriv->controller); + } + free(pPriv); +} +/*-------------------------------------------------------------------*/ +pCounterDriver MakeEL737HP(SConnection *pCon, char *name, + int argc, char *argv[]){ + pCounterDriver pNew = NULL; + pEL737hp pPriv = NULL; + char pHost[132]; + int port, status; + + /* + check arguments + */ + if(argc < 2) { + SCWrite(pCon,"ERROR: insufficient no af arguments to create EL737HP", + eError); + return NULL; + } + if(!isNumeric(argv[1])){ + SCWrite(pCon,"ERROR: expected numeric argument for port number", + eError); + return NULL; + } + port = atoi(argv[1]); + strncpy(pHost,argv[0],131); + + /* + allocate a bank worth of memory ........... + */ + pNew = CreateCounterDriver(name,"EL737HP"); + pPriv = (pEL737hp)malloc(sizeof(EL737hp)); + if(!pNew || !pPriv){ + return NULL; + } + memset(pPriv,0,sizeof(EL737hp)); + pPriv->controller = createRS232(pHost,port); + if(!pPriv->controller){ + DeleteCounterDriver(pNew); + return NULL; + } + + /* assign functions */ + pNew->GetStatus = EL737Status; + pNew->Start = EL737Start; + pNew->Halt = EL737Halt; + pNew->ReadValues = EL737Transfer; + pNew->GetError = EL737GetError; + pNew->TryAndFixIt = EL737FixIt; + pNew->Pause = EL737Pause; + pNew->Continue = EL737Continue; + pNew->Set = EL737Set; + pNew->Get = EL737Get; + pNew->Send = EL737Send; + pNew->KillPrivate = KillHP; + pNew->iNoOfMonitors = 7; + pNew->fTime = 0.; + pNew->pData = pPriv; + + /* + initialize connection + */ + setRS232Debug(pPriv->controller,0); + setRS232ReplyTerminator(pPriv->controller,"\r"); + status = initRS232(pPriv->controller); + status = EL737Command(pPriv,"RMT 1\r",pHost,131); + status = EL737Command(pPriv,"RMT 1\r",pHost,131); + status = EL737Command(pPriv,"ECHO 2\r",pHost,131); + + return pNew; +} + + + diff --git a/hardsup/el737_utility.c b/hardsup/el737_utility.c index 383ea83..6ed6010 100644 --- a/hardsup/el737_utility.c +++ b/hardsup/el737_utility.c @@ -1740,3 +1740,26 @@ return False; /* Error detected in EL737_GetStatus */ } /*-------------------------------------------- End of EL737_Utility.C =======*/ + + + + + + + + + + + + + + + + + + + + + + + diff --git a/hardsup/makefile_alpha b/hardsup/makefile_alpha index 3c58898..d15f5ce 100644 --- a/hardsup/makefile_alpha +++ b/hardsup/makefile_alpha @@ -5,9 +5,8 @@ # Mark Koennecke, November 1996 # Markus Zolliker, March 2003 #-------------------------------------------------------------------------- -# the following line only for fortified version -#DFORTIFY=-DFORTIFY -#========================================================================== + +include ../../alpha_def CC = cc CFLAGS = -std1 -I../.. -g $(DFORTIFY) -I$(SRC).. -I$(SRC). diff --git a/make_gen b/make_gen index 116e5a5..5f6fdaf 100644 --- a/make_gen +++ b/make_gen @@ -14,7 +14,7 @@ OBJ=psi.o buffer.o ruli.o dmc.o nxsans.o nextrics.o sps.o pimotor.o \ velodornier.o docho.o sanscook.o tecsdriv.o itc4driv.o itc4.o\ bruker.o ltc11.o A1931.o dilludriv.o eurodriv.o slsmagnet.o \ el755driv.o amorscan.o serial.o scontroller.o t_update.o \ - t_rlp.o t_conv.o + t_rlp.o t_conv.o el737hpdriv.o dornier2.o el734hp.o libpsi.a: $(OBJ) - rm libpsi.a diff --git a/makefile_alpha b/makefile_alpha index b54e224..96890cc 100644 --- a/makefile_alpha +++ b/makefile_alpha @@ -4,11 +4,8 @@ # # Mark Koennecke, June 2003 #-------------------------------------------------------------------------- -# the following line only for fortified version -#DFORTIFY=-DFORTIFY -#========================================================================== +include ../alpha_def -HDFROOT=/data/lnslib CC = cc CFLAGS = -std1 -g $(DFORTIFY) -I.. -I$(HDFROOT)/include -DHDF4 -DHDF5 \ -Ihardsup diff --git a/psi.c b/psi.c index 36e643f..8545902 100644 --- a/psi.c +++ b/psi.c @@ -101,6 +101,7 @@ static void RemovePsiCommands(SicsInterp *pSics){ /*---------------------------------------------------------------------*/ MotorDriver *CreateEL734(SConnection *pCon, int argc, char *argv[]); MotorDriver *CreateEL734DC(SConnection *pCon, int argc, char *argv[]); + MotorDriver *CreateEL734HP(SConnection *pCon, int argc, char *argv[]); /*-------------------------------------------------------------------*/ static pMotor CreatePsiMotor(SConnection *pCon, int argc, char *argv[]){ MotorDriver *pDriver = NULL; @@ -134,6 +135,18 @@ static pMotor CreatePsiMotor(SConnection *pCon, int argc, char *argv[]){ SCWrite(pCon,pBueffel,eError); return NULL; } + } else if(strcmp(argv[1],"el734hp") == 0){ + pDriver = (MotorDriver *)CreateEL734HP(pCon,argc-2,&argv[2]); + if(!pDriver){ + return NULL; + } + /* create the motor */ + pNew = MotorInit("EL734HP",argv[0],pDriver); + if(!pNew){ + sprintf(pBueffel,"Failure to create motor %s",argv[1]); + SCWrite(pCon,pBueffel,eError); + return NULL; + } } else if(strcmp(argv[1],"el734dc") == 0){ pDriver = (MotorDriver *)CreateEL734DC(pCon,argc-2,&argv[2]); if(!pDriver){ @@ -164,6 +177,8 @@ static pMotor CreatePsiMotor(SConnection *pCon, int argc, char *argv[]){ /*-------------------------------------------------------------------*/ extern pCounterDriver CreateEL737Counter(SConnection *pCon, char *name, int argc, char *argv[]); +extern pCounterDriver MakeEL737HP(SConnection *pCon, char *name, + int argc, char *argv[]); /*-------------------------------------------------------------------*/ static pCounterDriver CreatePsiCounterDriver(SConnection *pCon, int argc, @@ -175,6 +190,8 @@ static pCounterDriver CreatePsiCounterDriver(SConnection *pCon, */ if(strcmp(argv[2],"el737") == 0){ pNew = CreateEL737Counter(pCon,argv[1],argc-3,&argv[3]); + } else if(strcmp(argv[2],"el737hp") == 0){ + pNew = MakeEL737HP(pCon,argv[1],argc-3,&argv[3]); } else if(strcmp(argv[2],"ecb") == 0){ if(argc < 4){ SCWrite(pCon, @@ -199,12 +216,15 @@ static HistDriver *CreatePsiHistMem(char *name, pStringDict pOptions){ } /*-------------------------------------------------------------------*/ extern pVelSelDriv VSCreateDornierSINQ(char *name,Tcl_Interp *pTcl); + extern pVelSelDriv VSCreateDornier2003(char *name,Tcl_Interp *pTcl); /*-------------------------------------------------------------------*/ static pVelSelDriv CreatePsiVelSelDriv(char *name, char *array, Tcl_Interp *pTcl){ pVelSelDriv pNew = NULL; if(strcmp(name,"dornier") == 0){ pNew = VSCreateDornierSINQ(array,pTcl); + } else if(strcmp(name,"dornier2003") == 0){ + pNew = VSCreateDornier2003(array,pTcl); } return pNew; } diff --git a/tecs/makefile_alpha b/tecs/makefile_alpha index c9b8eb9..1944257 100644 --- a/tecs/makefile_alpha +++ b/tecs/makefile_alpha @@ -4,11 +4,8 @@ # # Markus Zolliker, March 2003 #-------------------------------------------------------------------------- -# the following lines only for fortified version -#DFORTIFY=-DFORTIFY -I$(SRC).. -#FORTIFYOBJ=../strdup.o ../fortify.o -#========================================================================== +include ../../alpha_def SICS=src/.. diff --git a/velodorn.c b/velodorn.c index af1d788..766e158 100644 --- a/velodorn.c +++ b/velodorn.c @@ -7,6 +7,11 @@ Mark Koennecke, Juli 1997 + Updated to decode the new dornier status messages as coughed up by the new + style Dornier software. + + Mark Koennecke, July 2003 + Copyright: Labor fuer Neutronenstreuung @@ -89,6 +94,95 @@ strcpy(pResult->echo,(const char *)ptr_token); ptr_src += strlen(ptr_token); + ptr_src = NULL; /* necessary for further search with strtok */ + for (;;) + { + /* read text till next separator '/' */ + ptr_token = strtok(ptr_src, tok_c); + if (ptr_token == NULL) break; + strcpy(tok_buf,ptr_token); + + for (key_id = 0; key_id<=15; key_id++) + { + /* search key ? */ + sl = strlen(keys[key_id]); + if (strncmp(&keys[key_id][0], tok_buf, sl) == 0) + { + /* step over key */ + for (cnt=0;cnt+sl < TOK_BUF_L; cnt++) + tok_buf[cnt] = tok_buf[cnt+sl]; + switch (key_id) + { + case 0: {strcpy(pResult->rm, tok_buf); break;} + case 1: {sscanf(tok_buf,"%d",&pResult->nom_rpm); break;} + case 2: {sscanf(tok_buf,"%d",&pResult->cur_rpm); break;} + case 3: {sscanf(tok_buf,"%d",&pResult->pwr); break;} + case 4: {sscanf(tok_buf,"%f",&pResult->curr); break;} + case 5: {sscanf(tok_buf,"%d",&pResult->rot_temp); break;} + case 6: {sscanf(tok_buf,"%d",&pResult->cont_temp); break;} + case 7: {sscanf(tok_buf,"%d",&pResult->inl_temp); break;} + case 8: {sscanf(tok_buf,"%d",&pResult->outl_temp); break;} + case 9: {sscanf(tok_buf,"%f",&pResult->cool_wat); break;} + case 10: {sscanf(tok_buf,"%f",&pResult->vacuum); break;} + case 11: {sscanf(tok_buf,"%f",&pResult->accel); break;} + case 12: { + if (strcmp(tok_buf, ena_str) == 0) + {pResult->komm = 1; break;} + if (strcmp(tok_buf, dis_str) == 0) + {pResult->komm = 0;break;} + break; + } + case 13: break; /* date */ + case 14: break; /* time */ + case 15: {sscanf(tok_buf,"%d",&pResult->iHz); break;} + } + } + } + } + return(1); + } +/*--------------------------- analyse Dornier status string ---------------- + This is the version for the NGS037 software from Dornier. Main difference + is that the keycodes are in germlish. + -------------------------------------------------------------------------*/ + int DecodeNewDornierStatus(char *pText, pDornierStatus pResult) + { + int cnt, key_id, sl, sts; + long err; + char ena_str[] = "ENABLED"; + char dis_str[] = "DISABLED"; + char keys[16][14] = + { + "MODE:\0 ", + "R_SPEED:\0 ", + "A_SPEED:\0 ", + "P_LOSS:\0 ", + "R_Current:\0 ", + "T_ROT:\0 ", + "T_HHH:\0 ", + "T_INL:\0 ", + "T_OUT:\0", + "F_RATE:\0", + "A_Vac:\0 ", + "V_OSC:\0 ", + "COM: \0 ", + "DATE: \0 ", + "TIME: \0 ", + "Hz:\0 "}; + + char tok_buf[TOK_BUF_L], *ptr_token, *ptr_src, *ptr; + const char tok_c[] = "/\\\0"; + char status[255]; + + ptr_src = pText; + memset(pResult,0,sizeof(DornierStatus)); + + /* skip over first token, should be command echo */ + ptr_token = strtok(ptr_src, tok_c); + if (ptr_token == NULL) return 0; /* error */ + strcpy(pResult->echo,(const char *)ptr_token); + ptr_src += strlen(ptr_token); + ptr_src = NULL; /* necessary for further search with strtok */ for (;;) { diff --git a/velodorn.h b/velodorn.h index 71ae40a..69b06e0 100644 --- a/velodorn.h +++ b/velodorn.h @@ -1,5 +1,5 @@ -#line 46 "velodorn.w" +#line 47 "velodorn.w" /*--------------------------------------------------------------------------- V E L O D O R N @@ -9,6 +9,8 @@ Mark Koennecke, Juli 1997 + updated to support new format fo status messages, Mark Koennecke, July 2003 + copyright: see implementation file. ------------------------------------------------------------------------------*/ #ifndef VELODORN @@ -48,8 +50,9 @@ int GetDornierStatus(void **pData, pDornierStatus pDornier); int DornierSend(void **pData, char *pCommand, char *pReply, int iLen); + int DecodeNewDornierStatus(char *pText, pDornierStatus pDornier); -#line 89 "velodorn.w" +#line 92 "velodorn.w" #endif diff --git a/velodorn.w b/velodorn.w index c80387f..dc5a699 100644 --- a/velodorn.w +++ b/velodorn.w @@ -41,6 +41,7 @@ done in the DornierStat function. @d dh @{ int GetDornierStatus(void **pData, pDornierStatus pDornier); int DornierSend(void **pData, char *pCommand, char *pReply, int iLen); + int DecodeNewDornierStatus(char *pText, pDornierStatus pDornier); @} @o velodorn.h -d @{ @@ -52,6 +53,8 @@ done in the DornierStat function. Mark Koennecke, Juli 1997 + updated to support new format fo status messages, Mark Koennecke, July 2003 + copyright: see implementation file. ------------------------------------------------------------------------------*/ #ifndef VELODORN