- Rearranged directory structure for forking out ANSTO

- Refactored site specific stuff into a site module
- PSI specific stuff is now in the PSI directory.
- The old version has been tagged with pre-ansto
This commit is contained in:
cvs
2003-06-20 10:18:47 +00:00
commit 064ec37e9a
271 changed files with 115513 additions and 0 deletions

828
ltc11.c Normal file
View File

@ -0,0 +1,828 @@
/*-------------------------------------------------------------------------
L T C 1 1
an environment control device driver for a Neocera LTC-11 temperature
controller.
copyright: see copyright.h
Mark Koennecke, November 1998
---------------------------------------------------------------------------*/
#include <string.h>
#include <stdlib.h>
#include <time.h>
#include <tcl.h>
#include <math.h>
#include <assert.h>
#include <fortify.h>
#include <sics.h>
#include <obpar.h>
#include <evcontroller.h>
#include <evcontroller.i>
#include <evdriver.i>
#include "hardsup/serialsinq.h"
#include "hardsup/el734_errcodes.h"
#include "hardsup/el734fix.h"
#include "ltc11.h"
/*
#define debug 1
*/
/*-----------------------------------------------------------------------
The LTC11 Data Structure
*/
typedef struct {
void *pData;
char *pHost;
int iPort;
int iChannel;
int iMode;
int iSensor;
int iControlHeat;
int iControlAnalog;
int iLastError;
time_t lastRequest;
float fLast;
} LTC11Driv, *pLTC11Driv;
/*-----------------------------------------------------------------------
A couple of defines for LTC11 modes and special error conditions
*/
#define ANALOG 2
#define HEATER 1
#define MISERABLE 3
/* errors */
#define BADSTATE -920
#define NOCONN -921
#define BADANSWER -923
#define BADCONFIRM -924
/*-----------------------------------------------------------------------*/
static void LTC11Unlock(pLTC11Driv self)
{
SerialNoReply(&(self->pData),"SLLOCK 0;");
}
/*-------------------------------------------------------------------------
The LTC11 can either control a heater or an analog output. It is a common
task to figure out which mode is active. If the value returned from QOUT
is 3, no sensor is defined, if it is 6 it is in monitor mode, in both cases
control is NOT there.
*/
int LTC11GetMode(pEVDriver pEva, int *iMode)
{
pLTC11Driv self = NULL;
int iRet, iiMode;
char pBueffel[80];
self = (pLTC11Driv)pEva->pPrivate;
assert(self);
if(self->pData == NULL)
{
self->iLastError = NOCONN;
return 0;
}
/* query the state, it can be in an invalid mode */
iRet = SerialWriteRead(&(self->pData),"QISTATE?;",pBueffel,79);
LTC11Unlock(self);
if(iRet != 1)
{
self->iLastError = iRet;
return 0;
}
if(strcmp(pBueffel,"?TMO") == 0)
{
self->iLastError = TIMEOUT;
return 0;
}
if(sscanf(pBueffel,"%d",&iiMode) != 1)
{
self->iLastError = EL734__BAD_ILLG;
return 0;
}
if( (iiMode != 1) && (iiMode != 2) )
{
self->iLastError = BADSTATE;
*iMode = MISERABLE;
return 0;
}
/* check the sensor in heater mode */
iRet = SerialWriteRead(&(self->pData),"QOUT?1;",pBueffel,79);
LTC11Unlock(self);
if(iRet != 1)
{
self->iLastError = iRet;
return 0;
}
if(strcmp(pBueffel,"?TMO") == 0)
{
self->iLastError = TIMEOUT;
return 0;
}
if(sscanf(pBueffel,"%d",&iiMode) != 1)
{
self->iLastError = EL734__BAD_ILLG;
return 0;
}
if( (iiMode != 3) && (iiMode != 6 ) )
{
*iMode = HEATER;
self->iControlHeat = iiMode;
return 1;
}
/* check the sensor in analog mode */
iRet = SerialWriteRead(&(self->pData),"QOUT?2;",pBueffel,79);
LTC11Unlock(self);
if(iRet != 1)
{
self->iLastError = iRet;
return 0;
}
if(strcmp(pBueffel,"?TMO") == 0)
{
self->iLastError = TIMEOUT;
return 0;
}
if(sscanf(pBueffel,"%d",&iiMode) != 1)
{
self->iLastError = EL734__BAD_ILLG;
return 0;
}
if( (iiMode != 3) && (iiMode != 6 ) )
{
*iMode = ANALOG;
self->iControlAnalog = iiMode;
return 1;
}
/* if we are here something is very bad */
self->iLastError = BADSTATE;
return 0;
}
/*-----------------------------------------------------------------------
iMode below 10 will be interpreted as heater control, above 10 as analog
control.
*/
int LTC11SetMode(pEVDriver pEva, int iMode)
{
pLTC11Driv self = NULL;
int iRet, iiMode;
char pBueffel[80], pCommand[20];
self = (pLTC11Driv)pEva->pPrivate;
assert(self);
if(self->pData == NULL)
{
self->iLastError = NOCONN;
return 0;
}
if(iMode < 10) /* heater mode */
{
sprintf(pCommand,"SHCONT%1.1d;",iMode);
iRet = SerialNoReply(&(self->pData),pCommand);
LTC11Unlock(self);
if(iRet != 1)
{
self->iLastError = iRet;
return 0;
}
return 1;
}
else
{
iMode -= 10;
sprintf(pCommand,"SACONT%1.1d;",iMode);
iRet = SerialNoReply(&(self->pData),pCommand);
LTC11Unlock(self);
if(iRet != 1)
{
self->iLastError = iRet;
return 0;
}
return 1;
}
/* should not get here */
self->iLastError = BADSTATE;
return 0;
}
/*-------------------------------------------------------------------------*/
static int LTC11Get(pEVDriver pEva, float *fValue)
{
pLTC11Driv self = NULL;
int iRet;
char pBueffel[80];
char pCommand[46];
char c;
float fVal;
self = (pLTC11Driv)pEva->pPrivate;
assert(self);
if(self->pData == NULL)
{
self->iLastError = NOCONN;
return 0;
}
if(time(NULL) < self->lastRequest)
{
*fValue = self->fLast;
return 1;
}
else
{
self->lastRequest = time(NULL) + 5; /* buffer 5 seconds */
}
sprintf(pCommand,"QSAMP?%1.1d;",self->iSensor);
iRet = SerialWriteRead(&(self->pData),pCommand,pBueffel,79);
LTC11Unlock(self);
if(iRet != 1)
{
self->iLastError = iRet;
return 0;
}
if(strcmp(pBueffel,"?TMO") == 0)
{
self->iLastError = TIMEOUT;
return 0;
}
iRet = sscanf(pBueffel,"%f%c",fValue,&c);
if(iRet != 2)
{
self->iLastError = BADANSWER;
return 0;
}
if( (c != 'K') && (c != 'C') && (c != 'F') && (c != 'N')
&& (c != 'V') && (c != 'O') )
{
self->iLastError = BADANSWER;
return 0;
}
self->fLast = *fValue;
return 1;
}
/*-------------------------------------------------------------------------*/
static int LTC11Run(pEVDriver pEva, float fVal)
{
pLTC11Driv self = NULL;
int iRet, iMode;
char pBueffel[80];
char pCommand[40];
float fTest = 0.0, fDelta;
self = (pLTC11Driv)pEva->pPrivate;
assert(self);
if(self->pData == NULL)
{
self->iLastError = NOCONN;
return 0;
}
/* find our operation mode */
iRet = LTC11GetMode(pEva,&iMode);
if( (iRet < 1) || (iMode == MISERABLE) )
{
return 0;
}
/* format command */
sprintf(pCommand,"SETP %d,%f;",iMode, fVal);
/* send command */
iRet = SerialNoReply(&(self->pData),pCommand);
if(iRet != 1)
{
self->iLastError = iRet;
LTC11Unlock(self);
return 0;
}
/* read back */
sprintf(pCommand,"QSETP?%d;", iMode);
iRet = SerialWriteRead(&(self->pData),pCommand,pBueffel,79);
LTC11Unlock(self);
if(iRet != 1)
{
self->iLastError = iRet;
return 0;
}
/* check confirmation */
if(strcmp(pBueffel,"?TMO") == 0)
{
self->iLastError = TIMEOUT;
return 0;
}
sscanf(pBueffel,"%f",&fTest);
fDelta = fVal - fTest;
if(fDelta < 0.0)
fDelta = -fDelta;
if(fDelta > 0.1)
{
self->iLastError = BADCONFIRM;
return 0;
}
return 1;
}
/*------------------------------------------------------------------------*/
static int LTC11Error(pEVDriver pEva, int *iCode, char *pError,
int iErrLen)
{
pLTC11Driv self = NULL;
self = (pLTC11Driv)pEva->pPrivate;
assert(self);
*iCode = self->iLastError;
switch(*iCode)
{
case NOCONN:
strncpy(pError,"No Connection to Bruker Controller",iErrLen);
break;
case MISERABLE:
case BADSTATE:
strncpy(pError,"The LTC-11 is in a very bad state",iErrLen);
break;
case BADANSWER:
strncpy(pError,"The LTC-11 returned a bad reply",iErrLen);
break;
case BADCONFIRM:
strncpy(pError,"The LTC-11 did not accept the new set point",iErrLen);
break;
case TIMEOUT:
strncpy(pError,"Timeout receiving data from LTC-11",iErrLen);
break;
default:
SerialError(*iCode,pError,iErrLen);
break;
}
return 1;
}
/*---------------------------------------------------------------------------*/
static int LTC11Send(pEVDriver pEva, char *pCommand, char *pReply,
int iReplyLen)
{
pLTC11Driv self = NULL;
int iRet;
self = (pLTC11Driv)pEva->pPrivate;
assert(self);
if(self->pData == NULL)
{
self->iLastError = NOCONN;
return 0;
}
iRet = SerialWriteRead(&(self->pData),pCommand, pReply, iReplyLen);
if(iRet != 1)
{
self->iLastError = iRet;
return 0;
}
return 1;
}
/*--------------------------------------------------------------------------*/
static int LTC11Init(pEVDriver pEva)
{
pLTC11Driv self = NULL;
int iRet;
char pBueffel[80], pCommand[20];
self = (pLTC11Driv)pEva->pPrivate;
assert(self);
/* open port connection */
self->pData = NULL;
iRet = SerialOpen(&(self->pData),self->pHost, self->iPort, self->iChannel);
if(iRet != 1)
{
self->iLastError = iRet;
return 0;
}
/* configure serial port terminators */
SerialSendTerm(&(self->pData),";");
SerialATerm(&(self->pData),"1;");
SerialConfig(&(self->pData),30000);
self->iSensor = 1;
/* initialize control sensors to unknown, then call GetMode
to get real values
*/
self->iControlHeat = 6;
self->iControlAnalog = 6;
LTC11GetMode(pEva,&iRet);
return 1;
}
/*-------------------------------------------------------------------------*/
static int LTC11Close(pEVDriver pEva)
{
pLTC11Driv self = NULL;
self = (pLTC11Driv)pEva->pPrivate;
assert(self);
SerialClose(&(self->pData));
self->pData = 0;
return 1;
}
/*---------------------------------------------------------------------------*/
static int LTC11Fix(pEVDriver self, int iError)
{
pLTC11Driv pMe = NULL;
int iRet;
char pCommand[20], pBueffel[80];
assert(self);
pMe = (pLTC11Driv )self->pPrivate;
assert(pMe);
switch(iError)
{
/* network errors */
case EL734__BAD_FLUSH:
case EL734__BAD_RECV:
case EL734__BAD_RECV_NET:
case EL734__BAD_RECV_UNKN:
case EL734__BAD_RECVLEN:
case EL734__BAD_RECV1:
case EL734__BAD_RECV1_PIPE:
case EL734__BAD_RNG:
case EL734__BAD_SEND:
case EL734__BAD_SEND_PIPE:
case EL734__BAD_SEND_NET:
case EL734__BAD_SEND_UNKN:
case EL734__BAD_SENDLEN:
LTC11Close(self);
iRet = LTC11Init(self);
if(iRet)
{
return DEVREDO;
}
else
{
return DEVFAULT;
}
break;
case EL734__FORCED_CLOSED:
case NOCONN:
iRet = LTC11Init(self);
if(iRet)
{
return DEVREDO;
}
else
{
return DEVFAULT;
}
break;
/* fixable LTC11 Errors */
case MISERABLE:
case BADSTATE:
iRet = SerialNoReply(&(pMe->pData),"SCONT;");
LTC11Unlock(pMe);
return DEVREDO;
break;
case BADANSWER:
case BADCONFIRM:
case TIMEOUT:
return DEVREDO;
break;
default:
return DEVFAULT;
break;
}
return DEVFAULT;
}
/*------------------------------------------------------------------------*/
void KillLTC11(void *pData)
{
pLTC11Driv pMe = NULL;
pMe = (pLTC11Driv)pData;
assert(pMe);
if(pMe->pHost)
{
free(pMe->pHost);
}
free(pMe);
}
/*------------------------------------------------------------------------*/
pEVDriver CreateLTC11Driver(int argc, char *argv[])
{
pEVDriver pNew = NULL;
pLTC11Driv pSim = NULL;
/* check for arguments */
if(argc < 3)
{
return NULL;
}
pNew = CreateEVDriver(argc,argv);
pSim = (pLTC11Driv)malloc(sizeof(LTC11Driv));
memset(pSim,0,sizeof(LTC11Driv));
if(!pNew || !pSim)
{
return NULL;
}
pNew->pPrivate = pSim;
pNew->KillPrivate = KillLTC11;
/* initalise LTC11Driver */
pSim->iLastError = 0;
pSim->pHost = strdup(argv[0]);
pSim->iPort = atoi(argv[1]);
pSim->iChannel = atoi(argv[2]);
/* initialise function pointers */
pNew->SetValue = LTC11Run;
pNew->GetValue = LTC11Get;
pNew->Send = LTC11Send;
pNew->GetError = LTC11Error;
pNew->TryFixIt = LTC11Fix;
pNew->Init = LTC11Init;
pNew->Close = LTC11Close;
return pNew;
}
/*------------------------------------------------------------------------*/
static int LTC11AssignControl(pEVDriver pEva, int iMode, int iSensor)
{
pLTC11Driv self = NULL;
int iRet, iRead = 0;
char pBueffel[80], pCommand[50];
self = (pLTC11Driv)pEva->pPrivate;
assert(self);
assert( (iMode == HEATER) || (iMode == ANALOG) );
if(!self->pData)
{
self->iLastError = NOCONN;
return 0;
}
sprintf(pCommand,"SOSEN %d,%d;",iMode,iSensor);
iRet = SerialNoReply(&(self->pData),pCommand);
if(iRet != 1)
{
self->iLastError = iRet;
return 0;
}
sprintf(pCommand,"QOUT?%d;",iMode);
iRet = SerialWriteRead(&(self->pData),pCommand,pBueffel,79);
LTC11Unlock(self);
if(strcmp(pBueffel,"?TMO") == 0)
{
self->iLastError = TIMEOUT;
return 0;
}
sscanf(pBueffel,"%d;",&iRead);
if(iRead != iSensor)
{
self->iLastError = BADCONFIRM;
return 0;
}
if(iMode == ANALOG)
{
self->iControlAnalog = iSensor;
}
else
{
self->iControlHeat = iSensor;
}
/* switch back to control mode */
SerialNoReply(&(self->pData),"SCONT;");
return 1;
}
/*--------------------------------------------------------------------------
handle LTC11 specific commands:
- sensor requests or sets read sensor
- mode requests or sets operation mode
- controlheat requests or sets sensor for heater control
- controlanalog requests or sets sensor for analog control
in all other cases fall back and call EVControllerWrapper to handle it or
eventually throw an error.
*/
int LTC11Action(SConnection *pCon, SicsInterp *pSics, void *pData,
int argc, char *argv[])
{
pEVControl self = NULL;
int iRet, iMode;
char pBueffel[256], pError[132];
pLTC11Driv pMe = NULL;
float fVal;
self = (pEVControl)pData;
assert(self);
pMe = (pLTC11Driv)self->pDriv->pPrivate;
assert(pMe);
if(argc > 1)
{
strtolower(argv[1]);
/*------ sensor */
if(strcmp(argv[1],"sensor") == 0)
{
if(argc > 2) /* set case */
{
/* check permission */
if(!SCMatchRights(pCon,usUser))
{
return 0;
}
iRet = Tcl_GetInt(pSics->pTcl,argv[2],&iMode);
if(iRet != TCL_OK)
{
sprintf(pBueffel,"ERROR: needed integer, got %s",
argv[2]);
SCWrite(pCon,pBueffel,eError);
return 0;
}
pMe->iSensor = iMode;
SCSendOK(pCon);
return 1;
}
else /* get case */
{
sprintf(pBueffel,"%s.sensor = %d", argv[0],pMe->iSensor);
SCWrite(pCon,pBueffel,eValue);
return 1;
}
}
/*------ controlanalog */
if(strcmp(argv[1],"controlanalog") == 0)
{
if(argc > 2) /* set case */
{
/* check permission */
if(!SCMatchRights(pCon,usUser))
{
return 0;
}
iRet = Tcl_GetInt(pSics->pTcl,argv[2],&iMode);
if(iRet != TCL_OK)
{
sprintf(pBueffel,"ERROR: needed integer, got %s",
argv[2]);
SCWrite(pCon,pBueffel,eError);
return 0;
}
iRet = LTC11AssignControl(self->pDriv,ANALOG,iMode);
if(iRet != 1)
{
self->pDriv->GetError(self->pDriv,&iMode,pError,131);
sprintf(pBueffel,"ERROR: failed to set sensor: %s",pError);
SCWrite(pCon,pBueffel,eError);
return 0;
}
SCSendOK(pCon);
return 1;
}
else /* get case */
{
sprintf(pBueffel,"%s.controlanalog = %d", argv[0],pMe->iControlAnalog);
SCWrite(pCon,pBueffel,eValue);
return 1;
}
}
/*------ controlheat */
if(strcmp(argv[1],"controlheat") == 0)
{
if(argc > 2) /* set case */
{
/* check permission */
if(!SCMatchRights(pCon,usUser))
{
return 0;
}
iRet = Tcl_GetInt(pSics->pTcl,argv[2],&iMode);
if(iRet != TCL_OK)
{
sprintf(pBueffel,"ERROR: needed integer, got %s",
argv[2]);
SCWrite(pCon,pBueffel,eError);
return 0;
}
iRet = LTC11AssignControl(self->pDriv,HEATER,iMode);
if(iRet != 1)
{
self->pDriv->GetError(self->pDriv,&iMode,pError,131);
sprintf(pBueffel,"ERROR: failed to set sensor: %s",pError);
SCWrite(pCon,pBueffel,eError);
return 0;
}
SCSendOK(pCon);
return 1;
}
else /* get case */
{
sprintf(pBueffel,"%s.controlheat = %d", argv[0],pMe->iControlHeat);
SCWrite(pCon,pBueffel,eValue);
return 1;
}
}
/*-------- mode */
else if(strcmp(argv[1],"mode") == 0)
{
if(argc > 2) /* set case */
{
/* check permission */
if(!SCMatchRights(pCon,usUser))
{
return 0;
}
iRet = Tcl_GetInt(pSics->pTcl,argv[2],&iMode);
if(iRet != TCL_OK)
{
sprintf(pBueffel,"ERROR: needed integer, got %s",
argv[2]);
SCWrite(pCon,pBueffel,eError);
return 0;
}
iRet = LTC11SetMode(self->pDriv,iMode);
if(iRet != 1)
{
self->pDriv->GetError(self->pDriv,&iMode,pError,131);
sprintf(pBueffel,"ERROR: failed to set mode %s",pError);
SCWrite(pCon,pBueffel,eError);
return 0;
}
else
{
SCSendOK(pCon);
return 1;
}
}
else /* get case */
{
iRet = LTC11GetMode(self->pDriv,&iMode);
if(iRet != 1)
{
self->pDriv->GetError(self->pDriv,&iMode,pError,131);
sprintf(pBueffel,"ERROR: failed to get mode %s",pError);
SCWrite(pCon,pBueffel,eError);
return 0;
}
if(iMode == ANALOG)
{
sprintf(pBueffel,"%s.mode = Analog Control", argv[0]);
}
else
{
sprintf(pBueffel,"%s.mode = Heater Control", argv[0]);
}
SCWrite(pCon,pBueffel,eValue);
return 1;
}
}
/*--------- list */
else if(strcmp(argv[1],"list") == 0)
{
/* print generals first */
EVControlWrapper(pCon,pSics,pData,argc,argv);
/* print our add on stuff */
sprintf(pBueffel,"%s.sensor = %d",argv[0],pMe->iSensor);
SCWrite(pCon,pBueffel,eValue);
sprintf(pBueffel,"%s.controlanalog = %d",argv[0],pMe->iControlAnalog);
SCWrite(pCon,pBueffel,eValue);
sprintf(pBueffel,"%s.controlheat = %d",argv[0],pMe->iControlHeat);
SCWrite(pCon,pBueffel,eValue);
iRet = LTC11GetMode(self->pDriv,&iMode);
if(iRet != 1)
{
self->pDriv->GetError(self->pDriv,&iMode,pError,131);
sprintf(pBueffel,"ERROR: failed to get mode %s",pError);
SCWrite(pCon,pBueffel,eError);
}
if(iMode == ANALOG)
{
sprintf(pBueffel,"%s.mode = Analog Control", argv[0]);
}
else
{
sprintf(pBueffel,"%s.mode = Heater Control", argv[0]);
}
SCWrite(pCon,pBueffel,eValue);
return 1;
}
else
{
return EVControlWrapper(pCon,pSics,pData,argc,argv);
}
}
return EVControlWrapper(pCon,pSics,pData,argc,argv);
}