Files
sics/hklmot.c
koennecke b737b4d936 - Many fixes to accomodate a nitty picky TRICS wishlist
- Added a log facility to scan which includes a variable which is logged but
  not driven during a scan.
- Fixed normal beam operation
2006-01-27 11:33:06 +00:00

249 lines
7.3 KiB
C

/*------------------------------------------------------------------------------------------------------
Virtual motor interface to reciprocal space coordinates H, K and L for a four circle diffractometer.
Requires a HKL object for calculations.
copyright: see file COPYRIGHT
Mark Koennecke, February 2005
--------------------------------------------------------------------------------------------------------*/
#include <stdlib.h>
#include <assert.h>
#include "sics.h"
#include "fortify.h"
#include "motor.h"
#include "matrix/matrix.h"
#include "hkl.h"
#include "hkl.i"
#include "hklmot.h"
/*=================== Object Descriptor Interface ===================================================*/
static void *HKLGetInterface(void *pData, int iID){
pHKLMot self = NULL;
self = (pHKLMot)pData;
if(self == NULL){
return NULL;
}
if(iID == DRIVEID){
return self->pDriv;
}
return NULL;
}
/*=================== Drivable Interface ============================================================*/
static int HKLHalt(void *pData){
pHKLMot self = NULL;
self = (pHKLMot)pData;
assert(self != NULL);
self->pHkl->pTheta->pDrivInt->Halt(self->pHkl->pTheta);
self->pHkl->pOmega->pDrivInt->Halt(self->pHkl->pOmega);
if(self->pHkl->iNOR == 1){
self->pHkl->pNu->pDrivInt->Halt(self->pHkl->pNu);
} else {
self->pHkl->pChi->pDrivInt->Halt(self->pHkl->pChi);
self->pHkl->pPhi->pDrivInt->Halt(self->pHkl->pPhi);
}
return 1;
}
/*-----------------------------------------------------------------------------------------------------*/
static int HKLCheckLimits(void *self, float fVal, char *error, int errLen){
/*
There is no meaningful implementation here. This gets called when starting the motor.
At that stage not all other values may be known. If the calculation fails, this will die
at status check time.
*/
return 1;
}
/*----------------------------------------------------------------------------------------------------*/
static long HKLSetValue(void *pData, SConnection *pCon, float fVal){
pHKLMot self = NULL;
if(!SCMatchRights(pCon,usUser)){
return 0;
}
self = (pHKLMot)pData;
assert(self != NULL);
self->pHkl->targetHKL[self->index] = fVal;
self->pHkl->targetDirty = 1;
return OKOK;
}
/*---------------------------------------------------------------------------------------------------*/
static int checkMotors(pHKLMot self, SConnection *pCon){
int status;
status = self->pHkl->pTheta->pDrivInt->CheckStatus(self->pHkl->pTheta, pCon);
if(status != HWIdle && status != OKOK){
return status;
}
status = self->pHkl->pOmega->pDrivInt->CheckStatus(self->pHkl->pOmega, pCon);
if(status != HWIdle && status != OKOK){
return status;
}
if(self->pHkl->iNOR == 1){
status = self->pHkl->pNu->pDrivInt->CheckStatus(self->pHkl->pNu, pCon);
if(status != HWIdle && status != OKOK){
return status;
}
} else {
status = self->pHkl->pChi->pDrivInt->CheckStatus(self->pHkl->pChi, pCon);
if(status != HWIdle && status != OKOK){
return status;
}
status = self->pHkl->pPhi->pDrivInt->CheckStatus(self->pHkl->pPhi, pCon);
if(status != HWIdle && status != OKOK){
return status;
}
}
return HWIdle;
}
/*-----------------------------------------------------------------------------------------------------*/
static int HKLCheckStatus(void *pData, SConnection *pCon){
pHKLMot self = NULL;
int status;
self = (pHKLMot)pData;
assert(self != NULL);
if(self->pHkl->targetDirty == 1){
status = RunHKL(self->pHkl,self->pHkl->targetHKL,.0,0,pCon);
self->pHkl->targetDirty = 0;
if(status != 1){
SCSetInterrupt(pCon,eAbortOperation);
return HWFault;
}
return HWBusy;
} else {
return checkMotors(self,pCon);
}
}
/*-----------------------------------------------------------------------------------------------------*/
static float HKLGetValue(void *pData, SConnection *pCon){
pHKLMot self = NULL;
float fVal[3];
int status;
self = (pHKLMot)pData;
assert(self != NULL);
status = GetHKLFromAngles(self->pHkl,pCon,fVal);
if(status != 1){
SCWrite(pCon,"ERROR: failed to read positions or convert to HKL",eError);
return -9999.99;
}
return fVal[self->index];
}
/*=============================== Live and Death ====================================*/
static pHKLMot MakeHKLMot(pHKL pHkl, int index){
pHKLMot self = NULL;
assert(pHkl != NULL);
assert(index >= 0 && index < 3);
self = (pHKLMot)malloc(sizeof(HKLMot));
if(self == NULL){
return NULL;
}
memset(self,0,sizeof(HKLMot));
self->pDes = CreateDescriptor("HKLMot");
self->pDriv = CreateDrivableInterface();
if(self->pDes == NULL || self->pDriv == NULL){
free(self);
return NULL;
}
self->pDes->GetInterface = HKLGetInterface;
self->pDriv->Halt = HKLHalt;
self->pDriv->CheckLimits = HKLCheckLimits;
self->pDriv->SetValue = HKLSetValue;
self->pDriv->CheckStatus = HKLCheckStatus;
self->pDriv->GetValue = HKLGetValue;
self->pHkl = pHkl;
self->index = index;
return self;
}
/*----------------------------------------------------------------------------------*/
static void KillHklMot(void *pData){
pHKLMot self = NULL;
self = (pHKLMot)pData;
if(self == NULL){
return;
}
if(self->pDes != NULL){
DeleteDescriptor(self->pDes);
}
if(self->pDriv){
free(self->pDriv);
}
free(self);
}
/*=============================== Interpreter Interface ============================*/
int HKLMotAction(SConnection *pCon, SicsInterp *pSics, void *pData, int argc, char *argv[]){
pHKLMot self = NULL;
float value;
char pBuffer[132];
self = (pHKLMot)pData;
assert(self != NULL);
value = self->pDriv->GetValue(self,pCon);
if(value < -9000.){
snprintf(pBuffer,131,"ERROR: failed to read %s",argv[0]);
SCWrite(pCon,pBuffer,eError);
return 0;
}
snprintf(pBuffer,131,"%s = %f", argv[0], value);
SCWrite(pCon,pBuffer,eValue);
return 1;
}
/*------------------------------------------------------------------------------------------*/
int HKLMotInstall(SConnection *pCon, SicsInterp *pSics, void *pData, int argc, char *argv[]){
pHKL pHkl;
pHKLMot pMot = NULL;
char pBuffer[131];
if(argc < 2){
SCWrite(pCon,"ERROR: Insifficient number of arguments to HKLMotInstall",eError);
return 0;
}
strtolower(argv[1]);
pHkl = (pHKL)FindCommandData(pSics,argv[1],"4-Circle-Calculus");
if(pHkl == NULL){
snprintf(pBuffer,131,"ERROR: %s is not present or no HKL object",argv[1]);
SCWrite(pCon,pBuffer,eError);
return 0;
}
pMot = MakeHKLMot(pHkl, 0);
if(pMot == NULL){
SCWrite(pCon,"ERROR: out of memory creating H Motor",eError);
return 0;
}
if(!AddCommand(pSics,"H",HKLMotAction,KillHklMot,pMot)){
SCWrite(pCon,"ERROR: duplicate command H not created",eError);
return 0;
}
pMot = MakeHKLMot(pHkl, 1);
if(pMot == NULL){
SCWrite(pCon,"ERROR: out of memory creating K Motor",eError);
return 0;
}
if(!AddCommand(pSics,"K",HKLMotAction,KillHklMot,pMot)){
SCWrite(pCon,"ERROR: duplicate command K not created",eError);
return 0;
}
pMot = MakeHKLMot(pHkl, 2);
if(pMot == NULL){
SCWrite(pCon,"ERROR: out of memory creating L Motor",eError);
return 0;
}
if(!AddCommand(pSics,"L",HKLMotAction,KillHklMot,pMot)){
SCWrite(pCon,"ERROR: duplicate command L not created",eError);
return 0;
}
return 1;
}