Files
sics/eurodriv.c
cvs e3cd728ecb - 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


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
2003-06-20 10:17:44 +00:00

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;
}