
- Added strlcpy and strlcat to SICS - Added a driver for the POLDI power supplies SKIPPED: psi/A1931.c psi/autowin.c psi/bruker.c psi/docho.c psi/dornier2.c psi/dspcode.c psi/ease.c psi/ecb.c psi/ecbcounter.c psi/ecbdriv.c psi/el734dc.c psi/el734driv.c psi/el734hp.c psi/el737driv.c psi/el737hpdriv.c psi/el737hpdrivsps.c psi/el737hpv2driv.c psi/el755driv.c psi/eurodriv.c psi/haakedriv.c psi/itc4driv.c psi/julcho.c psi/linadriv.c psi/lmd200.c psi/lscsupport.c psi/ltc11.c psi/make_gen psi/oicom.c psi/oxinst.c psi/pimotor.c psi/pipiezo.c psi/polterwrite.c psi/psi.c psi/sanscook.c psi/sanslirebin.c psi/sanswave.c psi/sinqhmdriv.c psi/sinqhttp.c psi/slsecho.c psi/slsmagnet.c psi/slsvme.c psi/sps.c psi/swmotor.c psi/swmotor2.c psi/tabledrive.c psi/tasscan.c psi/tdchm.c psi/velodorn.c psi/velodornier.c
411 lines
12 KiB
C
411 lines
12 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)
|
|
{
|
|
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);
|
|
}
|