Initial revision
This commit is contained in:
842
selector.c
Normal file
842
selector.c
Normal file
@@ -0,0 +1,842 @@
|
||||
/*--------------------------------------------------------------------------
|
||||
|
||||
S E L E C T O R
|
||||
|
||||
This is the implementation file for the the code necessary to deal
|
||||
with an energy selector, monochromator. This is the Crystal
|
||||
variety.
|
||||
|
||||
|
||||
Mark Koennecke, January 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 <stdlib.h>
|
||||
#include <assert.h>
|
||||
#include <string.h>
|
||||
#include <math.h>
|
||||
#include "fortify.h"
|
||||
#include "conman.h"
|
||||
#include "SCinter.h"
|
||||
#include "Scommon.h"
|
||||
#include "obdes.h"
|
||||
#include "interface.h"
|
||||
#include "motor.h"
|
||||
#include "splitter.h"
|
||||
#include "devexec.h"
|
||||
#include "selector.h"
|
||||
|
||||
#define SS 0
|
||||
#define B1C1 1
|
||||
#define B1C2 2
|
||||
#define B1MIN 3
|
||||
#define B1MAX 4
|
||||
#define B2C1 5
|
||||
#define B2C2 6
|
||||
#define B2MIN 7
|
||||
#define B2MAX 8
|
||||
#define LATD 9
|
||||
#define RIGHTS 10
|
||||
/*------------------------------------------------------------------------*/
|
||||
typedef struct __SicsSelector {
|
||||
ObjectDescriptor *pDes;
|
||||
ObPar *pParams;
|
||||
char *name;
|
||||
pMotor pTheta;
|
||||
pMotor pTwoTheta;
|
||||
pMotor pBend1;
|
||||
pMotor pBend2;
|
||||
char *pType;
|
||||
} SicsSelector;
|
||||
/*-------------------------------------------------------------------------*/
|
||||
char *MonoGetType(pSicsSelector self)
|
||||
{
|
||||
assert(self);
|
||||
return self->pType;
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
pSicsSelector CreateSelector(char *name, pMotor pTheta, pMotor pTwoTheta,
|
||||
pMotor pBend1, pMotor pBend2)
|
||||
{
|
||||
pSicsSelector pRes = NULL;
|
||||
int iRet;
|
||||
float fVal;
|
||||
|
||||
assert(pTheta);
|
||||
assert(pTwoTheta);
|
||||
|
||||
/* allocate memory */
|
||||
pRes = (pSicsSelector)malloc(sizeof(SicsSelector));
|
||||
if(!pRes)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* create ObjectDescriptor */
|
||||
pRes->pDes = CreateDescriptor("CrystalSelector");
|
||||
if(!pRes->pDes)
|
||||
{
|
||||
free(pRes);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* create Parameter Array */
|
||||
pRes->pParams = ObParCreate(11);
|
||||
if(!pRes->pParams)
|
||||
{
|
||||
free(pRes->pDes);
|
||||
free(pRes);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* create all the parameters */
|
||||
ObParInit(pRes->pParams,SS, "ss",1.,usUser);
|
||||
ObParInit(pRes->pParams,B1C1, "vk1",1.,usInternal);
|
||||
ObParInit(pRes->pParams,B1C2, "vk2",1.,usInternal);
|
||||
ObParInit(pRes->pParams,B2C1, "hk1",1.,usInternal);
|
||||
ObParInit(pRes->pParams,B2C2, "hk2",1.,usInternal);
|
||||
ObParInit(pRes->pParams,LATD, "dd",2.087,usMugger);
|
||||
ObParInit(pRes->pParams,RIGHTS, "access",usUser,usMugger);
|
||||
|
||||
/* assign motors */
|
||||
pRes->pTheta = pTheta;
|
||||
pRes->pTwoTheta = pTwoTheta;
|
||||
|
||||
/* provide default values for Bender Parameters in order to make
|
||||
things look nice
|
||||
*/
|
||||
fVal = 0.;
|
||||
ObParInit(pRes->pParams,B1MIN, "vmin",fVal,usInternal);
|
||||
ObParInit(pRes->pParams,B1MAX, "vmax",fVal,usInternal);
|
||||
ObParInit(pRes->pParams,B2MIN, "hmin",fVal,usInternal);
|
||||
ObParInit(pRes->pParams,B2MAX, "hmax",fVal,usInternal);
|
||||
|
||||
|
||||
/* handle benders, if present */
|
||||
pRes->pBend1 = pBend1;
|
||||
if(pBend1)
|
||||
{
|
||||
iRet = MotorGetPar(pBend1,"hardlowerlim",&fVal);
|
||||
assert(iRet);
|
||||
ObParInit(pRes->pParams,B1MIN, "vmin",fVal,usInternal);
|
||||
iRet = MotorGetPar(pBend1,"hardupperlim",&fVal);
|
||||
assert(iRet);
|
||||
ObParInit(pRes->pParams,B1MAX, "vmax",fVal,usInternal);
|
||||
}
|
||||
pRes->pBend2 = pBend2;
|
||||
if(pBend2)
|
||||
{
|
||||
iRet = MotorGetPar(pBend2,"hardlowerlim",&fVal);
|
||||
assert(iRet);
|
||||
ObParInit(pRes->pParams,B2MIN, "hmin",fVal,usInternal);
|
||||
iRet = MotorGetPar(pBend2,"hardupperlim",&fVal);
|
||||
assert(iRet);
|
||||
ObParInit(pRes->pParams,B2MAX, "hmax",fVal,usInternal);
|
||||
}
|
||||
pRes->name = strdup(name);
|
||||
pRes->pType = strdup("Unknown");
|
||||
return pRes;
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
void DeleteSelector(void *self)
|
||||
{
|
||||
pSicsSelector pSelf;
|
||||
|
||||
assert(self);
|
||||
|
||||
pSelf = (pSicsSelector)self;
|
||||
|
||||
if(pSelf->pDes)
|
||||
{
|
||||
DeleteDescriptor(pSelf->pDes);
|
||||
}
|
||||
if(pSelf->pParams)
|
||||
{
|
||||
ObParDelete(pSelf->pParams);
|
||||
}
|
||||
if(pSelf->name)
|
||||
{
|
||||
free(pSelf->name);
|
||||
}
|
||||
if(pSelf->pType)
|
||||
{
|
||||
free(pSelf->pType);
|
||||
}
|
||||
free(pSelf);
|
||||
}
|
||||
/*--------------------------------------------------------------------------
|
||||
Syntax:
|
||||
MonoInit name Type ThetaMotor TwoThetaMotor Bend1Motor Bend2Motor
|
||||
with Bend1Motor, Bend2Motor beeing optional.
|
||||
*/
|
||||
|
||||
int MonoInit(SConnection *pCon, SicsInterp *pSics, void *pData,
|
||||
int argc, char *argv[])
|
||||
{
|
||||
pSicsSelector pRes = NULL;
|
||||
pMotor pTheta = NULL;
|
||||
pMotor pTwoTheta = NULL;
|
||||
pMotor pBend1 = NULL;
|
||||
pMotor pBend2 = NULL;
|
||||
TokenList *pList = NULL;
|
||||
int iRet = 0;
|
||||
TokenList *pCurrent;
|
||||
char pBueffel[132];
|
||||
char pName[132];
|
||||
char *pType = NULL;
|
||||
|
||||
assert(pCon);
|
||||
assert(pSics);
|
||||
|
||||
/* split arguments */
|
||||
argtolower(argc,argv);
|
||||
pList = SplitArguments(argc,argv);
|
||||
if(!pList)
|
||||
{
|
||||
sprintf(pBueffel,"ERROR: parsing arguments in %s",argv[0]);
|
||||
SCWrite(pCon,pBueffel,eError);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* advance and search name */
|
||||
pCurrent = pList->pNext;
|
||||
if(!pCurrent)
|
||||
{
|
||||
sprintf(pBueffel,"ERRROR: Insufficient number of arguments to %s",
|
||||
argv[0]);
|
||||
SCWrite(pCon,pBueffel,eError);
|
||||
goto end;
|
||||
}
|
||||
strcpy(pName,pCurrent->text);
|
||||
|
||||
/* advance and find Type string */
|
||||
pCurrent = pCurrent->pNext;
|
||||
if(!pCurrent)
|
||||
{
|
||||
sprintf(pBueffel,"ERRROR: Insufficient number of arguments to %s",
|
||||
argv[0]);
|
||||
SCWrite(pCon,pBueffel,eError);
|
||||
goto end;
|
||||
}
|
||||
pType = pCurrent->text;
|
||||
|
||||
/* advance and find Theta motor */
|
||||
pCurrent = pCurrent->pNext;
|
||||
if(!pCurrent)
|
||||
{
|
||||
sprintf(pBueffel,"ERRROR: Insufficient number of arguments to %s",
|
||||
argv[0]);
|
||||
SCWrite(pCon,pBueffel,eError);
|
||||
goto end;
|
||||
}
|
||||
pTheta = FindMotor(pSics,pCurrent->text);
|
||||
if(!pTheta)
|
||||
{
|
||||
sprintf(pBueffel,"ERROR: Cannot find motor %s for driving Theta",
|
||||
pCurrent->text);
|
||||
SCWrite(pCon,pBueffel,eError);
|
||||
goto end;
|
||||
}
|
||||
|
||||
/* advance and find Two Theta motor */
|
||||
pCurrent = pCurrent->pNext;
|
||||
if(!pCurrent)
|
||||
{
|
||||
sprintf(pBueffel,"ERRROR: Insufficient number of arguments to %s",
|
||||
argv[0]);
|
||||
SCWrite(pCon,pBueffel,eError);
|
||||
goto end;
|
||||
}
|
||||
pTwoTheta = FindMotor(pSics,pCurrent->text);
|
||||
if(!pTwoTheta)
|
||||
{
|
||||
sprintf(pBueffel,"ERROR: Cannot find motor %s for driving Two Theta",
|
||||
pCurrent->text);
|
||||
SCWrite(pCon,pBueffel,eError);
|
||||
goto end;
|
||||
}
|
||||
iRet = 1; /* we are now able to install a monochromator */
|
||||
|
||||
/* try find first bending motor */
|
||||
pCurrent = pCurrent->pNext;
|
||||
if(pCurrent)
|
||||
{
|
||||
pBend1 = FindMotor(pSics,pCurrent->text);
|
||||
if(!pBend1)
|
||||
{
|
||||
sprintf(pBueffel,"ERROR: Cannot find motor %s for driving vertical bender",
|
||||
pCurrent->text);
|
||||
SCWrite(pCon,pBueffel,eError);
|
||||
goto end;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
goto end;
|
||||
}
|
||||
|
||||
/* find second bender */
|
||||
pCurrent = pCurrent->pNext;
|
||||
if(pCurrent)
|
||||
{
|
||||
pBend2 = FindMotor(pSics,pCurrent->text);
|
||||
if(!pBend2)
|
||||
{
|
||||
sprintf(pBueffel,"ERROR: Cannot find motor %s for driving horizontal bender",
|
||||
pCurrent->text);
|
||||
SCWrite(pCon,pBueffel,eError);
|
||||
goto end;
|
||||
}
|
||||
}
|
||||
|
||||
end:
|
||||
if(iRet)
|
||||
{
|
||||
pRes = CreateSelector(pName, pTheta, pTwoTheta,pBend1,pBend2);
|
||||
if(!pRes)
|
||||
{
|
||||
iRet = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
if(pRes->pType)
|
||||
{
|
||||
free(pRes->pType);
|
||||
}
|
||||
pRes->pType = strdup(pType);
|
||||
iRet = AddCommand(pSics, pName,MonoAction,DeleteSelector,(void *)pRes);
|
||||
if(!iRet)
|
||||
{
|
||||
sprintf(pBueffel,"ERROR: duplicate command %s not created",argv[2]);
|
||||
SCWrite(pCon,pBueffel,eError);
|
||||
DeleteTokenList(pList);
|
||||
DeleteSelector((void *)pRes);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
DeleteTokenList(pList);
|
||||
return iRet;
|
||||
|
||||
}
|
||||
/*---------------------------------------------------------------------------
|
||||
a private function used in MonoAction to print all relevant features of
|
||||
the monochromator
|
||||
*/
|
||||
static void MonoList(pSicsSelector self, SConnection *pCon)
|
||||
{
|
||||
char pBueffel[512];
|
||||
int i, iLen;
|
||||
|
||||
/* print known parameters */
|
||||
iLen = ObParLength(self->pParams);
|
||||
sprintf(pBueffel,"Parameter Listing for %s\n",self->name);
|
||||
SCWrite(pCon,pBueffel,eStatus);
|
||||
for(i = 0; i < iLen; i++)
|
||||
{
|
||||
sprintf(pBueffel,"%s.%s = %f\n",self->name,
|
||||
self->pParams[i].name,self->pParams[i].fVal);
|
||||
SCWrite(pCon,pBueffel,eStatus);
|
||||
}
|
||||
|
||||
/* print motornames as well */
|
||||
sprintf(pBueffel,"%s.ThetaMotor = %s\n",self->name,self->pTheta->name);
|
||||
SCWrite(pCon,pBueffel,eStatus);
|
||||
sprintf(pBueffel,"%s.TwoThetaMotor = %s\n",self->name,self->pTwoTheta->name);
|
||||
SCWrite(pCon,pBueffel,eStatus);
|
||||
if(self->pBend1)
|
||||
{
|
||||
sprintf(pBueffel,"%s.VerticalBenderMotor = %s\n",self->name,self->pBend1->name);
|
||||
SCWrite(pCon,pBueffel,eStatus);
|
||||
}
|
||||
if(self->pBend2)
|
||||
{
|
||||
sprintf(pBueffel,"%s.HorizontalBenderMotor = %s\n",self->name,self->pBend2->name);
|
||||
SCWrite(pCon,pBueffel,eStatus);
|
||||
}
|
||||
}
|
||||
/*-----------------------------------------------------------------------------
|
||||
The Action function. Syntax:
|
||||
mononame list -- list all pars
|
||||
mononame parname -- prints parameter
|
||||
mononame parname value -- tries changing the parameter
|
||||
*/
|
||||
|
||||
int MonoAction(SConnection *pCon, SicsInterp *pSics, void *pData,
|
||||
int argc, char *argv[])
|
||||
{
|
||||
pSicsSelector pSelf = NULL;
|
||||
TokenList *pList = NULL;
|
||||
TokenList *pCurrent;
|
||||
int iRet;
|
||||
char pBueffel[132];
|
||||
char pName[132];
|
||||
float fVal;
|
||||
ObPar *pPar = NULL;
|
||||
|
||||
assert(pCon);
|
||||
assert(pSics);
|
||||
assert(pData);
|
||||
|
||||
pSelf = (pSicsSelector)pData;
|
||||
|
||||
/* split arguments */
|
||||
argtolower(argc,argv);
|
||||
pList = SplitArguments(argc,argv);
|
||||
if(!pList)
|
||||
{
|
||||
sprintf(pBueffel,"ERROR: parsing arguments in %s",argv[0]);
|
||||
SCWrite(pCon,pBueffel,eError);
|
||||
return 0;
|
||||
}
|
||||
|
||||
pCurrent = pList->pNext;
|
||||
/* now we can have "list" or a parametername */
|
||||
/* check for list first */
|
||||
if(!pCurrent)
|
||||
{
|
||||
sprintf(pBueffel,"ERROR: Insufficient number of arguments to %s",
|
||||
argv[0]);
|
||||
SCWrite(pCon,pBueffel,eError);
|
||||
goto end;
|
||||
}
|
||||
if(strcmp(pCurrent->text,"list") == 0)
|
||||
{
|
||||
MonoList(pSelf,pCon);
|
||||
iRet = 1;
|
||||
goto end;
|
||||
}
|
||||
|
||||
/* must be parametername now */
|
||||
strcpy(pName,pCurrent->text);
|
||||
|
||||
/* find out if it is a set or a get. On set there is another paremeter,
|
||||
else none
|
||||
*/
|
||||
pCurrent = pCurrent->pNext;
|
||||
if(pCurrent) /* set */
|
||||
{
|
||||
/* check if input is proper */
|
||||
if(pCurrent->Type == eFloat)
|
||||
{
|
||||
fVal = pCurrent->fVal;
|
||||
}
|
||||
else if(pCurrent->Type == eInt)
|
||||
{
|
||||
fVal = (float)pCurrent->iVal;
|
||||
}
|
||||
else
|
||||
{
|
||||
sprintf(pBueffel,"ERROR: Illegal parameter %s given to %s",
|
||||
pCurrent->text, argv[0]);
|
||||
SCWrite(pCon,pBueffel,eError);
|
||||
goto end;
|
||||
}
|
||||
iRet = ObParSet(pSelf->pParams,argv[0],pName,fVal,pCon);
|
||||
goto end;
|
||||
}
|
||||
else /* get */
|
||||
{
|
||||
pPar = ObParFind(pSelf->pParams,pName);
|
||||
if(!pPar)
|
||||
{
|
||||
sprintf(pBueffel,"ERROR: Parameter %s not found in %s",pName, argv[0]);
|
||||
SCWrite(pCon,pBueffel,eError);
|
||||
goto end;
|
||||
}
|
||||
else
|
||||
{
|
||||
sprintf(pBueffel,"%s.%s = %f",argv[0],pName,pPar->fVal);
|
||||
SCWrite(pCon,pBueffel,eValue);
|
||||
iRet = 1;
|
||||
goto end;
|
||||
}
|
||||
}
|
||||
end:
|
||||
DeleteTokenList(pList);
|
||||
if(iRet)
|
||||
SCSendOK(pCon);
|
||||
return iRet;
|
||||
}
|
||||
/*--------------------------------------------------------------------------*/
|
||||
struct SelPos {
|
||||
float fTheta, fTwoTheta, fVert, fHor;
|
||||
};
|
||||
#define PI 3.14159265358979323846264338327950
|
||||
#define RD 57.29577951308232087679815481410517
|
||||
/* ------------------- C has no proper abs -------------------------------*/
|
||||
static double absd(double f)
|
||||
{
|
||||
if(f < .0)
|
||||
{
|
||||
f = -f;
|
||||
}
|
||||
return f;
|
||||
}
|
||||
/*-------------------------------------------------------------------------*/
|
||||
static struct SelPos CalculatePosition(pSicsSelector self, float fWaveLength)
|
||||
{
|
||||
struct SelPos pRes;
|
||||
double fD;
|
||||
|
||||
/* Theta, TwoTheta first */
|
||||
fD = fWaveLength/(2.0* ObVal(self->pParams,LATD));
|
||||
if(fD > 1.0)
|
||||
{
|
||||
pRes.fTheta = 1000.; /* error indication: energy to big */
|
||||
return pRes;
|
||||
}
|
||||
fD = asin(fD);
|
||||
pRes.fTheta = fD*ObVal(self->pParams,SS)*RD;
|
||||
pRes.fTwoTheta = 2 * pRes.fTheta;
|
||||
|
||||
/* now first bender */
|
||||
if(self->pBend1)
|
||||
{
|
||||
pRes.fVert = ObVal(self->pParams,B1C1)+(ObVal(self->pParams,B1C2)/
|
||||
sin(fD));
|
||||
}
|
||||
|
||||
|
||||
/* now second bender */
|
||||
if(self->pBend2)
|
||||
{
|
||||
pRes.fHor = ObVal(self->pParams,B2C1)+ (ObVal(self->pParams,B2C2)/
|
||||
sin(fD));
|
||||
}
|
||||
return pRes;
|
||||
}
|
||||
/*--------------------------------------------------------------------------*/
|
||||
int MonoLimits(pSicsSelector self, float fWaveLength,
|
||||
char *error, int iErrLen)
|
||||
{
|
||||
struct SelPos sNeu;
|
||||
char pBueffel[132];
|
||||
pIDrivable pDrivInt = NULL;
|
||||
|
||||
/* get Position */
|
||||
sNeu = CalculatePosition(self,fWaveLength);
|
||||
if(sNeu.fTheta > 900.) /* invalid wavelength or energy */
|
||||
{
|
||||
sprintf(pBueffel,"ERROR: Invalid wavelength or energy to high: %f",
|
||||
fWaveLength);
|
||||
strncpy(error,pBueffel,iErrLen-1);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* check each motor in turn */
|
||||
pDrivInt = self->pTheta->pDescriptor->GetInterface(self->pTheta,DRIVEID);
|
||||
if(!pDrivInt->CheckLimits(self->pTheta,sNeu.fTheta,error,iErrLen))
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
pDrivInt = self->pTwoTheta->pDescriptor->GetInterface(self->pTwoTheta,DRIVEID);
|
||||
if(!pDrivInt->CheckLimits(self->pTwoTheta,sNeu.fTwoTheta,
|
||||
error,iErrLen))
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
if(self->pBend1)
|
||||
{
|
||||
pDrivInt = self->pBend1->pDescriptor->GetInterface(self->pBend1,DRIVEID);
|
||||
if(!pDrivInt->CheckLimits(self->pBend1,sNeu.fVert,
|
||||
error,iErrLen))
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
if(self->pBend2)
|
||||
{
|
||||
pDrivInt = self->pBend2->pDescriptor->GetInterface(self->pBend2,DRIVEID);
|
||||
if(!pDrivInt->CheckLimits(self->pBend2,sNeu.fHor,
|
||||
error,iErrLen))
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
/*--------------------------------------------------------------------------*/
|
||||
int MonoHalt(pSicsSelector self)
|
||||
{
|
||||
pIDrivable pDrivInt = NULL;
|
||||
|
||||
/* halt each motor in turn */
|
||||
pDrivInt = self->pTheta->pDescriptor->GetInterface(self->pTheta,DRIVEID);
|
||||
if(pDrivInt)
|
||||
{
|
||||
pDrivInt->Halt(self->pTheta);
|
||||
}
|
||||
|
||||
pDrivInt = self->pTwoTheta->pDescriptor->GetInterface(self->pTwoTheta,DRIVEID);
|
||||
if(pDrivInt)
|
||||
{
|
||||
pDrivInt->Halt(self->pTwoTheta);
|
||||
}
|
||||
|
||||
if(self->pBend1)
|
||||
{
|
||||
pDrivInt = self->pBend1->pDescriptor->GetInterface(self->pBend1,DRIVEID);
|
||||
if(pDrivInt)
|
||||
{
|
||||
pDrivInt->Halt(self->pBend1);
|
||||
}
|
||||
}
|
||||
if(self->pBend2)
|
||||
{
|
||||
pDrivInt = self->pBend2->pDescriptor->GetInterface(self->pBend2,DRIVEID);
|
||||
if(pDrivInt)
|
||||
{
|
||||
pDrivInt->Halt(self->pBend2);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return 1;
|
||||
}
|
||||
/*-------------------------------------------------------------------------*/
|
||||
int MonoRun(pSicsSelector self, SConnection *pCon, float fWaveLength)
|
||||
{
|
||||
struct SelPos sNeu;
|
||||
char pBueffel[132];
|
||||
int iRet;
|
||||
|
||||
/* Check authorisation */
|
||||
if(!SCMatchRights(pCon,(int)ObVal(self->pParams,RIGHTS)))
|
||||
{
|
||||
sprintf(pBueffel,
|
||||
"ERROR: You are not authorised to move the monochromator %s",self->name);
|
||||
SCWrite(pCon,pBueffel,eError);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* get Position */
|
||||
sNeu = CalculatePosition(self,fWaveLength);
|
||||
if(sNeu.fTheta > 900.) /* invalid wavelength or energy */
|
||||
{
|
||||
sprintf(pBueffel,"ERROR: Invalid wavelength or energy to high: %f",
|
||||
fWaveLength);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* start each motor in turn */
|
||||
iRet = StartDevice(GetExecutor(),self->pTheta->name, self->pTheta->pDescriptor,
|
||||
self->pTheta,
|
||||
pCon,sNeu.fTheta);
|
||||
if(!iRet)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
iRet = StartDevice(GetExecutor(),self->pTwoTheta->name, self->pTwoTheta->pDescriptor,
|
||||
self->pTwoTheta,
|
||||
pCon,sNeu.fTwoTheta);
|
||||
if(!iRet)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/* bending motors */
|
||||
if(self->pBend1)
|
||||
{
|
||||
iRet = StartDevice(GetExecutor(),self->pBend1->name, self->pBend1->pDescriptor,
|
||||
self->pBend1,
|
||||
pCon,sNeu.fVert);
|
||||
if(!iRet)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
}
|
||||
if(self->pBend2)
|
||||
{
|
||||
iRet = StartDevice(GetExecutor(),self->pBend2->name, self->pBend2->pDescriptor,
|
||||
self->pBend2,
|
||||
pCon,sNeu.fHor);
|
||||
if(!iRet)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
/*--------------------------------------------------------------------------*/
|
||||
int MonoCheck(pSicsSelector self, SConnection *pCon)
|
||||
{
|
||||
int iRet;
|
||||
pIDrivable pDrivInt = NULL;
|
||||
|
||||
/* cheack each motor in turn */
|
||||
pDrivInt = self->pTheta->pDescriptor->GetInterface(self->pTheta,DRIVEID);
|
||||
if(pDrivInt)
|
||||
{
|
||||
iRet = pDrivInt->CheckStatus(self->pTheta,pCon);
|
||||
if( (iRet != OKOK) && (iRet != HWIdle))
|
||||
{
|
||||
return iRet;
|
||||
}
|
||||
}
|
||||
|
||||
pDrivInt = self->pTwoTheta->pDescriptor->GetInterface(self->pTwoTheta,DRIVEID);
|
||||
if(pDrivInt)
|
||||
{
|
||||
iRet = pDrivInt->CheckStatus(self->pTwoTheta,pCon);
|
||||
if( (iRet != OKOK) && (iRet != HWIdle))
|
||||
{
|
||||
return iRet;
|
||||
}
|
||||
}
|
||||
|
||||
if(self->pBend1)
|
||||
{
|
||||
pDrivInt = self->pBend1->pDescriptor->GetInterface(self->pBend1,DRIVEID);
|
||||
if(pDrivInt)
|
||||
{
|
||||
iRet = pDrivInt->CheckStatus(self->pBend1,pCon);
|
||||
if( (iRet != OKOK) && (iRet != HWIdle))
|
||||
{
|
||||
return iRet;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(self->pBend2)
|
||||
{
|
||||
pDrivInt = self->pBend2->pDescriptor->GetInterface(self->pBend2,DRIVEID);
|
||||
if(pDrivInt)
|
||||
{
|
||||
iRet = pDrivInt->CheckStatus(self->pBend2,pCon);
|
||||
if( (iRet != OKOK) && (iRet != HWIdle))
|
||||
{
|
||||
return iRet;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return HWIdle;
|
||||
}
|
||||
/*--------------------------------------------------------------------------
|
||||
returns the current Wavelength the monochromator is adjusted to
|
||||
*/
|
||||
float GetMonoPosition(pSicsSelector self, SConnection *pCon)
|
||||
{
|
||||
double fVal, dTheta;
|
||||
float fTheta, fTwoTheta;
|
||||
char pBueffel[132];
|
||||
int iRet;
|
||||
|
||||
/* get the two positions */
|
||||
iRet = MotorGetSoftPosition(self->pTheta,pCon,&fTheta);
|
||||
if(!iRet)
|
||||
{
|
||||
sprintf(pBueffel,"ERROR: cannot read Theta motor for monochromator %s\n",
|
||||
self->name);
|
||||
SCWrite(pCon,pBueffel,eError);
|
||||
return 0.;
|
||||
}
|
||||
iRet = MotorGetSoftPosition(self->pTwoTheta,pCon,&fTwoTheta);
|
||||
if(!iRet)
|
||||
{
|
||||
sprintf(pBueffel,"ERROR: cannot read TwoTheta motor for monochromator %s\n",
|
||||
self->name);
|
||||
SCWrite(pCon,pBueffel,eError);
|
||||
return 0.;
|
||||
}
|
||||
|
||||
/* check for sync */
|
||||
fVal = fTwoTheta - 2* fTheta;
|
||||
if(fVal < 0.)fVal = -fVal;
|
||||
if(fVal > 0.01)
|
||||
{
|
||||
sprintf(pBueffel,"WARNING: monochromator %s out of sync by %f\n",
|
||||
self->name,fVal);
|
||||
SCWrite(pCon,pBueffel,eStatus);
|
||||
}
|
||||
|
||||
/* calculate wavelength from angles */
|
||||
dTheta =(double)fTheta;
|
||||
dTheta = dTheta *(1.0/RD);
|
||||
fVal = 2.0 * (double)ObVal(self->pParams,LATD);
|
||||
fVal = fVal * sin(dTheta);
|
||||
return fVal;
|
||||
}
|
||||
/*--------------------------------------------------------------------------*/
|
||||
int GetMonoPositions(pSicsSelector self, SConnection *pCon,
|
||||
float *fTh, float *f2TH, float *fB1, float *fB2)
|
||||
{
|
||||
int iRet;
|
||||
char pBueffel[512];
|
||||
|
||||
iRet = MotorGetSoftPosition(self->pTheta,pCon,fTh);
|
||||
if(!iRet)
|
||||
{
|
||||
sprintf(pBueffel,"ERROR: cannot read Theta motor for monochromator %s\n",
|
||||
self->name);
|
||||
SCWrite(pCon,pBueffel,eError);
|
||||
return 0.;
|
||||
}
|
||||
iRet = MotorGetSoftPosition(self->pTwoTheta,pCon,f2TH);
|
||||
if(!iRet)
|
||||
{
|
||||
sprintf(pBueffel,"ERROR: cannot read TwoTheta motor for monochromator %s\n",
|
||||
self->name);
|
||||
SCWrite(pCon,pBueffel,eError);
|
||||
return 0.;
|
||||
}
|
||||
|
||||
if(self->pBend1)
|
||||
{
|
||||
iRet = MotorGetSoftPosition(self->pBend1,pCon,fB1);
|
||||
if(!iRet)
|
||||
{
|
||||
sprintf(pBueffel,"ERROR: cannot read vertical bender motor for monochromator %s\n",
|
||||
self->name);
|
||||
SCWrite(pCon,pBueffel,eError);
|
||||
return 0.;
|
||||
}
|
||||
}
|
||||
if(self->pBend2)
|
||||
{
|
||||
iRet = MotorGetSoftPosition(self->pBend2,pCon,fB2);
|
||||
if(!iRet)
|
||||
{
|
||||
sprintf(pBueffel,"ERROR: cannot read horizontal bender motor for monochromator %s\n",
|
||||
self->name);
|
||||
SCWrite(pCon,pBueffel,eError);
|
||||
return 0.;
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user