- Extended the callback interface to register scipts on callbacks - Fixed a stop bug in the anticollision object - Modified the HM code to do zero through a client connection
385 lines
10 KiB
C
385 lines
10 KiB
C
/*----------------------------------------------------------------------
|
|
Interface to a GPIB controller. This is the implementation file.
|
|
|
|
copyright: see file COPYRIGHT
|
|
|
|
Mark Koennecke, January 2003
|
|
------------------------------------------------------------------------*/
|
|
#include <stdlib.h>
|
|
#include <assert.h>
|
|
#include <errno.h>
|
|
#include <tcl.h>
|
|
#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);
|
|
}
|
|
|
|
|
|
|
|
|
|
|