- New drivers for EL737 and EL734 high performance

- Changes to makefiles
This commit is contained in:
cvs
2003-07-08 13:26:54 +00:00
parent cd13637987
commit 3a45c3051d
13 changed files with 1785 additions and 14 deletions

610
dornier2.c Normal file
View File

@ -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 <cr>,
command responses tend to come back with a \ and no <cr>!
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 <sics.h>
#include <string.h>
#include <math.h>
#include <tcl.h>
#include <time.h>
#include <fortify.h>
#include <rs232controller.h>
typedef struct __VelSelDriv *pVelSelDriv;
#include <velodriv.h>
#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 <cr> or <nl> 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;
}

447
el734hp.c Normal file
View File

@ -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 <stdlib.h>
#include <assert.h>
#include <string.h>
#include <fortify.h>
#include <sics.h>
#include <modriv.h>
#include <rs232controller.h>
/*-----------------------------------------------------------------------
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;
}

View File

@ -691,3 +691,13 @@ pCounterDriver CreateEL737Counter(SConnection *pCon, char *name,
free(pEL737->host); free(pEL737->host);
} }
} }

568
el737hpdriv.c Normal file
View File

@ -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 <stdlib.h>
#include <assert.h>
#include <math.h>
#include <fortify.h>
#include <string.h>
#include <sics.h>
#include <rs232controller.h>
#include <countdriv.h>
#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;
}

View File

@ -1740,3 +1740,26 @@
return False; /* Error detected in EL737_GetStatus */ return False; /* Error detected in EL737_GetStatus */
} }
/*-------------------------------------------- End of EL737_Utility.C =======*/ /*-------------------------------------------- End of EL737_Utility.C =======*/

View File

@ -5,9 +5,8 @@
# Mark Koennecke, November 1996 # Mark Koennecke, November 1996
# Markus Zolliker, March 2003 # Markus Zolliker, March 2003
#-------------------------------------------------------------------------- #--------------------------------------------------------------------------
# the following line only for fortified version
#DFORTIFY=-DFORTIFY include ../../alpha_def
#==========================================================================
CC = cc CC = cc
CFLAGS = -std1 -I../.. -g $(DFORTIFY) -I$(SRC).. -I$(SRC). CFLAGS = -std1 -I../.. -g $(DFORTIFY) -I$(SRC).. -I$(SRC).

View File

@ -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\ velodornier.o docho.o sanscook.o tecsdriv.o itc4driv.o itc4.o\
bruker.o ltc11.o A1931.o dilludriv.o eurodriv.o slsmagnet.o \ bruker.o ltc11.o A1931.o dilludriv.o eurodriv.o slsmagnet.o \
el755driv.o amorscan.o serial.o scontroller.o t_update.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) libpsi.a: $(OBJ)
- rm libpsi.a - rm libpsi.a

View File

@ -4,11 +4,8 @@
# #
# Mark Koennecke, June 2003 # Mark Koennecke, June 2003
#-------------------------------------------------------------------------- #--------------------------------------------------------------------------
# the following line only for fortified version include ../alpha_def
#DFORTIFY=-DFORTIFY
#==========================================================================
HDFROOT=/data/lnslib
CC = cc CC = cc
CFLAGS = -std1 -g $(DFORTIFY) -I.. -I$(HDFROOT)/include -DHDF4 -DHDF5 \ CFLAGS = -std1 -g $(DFORTIFY) -I.. -I$(HDFROOT)/include -DHDF4 -DHDF5 \
-Ihardsup -Ihardsup

20
psi.c
View File

