/*-------------------------------------------------------------------------- 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 #include #include /* #include */ #include #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; } }