- 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:
435
tasinit.c
Normal file
435
tasinit.c
Normal file
@ -0,0 +1,435 @@
|
||||
/*--------------------------------------------------------------------------
|
||||
This is one implementation file for the TASMAD simulation module for
|
||||
SICS. The requirement is to make SICS look as much as TASMAD as
|
||||
possible. This includes:
|
||||
- TASMAD is variable driven
|
||||
- Sometimes variables are accessed in storage order.
|
||||
- A complicated calculation has to be done for getting the instruments
|
||||
settings right. The appropriate F77 routine from TASMAD will be
|
||||
reused.
|
||||
- The scan logic is different.
|
||||
- Output of ILL-formatted data files is required.
|
||||
|
||||
This file implements the initialization part of the whole thing.
|
||||
|
||||
Mark Koennecke, November 2000
|
||||
---------------------------------------------------------------------------*/
|
||||
#include <stdlib.h>
|
||||
#include <assert.h>
|
||||
#include "fortify.h"
|
||||
#include "sics.h"
|
||||
#include "sicsvar.h"
|
||||
#include "counter.h"
|
||||
#include "motor.h"
|
||||
#include "scan.h"
|
||||
#include "scan.i"
|
||||
#include "tas.h"
|
||||
|
||||
extern int getSRO(SConnection *pCon, float *fVal); /* tasutil.c */
|
||||
|
||||
/*
|
||||
As variables may be accessed in storage order, it is necessary to
|
||||
know the order of the motors
|
||||
*/
|
||||
extern char *tasMotorOrder[] = { "a1",
|
||||
"a2",
|
||||
"a3",
|
||||
"a4",
|
||||
"a5",
|
||||
"a6",
|
||||
"mcv",
|
||||
"sro",
|
||||
"ach",
|
||||
"mtl",
|
||||
"mtu",
|
||||
"stl",
|
||||
"stu",
|
||||
"stl",
|
||||
"atu",
|
||||
"mgl",
|
||||
"sgl",
|
||||
"sgu",
|
||||
"agl",
|
||||
"atl",
|
||||
"tt",
|
||||
"i1" ,
|
||||
"i2",
|
||||
"i3",
|
||||
"i4",
|
||||
"hxx",
|
||||
"hyy",
|
||||
"hzz",
|
||||
"i5",
|
||||
"i6",
|
||||
"i7",
|
||||
"i8",
|
||||
NULL };
|
||||
/*
|
||||
In order to initialise the variable array in the TAS data structure we
|
||||
need to know the names of the variables in the right order. This order
|
||||
has to match the order defined in tas.h through the defines. Otherwise
|
||||
quite weird things may happen at runtime.
|
||||
*/
|
||||
extern char *tasVariableOrder[] = {
|
||||
"wav",
|
||||
"dm",
|
||||
"da",
|
||||
"etam",
|
||||
"etaa",
|
||||
"ti",
|
||||
"mn",
|
||||
"if1v",
|
||||
"if1h",
|
||||
"if2v",
|
||||
"if2h",
|
||||
"helm",
|
||||
"as",
|
||||
"bs",
|
||||
"cs",
|
||||
"aa",
|
||||
"bb",
|
||||
"cc",
|
||||
"etas",
|
||||
"ax",
|
||||
"ay",
|
||||
"az",
|
||||
"bx",
|
||||
"by",
|
||||
"bz",
|
||||
"ei",
|
||||
"ki",
|
||||
"ef",
|
||||
"kf",
|
||||
"qh",
|
||||
"qk",
|
||||
"ql",
|
||||
"en",
|
||||
"qm",
|
||||
"hx",
|
||||
"hy",
|
||||
"hz",
|
||||
"da1",
|
||||
"da2",
|
||||
"da3",
|
||||
"da4",
|
||||
"da5",
|
||||
"da6",
|
||||
"dmcv",
|
||||
"dsro",
|
||||
"dach",
|
||||
"dmtl",
|
||||
"dmtu",
|
||||
"dstl",
|
||||
"dstu",
|
||||
"datl",
|
||||
"datu",
|
||||
"dmgl",
|
||||
"dsgl",
|
||||
"dsgu",
|
||||
"dagl",
|
||||
"dei",
|
||||
"dki",
|
||||
"def",
|
||||
"dkf",
|
||||
"dqh",
|
||||
"dqk",
|
||||
"dql",
|
||||
"den",
|
||||
"dqm",
|
||||
"dtt",
|
||||
"sm",
|
||||
"ss",
|
||||
"sa",
|
||||
"fx",
|
||||
"np",
|
||||
"f1",
|
||||
"f2",
|
||||
"lpa",
|
||||
"mrx1",
|
||||
"mrx2",
|
||||
"arx1",
|
||||
"arx2",
|
||||
"instrument",
|
||||
"title",
|
||||
"user",
|
||||
"lastcommand",
|
||||
"alf1",
|
||||
"alf2",
|
||||
"alf3",
|
||||
"alf4",
|
||||
"bet1",
|
||||
"bet2",
|
||||
"bet3",
|
||||
"bet4",
|
||||
"output",
|
||||
"local",
|
||||
"swunit",
|
||||
"scaninfo",
|
||||
"tei",
|
||||
"tki",
|
||||
"tef",
|
||||
"tkf",
|
||||
"tqh",
|
||||
"tqk",
|
||||
"tql",
|
||||
"ten",
|
||||
"tqm",
|
||||
"ti1",
|
||||
"ti2",
|
||||
"ti3",
|
||||
"ti4",
|
||||
"ti5",
|
||||
"ti6",
|
||||
"ti7",
|
||||
"ti8",
|
||||
"di1",
|
||||
"di2",
|
||||
"di3",
|
||||
"di4",
|
||||
"di5",
|
||||
"di6",
|
||||
"di7",
|
||||
"di8",
|
||||
"dhx",
|
||||
"dhy",
|
||||
"dhz",
|
||||
"thx",
|
||||
"thy",
|
||||
"thz",
|
||||
"hconv1",
|
||||
"hconv2",
|
||||
"hconv3",
|
||||
"hconv4",
|
||||
"polfile",
|
||||
NULL};
|
||||
/*-------------------------------------------------------------------
|
||||
Normally SICS does not store motor hardware limits into status files as
|
||||
they are read from the motor controller. However, in order to better
|
||||
synchronize simulation and instrument this has to be done for TASP.
|
||||
TasSave does just that: saving hard limits in order for the simulation to
|
||||
be able to read them.
|
||||
------------------------------------------------------------------------*/
|
||||
static int TasSaveStatus(void *self, char *name, FILE *fd)
|
||||
{
|
||||
int i = 0;
|
||||
pMotor pMot;
|
||||
float value;
|
||||
SConnection *pCon = NULL;
|
||||
|
||||
pCon = SCCreateDummyConnection(pServ->pSics);
|
||||
if(!pCon)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
while(tasMotorOrder[i] != NULL)
|
||||
{
|
||||
pMot = FindMotor(pServ->pSics,tasMotorOrder[i]);
|
||||
if(pMot)
|
||||
{
|
||||
MotorGetPar(pMot,"hardupperlim",&value);
|
||||
fprintf(fd,"%s hardupperlim %f\n",tasMotorOrder[i], value);
|
||||
MotorGetPar(pMot,"hardlowerlim",&value);
|
||||
fprintf(fd,"%s hardlowerlim %f\n",tasMotorOrder[i], value);
|
||||
/*
|
||||
DISABLED: reading all the motors made to much of a delay during
|
||||
normal operation of the instrument. This is mainly due to the
|
||||
sloooooooooowwwwwwwww SINQ hardware
|
||||
MotorGetSoftPosition(pMot,pCon,&value);
|
||||
fprintf(fd,"run %s %f\n",tasMotorOrder[i], value);
|
||||
*/
|
||||
}
|
||||
i++;
|
||||
}
|
||||
SCDeleteConnection(pCon);
|
||||
/*
|
||||
fprintf(fd,"success\n");
|
||||
*/
|
||||
|
||||
fprintf(fd,"updateqe\n");
|
||||
return 1;
|
||||
}
|
||||
/*---------------------------------------------------------------------
|
||||
There is a special feauture in MAD where the count mode is determined
|
||||
which variable, MN for monitor od TI for time has been set as the last
|
||||
one. In order to implement this in SICS callback functions will be
|
||||
used on the variables which switch the counter box into the appropriate
|
||||
mode.
|
||||
-----------------------------------------------------------------------*/
|
||||
static int MonitorCallback(int iEvent, void *pEvent, void *pUser)
|
||||
{
|
||||
pTASdata self = (pTASdata)pUser;
|
||||
assert(self);
|
||||
|
||||
if(iEvent != VALUECHANGE)
|
||||
return 0;
|
||||
|
||||
SetCounterMode(self->pScan->pCounterData,ePreset);
|
||||
SetCounterPreset(self->pScan->pCounterData,(float)self->tasPar[MN]->iVal);
|
||||
return 1;
|
||||
}
|
||||
/*---------------------------------------------------------------------*/
|
||||
static int TimerCallback(int iEvent, void *pEvent, void *pUser)
|
||||
{
|
||||
pTASdata self = (pTASdata)pUser;
|
||||
assert(self);
|
||||
|
||||
if(iEvent != VALUECHANGE)
|
||||
return 0;
|
||||
|
||||
SetCounterMode(self->pScan->pCounterData,eTimer);
|
||||
SetCounterPreset(self->pScan->pCounterData,self->tasPar[TI]->fVal);
|
||||
return 1;
|
||||
}
|
||||
/*-----------------------------------------------------------------------
|
||||
This is an interpreter wrapper function which allows to call for the
|
||||
recalculation of the energy variables from scripts.
|
||||
--------------------------------------------------------------------------*/
|
||||
extern int TASUpdate(pTASdata self,SConnection *pCon); /* tasutil.c */
|
||||
|
||||
static int RecalcAction(SConnection *pCon, SicsInterp *pSics, void *pData,
|
||||
int argc, char *argv[])
|
||||
{
|
||||
pTASdata self = NULL;
|
||||
|
||||
assert(pCon);
|
||||
assert(pSics);
|
||||
self = (pTASdata)pData;
|
||||
assert(self);
|
||||
|
||||
return TASUpdate(self,pCon);
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------------
|
||||
A function for killing the TAS data structure is needed
|
||||
-------------------------------------------------------------------------*/
|
||||
static void TASKill(void *pData)
|
||||
{
|
||||
pTASdata self = (pTASdata)pData;
|
||||
if(!self)
|
||||
return;
|
||||
|
||||
if(self->pDes)
|
||||
DeleteDescriptor(self->pDes);
|
||||
free(self);
|
||||
}
|
||||
/*-----------------------------------------------------------------------*/
|
||||
int TASFactory(SConnection *pCon, SicsInterp *pSics, void *pData,
|
||||
int argc, char *argv[])
|
||||
{
|
||||
pTASdata pNew = NULL;
|
||||
int iPtr, iError;
|
||||
char pBueffel[132];
|
||||
pSicsVariable pVar = NULL;
|
||||
CommandList *pCom = NULL;
|
||||
|
||||
/* check arguments*/
|
||||
if(argc < 2)
|
||||
{
|
||||
SCWrite(pCon,"ERROR: insufficient paarameters to MakeTAS",eError);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* create a new data structure */
|
||||
pNew = (pTASdata)malloc(sizeof(TASdata));
|
||||
if(!pNew)
|
||||
{
|
||||
SCWrite(pCon,"ERROR: insufficient memory to allocate TAS data structure",
|
||||
eError);
|
||||
return 0;
|
||||
}
|
||||
memset(pNew,0,sizeof(TASdata));
|
||||
pNew->pDes = CreateDescriptor("TAS");
|
||||
if(!pNew->pDes)
|
||||
{
|
||||
SCWrite(pCon,"ERROR: insufficient memory to allocate TAS data structure",
|
||||
eError);
|
||||
free(pNew);
|
||||
return 0;
|
||||
}
|
||||
pNew->iPOL = -1;
|
||||
pNew->pDes->SaveStatus = TasSaveStatus;
|
||||
|
||||
/* connect to all the variables */
|
||||
iPtr = 0; iError = 0;
|
||||
while(tasVariableOrder[iPtr] != NULL)
|
||||
{
|
||||
pNew->tasPar[iPtr] = FindVariable(pSics,tasVariableOrder[iPtr]);
|
||||
if(!pNew->tasPar[iPtr])
|
||||
{
|
||||
sprintf(pBueffel,"ERROR: TAS variable %s not found",
|
||||
tasVariableOrder[iPtr]);
|
||||
SCWrite(pCon,pBueffel,eError);
|
||||
iError++;
|
||||
}
|
||||
iPtr++;
|
||||
}
|
||||
if(iError != 0)
|
||||
{
|
||||
SCWrite(pCon,"ERROR: TAS bad initialisation, TAS not created",eError);
|
||||
TASKill(pNew);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* connect to the scan object */
|
||||
pCom = FindCommand(pSics,argv[1]);
|
||||
if(!pCom)
|
||||
{
|
||||
SCWrite(pCon,"ERROR: no scan routine for TAS found",eError);
|
||||
TASKill(pNew);
|
||||
return 0;
|
||||
}
|
||||
pNew->pScan = (pScanData)pCom->pData;
|
||||
|
||||
/*
|
||||
Install the callbacks for TI and MN. Sloppy error checking because
|
||||
the variables should have been accessed earlier on.
|
||||
*/
|
||||
pVar = FindVariable(pSics,"MN");
|
||||
if(pVar)
|
||||
{
|
||||
RegisterCallback(pVar->pCall,VALUECHANGE,MonitorCallback,pNew,NULL);
|
||||
}
|
||||
pVar = FindVariable(pSics,"TI");
|
||||
if(pVar)
|
||||
{
|
||||
RegisterCallback(pVar->pCall,VALUECHANGE,TimerCallback,pNew,NULL);
|
||||
}
|
||||
|
||||
/*
|
||||
initialize SRO value
|
||||
*/
|
||||
getSRO(pCon,&pNew->oldSRO);
|
||||
|
||||
/* install TAS commands */
|
||||
iError = AddCommand(pSics,"dr",TASDrive,TASKill,pNew);
|
||||
if(!iError)
|
||||
{
|
||||
SCWrite(pCon,"ERROR: duplicate dr command not created",eError);
|
||||
TASKill(pNew);
|
||||
return 0;
|
||||
}
|
||||
iError = AddCommand(pSics,"sc",TASScan,NULL,pNew);
|
||||
if(!iError)
|
||||
{
|
||||
SCWrite(pCon,"ERROR: duplicate sc command not created",eError);
|
||||
TASKill(pNew);
|
||||
return 0;
|
||||
}
|
||||
iError = AddCommand(pSics,"fs",TASScan,NULL,pNew);
|
||||
if(!iError)
|
||||
{
|
||||
SCWrite(pCon,"ERROR: duplicate sf command not created",eError);
|
||||
TASKill(pNew);
|
||||
return 0;
|
||||
}
|
||||
iError = AddCommand(pSics,"updateqe",RecalcAction,NULL,pNew);
|
||||
if(!iError)
|
||||
{
|
||||
SCWrite(pCon,"ERROR: duplicate updateqe command not created",eError);
|
||||
TASKill(pNew);
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user