- many fixes to TAS - Changed HM code for ILL PSD to account for Christoph's offset to positive.
378 lines
11 KiB
C
378 lines
11 KiB
C
/*--------------------------------------------------------------------------
|
|
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"
|
|
|
|
/*
|
|
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",
|
|
"tt",
|
|
"i1" ,
|
|
"i2",
|
|
"i3",
|
|
"i4",
|
|
"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",
|
|
"dt",
|
|
"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};
|
|
/*---------------------------------------------------------------------
|
|
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;
|
|
|
|
/* 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);
|
|
}
|
|
|
|
/* 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;
|
|
}
|
|
|
|
|