required inclusion of a matrix package. - modified counter error handling to send a Stop when the _BAD_BUSY error is received. - added an environment interface to the general controller stuff in choco.* Also added setting a parameter directly at the controller object. - Added a driver for the ETH High Temperature Furnace to be used at SANS.
1438 lines
42 KiB
C
1438 lines
42 KiB
C
/*---------------------------------------------------------------------------
|
|
E N V I R O N M E N T C O N T R O L L E R
|
|
|
|
This is the implementation file for a base class for all environement
|
|
control devices in SICS.
|
|
|
|
Mark Koennecke, Juli 1997
|
|
|
|
Copyright:
|
|
|
|
Labor fuer Neutronenstreuung
|
|
Paul Scherrer Institut
|
|
CH-5423 Villigen-PSI
|
|
|
|
|
|
The authors hereby grant permission to use, copy, modify, distribute,
|
|
and license this software and its documentation for any purpose, provided
|
|
that existing copyright notices are retained in all copies and that this
|
|
notice is included verbatim in any distributions. No written agreement,
|
|
license, or royalty fee is required for any of the authorized uses.
|
|
Modifications to this software may be copyrighted by their authors
|
|
and need not follow the licensing terms described here, provided that
|
|
the new terms are clearly indicated on the first page of each file where
|
|
they apply.
|
|
|
|
IN NO EVENT SHALL THE AUTHORS OR DISTRIBUTORS BE LIABLE TO ANY PARTY
|
|
FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
|
|
ARISING OUT OF THE USE OF THIS SOFTWARE, ITS DOCUMENTATION, OR ANY
|
|
DERIVATIVES THEREOF, EVEN IF THE AUTHORS HAVE BEEN ADVISED OF THE
|
|
POSSIBILITY OF SUCH DAMAGE.
|
|
|
|
THE AUTHORS AND DISTRIBUTORS SPECIFICALLY DISCLAIM ANY WARRANTIES,
|
|
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY,
|
|
FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT. THIS SOFTWARE
|
|
IS PROVIDED ON AN "AS IS" BASIS, AND THE AUTHORS AND DISTRIBUTORS HAVE
|
|
NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR
|
|
MODIFICATIONS.
|
|
----------------------------------------------------------------------------*/
|
|
#include <string.h>
|
|
#include <stdlib.h>
|
|
#include <assert.h>
|
|
#include <tcl.h>
|
|
#include "fortify.h"
|
|
#include "splitter.h"
|
|
#include "sics.h"
|
|
#include "obpar.h"
|
|
#include "devexec.h"
|
|
#include "nserver.h"
|
|
#include "interrupt.h"
|
|
#include "emon.h"
|
|
#include "varlog.h"
|
|
#include "evcontroller.h"
|
|
#include "evcontroller.i"
|
|
#include "evdriver.i"
|
|
#include "simev.h"
|
|
#include "itc4.h"
|
|
#include "dilludriv.h"
|
|
#include "tclev.h"
|
|
#include "bruker.h"
|
|
#include "ltc11.h"
|
|
#include "eurodriv.h"
|
|
#include "el755driv.h"
|
|
#include "tecsdriv.h"
|
|
#include "chadapter.h"
|
|
/*--------------------- Functions needed to implement interfaces -----------*/
|
|
static long EVIDrive(void *pData, SConnection *pCon, float fVal)
|
|
{
|
|
pEVControl self = NULL;
|
|
int iRet, iCode, i, iFix;
|
|
char pError[132], pBueffel[256];
|
|
|
|
self = (pEVControl)pData;
|
|
assert(self);
|
|
assert(pCon);
|
|
|
|
self->fTarget = fVal;
|
|
self->eMode = EVDrive;
|
|
self->iStop = 0;
|
|
|
|
/* try at least three times to do it */
|
|
for(i = 0; i < 3; i++)
|
|
{
|
|
iRet = self->pDriv->SetValue(self->pDriv,fVal);
|
|
if(!iRet)
|
|
{
|
|
self->pDriv->GetError(self->pDriv,&iCode, pError,131);
|
|
iFix = self->pDriv->TryFixIt(self->pDriv,iCode);
|
|
switch(iFix)
|
|
{
|
|
case DEVOK:
|
|
return 1;
|
|
break;
|
|
case DEVFAULT:
|
|
sprintf(pBueffel,"ERROR: %s",pError);
|
|
SCWrite(pCon,pBueffel,eError);
|
|
return 0;
|
|
case DEVREDO:
|
|
sprintf(pBueffel,"WARNING: Fixing problem %s",pError);
|
|
SCWrite(pCon,pBueffel,eWarning);
|
|
break;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
return 1;
|
|
}
|
|
}
|
|
SCWrite(pCon,"ERROR: Failed to fix previous problems, Device Error",
|
|
eError);
|
|
return 0;
|
|
}
|
|
/*---------------------------------------------------------------------------*/
|
|
static float EVIGet(void *pData, SConnection *pCon)
|
|
{
|
|
pEVControl self = NULL;
|
|
int iRet, iCode, i, iFix;
|
|
char pError[132], pBueffel[256];
|
|
float fPos = -999.;
|
|
int iPendingCount = 0;
|
|
|
|
self = (pEVControl)pData;
|
|
assert(self);
|
|
assert(pCon);
|
|
|
|
/* try at least three times to do it */
|
|
for(i = 0; i < 5; i++)
|
|
{
|
|
iRet = self->pDriv->GetValue(self->pDriv,&fPos);
|
|
if(iRet == 0)
|
|
{
|
|
self->pDriv->GetError(self->pDriv,&iCode, pError,131);
|
|
iFix = self->pDriv->TryFixIt(self->pDriv,iCode);
|
|
switch(iFix)
|
|
{
|
|
case DEVOK:
|
|
return fPos;
|
|
break;
|
|
case DEVFAULT:
|
|
sprintf(pBueffel,"ERROR: %s",pError);
|
|
SCWrite(pCon,pBueffel,eError);
|
|
return -999.;
|
|
case DEVREDO:
|
|
sprintf(pBueffel,"WARNING: Fixing problem %s",pError);
|
|
SCWrite(pCon,pBueffel,eWarning);
|
|
break;
|
|
}
|
|
}
|
|
else if(iRet == -1 ) /* pending */
|
|
{
|
|
i--;
|
|
iPendingCount++;
|
|
if(iPendingCount > 300)
|
|
{
|
|
SCWrite(pCon,"ERROR: cannot get data from socket",eError);
|
|
return -999.;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
return fPos;
|
|
}
|
|
}
|
|
SCWrite(pCon,"ERROR: Failed to fix previous problems, Device Error",
|
|
eError);
|
|
return -999.;
|
|
}
|
|
/*---------------------------------------------------------------------------*/
|
|
static int EVIStatus(void *pData, SConnection *pCon)
|
|
{
|
|
pEVControl self = NULL;
|
|
float fPos, fDelta;
|
|
int iRet, iCode, iFix;
|
|
char pBueffel[256], pError[132];
|
|
static int iCount;
|
|
|
|
self = (pEVControl)pData;
|
|
assert(self);
|
|
assert(pCon);
|
|
|
|
/* go to idle when stopped */
|
|
if(self->iStop)
|
|
{
|
|
return HWIdle;
|
|
}
|
|
|
|
/* get the current position */
|
|
|
|
iRet = self->pDriv->GetValue(self->pDriv,&fPos);
|
|
|
|
if(iRet == 0)
|
|
{
|
|
self->pDriv->GetError(self->pDriv,&iCode, pError,131);
|
|
iFix = self->pDriv->TryFixIt(self->pDriv,iCode);
|
|
switch(iFix)
|
|
{
|
|
case DEVOK:
|
|
return HWBusy;
|
|
break;
|
|
case DEVFAULT:
|
|
sprintf(pBueffel,"ERROR: %s",pError);
|
|
SCWrite(pCon,pBueffel,eError);
|
|
return HWFault;
|
|
case DEVREDO:
|
|
sprintf(pBueffel,"WARNING: Fixing problem %s",pError);
|
|
SCWrite(pCon,pBueffel,eWarning);
|
|
return HWBusy;
|
|
break;
|
|
}
|
|
}
|
|
else if(iRet == -1 ) /* pending */
|
|
{
|
|
return HWBusy;
|
|
}
|
|
|
|
if(fPos < -990.)
|
|
{
|
|
sprintf(pBueffel,"ERROR: %s cannot read its current value",
|
|
self->pName);
|
|
SCWrite(pCon,pBueffel,eError);
|
|
self->eMode = EVIdle;
|
|
return HWFault;
|
|
}
|
|
|
|
/* calculate difference to target */
|
|
fDelta = self->fTarget - fPos;
|
|
if(fDelta < 0.)
|
|
{
|
|
fDelta = - fDelta;
|
|
}
|
|
|
|
/* based on this: logic ! */
|
|
if(fDelta <= ObVal(self->pParam, TOLERANCE)) /* done */
|
|
{
|
|
iCount++;
|
|
if(iCount > 3)
|
|
{
|
|
self->eMode = EVMonitor;
|
|
return HWIdle;
|
|
}
|
|
else
|
|
{
|
|
return HWBusy;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
iCount = 0;
|
|
return HWBusy;
|
|
}
|
|
self->eMode = EVIdle;
|
|
return HWFault;
|
|
}
|
|
/*--------------------------------------------------------------------------*/
|
|
static int EVILimits(void *pData, float fVal, char *pError, int iErrLen)
|
|
{
|
|
pEVControl self = NULL;
|
|
char pBueffel[256];
|
|
|
|
self = (pEVControl)pData;
|
|
assert(self);
|
|
|
|
/* lower limit */
|
|
if( fVal < ObVal(self->pParam, LOWLIMIT))
|
|
{
|
|
sprintf(pBueffel,"ERROR: %f violates lower limit of device",fVal);
|
|
strncpy(pError,pBueffel,iErrLen);
|
|
return 0;
|
|
}
|
|
|
|
/* upper limit */
|
|
if( fVal > ObVal(self->pParam, UPLIMIT))
|
|
{
|
|
sprintf(pBueffel,"ERROR: %f violates upper limit of device",fVal);
|
|
strncpy(pError,pBueffel,iErrLen);
|
|
return 0;
|
|
}
|
|
|
|
/* OK */
|
|
return 1;
|
|
}
|
|
/*---------------------------------------------------------------------------*/
|
|
static int EVIHalt(void *pData)
|
|
{
|
|
pEVControl self = NULL;
|
|
float fPos;
|
|
int iRet, iRes;
|
|
|
|
self = (pEVControl)pData;
|
|
assert(self);
|
|
|
|
iRes = 1;
|
|
self->eMode = EVIdle;
|
|
self->iStop = 1;
|
|
|
|
return iRes;
|
|
}
|
|
/*---------------------------- Error Handlers --------------------------------*/
|
|
static int ErrLazy(void *pData)
|
|
{
|
|
pEVControl self = NULL;
|
|
pExeList pExe;
|
|
SConnection *pCon = NULL;
|
|
float fPos;
|
|
char pBueffel[256];
|
|
|
|
self = (pEVControl)pData;
|
|
assert(self);
|
|
|
|
|
|
self->pDriv->GetValue(self->pDriv,&fPos);
|
|
sprintf(pBueffel,"WARNING: %s is out of range by %f",self->pName,
|
|
self->fTarget - fPos);
|
|
pExe = GetExecutor();
|
|
pCon = GetExeOwner(pExe);
|
|
if(!self->iWarned)
|
|
{
|
|
if(pCon)
|
|
{
|
|
SCWrite(pCon,pBueffel,eWarning);
|
|
}
|
|
else
|
|
{
|
|
ServerWriteGlobal(pBueffel,eWarning);
|
|
}
|
|
}
|
|
self->iWarned = 1;
|
|
return 1;
|
|
}
|
|
/*--------------------------------------------------------------------------*/
|
|
static int ErrPause(void *pData)
|
|
{
|
|
pEVControl self = NULL;
|
|
pExeList pExe;
|
|
SConnection *pCon = NULL;
|
|
float fPos;
|
|
char pBueffel[256];
|
|
int iRet;
|
|
|
|
self = (pEVControl)pData;
|
|
assert(self);
|
|
|
|
|
|
self->pDriv->GetValue(self->pDriv,&fPos);
|
|
sprintf(pBueffel,"WARNING: %s is out of range by %f",self->pName,
|
|
self->fTarget - fPos);
|
|
pExe = GetExecutor();
|
|
pCon = GetExeOwner(pExe);
|
|
|
|
if(!self->iWarned)
|
|
{
|
|
if(pCon)
|
|
{
|
|
SCWrite(pCon,pBueffel,eWarning);
|
|
}
|
|
else
|
|
{
|
|
ServerWriteGlobal(pBueffel,eWarning);
|
|
}
|
|
}
|
|
self->iWarned = 1;
|
|
|
|
|
|
if(IsCounting(pExe))
|
|
{
|
|
SCWrite(GetExeOwner(pExe),"Pausing till OK",eError);
|
|
PauseExecution(pExe);
|
|
|
|
/* wait till OK */
|
|
iRet = 0;
|
|
while(iRet == 0)
|
|
{
|
|
SicsWait(5);
|
|
iRet = self->pEnvir->IsInTolerance(self);
|
|
|
|
}
|
|
|
|
/* OK now, continue */
|
|
ContinueExecution(pExe);
|
|
return 1;
|
|
}
|
|
return 1;
|
|
}
|
|
/*---------------------------------------------------------------------------*/
|
|
static int ErrInterrupt(void *pData)
|
|
{
|
|
pEVControl self = NULL;
|
|
pExeList pExe;
|
|
SConnection *pCon = NULL;
|
|
float fPos;
|
|
char pBueffel[256];
|
|
int iRet;
|
|
|
|
self = (pEVControl)pData;
|
|
assert(self);
|
|
|
|
/* report problem */
|
|
self->pDriv->GetValue(self->pDriv,&fPos);
|
|
sprintf(pBueffel,"WARNING: %s is out of range by %f",self->pName,
|
|
self->fTarget - fPos);
|
|
pExe = GetExecutor();
|
|
pCon = GetExeOwner(pExe);
|
|
if(!self->iWarned)
|
|
{
|
|
if(pCon)
|
|
{
|
|
SCWrite(pCon,pBueffel,eWarning);
|
|
}
|
|
else
|
|
{
|
|
ServerWriteGlobal(pBueffel,eWarning);
|
|
}
|
|
}
|
|
self->iWarned = 1;
|
|
|
|
/* interrupt */
|
|
SetInterrupt((int)ObVal(self->pParam,INTERRUPT));
|
|
return 1;
|
|
}
|
|
/*---------------------------------------------------------------------------*/
|
|
static int ErrRun(void *pData)
|
|
{
|
|
pEVControl self = NULL;
|
|
pExeList pExe;
|
|
SConnection *pCon = NULL;
|
|
float fPos;
|
|
char pBueffel[256];
|
|
int iRet;
|
|
|
|
self = (pEVControl)pData;
|
|
assert(self);
|
|
|
|
/* report problem */
|
|
self->pDriv->GetValue(self->pDriv,&fPos);
|
|
sprintf(pBueffel,"WARNING: %s is out of range by %f",self->pName,
|
|
self->fTarget - fPos);
|
|
pExe = GetExecutor();
|
|
pCon = GetExeOwner(pExe);
|
|
if(pCon)
|
|
{
|
|
SCWrite(pCon,pBueffel,eWarning);
|
|
SCWrite(pCon,"Driving to a safe place",eWarning);
|
|
}
|
|
else
|
|
{
|
|
ServerWriteGlobal(pBueffel,eWarning);
|
|
ServerWriteGlobal("Driving to a safe place",eWarning);
|
|
}
|
|
|
|
self->pDriv->SetValue(self->pDriv, ObVal(self->pParam,SAFEVALUE));
|
|
self->eMode = EVIdle;
|
|
return 1;
|
|
}
|
|
/*---------------------------------------------------------------------------*/
|
|
static int EVIErrHandler(void *pData)
|
|
{
|
|
pEVControl self = NULL;
|
|
int iRet, iHandler, iStatus;
|
|
|
|
self = (pEVControl)pData;
|
|
assert(self);
|
|
|
|
/* select an error handler according to the variable set
|
|
in Controller
|
|
*/
|
|
iHandler = (int)ObVal(self->pParam, ERRORHANDLER);
|
|
self->eMode = EVError;
|
|
switch(iHandler)
|
|
{
|
|
case 0: /* no op */
|
|
iStatus = ErrLazy(pData);
|
|
break;
|
|
case 1: /* Pause */
|
|
iStatus = ErrPause(pData);
|
|
break;
|
|
case 2: /* Interrupt */
|
|
iStatus = ErrInterrupt(pData);
|
|
break;
|
|
case 3: /* run to a safe place, put him into idle afterwards */
|
|
iStatus = ErrRun(pData);
|
|
return iStatus;
|
|
break;
|
|
default:
|
|
return 0;
|
|
|
|
}
|
|
/* reset mode to monitor again! */
|
|
self->eMode = EVMonitor;
|
|
return iStatus;
|
|
}
|
|
/*---------------------------------------------------------------------------*/
|
|
static EVMode EVIGetMode(void *pData)
|
|
{
|
|
pEVControl self = NULL;
|
|
|
|
self = (pEVControl)pData;
|
|
assert(self);
|
|
|
|
return self->eMode;
|
|
}
|
|
/*--------------------------------------------------------------------------*/
|
|
static int EVIIsInTolerance(void *pData)
|
|
{
|
|
pEVControl self = NULL;
|
|
float fPos, fDelta;
|
|
int iRet, iCode, iStat;
|
|
char pError[10], pBueffel[512];
|
|
pExeList pExe = NULL;
|
|
SConnection *pCon = NULL;
|
|
|
|
self = (pEVControl)pData;
|
|
assert(self);
|
|
|
|
|
|
iRet = self->pDriv->GetValue(self->pDriv, &fPos);
|
|
if( iRet == 1 )
|
|
{
|
|
if(self->iLog)
|
|
{
|
|
VarlogAdd(self->pLog, fPos);
|
|
}
|
|
fDelta = self->fTarget - fPos;
|
|
if(fDelta < 0.)
|
|
{
|
|
fDelta = -fDelta;
|
|
}
|
|
if(fDelta < ObVal(self->pParam,TOLERANCE))
|
|
{
|
|
self->eMode = EVMonitor;
|
|
if(self->iWarned)
|
|
{
|
|
pExe = GetExecutor();
|
|
pCon = GetExeOwner(pExe);
|
|
sprintf(pBueffel,"Environment device %s back in tolerances again",
|
|
self->pName);
|
|
if(pCon)
|
|
{
|
|
SCWrite(pCon,pBueffel,eWarning);
|
|
}
|
|
else
|
|
{
|
|
ServerWriteGlobal(pBueffel,eWarning);
|
|
}
|
|
self->iWarned = 0;
|
|
}
|
|
return 1;
|
|
}
|
|
else
|
|
{
|
|
return 0;
|
|
}
|
|
}
|
|
else if(iRet == -1) /* pending */
|
|
{
|
|
/* pending means OK to me */
|
|
return 1;
|
|
}
|
|
else
|
|
{
|
|
/* break down of connection to a environment device has to be
|
|
considered a problem as well
|
|
*/
|
|
self->pDriv->GetError(self->pDriv, &iCode,pError,9);
|
|
iStat = self->pDriv->TryFixIt(self->pDriv, iCode);
|
|
if( (iStat == DEVOK) || (iStat == DEVREDO) )
|
|
{
|
|
return 1; /* effectively a redo in some time */
|
|
}
|
|
else
|
|
{
|
|
return 0;
|
|
}
|
|
}
|
|
return 0;
|
|
}
|
|
/*-------------------------------------------------------------------------*/
|
|
static void *EVIInterface(void *pData, int iCode)
|
|
{
|
|
pEVControl self = NULL;
|
|
|
|
self = (pEVControl)pData;
|
|
assert(self);
|
|
|
|
if(iCode == DRIVEID)
|
|
{
|
|
return self->pDrivInt;
|
|
}
|
|
else if(iCode == ENVIRINTERFACE)
|
|
{
|
|
return self->pEnvir;
|
|
}
|
|
return NULL;
|
|
}
|
|
/*-------- All this done, we can actually implement the controller ---------*/
|
|
pEVControl CreateEVController(pEVDriver pDriv, char *pName, int *iErr)
|
|
{
|
|
pEVControl pRes = NULL;
|
|
int iRet;
|
|
|
|
assert(pDriv);
|
|
*iErr = 1;
|
|
|
|
/* new memory first */
|
|
pRes = (pEVControl)malloc(sizeof(EVControl));
|
|
if(!pRes)
|
|
{
|
|
return NULL;
|
|
}
|
|
memset(pRes,0,sizeof(EVControl));
|
|
|
|
/* new Object Descriptor */
|
|
pRes->pDes = CreateDescriptor("Environment Controller");
|
|
if(!pRes->pDes)
|
|
{
|
|
free(pRes);
|
|
return NULL;
|
|
}
|
|
pRes->pDes->GetInterface = EVIInterface;
|
|
|
|
/* new Drivable interface */
|
|
pRes->pDrivInt = CreateDrivableInterface();
|
|
if(!pRes->pDrivInt)
|
|
{
|
|
DeleteDescriptor(pRes->pDes);
|
|
free(pRes);
|
|
return NULL;
|
|
}
|
|
pRes->pDrivInt->Halt = EVIHalt;
|
|
pRes->pDrivInt->CheckLimits = EVILimits;
|
|
pRes->pDrivInt->SetValue = EVIDrive;
|
|
pRes->pDrivInt->CheckStatus = EVIStatus;
|
|
pRes->pDrivInt->GetValue = EVIGet;
|
|
|
|
|
|
/* new environment interface */
|
|
pRes->pEnvir = CreateEVInterface();
|
|
if(!pRes->pEnvir)
|
|
{
|
|
free(pRes->pDrivInt);
|
|
DeleteDescriptor(pRes->pDes);
|
|
free(pRes);
|
|
return NULL;
|
|
}
|
|
pRes->pEnvir->GetMode = EVIGetMode;
|
|
pRes->pEnvir->IsInTolerance = EVIIsInTolerance;
|
|
pRes->pEnvir->HandleError = EVIErrHandler;
|
|
|
|
/* new parameter space */
|
|
pRes->pParam = ObParCreate(7);
|
|
if(!pRes->pParam)
|
|
{
|
|
free(pRes->pDrivInt);
|
|
free(pRes->pEnvir);
|
|
DeleteDescriptor(pRes->pDes);
|
|
free(pRes);
|
|
return NULL;
|
|
}
|
|
ObParInit(pRes->pParam, TOLERANCE, "tolerance", 2.0, usUser);
|
|
ObParInit(pRes->pParam, ACCESS, "access", usUser, usMugger);
|
|
ObParInit(pRes->pParam, ERRORHANDLER, "errorhandler", 0.0, usUser);
|
|
ObParInit(pRes->pParam, INTERRUPT, "interrupt", eContinue, usUser);
|
|
ObParInit(pRes->pParam, UPLIMIT, "upperlimit", 300.0, usUser);
|
|
ObParInit(pRes->pParam, LOWLIMIT, "lowerlimit", 2., usUser);
|
|
ObParInit(pRes->pParam, SAFEVALUE, "safevalue", 0., usUser);
|
|
|
|
/* local initialisations */
|
|
pRes->pDriv = pDriv;
|
|
iRet = pDriv->Init(pDriv);
|
|
if(iRet >= 0)
|
|
{
|
|
*iErr = iRet;
|
|
}
|
|
|
|
/* new var log for logging values */
|
|
pRes->iLog = 1;
|
|
if(!VarlogInit(&pRes->pLog))
|
|
{
|
|
DeleteEVController(pRes);
|
|
return NULL;
|
|
}
|
|
|
|
pRes->pName = strdup(pName);
|
|
pRes->eMode = EVIdle;
|
|
pRes->iWarned = 0;
|
|
|
|
/* a terminal error gives a -1 in iRet */
|
|
if(iRet < 0)
|
|
{
|
|
DeleteEVController(pRes);
|
|
return NULL;
|
|
}
|
|
|
|
return pRes;
|
|
}
|
|
/*---------------------------------------------------------------------------*/
|
|
void DeleteEVController(void *pData)
|
|
{
|
|
pEVControl self = NULL;
|
|
|
|
self = (pEVControl)pData;
|
|
assert(self);
|
|
|
|
if(self->pDes)
|
|
{
|
|
DeleteDescriptor(self->pDes);
|
|
}
|
|
if(self->pDrivInt)
|
|
{
|
|
free(self->pDrivInt);
|
|
}
|
|
if(self->pEnvir)
|
|
{
|
|
free(self->pEnvir);
|
|
}
|
|
if(self->KillPrivate)
|
|
{
|
|
self->KillPrivate(self->pPrivate);
|
|
}
|
|
if(self->pDriv)
|
|
{
|
|
self->pDriv->Close(self->pDriv);
|
|
DeleteEVDriver(self->pDriv);
|
|
}
|
|
if(self->pName)
|
|
{
|
|
free(self->pName);
|
|
}
|
|
if(self->pParam)
|
|
{
|
|
ObParDelete(self->pParam);
|
|
}
|
|
if(self->pLog)
|
|
{
|
|
VarlogDelete(self->pLog);
|
|
}
|
|
free(self);
|
|
}
|
|
/*--------------------------------------------------------------------------*/
|
|
int EVCDrive(pEVControl self, SConnection *pCon, float fVal)
|
|
{
|
|
char pBueffel[256], pError[132];
|
|
int iRet;
|
|
|
|
assert(self);
|
|
assert(pCon);
|
|
|
|
/* Check Limits */
|
|
iRet = self->pDrivInt->CheckLimits(self, fVal, pError,131);
|
|
if(!iRet)
|
|
{
|
|
SCWrite(pCon,pError,eError);
|
|
return 0;
|
|
}
|
|
|
|
/* start executing */
|
|
iRet = StartDevice(GetExecutor(), self->pName, self->pDes,
|
|
self, pCon, fVal);
|
|
if(!iRet)
|
|
{
|
|
sprintf(pBueffel,"ERROR: Failure to start %s",self->pName);
|
|
SCWrite(pCon,pBueffel,eError);
|
|
return 0;
|
|
}
|
|
|
|
/* Wait for success */
|
|
iRet = Wait4Success(GetExecutor());
|
|
if(iRet == DEVINT)
|
|
{
|
|
return 0;
|
|
}
|
|
return 1;
|
|
}
|
|
/*--------------------------------------------------------------------------*/
|
|
int EVCGetPos(pEVControl self, SConnection *pCon, float *fPos)
|
|
{
|
|
float fVal;
|
|
|
|
assert(self);
|
|
assert(pCon);
|
|
|
|
fVal = self->pDrivInt->GetValue(self, pCon);
|
|
if(fVal < -990)
|
|
{
|
|
return 0;
|
|
}
|
|
*fPos = fVal;
|
|
return 1;
|
|
}
|
|
/*-------------------------------------------------------------------------*/
|
|
pVarLog EVCGetVarLog(pEVControl self)
|
|
{
|
|
|
|
assert(self);
|
|
|
|
return self->pLog;
|
|
}
|
|
/*---------------------------------------------------------------------------*/
|
|
EVMode EVCGetMode(pEVControl self)
|
|
{
|
|
assert(self);
|
|
return self->eMode;
|
|
}
|
|
/*--------------------------------------------------------------------------*/
|
|
int EVCSetMode(pEVControl self, EVMode eNew)
|
|
{
|
|
assert(self);
|
|
self->eMode = eNew;
|
|
return 1;
|
|
}
|
|
/*---------------------------------------------------------------------------*/
|
|
int EVCGetPar(pEVControl self, char *name, float *fVal)
|
|
{
|
|
ObPar *pPar = NULL;
|
|
assert(self);
|
|
|
|
pPar = ObParFind(self->pParam,name);
|
|
if(pPar)
|
|
{
|
|
*fVal = pPar->fVal;
|
|
return 1;
|
|
}
|
|
else
|
|
{
|
|
return 0;
|
|
}
|
|
}
|
|
/*---------------------------------------------------------------------------*/
|
|
int EVCSetPar(pEVControl self, char *name, float fVal,SConnection *pCon)
|
|
{
|
|
ObPar *pPar = NULL;
|
|
char pBueffel[512];
|
|
int iRet;
|
|
|
|
assert(self);
|
|
assert(pCon);
|
|
|
|
iRet = ObParSet(self->pParam,self->pName,name,fVal,pCon);
|
|
if(!iRet)
|
|
{
|
|
return iRet;
|
|
}
|
|
if(self->iTcl)
|
|
{
|
|
iRet = UpdateTclVariable(self->pDriv,name,fVal);
|
|
}
|
|
return iRet;
|
|
}
|
|
/*--------------------------------------------------------------------------*/
|
|
int EVCList(pEVControl self, SConnection *pCon)
|
|
{
|
|
char pBueffel[256];
|
|
float fPos;
|
|
|
|
assert(self);
|
|
assert(pCon);
|
|
|
|
sprintf(pBueffel,"Parameter listing for %s",self->pName);
|
|
SCWrite(pCon,pBueffel,eValue);
|
|
|
|
sprintf(pBueffel,"%s.%s = %f ",self->pName, "tolerance",
|
|
ObVal(self->pParam,TOLERANCE));
|
|
SCWrite(pCon,pBueffel, eValue);
|
|
sprintf(pBueffel,"%s.%s = %f",self->pName, "access",
|
|
ObVal(self->pParam,ACCESS));
|
|
SCWrite(pCon,pBueffel, eValue);
|
|
sprintf(pBueffel,"%s.%s = %f",self->pName, "ErrorHandler",
|
|
ObVal(self->pParam,ERRORHANDLER));
|
|
SCWrite(pCon,pBueffel, eValue);
|
|
sprintf(pBueffel,"%s.%s = %f",self->pName, "interrupt",
|
|
ObVal(self->pParam,INTERRUPT));
|
|
SCWrite(pCon,pBueffel, eValue);
|
|
sprintf(pBueffel,"%s.%s = %f",self->pName, "UpperLimit",
|
|
ObVal(self->pParam,UPLIMIT));
|
|
SCWrite(pCon,pBueffel, eValue);
|
|
sprintf(pBueffel,"%s.%s = %f",self->pName, "LowerLimit",
|
|
ObVal(self->pParam,LOWLIMIT));
|
|
SCWrite(pCon,pBueffel, eValue);
|
|
sprintf(pBueffel,"%s.%s = %f",self->pName, "SafeValue",
|
|
ObVal(self->pParam,SAFEVALUE));
|
|
SCWrite(pCon,pBueffel, eValue);
|
|
EVCGetPos(self,pCon,&fPos);
|
|
sprintf(pBueffel,"%s.%s = %f",self->pName, "CurrentValue",
|
|
fPos);
|
|
SCWrite(pCon,pBueffel, eValue);
|
|
sprintf(pBueffel,"%s.%s = %f",self->pName, "TargetValue",
|
|
self->fTarget);
|
|
SCWrite(pCon,pBueffel, eValue);
|
|
|
|
return 1;
|
|
}
|
|
/*---------------------------------------------------------------------------
|
|
The wrapper understands the following syntax:
|
|
EVControl : print current value
|
|
EVControl fVal : drive value
|
|
EVControl par : print parameter
|
|
EVControl par fVal : set parameter
|
|
EVControl list : lists parameters
|
|
EVControl log ... : log subcommands
|
|
EVControl send bla bla ..... : sends everything after
|
|
send to the device
|
|
---------------------------------------------------------------------------*/
|
|
int EVControlWrapper(SConnection *pCon, SicsInterp *pSics, void *pData,
|
|
int argc, char *argv[])
|
|
{
|
|
pEVControl self = NULL;
|
|
char pBueffel[256], pReply[512];
|
|
double dVal;
|
|
float fPos;
|
|
int iRet;
|
|
|
|
self = (pEVControl)pData;
|
|
assert(self);
|
|
assert(pSics);
|
|
assert(pCon);
|
|
|
|
if(argc < 2) /* only value requested */
|
|
{
|
|
iRet = EVCGetPos(self,pCon,&fPos);
|
|
if(iRet)
|
|
{
|
|
sprintf(pBueffel,"%s.%s = %f",self->pName,"CurrentValue", fPos);
|
|
SCWrite(pCon,pBueffel,eValue);
|
|
return 1;
|
|
}
|
|
return 0;
|
|
}
|
|
else
|
|
{
|
|
strtolower(argv[1]);
|
|
}
|
|
|
|
/* analyse commands */
|
|
if(strcmp(argv[1],"send") == 0) /* send to controller */
|
|
{
|
|
Arg2Text(argc-2,&argv[2],pBueffel,255);
|
|
iRet = self->pDriv->Send(self->pDriv,pBueffel,pReply, 511);
|
|
SCWrite(pCon,pReply,eValue);
|
|
return iRet;
|
|
}
|
|
else if(strcmp(argv[1],"log") == 0) /* log commands */
|
|
{
|
|
if(argc < 3)
|
|
{
|
|
SCWrite(pCon,"ERROR: insufficient number of commands for varlog",eError);
|
|
return 0;
|
|
}
|
|
iRet = VarlogWrapper(self->pLog,pCon,
|
|
argv[2],argv[3],argv[0]);
|
|
if(iRet)
|
|
{
|
|
SCSendOK(pCon);
|
|
}
|
|
return iRet;
|
|
}
|
|
else if( argc < 3) /* either parameter or drive */
|
|
{
|
|
iRet = Tcl_GetDouble(pSics->pTcl,argv[1],&dVal);
|
|
if(iRet == TCL_OK) /* float Value: drive */
|
|
{
|
|
if(!SCMatchRights(pCon,usUser))
|
|
{
|
|
return 0;
|
|
}
|
|
iRet = EVCDrive(self,pCon,(float)dVal);
|
|
if(iRet)
|
|
{
|
|
SCSendOK(pCon);
|
|
}
|
|
return iRet;
|
|
}
|
|
else if(strcmp(argv[1],"list") == 0)
|
|
{
|
|
EVCList(self,pCon);
|
|
return 1;
|
|
}
|
|
else if(strcmp(argv[1],"send") == 0) /* send to controller */
|
|
{
|
|
Arg2Text(argc-2,&argv[2],pBueffel,255);
|
|
iRet = self->pDriv->Send(self->pDriv,pBueffel,pReply, 511);
|
|
SCWrite(pCon,pReply,eValue);
|
|
return iRet;
|
|
}
|
|
else if(strcmp(argv[1],"log") == 0) /* log commands */
|
|
{
|
|
if(argc < 3)
|
|
{
|
|
SCWrite(pCon,"ERROR: insufficient number of commands for varlog",eError);
|
|
return 0;
|
|
}
|
|
return VarlogWrapper(self->pLog,pCon,
|
|
argv[2],argv[3],argv[0]);
|
|
}
|
|
else /* parameter request */
|
|
{
|
|
iRet = EVCGetPar(self,argv[1],&fPos);
|
|
if(!iRet)
|
|
{
|
|
sprintf(pBueffel,"ERROR: parameter %s NOT found",
|
|
argv[1]);
|
|
SCWrite(pCon,pBueffel,eError);
|
|
return 0;
|
|
}
|
|
else
|
|
{
|
|
sprintf(pBueffel,"%s.%s = %f",self->pName,argv[1],fPos);
|
|
SCWrite(pCon,pBueffel,eValue);
|
|
return 1;
|
|
}
|
|
}
|
|
}
|
|
else /* try to set parameter */
|
|
{
|
|
iRet = Tcl_GetDouble(pSics->pTcl,argv[2],&dVal);
|
|
if(iRet != TCL_OK)
|
|
{
|
|
sprintf(pBueffel,"ERROR: %s no valid number", argv[2]);
|
|
SCWrite(pCon,pBueffel,eError);
|
|
return 0;
|
|
}
|
|
iRet = EVCSetPar(self, argv[1],(float)dVal,pCon);
|
|
if(iRet)
|
|
{
|
|
SCSendOK(pCon);
|
|
}
|
|
return iRet;
|
|
}
|
|
return 0; /* not reached */
|
|
}
|
|
/*-------------------------------------------------------------------------
|
|
EVControlFactory implements a SICS command which creates and deletes
|
|
Controllers at run-time. Syntax:
|
|
|
|
ControlFactory new name SIM
|
|
-- creates a new controller name with a simulation driver
|
|
ControlFactory del name
|
|
-- deletes controller name
|
|
-------------------------------------------------------------------------*/
|
|
int EVControlFactory(SConnection *pCon, SicsInterp *pSics, void *pData,
|
|
int argc, char *argv[])
|
|
{
|
|
pEVControl pNew = NULL;
|
|
pEVDriver pDriv = NULL;
|
|
char pBueffel[512],pError[132];
|
|
int iRet;
|
|
CommandList *pCom = NULL;
|
|
|
|
assert(pSics);
|
|
assert(pCon);
|
|
|
|
if(argc < 3)
|
|
{
|
|
SCWrite(pCon,"ERROR: Insufficient number of arguments to EVFactory",
|
|
eError);
|
|
return 0;
|
|
}
|
|
|
|
/* check rights */
|
|
if(!SCMatchRights(pCon,usUser))
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
strtolower(argv[1]);
|
|
if(strcmp(argv[1],"del") == 0) /* delete */
|
|
{
|
|
if(!pServ->pExecutor)
|
|
{
|
|
SCSendOK(pCon);
|
|
return 1;
|
|
}
|
|
if(isInRunMode(pServ->pExecutor))
|
|
{
|
|
SCWrite(pCon,"ERROR: cannot delete while running",eError);
|
|
return 0;
|
|
}
|
|
EVUnregister(FindEMON(pSics),argv[2]);
|
|
iRet = RemoveCommand(pSics,argv[2]);
|
|
if(!iRet)
|
|
{
|
|
sprintf(pBueffel,"ERROR: %s not found, NOT deleted",argv[2]);
|
|
SCWrite(pCon,pBueffel,eError);
|
|
return 0;
|
|
}
|
|
SCSendOK(pCon);
|
|
return 1;
|
|
}
|
|
else if(strcmp(argv[1],"new") == 0) /*make a new one */
|
|
{
|
|
/* argv[2] = name */
|
|
/* argv[3] must be type */
|
|
if(argc < 4)
|
|
{
|
|
SCWrite(pCon,"ERROR: no type specified for Environment Controller",
|
|
eError);
|
|
return 0;
|
|
}
|
|
strtolower(argv[2]);
|
|
strtolower(argv[3]);
|
|
pCom = FindCommand(pSics,argv[2]);
|
|
if(pCom)
|
|
{
|
|
sprintf(pBueffel,"ERROR: environment device %s already installed, delete first",
|
|
argv[2]);
|
|
SCWrite(pCon,pBueffel,eError);
|
|
return 0;
|
|
}
|
|
if(strcmp(argv[3],"sim") == 0) /* SIM driver */
|
|
{
|
|
/* Create a Sim Driver */
|
|
|
|
pDriv = CreateSIMEVDriver(argc-4,&argv[4]);
|
|
if(!pDriv)
|
|
{
|
|
SCWrite(pCon,"ERROR: failed to create Environment Device driver",eError);
|
|
return 0;
|
|
}
|
|
|
|
}
|
|
else if(strcmp(argv[3],"tecs") == 0) /* TECS temperature server */
|
|
{
|
|
/* Create a driver */
|
|
pDriv = CreateTecsDriver(argc-4,&argv[4]);
|
|
if(!pDriv)
|
|
{
|
|
SCWrite(pCon,"ERROR: failed to create TECS device driver",eError);
|
|
return 0;
|
|
}
|
|
/* got a driver, initialise everything */
|
|
pNew = CreateEVController(pDriv,argv[2],&iRet);
|
|
if(!pNew)
|
|
{
|
|
SCWrite(pCon,"ERROR: failed to initialize Tecs",eError);
|
|
SCWrite(pCon,"ERROR creating Environment Controller",eError);
|
|
return 0;
|
|
}
|
|
if(!iRet)
|
|
{
|
|
SCWrite(pCon,"ERROR: problem initialising Environment controller",
|
|
eError);
|
|
pDriv->GetError(pDriv,&iRet,pError,131);
|
|
sprintf(pBueffel,"HW reported: %s",pError);
|
|
SCWrite(pCon,pBueffel,eError);
|
|
}
|
|
/* set a few parameters */
|
|
EVCSetPar(pNew,"upperlimit",300.0,pCon);
|
|
EVCSetPar(pNew,"lowerlimit",1.0,pCon);
|
|
/* install command */
|
|
iRet = AddCommand(pSics,argv[2],TecsWrapper,DeleteEVController,
|
|
pNew);
|
|
if(!iRet)
|
|
{
|
|
sprintf(pBueffel,"ERROR: duplicate command %s not created",argv[2]);
|
|
DeleteEVController((void *)pNew);
|
|
SCWrite(pCon,pBueffel,eError);
|
|
return 0;
|
|
}
|
|
EVRegisterController(FindEMON(pSics),argv[2],pNew, pCon);
|
|
SCSendOK(pCon);
|
|
return 1;
|
|
}
|
|
else if(strcmp(argv[3],"itc4") == 0) /* ITC4 driver */
|
|
{
|
|
/* Create a driver */
|
|
pDriv = CreateITC4Driver(argc-4,&argv[4]);
|
|
if(!pDriv)
|
|
{
|
|
SCWrite(pCon,"ERROR: failed to create ITC4 device driver",eError);
|
|
return 0;
|
|
}
|
|
/* got a driver, initialise everything */
|
|
pNew = CreateEVController(pDriv,argv[2],&iRet);
|
|
if(!pNew)
|
|
{
|
|
SCWrite(pCon,"ERROR creating Environment Controller",eError);
|
|
return 0;
|
|
}
|
|
if(!iRet)
|
|
{
|
|
SCWrite(pCon,"ERROR: problem initialising Environment controller",
|
|
eError);
|
|
pDriv->GetError(pDriv,&iRet,pError,131);
|
|
sprintf(pBueffel,"HW reported: %s",pError);
|
|
SCWrite(pCon,pBueffel,eError);
|
|
}
|
|
/* set a few parameters */
|
|
EVCSetPar(pNew,"upperlimit",300.0,pCon);
|
|
EVCSetPar(pNew,"lowerlimit",1.0,pCon);
|
|
/* install command */
|
|
iRet = AddCommand(pSics,argv[2],ITC4Wrapper,DeleteEVController,
|
|
pNew);
|
|
if(!iRet)
|
|
{
|
|
sprintf(pBueffel,"ERROR: duplicate command %s not created",argv[2]);
|
|
DeleteEVController((void *)pNew);
|
|
SCWrite(pCon,pBueffel,eError);
|
|
return 0;
|
|
}
|
|
EVRegisterController(FindEMON(pSics),argv[2],pNew, pCon);
|
|
SCSendOK(pCon);
|
|
return 1;
|
|
}
|
|
else if(strcmp(argv[3],"bruker") == 0) /* Bruker Magnet Controller driver */
|
|
{
|
|
/* Create a driver */
|
|
pDriv = CreateBrukerDriver(argc-4,&argv[4]);
|
|
if(!pDriv)
|
|
{
|
|
SCWrite(pCon,"ERROR: failed to create Bruker Controller device driver",eError);
|
|
return 0;
|
|
}
|
|
/* got a driver, initialise everything */
|
|
pNew = CreateEVController(pDriv,argv[2],&iRet);
|
|
if(!pNew)
|
|
{
|
|
SCWrite(pCon,"ERROR creating Environment Controller",eError);
|
|
return 0;
|
|
}
|
|
if(!iRet)
|
|
{
|
|
SCWrite(pCon,"ERROR: problem initialising Environment controller",
|
|
eError);
|
|
pDriv->GetError(pDriv,&iRet,pError,131);
|
|
sprintf(pBueffel,"HW reported: %s",pError);
|
|
SCWrite(pCon,pBueffel,eError);
|
|
}
|
|
|
|
/* set a few parameters */
|
|
EVCSetPar(pNew,"upperlimit",45.0,pCon);
|
|
EVCSetPar(pNew,"lowerlimit",0.0,pCon);
|
|
/* install command */
|
|
iRet = AddCommand(pSics,argv[2],BrukerAction,DeleteEVController,
|
|
pNew);
|
|
if(!iRet)
|
|
{
|
|
sprintf(pBueffel,"ERROR: duplicate command %s not created",argv[2]);
|
|
DeleteEVController((void *)pNew);
|
|
SCWrite(pCon,pBueffel,eError);
|
|
return 0;
|
|
}
|
|
EVRegisterController(FindEMON(pSics),argv[2],pNew, pCon);
|
|
SCSendOK(pCon);
|
|
return 1;
|
|
}
|
|
else if(strcmp(argv[3],"ltc11") == 0)
|
|
/* Neocera LTC-11 temperature controller*/
|
|
{
|
|
/* Create a driver */
|
|
pDriv = CreateLTC11Driver(argc-4,&argv[4]);
|
|
if(!pDriv)
|
|
{
|
|
SCWrite(pCon,"ERROR: failed to create LTC-11 device driver",eError);
|
|
return 0;
|
|
}
|
|
/* got a driver, initialise everything */
|
|
pNew = CreateEVController(pDriv,argv[2],&iRet);
|
|
if(!pNew)
|
|
{
|
|
SCWrite(pCon,"ERROR creating Environment Controller",eError);
|
|
return 0;
|
|
}
|
|
if(!iRet)
|
|
{
|
|
SCWrite(pCon,"ERROR: problem initialising Environment controller",
|
|
eError);
|
|
pDriv->GetError(pDriv,&iRet,pError,131);
|
|
sprintf(pBueffel,"HW reported: %s",pError);
|
|
SCWrite(pCon,pBueffel,eError);
|
|
}
|
|
/* set a few parameters */
|
|
EVCSetPar(pNew,"upperlimit",500.,pCon);
|
|
EVCSetPar(pNew,"lowerlimit",1.5,pCon);
|
|
/* install command */
|
|
iRet = AddCommand(pSics,argv[2],LTC11Action,DeleteEVController,
|
|
pNew);
|
|
if(!iRet)
|
|
{
|
|
sprintf(pBueffel,"ERROR: duplicate command %s not created",argv[2]);
|
|
DeleteEVController((void *)pNew);
|
|
SCWrite(pCon,pBueffel,eError);
|
|
return 0;
|
|
}
|
|
EVRegisterController(FindEMON(pSics),argv[2],pNew, pCon);
|
|
SCSendOK(pCon);
|
|
return 1;
|
|
}
|
|
else if(strcmp(argv[3],"tcl") == 0) /* Tcl driver */
|
|
{
|
|
/* Create a driver */
|
|
pDriv = CreateTclDriver(argc-4,&argv[4],argv[2], pCon);
|
|
if(!pDriv)
|
|
{
|
|
SCWrite(pCon,"ERROR: failed to create TCL device driver",eError);
|
|
return 0;
|
|
}
|
|
/* got a driver, initialise everything */
|
|
pNew = CreateEVController(pDriv,argv[2],&iRet);
|
|
if(!pNew)
|
|
{
|
|
SCWrite(pCon,"ERROR creating Environment Controller",eError);
|
|
DeleteEVDriver(pDriv);
|
|
return 0;
|
|
}
|
|
if(!iRet)
|
|
{
|
|
SCWrite(pCon,"ERROR: problem initialising Environment controller",
|
|
eError);
|
|
pDriv->GetError(pDriv,&iRet,pError,131);
|
|
sprintf(pBueffel,"HW reported: %s",pError);
|
|
SCWrite(pCon,pBueffel,eError);
|
|
}
|
|
/* install command */
|
|
iRet = AddCommand(pSics,argv[2],TclEnvironmentWrapper,DeleteEVController,
|
|
pNew);
|
|
if(!iRet)
|
|
{
|
|
sprintf(pBueffel,"ERROR: duplicate command %s not created",argv[2]);
|
|
DeleteEVController((void *)pNew);
|
|
SCWrite(pCon,pBueffel,eError);
|
|
return 0;
|
|
}
|
|
pNew->iTcl = 1;
|
|
/* make ev parameters available to Tcl */
|
|
UpdateTclVariable(pNew->pDriv,"tolerance",
|
|
ObVal(pNew->pParam,TOLERANCE));
|
|
UpdateTclVariable(pNew->pDriv,"upperlimit",
|
|
ObVal(pNew->pParam,UPLIMIT));
|
|
UpdateTclVariable(pNew->pDriv,"lowerlimit",
|
|
ObVal(pNew->pParam,LOWLIMIT));
|
|
|
|
/* register controller for monitoring */
|
|
EVRegisterController(FindEMON(pSics),argv[2],pNew, pCon);
|
|
SCSendOK(pCon);
|
|
return 1;
|
|
}
|
|
else if(strcmp(argv[3],"dillu") == 0) /* dillution driver */
|
|
{
|
|
/* Create a driver */
|
|
pDriv = CreateDILLUDriv(argc-4,&argv[4]);
|
|
if(!pDriv)
|
|
{
|
|
SCWrite(pCon,
|
|
"ERROR: failed to create Dillution device driver",eError);
|
|
return 0;
|
|
}
|
|
}
|
|
else if(strcmp(argv[3],"gencon") == 0) /* general controller */
|
|
{
|
|
/* Create a driver */
|
|
pDriv = MakeControllerEnvironmentDriver(argc-4,&argv[4]);
|
|
if(!pDriv)
|
|
{
|
|
SCWrite(pCon,
|
|
"ERROR: failed to create Controller Environment driver",
|
|
eError);
|
|
return 0;
|
|
}
|
|
}
|
|
else if(strcmp(argv[3],"euro") == 0) /* dillution driver */
|
|
{
|
|
/* Create a driver */
|
|
pDriv = CreateEURODriv(argc-4,&argv[4]);
|
|
if(!pDriv)
|
|
{
|
|
SCWrite(pCon,
|
|
"ERROR: failed to create Eurotherm device driver",eError);
|
|
return 0;
|
|
}
|
|
}
|
|
else if(strcmp(argv[3],"el755") == 0) /* EL755 magnet driver */
|
|
{
|
|
/* Create a driver */
|
|
pDriv = CreateEL755Driv(argc-4,&argv[4]);
|
|
if(!pDriv)
|
|
{
|
|
SCWrite(pCon,
|
|
"ERROR: failed to create EL755 device driver",eError);
|
|
return 0;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
sprintf(pBueffel,"ERROR: %s not recognized as a valid driver type",
|
|
argv[3]);
|
|
SCWrite(pCon,pBueffel,eError);
|
|
return 0;
|
|
}
|
|
/* got a driver, initialise everything */
|
|
pNew = CreateEVController(pDriv,argv[2],&iRet);
|
|
if(!pNew)
|
|
{
|
|
SCWrite(pCon,"ERROR creating Environment Controller",eError);
|
|
return 0;
|
|
}
|
|
if(!iRet)
|
|
{
|
|
SCWrite(pCon,"ERROR: problem initialising Environment controller",
|
|
eError);
|
|
pDriv->GetError(pDriv,&iRet,pError,131);
|
|
sprintf(pBueffel,"HW reported: %s",pError);
|
|
SCWrite(pCon,pBueffel,eError);
|
|
}
|
|
|
|
/* set a few parameters */
|
|
if(strcmp(argv[3],"euro") == 0)
|
|
{
|
|
EVCSetPar(pNew,"upperlimit",750.0,pCon);
|
|
EVCSetPar(pNew,"lowerlimit",15.0,pCon);
|
|
}
|
|
else if(strcmp(argv[3],"el755") == 0)
|
|
{
|
|
EVCSetPar(pNew,"upperlimit",10.,pCon);
|
|
EVCSetPar(pNew,"lowerlimit",-10.,pCon);
|
|
}
|
|
else
|
|
{
|
|
EVCSetPar(pNew,"upperlimit",4.0,pCon);
|
|
EVCSetPar(pNew,"lowerlimit",0.05,pCon);
|
|
}
|
|
/* install command */
|
|
iRet = AddCommand(pSics,argv[2],EVControlWrapper,DeleteEVController,
|
|
pNew);
|
|
if(!iRet)
|
|
{
|
|
sprintf(pBueffel,"ERROR: duplicate command %s not created",argv[2]);
|
|
DeleteEVController((void *)pNew);
|
|
SCWrite(pCon,pBueffel,eError);
|
|
return 0;
|
|
}
|
|
EVRegisterController(FindEMON(pSics),argv[2],pNew, pCon);
|
|
SCSendOK(pCon);
|
|
return 1;
|
|
}
|
|
SCWrite(pCon,"ERROR: command not understood",eError);
|
|
return 0;
|
|
}
|
|
|
|
|
|
|