- Refactored site specific stuff into a site module - PSI specific stuff is now in the PSI directory. - The old version has been tagged with pre-ansto
401 lines
10 KiB
C
401 lines
10 KiB
C
/*--------------------------------------------------------------------------
|
|
|
|
Some code to make EL737 COUNTERS as used at SINQ available in TCL.
|
|
Just a wrapper around David Maden's COUNTER routines.
|
|
|
|
You are free to use and modify this software for noncommercial
|
|
usage.
|
|
|
|
No warranties or liabilities of any kind taken by me or my employer
|
|
|
|
Mark Koennecke July 1996
|
|
----------------------------------------------------------------------------*/
|
|
#include "sinq_prototypes.h"
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
/*
|
|
#include <timers.h>
|
|
*/
|
|
#include <tcl.h>
|
|
#include "el737_def.h"
|
|
|
|
#define True 1
|
|
#define False 0
|
|
|
|
typedef struct
|
|
{
|
|
void *pData; /* EL737 open struct */
|
|
} EL737st;
|
|
|
|
EXTERN int EL737Action(ClientData pDat, Tcl_Interp *i, int a, char *argv[]);
|
|
static void EL737Error2Text(char *pBuffer, int errcode);
|
|
|
|
/*---------------------------------------------------------------------------
|
|
Tcl has a high niceness level. It deletes a command properly when
|
|
exiting, reinitializing etc. I use this facility to kill off the
|
|
counter initialised in CterEL737.
|
|
---------------------------------------------------------------------------*/
|
|
EXTERN void EL737Murder(ClientData pData)
|
|
{
|
|
EL737st *pTa = (EL737st *)pData;
|
|
EL737_Close(&(pTa->pData));
|
|
free(pData);
|
|
}
|
|
/*----------------------------------------------------------------------------
|
|
CterEL737 is the main entry point for this stuff. It connects to a counter
|
|
and, on success, creates a new command with the name of the counter.
|
|
Syntax:
|
|
EL737 name host port channel
|
|
---------------------------------------------------------------------------*/
|
|
|
|
int CterEL737(ClientData clientData, Tcl_Interp *interp,
|
|
int argc, char *argv[])
|
|
{
|
|
int iRet;
|
|
EL737st *pEL737 = NULL;
|
|
int iPort, iChannel, iMotor;
|
|
char *pErr = NULL;
|
|
char pBueffel[80];
|
|
|
|
/* check arguments */
|
|
if(argc < 5)
|
|
{
|
|
Tcl_AppendResult(interp,
|
|
" Insufficient arguments: CterEL737 name host port channel"
|
|
, (char *) NULL);
|
|
return TCL_ERROR;
|
|
}
|
|
|
|
/* convert arguments */
|
|
iRet = Tcl_GetInt(interp,argv[3],&iPort);
|
|
if(iRet == TCL_ERROR)
|
|
{
|
|
Tcl_AppendResult(interp,"Need integer value for port",
|
|
(char *)NULL);
|
|
return iRet;
|
|
}
|
|
|
|
iRet = Tcl_GetInt(interp,argv[4],&iChannel);
|
|
if(iRet == TCL_ERROR)
|
|
{
|
|
Tcl_AppendResult(interp,"Need integer value for channel",
|
|
(char *)NULL);
|
|
return iRet;
|
|
}
|
|
|
|
/* make a new pointer, initialise EL737st */
|
|
pEL737 = (EL737st *)malloc(sizeof(EL737st));
|
|
if(pEL737 ==NULL)
|
|
{
|
|
Tcl_AppendResult(interp,"No memory in EL734",NULL);
|
|
return TCL_ERROR;
|
|
}
|
|
|
|
/* open the rotten Counter, finally */
|
|
iRet = EL737_Open(&(pEL737->pData), argv[2],iPort,iChannel);
|
|
if(iRet) /* success */
|
|
{
|
|
/* handle TCL, create new command: the Counter */
|
|
Tcl_CreateCommand(interp,strdup(argv[1]),EL737Action,
|
|
(ClientData)pEL737,EL737Murder);
|
|
Tcl_AppendResult(interp,strdup(argv[1]),(char *)NULL);
|
|
return TCL_OK;
|
|
}
|
|
else
|
|
{
|
|
EL737_ErrInfo(&pErr,&iPort,&iChannel, &iMotor);
|
|
EL737Error2Text(pBueffel,iPort);
|
|
Tcl_AppendResult(interp,pBueffel,(char *) NULL);
|
|
free(pEL737);
|
|
return TCL_ERROR;
|
|
}
|
|
}
|
|
/*--------------------------------------------------------------------------
|
|
|
|
EL737 Action is the routine where commands send to the conter will
|
|
end up.
|
|
|
|
Syntax: timer starts counter with a preset value
|
|
counter wait val for counts or time and does
|
|
monitor not return before finished
|
|
|
|
timer starts counter with a preset value
|
|
counter start val for counts or time and
|
|
monitor returns immediatly
|
|
counter isDone returns True, false depending if
|
|
started run has ended or not
|
|
counter value gets counter values as a little list
|
|
consisting of:
|
|
{ counts monitor time }
|
|
counter Stop forces counter to stop
|
|
----------------------------------------------------------------------------*/
|
|
EXTERN int EL737Action(ClientData clientData, Tcl_Interp *interp,
|
|
int argc, char *argv[])
|
|
{
|
|
EL737st *pData = (EL737st *)clientData;
|
|
char pBueffel[132];
|
|
char pNumBuf[20];
|
|
char *pErr = NULL;
|
|
int iC1, iC2, iC3, iC4, iRS, iRet;
|
|
float fTime;
|
|
int iFlag = 0;
|
|
int iMode;
|
|
double dVal;
|
|
|
|
/* obviously we need at least a keyword! */
|
|
if(argc < 2)
|
|
{
|
|
Tcl_AppendResult(interp,"No keyword given",NULL);
|
|
return TCL_ERROR;
|
|
}
|
|
|
|
/* get values out */
|
|
if(strcmp(argv[1],"value") == 0)
|
|
{
|
|
iRet = EL737_GetStatus(&(pData->pData),&iC1, &iC2, &iC3,
|
|
&iC4,&fTime,&iRS);
|
|
if(!iRet)
|
|
{
|
|
EL737_ErrInfo(&pErr,&iC1,&iC2, &iC3);
|
|
EL737Error2Text(pBueffel,iC1);
|
|
Tcl_AppendResult(interp,pBueffel,(char *) NULL);
|
|
return TCL_ERROR;
|
|
}
|
|
sprintf(pNumBuf,"%d",iC2);
|
|
Tcl_AppendElement(interp,pNumBuf);
|
|
sprintf(pNumBuf,"%d",iC1);
|
|
Tcl_AppendElement(interp,pNumBuf);
|
|
sprintf(pNumBuf,"%f",fTime);
|
|
Tcl_AppendElement(interp,pNumBuf);
|
|
return TCL_OK;
|
|
}
|
|
|
|
/* isDone ? */
|
|
if(strcmp(argv[1],"isDone") == 0)
|
|
{
|
|
iRet = EL737_GetStatus(&(pData->pData),&iC1, &iC2, &iC3,
|
|
&iC4,&fTime,&iRS);
|
|
if(!iRet)
|
|
{
|
|
EL737_ErrInfo(&pErr,&iC1,&iC2, &iC3);
|
|
EL737Error2Text(pBueffel,iC1);
|
|
Tcl_AppendResult(interp,pBueffel,(char *) NULL);
|
|
return TCL_ERROR;
|
|
}
|
|
if(iRS == 0) /* done is true */
|
|
{
|
|
sprintf(pNumBuf,"%d",True);
|
|
}
|
|
else
|
|
{
|
|
sprintf(pNumBuf,"%d",False);
|
|
}
|
|
Tcl_AppendResult(interp,pNumBuf,(char *) NULL);
|
|
return TCL_OK;
|
|
}
|
|
|
|
/* actual counting neutrons in two different modes */
|
|
if(strcmp(argv[1],"wait") == 0)
|
|
{
|
|
iFlag = 2;
|
|
}
|
|
if(strcmp(argv[1],"start") == 0)
|
|
{
|
|
iFlag = 1;
|
|
}
|
|
if(iFlag > 0) /* we need to count */
|
|
{
|
|
if(argc < 4) /* not enough arguments */
|
|
{
|
|
Tcl_AppendResult(interp,"Usage: ",argv[0],argv[1],
|
|
" timer or monitor val",NULL);
|
|
return TCL_ERROR;
|
|
}
|
|
|
|
/* timer or monitor preset ? */
|
|
if(strcmp(argv[2],"timer") == 0)
|
|
{
|
|
iMode = 1;
|
|
}
|
|
else if (strcmp(argv[2],"monitor") == 0)
|
|
{
|
|
iMode = 2;
|
|
}
|
|
else
|
|
{
|
|
Tcl_AppendResult(interp,"Usage: ",argv[0],argv[1],
|
|
" timer or monitor val",NULL);
|
|
return TCL_ERROR;
|
|
}
|
|
|
|
/* get the preset value */
|
|
iRet = Tcl_GetDouble(interp,argv[3],&dVal);
|
|
if(iRet == TCL_ERROR)
|
|
{
|
|
return TCL_ERROR;
|
|
}
|
|
|
|
/* actual start collecting neutrons */
|
|
if(iMode == 1)
|
|
{
|
|
iRet = EL737_StartTime(&(pData->pData),(float)dVal,
|
|
&iRS);
|
|
}
|
|
else
|
|
{
|
|
iRet = EL737_StartCnt(&(pData->pData),(int)dVal,
|
|
&iRS);
|
|
}
|
|
if(!iRet)
|
|
{
|
|
EL737_ErrInfo(&pErr,&iC1,&iC2, &iC3);
|
|
EL737Error2Text(pBueffel,iC1);
|
|
Tcl_AppendResult(interp,pBueffel,(char *) NULL);
|
|
return TCL_ERROR;
|
|
}
|
|
} /* end of count startup code */
|
|
|
|
/* if apropriate: wait */
|
|
if(iFlag == 2)
|
|
{
|
|
iRet = EL737_WaitIdle(&(pData->pData),&iC1, &iC2, &iC3,
|
|
&iC4,&fTime);
|
|
if(!iRet)
|
|
{
|
|
EL737_ErrInfo(&pErr,&iC1,&iC2, &iC3);
|
|
EL737Error2Text(pBueffel,iC1);
|
|
Tcl_AppendResult(interp,pBueffel,(char *) NULL);
|
|
return TCL_ERROR;
|
|
}
|
|
return TCL_OK;
|
|
}
|
|
else if(iFlag == 1)
|
|
{
|
|
return TCL_OK;
|
|
}
|
|
|
|
/* the stop command */
|
|
if(strcmp(argv[1],"stop") == 0)
|
|
{
|
|
iRet = EL737_Stop(&(pData->pData),&iC1, &iC2, &iC3,
|
|
&iC4,&fTime,&iRS);
|
|
if(!iRet)
|
|
{
|
|
EL737_ErrInfo(&pErr,&iC1,&iC2, &iC3);
|
|
EL737Error2Text(pBueffel,iC1);
|
|
Tcl_AppendResult(interp,pBueffel,(char *) NULL);
|
|
return TCL_ERROR;
|
|
}
|
|
return TCL_OK;
|
|
}
|
|
|
|
Tcl_AppendResult(interp," obscure command: ",argv[1],
|
|
" not understood by EL737 counter", NULL);
|
|
return TCL_ERROR;
|
|
}
|
|
/*---------------------------------------------------------------------------
|
|
|
|
EL737Error2Text converts between an EL734 error code to text
|
|
-----------------------------------------------------------------------------*/
|
|
void EL737Error2Text(char *pBuffer, int iErr)
|
|
{
|
|
switch(iErr)
|
|
{
|
|
case -28:
|
|
strcpy(pBuffer,"EL737__BAD_ADR");
|
|
break;
|
|
case -8:
|
|
strcpy(pBuffer,"EL737__BAD_OVFL");
|
|
break;
|
|
case -30:
|
|
strcpy(pBuffer,"EL737__BAD_BSY");
|
|
break;
|
|
case -3:
|
|
strcpy(pBuffer,"EL737__BAD_SNTX");
|
|
break;
|
|
case -9:
|
|
strcpy(pBuffer,"EL737__BAD_CONNECT");
|
|
break;
|
|
case -23:
|
|
strcpy(pBuffer,"EL737__BAD_FLUSH");
|
|
break;
|
|
case -6:
|
|
strcpy(pBuffer,"EL734__BAD_DEV");
|
|
break;
|
|
case -10:
|
|
strcpy(pBuffer,"EL737__BAD_ID");
|
|
break;
|
|
case -5:
|
|
strcpy(pBuffer,"EL737__BAD_ILLG");
|
|
break;
|
|
case -2:
|
|
strcpy(pBuffer,"EL737__BAD_LOC");
|
|
break;
|
|
case -11:
|
|
strcpy(pBuffer,"EL737__BAD_MALLOC");
|
|
break;
|
|
case -21:
|
|
strcpy(pBuffer,"EL737__BAD_NOT_BCD");
|
|
break;
|
|
case -4:
|
|
strcpy(pBuffer,"EL737__BAD_OFL");
|
|
break;
|
|
case -29:
|
|
strcpy(pBuffer,"EL737__BAD_PAR");
|
|
break;
|
|
|
|
case -17:
|
|
strcpy(pBuffer,"EL737__BAD_RECV");
|
|
break;
|
|
case -19:
|
|
strcpy(pBuffer,"EL737__BAD_RECV_NET");
|
|
break;
|
|
case -18:
|
|
strcpy(pBuffer,"EL737__BAD_RECV_PIPE");
|
|
break;
|
|
case -20:
|
|
strcpy(pBuffer,"EL737__BAD_RECV_UNKN");
|
|
break;
|
|
case -22:
|
|
strcpy(pBuffer,"EL737__BAD_RECVLEN");
|
|
break;
|
|
case -24:
|
|
strcpy(pBuffer,"EL737__BAD_RECV1");
|
|
break;
|
|
case -26:
|
|
strcpy(pBuffer,"EL737__BAD_RECV1_NET");
|
|
break;
|
|
case -25:
|
|
strcpy(pBuffer,"EL737__BAD_RECV1_PIPE");
|
|
break;
|
|
case -27:
|
|
strcpy(pBuffer,"EL737__BAD_RNG");
|
|
break;
|
|
case -13:
|
|
strcpy(pBuffer,"EL737__BAD_SEND");
|
|
break;
|
|
case -14:
|
|
strcpy(pBuffer,"EL737__BAD_SEND_PIPE");
|
|
break;
|
|
case -15:
|
|
strcpy(pBuffer,"EL737__BAD_SEND_NET");
|
|
break;
|
|
case -16:
|
|
strcpy(pBuffer,"EL737__BAD_SEND_UNKN");
|
|
break;
|
|
case -12:
|
|
strcpy(pBuffer,"EL737__BAD_SENDLEN");
|
|
break;
|
|
case -7:
|
|
strcpy(pBuffer,"EL737__BAD_SOCKET");
|
|
break;
|
|
case -1:
|
|
strcpy(pBuffer,"EL737__BAD_TMO");
|
|
break;
|
|
default:
|
|
strcpy(pBuffer,"Unknown EL737 error");
|
|
break;
|
|
}
|
|
}
|