Files
sicspsi/hardsup/el737tcl.c
2009-02-13 09:01:24 +00:00

365 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;
}
}