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.
298 lines
7.9 KiB
C
298 lines
7.9 KiB
C
/*------------------------------------------------------------------------
|
|
C h o p p e r C o n t r o l l e r
|
|
|
|
Implementation file for the SICS chopper controller and general controller
|
|
device. For details about this object and its relation with the SICS system
|
|
see choco.w or choco.tex.
|
|
|
|
Mark Koennecke, January 1998
|
|
-------------------------------------------------------------------------*/
|
|
#include <stdlib.h>
|
|
#include <tcl.h>
|
|
#include <assert.h>
|
|
#include "fortify.h"
|
|
#include "sics.h"
|
|
#define CHOCOINTERNAL
|
|
#include "choco.h"
|
|
|
|
|
|
|
|
/*------------------------------------------------------------------------*/
|
|
int CHGetParameter(pChoco self, char *parname, char *pParValue,
|
|
int iBuflen)
|
|
{
|
|
int iRet, iCode;
|
|
|
|
assert(self);
|
|
|
|
iRet = self->pDriv->GetPar(self->pDriv, parname, pParValue,
|
|
iBuflen);
|
|
if(!iRet)
|
|
{
|
|
iRet = 0;
|
|
self->pDriv->GetError(self->pDriv,&iCode,pParValue, iBuflen);
|
|
}
|
|
return iRet;
|
|
}
|
|
/*------------------------------------------------------------------------*/
|
|
pCodri CHGetDriver(pChoco self)
|
|
{
|
|
assert(self);
|
|
|
|
return self->pDriv;
|
|
}
|
|
/*------------------------------------------------------------------------*/
|
|
int CHList(pChoco self, SConnection *pCon, char *name)
|
|
{
|
|
char *pPar, *pCopy = NULL;
|
|
char pValue[80];
|
|
char pMessage[256];
|
|
int iRet, iLen;
|
|
Tcl_DString tlist;
|
|
|
|
assert(self);
|
|
|
|
/* copy pParList as it will be destroyed by strtok */
|
|
iLen = strlen(self->pDriv->pParList);
|
|
pCopy = (char *)malloc((iLen+10)*sizeof(char));
|
|
if(!pCopy)
|
|
{
|
|
SCWrite(pCon,"ERROR: out of memory in CHList",eError);
|
|
return 0;
|
|
}
|
|
memset(pCopy,0,iLen+10);
|
|
strcpy(pCopy,self->pDriv->pParList);
|
|
Tcl_DStringInit(&tlist);
|
|
|
|
pPar = strtok(pCopy,",");
|
|
while(pPar != NULL)
|
|
{
|
|
iRet = CHGetParameter(self,pPar,pValue,79);
|
|
if(iRet)
|
|
{
|
|
sprintf(pMessage,"%s.%s = %s \n",name,pPar,pValue);
|
|
}
|
|
else
|
|
{
|
|
sprintf(pMessage,"ERROR: %s : while reading parameter %s \n",
|
|
pValue,pPar);
|
|
}
|
|
Tcl_DStringAppend(&tlist, pMessage,-1);
|
|
pPar = strtok(NULL,",");
|
|
}
|
|
SCWrite(pCon,Tcl_DStringValue(&tlist),eValue);
|
|
Tcl_DStringFree(&tlist);
|
|
free(pCopy);
|
|
return 1;
|
|
}
|
|
/*-----------------------------------------------------------------------*/
|
|
int ChocoAction(SConnection *pCon, SicsInterp *pSics, void *pData,
|
|
int argc, char *argv[])
|
|
{
|
|
pChoco self = NULL;
|
|
char pValue[80], pMessage[256];
|
|
int iRet;
|
|
|
|
self = (pChoco)pData;
|
|
assert(self);
|
|
|
|
if(argc < 2)
|
|
{
|
|
sprintf(pMessage, "ERROR: Ragument required for %s",argv[0]);
|
|
SCWrite(pCon,pMessage,eError);
|
|
return 0;
|
|
}
|
|
|
|
/* argument can either be list or parameter name */
|
|
strtolower(argv[1]);
|
|
if(strcmp(argv[1],"list") == 0)
|
|
{
|
|
return CHList(self,pCon,argv[0]);
|
|
}
|
|
else
|
|
{
|
|
if(argc > 2)
|
|
{
|
|
/* set case */
|
|
iRet = self->pDriv->SetPar2(self->pDriv,argv[1],argv[2]);
|
|
if(!iRet)
|
|
{
|
|
self->pDriv->GetError(self->pDriv,&iRet,pValue,79);
|
|
sprintf(pMessage,"ERROR: %s",pValue);
|
|
SCWrite(pCon,pMessage,eError);
|
|
return 0;
|
|
}
|
|
else
|
|
{
|
|
SCSendOK(pCon);
|
|
return 1;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
/* get case */
|
|
iRet = CHGetParameter(self,argv[1],pValue,79);
|
|
if(iRet)
|
|
{
|
|
sprintf(pMessage,"%s.%s = %s",argv[0],argv[1],pValue);
|
|
}
|
|
else
|
|
{
|
|
sprintf(pMessage,"ERROR: %s : while reading parameter %s",
|
|
pValue,argv[1]);
|
|
}
|
|
SCWrite(pCon,pMessage,eValue);
|
|
return iRet;
|
|
}
|
|
}
|
|
return 0;
|
|
}
|
|
/*----------------------------------------------------------------------*/
|
|
static void KillChoco(void *pData)
|
|
{
|
|
pChoco self = NULL;
|
|
|
|
self = (pChoco)pData;
|
|
if(!self)
|
|
return;
|
|
|
|
if(self->pDriv)
|
|
{
|
|
self->pDriv->Close(self->pDriv);
|
|
self->pDriv->Delete(self->pDriv);
|
|
if(self->pDriv->pParList)
|
|
free(self->pDriv->pParList);
|
|
free(self->pDriv);
|
|
}
|
|
if(self->pDes)
|
|
DeleteDescriptor(self->pDes);
|
|
|
|
free(self);
|
|
}
|
|
/*-----------------------------------------------------------------------
|
|
DRIVERS
|
|
*/
|
|
|
|
extern pCodri MakeSimChopper(void);
|
|
extern pCodri MakeDoChoDriver(char *pHost, int iPort, int iChannel);
|
|
extern pCodri MakeCookerDriver(char *pHost, int iPort, int iChannel);
|
|
/*-----------------------------------------------------------------------*/
|
|
int ChocoFactory(SConnection *pCon, SicsInterp *pSics, void *pData,
|
|
int argc, char *argv[])
|
|
{
|
|
pChoco pNew = NULL;
|
|
pCodri pDriv = NULL;
|
|
pObjectDescriptor pDes = NULL;
|
|
char pBueffel[132];
|
|
int iRet, iPort, iChannel;
|
|
|
|
if(argc < 3)
|
|
{
|
|
SCWrite(pCon,
|
|
"ERROR: Insufficient number of arguments to MakeController",
|
|
eError);
|
|
return 0;
|
|
}
|
|
|
|
|
|
/* first try to get everything done */
|
|
pNew = (pChoco)malloc(sizeof(Choco));
|
|
pDes = CreateDescriptor("Chopper");
|
|
/* do driver */
|
|
strtolower(argv[2]);
|
|
if(strcmp(argv[2],"sim") == 0)
|
|
{
|
|
pDriv = MakeSimChopper();
|
|
}
|
|
else if(strcmp(argv[2],"docho") == 0)
|
|
{
|
|
if(argc < 6)
|
|
{
|
|
SCWrite(pCon,
|
|
"ERROR: Insufficient number of arguments to install Dornier Chopper driver",
|
|
eError);
|
|
return 0;
|
|
}
|
|
iRet = Tcl_GetInt(pSics->pTcl,argv[4],&iPort);
|
|
if(iRet != TCL_OK)
|
|
{
|
|
sprintf(pBueffel,"ERROR: expected integer as port number, got %s",
|
|
argv[4]);
|
|
SCWrite(pCon,pBueffel,eError);
|
|
return 0;
|
|
}
|
|
iRet = Tcl_GetInt(pSics->pTcl,argv[5],&iChannel);
|
|
if(iRet != TCL_OK)
|
|
{
|
|
sprintf(pBueffel,"ERROR: expected integer as channel number, got %s",
|
|
argv[4]);
|
|
SCWrite(pCon,pBueffel,eError);
|
|
return 0;
|
|
}
|
|
pDriv = MakeDoChoDriver(argv[3],iPort,iChannel);
|
|
}
|
|
else if(strcmp(argv[2],"sanscook") == 0)
|
|
{
|
|
if(argc < 6)
|
|
{
|
|
SCWrite(pCon,
|
|
"ERROR: Insufficient number of arguments to install SANS Cooker driver",
|
|
eError);
|
|
return 0;
|
|
}
|
|
iRet = Tcl_GetInt(pSics->pTcl,argv[4],&iPort);
|
|
if(iRet != TCL_OK)
|
|
{
|
|
sprintf(pBueffel,"ERROR: expected integer as port number, got %s",
|
|
argv[4]);
|
|
SCWrite(pCon,pBueffel,eError);
|
|
return 0;
|
|
}
|
|
iRet = Tcl_GetInt(pSics->pTcl,argv[5],&iChannel);
|
|
if(iRet != TCL_OK)
|
|
{
|
|
sprintf(pBueffel,"ERROR: expected integer as channel number, got %s",
|
|
argv[4]);
|
|
SCWrite(pCon,pBueffel,eError);
|
|
return 0;
|
|
}
|
|
pDriv = MakeCookerDriver(argv[3],iPort,iChannel);
|
|
}
|
|
else
|
|
{
|
|
sprintf(pBueffel,"ERROR: Driver %s NOT supported for MakeController",
|
|
argv[2]);
|
|
SCWrite(pCon,pBueffel,eError);
|
|
return 0;
|
|
}
|
|
if( (pNew == NULL) || (pDes == NULL) || (pDriv == NULL) )
|
|
{
|
|
SCWrite(pCon,"ERROR: No memory left to create controller",eError);
|
|
return 0;
|
|
}
|
|
pNew->pDes = pDes;
|
|
pNew->pDriv = pDriv;
|
|
|
|
/* initialize driver */
|
|
iRet = pDriv->Init(pDriv);
|
|
if(!iRet)
|
|
{
|
|
SCWrite(pCon,"ERROR: Failed to initialize driver",eError);
|
|
KillChoco(pNew);
|
|
return 0;
|
|
}
|
|
|
|
/* install as command */
|
|
iRet = AddCommand(pSics, argv[1],ChocoAction,KillChoco,pNew);
|
|
if(!iRet)
|
|
{
|
|
sprintf(pBueffel,"ERROR: duplicate command %s NOT created",
|
|
argv[1]);
|
|
SCWrite(pCon,pBueffel,eError);
|
|
return 0;
|
|
}
|
|
return 1;
|
|
}
|
|
|
|
|