368 lines
9.1 KiB
C
368 lines
9.1 KiB
C
/*-------------------------------------------------------------------------
|
|
This is the implementation file for a driver for the Risoe A1931a
|
|
temperature controller. This driver controls the device through a GPIB
|
|
interface.
|
|
|
|
copyright: see file COPYRIGHT
|
|
|
|
Mark Koennecke, February 2003
|
|
-------------------------------------------------------------------------*/
|
|
#include <string.h>
|
|
#include <stdio.h>
|
|
#include <time.h>
|
|
#include <math.h>
|
|
#include <assert.h>
|
|
#include <unistd.h>
|
|
#include <fortify.h>
|
|
#include <sics.h>
|
|
#include <obpar.h>
|
|
#include <evcontroller.h>
|
|
#include <evcontroller.i>
|
|
#include <evdriver.i>
|
|
#include <gpibcontroller.h>
|
|
#include "A1931.h"
|
|
|
|
/*========================== private data structure ====================*/
|
|
typedef struct {
|
|
int sensor; /* the control sensor */
|
|
pGPIB gpib; /* the GPIB interface to use in order to talk to the thing */
|
|
int gpibAddress; /* address on bus */
|
|
int devID; /* deviceID of the controller on the GPIB */
|
|
char errorBuffer[132]; /* a buffer for error messages from the thing */
|
|
char commandLine[132]; /* buffer to keep the offending command line */
|
|
int errorCode; /* error indicator */
|
|
} A1931, *pA1931;
|
|
/*============================ defines ================================*/
|
|
#define COMMERROR -300
|
|
#define A1931ERROR -301
|
|
#define FILEERROR -302
|
|
/*====================================================================*/
|
|
static char *A1931comm(pEVDriver pData, char *command)
|
|
{
|
|
char buffer[256], *pPtr;
|
|
int status;
|
|
pA1931 self = NULL;
|
|
Tcl_DString reply;
|
|
|
|
self = (pA1931) pData->pPrivate;
|
|
assert(self);
|
|
|
|
/*
|
|
send
|
|
*/
|
|
strncpy(buffer, command, 250);
|
|
strcat(buffer, "\n");
|
|
status = GPIBsend(self->gpib, self->devID, buffer, (int) strlen(buffer));
|
|
if (status < 0) {
|
|
self->errorCode = COMMERROR;
|
|
GPIBerrorDescription(self->gpib, status, self->errorBuffer, 131);
|
|
return NULL;
|
|
}
|
|
|
|
/*
|
|
read until > is found
|
|
*/
|
|
Tcl_DStringInit(&reply);
|
|
while (1) {
|
|
pPtr = GPIBreadTillTerm(self->gpib, self->devID, 10);
|
|
if (strstr(pPtr, "GPIB READ ERROR") != NULL) {
|
|
free(pPtr);
|
|
self->errorCode = COMMERROR;
|
|
Tcl_DStringFree(&reply);
|
|
return NULL;
|
|
} else {
|
|
Tcl_DStringAppend(&reply, pPtr, -1);
|
|
if (strchr(pPtr, '>') != NULL) {
|
|
/*
|
|
finished
|
|
*/
|
|
free(pPtr);
|
|
break;
|
|
}
|
|
free(pPtr);
|
|
}
|
|
}
|
|
pPtr = NULL;
|
|
pPtr = strdup(Tcl_DStringValue(&reply));
|
|
Tcl_DStringFree(&reply);
|
|
if (pPtr[0] == '#') {
|
|
/*
|
|
error
|
|
*/
|
|
self->errorCode = A1931ERROR;
|
|
strncpy(self->errorBuffer, pPtr, 131);
|
|
free(pPtr);
|
|
return NULL;
|
|
}
|
|
return pPtr;
|
|
}
|
|
|
|
/*--------------------------------------------------------------------*/
|
|
static int A1931command(pEVDriver pData, char *command, char *replyBuffer,
|
|
int replyBufferLen)
|
|
{
|
|
pA1931 self = NULL;
|
|
char *pReply = NULL;
|
|
|
|
self = (pA1931) pData->pPrivate;
|
|
assert(self);
|
|
|
|
pReply = A1931comm(pData, command);
|
|
if (pReply != NULL) {
|
|
strncpy(replyBuffer, pReply, replyBufferLen);
|
|
free(pReply);
|
|
return 1;
|
|
} else {
|
|
strncpy(replyBuffer, self->errorBuffer, replyBufferLen);
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
/*====================================================================*/
|
|
static int A1931Init(pEVDriver pData)
|
|
{
|
|
pA1931 self = NULL;
|
|
|
|
self = (pA1931) pData->pPrivate;
|
|
assert(self);
|
|
|
|
self->devID = GPIBattach(self->gpib, 0, self->gpibAddress, 0, 13, 0, 0);
|
|
if (self->devID < 0) {
|
|
return 0;
|
|
}
|
|
return 1;
|
|
}
|
|
|
|
/*====================================================================*/
|
|
static int A1931Close(pEVDriver pData)
|
|
{
|
|
pA1931 self = NULL;
|
|
|
|
self = (pA1931) pData->pPrivate;
|
|
assert(self);
|
|
|
|
GPIBdetach(self->gpib, self->devID);
|
|
self->devID = 0;
|
|
return 1;
|
|
}
|
|
|
|
/*===================================================================*/
|
|
static int A1931Get(pEVDriver pData, float *fPos)
|
|
{
|
|
pA1931 self = NULL;
|
|
char buffer[132], command[50];
|
|
int status;
|
|
|
|
self = (pA1931) pData->pPrivate;
|
|
assert(self);
|
|
|
|
sprintf(command, "?TEMP%1.1d", self->sensor);
|
|
status = A1931command(pData, command, buffer, 131);
|
|
if (!status) {
|
|
return 0;
|
|
}
|
|
sscanf(buffer, "%f", fPos);
|
|
return 1;
|
|
}
|
|
|
|
/*=====================================================================*/
|
|
static int A1931Set(pEVDriver pData, float fNew)
|
|
{
|
|
pA1931 self = NULL;
|
|
char buffer[132], command[50];
|
|
int status;
|
|
|
|
self = (pA1931) pData->pPrivate;
|
|
assert(self);
|
|
|
|
sprintf(command, "SET%1.1d=%f", self->sensor, fNew);
|
|
status = A1931command(pData, command, buffer, 131);
|
|
if (!status) {
|
|
return 0;
|
|
}
|
|
return 1;
|
|
}
|
|
|
|
/*====================================================================*/
|
|
static int A1931error(pEVDriver pData, int *iCode, char *errBuff,
|
|
int bufLen)
|
|
{
|
|
pA1931 self = NULL;
|
|
char pError[256];
|
|
|
|
self = (pA1931) pData->pPrivate;
|
|
assert(self);
|
|
|
|
*iCode = self->errorCode;
|
|
sprintf(pError, "ERROR: %s", self->errorBuffer);
|
|
strncpy(errBuff, pError, bufLen);
|
|
return 1;
|
|
}
|
|
|
|
/*====================================================================*/
|
|
static int A1931fix(pEVDriver pData, int iCode)
|
|
{
|
|
pA1931 self = NULL;
|
|
char pError[256];
|
|
|
|
self = (pA1931) pData->pPrivate;
|
|
assert(self);
|
|
|
|
if (iCode == COMMERROR) {
|
|
GPIBclear(self->gpib, self->devID);
|
|
return DEVREDO;
|
|
}
|
|
return DEVFAULT;
|
|
}
|
|
|
|
/*=====================================================================*/
|
|
pEVDriver CreateA1931Driver(int argc, char *argv[])
|
|
{
|
|
pEVDriver self = NULL;
|
|
pA1931 priv = NULL;
|
|
|
|
if (argc < 2) {
|
|
return NULL;
|
|
}
|
|
|
|
/*
|
|
allocate space
|
|
*/
|
|
self = CreateEVDriver(argc, argv);
|
|
priv = (pA1931) malloc(sizeof(A1931));
|
|
if (self == NULL || priv == NULL) {
|
|
return NULL;
|
|
}
|
|
memset(priv, 0, sizeof(A1931));
|
|
self->pPrivate = priv;
|
|
self->KillPrivate = free;
|
|
|
|
/*
|
|
initialize
|
|
*/
|
|
priv->gpib = (pGPIB) FindCommandData(pServ->pSics, argv[0], "GPIB");
|
|
if (!priv->gpib) {
|
|
DeleteEVDriver(self);
|
|
return NULL;
|
|
}
|
|
priv->sensor = 1;
|
|
priv->gpibAddress = atoi(argv[1]);
|
|
|
|
/*
|
|
initialize function pointers
|
|
*/
|
|
self->Send = A1931command;
|
|
self->Init = A1931Init;
|
|
self->Close = A1931Close;
|
|
self->GetValue = A1931Get;
|
|
self->SetValue = A1931Set;
|
|
self->GetError = A1931error;
|
|
self->TryFixIt = A1931fix;
|
|
|
|
return self;
|
|
}
|
|
|
|
/*=======================================================================*/
|
|
static int downloadFile(pA1931 self, FILE * fd)
|
|
{
|
|
char buffer[132], *pPtr;
|
|
int status;
|
|
|
|
while (1) {
|
|
if (fgets(buffer, 130, fd) == NULL) {
|
|
self->errorCode = FILEERROR;
|
|
strcpy(self->errorBuffer, "Failed to read from file");
|
|
return 0;
|
|
}
|
|
if (strstr(buffer, "$END") != NULL) {
|
|
break;
|
|
}
|
|
status =
|
|
GPIBsend(self->gpib, self->devID, buffer, (int) strlen(buffer));
|
|
if (status < 0) {
|
|
self->errorCode = COMMERROR;
|
|
GPIBerrorDescription(self->gpib, status, self->errorBuffer, 131);
|
|
return 0;
|
|
}
|
|
pPtr = GPIBreadTillTerm(self->gpib, self->devID, 10);
|
|
if (pPtr[0] == '#') {
|
|
self->errorCode = A1931ERROR;
|
|
strncpy(self->errorBuffer, pPtr, 131);
|
|
strncpy(self->commandLine, buffer, 131);
|
|
free(pPtr);
|
|
return 0;
|
|
}
|
|
free(pPtr);
|
|
usleep(50);
|
|
}
|
|
return 1;
|
|
}
|
|
|
|
/*=======================================================================*/
|
|
int A1931Action(SConnection * pCon, SicsInterp * pSics, void *pData,
|
|
int argc, char *argv[])
|
|
{
|
|
pEVControl pEV = NULL;
|
|
pA1931 self = NULL;
|
|
char buffer[256];
|
|
char error[132];
|
|
FILE *fd = NULL;
|
|
int status, iCode;
|
|
|
|
pEV = (pEVControl) pData;
|
|
assert(pEV);
|
|
self = (pA1931) pEV->pDriv->pPrivate;
|
|
assert(self);
|
|
|
|
if (argc > 1) {
|
|
strtolower(argv[1]);
|
|
if (strcmp(argv[1], "sensor") == 0) {
|
|
if (argc > 2) {
|
|
/* set case */
|
|
if (!SCMatchRights(pCon, usUser)) {
|
|
return 0;
|
|
}
|
|
self->sensor = atoi(argv[2]);
|
|
SCSendOK(pCon);
|
|
return 1;
|
|
} else {
|
|
/* get case */
|
|
sprintf(buffer, "%s.sensor = %d", argv[0], self->sensor);
|
|
SCWrite(pCon, buffer, eValue);
|
|
return 1;
|
|
}
|
|
} else if (strcmp(argv[1], "list") == 0) {
|
|
sprintf(buffer, "%s.sensor = %d", argv[0], self->sensor);
|
|
SCWrite(pCon, buffer, eValue);
|
|
return EVControlWrapper(pCon, pSics, pData, argc, argv);
|
|
} else if (strcmp(argv[1], "file") == 0) {
|
|
if (!SCMatchRights(pCon, usUser)) {
|
|
return 0;
|
|
}
|
|
if (argc < 3) {
|
|
SCWrite(pCon, "ERROR: need filename argument", eError);
|
|
return 0;
|
|
}
|
|
fd = fopen(argv[2], "r");
|
|
if (fd == NULL) {
|
|
sprintf(buffer, "ERROR: failed to open %s", argv[2]);
|
|
SCWrite(pCon, buffer, eError);
|
|
return 0;
|
|
}
|
|
status = downloadFile(self, fd);
|
|
fclose(fd);
|
|
if (!status) {
|
|
A1931error(pEV->pDriv, &iCode, error, 131);
|
|
sprintf(buffer, "%s while transfering file", error);
|
|
SCWrite(pCon, buffer, eError);
|
|
sprintf(buffer, "Offending command: %s", self->commandLine);
|
|
SCWrite(pCon, buffer, eError);
|
|
return 0;
|
|
}
|
|
SCSendOK(pCon);
|
|
return 1;
|
|
}
|
|
}
|
|
return EVControlWrapper(pCon, pSics, pData, argc, argv);
|
|
}
|