/*---------------------------------------------------------------------- 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){ strncpy(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){ sprintf(pBuffer,"%d",status); SCWrite(pCon,pBuffer,eValue); return 1; } else { sprintf(pBuffer,"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 { sprintf(pBuffer,"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 { sprintf(pBuffer,"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; } strncpy(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 { sprintf(pBuffer,"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 { sprintf(pBuffer,"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){ sprintf(pBuffer,"gpib %d = %d",devID,value); SCWrite(pCon,pBuffer,eValue); return 1; } else { /* sprintf(pBuffer,"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); }