@ -101,6 +101,7 @@ static void RemovePsiCommands(SicsInterp *pSics){
/*---------------------------------------------------------------------*/ /*---------------------------------------------------------------------*/
MotorDriver *CreateEL734(SConnection *pCon, int argc, char *argv[]); MotorDriver *CreateEL734(SConnection *pCon, int argc, char *argv[]);
MotorDriver *CreateEL734DC(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[]){ static pMotor CreatePsiMotor(SConnection *pCon, int argc, char *argv[]){
MotorDriver *pDriver = NULL; MotorDriver *pDriver = NULL;
@ -134,6 +135,18 @@ static pMotor CreatePsiMotor(SConnection *pCon, int argc, char *argv[]){
SCWrite(pCon,pBueffel,eError); SCWrite(pCon,pBueffel,eError);
return NULL; 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){ } else if(strcmp(argv[1],"el734dc") == 0){
pDriver = (MotorDriver *)CreateEL734DC(pCon,argc-2,&argv[2]); pDriver = (MotorDriver *)CreateEL734DC(pCon,argc-2,&argv[2]);
if(!pDriver){ if(!pDriver){
@ -164,6 +177,8 @@ static pMotor CreatePsiMotor(SConnection *pCon, int argc, char *argv[]){
/*-------------------------------------------------------------------*/ /*-------------------------------------------------------------------*/
extern pCounterDriver CreateEL737Counter(SConnection *pCon, char *name, extern pCounterDriver CreateEL737Counter(SConnection *pCon, char *name,
int argc, char *argv[]); int argc, char *argv[]);
extern pCounterDriver MakeEL737HP(SConnection *pCon, char *name,
int argc, char *argv[]);
/*-------------------------------------------------------------------*/ /*-------------------------------------------------------------------*/
static pCounterDriver CreatePsiCounterDriver(SConnection *pCon, static pCounterDriver CreatePsiCounterDriver(SConnection *pCon,
int argc, int argc,
@ -175,6 +190,8 @@ static pCounterDriver CreatePsiCounterDriver(SConnection *pCon,
*/ */
if(strcmp(argv[2],"el737") == 0){ if(strcmp(argv[2],"el737") == 0){
pNew = CreateEL737Counter(pCon,argv[1],argc-3,&argv[3]); 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){ } else if(strcmp(argv[2],"ecb") == 0){
if(argc < 4){ if(argc < 4){
SCWrite(pCon, SCWrite(pCon,
@ -199,12 +216,15 @@ static HistDriver *CreatePsiHistMem(char *name, pStringDict pOptions){
} }
/*-------------------------------------------------------------------*/ /*-------------------------------------------------------------------*/
extern pVelSelDriv VSCreateDornierSINQ(char *name,Tcl_Interp *pTcl); extern pVelSelDriv VSCreateDornierSINQ(char *name,Tcl_Interp *pTcl);
extern pVelSelDriv VSCreateDornier2003(char *name,Tcl_Interp *pTcl);
/*-------------------------------------------------------------------*/ /*-------------------------------------------------------------------*/
static pVelSelDriv CreatePsiVelSelDriv(char *name, char *array, static pVelSelDriv CreatePsiVelSelDriv(char *name, char *array,
Tcl_Interp *pTcl){ Tcl_Interp *pTcl){
pVelSelDriv pNew = NULL; pVelSelDriv pNew = NULL;
if(strcmp(name,"dornier") == 0){ if(strcmp(name,"dornier") == 0){
pNew = VSCreateDornierSINQ(array,pTcl); pNew = VSCreateDornierSINQ(array,pTcl);
} else if(strcmp(name,"dornier2003") == 0){
pNew = VSCreateDornier2003(array,pTcl);
} }
return pNew; return pNew;
} }

View File

@ -4,11 +4,8 @@
# #
# Markus Zolliker, March 2003 # 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/.. SICS=src/..

View File

@ -7,6 +7,11 @@
Mark Koennecke, Juli 1997 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: Copyright:
Labor fuer Neutronenstreuung Labor fuer Neutronenstreuung
@ -89,6 +94,95 @@
strcpy(pResult->echo,(const char *)ptr_token); strcpy(pResult->echo,(const char *)ptr_token);
ptr_src += strlen(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 */ ptr_src = NULL; /* necessary for further search with strtok */
for (;;) for (;;)
{ {

View File

@ -1,5 +1,5 @@
#line 46 "velodorn.w" #line 47 "velodorn.w"
/*--------------------------------------------------------------------------- /*---------------------------------------------------------------------------
V E L O D O R N V E L O D O R N
@ -9,6 +9,8 @@
Mark Koennecke, Juli 1997 Mark Koennecke, Juli 1997
updated to support new format fo status messages, Mark Koennecke, July 2003
copyright: see implementation file. copyright: see implementation file.
------------------------------------------------------------------------------*/ ------------------------------------------------------------------------------*/
#ifndef VELODORN #ifndef VELODORN
@ -48,8 +50,9 @@
int GetDornierStatus(void **pData, pDornierStatus pDornier); int GetDornierStatus(void **pData, pDornierStatus pDornier);
int DornierSend(void **pData, char *pCommand, char *pReply, int iLen); 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 #endif

View File

@ -41,6 +41,7 @@ done in the DornierStat function.
@d dh @{ @d dh @{
int GetDornierStatus(void **pData, pDornierStatus pDornier); int GetDornierStatus(void **pData, pDornierStatus pDornier);
int DornierSend(void **pData, char *pCommand, char *pReply, int iLen); int DornierSend(void **pData, char *pCommand, char *pReply, int iLen);
int DecodeNewDornierStatus(char *pText, pDornierStatus pDornier);
@} @}
@o velodorn.h -d @{ @o velodorn.h -d @{
@ -52,6 +53,8 @@ done in the DornierStat function.
Mark Koennecke, Juli 1997 Mark Koennecke, Juli 1997
updated to support new format fo status messages, Mark Koennecke, July 2003
copyright: see implementation file. copyright: see implementation file.
------------------------------------------------------------------------------*/ ------------------------------------------------------------------------------*/
#ifndef VELODORN #ifndef VELODORN