- 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 SKIPPED: psi/A1931.c psi/A1931.h psi/amor2t.c psi/amor2t.h psi/amor2t.i psi/amor2t.tex psi/amor2t.w psi/amorscan.c psi/amorscan.h psi/amorscan.w psi/amorstat.c psi/amorstat.h psi/amorstat.i psi/amorstat.tex psi/amorstat.w psi/bruker.c psi/bruker.h psi/bruker.w psi/buffer.c psi/buffer.h psi/dilludriv.c psi/dilludriv.h psi/dmc.c psi/dmc.h psi/dmc.w psi/docho.c psi/ecb.c psi/ecb.h psi/ecb.i psi/ecb.w psi/ecbdriv.c psi/ecbdriv.h psi/el734dc.c psi/el734driv.c psi/el755driv.c psi/el755driv.h psi/faverage.c psi/faverage.h psi/faverage.tex psi/faverage.w psi/fowrite.c psi/fowrite.h psi/itc4.c psi/itc4.h psi/itc4.w psi/itc4driv.c psi/ltc11.c psi/ltc11.h psi/nextrics.c psi/nextrics.h psi/nxamor.c psi/nxamor.h psi/nxamor.tex psi/nxamor.w psi/pimotor.c psi/pimotor.h psi/pimotor.tex psi/pimotor.w psi/pipiezo.c psi/polterwrite.c psi/polterwrite.h psi/psi.c psi/ruli.c psi/ruli.h psi/sanscook.c psi/sanswave.c psi/sanswave.h psi/sanswave.tex psi/sanswave.w psi/serial.c psi/serial.h psi/serial.w psi/sinqhmdriv.c psi/sinqhmdriv.i psi/sinqhmdriv.w psi/slsmagnet.c psi/sps.c psi/sps.h psi/sps.i psi/sps.tex psi/sps.w psi/swmotor.c psi/swmotor.h psi/swmotor.i psi/tas.c psi/tas.h psi/tas.tex psi/tas.w psi/tasdrive.c psi/tasinit.c psi/tasscan.c psi/tasu.h psi/tasutil.c psi/tdchm.c psi/tdchm.h psi/tecsdriv.c psi/tecsdriv.h psi/velodorn.c psi/velodorn.h psi/velodorn.w psi/velodornier.c psi/hardsup/README psi/hardsup/StrMatch.c psi/hardsup/asynsrv_def.h psi/hardsup/asynsrv_errcodes.h psi/hardsup/asynsrv_mark.c psi/hardsup/asynsrv_utility.c psi/hardsup/c_interfaces.c psi/hardsup/dillutil.c psi/hardsup/dillutil.h psi/hardsup/el734_def.h psi/hardsup/el734_errcodes.h psi/hardsup/el734_utility.c psi/hardsup/el734fix.h psi/hardsup/el734tcl.c psi/hardsup/el737_def.h psi/hardsup/el737_errcodes.h psi/hardsup/el737_utility.c psi/hardsup/el737fix.h psi/hardsup/el737tcl.c psi/hardsup/el755_def.h psi/hardsup/el755_errcodes.h psi/hardsup/el755_errorlog.c psi/hardsup/el755_utility.c psi/hardsup/err.c psi/hardsup/failinet.c psi/hardsup/geterrno.c psi/hardsup/itc4util.c psi/hardsup/itc4util.h psi/hardsup/make_gen psi/hardsup/makefile_alpha psi/hardsup/makefile_linux psi/hardsup/makeprint.c psi/hardsup/rs232c_def.h psi/hardsup/serialsinq.c psi/hardsup/serialsinq.h psi/hardsup/sinq_defs.h psi/hardsup/sinq_prototypes.h psi/hardsup/sinqhm.c psi/hardsup/sinqhm.h psi/hardsup/sinqhm_def.h psi/hardsup/stredit.c psi/hardsup/strjoin.c psi/hardsup/table.c psi/hardsup/table.h psi/hardsup/velsel_def.h psi/hardsup/velsel_utility.c psi/motor/Makefile psi/motor/el734_test psi/motor/el734_test.c psi/motor/makeprint.c psi/sinqhm/FOCUS_gbl.h psi/sinqhm/FOCUS_srv_main.c psi/sinqhm/Makefile psi/sinqhm/SinqHM_bootParamsConfig.c psi/sinqhm/SinqHM_bootUtil.c psi/sinqhm/SinqHM_def.h psi/sinqhm/SinqHM_gbl.h psi/sinqhm/SinqHM_srv_filler.c psi/sinqhm/SinqHM_srv_main.c psi/sinqhm/SinqHM_srv_routines.c psi/sinqhm/SinqHM_srv_server.c psi/sinqhm/bld psi/sinqhm/bld2 psi/sinqhm/bldmen psi/sinqhm/hist_mem_notes.tex psi/sinqhm/hist_mem_spec.tex psi/sinqhm/hist_mem_spec_fig1.ps psi/sinqhm/hist_mem_spec_fig2.ps psi/sinqhm/hist_mem_spec_fig3.ps psi/sinqhm/hist_mem_spec_fig4.ps psi/sinqhm/lwl_client.c psi/sinqhm/lwl_server.c psi/sinqhm/make_sinqhm.com psi/sinqhm/monitor.c psi/sinqhm/psi_logo.ps psi/sinqhm/sinq_logo.ps psi/sinqhm/sinqhm_bootutil_client.c psi/sinqhm/sinqhm_client.c psi/sinqhm/sinqhm_ctrl.c psi/sinqhm/usrConfig.c psi/sinqhm/usrConfig.c_diffs psi/sinqhm/usrConfig2604.c psi/sinqhm/vmio10_def.h psi/sinqhm/vmio_utility.c psi/tecs/coc_client.c psi/tecs/coc_client.h psi/tecs/coc_logfile.c psi/tecs/coc_logfile.h psi/tecs/coc_server.c psi/tecs/coc_server.h psi/tecs/coc_util.c psi/tecs/coc_util.h psi/tecs/fortify1.c psi/tecs/instr_hosts.c psi/tecs/instr_hosts.h psi/tecs/keep_running.c psi/tecs/make_gen psi/tecs/make_opt psi/tecs/make_opt_alpha psi/tecs/make_opt_llc psi/tecs/makefile psi/tecs/makefile_alpha psi/tecs/makefile_linux psi/tecs/myc_buf.c psi/tecs/myc_buf.h psi/tecs/myc_err.c psi/tecs/myc_err.h psi/tecs/myc_fortran.h psi/tecs/myc_mem.h psi/tecs/myc_str.c psi/tecs/myc_str.h psi/tecs/myc_time.c psi/tecs/myc_time.h psi/tecs/myc_tmp.c psi/tecs/myc_tmp.h psi/tecs/rstart.c psi/tecs/six.c psi/tecs/str.f psi/tecs/sys_cmdpar.f psi/tecs/sys_date.f psi/tecs/sys_env.c psi/tecs/sys_get_key.f psi/tecs/sys_getenv.f psi/tecs/sys_lun.f psi/tecs/sys_open.f psi/tecs/sys_open_alpha.f psi/tecs/sys_rdline.c psi/tecs/sys_select.c psi/tecs/sys_select.h psi/tecs/sys_unix.c psi/tecs/sys_wait.f psi/tecs/tecs.bld psi/tecs/tecs.c psi/tecs/tecs.tcl psi/tecs/tecs_c.c psi/tecs/tecs_c.h psi/tecs/tecs_cli.c psi/tecs/tecs_cli.h psi/tecs/tecs_client.f psi/tecs/tecs_data.c psi/tecs/tecs_data.h psi/tecs/tecs_dlog.inc psi/tecs/tecs_for.f psi/tecs/tecs_lsc.c psi/tecs/tecs_lsc.h psi/tecs/tecs_plot.f psi/tecs/tecs_serial.c psi/tecs/tecs_serial.h psi/tecs/term.c psi/tecs/term.h psi/utils/Makefile psi/utils/SerPortServer.c psi/utils/asynsrv_test.c psi/utils/ecb-load.c psi/utils/el734.c psi/utils/el734_test.c psi/utils/el737.c psi/utils/make.ecb psi/utils/check/amorcheck psi/utils/check/dmccheck psi/utils/check/focuscheck psi/utils/check/focusstatus.tcl psi/utils/check/hrptcheck psi/utils/check/sanscheck psi/utils/check/sicssyntax.tex psi/utils/check/sicssyntaxlib.tcl psi/utils/check/test.tcl psi/utils/check/topsicheck psi/utils/check/tricscheck psi/utils/check/tst
396 lines
10 KiB
C
396 lines
10 KiB
C
/*--------------------------------------------------------------------------
|
|
E U R O D R I V
|
|
|
|
This file contains the implementation for the Eurotherm temperature
|
|
controller as used at SANS. The Eurotherm is a grossly strange device
|
|
which has a very weird command protocoll. The implementation here uses
|
|
the EI-Bisynch Protocoll option. This has to be configured in the
|
|
Eurotherm on the manual interface!! Also watch out for the unusual RS232-
|
|
setting: 7 bits, even parity, 1 stop bit.
|
|
|
|
Mark Koennecke, May 1999
|
|
|
|
Copyright: see copyright.h
|
|
----------------------------------------------------------------------------*/
|
|
#include <string.h>
|
|
#include <stdlib.h>
|
|
#include <time.h>
|
|
#include <math.h>
|
|
#include <assert.h>
|
|
#include "fortify.h"
|
|
#include "conman.h"
|
|
#include "servlog.h"
|
|
#include "fortify.h"
|
|
|
|
typedef struct __EVDriver *pEVDriver;
|
|
|
|
#include "evdriver.i"
|
|
#include "psi/hardsup/el734_def.h"
|
|
#include "psi/hardsup/el734fix.h"
|
|
#include "psi/hardsup/serialsinq.h"
|
|
#include "eurodriv.h"
|
|
|
|
#define INVALIDANSWER -1005
|
|
#define INVALIDNUMBER -1006
|
|
#define ERRNAK -1007
|
|
#define NOSEND -1008
|
|
/*-----------------------------------------------------------------------*/
|
|
typedef struct {
|
|
void *pData;
|
|
char *pHost;
|
|
int iPort;
|
|
int iChannel;
|
|
int iLastError;
|
|
} EuroDriv, *pEuroDriv;
|
|
|
|
/*------------------------------------------------------------------------*/
|
|
int EuroGetParameter(void **pData, char *pPar,int iLen, float *fVal)
|
|
{
|
|
char pCommand[20];
|
|
char pReply[20];
|
|
char *pStart = NULL, *pEnd = NULL;
|
|
int iRet,i;
|
|
|
|
/* configure the serial port */
|
|
SerialATerm(pData,"1\x3"); /* ETX */
|
|
pCommand[0] = '\x4'; /* EOT */
|
|
pCommand[1] = '0'; /* GID*/
|
|
pCommand[2] = '0'; /* GID*/
|
|
pCommand[3] = '1'; /* UID*/
|
|
pCommand[4] = '1'; /* UID*/
|
|
pCommand[5] = '1'; /* CHAN */
|
|
for(i = 0; i < iLen; i++)
|
|
{
|
|
pCommand[6+i] = pPar[i];
|
|
}
|
|
pCommand[6+iLen] = '\x5'; /* ENQ*/
|
|
pCommand[7+iLen] = '\0';
|
|
|
|
/* send */
|
|
iRet = SerialWriteRead(pData,pCommand,pReply,19);
|
|
if(iRet != 1)
|
|
{
|
|
return iRet;
|
|
}
|
|
|
|
/* decode reply */
|
|
pStart = strstr(pReply,pPar);
|
|
if(!pStart)
|
|
{
|
|
if(strstr(pReply,"?TMO"))
|
|
{
|
|
return EL734__BAD_TMO;
|
|
}
|
|
else
|
|
{
|
|
return INVALIDANSWER;
|
|
}
|
|
}
|
|
iRet = sscanf(pStart+strlen(pPar),"%f",fVal);
|
|
if(iRet != 1)
|
|
{
|
|
return INVALIDNUMBER;
|
|
}
|
|
return 1;
|
|
}
|
|
/*------------------------------------------------------------------------*/
|
|
int EuroSetParameter(void **pData, char *pPar,int iLen,
|
|
char *pFormat, float fVal)
|
|
{
|
|
char pCommand[30];
|
|
char pNum[10];
|
|
char *pPtr, *pPtr2;
|
|
char pReply[20];
|
|
char bcc;
|
|
int iRet,i;
|
|
|
|
|
|
/* configure the serial port */
|
|
SerialATerm(pData,"1\x06\x15"); /* ACK,NAK */
|
|
pCommand[0] = '\x04'; /* EOT */
|
|
pCommand[1] = '0'; /* GID*/
|
|
pCommand[2] = '0'; /* GID*/
|
|
pCommand[3] = '1'; /* UID*/
|
|
pCommand[4] = '1'; /* UID*/
|
|
pCommand[5] = '\x02';
|
|
pCommand[6] = '1'; /* CHAN */
|
|
for(i = 0; i < iLen; i++)
|
|
{
|
|
pCommand[7+i] = pPar[i];
|
|
}
|
|
pPtr = pCommand + 7 + iLen;
|
|
sprintf(pNum,pFormat,fVal);
|
|
strcpy(pPtr,pNum);
|
|
pPtr += strlen(pNum);
|
|
*pPtr = '\x03';
|
|
pPtr++;
|
|
|
|
/* build the checksum */
|
|
bcc = pCommand[6];
|
|
pPtr2 = &pCommand[7];
|
|
while(pPtr2 != pPtr)
|
|
{
|
|
bcc = bcc ^ *pPtr2;
|
|
pPtr2++;
|
|
}
|
|
*pPtr = bcc;
|
|
pPtr++;
|
|
*pPtr = '\0';
|
|
|
|
/* send */
|
|
iRet = SerialSend(pData,pCommand);
|
|
if(iRet != 1)
|
|
{
|
|
return iRet;
|
|
}
|
|
iRet = SerialReceiveWithTerm(pData,pReply,19,&bcc);
|
|
/*
|
|
printf("%s\n",pReply);
|
|
*/
|
|
if(iRet != 1)
|
|
{
|
|
return iRet;
|
|
}
|
|
if(bcc == '\x15')
|
|
{
|
|
return ERRNAK;
|
|
}
|
|
if(strstr(pReply,"?TMO"))
|
|
{
|
|
return EL734__BAD_TMO;
|
|
}
|
|
|
|
return 1;
|
|
}
|
|
/*---------------------------------------------------------------------------*/
|
|
static int GetEuroPos(pEVDriver self, float *fPos)
|
|
{
|
|
pEuroDriv pMe = NULL;
|
|
int iRet;
|
|
|
|
assert(self);
|
|
pMe = (pEuroDriv)self->pPrivate;
|
|
assert(pMe);
|
|
|
|
iRet = EuroGetParameter(&(pMe->pData),"PV",2,fPos);
|
|
if(iRet != 1)
|
|
{
|
|
pMe->iLastError = iRet;
|
|
return 0;
|
|
}
|
|
return 1;
|
|
}
|
|
/*----------------------------------------------------------------------------*/
|
|
static int EuroRun(pEVDriver self, float fVal)
|
|
{
|
|
pEuroDriv pMe = NULL;
|
|
int iRet;
|
|
|
|
assert(self);
|
|
pMe = (pEuroDriv )self->pPrivate;
|
|
assert(pMe);
|
|
|
|
iRet = EuroSetParameter(&(pMe->pData),"SL",2,"%4.1f",fVal);
|
|
if(iRet != 1)
|
|
{
|
|
pMe->iLastError = iRet;
|
|
return 0;
|
|
}
|
|
return 1;
|
|
}
|
|
/*--------------------------------------------------------------------------*/
|
|
static int EuroError(pEVDriver self, int *iCode, char *error, int iErrLen)
|
|
{
|
|
pEuroDriv pMe = NULL;
|
|
|
|
assert(self);
|
|
pMe = (pEuroDriv)self->pPrivate;
|
|
assert(pMe);
|
|
|
|
*iCode = pMe->iLastError;
|
|
switch(pMe->iLastError)
|
|
{
|
|
case INVALIDANSWER:
|
|
strncpy(error,"Unexpected reply from Eurotherm",iErrLen);
|
|
break;
|
|
case INVALIDNUMBER:
|
|
strncpy(error,"No number in Eurotherm answer",iErrLen);
|
|
break;
|
|
case ERRNAK:
|
|
strncpy(error,"Eurothem did NOT acknowledge command",iErrLen);
|
|
break;
|
|
case NOSEND:
|
|
strncpy(error,
|
|
"Eurotherm has a bizarre protocoll, sending things is very STUPID",iErrLen);
|
|
break;
|
|
default:
|
|
SerialError(pMe->iLastError,error,iErrLen);
|
|
break;
|
|
}
|
|
|
|
return 1;
|
|
}
|
|
/*--------------------------------------------------------------------------*/
|
|
static int EuroSend(pEVDriver self, char *pCommand, char *pReply, int iLen)
|
|
{
|
|
pEuroDriv pMe = NULL;
|
|
|
|
assert(self);
|
|
pMe = (pEuroDriv)self->pPrivate;
|
|
assert(pMe);
|
|
|
|
pMe->iLastError = NOSEND;
|
|
strncpy(pReply,"ERROR: Eurotherm does not support send functionality",
|
|
iLen);
|
|
return 0;
|
|
}
|
|
/*--------------------------------------------------------------------------*/
|
|
static int EuroInit(pEVDriver self)
|
|
{
|
|
pEuroDriv pMe = NULL;
|
|
int iRet;
|
|
|
|
assert(self);
|
|
pMe = (pEuroDriv )self->pPrivate;
|
|
assert(pMe);
|
|
|
|
pMe->pData = NULL;
|
|
iRet = SerialOpen(&pMe->pData, pMe->pHost, pMe->iPort, pMe->iChannel);
|
|
if(iRet != 1)
|
|
{
|
|
pMe->iLastError = iRet;
|
|
return 0;
|
|
}
|
|
SerialSendTerm(&pMe->pData,"");
|
|
return 1;
|
|
}
|
|
/*--------------------------------------------------------------------------*/
|
|
static int EuroClose(pEVDriver self)
|
|
{
|
|
pEuroDriv pMe = NULL;
|
|
int iRet;
|
|
|
|
assert(self);
|
|
pMe = (pEuroDriv )self->pPrivate;
|
|
assert(pMe);
|
|
|
|
SerialClose(&pMe->pData);
|
|
return 1;
|
|
}
|
|
/*---------------------------------------------------------------------------*/
|
|
static int EuroFix(pEVDriver self, int iError)
|
|
{
|
|
pEuroDriv pMe = NULL;
|
|
int iRet;
|
|
|
|
assert(self);
|
|
pMe = (pEuroDriv )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:
|
|
EuroClose(self);
|
|
iRet = EuroInit(self);
|
|
if(iRet)
|
|
{
|
|
return DEVREDO;
|
|
}
|
|
else
|
|
{
|
|
return DEVFAULT;
|
|
}
|
|
break;
|
|
/* handable protocoll errors */
|
|
case EL734__BAD_TMO:
|
|
return DEVREDO;
|
|
break;
|
|
case ERRNAK:
|
|
case NOSEND:
|
|
case INVALIDANSWER:
|
|
case INVALIDNUMBER:
|
|
return DEVFAULT;
|
|
default:
|
|
return DEVFAULT;
|
|
break;
|
|
}
|
|
return DEVFAULT;
|
|
}
|
|
|
|
/*--------------------------------------------------------------------------*/
|
|
static int EuroHalt(pEVDriver *self)
|
|
{
|
|
assert(self);
|
|
|
|
return 1;
|
|
}
|
|
/*------------------------------------------------------------------------*/
|
|
void KillEuro(void *pData)
|
|
{
|
|
pEuroDriv pMe = NULL;
|
|
|
|
pMe = (pEuroDriv)pData;
|
|
assert(pMe);
|
|
|
|
if(pMe->pHost)
|
|
{
|
|
free(pMe->pHost);
|
|
}
|
|
free(pMe);
|
|
}
|
|
/*------------------------------------------------------------------------*/
|
|
pEVDriver CreateEURODriv(int argc, char *argv[])
|
|
{
|
|
pEVDriver pNew = NULL;
|
|
pEuroDriv pSim = NULL;
|
|
|
|
/* check for arguments */
|
|
if(argc < 3)
|
|
{
|
|
return NULL;
|
|
}
|
|
|
|
pNew = CreateEVDriver(argc,argv);
|
|
pSim = (pEuroDriv)malloc(sizeof(EuroDriv));
|
|
memset(pSim,0,sizeof(EuroDriv));
|
|
if(!pNew || !pSim)
|
|
{
|
|
return NULL;
|
|
}
|
|
pNew->pPrivate = pSim;
|
|
pNew->KillPrivate = KillEuro;
|
|
|
|
/* initalise pDILLUDriver */
|
|
pSim->iLastError = 0;
|
|
pSim->pHost = strdup(argv[0]);
|
|
pSim->iPort = atoi(argv[1]);
|
|
pSim->iChannel = atoi(argv[2]);
|
|
|
|
/* initialise function pointers */
|
|
pNew->SetValue = EuroRun;
|
|
pNew->GetValue = GetEuroPos;
|
|
pNew->Send = EuroSend;
|
|
pNew->GetError = EuroError;
|
|
pNew->TryFixIt = EuroFix;
|
|
pNew->Init = EuroInit;
|
|
pNew->Close = EuroClose;
|
|
|
|
return pNew;
|
|
}
|
|
|
|
|
|
|