/*---------------------------------------------------------------------- Interface to a GPIB controller. This is the implementation file. copyright: see file COPYRIGHT Mark Koennecke, January 2003 ------------------------------------------------------------------------*/ #include #include #include #include #include "fortify.h" #include "sics.h" #include "splitter.h" #include "gpibcontroller.h" #include "gpibcontroller.i" /*----------------------------------------------------------------------*/ int GPIBattach(pGPIB self, int boardNo, int address, int secondaryAddress, int tmo, int eot, int eos) { return self->attach(boardNo, address, secondaryAddress, tmo, eot, eos); } /*---------------------------------------------------------------------*/ int GPIBdetach(pGPIB self, int devID) { return self->detach(devID); } /*----------------------------------------------------------------------*/ int GPIBsend(pGPIB self, int devID, void *buffer, int bytesToWrite) { return self->send(devID, buffer, bytesToWrite); } /*--------------------------------------------------------------------*/ int GPIBread(pGPIB self, int devID, void *buffer, int bytesToRead) { return self->read(devID, buffer, bytesToRead); } /*--------------------------------------------------------------------*/ char *GPIBreadTillTerm(pGPIB self, int devID, int terminator) { char buchstabe[2]; Tcl_DString buffer; char *result = NULL; int status; Tcl_DStringInit(&buffer); buchstabe[1] = '\0'; GPIBread(self, devID, buchstabe, 1); while (buchstabe[0] != (unsigned char) terminator) { Tcl_DStringAppend(&buffer, buchstabe, -1); status = GPIBread(self, devID, buchstabe, 1); if (status != 1) { Tcl_DStringAppend(&buffer, "GPIB Read Error", -1); break; } } result = strdup(Tcl_DStringValue(&buffer)); Tcl_DStringFree(&buffer); return result; } /*--------------------------------------------------------------------*/ void GPIBclear(pGPIB self, int devID) { self->clear(devID); } /*--------------------------------------------------------------------*/ void GPIBerrorDescription(pGPIB self, int code, char *buffer, int maxBuf) { self->getErrorDescription(code, buffer, maxBuf); } /*------------------------------------------------------------------- These are void implementations of the functions for simulation purposes ----------------------------------------------------------------------*/ static int SIMattach(int boardNo, int address, int secondaryAddress, int tmo, int eoi, int eot) { return 1; } /*----------------------------------------------------------------------*/ static int SIMdetach(int devID) { return 1; } /*---------------------------------------------------------------------*/ static int SIMsend(int devID, void *buffer, int bytesToWrite) { return 1; } /*--------------------------------------------------------------------*/ static int SIMread(int devID, void *buffer, int bytesToRead) { return 1; } /*--------------------------------------------------------------------*/ static int SIMclear(int devID) { return 1; } /*---------------------------------------------------------------------*/ static void SIMerror(int code, char *buffer, int maxBuf) { strlcpy(buffer, "Unknown simulated error", maxBuf); } /*---------------------------------------------------------------------*/ void GPIBKill(void *pData) { pGPIB self = NULL; if (pData != NULL) { self = (pGPIB) pData; if (self->pDes) { DeleteDescriptor(self->pDes); } free(pData); } } /*---------------------------------------------------------------------*/ int GPIBAction(SConnection * pCon, SicsInterp * pSics, void *pData, int argc, char *argv[]) { pGPIB self = (pGPIB) pData; int boardID, devID, tmo, count, eoi, eot, address, secondaryAddress, status, terminator, value; char pBuffer[1024]; char *result = NULL; assert(self != NULL); /* Only managers will be allowed to wrestle directly with GPIB controllers. */ if (!SCinMacro(pCon)) { if (!SCMatchRights(pCon, usMugger)) { return 0; } } if (argc > 1) { strtolower(argv[1]); if (strcmp(argv[1], "attach") == 0) { /* the attach command */ if (argc < 8) { SCWrite(pCon, "ERROR: insufficient number of arguments to attach", eError); return 0; } count = 0; count += Tcl_GetInt(pSics->pTcl, argv[2], &boardID); count += Tcl_GetInt(pSics->pTcl, argv[3], &address); count += Tcl_GetInt(pSics->pTcl, argv[4], &secondaryAddress); count += Tcl_GetInt(pSics->pTcl, argv[5], &tmo); count += Tcl_GetInt(pSics->pTcl, argv[6], &eot); count += Tcl_GetInt(pSics->pTcl, argv[7], &eoi); if (count != 6 * TCL_OK) { SCWrite(pCon, "ERROR: failed to convert arguments to integer", eError); return 0; } status = GPIBattach(self, boardID, address, secondaryAddress, tmo, eot, eoi); if (status > 0) { snprintf(pBuffer,sizeof(pBuffer)-1, "%d", status); SCWrite(pCon, pBuffer, eValue); return 1; } else { snprintf(pBuffer,sizeof(pBuffer)-1, "ERROR: error %d on attach", status); SCWrite(pCon, pBuffer, eError); return 0; } } else if (strcmp(argv[1], "detach") == 0) { /* detach command */ if (argc < 2) { SCWrite(pCon, "ERROR: insufficient number of arguments to dettach", eError); return 0; } if (Tcl_GetInt(pSics->pTcl, argv[2], &devID) != TCL_OK) { SCWrite(pCon, "ERROR: failed to convert arguments to integer", eError); return 0; } status = GPIBdetach(self, devID); if (status > 0) { SCSendOK(pCon); return 1; } else { snprintf(pBuffer,sizeof(pBuffer)-1, "ERROR: error %d on dettach", status); SCWrite(pCon, pBuffer, eError); return 0; } } else if (strcmp(argv[1], "clear") == 0) { /* clear command */ if (argc < 2) { SCWrite(pCon, "ERROR: insufficient number of arguments to clear", eError); return 0; } if (Tcl_GetInt(pSics->pTcl, argv[2], &devID) != TCL_OK) { SCWrite(pCon, "ERROR: failed to convert arguments to integer", eError); return 0; } GPIBclear(self, devID); SCSendOK(pCon); return 1; } else if (strcmp(argv[1], "send") == 0) { /* send command */ if (argc < 4) { SCWrite(pCon, "ERROR: insufficient number of arguments to send", eError); return 0; } if (Tcl_GetInt(pSics->pTcl, argv[2], &devID) != TCL_OK) { SCWrite(pCon, "ERROR: failed to convert arguments to integer", eError); return 0; } Arg2Text(argc - 3, argv + 3, pBuffer, 1023); status = GPIBsend(self, devID, pBuffer, (int) strlen(pBuffer)); if (status > 0) { SCSendOK(pCon); return 1; } else { snprintf(pBuffer,sizeof(pBuffer)-1, "ERROR: error %d on send", status); SCWrite(pCon, pBuffer, eError); return 0; } } else if (strcmp(argv[1], "sendwithterm") == 0) { /* send command */ if (argc < 5) { SCWrite(pCon, "ERROR: insufficient number of arguments to sendwithterm", eError); return 0; } if (Tcl_GetInt(pSics->pTcl, argv[2], &devID) != TCL_OK) { SCWrite(pCon, "ERROR: failed to convert arguments to integer", eError); return 0; } if (Tcl_GetInt(pSics->pTcl, argv[4], &terminator) != TCL_OK) { SCWrite(pCon, "ERROR: failed to convert arguments to integer", eError); return 0; } strlcpy(pBuffer, argv[3], 1024); pBuffer[strlen(pBuffer)] = (char) terminator; status = GPIBsend(self, devID, pBuffer, (int) strlen(pBuffer)); if (status > 0) { SCSendOK(pCon); return 1; } else { snprintf(pBuffer,sizeof(pBuffer)-1, "ERROR: error %d on send", status); SCWrite(pCon, pBuffer, eError); return 0; } } else if (strcmp(argv[1], "read") == 0) { /* read command */ if (argc < 2) { SCWrite(pCon, "ERROR: insufficient number of arguments to read", eError); return 0; } if (Tcl_GetInt(pSics->pTcl, argv[2], &devID) != TCL_OK) { SCWrite(pCon, "ERROR: failed to convert arguments to integer", eError); return 0; } status = GPIBread(self, devID, pBuffer, 1023); if (status > 0) { SCWrite(pCon, pBuffer, eValue); return 1; } else { snprintf(pBuffer,sizeof(pBuffer)-1, "ERROR: error %d on read", status); SCWrite(pCon, pBuffer, eError); return 0; } } else if (strcmp(argv[1], "readnum") == 0) { /* readnum command */ if (argc < 2) { SCWrite(pCon, "ERROR: insufficient number of arguments to read", eError); return 0; } if (Tcl_GetInt(pSics->pTcl, argv[2], &devID) != TCL_OK) { SCWrite(pCon, "ERROR: failed to convert arguments to integer", eError); return 0; } status = GPIBread(self, devID, &value, 4); if (status > 0) { snprintf(pBuffer,sizeof(pBuffer)-1, "gpib %d = %d", devID, value); SCWrite(pCon, pBuffer, eValue); return 1; } else { /* snprintf(pBuffer,sizeof(pBuffer)-1,"ERROR: error %d on read", status); SCWrite(pCon,pBuffer,eError); */ return 0; } } else if (strcmp(argv[1], "readtillterm") == 0) { /* read command */ if (argc < 3) { SCWrite(pCon, "ERROR: insufficient number of arguments to read", eError); return 0; } if (Tcl_GetInt(pSics->pTcl, argv[2], &devID) != TCL_OK) { SCWrite(pCon, "ERROR: failed to convert arguments to integer", eError); return 0; } if (Tcl_GetInt(pSics->pTcl, argv[3], &terminator) != TCL_OK) { SCWrite(pCon, "ERROR: failed to convert arguments to integer", eError); return 0; } result = GPIBreadTillTerm(self, devID, terminator); if (result != NULL) { SCWrite(pCon, result, eValue); free(result); return 1; } else { SCWrite(pCon, "ERROR: failed to read at GPIB", eError); return 0; } } else { SCWrite(pCon, "ERROR: command not recognized", eError); return 0; } } else { SCWrite(pCon, "ERROR: no command given to GPIB", eError); return 0; } } /*--------------------------------------------------------------------*/ #ifdef HAVENI extern void NIassign(pGPIB self); #endif int MakeGPIB(SConnection * pCon, SicsInterp * pSics, void *pData, int argc, char *argv[]) { pGPIB self = NULL; if (argc < 3) { SCWrite(pCon, "ERROR: insufficient number of arguments to MakeGPIB", eError); return 0; } self = (pGPIB) malloc(sizeof(GPIB)); if (self == NULL) { SCWrite(pCon, "ERROR: cannot allocate memory in MakeGPIB", eError); return 0; } memset(self, 0, sizeof(GPIB)); self->pDes = CreateDescriptor("GPIB"); strtolower(argv[2]); if (strcmp(argv[2], "sim") == 0) { self->attach = SIMattach; self->detach = SIMdetach; self->send = SIMsend; self->read = SIMread; self->clear = SIMclear; self->getErrorDescription = SIMerror; #ifdef HAVENI } else if (strcmp(argv[2], "ni") == 0) { NIassign(self); #endif } else { SCWrite(pCon, "ERROR: GPIB driver not recognised", eError); return 0; } return AddCommand(pSics, argv[1], GPIBAction, GPIBKill, self); }