- Removed old code
- Extended tasker to support task groups - Added task functions for motors and counters - Modifed devexec to use the new task functions - Modified TAS to treat the monochromator separatly - Coded a EIGER monochromator module to reflect even more new requirements - Added EPICS counters and motors - Modified multicounter to be better performing SKIPPED: psi/eigermono.c psi/make_gen psi/makefile_linux psi/psi.c psi/sinqhttp.c
This commit is contained in:
@ -23,6 +23,7 @@
|
|||||||
#include "nserver.h"
|
#include "nserver.h"
|
||||||
#include "servlog.h"
|
#include "servlog.h"
|
||||||
|
|
||||||
|
extern void KeepStartupCommands(); /* ofac.c */
|
||||||
/***************************** Necessary Globals ****************************/
|
/***************************** Necessary Globals ****************************/
|
||||||
|
|
||||||
IPair *pSICSOptions = NULL;
|
IPair *pSICSOptions = NULL;
|
||||||
@ -47,6 +48,8 @@ int main(int argc, char *argv[])
|
|||||||
for (i = 1; i < argc; i++) {
|
for (i = 1; i < argc; i++) {
|
||||||
if (strcmp(argv[i], "-nolog") == 0) {
|
if (strcmp(argv[i], "-nolog") == 0) {
|
||||||
SICSLogEnable(0);
|
SICSLogEnable(0);
|
||||||
|
}else if(strcmp(argv[i],"-keepstartup") == 0){
|
||||||
|
KeepStartupCommands();
|
||||||
} else if (file == NULL) {
|
} else if (file == NULL) {
|
||||||
file = argv[i];
|
file = argv[i];
|
||||||
}
|
}
|
||||||
|
@ -14,14 +14,14 @@
|
|||||||
- a checkscript to be run at the end of driving the motor
|
- a checkscript to be run at the end of driving the motor
|
||||||
- a means to call the write script multiple times. This is useful if
|
- a means to call the write script multiple times. This is useful if
|
||||||
you need to drive to the value in multiple steps. An example is the
|
you need to drive to the value in multiple steps. An example is the
|
||||||
BOA double crystal monochromator where you first have to pu the baldes to
|
BOA double crystal monochromator where you first have to put the blades to
|
||||||
0, then drive the translation and then drive the blades to the real theta.
|
0, then drive the translation and then drive the blades to the real theta.
|
||||||
All this to avoid collisions. In order to support this, a state field and
|
All this to avoid collisions. In order to support this, a state field and
|
||||||
and a readable target field has been added. The mode of operation is such
|
and a readable target field has been added. The mode of operation is such
|
||||||
that the on first run the, writescript set the state to something different
|
that the on first run the, writescript set the state to something different
|
||||||
then idle. This causes after the first set of motors finished running the
|
then idle. This causes after the first set of motors finished running the
|
||||||
writescript to be called again. This can figure out by lookin at the
|
writescript to be called again. This can figure out by lookin at the
|
||||||
state variable what to do. This can be doen in repetition until the
|
state variable what to do. This can be done in repetition until the
|
||||||
writescript sets state to idle again.
|
writescript sets state to idle again.
|
||||||
|
|
||||||
Mark Koennecke, April 2012
|
Mark Koennecke, April 2012
|
||||||
|
@ -61,7 +61,7 @@ typedef struct {
|
|||||||
char *pName;
|
char *pName;
|
||||||
} MonEvent, *pMonEvent;
|
} MonEvent, *pMonEvent;
|
||||||
|
|
||||||
/*--------------------------------------------------------------------------*/
|
/*-----------------------------------------------------------------------------*/
|
||||||
static int Halt(void *pData)
|
static int Halt(void *pData)
|
||||||
{
|
{
|
||||||
pCounter self = NULL;
|
pCounter self = NULL;
|
||||||
@ -444,12 +444,13 @@ int MakeCounter(SConnection * pCon, SicsInterp * pSics, void *pData,
|
|||||||
assert(pCon);
|
assert(pCon);
|
||||||
assert(pSics);
|
assert(pSics);
|
||||||
|
|
||||||
argtolower(argc, argv);
|
|
||||||
if (argc < 3) {
|
if (argc < 3) {
|
||||||
SCWrite(pCon, "ERROR: insuficient number of arguments to MakeCounter",
|
SCWrite(pCon, "ERROR: insuficient number of arguments to MakeCounter",
|
||||||
eError);
|
eError);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
strtolower(argv[1]);
|
||||||
|
strtolower(argv[2]);
|
||||||
site = getSite();
|
site = getSite();
|
||||||
if (site != NULL) {
|
if (site != NULL) {
|
||||||
pDriv = site->CreateCounterDriver(pCon, argc, argv);
|
pDriv = site->CreateCounterDriver(pCon, argc, argv);
|
||||||
|
@ -184,5 +184,7 @@
|
|||||||
*/
|
*/
|
||||||
void *GetExecutorCallback(pExeList self);
|
void *GetExecutorCallback(pExeList self);
|
||||||
/*----------------------- Logging -----------------------------------------*/
|
/*----------------------- Logging -----------------------------------------*/
|
||||||
void DevexecLog(char *op, char *device);
|
void DevexecLog(char *op, char *device);
|
||||||
|
void ExeInterest(pExeList pExe, char *name, char *action);
|
||||||
|
void InvokeNewTarget(pExeList pExe, char *name, float fTarget);
|
||||||
#endif
|
#endif
|
||||||
|
@ -373,7 +373,9 @@ to the global SICS device executor.
|
|||||||
\mbox{}\verb@ */ @\\
|
\mbox{}\verb@ */ @\\
|
||||||
\mbox{}\verb@ void *GetExecutorCallback(pExeList self);@\\
|
\mbox{}\verb@ void *GetExecutorCallback(pExeList self);@\\
|
||||||
\mbox{}\verb@/*----------------------- Logging -----------------------------------------*/@\\
|
\mbox{}\verb@/*----------------------- Logging -----------------------------------------*/@\\
|
||||||
\mbox{}\verb@ void DevexecLog(char *op, char *device); @\\
|
\mbox{}\verb@ void DevexecLog(char *op, char *device);@\\
|
||||||
|
\mbox{}\verb@ void ExeInterest(pExeList pExe, char *name, char *action); @\\
|
||||||
|
\mbox{}\verb@ void InvokeNewTarget(pExeList pExe, char *name, float fTarget);@\\
|
||||||
\mbox{}\verb@#endif @\\
|
\mbox{}\verb@#endif @\\
|
||||||
\mbox{}\verb@@$\Diamond$
|
\mbox{}\verb@@$\Diamond$
|
||||||
\end{list}
|
\end{list}
|
||||||
|
@ -319,7 +319,9 @@ to the global SICS device executor.
|
|||||||
*/
|
*/
|
||||||
void *GetExecutorCallback(pExeList self);
|
void *GetExecutorCallback(pExeList self);
|
||||||
/*----------------------- Logging -----------------------------------------*/
|
/*----------------------- Logging -----------------------------------------*/
|
||||||
void DevexecLog(char *op, char *device);
|
void DevexecLog(char *op, char *device);
|
||||||
|
void ExeInterest(pExeList pExe, char *name, char *action);
|
||||||
|
void InvokeNewTarget(pExeList pExe, char *name, float fTarget);
|
||||||
#endif
|
#endif
|
||||||
@}
|
@}
|
||||||
|
|
||||||
|
481
difrac.c
481
difrac.c
@ -1,481 +0,0 @@
|
|||||||
/*-------------------------------------------------------------------------
|
|
||||||
D I F R A C
|
|
||||||
|
|
||||||
A four-circle diffractometer requires sophicticated procedures for
|
|
||||||
searching peaks, orienting crystals and for performing data collection.
|
|
||||||
Rather then invent all of this again the DIFRAC-F77 program written by
|
|
||||||
Peter White and Eric Gabe has been incoporated into SICS. This module
|
|
||||||
provides the C-language side of the interface between DIFRAC and SICS.
|
|
||||||
DIFRAC can only be included once into SICS, it is not possible to have
|
|
||||||
more then one copy of this. This is why there is file static global data
|
|
||||||
here.
|
|
||||||
|
|
||||||
copyright: see copyright.h
|
|
||||||
|
|
||||||
Mark Koennecke, November 1999
|
|
||||||
--------------------------------------------------------------------------*/
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <assert.h>
|
|
||||||
#include <ctype.h>
|
|
||||||
#include "fortify.h"
|
|
||||||
#include "sics.h"
|
|
||||||
#include "motor.h"
|
|
||||||
#include "counter.h"
|
|
||||||
#include "status.h"
|
|
||||||
#include "splitter.h"
|
|
||||||
#include "difrac.h"
|
|
||||||
|
|
||||||
/*--------------------------------------------------------------------------
|
|
||||||
In order to deal with multiple request to the DIFRAC subsystem we need to
|
|
||||||
keep the connection objects on a stack. This stack is defined here.
|
|
||||||
---------------------------------------------------------------------------*/
|
|
||||||
#define MAXSTACK 50
|
|
||||||
|
|
||||||
static SConnection *ConStack[MAXSTACK];
|
|
||||||
static int iConStackPtr = -1;
|
|
||||||
|
|
||||||
/*--------------------------------------------------------------------------
|
|
||||||
In order to do the four circle work we need to know the motors of the
|
|
||||||
eulerian cradle and access to the counter. Furthermore we need to know
|
|
||||||
about the omega2theta motor and the scanning routine.
|
|
||||||
These data structures are initialized by the installation routine.
|
|
||||||
---------------------------------------------------------------------------*/
|
|
||||||
|
|
||||||
static pMotor pTTH, pOM, pCHI, pPHI;
|
|
||||||
static pCounter counter;
|
|
||||||
/*---------------------------------------------------------------------------
|
|
||||||
The following routines will be called from F77. Their names take care of the
|
|
||||||
system dependent name mangling scheme for calling C from F77. This may
|
|
||||||
need adjustment when porting to another system
|
|
||||||
---------------------------------------------------------------------------*/
|
|
||||||
/*========= read angles */
|
|
||||||
void sicsanget_(float *fTH, float *fOM, float *fCHI, float *fPHI)
|
|
||||||
{
|
|
||||||
int iRet;
|
|
||||||
|
|
||||||
/* this is just security, may never happen */
|
|
||||||
if (iConStackPtr < 0) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (ConStack[iConStackPtr] == NULL) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
iRet = MotorGetSoftPosition(pTTH, ConStack[iConStackPtr], fTH);
|
|
||||||
if (iRet != 1) {
|
|
||||||
SCWrite(ConStack[iConStackPtr],
|
|
||||||
"ERROR: failed to read two theta, DIFRAC may be confused now",
|
|
||||||
eError);
|
|
||||||
}
|
|
||||||
iRet = MotorGetSoftPosition(pOM, ConStack[iConStackPtr], fOM);
|
|
||||||
if (iRet != 1) {
|
|
||||||
SCWrite(ConStack[iConStackPtr],
|
|
||||||
"ERROR: failed to read omega, DIFRAC may be confused now",
|
|
||||||
eError);
|
|
||||||
}
|
|
||||||
iRet = MotorGetSoftPosition(pCHI, ConStack[iConStackPtr], fCHI);
|
|
||||||
if (iRet != 1) {
|
|
||||||
SCWrite(ConStack[iConStackPtr],
|
|
||||||
"ERROR: failed to read chi, DIFRAC may be confused now",
|
|
||||||
eError);
|
|
||||||
}
|
|
||||||
iRet = MotorGetSoftPosition(pPHI, ConStack[iConStackPtr], fPHI);
|
|
||||||
if (iRet != 1) {
|
|
||||||
SCWrite(ConStack[iConStackPtr],
|
|
||||||
"ERROR: failed to read two theta, DIFRAC may be confused now",
|
|
||||||
eError);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#define ABS(x) (x < 0 ? -(x) : (x))
|
|
||||||
/*=========== check angles */
|
|
||||||
void sicsangcheck_(float *fTH, float *fOM, float *fCHI, float *fPHI,
|
|
||||||
int *iInvalid)
|
|
||||||
{
|
|
||||||
int iRet;
|
|
||||||
SConnection *pCon = NULL;
|
|
||||||
float fHard;
|
|
||||||
char pBueffel[256], pError[131];
|
|
||||||
|
|
||||||
/* this is just security, may never happen */
|
|
||||||
if (iConStackPtr < 0) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (ConStack[iConStackPtr] == NULL) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
pCon = ConStack[iConStackPtr];
|
|
||||||
|
|
||||||
*iInvalid = 0;
|
|
||||||
iRet = MotorCheckBoundary(pTTH, *fTH, &fHard, pError, 131);
|
|
||||||
if (iRet != 1) {
|
|
||||||
sprintf(pBueffel,
|
|
||||||
"ERROR: %6.2f %6.2f %6.2f %6.2f violates twotheta limits",
|
|
||||||
*fTH, *fOM, *fCHI, *fPHI);
|
|
||||||
SCWrite(pCon, pBueffel, eError);
|
|
||||||
*iInvalid = 4;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
iRet = MotorCheckBoundary(pOM, *fOM, &fHard, pError, 131);
|
|
||||||
if (iRet != 1) {
|
|
||||||
sprintf(pBueffel,
|
|
||||||
"ERROR: %6.2f %6.2f %6.2f %6.2f violates omega limits",
|
|
||||||
*fTH, *fOM, *fCHI, *fPHI);
|
|
||||||
SCWrite(pCon, pBueffel, eError);
|
|
||||||
*iInvalid = 4;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
iRet = MotorCheckBoundary(pCHI, *fCHI, &fHard, pError, 131);
|
|
||||||
if (iRet != 1) {
|
|
||||||
sprintf(pBueffel,
|
|
||||||
"ERROR: %6.2f %6.2f %6.2f %6.2f violates chi limits",
|
|
||||||
*fTH, *fOM, *fCHI, *fPHI);
|
|
||||||
SCWrite(pCon, pBueffel, eError);
|
|
||||||
*iInvalid = 4;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
iRet = MotorCheckBoundary(pPHI, *fPHI, &fHard, pError, 131);
|
|
||||||
if (iRet != 1) {
|
|
||||||
sprintf(pBueffel,
|
|
||||||
"ERROR: %6.2f %6.2f %6.2f %6.2f violates phi limits",
|
|
||||||
*fTH, *fOM, *fCHI, *fPHI);
|
|
||||||
SCWrite(pCon, pBueffel, eError);
|
|
||||||
*iInvalid = 4;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*======== set angles */
|
|
||||||
void sicsangset_(float *fTTH, float *fOM, float *fCHI, float *fPHI,
|
|
||||||
int *icol)
|
|
||||||
{
|
|
||||||
pDummy pDum;
|
|
||||||
int iRet;
|
|
||||||
SConnection *pCon = NULL;
|
|
||||||
float fT1, fT2, fT3, fT4;
|
|
||||||
|
|
||||||
*icol = 0;
|
|
||||||
|
|
||||||
/* this is just security, may never happen */
|
|
||||||
if (iConStackPtr < 0) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (ConStack[iConStackPtr] == NULL) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
pCon = ConStack[iConStackPtr];
|
|
||||||
|
|
||||||
|
|
||||||
/* check if this is possible, if not complain */
|
|
||||||
sicsangcheck_(fTTH, fOM, fCHI, fPHI, &iRet);
|
|
||||||
if (iRet >= 4) {
|
|
||||||
*icol = 1;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* start */
|
|
||||||
pDum = (pDummy) pTTH;
|
|
||||||
iRet = StartDevice(pServ->pExecutor, "TTH",
|
|
||||||
pDum->pDescriptor, pDum, pCon, *fTTH);
|
|
||||||
if (!iRet) {
|
|
||||||
SCWrite(pCon, "ERROR: cannot start two theta motor", eError);
|
|
||||||
StopExe(pServ->pExecutor, "all");
|
|
||||||
*icol = 10;
|
|
||||||
}
|
|
||||||
pDum = (pDummy) pOM;
|
|
||||||
iRet = StartDevice(pServ->pExecutor, "OM",
|
|
||||||
pDum->pDescriptor, pDum, pCon, *fOM);
|
|
||||||
if (!iRet) {
|
|
||||||
SCWrite(pCon, "ERROR: cannot start omega motor", eError);
|
|
||||||
StopExe(pServ->pExecutor, "all");
|
|
||||||
*icol = 10;
|
|
||||||
}
|
|
||||||
pDum = (pDummy) pCHI;
|
|
||||||
iRet = StartDevice(pServ->pExecutor, "CHI",
|
|
||||||
pDum->pDescriptor, pDum, pCon, *fCHI);
|
|
||||||
if (!iRet) {
|
|
||||||
SCWrite(pCon, "ERROR: cannot start chi motor", eError);
|
|
||||||
StopExe(pServ->pExecutor, "all");
|
|
||||||
*icol = 10;
|
|
||||||
}
|
|
||||||
pDum = (pDummy) pPHI;
|
|
||||||
iRet = StartDevice(pServ->pExecutor, "PHI",
|
|
||||||
pDum->pDescriptor, pDum, pCon, *fPHI);
|
|
||||||
if (!iRet) {
|
|
||||||
SCWrite(pCon, "ERROR: cannot start two theta motor", eError);
|
|
||||||
StopExe(pServ->pExecutor, "all");
|
|
||||||
*icol = 10;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* wait for end of it */
|
|
||||||
iRet = Wait4Success(pServ->pExecutor);
|
|
||||||
switch (iRet) {
|
|
||||||
case DEVINT:
|
|
||||||
if (SCGetInterrupt(pCon) == eAbortOperation) {
|
|
||||||
SCSetInterrupt(pCon, eContinue);
|
|
||||||
SCSetError(pCon, OKOK);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case DEVDONE:
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
As TRICS has such a shitty cradle check angles and report error
|
|
||||||
if bad
|
|
||||||
*/
|
|
||||||
sicsanget_(&fT1, &fT2, &fT3, &fT4);
|
|
||||||
if (ABS(fT1 - *fTTH) > .2) {
|
|
||||||
*icol = 10;
|
|
||||||
}
|
|
||||||
if (ABS(fT2 - *fOM) > .2) {
|
|
||||||
*icol = 10;
|
|
||||||
}
|
|
||||||
if (ABS(fT3 - *fCHI) > .2) {
|
|
||||||
*icol = 10;
|
|
||||||
}
|
|
||||||
if (ABS(fT4 - *fPHI) > .2) {
|
|
||||||
*icol = 10;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*=========== count */
|
|
||||||
void sicscount_(float *fPreset, float *fCounts)
|
|
||||||
{
|
|
||||||
pDummy pDum;
|
|
||||||
int iRet;
|
|
||||||
SConnection *pCon = NULL;
|
|
||||||
long lTask;
|
|
||||||
|
|
||||||
/* this is just security, may never happen */
|
|
||||||
if (iConStackPtr < 0) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (ConStack[iConStackPtr] == NULL) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
pCon = ConStack[iConStackPtr];
|
|
||||||
|
|
||||||
pDum = (pDummy) counter;
|
|
||||||
SetCounterPreset(counter, *fPreset);
|
|
||||||
iRet = StartDevice(pServ->pExecutor,
|
|
||||||
"DifracCount",
|
|
||||||
pDum->pDescriptor, counter, pCon, *fPreset);
|
|
||||||
if (!iRet) {
|
|
||||||
SCWrite(pCon, "ERROR: Failed to start counting ", eError);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
SetStatus(eCounting);
|
|
||||||
/* wait for finish */
|
|
||||||
lTask = GetDevexecID(pServ->pExecutor);
|
|
||||||
if (lTask > 0);
|
|
||||||
{
|
|
||||||
TaskWait(pServ->pTasker, lTask);
|
|
||||||
}
|
|
||||||
*fCounts = (float) GetCounts(counter, pCon);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*========= sicswrite */
|
|
||||||
void sicswrite_(int *iText, int *iLen)
|
|
||||||
{
|
|
||||||
SConnection *pCon = NULL;
|
|
||||||
char pBueffel[256];
|
|
||||||
int i;
|
|
||||||
|
|
||||||
if (*iLen > 255)
|
|
||||||
return;
|
|
||||||
|
|
||||||
for (i = 0; i < *iLen; i++) {
|
|
||||||
pBueffel[i] = (char) iText[i];
|
|
||||||
}
|
|
||||||
pBueffel[i] = '\0';
|
|
||||||
|
|
||||||
/* this is just security, may never happen */
|
|
||||||
if (iConStackPtr < 0) {
|
|
||||||
puts(pBueffel);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (ConStack[iConStackPtr] == NULL) {
|
|
||||||
puts(pBueffel);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
pCon = ConStack[iConStackPtr];
|
|
||||||
|
|
||||||
SCWrite(pCon, pBueffel, eValue);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*========== sicsgetline */
|
|
||||||
void sicsgetline_(int *iText, int *iLen)
|
|
||||||
{
|
|
||||||
SConnection *pCon = NULL;
|
|
||||||
char pBueffel[256];
|
|
||||||
int i, iRet;
|
|
||||||
|
|
||||||
/* this is just security, may never happen */
|
|
||||||
if (iConStackPtr < 0) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (ConStack[iConStackPtr] == NULL) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
pCon = ConStack[iConStackPtr];
|
|
||||||
|
|
||||||
iRet = SCPrompt(pCon, "Enter data please >>", pBueffel, 255);
|
|
||||||
/* difrac cannot handle an interrupted input operation */
|
|
||||||
if (iRet == 0) {
|
|
||||||
SCSetInterrupt(pCon, eContinue);
|
|
||||||
}
|
|
||||||
for (i = 0; i < strlen(pBueffel); i++) {
|
|
||||||
iText[i] = (int) pBueffel[i];
|
|
||||||
}
|
|
||||||
*iLen = strlen(pBueffel);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*============= checkint */
|
|
||||||
void checkint_(int *iK)
|
|
||||||
{
|
|
||||||
SConnection *pCon = NULL;
|
|
||||||
char pBueffel[256];
|
|
||||||
int i;
|
|
||||||
|
|
||||||
/* this is just security, may never happen */
|
|
||||||
if (iConStackPtr < 0) {
|
|
||||||
*iK = 0;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (ConStack[iConStackPtr] == NULL) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
pCon = ConStack[iConStackPtr];
|
|
||||||
|
|
||||||
if (SCGetInterrupt(pCon) >= eAbortScan) {
|
|
||||||
*iK = 0;
|
|
||||||
} else {
|
|
||||||
*iK = 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*--------------------------------------------------------------------------
|
|
||||||
DifracAction is the interface routine between the SICS interpreter and
|
|
||||||
the DIFRAC subsystem. What it basically does is: pop the connection onto
|
|
||||||
the stack. Concatenate all pending command line data to a string. Then
|
|
||||||
call DIFRAC with this string as an parameter. On return, remove the
|
|
||||||
connection from the stack again and return.
|
|
||||||
-------------------------------------------------------------------------*/
|
|
||||||
/* some protoypes for things defined in F77 */
|
|
||||||
|
|
||||||
extern void difini_(void);
|
|
||||||
extern void difint_(int *iText, int *iLen);
|
|
||||||
|
|
||||||
int DifracAction(SConnection * pCon, SicsInterp * pSics, void *pData,
|
|
||||||
int argc, char *argv[])
|
|
||||||
{
|
|
||||||
char pInput[256];
|
|
||||||
int iInput[256];
|
|
||||||
int iLen, i;
|
|
||||||
|
|
||||||
|
|
||||||
if (argc < 2) {
|
|
||||||
SCWrite(pCon, "ERROR: dif expects at least one argument", eError);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* user privilege required */
|
|
||||||
if (!SCMatchRights(pCon, usUser)) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* steal: redirect the I/O to me */
|
|
||||||
strcpy(pInput, argv[1]);
|
|
||||||
strtolower(pInput);
|
|
||||||
if (strcmp(pInput, "steal") == 0) {
|
|
||||||
if (iConStackPtr >= 0) {
|
|
||||||
ConStack[iConStackPtr] = pCon;
|
|
||||||
}
|
|
||||||
SCSendOK(pCon);
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
iConStackPtr++;
|
|
||||||
ConStack[iConStackPtr] = pCon;
|
|
||||||
|
|
||||||
Arg2Text(argc - 1, &argv[1], pInput, 255);
|
|
||||||
iLen = strlen(pInput);
|
|
||||||
for (i = 0; i < iLen; i++) {
|
|
||||||
iInput[i] = toupper((int) pInput[i]);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* do difrac */
|
|
||||||
difint_(iInput, &iLen);
|
|
||||||
SCWrite(pCon, "Difrac subsystem finished", eWarning);
|
|
||||||
|
|
||||||
iConStackPtr--;
|
|
||||||
if (SCGetInterrupt(pCon) != eContinue) {
|
|
||||||
return 0;
|
|
||||||
} else {
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*-------------------- The initialization routine ----------------------*/
|
|
||||||
int MakeDifrac(SConnection * pCon, SicsInterp * pSics, void *pData,
|
|
||||||
int argc, char *argv[])
|
|
||||||
{
|
|
||||||
CommandList *pCom = NULL;
|
|
||||||
pICountable pCts = NULL;
|
|
||||||
int iRet;
|
|
||||||
|
|
||||||
if (argc < 6) {
|
|
||||||
SCWrite(pCon,
|
|
||||||
"ERROR: Insufficient number of arguments to MakeDifrac",
|
|
||||||
eError);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* find motors */
|
|
||||||
pTTH = FindMotor(pSics, argv[1]);
|
|
||||||
if (!pTTH) {
|
|
||||||
SCWrite(pCon, "ERROR: cannot find two theta motor", eError);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
pOM = FindMotor(pSics, argv[2]);
|
|
||||||
if (!pOM) {
|
|
||||||
SCWrite(pCon, "ERROR: cannot find omega motor", eError);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
pCHI = FindMotor(pSics, argv[3]);
|
|
||||||
if (!pTTH) {
|
|
||||||
SCWrite(pCon, "ERROR: cannot find chi motor", eError);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
pPHI = FindMotor(pSics, argv[4]);
|
|
||||||
if (!pTTH) {
|
|
||||||
SCWrite(pCon, "ERROR: cannot find phi motor", eError);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* locate counter */
|
|
||||||
pCom = FindCommand(pSics, argv[5]);
|
|
||||||
if (pCom == NULL) {
|
|
||||||
SCWrite(pCon, "ERROR: counter not found in MakeDifrac", eError);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
pCts = GetCountableInterface(pCom->pData);
|
|
||||||
if (!pCts) {
|
|
||||||
SCWrite(pCon, "ERROR: argument to MakeDifrac is no counter", eError);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
counter = (pCounter) pCom->pData;
|
|
||||||
|
|
||||||
/* initialize difrac */
|
|
||||||
difini_();
|
|
||||||
|
|
||||||
/* install command */
|
|
||||||
iRet = AddCommand(pSics, "dif", DifracAction, NULL, NULL);
|
|
||||||
if (!iRet) {
|
|
||||||
SCWrite(pCon, "ERROR: duplicate command dif NOT created", eError);
|
|
||||||
}
|
|
||||||
return iRet;
|
|
||||||
}
|
|
14
difrac.h
14
difrac.h
@ -1,14 +0,0 @@
|
|||||||
/*--------------------------------------------------------------------------
|
|
||||||
D I F R A C
|
|
||||||
|
|
||||||
Header file for the interface between SICS and the F77 package
|
|
||||||
DIFRAC. Only the factory routine is defined.
|
|
||||||
|
|
||||||
Mark Koennecke, November 1999
|
|
||||||
--------------------------------------------------------------------------*/
|
|
||||||
#ifndef DIFRAC
|
|
||||||
#define DIFRAC
|
|
||||||
|
|
||||||
int MakeDifrac(SConnection * pCon, SicsInterp * pSics, void *pData,
|
|
||||||
int argc, char *argv[]);
|
|
||||||
#endif
|
|
89
drive.c
89
drive.c
@ -160,7 +160,7 @@ int Start2Run(SConnection * pCon, SicsInterp * pInter, char *name,
|
|||||||
|
|
||||||
/* check if user is allowed to drive */
|
/* check if user is allowed to drive */
|
||||||
if (!SCMatchRights(pCon, usUser)) {
|
if (!SCMatchRights(pCon, usUser)) {
|
||||||
snprintf(pBueffel,511, "Insuficient Privilege to drive %s", name);
|
snprintf(pBueffel,511, "ERROR: Insuficient Privilege to drive %s", name);
|
||||||
SCWrite(pCon, pBueffel, eError);
|
SCWrite(pCon, pBueffel, eError);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -168,7 +168,7 @@ int Start2Run(SConnection * pCon, SicsInterp * pInter, char *name,
|
|||||||
/* first try to find the thing to drive */
|
/* first try to find the thing to drive */
|
||||||
pObject = FindCommand(pInter, name);
|
pObject = FindCommand(pInter, name);
|
||||||
if (!pObject) {
|
if (!pObject) {
|
||||||
snprintf(pBueffel,511, "Cannot find %s to drive ", name);
|
snprintf(pBueffel,511, "ERROR: Cannot find %s to drive ", name);
|
||||||
SCWrite(pCon, pBueffel, eError);
|
SCWrite(pCon, pBueffel, eError);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -179,7 +179,7 @@ int Start2Run(SConnection * pCon, SicsInterp * pInter, char *name,
|
|||||||
pDum = (Dummy *) pObject->pData;
|
pDum = (Dummy *) pObject->pData;
|
||||||
pDes = pDum->pDescriptor;
|
pDes = pDum->pDescriptor;
|
||||||
if (!pDes) {
|
if (!pDes) {
|
||||||
snprintf(pBueffel,511, "%s is NOT drivable!", pDes->name);
|
snprintf(pBueffel,511, "ERROR: %s is NOT drivable!", pDes->name);
|
||||||
SCWrite(pCon, pBueffel, eError);
|
SCWrite(pCon, pBueffel, eError);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -189,14 +189,14 @@ int Start2Run(SConnection * pCon, SicsInterp * pInter, char *name,
|
|||||||
*/
|
*/
|
||||||
pInt = pDes->GetInterface(pDum, DRIVEID);
|
pInt = pDes->GetInterface(pDum, DRIVEID);
|
||||||
if (!pInt) {
|
if (!pInt) {
|
||||||
snprintf(pBueffel,511, "%s is NOT drivable!", pDes->name);
|
snprintf(pBueffel,511, "ERROR: %s is NOT drivable!", pDes->name);
|
||||||
SCWrite(pCon, pBueffel, eError);
|
SCWrite(pCon, pBueffel, eError);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
if (pInt) {
|
if (pInt) {
|
||||||
iRet = pInt->CheckLimits(pDum, fNew, pBueffel, 511);
|
iRet = pInt->CheckLimits(pDum, fNew, pBueffel, 511);
|
||||||
if (!iRet) {
|
if (!iRet) {
|
||||||
SCWrite(pCon, pBueffel, eError);
|
SCPrintf(pCon, eError, "ERROR: %s", pBueffel);
|
||||||
SCSetInterrupt(pCon, eAbortOperation);
|
SCSetInterrupt(pCon, eAbortOperation);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -207,7 +207,7 @@ int Start2Run(SConnection * pCon, SicsInterp * pInter, char *name,
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
snprintf(pBueffel,511, "%s is NOT drivable", pDes->name);
|
snprintf(pBueffel,511, "ERROR: %s is NOT drivable", pDes->name);
|
||||||
SCWrite(pCon, pBueffel, eError);
|
SCWrite(pCon, pBueffel, eError);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -426,7 +426,72 @@ int RunWrapper(SConnection * pCon, SicsInterp * pSics, void *pData,
|
|||||||
}
|
}
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
/*---------------------------------------------------------------------------*/
|
||||||
|
int MoveWrapper(SConnection * pCon, SicsInterp * pSics, void *pData,
|
||||||
|
int argc, char *argv[])
|
||||||
|
{
|
||||||
|
Tcl_Interp *tcl_interp;
|
||||||
|
int iRet, i;
|
||||||
|
double dTarget;
|
||||||
|
float curPos;
|
||||||
|
char pBueffel[512];
|
||||||
|
Status eOld;
|
||||||
|
long groupID, taskID;
|
||||||
|
void *obj;
|
||||||
|
|
||||||
|
assert(pCon);
|
||||||
|
assert(pSics);
|
||||||
|
tcl_interp = InterpGetTcl(pSics);
|
||||||
|
/* check Status */
|
||||||
|
eOld = GetStatus();
|
||||||
|
|
||||||
|
|
||||||
|
/* check no of args */
|
||||||
|
if (argc < 3) {
|
||||||
|
snprintf(pBueffel,511, "Insufficient number of args. Usage %s name val",
|
||||||
|
argv[0]);
|
||||||
|
SCWrite(pCon, pBueffel, eError);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* check authorisation */
|
||||||
|
if (!SCMatchRights(pCon, usUser)) {
|
||||||
|
SCWrite(pCon,
|
||||||
|
"ERROR: You are not authorized to use the mv command",
|
||||||
|
eError);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
groupID = GetTaskGroupID(pServ->pTasker);
|
||||||
|
for (i = 1; i < argc; i += 2) {
|
||||||
|
if (argv[i + 1] == NULL) {
|
||||||
|
snprintf(pBueffel,511, "ERROR: no value found for driving %s", argv[i]);
|
||||||
|
SCWrite(pCon, pBueffel, eError);
|
||||||
|
SetStatus(eOld);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
iRet = Tcl_GetDouble(tcl_interp, argv[i + 1], &dTarget);
|
||||||
|
if (iRet == TCL_ERROR) {
|
||||||
|
SCWrite(pCon, Tcl_GetStringResult(tcl_interp), eError);
|
||||||
|
StopExe(GetExecutor(), "ALL");
|
||||||
|
SetStatus(eOld);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
obj = FindCommandData(pSics,argv[i],NULL);
|
||||||
|
if(obj == NULL || GetDrivableInterface(obj) == NULL){
|
||||||
|
SCPrintf(pCon,eError, "ERROR: %s not found, not started",argv[i]);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
GetDrivablePosition(obj,pCon,&curPos);
|
||||||
|
dTarget = curPos + dTarget;
|
||||||
|
taskID = StartDriveTask(obj, pCon, argv[i], (float)dTarget);
|
||||||
|
AddTaskToGroup(pServ->pTasker,taskID,groupID);
|
||||||
|
}
|
||||||
|
while(isTaskGroupRunning(pServ->pTasker,groupID)){
|
||||||
|
TaskYield(pServ->pTasker);
|
||||||
|
}
|
||||||
|
SCSendOK(pCon);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
/*---------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------*/
|
||||||
int MakeDrive(SConnection * pCon, SicsInterp * pSics, void *pData,
|
int MakeDrive(SConnection * pCon, SicsInterp * pSics, void *pData,
|
||||||
int argc, char *argv[])
|
int argc, char *argv[])
|
||||||
@ -457,5 +522,17 @@ int MakeDrive(SConnection * pCon, SicsInterp * pSics, void *pData,
|
|||||||
SCWrite(pCon, pBueffel, eError);
|
SCWrite(pCon, pBueffel, eError);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (argc > 3) {
|
||||||
|
iRet = AddCommand(pSics, argv[2], MoveWrapper, NULL, NULL);
|
||||||
|
} else {
|
||||||
|
iRet = AddCommand(pSics, "mv", MoveWrapper, NULL, NULL);
|
||||||
|
}
|
||||||
|
if (!iRet) {
|
||||||
|
sprintf(pBueffel, "ERROR: duplicate command mv not created");
|
||||||
|
SCWrite(pCon, pBueffel, eError);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
622
ecbcounter.c
622
ecbcounter.c
@ -1,622 +0,0 @@
|
|||||||
/*----------------------------------------------------------------------------
|
|
||||||
This is a single counter implemented on top of the Risoe ECB electronic
|
|
||||||
|
|
||||||
copyright: see file COPYRIGHT
|
|
||||||
|
|
||||||
Mark Koennecke, January-February 2003
|
|
||||||
---------------------------------------------------------------------------*/
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <assert.h>
|
|
||||||
#include <errno.h>
|
|
||||||
#include <tcl.h>
|
|
||||||
#include <math.h>
|
|
||||||
#include <unistd.h>
|
|
||||||
#include "fortify.h"
|
|
||||||
#include "sics.h"
|
|
||||||
#include "status.h"
|
|
||||||
#include "psi/ecb.h"
|
|
||||||
#include "countdriv.h"
|
|
||||||
|
|
||||||
/*------------------ our private data structure ------------------------*/
|
|
||||||
typedef struct {
|
|
||||||
pECB ecb; /* the ECB system we talk to */
|
|
||||||
unsigned char prescaler[8]; /* an array for the prescaler values */
|
|
||||||
int tfreq; /* timer frequency */
|
|
||||||
unsigned char control; /* marks the control monitor */
|
|
||||||
int state; /* current counting state */
|
|
||||||
} ECBCounter, *pECBCounter;
|
|
||||||
|
|
||||||
/*----------------- private defines ------------------------------------*/
|
|
||||||
#define STFRD 137
|
|
||||||
#define STREAD 138
|
|
||||||
#define STOPS 136
|
|
||||||
#define STCLEA 134
|
|
||||||
#define PRELOA 139
|
|
||||||
#define STLOAD 156
|
|
||||||
#define STCPRE 133
|
|
||||||
#define STARTS 135
|
|
||||||
#define SPCSTA 169
|
|
||||||
|
|
||||||
/*------------------ state codes --------------------------------------*/
|
|
||||||
#define IDLE 0
|
|
||||||
#define COUNT 2
|
|
||||||
#define NOBEAM 3
|
|
||||||
/*--------------------------------------------------------------------*/
|
|
||||||
#define MAX_COUNT 4294967295.0
|
|
||||||
/*------------------ error codes --------------------------------------*/
|
|
||||||
#define COMMERROR -300
|
|
||||||
#define TOMANYCOUNTS -301
|
|
||||||
#define NOSEND -302
|
|
||||||
#define INVALIDCOUNTER -304
|
|
||||||
#define INVALIDPRESCALER -305
|
|
||||||
#define BADFREQ -306
|
|
||||||
/*======================================================================*/
|
|
||||||
static int readScaler(pECBCounter pPriv, int scaler, int *count)
|
|
||||||
{
|
|
||||||
int status;
|
|
||||||
Z80_reg in, out;
|
|
||||||
Ecb_pack data;
|
|
||||||
|
|
||||||
in.c = (unsigned char) scaler;
|
|
||||||
status = ecbExecute(pPriv->ecb, STREAD, in, &out);
|
|
||||||
if (status != 1) {
|
|
||||||
return COMMERROR;
|
|
||||||
}
|
|
||||||
|
|
||||||
data.b.byt3 = out.c;
|
|
||||||
data.b.byt2 = out.b;
|
|
||||||
data.b.byt1 = out.d;
|
|
||||||
data.b.byt0 = out.e;
|
|
||||||
if (scaler == 0) {
|
|
||||||
*count = data.result / pPriv->tfreq;
|
|
||||||
} else {
|
|
||||||
*count = data.result;
|
|
||||||
}
|
|
||||||
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*---------------------------------------------------------------------*/
|
|
||||||
static int check4Beam(struct __COUNTER *pCter, int *beam)
|
|
||||||
{
|
|
||||||
Z80_reg in, out;
|
|
||||||
pECBCounter self = NULL;
|
|
||||||
int status;
|
|
||||||
|
|
||||||
self = (pECBCounter) pCter->pData;
|
|
||||||
assert(self);
|
|
||||||
|
|
||||||
in.c = 1;
|
|
||||||
status = ecbExecute(self->ecb, SPCSTA, in, &out);
|
|
||||||
if (status != 1) {
|
|
||||||
pCter->iErrorCode = COMMERROR;
|
|
||||||
return HWFault;
|
|
||||||
}
|
|
||||||
*beam = (int) out.d;
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*----------------------------------------------------------------------*/
|
|
||||||
static int stopScalers(pECBCounter self)
|
|
||||||
{
|
|
||||||
int status;
|
|
||||||
Z80_reg in, out;
|
|
||||||
|
|
||||||
status = ecbExecute(self->ecb, STOPS, in, &out);
|
|
||||||
if (status != 1) {
|
|
||||||
return COMMERROR;
|
|
||||||
}
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*========================================================================
|
|
||||||
These two functions currently rely on the idea that the ECB stops
|
|
||||||
and starts without clearing counters in between. The sequence of
|
|
||||||
things necessary to start it, suggests this. If this is not the case then
|
|
||||||
this will not work.
|
|
||||||
===========================================================================*/
|
|
||||||
static int ECBPause(struct __COUNTER *self)
|
|
||||||
{
|
|
||||||
int status;
|
|
||||||
pECBCounter pPriv = NULL;
|
|
||||||
|
|
||||||
assert(self);
|
|
||||||
pPriv = (pECBCounter) self->pData;
|
|
||||||
assert(pPriv);
|
|
||||||
|
|
||||||
if ((status = stopScalers(pPriv)) <= 0) {
|
|
||||||
self->iErrorCode = status;
|
|
||||||
return HWFault;
|
|
||||||
}
|
|
||||||
return OKOK;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*=======================================================================*/
|
|
||||||
static int ECBContinue(struct __COUNTER *self)
|
|
||||||
{
|
|
||||||
int status;
|
|
||||||
pECBCounter pPriv = NULL;
|
|
||||||
Z80_reg in, out;
|
|
||||||
|
|
||||||
assert(self);
|
|
||||||
pPriv = (pECBCounter) self->pData;
|
|
||||||
assert(pPriv);
|
|
||||||
|
|
||||||
status = ecbExecute(pPriv->ecb, STARTS, in, &out);
|
|
||||||
if (status != 1) {
|
|
||||||
self->iErrorCode = status;
|
|
||||||
return HWFault;
|
|
||||||
}
|
|
||||||
|
|
||||||
return OKOK;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*-----------------------------------------------------------------------*/
|
|
||||||
static int ECBGetStatus(struct __COUNTER *self, float *fControl)
|
|
||||||
{
|
|
||||||
pECBCounter pPriv = (pECBCounter) self->pData;
|
|
||||||
int status, result, scaler;
|
|
||||||
Z80_reg in, out;
|
|
||||||
int count, beam;
|
|
||||||
|
|
||||||
assert(pPriv);
|
|
||||||
|
|
||||||
/*
|
|
||||||
This can happen after a stop
|
|
||||||
*/
|
|
||||||
if (pPriv->state == IDLE) {
|
|
||||||
ECBTransfer(self);
|
|
||||||
return HWIdle;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
read status bit
|
|
||||||
*/
|
|
||||||
status = ecbExecute(pPriv->ecb, STFRD, in, &out);
|
|
||||||
if (status != 1) {
|
|
||||||
self->iErrorCode = COMMERROR;
|
|
||||||
pPriv->state = IDLE;
|
|
||||||
return HWFault;
|
|
||||||
}
|
|
||||||
/*
|
|
||||||
read beam status
|
|
||||||
*/
|
|
||||||
status = check4Beam(self, &beam);
|
|
||||||
if (status != 1) {
|
|
||||||
self->iErrorCode = COMMERROR;
|
|
||||||
return HWFault;
|
|
||||||
}
|
|
||||||
beam &= 1;
|
|
||||||
|
|
||||||
/*
|
|
||||||
sophisticated logic in order to keep track of the various states
|
|
||||||
the thing can be in. Complicated by the fact that the status becomes
|
|
||||||
idle (out.d = 0) when the measurement is paused due to the lack of
|
|
||||||
beam.
|
|
||||||
*/
|
|
||||||
if (pPriv->state == COUNT && beam == 1) {
|
|
||||||
ECBPause(self);
|
|
||||||
pPriv->state = NOBEAM;
|
|
||||||
SetStatus(eOutOfBeam);
|
|
||||||
result = HWNoBeam;
|
|
||||||
}
|
|
||||||
if (pPriv->state == NOBEAM && beam == 0) {
|
|
||||||
ECBContinue(self);
|
|
||||||
pPriv->state = COUNT;
|
|
||||||
SetStatus(eCounting);
|
|
||||||
return HWBusy;
|
|
||||||
}
|
|
||||||
if (pPriv->state == NOBEAM && beam == 1) {
|
|
||||||
return HWNoBeam;
|
|
||||||
}
|
|
||||||
if (out.d == 0 && pPriv->state == COUNT) {
|
|
||||||
result = HWIdle;
|
|
||||||
ECBTransfer(self);
|
|
||||||
pPriv->state = IDLE;
|
|
||||||
} else {
|
|
||||||
result = HWBusy;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
select which scaler to read
|
|
||||||
*/
|
|
||||||
if (self->eMode == eTimer) {
|
|
||||||
scaler = 0;
|
|
||||||
} else {
|
|
||||||
scaler = pPriv->control;
|
|
||||||
}
|
|
||||||
|
|
||||||
readScaler(pPriv, scaler, &count);
|
|
||||||
/*
|
|
||||||
ignore errors on this one
|
|
||||||
*/
|
|
||||||
*fControl = (float) count;
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}exit
|
|
||||||
|
|
||||||
|
|
||||||
/*=====================================================================*/
|
|
||||||
static int clearScalers(pECBCounter self)
|
|
||||||
{
|
|
||||||
int status;
|
|
||||||
Z80_reg in, out;
|
|
||||||
|
|
||||||
status = ecbExecute(self->ecb, STCLEA, in, &out);
|
|
||||||
if (status != 1) {
|
|
||||||
return COMMERROR;
|
|
||||||
}
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*----------------------------------------------------------------------*/
|
|
||||||
static int loadPrescalers(pECBCounter self)
|
|
||||||
{
|
|
||||||
Z80_reg in, out;
|
|
||||||
int status, i;
|
|
||||||
|
|
||||||
for (i = 0; i < 8; i++) {
|
|
||||||
in.c = (unsigned char) i;
|
|
||||||
in.d = self->prescaler[i];
|
|
||||||
status = ecbExecute(self->ecb, PRELOA, in, &out);
|
|
||||||
if (status != 1) {
|
|
||||||
return COMMERROR;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*----------------------------------------------------------------------*/
|
|
||||||
static int loadPreset(pECBCounter self, int preset, unsigned char control)
|
|
||||||
{
|
|
||||||
Z80_reg in, out;
|
|
||||||
Ecb_pack data;
|
|
||||||
int status, i;
|
|
||||||
|
|
||||||
data.result = preset;
|
|
||||||
|
|
||||||
in.c = data.b.byt3;
|
|
||||||
in.b = data.b.byt2;
|
|
||||||
in.e = data.b.byt1;
|
|
||||||
in.d = data.b.byt0;
|
|
||||||
status = ecbExecute(self->ecb, STLOAD, in, &out);
|
|
||||||
if (status != 1) {
|
|
||||||
return COMMERROR;
|
|
||||||
}
|
|
||||||
|
|
||||||
in.b = data.b.byt2;
|
|
||||||
in.e = data.b.byt1;
|
|
||||||
in.d = data.b.byt0;
|
|
||||||
in.c = 4 * control;
|
|
||||||
status = ecbExecute(self->ecb, STCPRE, in, &out);
|
|
||||||
if (status != 1) {
|
|
||||||
return COMMERROR;
|
|
||||||
}
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*-----------------------------------------------------------------------*/
|
|
||||||
static int ECBStart(struct __COUNTER *self)
|
|
||||||
{
|
|
||||||
pECBCounter pPriv = NULL;
|
|
||||||
int preset, status, controlUnit;
|
|
||||||
Z80_reg in, out;
|
|
||||||
|
|
||||||
assert(self);
|
|
||||||
pPriv = (pECBCounter) self->pData;
|
|
||||||
assert(pPriv);
|
|
||||||
|
|
||||||
/*
|
|
||||||
check if the preset is permissible
|
|
||||||
*/
|
|
||||||
preset = (int) rint(self->fPreset);
|
|
||||||
if (preset > MAX_COUNT) {
|
|
||||||
self->iErrorCode = TOMANYCOUNTS;
|
|
||||||
return HWFault;
|
|
||||||
}
|
|
||||||
if (self->eMode == eTimer) {
|
|
||||||
controlUnit = 0;
|
|
||||||
preset *= pPriv->tfreq;
|
|
||||||
if (preset > MAX_COUNT) {
|
|
||||||
self->iErrorCode = TOMANYCOUNTS;
|
|
||||||
return HWFault;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
controlUnit = pPriv->control;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((status = stopScalers(pPriv)) <= 0) {
|
|
||||||
self->iErrorCode = status;
|
|
||||||
return HWFault;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((status = clearScalers(pPriv)) <= 0) {
|
|
||||||
self->iErrorCode = status;
|
|
||||||
return HWFault;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((status = loadPrescalers(pPriv)) <= 0) {
|
|
||||||
self->iErrorCode = status;
|
|
||||||
return HWFault;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((status =
|
|
||||||
loadPreset(pPriv, preset, (unsigned char) controlUnit)) <= 0) {
|
|
||||||
self->iErrorCode = status;
|
|
||||||
return HWFault;
|
|
||||||
}
|
|
||||||
|
|
||||||
status = ecbExecute(pPriv->ecb, STARTS, in, &out);
|
|
||||||
if (status != 1) {
|
|
||||||
self->iErrorCode = status;
|
|
||||||
return HWFault;
|
|
||||||
}
|
|
||||||
|
|
||||||
pPriv->state = COUNT;
|
|
||||||
return OKOK;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*=======================================================================*/
|
|
||||||
static int ECBHalt(struct __COUNTER *self)
|
|
||||||
{
|
|
||||||
int status;
|
|
||||||
pECBCounter pPriv = NULL;
|
|
||||||
|
|
||||||
assert(self);
|
|
||||||
pPriv = (pECBCounter) self->pData;
|
|
||||||
assert(pPriv);
|
|
||||||
|
|
||||||
pPriv->state = IDLE;
|
|
||||||
if ((status = stopScalers(pPriv)) <= 0) {
|
|
||||||
self->iErrorCode = status;
|
|
||||||
return HWFault;
|
|
||||||
}
|
|
||||||
return OKOK;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*=======================================================================*/
|
|
||||||
static int ECBTransfer(struct __COUNTER *self)
|
|
||||||
{
|
|
||||||
int status, count, i;
|
|
||||||
pECBCounter pPriv = NULL;
|
|
||||||
|
|
||||||
assert(self);
|
|
||||||
pPriv = (pECBCounter) self->pData;
|
|
||||||
assert(pPriv);
|
|
||||||
|
|
||||||
/*
|
|
||||||
read time
|
|
||||||
*/
|
|
||||||
status = readScaler(pPriv, 0, &count);
|
|
||||||
if (status <= 0) {
|
|
||||||
self->iErrorCode = COMMERROR;
|
|
||||||
return HWFault;
|
|
||||||
}
|
|
||||||
self->fTime = (float) count;
|
|
||||||
|
|
||||||
/*
|
|
||||||
read other scalers
|
|
||||||
*/
|
|
||||||
for (i = 1; i < 8; i++) {
|
|
||||||
status = readScaler(pPriv, i, &count);
|
|
||||||
if (status <= 0) {
|
|
||||||
self->iErrorCode = COMMERROR;
|
|
||||||
return HWFault;
|
|
||||||
}
|
|
||||||
self->lCounts[i - 1] = count;
|
|
||||||
}
|
|
||||||
return OKOK;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*======================================================================*/
|
|
||||||
static int ECBGetError(struct __COUNTER *self, int *iCode,
|
|
||||||
char *errorText, int errlen)
|
|
||||||
{
|
|
||||||
char pBueffel[132];
|
|
||||||
|
|
||||||
*iCode = self->iErrorCode;
|
|
||||||
switch (self->iErrorCode) {
|
|
||||||
case COMMERROR:
|
|
||||||
strlcpy(errorText, "Communication error with ECB", errlen);
|
|
||||||
break;
|
|
||||||
case TOMANYCOUNTS:
|
|
||||||
strlcpy(errorText, "Preset is to high!", errlen);
|
|
||||||
break;
|
|
||||||
case NOSEND:
|
|
||||||
strlcpy(errorText, "Cannot send naked data to ECB", errlen);
|
|
||||||
break;
|
|
||||||
case UNKNOWNPAR:
|
|
||||||
strlcpy(errorText, "parameter unknown", errlen);
|
|
||||||
break;
|
|
||||||
case INVALIDCOUNTER:
|
|
||||||
strlcpy(errorText, "Invalid counter number requested, 0-7 allowed",
|
|
||||||
errlen);
|
|
||||||
break;
|
|
||||||
case INVALIDPRESCALER:
|
|
||||||
strlcpy(errorText, "Invalid prescaler value, allowed 1 or 10", errlen);
|
|
||||||
break;
|
|
||||||
case BADFREQ:
|
|
||||||
strlcpy(errorText, "Bad timer frequency: 10 or 1000 allowed", errlen);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
sprintf(pBueffel, "Unknown error code %d", self->iErrorCode);
|
|
||||||
strlcpy(errorText, pBueffel, errlen);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*=======================================================================*/
|
|
||||||
static int ECBFixIt(struct __COUNTER *self, int iCode)
|
|
||||||
{
|
|
||||||
return COTERM;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*======================================================================*/
|
|
||||||
|
|
||||||
/*******************************************************************************
|
|
||||||
* Load the parameters 'dot' and 'divide' for a motor or an encoder.
|
|
||||||
* 'dot' specifies the placement of a punctuation mark on the display
|
|
||||||
* of f.ex a motor position. 'divide' specifies how many times the po-
|
|
||||||
* sition is to be divided by two before it is displayed.
|
|
||||||
******************************************************************************/
|
|
||||||
static void Dot_divide(int device, int data, pECB ecb)
|
|
||||||
{
|
|
||||||
int function, dot, divide;
|
|
||||||
Z80_reg x_inreg, out;
|
|
||||||
|
|
||||||
if (data == 0) /* If zero, dont send dot/divide) */
|
|
||||||
return;
|
|
||||||
|
|
||||||
dot = 0;
|
|
||||||
while ((data % 10) == 0) {
|
|
||||||
dot++;
|
|
||||||
data /= 10;
|
|
||||||
}
|
|
||||||
divide = 0;
|
|
||||||
while ((data % 2) == 0) {
|
|
||||||
divide++;
|
|
||||||
data /= 2;
|
|
||||||
}
|
|
||||||
if (data != 1) /* If != 1, not a binary No. */
|
|
||||||
return;
|
|
||||||
if (dot > 0)
|
|
||||||
dot = 8 - dot;
|
|
||||||
x_inreg.c = 0; /* Specify input */
|
|
||||||
x_inreg.b = (unsigned char) device;
|
|
||||||
x_inreg.d = (unsigned char) dot; /* Dot position */
|
|
||||||
x_inreg.e = (unsigned char) divide; /* No. of times to divide by 2 */
|
|
||||||
|
|
||||||
ecbExecute(ecb, 170, x_inreg, &out);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*-----------------------------------------------------------------------*/
|
|
||||||
static int ECBSet(struct __COUNTER *self, char *name,
|
|
||||||
int iCter, float fVal)
|
|
||||||
{
|
|
||||||
pECBCounter pPriv = NULL;
|
|
||||||
int iVal;
|
|
||||||
|
|
||||||
assert(self);
|
|
||||||
pPriv = (pECBCounter) self->pData;
|
|
||||||
assert(pPriv);
|
|
||||||
|
|
||||||
iVal = (int) rint(fVal);
|
|
||||||
|
|
||||||
if (strcmp(name, "prescaler") == 0) {
|
|
||||||
if (iCter < 0 || iCter > 7) {
|
|
||||||
self->iErrorCode = INVALIDCOUNTER;
|
|
||||||
return HWFault;
|
|
||||||
}
|
|
||||||
if (iVal != 1 && iVal != 10) {
|
|
||||||
self->iErrorCode = INVALIDPRESCALER;
|
|
||||||
return HWFault;
|
|
||||||
}
|
|
||||||
pPriv->prescaler[iCter] = (unsigned char) iVal;
|
|
||||||
return OKOK;
|
|
||||||
} else if (strcmp(name, "tfreq") == 0) {
|
|
||||||
if (fVal == 1000) {
|
|
||||||
pPriv->prescaler[0] = 1;
|
|
||||||
pPriv->tfreq = 1000;
|
|
||||||
Dot_divide(64, 1000, pPriv->ecb);
|
|
||||||
return OKOK;
|
|
||||||
} else if (fVal == 10) {
|
|
||||||
pPriv->tfreq = 10;
|
|
||||||
pPriv->prescaler[0] = 10;
|
|
||||||
Dot_divide(64, 10, pPriv->ecb);
|
|
||||||
return OKOK;
|
|
||||||
} else {
|
|
||||||
self->iErrorCode = BADFREQ;
|
|
||||||
return HWFault;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
self->iErrorCode = UNKNOWNPAR;
|
|
||||||
return HWFault;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*===================================================================*/
|
|
||||||
static int ECBGet(struct __COUNTER *self, char *name,
|
|
||||||
int iCter, float *fVal)
|
|
||||||
{
|
|
||||||
pECBCounter pPriv = NULL;
|
|
||||||
|
|
||||||
assert(self);
|
|
||||||
pPriv = (pECBCounter) self->pData;
|
|
||||||
assert(pPriv);
|
|
||||||
|
|
||||||
if (strcmp(name, "prescaler") == 0) {
|
|
||||||
*fVal = (float) pPriv->prescaler[iCter];
|
|
||||||
return OKOK;
|
|
||||||
} else if (strcmp(name, "tfreq") == 0) {
|
|
||||||
*fVal = (float) pPriv->tfreq;
|
|
||||||
return OKOK;
|
|
||||||
} else {
|
|
||||||
self->iErrorCode = UNKNOWNPAR;
|
|
||||||
return HWFault;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*=====================================================================*/
|
|
||||||
static int ECBSend(struct __COUNTER *self, char *text,
|
|
||||||
char *reply, int replylen)
|
|
||||||
{
|
|
||||||
strlcpy(reply, "ECB does not feast on ASCII strings, refused!",
|
|
||||||
replylen);
|
|
||||||
return OKOK;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*====================================================================*/
|
|
||||||
pCounterDriver MakeECBCounter(char *ecb)
|
|
||||||
{
|
|
||||||
pECBCounter pPriv = NULL;
|
|
||||||
pCounterDriver self = NULL;
|
|
||||||
int i;
|
|
||||||
|
|
||||||
/*
|
|
||||||
memory for everybody
|
|
||||||
*/
|
|
||||||
self = CreateCounterDriver("ecb", "ecb");
|
|
||||||
pPriv = (pECBCounter) malloc(sizeof(ECBCounter));
|
|
||||||
if (self == NULL || pPriv == NULL) {
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
memset(pPriv, 0, sizeof(ECBCounter));
|
|
||||||
|
|
||||||
/*
|
|
||||||
initialize private data structure
|
|
||||||
*/
|
|
||||||
pPriv->ecb = (pECB) FindCommandData(pServ->pSics, ecb, "ECB");
|
|
||||||
if (pPriv->ecb == NULL) {
|
|
||||||
DeleteCounterDriver(self);
|
|
||||||
free(pPriv);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
for (i = 0; i < 8; i++) {
|
|
||||||
pPriv->prescaler[i] = 1;
|
|
||||||
}
|
|
||||||
pPriv->tfreq = 1000;
|
|
||||||
pPriv->control = 1;
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
assign function pointers
|
|
||||||
*/
|
|
||||||
self->GetStatus = ECBGetStatus;
|
|
||||||
self->Start = ECBStart;
|
|
||||||
self->Pause = ECBPause;
|
|
||||||
self->Continue = ECBContinue;
|
|
||||||
self->Halt = ECBHalt;
|
|
||||||
self->ReadValues = ECBTransfer;
|
|
||||||
self->GetError = ECBGetError;
|
|
||||||
self->TryAndFixIt = ECBFixIt;
|
|
||||||
self->Set = ECBSet;
|
|
||||||
self->Get = ECBGet;
|
|
||||||
self->Send = ECBSend;
|
|
||||||
self->KillPrivate = NULL;
|
|
||||||
|
|
||||||
self->pData = pPriv;
|
|
||||||
return self;
|
|
||||||
}
|
|
17
ecbcounter.h
17
ecbcounter.h
@ -1,17 +0,0 @@
|
|||||||
/*-------------------------------------------------------------------------
|
|
||||||
Header file for the counter driver for the Risoe ECB system.
|
|
||||||
|
|
||||||
copyright: see file COPYRIGHT
|
|
||||||
|
|
||||||
Mark Koennecke, January 2003
|
|
||||||
-------------------------------------------------------------------------*/
|
|
||||||
|
|
||||||
#ifndef ECBCOUNTER
|
|
||||||
#define ECBCOUNTER
|
|
||||||
|
|
||||||
#include "countdriv.h"
|
|
||||||
|
|
||||||
pCounterDriver MakeECBCounter(char *ecb);
|
|
||||||
void KillECBCounter(CounterDriver * pDriv);
|
|
||||||
|
|
||||||
#endif
|
|
313
epicsmotor.c
Normal file
313
epicsmotor.c
Normal file
@ -0,0 +1,313 @@
|
|||||||
|
/**
|
||||||
|
* This is a very basic first generation SICS EPICS motor driver for testing.
|
||||||
|
* It should be replaced by a second generation version when SINQ gets serious
|
||||||
|
* about EPICS and SICS.
|
||||||
|
*
|
||||||
|
* Mark Koennecke, February 2012
|
||||||
|
*/
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <sics.h>
|
||||||
|
#include <modriv.h>
|
||||||
|
|
||||||
|
/* EPICS stuff */
|
||||||
|
#include <tsDefs.h>
|
||||||
|
#include <cadef.h>
|
||||||
|
#include <ezca.h>
|
||||||
|
#include <alarmString.h>
|
||||||
|
#include <menuAlarmStat.h>
|
||||||
|
#include <db_access.h>
|
||||||
|
#include <epicsThread.h>
|
||||||
|
|
||||||
|
typedef struct __epicsMoDriv{
|
||||||
|
/* general motor driver interface
|
||||||
|
fields. REQUIRED!
|
||||||
|
*/
|
||||||
|
float fUpper; /* upper limit */
|
||||||
|
float fLower; /* lower limit */
|
||||||
|
char *name;
|
||||||
|
int (*GetPosition)(void *self, float *fPos);
|
||||||
|
int (*RunTo)(void *self,float fNewVal);
|
||||||
|
int (*GetStatus)(void *self);
|
||||||
|
void (*GetError)(void *self, int *iCode, char *buffer, int iBufLen);
|
||||||
|
int (*TryAndFixIt)(void *self, int iError,float fNew);
|
||||||
|
int (*Halt)(void *self);
|
||||||
|
int (*GetDriverPar)(void *self, char *name,
|
||||||
|
float *value);
|
||||||
|
int (*SetDriverPar)(void *self,SConnection *pCon,
|
||||||
|
char *name, float newValue);
|
||||||
|
void (*ListDriverPar)(void *self, char *motorName,
|
||||||
|
SConnection *pCon);
|
||||||
|
void (*KillPrivate)(void *self);
|
||||||
|
/* your drivers private fields follow below */
|
||||||
|
char *motBaseName;
|
||||||
|
char *ezcaError;
|
||||||
|
int ezcaCode;
|
||||||
|
int connectCount;
|
||||||
|
} epicsMotorDriver;
|
||||||
|
|
||||||
|
/*================================================================
|
||||||
|
GetPos returns OKOK on success, HWFault on failure
|
||||||
|
------------------------------------------------------------------*/
|
||||||
|
static int epicsGetPos(void *data, float *fPos){
|
||||||
|
epicsMotorDriver *self = NULL;
|
||||||
|
char fullName[132];
|
||||||
|
int status;
|
||||||
|
double position;
|
||||||
|
|
||||||
|
self = (epicsMotorDriver *)data;
|
||||||
|
snprintf(fullName,sizeof(fullName),"%s.DRBV",self->motBaseName);
|
||||||
|
status = ezcaGet(fullName,ezcaDouble,1, &position);
|
||||||
|
if(status == EZCA_OK){
|
||||||
|
*fPos =(float) position;
|
||||||
|
self->connectCount = 0;
|
||||||
|
return OKOK;
|
||||||
|
} else {
|
||||||
|
ezcaGetErrorString("ERROR: EPICS: ", &self->ezcaError);
|
||||||
|
self->ezcaCode = status;
|
||||||
|
return HWFault;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/*-------------- dummy callback for runto -------------------------*/
|
||||||
|
static void RunToDummy(struct event_handler_args d)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
/*----------------------------------------------------------------
|
||||||
|
RunTo starts the motor running. Returns OKOK on success, HWfault
|
||||||
|
on Errors
|
||||||
|
------------------------------------------------------------------*/
|
||||||
|
static int epicsRunTo(void *data, float newValue){
|
||||||
|
epicsMotorDriver *self = NULL;
|
||||||
|
char fullName[132];
|
||||||
|
double position = newValue;
|
||||||
|
int status;
|
||||||
|
chid *cid;
|
||||||
|
|
||||||
|
self = (epicsMotorDriver *)data;
|
||||||
|
snprintf(fullName,sizeof(fullName),"%s.DVAL",self->motBaseName);
|
||||||
|
ezcaPvToChid(fullName,&cid);
|
||||||
|
status = ca_put_callback(DBR_DOUBLE,*cid,&position, RunToDummy,NULL);
|
||||||
|
if(status != ECA_NORMAL){
|
||||||
|
snprintf(fullName, sizeof(fullName),"Bad CA status %d", status);
|
||||||
|
self->ezcaError = strdup(fullName);
|
||||||
|
self->ezcaCode = status;
|
||||||
|
return HWFault;
|
||||||
|
} else {
|
||||||
|
ca_pend_event(.05);
|
||||||
|
self->connectCount = 0;
|
||||||
|
return OKOK;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
/*------------------------------------------------------------------
|
||||||
|
CheckStatus queries the sattus of a running motor. Possible return
|
||||||
|
values can be:
|
||||||
|
HWBusy : motor still running
|
||||||
|
HWFault : motor error detected
|
||||||
|
HWPosFault : motor finished, but position not reached
|
||||||
|
HWIdle : motor finished OK
|
||||||
|
HWWarn : motor issued warning
|
||||||
|
--------------------------------------------------------------------*/
|
||||||
|
static int epicsCheckStatus(void *data){
|
||||||
|
epicsMotorDriver *self = NULL;
|
||||||
|
char fullName[132];
|
||||||
|
short smov, stat;
|
||||||
|
int status;
|
||||||
|
|
||||||
|
self = (epicsMotorDriver *)data;
|
||||||
|
snprintf(fullName,sizeof(fullName),"%s.DMOV",self->motBaseName);
|
||||||
|
status = ezcaGet(fullName,ezcaShort,1, &smov);
|
||||||
|
if(status == EZCA_OK){
|
||||||
|
self->connectCount = 0;
|
||||||
|
if(smov == 0){
|
||||||
|
return HWBusy;
|
||||||
|
} else {
|
||||||
|
snprintf(fullName,sizeof(fullName),"%s.STAT",self->motBaseName);
|
||||||
|
status = ezcaGet(fullName,ezcaShort,1, &stat);
|
||||||
|
if(stat != menuAlarmStatNO_ALARM){
|
||||||
|
snprintf(fullName,sizeof(fullName),"EPICS ALARM: %s", epicsAlarmConditionStrings[stat]);
|
||||||
|
self->ezcaError = strdup(fullName);
|
||||||
|
return HWFault;
|
||||||
|
} else {
|
||||||
|
return HWIdle;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
ezcaGetErrorString("ERROR: EPICS: ", &self->ezcaError);
|
||||||
|
self->ezcaCode = status;
|
||||||
|
return HWFault;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/*------------------------------------------------------------------
|
||||||
|
GetError gets more information about error which occurred
|
||||||
|
*iCode is an integer error code to be used in TryFixIt as indicator
|
||||||
|
buffer is a buffer for a text description of the problem
|
||||||
|
iBufLen is the length of buffer
|
||||||
|
--------------------------------------------------------------------*/
|
||||||
|
static void epicsGetError(void *data, int *iCode, char *buffer,
|
||||||
|
int iBufLen){
|
||||||
|
epicsMotorDriver *self = NULL;
|
||||||
|
|
||||||
|
self = (epicsMotorDriver *)data;
|
||||||
|
if(self->ezcaError != NULL){
|
||||||
|
strncpy(buffer,self->ezcaError,iBufLen);
|
||||||
|
ezcaFree(self->ezcaError);
|
||||||
|
self->ezcaError = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/*------------------------------------------------------------------
|
||||||
|
TryAndFixIt tries everything which is possible in software to fix
|
||||||
|
a problem. iError is the error code from GetError, newValue is
|
||||||
|
the target value for the motor
|
||||||
|
Possible retrun values are:
|
||||||
|
MOTOK : everything fixed
|
||||||
|
MOTREDO : try again
|
||||||
|
MOTFAIL : cannot fix this
|
||||||
|
--------------------------------------------------------------------*/
|
||||||
|
static int epicsFixIt(void *data, int iError, float newValue){
|
||||||
|
epicsMotorDriver *self = NULL;
|
||||||
|
|
||||||
|
self = (epicsMotorDriver *)data;
|
||||||
|
if(self->ezcaCode == EZCA_NOTCONNECTED && self->connectCount < 2) {
|
||||||
|
self->connectCount++;
|
||||||
|
return MOTREDO;
|
||||||
|
}
|
||||||
|
return MOTFAIL;
|
||||||
|
}
|
||||||
|
/*-------------------------------------------------------------------
|
||||||
|
Halt tries to stop the motor. Halt errors are ignored.
|
||||||
|
|
||||||
|
For some as yet unknown reasons, I cannot send the stop on the
|
||||||
|
same CA line then the rest. But with a new thread which just sends
|
||||||
|
the stop, it works. This is a straightforward use of a thread:
|
||||||
|
do your thing and terminate. Do not interact with other parts
|
||||||
|
of the program.
|
||||||
|
---------------------------------------------------------------------*/
|
||||||
|
static void HaltThreadFunc(void *param)
|
||||||
|
{
|
||||||
|
char *pvName = (char *)param;
|
||||||
|
short stop = 1;
|
||||||
|
chid cid;
|
||||||
|
|
||||||
|
ca_context_create(ca_disable_preemptive_callback);
|
||||||
|
ca_create_channel(pvName,NULL,NULL,10,&cid);
|
||||||
|
ca_pend_io(5.);
|
||||||
|
ca_put(DBR_SHORT,cid,&stop);
|
||||||
|
ca_pend_io(5.0);
|
||||||
|
free(pvName);
|
||||||
|
printf("HaltThread ends\n");
|
||||||
|
|
||||||
|
}
|
||||||
|
/*-------------------------------------------------------------------*/
|
||||||
|
static int epicsHalt(void *data){
|
||||||
|
epicsMotorDriver *self = NULL;
|
||||||
|
char fullName[132];
|
||||||
|
short stop =1;
|
||||||
|
chid *cid;
|
||||||
|
int status;
|
||||||
|
|
||||||
|
self = (epicsMotorDriver *)data;
|
||||||
|
snprintf(fullName,sizeof(fullName),"%s.STOP",self->motBaseName);
|
||||||
|
/* ezcaStartGroup(); */
|
||||||
|
/* ezcaPut(fullName,ezcaShort,1,&stop); */
|
||||||
|
/* ezcaEndGroup(); */
|
||||||
|
/* ezcaPvToChid(fullName,&cid); */
|
||||||
|
/* status = ca_put_callback(DBR_SHORT,*cid,&stop, RunToDummy,NULL); */
|
||||||
|
/* printf("Halt status %d\n", status); */
|
||||||
|
/* ca_flush_io(); */
|
||||||
|
/* printf("Halt after poll\n"); */
|
||||||
|
epicsThreadCreate("Hugo",
|
||||||
|
epicsThreadPriorityHigh,
|
||||||
|
epicsThreadStackMedium,
|
||||||
|
HaltThreadFunc,
|
||||||
|
(void *)strdup(fullName));
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
/*--------------------------------------------------------------------
|
||||||
|
GetDriverPar retrieves the value of a driver parameter.
|
||||||
|
Name is the name of the parameter, fValue the value when found.
|
||||||
|
Returns 0 on success, 0 else
|
||||||
|
-----------------------------------------------------------------------*/
|
||||||
|
static int epicsGetDriverPar(void *data, char *name, float *value){
|
||||||
|
epicsMotorDriver *self = NULL;
|
||||||
|
|
||||||
|
self = (epicsMotorDriver *)data;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
/*----------------------------------------------------------------------
|
||||||
|
SetDriverPar sets a driver parameter. Returns 0 on failure, 1 on
|
||||||
|
success. Name is the parameter name, pCon the connection to report
|
||||||
|
errors too, value the new value
|
||||||
|
------------------------------------------------------------------------*/
|
||||||
|
static int epicsSetDriverPar(void *data, SConnection *pCon,
|
||||||
|
char *name, float value){
|
||||||
|
epicsMotorDriver *self = NULL;
|
||||||
|
|
||||||
|
self = (epicsMotorDriver *)data;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
/*-----------------------------------------------------------------------
|
||||||
|
ListDriverPar lists the names and values of driver parameters to
|
||||||
|
pCon. Motorname is the name of the motor ro prefix to the listing.
|
||||||
|
-------------------------------------------------------------------------*/
|
||||||
|
static void epicsListDriverPar(void *data, char *motorname,
|
||||||
|
SConnection *pCon){
|
||||||
|
epicsMotorDriver *self = NULL;
|
||||||
|
|
||||||
|
self = (epicsMotorDriver *)data;
|
||||||
|
}
|
||||||
|
/*-----------------------------------------------------------------------
|
||||||
|
KillPrivate has the task to delete possibly dynamically allocated
|
||||||
|
memory in the private part of the driver structure
|
||||||
|
------------------------------------------------------------------------*/
|
||||||
|
static void epicsKillPrivate(void *data){
|
||||||
|
epicsMotorDriver *self = NULL;
|
||||||
|
|
||||||
|
self = (epicsMotorDriver *)data;
|
||||||
|
if(self->ezcaError != NULL){
|
||||||
|
ezcaFree(self->ezcaError);
|
||||||
|
}
|
||||||
|
if(self->motBaseName != NULL){
|
||||||
|
free(self->motBaseName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/*=======================================================================*/
|
||||||
|
MotorDriver *epicsMakeMotorDriver(char *baseName) {
|
||||||
|
epicsMotorDriver *pNew = NULL;
|
||||||
|
char fullName[132];
|
||||||
|
double limit;
|
||||||
|
|
||||||
|
pNew = malloc(sizeof(epicsMotorDriver));
|
||||||
|
if(pNew == NULL){
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
memset(pNew,0,sizeof(epicsMotorDriver));
|
||||||
|
pNew->motBaseName = strdup(baseName);
|
||||||
|
snprintf(fullName,sizeof(fullName),"%s.DRBV",pNew->motBaseName);
|
||||||
|
ezcaSetMonitor(fullName,ezcaDouble,1);
|
||||||
|
snprintf(fullName,sizeof(fullName),"%s.DMOV",pNew->motBaseName);
|
||||||
|
ezcaSetMonitor(fullName,ezcaShort,1);
|
||||||
|
snprintf(fullName,sizeof(fullName),"%s.STAT",pNew->motBaseName);
|
||||||
|
ezcaSetMonitor(fullName,ezcaShort,1);
|
||||||
|
|
||||||
|
snprintf(fullName,sizeof(fullName),"%s.HLM",pNew->motBaseName);
|
||||||
|
ezcaGet(fullName,ezcaDouble,1, &limit);
|
||||||
|
pNew->fUpper = limit;
|
||||||
|
snprintf(fullName,sizeof(fullName),"%s.LLM",pNew->motBaseName);
|
||||||
|
ezcaGet(fullName,ezcaDouble,1, &limit);
|
||||||
|
pNew->fLower = limit;
|
||||||
|
|
||||||
|
pNew->GetPosition = epicsGetPos;
|
||||||
|
pNew->RunTo = epicsRunTo;
|
||||||
|
pNew->Halt = epicsHalt;
|
||||||
|
pNew->GetStatus = epicsCheckStatus;
|
||||||
|
pNew->GetError = epicsGetError;
|
||||||
|
pNew->TryAndFixIt = epicsFixIt;
|
||||||
|
pNew->GetDriverPar = epicsGetDriverPar;
|
||||||
|
pNew->SetDriverPar = epicsSetDriverPar;
|
||||||
|
pNew->ListDriverPar = epicsListDriverPar;
|
||||||
|
pNew->KillPrivate = epicsKillPrivate;
|
||||||
|
|
||||||
|
/* ezcaTraceOn(); */
|
||||||
|
return (MotorDriver *)pNew;
|
||||||
|
}
|
2
event.c
2
event.c
@ -71,6 +71,8 @@ static char *pEvent[] = {
|
|||||||
"STATEEND",
|
"STATEEND",
|
||||||
"NEWTARGET",
|
"NEWTARGET",
|
||||||
"DIMCHANGE",
|
"DIMCHANGE",
|
||||||
|
"PAUSE",
|
||||||
|
"CONTINUE",
|
||||||
NULL
|
NULL
|
||||||
};
|
};
|
||||||
|
|
||||||
|
12
event.h
12
event.h
@ -1,5 +1,5 @@
|
|||||||
|
|
||||||
#line 103 "event.w"
|
#line 108 "event.w"
|
||||||
|
|
||||||
/*----------------------------------------------------------------------------
|
/*----------------------------------------------------------------------------
|
||||||
E V E N T
|
E V E N T
|
||||||
@ -18,7 +18,7 @@
|
|||||||
|
|
||||||
int Text2Event(char *pText);
|
int Text2Event(char *pText);
|
||||||
|
|
||||||
#line 116 "event.w"
|
#line 121 "event.w"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@ -49,8 +49,10 @@
|
|||||||
#define STEND 22
|
#define STEND 22
|
||||||
#define NEWTARGET 23
|
#define NEWTARGET 23
|
||||||
#define DIMCHANGE 24
|
#define DIMCHANGE 24
|
||||||
|
#define IPAUSE 25
|
||||||
|
#define CONTINUE 26
|
||||||
|
|
||||||
#line 118 "event.w"
|
#line 123 "event.w"
|
||||||
|
|
||||||
|
|
||||||
/*----------------- event data structure for the NEWTARGET event ---------*/
|
/*----------------- event data structure for the NEWTARGET event ---------*/
|
||||||
@ -60,7 +62,7 @@ typedef struct {
|
|||||||
} NewTarget, *pNewTarget;
|
} NewTarget, *pNewTarget;
|
||||||
/*--------------- Signals for the Signalfunction of each task ------------*/
|
/*--------------- Signals for the Signalfunction of each task ------------*/
|
||||||
|
|
||||||
#line 85 "event.w"
|
#line 90 "event.w"
|
||||||
|
|
||||||
#define SICSINT 300
|
#define SICSINT 300
|
||||||
#define SICSBROADCAST 301
|
#define SICSBROADCAST 301
|
||||||
@ -69,6 +71,6 @@ typedef struct {
|
|||||||
#define COMLOG 304
|
#define COMLOG 304
|
||||||
#define CRONLIST 305
|
#define CRONLIST 305
|
||||||
|
|
||||||
#line 126 "event.w"
|
#line 131 "event.w"
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -60,6 +60,8 @@ $\langle$VE {\footnotesize ?}$\rangle\equiv$
|
|||||||
\mbox{}\verb@#define STEND 22@\\
|
\mbox{}\verb@#define STEND 22@\\
|
||||||
\mbox{}\verb@#define NEWTARGET 23@\\
|
\mbox{}\verb@#define NEWTARGET 23@\\
|
||||||
\mbox{}\verb@#define DIMCHANGE 24@\\
|
\mbox{}\verb@#define DIMCHANGE 24@\\
|
||||||
|
\mbox{}\verb@#define IPAUSE 25@\\
|
||||||
|
\mbox{}\verb@#define CONTINUE 26@\\
|
||||||
\mbox{}\verb@@$\Diamond$
|
\mbox{}\verb@@$\Diamond$
|
||||||
\end{list}
|
\end{list}
|
||||||
\vspace{-1ex}
|
\vspace{-1ex}
|
||||||
@ -99,8 +101,11 @@ operation.
|
|||||||
\item[HDBVAL] The Hdb is notified of a value change. The eventData will be
|
\item[HDBVAL] The Hdb is notified of a value change. The eventData will be
|
||||||
the object on which the data changed.
|
the object on which the data changed.
|
||||||
\item[NEWTARGET] is invoked when a new target has been set on a drivable.
|
\item[NEWTARGET] is invoked when a new target has been set on a drivable.
|
||||||
|
\item[PAUSE] Pause counting
|
||||||
|
\item[CONTINUE] Continue counting
|
||||||
\end{description}
|
\end{description}
|
||||||
|
|
||||||
|
|
||||||
Furthermore event contains system wide signal codes which are interpreted in
|
Furthermore event contains system wide signal codes which are interpreted in
|
||||||
the signal functions provided by each SICS task. These code are
|
the signal functions provided by each SICS task. These code are
|
||||||
evaluated by the TaskSignalFunction which may be configured for each
|
evaluated by the TaskSignalFunction which may be configured for each
|
||||||
|
5
event.w
5
event.w
@ -43,6 +43,8 @@ if the event code is not known, else the apropriate event code.
|
|||||||
#define STEND 22
|
#define STEND 22
|
||||||
#define NEWTARGET 23
|
#define NEWTARGET 23
|
||||||
#define DIMCHANGE 24
|
#define DIMCHANGE 24
|
||||||
|
#define IPAUSE 25
|
||||||
|
#define CONTINUE 26
|
||||||
@}
|
@}
|
||||||
\begin{description}
|
\begin{description}
|
||||||
\item[VALUECHANGE] This is a variable changing its value. As event data a pointer to the
|
\item[VALUECHANGE] This is a variable changing its value. As event data a pointer to the
|
||||||
@ -74,8 +76,11 @@ operation.
|
|||||||
\item[HDBVAL] The Hdb is notified of a value change. The eventData will be
|
\item[HDBVAL] The Hdb is notified of a value change. The eventData will be
|
||||||
the object on which the data changed.
|
the object on which the data changed.
|
||||||
\item[NEWTARGET] is invoked when a new target has been set on a drivable.
|
\item[NEWTARGET] is invoked when a new target has been set on a drivable.
|
||||||
|
\item[PAUSE] Pause counting
|
||||||
|
\item[CONTINUE] Continue counting
|
||||||
\end{description}
|
\end{description}
|
||||||
|
|
||||||
|
|
||||||
Furthermore event contains system wide signal codes which are interpreted in
|
Furthermore event contains system wide signal codes which are interpreted in
|
||||||
the signal functions provided by each SICS task. These code are
|
the signal functions provided by each SICS task. These code are
|
||||||
evaluated by the TaskSignalFunction which may be configured for each
|
evaluated by the TaskSignalFunction which may be configured for each
|
||||||
|
21
hdbtable.c
21
hdbtable.c
@ -17,6 +17,10 @@
|
|||||||
* copyright: see file COPYRIGHT
|
* copyright: see file COPYRIGHT
|
||||||
*
|
*
|
||||||
* Mark Koennecke, March 2009
|
* Mark Koennecke, March 2009
|
||||||
|
*
|
||||||
|
* Added CountTblCmd
|
||||||
|
*
|
||||||
|
* Mark Koennecke, march 2013
|
||||||
*/
|
*/
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include "sicshipadaba.h"
|
#include "sicshipadaba.h"
|
||||||
@ -75,6 +79,20 @@ static int ClearTblCmd(pSICSOBJ self, SConnection *pCon, pHdb commandNode,
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
/*----------------------------------------------------------------------*/
|
/*----------------------------------------------------------------------*/
|
||||||
|
int CountTblCmd(pSICSOBJ self, SConnection *pCon, pHdb commandNode,
|
||||||
|
pHdb par[], int nPar)
|
||||||
|
{
|
||||||
|
pHdb node;
|
||||||
|
int nRows = 0;
|
||||||
|
|
||||||
|
node = GetHipadabaNode(self->objectNode,"data");
|
||||||
|
if(node != NULL){
|
||||||
|
nRows = CountHdbChildren(node);
|
||||||
|
}
|
||||||
|
SCPrintf(pCon,eValue,"rows = %d", nRows);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
/*----------------------------------------------------------------------*/
|
||||||
static int AddTblRowCmd(pSICSOBJ self, SConnection *pCon, pHdb commandNode,
|
static int AddTblRowCmd(pSICSOBJ self, SConnection *pCon, pHdb commandNode,
|
||||||
pHdb par[], int nPar)
|
pHdb par[], int nPar)
|
||||||
{
|
{
|
||||||
@ -470,6 +488,9 @@ pSICSOBJ MakeHdbTable(char *name, char *hdbclass)
|
|||||||
SetHdbProperty(node,"priv","user");
|
SetHdbProperty(node,"priv","user");
|
||||||
AddHipadabaChild(cmd,node, NULL);
|
AddHipadabaChild(cmd,node, NULL);
|
||||||
|
|
||||||
|
cmd = AddSICSHdbPar(result->objectNode, "count", usSpy,
|
||||||
|
MakeSICSFunc(CountTblCmd));
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
/*---------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------*/
|
||||||
|
27
histmem.c
27
histmem.c
@ -208,8 +208,8 @@ static int HistStartCount(void *pData, SConnection * pCon)
|
|||||||
iRet = self->pDriv->Start(self->pDriv, pCon);
|
iRet = self->pDriv->Start(self->pDriv, pCon);
|
||||||
if (iRet == OKOK) {
|
if (iRet == OKOK) {
|
||||||
/* send a COUNTSTART event */
|
/* send a COUNTSTART event */
|
||||||
|
clearHMData(self->pDriv->data);
|
||||||
InvokeCallBack(self->pCall, COUNTSTART, pCon);
|
InvokeCallBack(self->pCall, COUNTSTART, pCon);
|
||||||
updateHMData(self->pDriv->data);
|
|
||||||
return iRet;
|
return iRet;
|
||||||
} else {
|
} else {
|
||||||
iRet = self->pDriv->GetError(self->pDriv, &iErr, pError, 79);
|
iRet = self->pDriv->GetError(self->pDriv, &iErr, pError, 79);
|
||||||
@ -350,9 +350,9 @@ static int HistCountStatus(void *pData, SConnection * pCon)
|
|||||||
return HWBusy;
|
return HWBusy;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (eCt == HWBusy){
|
/* if (eCt == HWBusy){ */
|
||||||
updateHMData(self->pDriv->data);
|
/* updateHMData(self->pDriv->data); */
|
||||||
}
|
/* } */
|
||||||
|
|
||||||
if (eCt == HWIdle) {
|
if (eCt == HWIdle) {
|
||||||
/* force an update of local histogram data with next
|
/* force an update of local histogram data with next
|
||||||
@ -879,7 +879,7 @@ int GetHistogram(pHistMem self, SConnection * pCon,
|
|||||||
eWarning);
|
eWarning);
|
||||||
iEnd = (iDataLen / sizeof(HistInt)) - 1;
|
iEnd = (iDataLen / sizeof(HistInt)) - 1;
|
||||||
}
|
}
|
||||||
return getHMDataHistogram(self, pCon, i, iStart, iEnd, lData);
|
return getHMDataHistogram(self, pCon, i, iStart, iEnd-iStart, lData);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*-------------------------------------------------------------------------*/
|
/*-------------------------------------------------------------------------*/
|
||||||
@ -1335,6 +1335,22 @@ int HistAction(SConnection * pCon, SicsInterp * pSics, void *pData,
|
|||||||
} else {
|
} else {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
} else if (strcmp(argv[1], "clearhm") == 0) {
|
||||||
|
/*
|
||||||
|
clear the local copy of the HM. Assumes that the HM
|
||||||
|
clears itself on start. Which it does.
|
||||||
|
*/
|
||||||
|
if (SCMatchRights(pCon, usUser)) {
|
||||||
|
if(self->pDriv->data != NULL){
|
||||||
|
clearHMData(self->pDriv->data);
|
||||||
|
SCSendOK(pCon);
|
||||||
|
return 1;
|
||||||
|
} else {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
} else if (strcmp(argv[1], "list") == 0) {
|
} else if (strcmp(argv[1], "list") == 0) {
|
||||||
HMListOption(self, pCon);
|
HMListOption(self, pCon);
|
||||||
return 1;
|
return 1;
|
||||||
@ -1798,4 +1814,5 @@ int HistAction(SConnection * pCon, SicsInterp * pSics, void *pData,
|
|||||||
SCWrite(pCon, pBueffel, eError);
|
SCWrite(pCon, pBueffel, eError);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
49
hkl.c
49
hkl.c
@ -26,6 +26,10 @@
|
|||||||
Heavily reworked to fit into the new four circle setup
|
Heavily reworked to fit into the new four circle setup
|
||||||
|
|
||||||
Mark Koennecke, July 2008
|
Mark Koennecke, July 2008
|
||||||
|
|
||||||
|
Added calculation of angles between reflection
|
||||||
|
|
||||||
|
Mark Koennecke, March 2013
|
||||||
-----------------------------------------------------------------------------*/
|
-----------------------------------------------------------------------------*/
|
||||||
#include <math.h>
|
#include <math.h>
|
||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
@ -687,6 +691,47 @@ static int HKLCalculateTheta(pHKL self, float fHKL[3], double *stt)
|
|||||||
*stt = 2. * theta;
|
*stt = 2. * theta;
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
/*-------------------------------------------------------------------------*/
|
||||||
|
static int HKLAngle(SConnection *pCon, int argc, char *argv[])
|
||||||
|
{
|
||||||
|
reflection r1, r2;
|
||||||
|
lattice direct;
|
||||||
|
const double *cell;
|
||||||
|
MATRIX B;
|
||||||
|
double ang;
|
||||||
|
|
||||||
|
if(argc < 8){
|
||||||
|
SCWrite(pCon,"ERROR: insufficient no of arguments to hkl angle",eError);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
r1.h = atof(argv[2]);
|
||||||
|
r1.k = atof(argv[3]);
|
||||||
|
r1.l = atof(argv[4]);
|
||||||
|
|
||||||
|
r2.h = atof(argv[5]);
|
||||||
|
r2.k = atof(argv[6]);
|
||||||
|
r2.l = atof(argv[7]);
|
||||||
|
|
||||||
|
cell = SXGetCell();
|
||||||
|
direct.a = cell[0];
|
||||||
|
direct.b = cell[1];
|
||||||
|
direct.c = cell[2];
|
||||||
|
direct.alpha = cell[3];
|
||||||
|
direct.beta = cell[4];
|
||||||
|
direct.gamma = cell[5];
|
||||||
|
|
||||||
|
B = mat_creat(3,3,ZERO_MATRIX);
|
||||||
|
if(B == NULL){
|
||||||
|
SCWrite(pCon,"ERROR: out of memory in HKL angle",eError);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
calculateBMatrix(direct,B);
|
||||||
|
ang = angleBetweenReflections(B,r1,r2);
|
||||||
|
SCPrintf(pCon,eValue,"angle = %f", ang);
|
||||||
|
mat_free(B);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
/*--------------------------------------------------------------------------*/
|
/*--------------------------------------------------------------------------*/
|
||||||
static int HandleBiToNB(SConnection *pCon, int argc, char *argv[])
|
static int HandleBiToNB(SConnection *pCon, int argc, char *argv[])
|
||||||
{
|
{
|
||||||
@ -993,6 +1038,10 @@ int HKLAction(SConnection * pCon, SicsInterp * pSics, void *pData,
|
|||||||
SCPrintf(pCon, eValue, "two-theta = %lf", stt);
|
SCPrintf(pCon, eValue, "two-theta = %lf", stt);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
/*--------------- calculate angle */
|
||||||
|
else if (strcmp(argv[1], "angle") == 0) {
|
||||||
|
return HKLAngle(pCon,argc,argv);
|
||||||
|
}
|
||||||
/*------------------ run */
|
/*------------------ run */
|
||||||
else if (strcmp(argv[1], "run") == 0) {
|
else if (strcmp(argv[1], "run") == 0) {
|
||||||
if (!SCMatchRights(pCon, usUser)) {
|
if (!SCMatchRights(pCon, usUser)) {
|
||||||
|
3
hmdata.c
3
hmdata.c
@ -59,6 +59,7 @@ void clearHMData(pHMdata self)
|
|||||||
size *= getNoOfTimebins(self);
|
size *= getNoOfTimebins(self);
|
||||||
}
|
}
|
||||||
memset(self->localBuffer, 0, size * sizeof(HistInt));
|
memset(self->localBuffer, 0, size * sizeof(HistInt));
|
||||||
|
self->nextUpdate = time(NULL) + self->updateIntervall;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*----------------------------------------------------------------------*/
|
/*----------------------------------------------------------------------*/
|
||||||
@ -313,7 +314,7 @@ static int updateHMbuffer(pHistMem hist, int bank, SConnection * pCon)
|
|||||||
}
|
}
|
||||||
if (status == OKOK) {
|
if (status == OKOK) {
|
||||||
return 1;
|
return 1;
|
||||||
} else {
|
} else {
|
||||||
return HWFault;
|
return HWFault;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
79
intcli.c
79
intcli.c
@ -1,79 +0,0 @@
|
|||||||
/*---------------------------------------------------------------------------
|
|
||||||
Client side implementation of the Interrupt interface.
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Mark Koennecke, December 1996
|
|
||||||
|
|
||||||
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 <stdio.h>
|
|
||||||
#include "fortify.h"
|
|
||||||
#include "network.h"
|
|
||||||
#include "interrupt.h"
|
|
||||||
|
|
||||||
static mkChannel *pChannel = NULL;
|
|
||||||
|
|
||||||
/*---------------------------------------------------------------------------*/
|
|
||||||
int ClientSetupInterrupt(char *host, int iPort)
|
|
||||||
{
|
|
||||||
pChannel = UDPConnect(host, iPort);
|
|
||||||
if (pChannel == NULL) {
|
|
||||||
return 0;
|
|
||||||
} else {
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*---------------------------------------------------------------------------*/
|
|
||||||
void ClientStopInterrupt(void)
|
|
||||||
{
|
|
||||||
if (pChannel) {
|
|
||||||
NETClosePort(pChannel);
|
|
||||||
free(pChannel);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*---------------------------------------------------------------------------*/
|
|
||||||
void SendInterrupt(int iCode)
|
|
||||||
{
|
|
||||||
char pBueffel[132];
|
|
||||||
|
|
||||||
if ((iCode < 0)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
snprintf(pBueffel,sizeof(pBueffel)-1, "SICSINT %d", iCode);
|
|
||||||
UDPWrite(pChannel, pBueffel, strlen(pBueffel));
|
|
||||||
}
|
|
214
interface.c
214
interface.c
@ -1,4 +1,4 @@
|
|||||||
/*--------------------------------------------------------------------------
|
/*--------------------------------------------------------------------------
|
||||||
I N T E R F A C E
|
I N T E R F A C E
|
||||||
|
|
||||||
|
|
||||||
@ -12,6 +12,11 @@
|
|||||||
Paul Scherrer Institut
|
Paul Scherrer Institut
|
||||||
CH-5423 Villigen-PSI
|
CH-5423 Villigen-PSI
|
||||||
|
|
||||||
|
Extended over time with utility functions
|
||||||
|
|
||||||
|
Added Drivable and Countable task functions
|
||||||
|
|
||||||
|
Mark Koennecke, February 2013
|
||||||
|
|
||||||
The authors hereby grant permission to use, copy, modify, distribute,
|
The authors hereby grant permission to use, copy, modify, distribute,
|
||||||
and license this software and its documentation for any purpose, provided
|
and license this software and its documentation for any purpose, provided
|
||||||
@ -42,6 +47,7 @@
|
|||||||
#include "fortify.h"
|
#include "fortify.h"
|
||||||
#include "sics.h"
|
#include "sics.h"
|
||||||
#include "motor.h"
|
#include "motor.h"
|
||||||
|
#include <status.h>
|
||||||
/*=========================================================================
|
/*=========================================================================
|
||||||
Empty driveable interface functions
|
Empty driveable interface functions
|
||||||
==========================================================================*/
|
==========================================================================*/
|
||||||
@ -168,7 +174,107 @@ int GetDrivablePosition(void *pObject, SConnection * pCon, float *fPos)
|
|||||||
*fPos = value;
|
*fPos = value;
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
/*--------------------------------------------------------------------------*/
|
||||||
|
typedef struct {
|
||||||
|
void *obj;
|
||||||
|
pIDrivable pDriv;
|
||||||
|
SConnection *pCon;
|
||||||
|
char *name;
|
||||||
|
}DriveTaskData;
|
||||||
|
/*-------------------------------------------------------------------------*/
|
||||||
|
static void KillDriveTaskData(void *data)
|
||||||
|
{
|
||||||
|
DriveTaskData *taskData = (DriveTaskData *)data;
|
||||||
|
|
||||||
|
if(taskData == NULL){
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if(taskData->name != NULL){
|
||||||
|
free(taskData->name);
|
||||||
|
}
|
||||||
|
if(taskData->pCon != NULL){
|
||||||
|
SCDeleteConnection(taskData->pCon);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/*-------------------------------------------------------------------------*/
|
||||||
|
static void DriveTaskSignal(void *data, int iSignal, void *pSigData)
|
||||||
|
{
|
||||||
|
DriveTaskData *taskData = (DriveTaskData *)data;
|
||||||
|
int *interrupt;
|
||||||
|
|
||||||
|
assert(taskData != NULL);
|
||||||
|
|
||||||
|
if(iSignal == SICSINT){
|
||||||
|
interrupt = (int *)pSigData;
|
||||||
|
if(*interrupt != eContinue){
|
||||||
|
SCPrintf(taskData->pCon,eLogError,"ERROR: Interrupting %s", taskData->name);
|
||||||
|
taskData->pDriv->Halt(taskData->obj);
|
||||||
|
SCSetInterrupt(taskData->pCon,*interrupt);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/*--------------------------------------------------------------------------*/
|
||||||
|
static int DriveTaskFunc(void *data)
|
||||||
|
{
|
||||||
|
DriveTaskData *taskData = (DriveTaskData *)data;
|
||||||
|
int status;
|
||||||
|
|
||||||
|
assert(taskData != NULL);
|
||||||
|
|
||||||
|
|
||||||
|
status = taskData->pDriv->CheckStatus(taskData->obj,taskData->pCon);
|
||||||
|
if(status == HWBusy){
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
DevexecLog("STOP",taskData->name);
|
||||||
|
if(status == HWIdle || status == OKOK){
|
||||||
|
ExeInterest(pServ->pExecutor,taskData->name, "finished");
|
||||||
|
} else {
|
||||||
|
ExeInterest(pServ->pExecutor,taskData->name, "finished with problem");
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
/*--------------------------------------------------------------------------*/
|
||||||
|
long StartDriveTask(void *obj, SConnection *pCon, char *name, float fTarget)
|
||||||
|
{
|
||||||
|
pIDrivable pDriv = NULL;
|
||||||
|
char error[132], buffer[132];
|
||||||
|
DriveTaskData *taskData = NULL;
|
||||||
|
|
||||||
|
pDriv = GetDrivableInterface(obj);
|
||||||
|
if(pDriv == NULL){
|
||||||
|
SCPrintf(pCon,eError,"ERROR: %s is not drivable", name);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
if(pDriv->CheckLimits(obj,fTarget,error,sizeof(error)) != OKOK){
|
||||||
|
SCPrintf(pCon,eError,"ERROR: %s cannot reach %f, reason %s", name,
|
||||||
|
fTarget, error);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
taskData = calloc(1,sizeof(DriveTaskData));
|
||||||
|
if(taskData == NULL){
|
||||||
|
SCPrintf(pCon,eError,"ERROR: out of memory starting %s", name);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if(pDriv->SetValue(obj,pCon,fTarget) != OKOK){
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
ExeInterest(pServ->pExecutor,name,"started");
|
||||||
|
DevexecLog("START",name);
|
||||||
|
InvokeNewTarget(pServ->pExecutor,name,fTarget);
|
||||||
|
|
||||||
|
taskData->obj = obj;
|
||||||
|
taskData->pDriv = pDriv;
|
||||||
|
taskData->pCon = SCCopyConnection(pCon);
|
||||||
|
taskData->name = strdup(name);
|
||||||
|
|
||||||
|
return TaskRegisterN(pServ->pTasker,
|
||||||
|
name,
|
||||||
|
DriveTaskFunc,
|
||||||
|
DriveTaskSignal,
|
||||||
|
KillDriveTaskData,
|
||||||
|
taskData,0);
|
||||||
|
}
|
||||||
/*--------------------------------------------------------------------------*/
|
/*--------------------------------------------------------------------------*/
|
||||||
pICountable GetCountableInterface(void *pObject)
|
pICountable GetCountableInterface(void *pObject)
|
||||||
{
|
{
|
||||||
@ -201,6 +307,112 @@ int isRunning(pICountable self)
|
|||||||
{
|
{
|
||||||
return self->running;
|
return self->running;
|
||||||
}
|
}
|
||||||
|
/*--------------------------------------------------------------------------*/
|
||||||
|
typedef struct {
|
||||||
|
void *obj;
|
||||||
|
pICountable pCount;
|
||||||
|
SConnection *pCon;
|
||||||
|
char *name;
|
||||||
|
}CountTaskData;
|
||||||
|
/*-------------------------------------------------------------------------*/
|
||||||
|
static void KillCountTaskData(void *data)
|
||||||
|
{
|
||||||
|
CountTaskData *taskData = (CountTaskData *)data;
|
||||||
|
|
||||||
|
if(taskData == NULL){
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if(taskData->name != NULL){
|
||||||
|
free(taskData->name);
|
||||||
|
}
|
||||||
|
if(taskData->pCon != NULL){
|
||||||
|
SCDeleteConnection(taskData->pCon);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/*-------------------------------------------------------------------------*/
|
||||||
|
static void CountTaskSignal(void *data, int iSignal, void *pSigData)
|
||||||
|
{
|
||||||
|
CountTaskData *taskData = (CountTaskData *)data;
|
||||||
|
int *interrupt;
|
||||||
|
|
||||||
|
assert(taskData != NULL);
|
||||||
|
|
||||||
|
if(iSignal == SICSINT){
|
||||||
|
interrupt = (int *)pSigData;
|
||||||
|
if(*interrupt != eContinue){
|
||||||
|
SCPrintf(taskData->pCon,eLogError,"ERROR: Interrupting %s", taskData->name);
|
||||||
|
taskData->pCount->Halt(taskData->obj);
|
||||||
|
SCSetInterrupt(taskData->pCon,*interrupt);
|
||||||
|
}
|
||||||
|
} else if(iSignal == IPAUSE){
|
||||||
|
taskData->pCount->Pause(taskData->obj,taskData->pCon);
|
||||||
|
} else if(iSignal == CONTINUE){
|
||||||
|
taskData->pCount->Continue(taskData->obj,taskData->pCon);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/*--------------------------------------------------------------------------*/
|
||||||
|
static int CountTaskFunc(void *data)
|
||||||
|
{
|
||||||
|
CountTaskData *taskData = (CountTaskData *)data;
|
||||||
|
int status;
|
||||||
|
|
||||||
|
assert(taskData != NULL);
|
||||||
|
|
||||||
|
status = taskData->pCount->CheckCountStatus(taskData->obj,taskData->pCon);
|
||||||
|
if(status == HWBusy) {
|
||||||
|
SetStatus(eCounting);
|
||||||
|
return 1;
|
||||||
|
} else if(status == HWNoBeam){
|
||||||
|
SetStatus(eOutOfBeam);
|
||||||
|
return 1;
|
||||||
|
} else if(status == HWPause){
|
||||||
|
SetStatus(ePaused);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
DevexecLog("STOP",taskData->name);
|
||||||
|
if(status == HWIdle || status == OKOK){
|
||||||
|
ExeInterest(pServ->pExecutor,taskData->name, "finished");
|
||||||
|
} else {
|
||||||
|
ExeInterest(pServ->pExecutor,taskData->name, "finished with problem");
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
/*--------------------------------------------------------------------------*/
|
||||||
|
long StartCountTask(void *obj, SConnection *pCon, char *name)
|
||||||
|
{
|
||||||
|
pICountable pCount = NULL;
|
||||||
|
char error[132], buffer[132];
|
||||||
|
CountTaskData *taskData = NULL;
|
||||||
|
|
||||||
|
pCount = FindInterface(obj,COUNTID);
|
||||||
|
if(pCount == NULL){
|
||||||
|
SCPrintf(pCon,eError,"ERROR: %s is not countable", name);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
taskData = calloc(1,sizeof(CountTaskData));
|
||||||
|
if(taskData == NULL){
|
||||||
|
SCPrintf(pCon,eError,"ERROR: out of memory starting %s", name);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if(pCount->StartCount(obj,pCon) != OKOK){
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
ExeInterest(pServ->pExecutor,name,"started");
|
||||||
|
DevexecLog("START",name);
|
||||||
|
|
||||||
|
taskData->obj = obj;
|
||||||
|
taskData->pCount = pCount;
|
||||||
|
taskData->pCon = SCCopyConnection(pCon);
|
||||||
|
taskData->name = strdup(name);
|
||||||
|
|
||||||
|
return TaskRegisterN(pServ->pTasker,
|
||||||
|
name,
|
||||||
|
CountTaskFunc,
|
||||||
|
CountTaskSignal,
|
||||||
|
KillCountTaskData,
|
||||||
|
taskData,0);
|
||||||
|
}
|
||||||
|
|
||||||
/*--------------------------------------------------------------------------*/
|
/*--------------------------------------------------------------------------*/
|
||||||
pICallBack GetCallbackInterface(void *pObject)
|
pICallBack GetCallbackInterface(void *pObject)
|
||||||
|
194
interface.h
194
interface.h
@ -1,5 +1,5 @@
|
|||||||
|
|
||||||
#line 399 "interface.w"
|
#line 412 "interface.w"
|
||||||
|
|
||||||
/*---------------------------------------------------------------------------
|
/*---------------------------------------------------------------------------
|
||||||
I N T E R F A C E S
|
I N T E R F A C E S
|
||||||
@ -30,107 +30,113 @@
|
|||||||
#line 121 "interface.w"
|
#line 121 "interface.w"
|
||||||
|
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
int ID;
|
int ID;
|
||||||
int (*Halt) (void *self);
|
int (*Halt)(void *self);
|
||||||
int (*CheckLimits) (void *self, float fVal, char *error, int iErrLen);
|
int (*CheckLimits)(void *self, float fVal,
|
||||||
long (*SetValue) (void *self, SConnection * pCon, float fVal);
|
char *error, int iErrLen);
|
||||||
int (*CheckStatus) (void *self, SConnection * pCon);
|
long (*SetValue)(void *self, SConnection *pCon,
|
||||||
float (*GetValue) (void *self, SConnection * pCon);
|
float fVal);
|
||||||
int iErrorCount;
|
int (*CheckStatus)(void *self, SConnection *pCon);
|
||||||
int drivableStatus;
|
float (*GetValue)(void *self, SConnection *pCon);
|
||||||
} IDrivable, *pIDrivable;
|
int iErrorCount;
|
||||||
|
int drivableStatus;
|
||||||
|
} IDrivable, *pIDrivable;
|
||||||
|
|
||||||
pIDrivable GetDrivableInterface(void *pObject);
|
pIDrivable GetDrivableInterface(void *pObject);
|
||||||
int GetDrivablePosition(void *pObject, SConnection * pCon, float *fPos);
|
int GetDrivablePosition(void *pObject, SConnection *pCon,
|
||||||
|
float *fPos);
|
||||||
|
|
||||||
|
long StartDriveTask(void *self, SConnection *pCon, char *name, float fTarget);
|
||||||
|
|
||||||
#line 425 "interface.w"
|
|
||||||
|
|
||||||
|
|
||||||
pIDrivable CreateDrivableInterface(void);
|
|
||||||
|
|
||||||
/* ------------------------ The countable interface ---------------------*/
|
|
||||||
|
|
||||||
#line 188 "interface.w"
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
int ID;
|
|
||||||
int running;
|
|
||||||
int (*Halt) (void *self);
|
|
||||||
void (*SetCountParameters) (void *self, float fPreset,
|
|
||||||
CounterMode eMode);
|
|
||||||
int (*StartCount) (void *self, SConnection * pCon);
|
|
||||||
int (*CheckCountStatus) (void *self, SConnection * pCon);
|
|
||||||
int (*Pause) (void *self, SConnection * pCon);
|
|
||||||
int (*Continue) (void *self, SConnection * pCon);
|
|
||||||
int (*TransferData) (void *self, SConnection * pCon);
|
|
||||||
} ICountable, *pICountable;
|
|
||||||
|
|
||||||
pICountable GetCountableInterface(void *pObject);
|
|
||||||
int GetCountLock(pICountable self, SConnection * pCon);
|
|
||||||
void ReleaseCountLock(pICountable self);
|
|
||||||
int isRunning(pICountable self);
|
|
||||||
|
|
||||||
#line 430 "interface.w"
|
|
||||||
|
|
||||||
|
|
||||||
pICountable CreateCountableInterface(void);
|
|
||||||
|
|
||||||
/* ------------------------- The CallBack Interface --------------------*/
|
|
||||||
|
|
||||||
#line 253 "interface.w"
|
|
||||||
|
|
||||||
typedef void (*KillFuncIT) (void *pData);
|
|
||||||
typedef int (*SICSCallBack) (int iEvent, void *pEventData,
|
|
||||||
void *pUserData);
|
|
||||||
|
|
||||||
#line 435 "interface.w"
|
|
||||||
|
|
||||||
|
|
||||||
#line 275 "interface.w"
|
|
||||||
|
|
||||||
typedef struct __ICallBack *pICallBack;
|
|
||||||
|
|
||||||
/* event source side */
|
|
||||||
pICallBack CreateCallBackInterface(void);
|
|
||||||
void DeleteCallBackInterface(pICallBack self);
|
|
||||||
int InvokeCallBack(pICallBack pInterface, int iEvent, void *pEventData);
|
|
||||||
|
|
||||||
/* callback client side */
|
|
||||||
long RegisterCallback(pICallBack pInterface,
|
|
||||||
int iEvent, SICSCallBack pFunc,
|
|
||||||
void *pUserData, KillFuncIT pKill);
|
|
||||||
int RemoveCallback(pICallBack pInterface, long iID);
|
|
||||||
int RemoveCallback2(pICallBack pInterface, void *pUserData);
|
|
||||||
int RemoveCallbackCon(pICallBack pInterface, SConnection * pCon);
|
|
||||||
|
|
||||||
int CallbackScript(SConnection * pCon, SicsInterp * pSics, void *pData,
|
|
||||||
int argc, char *argv[]);
|
|
||||||
|
|
||||||
pICallBack GetCallbackInterface(void *pData);
|
|
||||||
|
|
||||||
#line 436 "interface.w"
|
|
||||||
|
|
||||||
/*---------------------- The Environment Interface --------------------*/
|
|
||||||
|
|
||||||
#line 353 "interface.w"
|
|
||||||
|
|
||||||
typedef enum { EVIdle, EVDrive, EVMonitor, EVError } EVMode;
|
|
||||||
typedef struct {
|
|
||||||
int iID;
|
|
||||||
EVMode(*GetMode) (void *self);
|
|
||||||
int (*IsInTolerance) (void *self);
|
|
||||||
int (*HandleError) (void *self);
|
|
||||||
} EVInterface, *pEVInterface;
|
|
||||||
|
|
||||||
#line 438 "interface.w"
|
#line 438 "interface.w"
|
||||||
|
|
||||||
|
|
||||||
#line 379 "interface.w"
|
pIDrivable CreateDrivableInterface(void);
|
||||||
|
|
||||||
pEVInterface CreateEVInterface(void);
|
/* ------------------------ The countable interface ---------------------*/
|
||||||
|
|
||||||
#line 439 "interface.w"
|
#line 195 "interface.w"
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
int ID;
|
||||||
|
int running;
|
||||||
|
int (*Halt)(void *self);
|
||||||
|
void (*SetCountParameters)(void *self, float fPreset,
|
||||||
|
CounterMode eMode);\
|
||||||
|
int (*StartCount)(void *self, SConnection *pCon);
|
||||||
|
int (*CheckCountStatus)(void *self, SConnection *pCon);
|
||||||
|
int (*Pause)(void *self, SConnection *pCon);
|
||||||
|
int (*Continue)(void *self, SConnection *pCon);
|
||||||
|
int (*TransferData)(void *self, SConnection *pCon);
|
||||||
|
} ICountable, *pICountable;
|
||||||
|
|
||||||
|
pICountable GetCountableInterface(void *pObject);
|
||||||
|
int GetCountLock(pICountable self, SConnection *pCon);
|
||||||
|
void ReleaseCountLock(pICountable self);
|
||||||
|
int isRunning(pICountable self);
|
||||||
|
long StartCountTask(void *self, SConnection *pCon, char *name);
|
||||||
|
|
||||||
|
#line 443 "interface.w"
|
||||||
|
|
||||||
|
|
||||||
|
pICountable CreateCountableInterface(void);
|
||||||
|
|
||||||
|
/* ------------------------- The CallBack Interface --------------------*/
|
||||||
|
|
||||||
|
#line 266 "interface.w"
|
||||||
|
|
||||||
|
typedef void (*KillFuncIT)(void *pData);
|
||||||
|
typedef int (*SICSCallBack)(int iEvent, void *pEventData,
|
||||||
|
void *pUserData);
|
||||||
|
|
||||||
|
#line 448 "interface.w"
|
||||||
|
|
||||||
|
|
||||||
|
#line 288 "interface.w"
|
||||||
|
|
||||||
|
typedef struct __ICallBack *pICallBack;
|
||||||
|
|
||||||
|
/* event source side */
|
||||||
|
pICallBack CreateCallBackInterface(void);
|
||||||
|
void DeleteCallBackInterface(pICallBack self);
|
||||||
|
int InvokeCallBack(pICallBack pInterface, int iEvent, void *pEventData);
|
||||||
|
|
||||||
|
/* callback client side */
|
||||||
|
long RegisterCallback(pICallBack pInterface,
|
||||||
|
int iEvent, SICSCallBack pFunc,
|
||||||
|
void *pUserData, KillFuncIT pKill);
|
||||||
|
int RemoveCallback(pICallBack pInterface, long iID);
|
||||||
|
int RemoveCallback2(pICallBack pInterface, void *pUserData);
|
||||||
|
int RemoveCallbackCon(pICallBack pInterface, SConnection *pCon);
|
||||||
|
|
||||||
|
int CallbackScript(SConnection *pCon, SicsInterp *pSics, void *pData,
|
||||||
|
int argc, char *argv[]);
|
||||||
|
|
||||||
|
pICallBack GetCallbackInterface(void *pData);
|
||||||
|
|
||||||
|
#line 449 "interface.w"
|
||||||
|
|
||||||
|
/*---------------------- The Environment Interface --------------------*/
|
||||||
|
|
||||||
|
#line 366 "interface.w"
|
||||||
|
|
||||||
|
typedef enum { EVIdle, EVDrive, EVMonitor, EVError } EVMode;
|
||||||
|
typedef struct {
|
||||||
|
int iID;
|
||||||
|
EVMode (*GetMode)(void *self);
|
||||||
|
int (*IsInTolerance)(void *self);
|
||||||
|
int (*HandleError)(void *self);
|
||||||
|
} EVInterface, *pEVInterface;
|
||||||
|
|
||||||
|
#line 451 "interface.w"
|
||||||
|
|
||||||
|
|
||||||
|
#line 392 "interface.w"
|
||||||
|
|
||||||
|
pEVInterface CreateEVInterface(void);
|
||||||
|
|
||||||
|
#line 452 "interface.w"
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -154,6 +154,8 @@ $\langle$driv {\footnotesize ?}$\rangle\equiv$
|
|||||||
\mbox{}\verb@ int GetDrivablePosition(void *pObject, SConnection *pCon,@\\
|
\mbox{}\verb@ int GetDrivablePosition(void *pObject, SConnection *pCon,@\\
|
||||||
\mbox{}\verb@ float *fPos);@\\
|
\mbox{}\verb@ float *fPos);@\\
|
||||||
\mbox{}\verb@@\\
|
\mbox{}\verb@@\\
|
||||||
|
\mbox{}\verb@ long StartDriveTask(void *self, SConnection *pCon, char *name, float fTarget);@\\
|
||||||
|
\mbox{}\verb@@\\
|
||||||
\mbox{}\verb@@$\Diamond$
|
\mbox{}\verb@@$\Diamond$
|
||||||
\end{list}
|
\end{list}
|
||||||
\vspace{-1ex}
|
\vspace{-1ex}
|
||||||
@ -206,6 +208,11 @@ will be returned.
|
|||||||
object. If the device is a motor corrections for zero points and signs
|
object. If the device is a motor corrections for zero points and signs
|
||||||
will be applied. Returns 1 on success and 0 on failure}
|
will be applied. Returns 1 on success and 0 on failure}
|
||||||
|
|
||||||
|
{\bf StartDriveTask starts a drivable in a new task. If the task can be started, its
|
||||||
|
task ID is returned. -1 is returned on failure.
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
\subsubsection{The Countable Interface}
|
\subsubsection{The Countable Interface}
|
||||||
This is an interface for interacting with anything which counts.
|
This is an interface for interacting with anything which counts.
|
||||||
|
|
||||||
@ -233,6 +240,7 @@ $\langle$count {\footnotesize ?}$\rangle\equiv$
|
|||||||
\mbox{}\verb@ int GetCountLock(pICountable self, SConnection *pCon);@\\
|
\mbox{}\verb@ int GetCountLock(pICountable self, SConnection *pCon);@\\
|
||||||
\mbox{}\verb@ void ReleaseCountLock(pICountable self);@\\
|
\mbox{}\verb@ void ReleaseCountLock(pICountable self);@\\
|
||||||
\mbox{}\verb@ int isRunning(pICountable self);@\\
|
\mbox{}\verb@ int isRunning(pICountable self);@\\
|
||||||
|
\mbox{}\verb@ long StartCountTask(void *self, SConnection *pCon, char *name);@\\
|
||||||
\mbox{}\verb@@$\Diamond$
|
\mbox{}\verb@@$\Diamond$
|
||||||
\end{list}
|
\end{list}
|
||||||
\vspace{-1ex}
|
\vspace{-1ex}
|
||||||
@ -273,6 +281,11 @@ will be returned.
|
|||||||
{\bf ReleaseCountLock} release the count lock.
|
{\bf ReleaseCountLock} release the count lock.
|
||||||
|
|
||||||
{\bf isRunning} returns the running flag.
|
{\bf isRunning} returns the running flag.
|
||||||
|
|
||||||
|
{\bf StartCountTask starts a countable in a new task. If the task can be started, its
|
||||||
|
task ID is returned. -1 is returned on failure.
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
\subsubsection{The Callback Interface}
|
\subsubsection{The Callback Interface}
|
||||||
The Callback Interface is SICS suport for component behaviour for objects.
|
The Callback Interface is SICS suport for component behaviour for objects.
|
||||||
|
13
interface.w
13
interface.w
@ -137,6 +137,8 @@ environment controllers fit this bill as well.
|
|||||||
int GetDrivablePosition(void *pObject, SConnection *pCon,
|
int GetDrivablePosition(void *pObject, SConnection *pCon,
|
||||||
float *fPos);
|
float *fPos);
|
||||||
|
|
||||||
|
long StartDriveTask(void *self, SConnection *pCon, char *name, float fTarget);
|
||||||
|
|
||||||
@}
|
@}
|
||||||
The first member of this structure is an ID which can be used in order to
|
The first member of this structure is an ID which can be used in order to
|
||||||
check if the right datastructure has been obtained.
|
check if the right datastructure has been obtained.
|
||||||
@ -181,6 +183,11 @@ will be returned.
|
|||||||
object. If the device is a motor corrections for zero points and signs
|
object. If the device is a motor corrections for zero points and signs
|
||||||
will be applied. Returns 1 on success and 0 on failure}
|
will be applied. Returns 1 on success and 0 on failure}
|
||||||
|
|
||||||
|
{\bf StartDriveTask starts a drivable in a new task. If the task can be started, its
|
||||||
|
task ID is returned. -1 is returned on failure.
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
\subsubsection{The Countable Interface}
|
\subsubsection{The Countable Interface}
|
||||||
This is an interface for interacting with anything which counts.
|
This is an interface for interacting with anything which counts.
|
||||||
|
|
||||||
@ -203,6 +210,7 @@ This is an interface for interacting with anything which counts.
|
|||||||
int GetCountLock(pICountable self, SConnection *pCon);
|
int GetCountLock(pICountable self, SConnection *pCon);
|
||||||
void ReleaseCountLock(pICountable self);
|
void ReleaseCountLock(pICountable self);
|
||||||
int isRunning(pICountable self);
|
int isRunning(pICountable self);
|
||||||
|
long StartCountTask(void *self, SConnection *pCon, char *name);
|
||||||
@}
|
@}
|
||||||
|
|
||||||
{\bf running } Is a flag which says if the counter is operating or not.
|
{\bf running } Is a flag which says if the counter is operating or not.
|
||||||
@ -236,6 +244,11 @@ will be returned.
|
|||||||
{\bf ReleaseCountLock} release the count lock.
|
{\bf ReleaseCountLock} release the count lock.
|
||||||
|
|
||||||
{\bf isRunning} returns the running flag.
|
{\bf isRunning} returns the running flag.
|
||||||
|
|
||||||
|
{\bf StartCountTask starts a countable in a new task. If the task can be started, its
|
||||||
|
task ID is returned. -1 is returned on failure.
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
\subsubsection{The Callback Interface}
|
\subsubsection{The Callback Interface}
|
||||||
The Callback Interface is SICS suport for component behaviour for objects.
|
The Callback Interface is SICS suport for component behaviour for objects.
|
||||||
|
42
intserv.c
42
intserv.c
@ -8,6 +8,10 @@
|
|||||||
|
|
||||||
Mark Koennecke, November 1996
|
Mark Koennecke, November 1996
|
||||||
Revised: Mark Koennecke, September 1997
|
Revised: Mark Koennecke, September 1997
|
||||||
|
|
||||||
|
Removed unused UDP interrupt port stuff
|
||||||
|
|
||||||
|
Mark Koennecke, February 2013
|
||||||
|
|
||||||
Copyright: see copyright.h
|
Copyright: see copyright.h
|
||||||
|
|
||||||
@ -22,10 +26,7 @@
|
|||||||
#include <strlutil.h>
|
#include <strlutil.h>
|
||||||
|
|
||||||
#include "fortify.h"
|
#include "fortify.h"
|
||||||
#include "conman.h"
|
#include "sics.h"
|
||||||
#include "SCinter.h"
|
|
||||||
#include "nserver.h"
|
|
||||||
#include "obdes.h"
|
|
||||||
#include "network.h"
|
#include "network.h"
|
||||||
#include "interrupt.h"
|
#include "interrupt.h"
|
||||||
#include "status.h"
|
#include "status.h"
|
||||||
@ -40,8 +41,6 @@
|
|||||||
#define MAXINTERRUPT 7
|
#define MAXINTERRUPT 7
|
||||||
#define INTERUPTWAIT 5
|
#define INTERUPTWAIT 5
|
||||||
|
|
||||||
static mkChannel *IntPort = NULL;
|
|
||||||
static pTaskMan pTask = NULL;
|
|
||||||
/*----------------------------------------------------------------------------*/
|
/*----------------------------------------------------------------------------*/
|
||||||
static char *pIntText[] = {
|
static char *pIntText[] = {
|
||||||
"continue",
|
"continue",
|
||||||
@ -53,35 +52,6 @@ static char *pIntText[] = {
|
|||||||
"end",
|
"end",
|
||||||
NULL
|
NULL
|
||||||
};
|
};
|
||||||
|
|
||||||
/*---------------------------------------------------------------------------*/
|
|
||||||
int ServerSetupInterrupt(int iPort, pNetRead pNet, pTaskMan pTasker)
|
|
||||||
{
|
|
||||||
int i;
|
|
||||||
|
|
||||||
|
|
||||||
pTask = pTasker;
|
|
||||||
/* setup interrupt port */
|
|
||||||
IntPort = UDPOpen(iPort);
|
|
||||||
if (IntPort == NULL) {
|
|
||||||
return 0;
|
|
||||||
} else {
|
|
||||||
NetReadRegister(pNet, IntPort, udp, NULL);
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*--------------------------------------------------------------------------*/
|
|
||||||
void ServerStopInterrupt(void)
|
|
||||||
{
|
|
||||||
|
|
||||||
/* close the port */
|
|
||||||
if (IntPort) {
|
|
||||||
NETClosePort(IntPort);
|
|
||||||
free(IntPort);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*-------------------------------------------------------------------------*/
|
/*-------------------------------------------------------------------------*/
|
||||||
void SetInterrupt(int iCode)
|
void SetInterrupt(int iCode)
|
||||||
{
|
{
|
||||||
@ -89,7 +59,7 @@ void SetInterrupt(int iCode)
|
|||||||
|
|
||||||
iInt = iCode;
|
iInt = iCode;
|
||||||
|
|
||||||
TaskSignal(pTask, SICSINT, &iInt);
|
TaskSignal(pServ->pTasker, SICSINT, &iInt);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*--------------------------------------------------------------------------*/
|
/*--------------------------------------------------------------------------*/
|
||||||
|
10
make_gen
10
make_gen
@ -5,11 +5,13 @@
|
|||||||
# Markus Zolliker March 2003
|
# Markus Zolliker March 2003
|
||||||
#---------------------------------------------------------------------------
|
#---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
EPICSOBJ=epicsmotor.o
|
||||||
|
|
||||||
COBJ = Sclient.o network.o ifile.o intcli.o $(FORTIFYOBJ)
|
COBJ = Sclient.o network.o ifile.o intcli.o $(FORTIFYOBJ)
|
||||||
SOBJ = network.o ifile.o conman.o SCinter.o splitter.o passwd.o \
|
SOBJ = network.o ifile.o conman.o SCinter.o splitter.o passwd.o \
|
||||||
servlog.o sicvar.o nserver.o SICSmain.o motorlist.o\
|
servlog.o sicvar.o nserver.o SICSmain.o motorlist.o\
|
||||||
sicsexit.o costa.o task.o $(FORTIFYOBJ) testprot.o\
|
sicsexit.o costa.o task.o $(FORTIFYOBJ) testprot.o\
|
||||||
macro.o ofac.o obpar.o obdes.o drive.o status.o intserv.o \
|
macro.o ofac.o obpar.o obdes.o drive.o status.o intserv.o \
|
||||||
devexec.o mumo.o mumoconf.o selector.o selvar.o fupa.o lld.o \
|
devexec.o mumo.o mumoconf.o selector.o selvar.o fupa.o lld.o \
|
||||||
lld_blob.o strrepl.o lin2ang.o fomerge.o napi5.o napi4.o\
|
lld_blob.o strrepl.o lin2ang.o fomerge.o napi5.o napi4.o\
|
||||||
script.o o2t.o alias.o napi.o stringdict.o sdynar.o \
|
script.o o2t.o alias.o napi.o stringdict.o sdynar.o \
|
||||||
@ -42,13 +44,13 @@ SOBJ = network.o ifile.o conman.o SCinter.o splitter.o passwd.o \
|
|||||||
singlenb.o simindex.o simidx.o uselect.o singletas.o motorsec.o \
|
singlenb.o simindex.o simidx.o uselect.o singletas.o motorsec.o \
|
||||||
rwpuffer.o asynnet.o background.o countersec.o hdbtable.o velosec.o \
|
rwpuffer.o asynnet.o background.o countersec.o hdbtable.o velosec.o \
|
||||||
histmemsec.o sansbc.o sicsutil.o strlutil.o genbinprot.o trace.o\
|
histmemsec.o sansbc.o sicsutil.o strlutil.o genbinprot.o trace.o\
|
||||||
singlebinb.o taskobj.o sctcomtask.o
|
singlebinb.o taskobj.o sctcomtask.o tasmono.o
|
||||||
|
|
||||||
MOTOROBJ = motor.o simdriv.o
|
MOTOROBJ = motor.o simdriv.o
|
||||||
COUNTEROBJ = countdriv.o simcter.o counter.o
|
COUNTEROBJ = countdriv.o simcter.o counter.o
|
||||||
VELOOBJ = velo.o velosim.o
|
VELOOBJ = velo.o velosim.o
|
||||||
|
|
||||||
OBJ = $(SOBJ) $(MOTOROBJ) $(COUNTEROBJ) $(VELOOBJ) $(DIFIL) $(EXTRA)
|
OBJ = $(SOBJ) $(MOTOROBJ) $(COUNTEROBJ) $(VELOOBJ) $(DIFIL) $(EXTRA) $(EPICSOBJ)
|
||||||
|
|
||||||
.SUFFIXES:
|
.SUFFIXES:
|
||||||
.SUFFIXES: .tcl .htm .c .o .tc
|
.SUFFIXES: .tcl .htm .c .o .tc
|
||||||
@ -65,7 +67,7 @@ all: libmat libhlib libtecsl libpsi SICServer
|
|||||||
full: purge all
|
full: purge all
|
||||||
|
|
||||||
SICServer: $(OBJ) $(SUBLIBS)
|
SICServer: $(OBJ) $(SUBLIBS)
|
||||||
$(CC) -g -o SICServer $(OBJ) $(LIBS)
|
$(CC) $(DBG) -o SICServer $(OBJ) $(LIBS)
|
||||||
|
|
||||||
matrix/libmatrix.a: libmat
|
matrix/libmatrix.a: libmat
|
||||||
|
|
||||||
|
@ -11,19 +11,21 @@ NI= -DHAVENI
|
|||||||
NIOBJ= nigpib.o
|
NIOBJ= nigpib.o
|
||||||
NILIB=$(SINQDIR)/sl6/lib/cib.o
|
NILIB=$(SINQDIR)/sl6/lib/cib.o
|
||||||
|
|
||||||
|
EPICSLIBS=-L$(SINQDIR)/sl6/lib/linux-x86 -lezca -lca -lCom
|
||||||
|
|
||||||
include sllinux_def
|
include sllinux_def
|
||||||
|
|
||||||
CC = gcc
|
CC = gcc
|
||||||
CFLAGS = -I$(HDFROOT)/include -DNXXML -DHDF5 $(NI) \
|
CFLAGS = -I$(HDFROOT)/include -DNXXML -DHDF5 $(NI) \
|
||||||
-Ipsi/hardsup -I. -MMD \
|
-Ipsi/hardsup -I. -MMD \
|
||||||
-Werror -DCYGNUS -DNONINTF -g $(DFORTIFY) \
|
-Werror -DCYGNUS -DNONINTF $(DBG) $(DFORTIFY) \
|
||||||
-Wall -Wno-unused -Wunused-value -Wno-comment -Wno-switch
|
-Wall -Wno-unused -Wunused-value -Wno-comment -Wno-switch
|
||||||
|
|
||||||
BINTARGET = bin
|
BINTARGET = bin
|
||||||
EXTRA=nintf.o
|
EXTRA=nintf.o
|
||||||
SUBLIBS = psi/libpsi.a psi/hardsup/libhlib.a matrix/libmatrix.a \
|
SUBLIBS = psi/libpsi.a psi/hardsup/libhlib.a matrix/libmatrix.a \
|
||||||
psi/tecs/libtecsl.a
|
psi/tecs/libtecsl.a
|
||||||
LIBS = -L$(HDFROOT)/lib $(SUBLIBS) $(NILIB)\
|
LIBS = -L$(HDFROOT)/lib $(SUBLIBS) $(NILIB) $(EPICSLIBS) \
|
||||||
-ltcl $(HDFROOT)/lib/libhdf5.a \
|
-ltcl $(HDFROOT)/lib/libhdf5.a \
|
||||||
$(HDFROOT)/lib/libsz.a \
|
$(HDFROOT)/lib/libsz.a \
|
||||||
$(HDFROOT)/lib/libjson.a \
|
$(HDFROOT)/lib/libjson.a \
|
||||||
|
18
motor.c
18
motor.c
@ -992,6 +992,7 @@ int MotorCheckPosition(void *sulf, SConnection * pCon)
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
extern MotorDriver *MakePiPiezo(Tcl_Interp * pTcl, char *pArray);
|
extern MotorDriver *MakePiPiezo(Tcl_Interp * pTcl, char *pArray);
|
||||||
|
extern MotorDriver *epicsMakeMotorDriver(char *baseName);
|
||||||
|
|
||||||
int MotorCreate(SConnection * pCon, SicsInterp * pSics, void *pData,
|
int MotorCreate(SConnection * pCon, SicsInterp * pSics, void *pData,
|
||||||
int argc, char *argv[])
|
int argc, char *argv[])
|
||||||
@ -1052,6 +1053,23 @@ int MotorCreate(SConnection * pCon, SicsInterp * pSics, void *pData,
|
|||||||
SCWrite(pCon, pBueffel, eLogError);
|
SCWrite(pCon, pBueffel, eLogError);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
} else if (strcmp(argv[2], "epics") == 0) {
|
||||||
|
if(argc > 3){
|
||||||
|
pDriver = epicsMakeMotorDriver(argv[3]);
|
||||||
|
if (!pDriver) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
SCWrite(pCon,"ERROR: missing basename argument to create EPICS motor",eError);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
/* create the motor */
|
||||||
|
pNew = MotorInit("regress", argv[1], pDriver);
|
||||||
|
if (!pNew) {
|
||||||
|
snprintf(pBueffel,sizeof(pBueffel)-1, "Failure to create motor %s", argv[1]);
|
||||||
|
SCWrite(pCon, pBueffel, eLogError);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
site = getSite();
|
site = getSite();
|
||||||
if (site != NULL) {
|
if (site != NULL) {
|
||||||
|
@ -37,6 +37,7 @@ typedef struct {
|
|||||||
pICountable slaves[MAXSLAVE];
|
pICountable slaves[MAXSLAVE];
|
||||||
char *transferScript;
|
char *transferScript;
|
||||||
int nSlaves;
|
int nSlaves;
|
||||||
|
int checkSlaves;
|
||||||
} MultiCounter, *pMultiCounter;
|
} MultiCounter, *pMultiCounter;
|
||||||
/*--------------------------------------------------------------------------*/
|
/*--------------------------------------------------------------------------*/
|
||||||
static void KillMultiDriver(struct __COUNTER *data)
|
static void KillMultiDriver(struct __COUNTER *data)
|
||||||
@ -106,10 +107,12 @@ static int MMCCStart(void *pData, SConnection * pCon)
|
|||||||
pCount->isUpToDate = 0;
|
pCount->isUpToDate = 0;
|
||||||
pCount->tStart = time(NULL);
|
pCount->tStart = time(NULL);
|
||||||
InvokeCallBack(pCount->pCall, COUNTSTART, pCon);
|
InvokeCallBack(pCount->pCall, COUNTSTART, pCon);
|
||||||
|
self->checkSlaves = 0;
|
||||||
return OKOK;
|
return OKOK;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*-------------------------------------------------------------------------*/
|
/*-------------------------------------------------------------------------*/
|
||||||
|
|
||||||
static int MMCCStatus(void *pData, SConnection * pCon)
|
static int MMCCStatus(void *pData, SConnection * pCon)
|
||||||
{
|
{
|
||||||
int status, i;
|
int status, i;
|
||||||
@ -129,25 +132,46 @@ static int MMCCStatus(void *pData, SConnection * pCon)
|
|||||||
return HWFault;
|
return HWFault;
|
||||||
}
|
}
|
||||||
|
|
||||||
status = self->slaves[0]->CheckCountStatus(self->slaveData[0], pCon);
|
if(self->checkSlaves == 0) {
|
||||||
pMaster = (pCounter)self->slaveData[0];
|
status = self->slaves[0]->CheckCountStatus(self->slaveData[0], pCon);
|
||||||
pCount->pDriv->fLastCurrent = GetControlValue(pMaster);
|
if (status == HWIdle || status == HWFault) {
|
||||||
if (status == HWIdle || status == HWFault) {
|
/*
|
||||||
/*
|
stop counting on slaves when finished or when an error
|
||||||
stop counting on slaves when finished or when an error
|
occurred.
|
||||||
occurred.
|
*/
|
||||||
*/
|
MMCCHalt(pData);
|
||||||
InvokeCallBack(pCount->pCall, COUNTEND, pCon);
|
ReleaseCountLock(pCount->pCountInt);
|
||||||
MMCCHalt(pCount);
|
self->checkSlaves = 1;
|
||||||
}
|
status = HWBusy;
|
||||||
for (i = 1; i < MAXSLAVE; i++) {
|
|
||||||
if (self->slaves[i] != NULL) {
|
|
||||||
pDum = (pDummy) self->slaveData[i];
|
|
||||||
if (strcmp(pDum->pDescriptor->name, "HistMem") == 0) {
|
|
||||||
HistDirty((pHistMem) self->slaveData[i]);
|
|
||||||
}
|
|
||||||
ReleaseCountLock(self->slaves[i]);
|
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
/*
|
||||||
|
* wait for the detectors to report finish too. Otherwise, with the second
|
||||||
|
* generation HM data may not be fully transferred.
|
||||||
|
*/
|
||||||
|
for(i = 1; i < self->nSlaves; i++){
|
||||||
|
status = self->slaves[i]->CheckCountStatus(self->slaveData[i], pCon);
|
||||||
|
if(!(status == HWIdle || status == HWFault)){
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
Warning: this assumes that slaves 1 - MAXSLAVE are histogram memories.
|
||||||
|
If this assumption does not hold, change this code to check if this
|
||||||
|
is really a histogram memory.
|
||||||
|
*/
|
||||||
|
for (i = 1; i < self->nSlaves; i++) {
|
||||||
|
if (self->slaves[i] != NULL) {
|
||||||
|
pDum = (pDummy)self->slaveData[i];
|
||||||
|
if (strcmp(pDum->pDescriptor->name, "HistMem") == 0) {
|
||||||
|
HistDirty((pHistMem) self->slaveData[i]);
|
||||||
|
}
|
||||||
|
ReleaseCountLock(self->slaves[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
status = HWIdle;
|
||||||
|
InvokeCallBack(pCount->pCall, COUNTEND, pCon);
|
||||||
|
self->checkSlaves = 0;
|
||||||
}
|
}
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
19
nserver.c
19
nserver.c
@ -39,10 +39,6 @@
|
|||||||
#include "sicshipadaba.h"
|
#include "sicshipadaba.h"
|
||||||
#include "commandlog.h"
|
#include "commandlog.h"
|
||||||
|
|
||||||
int ServerSetupInterrupt(int iPort, pNetRead pNet, pTaskMan pTasker);
|
|
||||||
/*
|
|
||||||
configures a port for listening for interrupts
|
|
||||||
*/
|
|
||||||
|
|
||||||
extern void StopExit(void); /* in SICSmain.c */
|
extern void StopExit(void); /* in SICSmain.c */
|
||||||
|
|
||||||
@ -236,10 +232,6 @@ int InitServer(char *file, pServer * pServ)
|
|||||||
IFDeleteOptions(pSICSOptions);
|
IFDeleteOptions(pSICSOptions);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
iRet = ServerSetupInterrupt(iPort, pReader, self->pTasker);
|
|
||||||
if (!iRet) {
|
|
||||||
SCWrite(pCon, "WARNING: UDP interrupt port not initialized", eWarning);
|
|
||||||
}
|
|
||||||
/* install a secret fully priviledged entry point for ME */
|
/* install a secret fully priviledged entry point for ME */
|
||||||
AddUser("Achterbahn", "Kiel", usInternal);
|
AddUser("Achterbahn", "Kiel", usInternal);
|
||||||
|
|
||||||
@ -346,10 +338,6 @@ void StopServer(pServer self)
|
|||||||
/* remove the in memory password database */
|
/* remove the in memory password database */
|
||||||
KillPasswd();
|
KillPasswd();
|
||||||
|
|
||||||
|
|
||||||
/* close Interrupt system */
|
|
||||||
ServerStopInterrupt();
|
|
||||||
|
|
||||||
/* Remove Status Callback */
|
/* Remove Status Callback */
|
||||||
KillStatus(NULL);
|
KillStatus(NULL);
|
||||||
|
|
||||||
@ -481,6 +469,13 @@ int UserWait(SConnection * pCon, SicsInterp * pSics, void *pData,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
/*--------------------------------------------------------------------------*/
|
/*--------------------------------------------------------------------------*/
|
||||||
|
int UserYield(SConnection * pCon, SicsInterp * pSics, void *pData,
|
||||||
|
int argc, char *argv[])
|
||||||
|
{
|
||||||
|
TaskYield(pServ->pTasker);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
/*--------------------------------------------------------------------------*/
|
||||||
int SicsWait(long lTime)
|
int SicsWait(long lTime)
|
||||||
{
|
{
|
||||||
pTaskMan pTasker = NULL;
|
pTaskMan pTasker = NULL;
|
||||||
|
54
obdes.h
54
obdes.h
@ -1,5 +1,5 @@
|
|||||||
|
|
||||||
#line 385 "interface.w"
|
#line 398 "interface.w"
|
||||||
|
|
||||||
|
|
||||||
#line 29 "interface.w"
|
#line 29 "interface.w"
|
||||||
@ -25,19 +25,19 @@
|
|||||||
#include <ifile.h>
|
#include <ifile.h>
|
||||||
#include <hipadaba.h>
|
#include <hipadaba.h>
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
char *name;
|
char *name;
|
||||||
int (*SaveStatus) (void *self, char *name, FILE * fd);
|
int (*SaveStatus)(void *self, char *name,FILE *fd);
|
||||||
void *(*GetInterface) (void *self, int iInterfaceID);
|
void *(*GetInterface)(void *self, int iInterfaceID);
|
||||||
IPair *pKeys;
|
IPair *pKeys;
|
||||||
pHdb parNode;
|
pHdb parNode;
|
||||||
} ObjectDescriptor, *pObjectDescriptor;
|
} ObjectDescriptor, *pObjectDescriptor;
|
||||||
|
|
||||||
/*---------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------*/
|
||||||
pObjectDescriptor CreateDescriptor(char *name);
|
pObjectDescriptor CreateDescriptor(char *name);
|
||||||
void DeleteDescriptor(pObjectDescriptor self);
|
void DeleteDescriptor(pObjectDescriptor self);
|
||||||
pObjectDescriptor FindDescriptor(void *pData);
|
pObjectDescriptor FindDescriptor(void *pData);
|
||||||
|
|
||||||
/*============================================================================
|
/*============================================================================
|
||||||
Objects which do not carry data need a dummy descriptor. Otherwise
|
Objects which do not carry data need a dummy descriptor. Otherwise
|
||||||
drive or scan will protection fault when trying to drive something
|
drive or scan will protection fault when trying to drive something
|
||||||
@ -45,26 +45,26 @@ pObjectDescriptor FindDescriptor(void *pData);
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
pObjectDescriptor pDescriptor;
|
pObjectDescriptor pDescriptor;
|
||||||
} Dummy, *pDummy;
|
}Dummy, *pDummy;
|
||||||
|
|
||||||
|
|
||||||
|
pDummy CreateDummy(char *name);
|
||||||
|
void KillDummy(void *pData);
|
||||||
|
|
||||||
pDummy CreateDummy(char *name);
|
int iHasType(void *pData, char *Type);
|
||||||
void KillDummy(void *pData);
|
|
||||||
|
#endif
|
||||||
|
|
||||||
int iHasType(void *pData, char *Type);
|
#line 399 "interface.w"
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#line 386 "interface.w"
|
|
||||||
|
|
||||||
/*--------------------------------------------------------------------------*/
|
/*--------------------------------------------------------------------------*/
|
||||||
/* Additional properties used by the ANSTO site to provide more information
|
/* Additional properties used by the ANSTO site to provide more information
|
||||||
* about each object instance, especially devices.
|
* about each object instance, especially devices.
|
||||||
*/
|
*/
|
||||||
void SetDescriptorKey(pObjectDescriptor self, char *keyName, char *value);
|
void SetDescriptorKey(pObjectDescriptor self, char *keyName, char *value);
|
||||||
void SetDescriptorGroup(pObjectDescriptor self, char *group);
|
void SetDescriptorGroup(pObjectDescriptor self, char *group);
|
||||||
void SetDescriptorDescription(pObjectDescriptor self, char *description);
|
void SetDescriptorDescription(pObjectDescriptor self, char *description);
|
||||||
char *GetDescriptorKey(pObjectDescriptor self, char *keyName);
|
char * GetDescriptorKey(pObjectDescriptor self, char *keyName);
|
||||||
char *GetDescriptorGroup(pObjectDescriptor self);
|
char * GetDescriptorGroup(pObjectDescriptor self);
|
||||||
char *GetDescriptorDescription(pObjectDescriptor self);
|
char * GetDescriptorDescription(pObjectDescriptor self);
|
||||||
|
15
ofac.c
15
ofac.c
@ -17,6 +17,8 @@
|
|||||||
#include "site.h"
|
#include "site.h"
|
||||||
#include "sicshipadaba.h"
|
#include "sicshipadaba.h"
|
||||||
|
|
||||||
|
static unsigned int killStartupCommands = 1;
|
||||||
|
|
||||||
extern void DevExecInit(void); /* devexec.c */
|
extern void DevExecInit(void); /* devexec.c */
|
||||||
/*--------------------------------------------------------------------------*/
|
/*--------------------------------------------------------------------------*/
|
||||||
static void InitGeneral(void)
|
static void InitGeneral(void)
|
||||||
@ -44,6 +46,7 @@ static void InitGeneral(void)
|
|||||||
INIT(AddGenBinProtocoll);
|
INIT(AddGenBinProtocoll);
|
||||||
INIT(AddSyncedProt);
|
INIT(AddSyncedProt);
|
||||||
INIT(MakeTrace);
|
INIT(MakeTrace);
|
||||||
|
INIT(InitTaskOBJ);
|
||||||
INIT(SiteInit); /* site specific initializations */
|
INIT(SiteInit); /* site specific initializations */
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -111,6 +114,7 @@ static void InitIniCommands(SicsInterp * pInter)
|
|||||||
PCMD("TclReplaceDrivable", TclReplaceDrivable);
|
PCMD("TclReplaceDrivable", TclReplaceDrivable);
|
||||||
PCMD("transact", TransactAction);
|
PCMD("transact", TransactAction);
|
||||||
PCMD("wait", UserWait);
|
PCMD("wait", UserWait);
|
||||||
|
PCMD("yield", UserYield);
|
||||||
PCMD("checksum", CheckSum);
|
PCMD("checksum", CheckSum);
|
||||||
|
|
||||||
/* startup commands in alphabetic order */
|
/* startup commands in alphabetic order */
|
||||||
@ -169,7 +173,6 @@ static void InitIniCommands(SicsInterp * pInter)
|
|||||||
SCMD("SicsAlias", SicsAlias);
|
SCMD("SicsAlias", SicsAlias);
|
||||||
SCMD("SicsUser", PWSicsUser);
|
SCMD("SicsUser", PWSicsUser);
|
||||||
SCMD("TokenInit", TokenInit);
|
SCMD("TokenInit", TokenInit);
|
||||||
SCMD("MakeTask", TaskOBJFactory);
|
|
||||||
SCMD("UpdateFactory", UpdateFactory);
|
SCMD("UpdateFactory", UpdateFactory);
|
||||||
SCMD("VarMake", VarFactory);
|
SCMD("VarMake", VarFactory);
|
||||||
SCMD("VelocitySelector", VelSelFactory);
|
SCMD("VelocitySelector", VelSelFactory);
|
||||||
@ -229,7 +232,13 @@ int InitObjectCommands(pServer pServ, char *file)
|
|||||||
if (site != NULL && site->RemoveSiteCommands != NULL) {
|
if (site != NULL && site->RemoveSiteCommands != NULL) {
|
||||||
site->RemoveSiteCommands(pSics);
|
site->RemoveSiteCommands(pSics);
|
||||||
}
|
}
|
||||||
|
if(killStartupCommands){
|
||||||
RemoveStartupCommands();
|
RemoveStartupCommands();
|
||||||
|
}
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
/*---------------------------------------------------------------------------------*/
|
||||||
|
void KeepStartupCommands()
|
||||||
|
{
|
||||||
|
killStartupCommands = 0;
|
||||||
|
}
|
||||||
|
1
ofac.h
1
ofac.h
@ -21,5 +21,4 @@
|
|||||||
#include "sics.h"
|
#include "sics.h"
|
||||||
|
|
||||||
int InitObjectCommands(pServer pServ, char *file);
|
int InitObjectCommands(pServer pServ, char *file);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -24,6 +24,10 @@
|
|||||||
static char undef[] = "Undefined";
|
static char undef[] = "Undefined";
|
||||||
#define IDXFMT " %8.4f"
|
#define IDXFMT " %8.4f"
|
||||||
#define ANGFMT " %8.2f"
|
#define ANGFMT " %8.2f"
|
||||||
|
|
||||||
|
int CountTblCmd(pSICSOBJ self, SConnection *pCon, pHdb commandNode,
|
||||||
|
pHdb par[], int nPar); /* from hdbtable.c */
|
||||||
|
|
||||||
/*----------------------------------------------------------------------*/
|
/*----------------------------------------------------------------------*/
|
||||||
typedef struct {
|
typedef struct {
|
||||||
int idxCount;
|
int idxCount;
|
||||||
@ -549,6 +553,10 @@ pSICSOBJ CreateReflectionList(SConnection * pCon, SicsInterp * pSics,
|
|||||||
SetHdbProperty(cmd,"priv","user");
|
SetHdbProperty(cmd,"priv","user");
|
||||||
AddSICSHdbPar(cmd, "id", usUser, MakeHdbText(""));
|
AddSICSHdbPar(cmd, "id", usUser, MakeHdbText(""));
|
||||||
|
|
||||||
|
|
||||||
|
cmd = AddSICSHdbPar(pNew->objectNode, "count", usUser,
|
||||||
|
MakeSICSFunc(CountTblCmd));
|
||||||
|
|
||||||
AddCommand(pSics, name, InterInvokeSICSOBJ, KillSICSOBJ, pNew);
|
AddCommand(pSics, name, InterInvokeSICSOBJ, KillSICSOBJ, pNew);
|
||||||
return pNew;
|
return pNew;
|
||||||
}
|
}
|
||||||
|
2
scan.c
2
scan.c
@ -644,6 +644,7 @@ int DoScan(pScanData self, int iNP, int iMode, float fPreset,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
self->iActive = 1;
|
||||||
self->iNP = iNP;
|
self->iNP = iNP;
|
||||||
self->iMode = iMode;
|
self->iMode = iMode;
|
||||||
self->fPreset = fPreset;
|
self->fPreset = fPreset;
|
||||||
@ -661,7 +662,6 @@ int DoScan(pScanData self, int iNP, int iMode, float fPreset,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
self->iActive = 1;
|
|
||||||
iRet = ScanLoop(self);
|
iRet = ScanLoop(self);
|
||||||
ScriptScanFinish(self);
|
ScriptScanFinish(self);
|
||||||
InvokeCallBack(self->pCall, SCANEND, self);
|
InvokeCallBack(self->pCall, SCANEND, self);
|
||||||
|
@ -148,7 +148,7 @@ static long SCTDRIVSetValue(void *data, SConnection * pCon, float val)
|
|||||||
}
|
}
|
||||||
pPriv->pCon = SCCopyConnection(pCon);
|
pPriv->pCon = SCCopyConnection(pCon);
|
||||||
|
|
||||||
StopByData(pServ->pExecutor, data);
|
/* StopByData(pServ->pExecutor, data); */
|
||||||
|
|
||||||
v = MakeHdbFloat(val);
|
v = MakeHdbFloat(val);
|
||||||
SetHdbProperty(self->objectNode, "writestatus", "start");
|
SetHdbProperty(self->objectNode, "writestatus", "start");
|
||||||
|
@ -711,8 +711,13 @@ static int copyHM(pSICSData self, int argc, char *argv[],
|
|||||||
SCWrite(pCon, "ERROR: out of memory in SICSData copyhm", eError);
|
SCWrite(pCon, "ERROR: out of memory in SICSData copyhm", eError);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
GetHistogramDirect(pHist, pCon, 0, start, end, iData,
|
if(end > GetHistLength(pHist)){
|
||||||
|
GetHistogramDirect(pHist, pCon, 0, start, end, iData,
|
||||||
(end - start) * sizeof(int));
|
(end - start) * sizeof(int));
|
||||||
|
} else {
|
||||||
|
GetHistogram(pHist, pCon, 0, start, end, iData,
|
||||||
|
(end - start) * sizeof(int));
|
||||||
|
}
|
||||||
assignType(self, pos, pos + (end - start), INTTYPE);
|
assignType(self, pos, pos + (end - start), INTTYPE);
|
||||||
SCSendOK(pCon);
|
SCSendOK(pCon);
|
||||||
return 1;
|
return 1;
|
||||||
|
@ -284,7 +284,7 @@ static hdbCallbackReturn SetModeCB(pHdb node, void *userData,
|
|||||||
priv->mode = Bisecting;
|
priv->mode = Bisecting;
|
||||||
initializeSingleBisectingOrion(priv->diffractometer);
|
initializeSingleBisectingOrion(priv->diffractometer);
|
||||||
free(set->v->v.text);
|
free(set->v->v.text);
|
||||||
set->v->v.text = strdup("bi");
|
set->v->v.text = strdup("bio");
|
||||||
return hdbContinue;
|
return hdbContinue;
|
||||||
break;
|
break;
|
||||||
case NB:
|
case NB:
|
||||||
|
@ -10,4 +10,6 @@
|
|||||||
MFLAGS=-f makefile_linux$(DUMMY)
|
MFLAGS=-f makefile_linux$(DUMMY)
|
||||||
|
|
||||||
HDFROOT=/afs/psi.ch/project/sinq/sl6
|
HDFROOT=/afs/psi.ch/project/sinq/sl6
|
||||||
TCLINC=.
|
TCLINC=.
|
||||||
|
|
||||||
|
DBG= -g
|
627
tacov.c
627
tacov.c
@ -1,627 +0,0 @@
|
|||||||
/* tacov.f -- translated by f2c (version 20000817).
|
|
||||||
You must link the resulting object file with the libraries:
|
|
||||||
-lf2c -lm (in that order)
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "f2c.h"
|
|
||||||
|
|
||||||
/* Common Block Declarations */
|
|
||||||
|
|
||||||
struct {
|
|
||||||
integer inx;
|
|
||||||
real c1rx, c2rx, rmin, rmax, cl1r;
|
|
||||||
} curve_;
|
|
||||||
|
|
||||||
#define curve_1 curve_
|
|
||||||
|
|
||||||
/* Table of constant values */
|
|
||||||
|
|
||||||
static doublereal c_b7 = 1.;
|
|
||||||
static doublereal c_b9 = 360.;
|
|
||||||
|
|
||||||
/* ----------------------------------------------------------------------- */
|
|
||||||
/* FILE T_CONV */
|
|
||||||
/* SUBROUTINE T_CONV(EI,AKI,EF,AKF,QHKL,EN,HX,HY,HZ,IF1,IF2,LDK,LDH,LDF */
|
|
||||||
/* 1 LPA,DM,DA,HELM,F1H,F1V,F2H,F2V,F,IFX,ISS,ISM,ISA, */
|
|
||||||
/* 2 T_A,T_RM,T_ALM,LDRA,LDR_RM,LDR_ALM,P_IH,C_IH,IER) */
|
|
||||||
/* SUBROUTINE EX_CASE(DX,ISX,AKX,AX1,AX2,RX,ALX,IER) */
|
|
||||||
/* SUBROUTINE SAM_CASE(QT,QM,QS,AKI,AKF,AX3,AX4,ISS,IER) */
|
|
||||||
/* SUBROUTINE HELM_CASE(HX,HY,HZ,P_IH,AKI,AKF,A4,QM,HELM,IER) */
|
|
||||||
/* SUBROUTINE FLIP_CASE(IF1,IF2,P_IH,F1V,F1H,F2V,F2H,AKI,AKF,IER) */
|
|
||||||
/* ----------------------------------------------------------------------- */
|
|
||||||
/* Subroutine */ int t_conv__(real * ei, real * aki, real * ef, real * akf,
|
|
||||||
real *
|
|
||||||
qhkl, real * en, real * hx, real * hy,
|
|
||||||
real * hz, integer * if1, integer * if2,
|
|
||||||
logical * ldk, logical * ldh, logical * ldf,
|
|
||||||
logical * lpa, real * dm, real * da,
|
|
||||||
real * helm, real * f1h, real * f1v,
|
|
||||||
real * f2h, real * f2v, real * f,
|
|
||||||
integer * ifx, integer * iss, integer * ism,
|
|
||||||
integer * isa, real * t_a__, real * t_rm__,
|
|
||||||
real * t_alm__, real * qm, logical * ldra,
|
|
||||||
logical * ldr_rm__, logical * ldr_alm__,
|
|
||||||
real * p_ih__, real * c_ih__, integer * ier)
|
|
||||||
{
|
|
||||||
/* System generated locals */
|
|
||||||
doublereal d__1;
|
|
||||||
|
|
||||||
/* Builtin functions */
|
|
||||||
double sqrt(doublereal);
|
|
||||||
|
|
||||||
/* Local variables */
|
|
||||||
static doublereal edef[2], dakf, daki;
|
|
||||||
static integer imod;
|
|
||||||
extern /* Subroutine */ int sam_case__(doublereal *, doublereal *,
|
|
||||||
doublereal *, doublereal *,
|
|
||||||
doublereal *, doublereal *,
|
|
||||||
doublereal *, integer *,
|
|
||||||
integer *);
|
|
||||||
static integer i__;
|
|
||||||
static doublereal akdef[2];
|
|
||||||
extern /* Subroutine */ int helm_case__(real *, real *, real *, real *,
|
|
||||||
real *, real *, real *,
|
|
||||||
doublereal *, real *, real *,
|
|
||||||
integer *);
|
|
||||||
static doublereal dqhkl[3];
|
|
||||||
extern /* Subroutine */ int flip_case__(integer *, integer *, real *,
|
|
||||||
real *, real *, real *, real *,
|
|
||||||
real *, real *, integer *);
|
|
||||||
static logical lmoan[2];
|
|
||||||
static doublereal a1, a2, a3, a4, a5, a6;
|
|
||||||
static integer id;
|
|
||||||
static doublereal ra;
|
|
||||||
extern /* Subroutine */ int rl2spv_(doublereal *, doublereal *,
|
|
||||||
doublereal *, doublereal *,
|
|
||||||
integer *);
|
|
||||||
static integer iq;
|
|
||||||
static doublereal rm;
|
|
||||||
static logical lqhkle;
|
|
||||||
extern /* Subroutine */ int erreso_(integer *, integer *);
|
|
||||||
static doublereal dda, ala, def, dei, ddm, alm, dqm;
|
|
||||||
extern /* Subroutine */ int ex_case__(doublereal *, integer *, doublereal
|
|
||||||
*, doublereal *, doublereal *,
|
|
||||||
doublereal *, doublereal *,
|
|
||||||
integer *);
|
|
||||||
static doublereal dqt[3], dqs;
|
|
||||||
|
|
||||||
/* ----------------------------------------------------------------------- */
|
|
||||||
|
|
||||||
/* INPUT */
|
|
||||||
/* EI,AKI,EF,AKF,QHKL,EN,HX,HY,HZ : POTENTIAL TARGETS */
|
|
||||||
/* IF1,IF2 Status of flippers On (1) Off (0) */
|
|
||||||
/* LDK(8) LOGICAL INDICATING IF (ENERGY,K OR Q) ARE DRIVEN */
|
|
||||||
/* LDH,LDF LOGICAL INDICATING IF (HX,HY,HZ) OR (F1,F2) ARE DRIVEN */
|
|
||||||
|
|
||||||
/* configuration of the machine */
|
|
||||||
/* LPA LOGICAL TRUE IF MACHINE IN POLARIZATION MODE */
|
|
||||||
/* DM,DA,HELM,F1H,F1V,F2H,F2V,F,IFX,ISS,ISM,ISA,QM (F ENERGY UNIT) */
|
|
||||||
|
|
||||||
/* OUTPUT */
|
|
||||||
/* T_A TARGETS OF ANGLES A1-A6 */
|
|
||||||
/* T_RM,T_ALM TARGETS OF RM ,LM */
|
|
||||||
/* QM TARGETS OF QM */
|
|
||||||
/* LDRA LOGICAL INDICATING WHICH ANGLES ARE TO BE DRIVEN */
|
|
||||||
/* LDR_RM,LDR_ALM LOGICAL INDICATING IF RM OR ALM ARE TO BE DRIVEN */
|
|
||||||
/* P_IH TARGETS OF CURRENTS FOR FLIPPERS AND HELMOTZ (8 CURRENTS) */
|
|
||||||
/* C_IH CONVERSION FACTORS FOR HELMOTZ (4 CURRENTS) */
|
|
||||||
|
|
||||||
/* SPECIAL OUTPUTS */
|
|
||||||
/* TARGET OF EI(EF) IS UPDATED IS KI(KF) IS DRIVEN */
|
|
||||||
/* TARGET OF VARIABLE ENERGY IS UPDATED IF EN IS DRIVEN */
|
|
||||||
/* ----------------------------------------------------------------------- */
|
|
||||||
/* ----------------------------------------------------------------------- */
|
|
||||||
/* PASSED PARAMETERS */
|
|
||||||
/* ----------------------------------------------------------------------- */
|
|
||||||
/* LOCAL VARIABLES */
|
|
||||||
|
|
||||||
/* ----------------------------------------------------------------------- */
|
|
||||||
/* SET UP */
|
|
||||||
/* IMOD INDEX FOR ERROR TREATMENAT BY ERRESO */
|
|
||||||
/* LDQHKLE : LOGICAL INDICATING THAT WE ARE DEALING WITH A MOVE */
|
|
||||||
/* IN RECIPROCICAL SPACE */
|
|
||||||
/* WE REMAP THE ENERGY PB AS FIXED ENERGY IN EDEF(1) */
|
|
||||||
/* AND VARIABLE ENERGY IN EDEF(2) */
|
|
||||||
/* IF ISA IS NUL SET IFX TO 1 AND PUT EF,KF, EQUAL TO EI,KI */
|
|
||||||
|
|
||||||
/* Parameter adjustments */
|
|
||||||
--c_ih__;
|
|
||||||
--p_ih__;
|
|
||||||
--ldra;
|
|
||||||
--t_a__;
|
|
||||||
--ldk;
|
|
||||||
--qhkl;
|
|
||||||
|
|
||||||
/* Function Body */
|
|
||||||
imod = 3;
|
|
||||||
ddm = *dm;
|
|
||||||
dda = *da;
|
|
||||||
for (i__ = 1; i__ <= 2; ++i__) {
|
|
||||||
lmoan[i__ - 1] = FALSE_;
|
|
||||||
}
|
|
||||||
lqhkle = FALSE_;
|
|
||||||
for (iq = 5; iq <= 8; ++iq) {
|
|
||||||
lqhkle = lqhkle || ldk[iq];
|
|
||||||
}
|
|
||||||
daki = *aki;
|
|
||||||
dakf = *akf;
|
|
||||||
if (*isa == 0) {
|
|
||||||
*ifx = 1;
|
|
||||||
}
|
|
||||||
edef[*ifx - 1] = *ei;
|
|
||||||
akdef[*ifx - 1] = *aki;
|
|
||||||
edef[3 - *ifx - 1] = *ef;
|
|
||||||
akdef[3 - *ifx - 1] = *akf;
|
|
||||||
if (*isa == 0) {
|
|
||||||
edef[1] = edef[0];
|
|
||||||
akdef[1] = akdef[0];
|
|
||||||
ldk[3] = TRUE_;
|
|
||||||
ldk[4] = TRUE_;
|
|
||||||
t_a__[5] = 0.f;
|
|
||||||
t_a__[6] = 0.f;
|
|
||||||
ldra[5] = TRUE_;
|
|
||||||
ldra[6] = TRUE_;
|
|
||||||
}
|
|
||||||
/* ----------------------------------------------------------------------- */
|
|
||||||
/* FIRST TAKE IN ACCOUNT THE FIXED ENERGY PB */
|
|
||||||
|
|
||||||
if (ldk[(*ifx << 1) - 1] || ldk[*ifx * 2]) {
|
|
||||||
lmoan[*ifx - 1] = TRUE_;
|
|
||||||
if (ldk[(*ifx << 1) - 1]) {
|
|
||||||
*ier = 1;
|
|
||||||
if (edef[0] < .1) {
|
|
||||||
goto L999;
|
|
||||||
}
|
|
||||||
*ier = 0;
|
|
||||||
akdef[0] = sqrt(edef[0] / *f);
|
|
||||||
} else {
|
|
||||||
*ier = 1;
|
|
||||||
if (akdef[0] < .1) {
|
|
||||||
goto L999;
|
|
||||||
}
|
|
||||||
*ier = 0;
|
|
||||||
/* Computing 2nd power */
|
|
||||||
d__1 = akdef[0];
|
|
||||||
edef[0] = *f * (d__1 * d__1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
/* ----------------------------------------------------------------------- */
|
|
||||||
/* NOW TAKE IN ACCOUNT THE VARIABLE ENERGY PB */
|
|
||||||
/* VARIABLE ENERGUY IS DRIVEN EITHER EXPLICITLY */
|
|
||||||
/* E.G. BY DRIVING EI OR KI WITH IFX=2 */
|
|
||||||
/* ( AND WE MUST CALCULATE EN FROM EVAR) */
|
|
||||||
/* THE RULE IS : EI=EF+EN : EN IS THE ENERGY LOSS OF NEUTRONS */
|
|
||||||
/* OR ENERGY GAIN OF SAMPLE */
|
|
||||||
/* OR IMPLICITLY BY DRIVING THE TRANSFERED ENERGY EN */
|
|
||||||
/* ( AND WE MUST CALCULATE EVAR FROM EN) */
|
|
||||||
/* IF KI IS CONSTANT USE THE CURRENT VALUE CONTAINED IN POSN ARRAY */
|
|
||||||
/* TO CALCULATE THE NON-"CONSTANT" K. */
|
|
||||||
/* IF KF IS CONSTANT USE ALWAYS THE VALUE IN TARGET AND */
|
|
||||||
/* DO A DRIVE OF KF TO KEEP A5/A6 IN RIGHT POSITION */
|
|
||||||
|
|
||||||
if (ldk[5 - (*ifx << 1)] || ldk[6 - (*ifx << 1)]) {
|
|
||||||
lmoan[3 - *ifx - 1] = TRUE_;
|
|
||||||
if (ldk[5 - (*ifx << 1)]) {
|
|
||||||
*ier = 1;
|
|
||||||
if (edef[1] < 1e-4) {
|
|
||||||
goto L999;
|
|
||||||
}
|
|
||||||
*ier = 0;
|
|
||||||
akdef[1] = sqrt(edef[1] / *f);
|
|
||||||
} else {
|
|
||||||
*ier = 1;
|
|
||||||
if (akdef[1] < 1e-4) {
|
|
||||||
goto L999;
|
|
||||||
}
|
|
||||||
*ier = 0;
|
|
||||||
/* Computing 2nd power */
|
|
||||||
d__1 = akdef[1];
|
|
||||||
edef[1] = *f * (d__1 * d__1);
|
|
||||||
}
|
|
||||||
*en = (3 - (*ifx << 1)) * (edef[0] - edef[1]);
|
|
||||||
} else if (lqhkle) {
|
|
||||||
lmoan[3 - *ifx - 1] = TRUE_;
|
|
||||||
edef[1] = edef[0] + ((*ifx << 1) - 3) * *en;
|
|
||||||
*ier = 1;
|
|
||||||
if (edef[1] < 1e-4) {
|
|
||||||
goto L999;
|
|
||||||
}
|
|
||||||
*ier = 0;
|
|
||||||
akdef[1] = sqrt(edef[1] / *f);
|
|
||||||
}
|
|
||||||
/* ----------------------------------------------------------------------- */
|
|
||||||
/* CALCULATE MONOCHROMATOR AND ANALYSER ANGLES */
|
|
||||||
|
|
||||||
if (lmoan[0]) {
|
|
||||||
dei = edef[*ifx - 1];
|
|
||||||
daki = akdef[*ifx - 1];
|
|
||||||
ex_case__(&ddm, ism, &daki, &a1, &a2, &rm, &alm, ier);
|
|
||||||
if (*ier == 0) {
|
|
||||||
*aki = daki;
|
|
||||||
*ei = dei;
|
|
||||||
t_a__[1] = a1;
|
|
||||||
t_a__[2] = a2;
|
|
||||||
*t_rm__ = rm;
|
|
||||||
*t_alm__ = alm;
|
|
||||||
ldra[1] = TRUE_;
|
|
||||||
ldra[2] = TRUE_;
|
|
||||||
*ldr_rm__ = TRUE_;
|
|
||||||
*ldr_alm__ = TRUE_;
|
|
||||||
} else {
|
|
||||||
goto L999;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (lmoan[1]) {
|
|
||||||
def = edef[3 - *ifx - 1];
|
|
||||||
dakf = akdef[3 - *ifx - 1];
|
|
||||||
ex_case__(&dda, isa, &dakf, &a5, &a6, &ra, &ala, ier);
|
|
||||||
if (*ier == 0) {
|
|
||||||
*akf = dakf;
|
|
||||||
*ef = def;
|
|
||||||
t_a__[5] = a5;
|
|
||||||
t_a__[6] = a6;
|
|
||||||
ldra[5] = TRUE_;
|
|
||||||
ldra[6] = TRUE_;
|
|
||||||
} else {
|
|
||||||
goto L999;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
/* ----------------------------------------------------------------------- */
|
|
||||||
/* USE (QH,QK,QL) TO CALCULATE A3 AND A4 */
|
|
||||||
/* CALCULATE Q1 AND Q2 IN SCATTERING PLANE */
|
|
||||||
|
|
||||||
imod = 2;
|
|
||||||
if (lqhkle) {
|
|
||||||
for (id = 1; id <= 3; ++id) {
|
|
||||||
dqhkl[id - 1] = qhkl[id];
|
|
||||||
}
|
|
||||||
rl2spv_(dqhkl, dqt, &dqm, &dqs, ier);
|
|
||||||
if (*ier != 0) {
|
|
||||||
goto L999;
|
|
||||||
}
|
|
||||||
sam_case__(dqt, &dqm, &dqs, &daki, &dakf, &a3, &a4, iss, ier);
|
|
||||||
if (*ier == 0) {
|
|
||||||
t_a__[3] = a3;
|
|
||||||
t_a__[4] = a4;
|
|
||||||
ldra[3] = TRUE_;
|
|
||||||
ldra[4] = TRUE_;
|
|
||||||
*qm = dqm;
|
|
||||||
} else {
|
|
||||||
goto L999;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
/* ----------------------------------------------------------------------- */
|
|
||||||
/* DEAL WITH FLIPPERS AND HELMOTZ COILS IF LPA */
|
|
||||||
|
|
||||||
if (*lpa && (lmoan[0] || lmoan[1])) {
|
|
||||||
if (*ldf) {
|
|
||||||
flip_case__(if1, if2, &p_ih__[1], f1v, f1h, f2v, f2h, aki, akf, ier);
|
|
||||||
}
|
|
||||||
if (*ldh) {
|
|
||||||
helm_case__(hx, hy, hz, &p_ih__[1], &c_ih__[1], aki, akf, &a4, qm,
|
|
||||||
helm, ier);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
/* ----------------------------------------------------------------------- */
|
|
||||||
L999:
|
|
||||||
if (*ier != 0) {
|
|
||||||
erreso_(&imod, ier);
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
} /* t_conv__ */
|
|
||||||
|
|
||||||
/* Subroutine */ int ex_case__(doublereal * dx, integer * isx,
|
|
||||||
doublereal * akx,
|
|
||||||
doublereal * ax1, doublereal * ax2,
|
|
||||||
doublereal * rx, doublereal * alx,
|
|
||||||
integer * ier)
|
|
||||||
{
|
|
||||||
/* System generated locals */
|
|
||||||
doublereal d__1, d__2;
|
|
||||||
|
|
||||||
/* Builtin functions */
|
|
||||||
double asin(doublereal), sin(doublereal), cos(doublereal),
|
|
||||||
sqrt(doublereal);
|
|
||||||
|
|
||||||
/* Local variables */
|
|
||||||
static doublereal dcl1r, dc1rx, dc2rx, drmin, drmax, arg;
|
|
||||||
|
|
||||||
/* ----------------------------------------------------------------------- */
|
|
||||||
/* CALCULATE ANGLES ON MONO/ANALYSER */
|
|
||||||
/* CALCULATE AX1 AX2 */
|
|
||||||
/* CALCULATE RX LX MONO CURVATURE AND LM FOR IN8 */
|
|
||||||
|
|
||||||
/* INPUT */
|
|
||||||
/* DX D-SPACINGS */
|
|
||||||
/* ISX SENS OF SCATTERING ON CRYSTAL */
|
|
||||||
/* AKX TARGET OF MOMENTUM */
|
|
||||||
/* OUTPUT */
|
|
||||||
/* AX1 AX2 THETA 2*THETA ANGLES */
|
|
||||||
/* RX MONO OR ANALYSER CURVATURE */
|
|
||||||
/* ALX SPECIAL TRANSLATION FOR IN8 */
|
|
||||||
/* IER */
|
|
||||||
/* 1 ' KI OR KF CANNOT BE OBTAINED CHECK D-SPACINGS', */
|
|
||||||
/* 2 ' KI OR KF TOO SMALL', */
|
|
||||||
/* 3 ' KI OR KF TOO BIG', */
|
|
||||||
|
|
||||||
/* ----------------------------------------------------------------------- */
|
|
||||||
/* Values of parameters */
|
|
||||||
|
|
||||||
/* INX=1 IN8 , INX=0 others instruments */
|
|
||||||
/* C1RX C2RX constants values to calculate RM on all instruments */
|
|
||||||
/* RMIN, RMAX min max on RNM */
|
|
||||||
/* CL1R constant value to calculate LM for IN8 */
|
|
||||||
|
|
||||||
/* ----------------------------------------------------------------------- */
|
|
||||||
/* ----------------------------------------------------------------------- */
|
|
||||||
/* PASSED PARAMETERS */
|
|
||||||
/* ----------------------------------------------------------------------- */
|
|
||||||
/* LOCAL VAR */
|
|
||||||
/* ----------------------------------------------------------------------- */
|
|
||||||
/* INIT AND TEST */
|
|
||||||
|
|
||||||
*ier = 0;
|
|
||||||
dc1rx = curve_1.c1rx;
|
|
||||||
dc2rx = curve_1.c2rx;
|
|
||||||
drmin = curve_1.rmin;
|
|
||||||
drmax = curve_1.rmax;
|
|
||||||
dcl1r = curve_1.cl1r;
|
|
||||||
if (*dx < .1f) {
|
|
||||||
*ier = 1;
|
|
||||||
}
|
|
||||||
if (*akx < .1f) {
|
|
||||||
*ier = 2;
|
|
||||||
}
|
|
||||||
arg = 3.1415926535897932384626433832795f / (*dx * *akx);
|
|
||||||
if (abs(arg) > 1.f) {
|
|
||||||
*ier = 3;
|
|
||||||
}
|
|
||||||
if (*ier != 0) {
|
|
||||||
goto L999;
|
|
||||||
}
|
|
||||||
/* ----------------------------------------------------------------------- */
|
|
||||||
/* CALCULATION OF THE TWO ANGLES */
|
|
||||||
|
|
||||||
*ax1 = asin(arg) * *isx * 57.29577951308232087679815481410517f;
|
|
||||||
*ax2 = *ax1 * 2.;
|
|
||||||
/* ----------------------------------------------------------------------- */
|
|
||||||
/* CALCULATION OF MONO CURVATURE RM OR ANALYSER CURVATURE RA */
|
|
||||||
/* STANDARD LAW IS C1RX+C2RX/SIN(A1/RD) */
|
|
||||||
/* C1RX AND C2RX ARE CONSTANTS DEPENDING ON MONO AND MACHINES */
|
|
||||||
|
|
||||||
/* C1RX=.47 */
|
|
||||||
/* C2RX=.244 */
|
|
||||||
/* RMIN=0. */
|
|
||||||
/* RMAX=20. */
|
|
||||||
/* IN1/IN3/IN12/IN14/IN20 CASE */
|
|
||||||
if (curve_1.inx == 0) {
|
|
||||||
/* Computing MIN */
|
|
||||||
/* Computing MAX */
|
|
||||||
d__2 = dc1rx + dc2rx / sin(abs(*ax1) /
|
|
||||||
57.29577951308232087679815481410517f);
|
|
||||||
d__1 = max(d__2, drmin);
|
|
||||||
*rx = min(d__1, drmax);
|
|
||||||
} else {
|
|
||||||
/* IN8 CASE */
|
|
||||||
*alx =
|
|
||||||
dcl1r / sin(*ax2 / 57.29577951308232087679815481410517f) *
|
|
||||||
cos(*ax2 / 57.29577951308232087679815481410517f);
|
|
||||||
*rx = dc2rx * sqrt(sin(*ax2 / 57.29577951308232087679815481410517f))
|
|
||||||
- dc1rx;
|
|
||||||
}
|
|
||||||
/* ----------------------------------------------------------------------- */
|
|
||||||
L999:
|
|
||||||
return 0;
|
|
||||||
} /* ex_case__ */
|
|
||||||
|
|
||||||
/* ========================================================================= */
|
|
||||||
/* Subroutine */ int sam_case__(doublereal * qt, doublereal * qm,
|
|
||||||
doublereal *
|
|
||||||
qs, doublereal * aki, doublereal * akf,
|
|
||||||
doublereal * ax3, doublereal * ax4,
|
|
||||||
integer * iss, integer * ier)
|
|
||||||
{
|
|
||||||
/* System generated locals */
|
|
||||||
doublereal d__1, d__2;
|
|
||||||
|
|
||||||
/* Builtin functions */
|
|
||||||
double acos(doublereal), atan2(doublereal, doublereal), d_sign(doublereal
|
|
||||||
*,
|
|
||||||
doublereal
|
|
||||||
*),
|
|
||||||
d_mod(doublereal *, doublereal *);
|
|
||||||
|
|
||||||
/* Local variables */
|
|
||||||
static doublereal arg, sax3;
|
|
||||||
|
|
||||||
/* ----------------------------------------------------------------------- */
|
|
||||||
/* DEAL WITH SAMPLE ANGLES CALCULATION FROM Q VERTOR IN C-N PLANE */
|
|
||||||
/* CALCULATE A3 AND A4 */
|
|
||||||
/* INPUT */
|
|
||||||
/* QT Q-VECTOR IN SCATTERING PLANE */
|
|
||||||
/* QM,QS Q MODULUS AND QMODULUS SQUARED */
|
|
||||||
/* AKI,AKF MOMEMTA ON MONO AND ANYLSER */
|
|
||||||
/* ISS SENS OF SCATTERING ON SAMPLE */
|
|
||||||
|
|
||||||
/* OUTPUT */
|
|
||||||
/* AX3 AX4 ANGLES ON SAMPLES */
|
|
||||||
/* IER SAME ERROR AS RL2SPV */
|
|
||||||
/* IER */
|
|
||||||
/* 1 ' MATRIX S NOT OK', */
|
|
||||||
/* 2 ' Q NOT IN SCATTERING PLANE', */
|
|
||||||
/* 3 ' Q MODULUS TOO SMALL', */
|
|
||||||
/* 4 ' Q MODULUS TOO BIG', */
|
|
||||||
/* ----------------------------------------------------------------------- */
|
|
||||||
/* ----------------------------------------------------------------------- */
|
|
||||||
/* PASSED PARAMETERS */
|
|
||||||
/* ----------------------------------------------------------------------- */
|
|
||||||
/* INIT AND TEST */
|
|
||||||
|
|
||||||
/* Parameter adjustments */
|
|
||||||
--qt;
|
|
||||||
|
|
||||||
/* Function Body */
|
|
||||||
*ier = 0;
|
|
||||||
if (abs(*qs) < 1e-6 || abs(*qm) < .001) {
|
|
||||||
*ier = 3;
|
|
||||||
goto L999;
|
|
||||||
}
|
|
||||||
/* ----------------------------------------------------------------------- */
|
|
||||||
/* CALCULATE A3 AND MOVE IT INTHE -180 ,+180 INTERVAL */
|
|
||||||
|
|
||||||
/* Computing 2nd power */
|
|
||||||
d__1 = *aki;
|
|
||||||
/* Computing 2nd power */
|
|
||||||
d__2 = *akf;
|
|
||||||
arg = (d__1 * d__1 + d__2 * d__2 - *qs) / (*aki * 2. * *akf);
|
|
||||||
if (abs(arg) > 1.) {
|
|
||||||
*ier = 4;
|
|
||||||
goto L999;
|
|
||||||
} else {
|
|
||||||
*ax4 = acos(arg) * *iss * 57.29577951308232087679815481410517;
|
|
||||||
}
|
|
||||||
/* Computing 2nd power */
|
|
||||||
d__1 = *akf;
|
|
||||||
/* Computing 2nd power */
|
|
||||||
d__2 = *aki;
|
|
||||||
*ax3 =
|
|
||||||
(-atan2(qt[2], qt[1]) -
|
|
||||||
acos((d__1 * d__1 - *qs -
|
|
||||||
d__2 * d__2) / (*qm * -2. * *aki)) * d_sign(&c_b7,
|
|
||||||
ax4)) *
|
|
||||||
57.29577951308232087679815481410517;
|
|
||||||
sax3 = d_sign(&c_b7, ax3);
|
|
||||||
d__1 = *ax3 + sax3 * 180.;
|
|
||||||
*ax3 = d_mod(&d__1, &c_b9) - sax3 * 180.;
|
|
||||||
|
|
||||||
/* IF(LPLATE) AX3=-ATAN(SIN(AX4/RD)/(LSA*TAN(AX5/RD)/(ALMS*C */
|
|
||||||
/* 1 TAN(AX1/RD))*(AKI/KF)**2-COS(AX4/RD)))*RD !PLATE FOCALIZATION OPTION */
|
|
||||||
/* IF(AXX3.GT.180.D0) AX3=AX3-360.D0 */
|
|
||||||
/* IF( A3.LT.-180.D0) AX3=AX3+360.D0 */
|
|
||||||
/* IF(LPLATE.AND.A3.GT.0.0) AX3=AX3-180 */
|
|
||||||
/* C----------------------------------------------------------------------- */
|
|
||||||
L999:
|
|
||||||
return 0;
|
|
||||||
} /* sam_case__ */
|
|
||||||
|
|
||||||
/* ============================================================================ */
|
|
||||||
/* Subroutine */ int helm_case__(real * hx, real * hy, real * hz,
|
|
||||||
real * t_ih__,
|
|
||||||
real * c_ih__, real * aki, real * akf,
|
|
||||||
doublereal * a4, real * qm, real * helm,
|
|
||||||
integer * ier)
|
|
||||||
{
|
|
||||||
/* System generated locals */
|
|
||||||
real r__1, r__2;
|
|
||||||
|
|
||||||
/* Builtin functions */
|
|
||||||
double cos(doublereal), sin(doublereal), atan2(doublereal, doublereal),
|
|
||||||
sqrt(doublereal);
|
|
||||||
|
|
||||||
/* Local variables */
|
|
||||||
static real hrad, hdir, qpar, hdir2, qperp;
|
|
||||||
static integer ic;
|
|
||||||
static real phi;
|
|
||||||
|
|
||||||
/* ----------------------------------------------------------------------- */
|
|
||||||
/* DEAL WITH HELMOTZ COIL FIELD CALCULATIONS */
|
|
||||||
/* CALCULATE HX HY HZ */
|
|
||||||
/* ----------------------------------------------------------------------- */
|
|
||||||
/* ----------------------------------------------------------------------- */
|
|
||||||
/* PASSED PARAMETERS */
|
|
||||||
/* ----------------------------------------------------------------------- */
|
|
||||||
/* INIT AND TEST */
|
|
||||||
|
|
||||||
/* Parameter adjustments */
|
|
||||||
--c_ih__;
|
|
||||||
--t_ih__;
|
|
||||||
|
|
||||||
/* Function Body */
|
|
||||||
*ier = 1;
|
|
||||||
if (dabs(*qm) < 1e-4f) {
|
|
||||||
goto L999;
|
|
||||||
}
|
|
||||||
*ier = 0;
|
|
||||||
for (ic = 1; ic <= 4; ++ic) {
|
|
||||||
if (c_ih__[ic] < 1e-4f) {
|
|
||||||
*ier = 2;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (*ier != 0) {
|
|
||||||
goto L999;
|
|
||||||
}
|
|
||||||
/* ----------------------------------------------------------------------- */
|
|
||||||
/* CALCULATE MODULE AND ANGLES OF IN PLANE FIELD H */
|
|
||||||
/* PHI !ANGLE BETWEEN Q AND KI */
|
|
||||||
/* HRAD !RADIAL COMP. OF H */
|
|
||||||
/* HDIR !DIRECTION OF H (IN RADIANS) */
|
|
||||||
/* HDIR2 !ANGLE BETWEEN FIELD AND AXE OF COIL 1 */
|
|
||||||
|
|
||||||
qpar = *aki - *akf * cos(*a4 / 57.29577951308232087679815481410517f);
|
|
||||||
qperp = *akf * sin(*a4 / 57.29577951308232087679815481410517f);
|
|
||||||
phi = atan2(qpar, qperp);
|
|
||||||
/* Computing 2nd power */
|
|
||||||
r__1 = *hx;
|
|
||||||
/* Computing 2nd power */
|
|
||||||
r__2 = *hy;
|
|
||||||
hrad = sqrt(r__1 * r__1 + r__2 * r__2);
|
|
||||||
if (hrad > 1e-4f) {
|
|
||||||
hdir = atan2(*hy, *hx);
|
|
||||||
}
|
|
||||||
hdir2 = phi + hdir + *helm / 57.29577951308232087679815481410517f +
|
|
||||||
1.5707963267948966f;
|
|
||||||
/* ----------------------------------------------------------------------- */
|
|
||||||
/* !CALC CURRENTS */
|
|
||||||
/* !POSITION OF PSP FOR COIL I */
|
|
||||||
|
|
||||||
for (ic = 1; ic <= 3; ++ic) {
|
|
||||||
t_ih__[ic + 4] = cos(hdir2 + (ic - 1) * 2.f *
|
|
||||||
3.1415926535897932384626433832795f / 3.f) * hrad /
|
|
||||||
c_ih__[ic]
|
|
||||||
/ 1.5f;
|
|
||||||
}
|
|
||||||
t_ih__[8] = *hz / c_ih__[4];
|
|
||||||
/* ----------------------------------------------------------------------- */
|
|
||||||
L999:
|
|
||||||
return 0;
|
|
||||||
} /* helm_case__ */
|
|
||||||
|
|
||||||
/* Subroutine */ int flip_case__(integer * if1, integer * if2,
|
|
||||||
real * t_ih__,
|
|
||||||
real * f1v, real * f1h, real * f2v,
|
|
||||||
real * f2h, real * aki, real * akf,
|
|
||||||
integer * ier)
|
|
||||||
{
|
|
||||||
/* ----------------------------------------------------------------------- */
|
|
||||||
/* DEAL WITH FLIPPER COIL CALCULATIONS */
|
|
||||||
/* CALCULATE P_IF CURRENTS FOR THE TWO FLIPPERS */
|
|
||||||
/* ----------------------------------------------------------------------- */
|
|
||||||
/* PASSED PARAMETERS */
|
|
||||||
/* ----------------------------------------------------------------------- */
|
|
||||||
/* INIT AND TEST */
|
|
||||||
|
|
||||||
/* Parameter adjustments */
|
|
||||||
--t_ih__;
|
|
||||||
|
|
||||||
/* Function Body */
|
|
||||||
*ier = 0;
|
|
||||||
/* ----------------------------------------------------------------------- */
|
|
||||||
|
|
||||||
if (*if1 == 1) {
|
|
||||||
t_ih__[1] = *f1v;
|
|
||||||
t_ih__[2] = *aki * *f1h;
|
|
||||||
} else {
|
|
||||||
t_ih__[1] = 0.f;
|
|
||||||
t_ih__[2] = 0.f;
|
|
||||||
}
|
|
||||||
if (*if2 == 1) {
|
|
||||||
t_ih__[3] = *f2v;
|
|
||||||
t_ih__[4] = *akf * *f2h;
|
|
||||||
} else {
|
|
||||||
t_ih__[3] = 0.f;
|
|
||||||
t_ih__[4] = 0.f;
|
|
||||||
}
|
|
||||||
/* ----------------------------------------------------------------------- */
|
|
||||||
/* L999: */
|
|
||||||
return 0;
|
|
||||||
} /* flip_case__ */
|
|
164
tasdrive.c
164
tasdrive.c
@ -227,7 +227,16 @@ static int TASHalt(void *pData)
|
|||||||
if (self->math->tasMode == ELASTIC) {
|
if (self->math->tasMode == ELASTIC) {
|
||||||
length = 8;
|
length = 8;
|
||||||
}
|
}
|
||||||
for (i = 0; i < length; i++) {
|
|
||||||
|
/*
|
||||||
|
stop monochromator
|
||||||
|
*/
|
||||||
|
self->math->mono->Halt(self->math->monoData);
|
||||||
|
|
||||||
|
/*
|
||||||
|
stop rest
|
||||||
|
*/
|
||||||
|
for (i = 4; i < length; i++) {
|
||||||
if (self->math->motors[i] != NULL) {
|
if (self->math->motors[i] != NULL) {
|
||||||
pDriv = GetDrivableInterface(self->math->motors[i]);
|
pDriv = GetDrivableInterface(self->math->motors[i]);
|
||||||
pDriv->Halt(self->math->motors[i]);
|
pDriv->Halt(self->math->motors[i]);
|
||||||
@ -295,8 +304,8 @@ static int startTASMotor(pMotor mot, SConnection * pCon, char *name,
|
|||||||
to force updates on targets
|
to force updates on targets
|
||||||
*/
|
*/
|
||||||
InvokeNewTarget(pServ->pExecutor, name, target);
|
InvokeNewTarget(pServ->pExecutor, name, target);
|
||||||
|
writeMotPos(pCon, silent, name, val, target);
|
||||||
}
|
}
|
||||||
writeMotPos(pCon, silent, name, val, target);
|
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -313,39 +322,43 @@ static int startMotors(ptasMot self, tasAngles angles,
|
|||||||
/*
|
/*
|
||||||
monochromator
|
monochromator
|
||||||
*/
|
*/
|
||||||
status = startTASMotor(self->math->motors[A1], pCon, "a1",
|
/* status = startTASMotor(self->math->motors[A1], pCon, "a1", */
|
||||||
angles.monochromator_two_theta / 2., silent, stopFixed);
|
/* angles.monochromator_two_theta / 2., silent, stopFixed); */
|
||||||
if (status != OKOK) {
|
/* if (status != OKOK) { */
|
||||||
|
/* return status; */
|
||||||
|
/* } */
|
||||||
|
/* status = startTASMotor(self->math->motors[A2], pCon, "a2", */
|
||||||
|
/* angles.monochromator_two_theta, silent,stopFixed); */
|
||||||
|
/* if (status != OKOK) { */
|
||||||
|
/* return status; */
|
||||||
|
/* } */
|
||||||
|
|
||||||
|
/* if (self->math->motors[MCV] != NULL) { */
|
||||||
|
/* curve = maCalcVerticalCurvature(self->math->machine.monochromator, */
|
||||||
|
/* angles.monochromator_two_theta); */
|
||||||
|
/* status = startTASMotor(self->math->motors[MCV], pCon, "mcv", */
|
||||||
|
/* curve, silent,stopFixed); */
|
||||||
|
/* if (status != OKOK) { */
|
||||||
|
/* SCWrite(pCon,"WARNING: monochromator vertical curvature motor failed to start", eLog); */
|
||||||
|
/* SCSetInterrupt(pCon,eContinue); */
|
||||||
|
/* } */
|
||||||
|
/* } */
|
||||||
|
|
||||||
|
/* if (self->math->motors[MCH] != NULL) { */
|
||||||
|
/* curve = maCalcHorizontalCurvature(self->math->machine.monochromator, */
|
||||||
|
/* angles.monochromator_two_theta); */
|
||||||
|
/* status = startTASMotor(self->math->motors[MCH], pCon, "mch", */
|
||||||
|
/* curve, silent,stopFixed); */
|
||||||
|
/* if (status != OKOK) { */
|
||||||
|
/* SCWrite(pCon,"WARNING: monochromator horizontal curvature motor failed to start", eLog); */
|
||||||
|
/* SCSetInterrupt(pCon,eContinue); */
|
||||||
|
/* } */
|
||||||
|
/* } */
|
||||||
|
status = self->math->mono->SetValue(self->math->monoData,
|
||||||
|
pCon,angles.monochromator_two_theta);
|
||||||
|
if(status != OKOK){
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
status = startTASMotor(self->math->motors[A2], pCon, "a2",
|
|
||||||
angles.monochromator_two_theta, silent,stopFixed);
|
|
||||||
if (status != OKOK) {
|
|
||||||
return status;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (self->math->motors[MCV] != NULL) {
|
|
||||||
curve = maCalcVerticalCurvature(self->math->machine.monochromator,
|
|
||||||
angles.monochromator_two_theta);
|
|
||||||
status = startTASMotor(self->math->motors[MCV], pCon, "mcv",
|
|
||||||
curve, silent,stopFixed);
|
|
||||||
if (status != OKOK) {
|
|
||||||
SCWrite(pCon,"WARNING: monochromator vertical curvature motor failed to start", eLog);
|
|
||||||
SCSetInterrupt(pCon,eContinue);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (self->math->motors[MCH] != NULL) {
|
|
||||||
curve = maCalcHorizontalCurvature(self->math->machine.monochromator,
|
|
||||||
angles.monochromator_two_theta);
|
|
||||||
status = startTASMotor(self->math->motors[MCH], pCon, "mch",
|
|
||||||
curve, silent,stopFixed);
|
|
||||||
if (status != OKOK) {
|
|
||||||
SCWrite(pCon,"WARNING: monochromator horizontal curvature motor failed to start", eLog);
|
|
||||||
SCSetInterrupt(pCon,eContinue);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
analyzer
|
analyzer
|
||||||
@ -491,24 +504,24 @@ static int calculateAndDrive(ptasMot self, SConnection * pCon)
|
|||||||
|
|
||||||
switch (status) {
|
switch (status) {
|
||||||
case ENERGYTOBIG:
|
case ENERGYTOBIG:
|
||||||
SCWrite(pCon, "ERROR: desired energy to big", eError);
|
SCWrite(pCon, "ERROR: desired energy to big", eLogError);
|
||||||
return HWFault;
|
return HWFault;
|
||||||
break;
|
break;
|
||||||
case UBNOMEMORY:
|
case UBNOMEMORY:
|
||||||
SCWrite(pCon, "ERROR: out of memory calculating angles", eError);
|
SCWrite(pCon, "ERROR: out of memory calculating angles", eLogError);
|
||||||
driveQ = 0;
|
driveQ = 0;
|
||||||
break;
|
break;
|
||||||
case BADRMATRIX:
|
case BADRMATRIX:
|
||||||
SCWrite(pCon, "ERROR: bad crystallographic parameters or bad UB",
|
SCWrite(pCon, "ERROR: bad crystallographic parameters or bad UB",
|
||||||
eError);
|
eLogError);
|
||||||
driveQ = 0;
|
driveQ = 0;
|
||||||
break;
|
break;
|
||||||
case BADUBORQ:
|
case BADUBORQ:
|
||||||
SCWrite(pCon, "ERROR: bad UB matrix or bad Q-vector", eError);
|
SCWrite(pCon, "ERROR: bad UB matrix or bad Q-vector", eLogError);
|
||||||
driveQ = 0;
|
driveQ = 0;
|
||||||
break;
|
break;
|
||||||
case TRIANGLENOTCLOSED:
|
case TRIANGLENOTCLOSED:
|
||||||
SCWrite(pCon, "ERROR: cannot close scattering triangle", eError);
|
SCWrite(pCon, "ERROR: cannot close scattering triangle", eLogError);
|
||||||
driveQ = 0;
|
driveQ = 0;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -546,7 +559,7 @@ static int calculateAndDrive(ptasMot self, SConnection * pCon)
|
|||||||
|
|
||||||
if (driveQ == 0 && self->math->mustDriveQ == 1) {
|
if (driveQ == 0 && self->math->mustDriveQ == 1) {
|
||||||
SCWrite(pCon, "WARNING: NOT driving Q-vector because of errors",
|
SCWrite(pCon, "WARNING: NOT driving Q-vector because of errors",
|
||||||
eError);
|
eLogError);
|
||||||
}
|
}
|
||||||
/*
|
/*
|
||||||
* reset the Q flag
|
* reset the Q flag
|
||||||
@ -577,7 +590,20 @@ static int checkMotors(ptasMot self, SConnection * pCon)
|
|||||||
mask[SGL] = 0;
|
mask[SGL] = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (i = 0; i < 12; i++) {
|
/*
|
||||||
|
check monochromator
|
||||||
|
*/
|
||||||
|
status = self->math->mono->CheckStatus(self->math->monoData,pCon);
|
||||||
|
if(status == HWIdle){
|
||||||
|
for(i = 0; i < 4; i++){
|
||||||
|
busy[i] = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
check the rest
|
||||||
|
*/
|
||||||
|
for (i = 4; i < 12; i++) {
|
||||||
if(self->math->motors[i] == NULL){
|
if(self->math->motors[i] == NULL){
|
||||||
busy[i] = 0;
|
busy[i] = 0;
|
||||||
} else {
|
} else {
|
||||||
@ -635,35 +661,39 @@ static int startQMMotors(ptasMot self, tasAngles angles,
|
|||||||
/*
|
/*
|
||||||
monochromator
|
monochromator
|
||||||
*/
|
*/
|
||||||
status = startTASMotor(self->math->motors[A1], pCon, "a1",
|
/* status = startTASMotor(self->math->motors[A1], pCon, "a1", */
|
||||||
angles.monochromator_two_theta / 2., silent,stopFixed);
|
/* angles.monochromator_two_theta / 2., silent,stopFixed); */
|
||||||
if (status != OKOK) {
|
/* if (status != OKOK) { */
|
||||||
return status;
|
/* return status; */
|
||||||
}
|
/* } */
|
||||||
status = startTASMotor(self->math->motors[A2], pCon, "a2",
|
/* status = startTASMotor(self->math->motors[A2], pCon, "a2", */
|
||||||
angles.monochromator_two_theta, silent,stopFixed);
|
/* angles.monochromator_two_theta, silent,stopFixed); */
|
||||||
if (status != OKOK) {
|
/* if (status != OKOK) { */
|
||||||
return status;
|
/* return status; */
|
||||||
}
|
/* } */
|
||||||
|
|
||||||
if (self->math->motors[MCV] != NULL) {
|
/* if (self->math->motors[MCV] != NULL) { */
|
||||||
curve = maCalcVerticalCurvature(self->math->machine.monochromator,
|
/* curve = maCalcVerticalCurvature(self->math->machine.monochromator, */
|
||||||
angles.monochromator_two_theta);
|
/* angles.monochromator_two_theta); */
|
||||||
status = startTASMotor(self->math->motors[MCV], pCon, "mcv",
|
/* status = startTASMotor(self->math->motors[MCV], pCon, "mcv", */
|
||||||
curve, silent,stopFixed);
|
/* curve, silent,stopFixed); */
|
||||||
if (status != OKOK) {
|
/* if (status != OKOK) { */
|
||||||
return status;
|
/* return status; */
|
||||||
}
|
/* } */
|
||||||
}
|
/* } */
|
||||||
|
|
||||||
if (self->math->motors[MCH] != NULL) {
|
/* if (self->math->motors[MCH] != NULL) { */
|
||||||
curve = maCalcHorizontalCurvature(self->math->machine.monochromator,
|
/* curve = maCalcHorizontalCurvature(self->math->machine.monochromator, */
|
||||||
angles.monochromator_two_theta);
|
/* angles.monochromator_two_theta); */
|
||||||
status = startTASMotor(self->math->motors[MCH], pCon, "mch",
|
/* status = startTASMotor(self->math->motors[MCH], pCon, "mch", */
|
||||||
curve, silent,stopFixed);
|
/* curve, silent,stopFixed); */
|
||||||
if (status != OKOK) {
|
/* if (status != OKOK) { */
|
||||||
return status;
|
/* return status; */
|
||||||
}
|
/* } */
|
||||||
|
/* } */
|
||||||
|
status = self->math->mono->SetValue(self->math->monoData,pCon,angles.analyzer_two_theta);
|
||||||
|
if(status != OKOK){
|
||||||
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
37
task.c
37
task.c
@ -68,7 +68,8 @@ static pTaskHead MakeTaskHead(char *name, TaskFunc pTask, SignalFunc pSignal,
|
|||||||
pNew->pSignal = pSignal;
|
pNew->pSignal = pSignal;
|
||||||
pNew->pData = pData;
|
pNew->pData = pData;
|
||||||
pNew->pKill = pKill;
|
pNew->pKill = pKill;
|
||||||
pNew->lID = lIDMama++;
|
lIDMama++;
|
||||||
|
pNew->lID = lIDMama;
|
||||||
pNew->iStatus = READY;
|
pNew->iStatus = READY;
|
||||||
|
|
||||||
if(lIDMama < 0){
|
if(lIDMama < 0){
|
||||||
@ -455,6 +456,25 @@ int isTaskRunning(pTaskMan self, char *name)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
/*-----------------------------------------------------------------------------*/
|
/*-----------------------------------------------------------------------------*/
|
||||||
|
int isTaskIDRunning(pTaskMan self, long lID)
|
||||||
|
{
|
||||||
|
int iRet;
|
||||||
|
pTaskHead pCurrent, pNext;
|
||||||
|
|
||||||
|
if (self == NULL) return 0;
|
||||||
|
assert(self->iID == TASKERID);
|
||||||
|
|
||||||
|
pNext = self->pHead->pNext; /* skip dummy task */
|
||||||
|
while (pNext != NULL) {
|
||||||
|
pCurrent = pNext;
|
||||||
|
pNext = pCurrent->pNext;
|
||||||
|
if (pCurrent->lID == lID) {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
/*-----------------------------------------------------------------------------*/
|
||||||
pTaskHead TaskIteratorStart(pTaskMan self)
|
pTaskHead TaskIteratorStart(pTaskMan self)
|
||||||
{
|
{
|
||||||
if (self == NULL) return NULL;
|
if (self == NULL) return NULL;
|
||||||
@ -502,6 +522,21 @@ char *TaskDescription(pTaskHead it)
|
|||||||
|
|
||||||
}
|
}
|
||||||
/*------------------------------------------------------------------------------*/
|
/*------------------------------------------------------------------------------*/
|
||||||
|
long GetTaskID(pTaskHead it)
|
||||||
|
{
|
||||||
|
return it->lID;
|
||||||
|
}
|
||||||
|
/*------------------------------------------------------------------------------*/
|
||||||
|
long GetGroupID(pTaskHead it)
|
||||||
|
{
|
||||||
|
return it-> groupID;
|
||||||
|
}
|
||||||
|
/*------------------------------------------------------------------------------*/
|
||||||
|
const char * GetTaskName(pTaskHead it)
|
||||||
|
{
|
||||||
|
return (const char*)it->name;
|
||||||
|
}
|
||||||
|
/*------------------------------------------------------------------------------*/
|
||||||
long GetTaskGroupID(pTaskMan self)
|
long GetTaskGroupID(pTaskMan self)
|
||||||
{
|
{
|
||||||
lIDMama++;
|
lIDMama++;
|
||||||
|
23
task.h
23
task.h
@ -6,7 +6,10 @@
|
|||||||
a yield and a primitive form of inter task communication is implemented.
|
a yield and a primitive form of inter task communication is implemented.
|
||||||
|
|
||||||
Mark Koennecke, September 1997
|
Mark Koennecke, September 1997
|
||||||
|
|
||||||
|
extended to suuport task groups
|
||||||
|
Mark Koennecke, December 2012
|
||||||
|
|
||||||
copyright: see implementation file
|
copyright: see implementation file
|
||||||
-----------------------------------------------------------------------------*/
|
-----------------------------------------------------------------------------*/
|
||||||
#ifndef TASKOMAT
|
#ifndef TASKOMAT
|
||||||
@ -144,6 +147,11 @@ int TaskSignal(pTaskMan self, int iSignal, void *pSigData);
|
|||||||
/*
|
/*
|
||||||
returns 1 when task name is running, 0 else
|
returns 1 when task name is running, 0 else
|
||||||
*/
|
*/
|
||||||
|
/*--------------------------------------------------------------------------*/
|
||||||
|
int isTaskIDRunning(pTaskMan self, long lID);
|
||||||
|
/*
|
||||||
|
returns 1 when task name is running, 0 else
|
||||||
|
*/
|
||||||
/*===========================================================================
|
/*===========================================================================
|
||||||
Iterating the task list. This works like:
|
Iterating the task list. This works like:
|
||||||
|
|
||||||
@ -177,6 +185,19 @@ char *TaskDescription(pTaskHead it);
|
|||||||
get a description of the task at the current iterator
|
get a description of the task at the current iterator
|
||||||
You are responsible for deleting the returned character array.
|
You are responsible for deleting the returned character array.
|
||||||
*/
|
*/
|
||||||
|
long GetTaskID(pTaskHead it);
|
||||||
|
/*
|
||||||
|
get the ID of the current task
|
||||||
|
*/
|
||||||
|
long GetGroupID(pTaskHead it);
|
||||||
|
/*
|
||||||
|
get the group ID of the current task
|
||||||
|
*/
|
||||||
|
const char *GetTaskName(pTaskHead it);
|
||||||
|
/*
|
||||||
|
get the name of the current task. Do not delete the returned pointer.
|
||||||
|
*/
|
||||||
|
|
||||||
/*=============================================================================
|
/*=============================================================================
|
||||||
Task Groups. The implementation has the limit that any given task can
|
Task Groups. The implementation has the limit that any given task can
|
||||||
only be member of one task group
|
only be member of one task group
|
||||||
|
38
taskobj.c
38
taskobj.c
@ -61,6 +61,10 @@ static int KillCmd(pSICSOBJ self, SConnection *pCon, pHdb commandNode,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(!SCMatchRights(pCon,usMugger)){
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
status = StopTask(pServ->pTasker,par[0]->value.v.text);
|
status = StopTask(pServ->pTasker,par[0]->value.v.text);
|
||||||
if(status == 0) {
|
if(status == 0) {
|
||||||
SCWrite(pCon,"ERROR: cannot commit suicide!", eError);
|
SCWrite(pCon,"ERROR: cannot commit suicide!", eError);
|
||||||
@ -183,3 +187,37 @@ int TaskOBJFactory(SConnection *pCon, SicsInterp *pSics, void *pData,
|
|||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
/*-------------------------------------------------------------------*/
|
||||||
|
void InitTaskOBJ()
|
||||||
|
{
|
||||||
|
pSICSOBJ pNew = NULL;
|
||||||
|
pHdb cmd = NULL, node;
|
||||||
|
|
||||||
|
|
||||||
|
pNew = MakeSICSOBJv("task", "TaskOBJ", HIPNONE, usInternal);
|
||||||
|
if (pNew == NULL) {
|
||||||
|
SCWrite(pServ->dummyCon, "ERROR: out of memory creating new SICS object", eError);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
cmd = AddSICSHdbPar(pNew->objectNode, "ps", usSpy,
|
||||||
|
MakeSICSFunc(ListCmd));
|
||||||
|
|
||||||
|
cmd = AddSICSHdbPar(pNew->objectNode, "kill", usSpy,
|
||||||
|
MakeSICSFunc(KillCmd));
|
||||||
|
SetHdbProperty(cmd,"type","command");
|
||||||
|
SetHdbProperty(cmd,"priv","spy");
|
||||||
|
node = MakeSICSHdbPar("task",usSpy,MakeHdbText("banana"));
|
||||||
|
AddHipadabaChild(cmd,node,NULL);
|
||||||
|
|
||||||
|
cmd = AddSICSHdbPar(pNew->objectNode, "run", usSpy,
|
||||||
|
MakeSICSFunc(RunCmd));
|
||||||
|
SetHdbProperty(cmd,"type","command");
|
||||||
|
SetHdbProperty(cmd,"priv","spy");
|
||||||
|
node = MakeSICSHdbPar("script",usSpy,MakeHdbText("banana"));
|
||||||
|
AddHipadabaChild(cmd,node,NULL);
|
||||||
|
|
||||||
|
AddCommand(pServ->pSics,
|
||||||
|
"task", InterInvokeSICSOBJ, KillSICSOBJ, pNew);
|
||||||
|
|
||||||
|
}
|
||||||
|
234
tasmono.c
Normal file
234
tasmono.c
Normal file
@ -0,0 +1,234 @@
|
|||||||
|
/**
|
||||||
|
* Triple axis monochromator module
|
||||||
|
* EIGER made it necessary to abstract out the monochromator. This is
|
||||||
|
* the default implementation for a sane, normal TAS. This implements a
|
||||||
|
* drivable interface. It gets an A2 value from the tasub module and is
|
||||||
|
* supposed to drive and monitor all the dependent monochromator motors.
|
||||||
|
*
|
||||||
|
* copyright: see file COPYRIGHT
|
||||||
|
*
|
||||||
|
* Mark Koennecke, February 2013
|
||||||
|
*/
|
||||||
|
#include <sics.h>
|
||||||
|
#include "tasmono.h"
|
||||||
|
#include "tasub.h"
|
||||||
|
|
||||||
|
#define MOTPREC .01
|
||||||
|
#define A1 0
|
||||||
|
#define A2 1
|
||||||
|
#define MCV 2
|
||||||
|
#define MCH 3
|
||||||
|
#define NOTSTARTED -100
|
||||||
|
|
||||||
|
|
||||||
|
#define ABS(x) (x < 0 ? -(x) : (x))
|
||||||
|
|
||||||
|
/*----------------------------------------------------------------
|
||||||
|
This routine can return either OKOK or HWFault when thing
|
||||||
|
go wrong. However, the return value of Halt is usually ignored!
|
||||||
|
------------------------------------------------------------------*/
|
||||||
|
static int TAMOHalt(void *data) {
|
||||||
|
ptasUB self = NULL;
|
||||||
|
pIDrivable pDriv;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
self = (ptasUB)data;
|
||||||
|
for(i = 0; i < 4; i++){
|
||||||
|
if (self->motors[i] != NULL) {
|
||||||
|
pDriv = GetDrivableInterface(self->motors[i]);
|
||||||
|
pDriv->Halt(self->motors[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return OKOK;
|
||||||
|
}
|
||||||
|
/*----------------------------------------------------------------
|
||||||
|
This routine can return either 1 or 0. 1 means the position can
|
||||||
|
be reached, 0 NOT
|
||||||
|
If 0, error shall contain up to errlen characters of information
|
||||||
|
about which limit was violated
|
||||||
|
------------------------------------------------------------------*/
|
||||||
|
static int TAMOCheckLimits(void *data, float val,
|
||||||
|
char *error, int errlen){
|
||||||
|
ptasUB self = NULL;
|
||||||
|
|
||||||
|
self = (ptasUB)data;
|
||||||
|
|
||||||
|
/*
|
||||||
|
Not meaningful in this context
|
||||||
|
*/
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
/*----------------------------------------------------------------
|
||||||
|
This routine can return 0 when a limit problem occurred
|
||||||
|
OKOK when the motor was successfully started
|
||||||
|
HWFault when a problem occured starting the device
|
||||||
|
Possible errors shall be printed to pCon
|
||||||
|
For real motors, this is supposed to try at least three times
|
||||||
|
to start the motor in question
|
||||||
|
val is the value to drive the motor too
|
||||||
|
------------------------------------------------------------------*/
|
||||||
|
static void writeMotPos(SConnection * pCon, int silent, char *name,
|
||||||
|
float val, float target)
|
||||||
|
{
|
||||||
|
char pBueffel[132];
|
||||||
|
|
||||||
|
if (silent != 1) {
|
||||||
|
snprintf(pBueffel, 131, "Driving %5s from %8.3f to %8.3f",
|
||||||
|
name, val, target);
|
||||||
|
SCWrite(pCon, pBueffel, eLog);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/*--------------------------------------------------------------------------*/
|
||||||
|
static long startTASMotor(pMotor mot, SConnection * pCon, char *name,
|
||||||
|
double target, int silent, int stopFixed)
|
||||||
|
{
|
||||||
|
float val, fixed, precision = MOTPREC;
|
||||||
|
long status = NOTSTARTED;
|
||||||
|
char buffer[132];
|
||||||
|
pIDrivable pDriv = NULL;
|
||||||
|
pDummy dum = NULL;
|
||||||
|
pDynString mes = NULL;
|
||||||
|
|
||||||
|
|
||||||
|
dum = (pDummy)mot;
|
||||||
|
GetDrivablePosition(mot, pCon,&val);
|
||||||
|
if(strcmp(dum->pDescriptor->name,"Motor") == 0){
|
||||||
|
MotorGetPar(mot,"precision",&precision);
|
||||||
|
MotorGetPar(mot, "fixed", &fixed);
|
||||||
|
if (ABS(fixed - 1.0) < .1) {
|
||||||
|
if(stopFixed == 0){
|
||||||
|
snprintf(buffer, 131, "WARNING: %s is FIXED", name);
|
||||||
|
SCWrite(pCon, buffer, eLog);
|
||||||
|
}
|
||||||
|
return NOTSTARTED;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
mot->stopped = 0;
|
||||||
|
if (ABS(val - target) > precision) {
|
||||||
|
status = StartDriveTask(mot, pCon, name, (float)target);
|
||||||
|
if(status < 0){
|
||||||
|
SCPrintf(pCon,eLog,"ERROR: failed to drive %s to %f", name, target);
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
to force updates on targets
|
||||||
|
*/
|
||||||
|
InvokeNewTarget(pServ->pExecutor, name, target);
|
||||||
|
writeMotPos(pCon, silent, name, val, target);
|
||||||
|
return status;
|
||||||
|
} else {
|
||||||
|
return NOTSTARTED;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/*-------------------------------------------------------------------------*/
|
||||||
|
static long TAMOSetValue(void *data, SConnection *pCon, float val){
|
||||||
|
ptasUB self = NULL;
|
||||||
|
self = (ptasUB)data;
|
||||||
|
int stopFixed = 0;
|
||||||
|
double curve;
|
||||||
|
int status;
|
||||||
|
|
||||||
|
self->monoTaskID = GetTaskGroupID(pServ->pTasker);
|
||||||
|
|
||||||
|
status = startTASMotor(self->motors[A1], pCon, "a1",
|
||||||
|
val / 2., self->silent, stopFixed);
|
||||||
|
if (status < 0 && status != NOTSTARTED) {
|
||||||
|
return HWFault;
|
||||||
|
}
|
||||||
|
if(status != NOTSTARTED){
|
||||||
|
AddTaskToGroup(pServ->pTasker,status, self->monoTaskID);
|
||||||
|
}
|
||||||
|
|
||||||
|
status = startTASMotor(self->motors[A2], pCon, "a2",
|
||||||
|
val, self->silent,stopFixed);
|
||||||
|
if (status < 0 && status != NOTSTARTED) {
|
||||||
|
return HWFault;
|
||||||
|
}
|
||||||
|
if(status != NOTSTARTED){
|
||||||
|
AddTaskToGroup(pServ->pTasker,status, self->monoTaskID);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if (self->motors[MCV] != NULL) {
|
||||||
|
curve = maCalcVerticalCurvature(self->machine.monochromator,
|
||||||
|
val);
|
||||||
|
status = startTASMotor(self->motors[MCV], pCon, "mcv",
|
||||||
|
curve, self->silent,stopFixed);
|
||||||
|
if (status < 0 && status != NOTSTARTED) {
|
||||||
|
SCWrite(pCon,"WARNING: monochromator vertical curvature motor failed to start", eLog);
|
||||||
|
SCSetInterrupt(pCon,eContinue);
|
||||||
|
} else {
|
||||||
|
AddTaskToGroup(pServ->pTasker,status, self->monoTaskID);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (self->motors[MCH] != NULL) {
|
||||||
|
curve = maCalcHorizontalCurvature(self->machine.monochromator,
|
||||||
|
val);
|
||||||
|
status = startTASMotor(self->motors[MCH], pCon, "mch",
|
||||||
|
curve, self->silent,stopFixed);
|
||||||
|
if (status < 0 && status != NOTSTARTED) {
|
||||||
|
SCWrite(pCon,"WARNING: monochromator horizontal curvature motor failed to start", eLog);
|
||||||
|
SCSetInterrupt(pCon,eContinue);
|
||||||
|
}else {
|
||||||
|
AddTaskToGroup(pServ->pTasker,status,self->monoTaskID);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return OKOK;
|
||||||
|
}
|
||||||
|
/*----------------------------------------------------------------
|
||||||
|
Checks the status of a running motor. Possible return values
|
||||||
|
HWBusy The motor is still running
|
||||||
|
OKOK or HWIdle when the motor finished driving
|
||||||
|
HWFault when a hardware problem ocurred
|
||||||
|
HWPosFault when the hardware cannot reach a position
|
||||||
|
Errors are duly to be printed to pCon
|
||||||
|
For real motors CheckStatus again shall try hard to fix any
|
||||||
|
issues with the motor
|
||||||
|
------------------------------------------------------------------*/
|
||||||
|
static int TAMOCheckStatus(void *data, SConnection *pCon){
|
||||||
|
ptasUB self = NULL;
|
||||||
|
|
||||||
|
self = (ptasUB)data;
|
||||||
|
if(isTaskGroupRunning(pServ->pTasker,self->monoTaskID)) {
|
||||||
|
return HWBusy;
|
||||||
|
} else {
|
||||||
|
return HWIdle;
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
/*----------------------------------------------------------------
|
||||||
|
GetValue is supposed to read a motor position
|
||||||
|
On errors, -99999999.99 is returned and messages printed to pCon
|
||||||
|
------------------------------------------------------------------*/
|
||||||
|
static float TAMOGetValue(void *data, SConnection *pCon){
|
||||||
|
ptasUB self = NULL;
|
||||||
|
float val = -99999999.99;
|
||||||
|
|
||||||
|
int status;
|
||||||
|
|
||||||
|
self = (ptasUB)data;
|
||||||
|
status = GetDrivablePosition(self->motors[A2], pCon, &val);
|
||||||
|
if (status == 0) {
|
||||||
|
return -99999999.99;
|
||||||
|
}
|
||||||
|
return val;
|
||||||
|
}
|
||||||
|
/*----------------------------------------------------------------
|
||||||
|
returns NULL on failure, a new datastructure else
|
||||||
|
------------------------------------------------------------------*/
|
||||||
|
pIDrivable MakeTasMono(){
|
||||||
|
pIDrivable pDriv;
|
||||||
|
|
||||||
|
pDriv = calloc(1,sizeof(IDrivable));
|
||||||
|
if(pDriv == NULL){
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
pDriv->Halt = TAMOHalt;
|
||||||
|
pDriv->CheckLimits = TAMOCheckLimits;
|
||||||
|
pDriv->SetValue = TAMOSetValue;
|
||||||
|
pDriv->CheckStatus = TAMOCheckStatus;
|
||||||
|
pDriv->GetValue = TAMOGetValue;
|
||||||
|
|
||||||
|
return pDriv;
|
||||||
|
}
|
||||||
|
|
19
tasmono.h
Normal file
19
tasmono.h
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
/**
|
||||||
|
* Triple axis monochromator module
|
||||||
|
* EIGER made it necessary to abstract out the monochromator. This is
|
||||||
|
* the default implementation for a sane, normal TAS. This implements a
|
||||||
|
* drivable interface. It gets an A2 value from the tasub module and is
|
||||||
|
* supposed to drive and monitor all the dependent monochromator motors.
|
||||||
|
*
|
||||||
|
* copyright: see file COPYRIGHT
|
||||||
|
*
|
||||||
|
* Mark Koennecke, February 2013
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __TASMONO
|
||||||
|
#define __TASMONO
|
||||||
|
|
||||||
|
pIDrivable MakeTasMono();
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
6
tasub.c
6
tasub.c
@ -22,6 +22,7 @@
|
|||||||
#include "tasub.h"
|
#include "tasub.h"
|
||||||
#include "tasdrive.h"
|
#include "tasdrive.h"
|
||||||
#include "vector.h"
|
#include "vector.h"
|
||||||
|
#include "tasmono.h"
|
||||||
/*------------------- motor indexes in motor data structure ---------*/
|
/*------------------- motor indexes in motor data structure ---------*/
|
||||||
#define A1 0
|
#define A1 0
|
||||||
#define A2 1
|
#define A2 1
|
||||||
@ -173,6 +174,8 @@ static ptasUB MakeTasUB()
|
|||||||
pNew->actualEn = .0;
|
pNew->actualEn = .0;
|
||||||
pNew->outOfPlaneAllowed = 1;
|
pNew->outOfPlaneAllowed = 1;
|
||||||
pNew->mustRecalculate = 1;
|
pNew->mustRecalculate = 1;
|
||||||
|
pNew->mono = MakeTasMono();
|
||||||
|
pNew->monoData = pNew;
|
||||||
|
|
||||||
return pNew;
|
return pNew;
|
||||||
}
|
}
|
||||||
@ -198,6 +201,9 @@ static void KillTasUB(void *pData)
|
|||||||
if(self->updater != NULL){
|
if(self->updater != NULL){
|
||||||
free(self->updater);
|
free(self->updater);
|
||||||
}
|
}
|
||||||
|
if(self->mono != NULL){
|
||||||
|
free(self->mono);
|
||||||
|
}
|
||||||
free(self);
|
free(self);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
3
tasub.h
3
tasub.h
@ -30,6 +30,9 @@
|
|||||||
int mustDriveQ;
|
int mustDriveQ;
|
||||||
pMotor motors[12];
|
pMotor motors[12];
|
||||||
tasReflection r1, r2;
|
tasReflection r1, r2;
|
||||||
|
pIDrivable mono;
|
||||||
|
long monoTaskID;
|
||||||
|
void *monoData;
|
||||||
int ubValid;
|
int ubValid;
|
||||||
int silent;
|
int silent;
|
||||||
int stopFixed; /* flag to stop multiple fixed messages in scans*/
|
int stopFixed; /* flag to stop multiple fixed messages in scans*/
|
||||||
|
20
trace.c
20
trace.c
@ -199,12 +199,20 @@ static int strrepc(char *pszStr, char cFrom, char cTo)
|
|||||||
/*-----------------------------------------------------------------*/
|
/*-----------------------------------------------------------------*/
|
||||||
void traceprint(char *sub, char *id, char *data)
|
void traceprint(char *sub, char *id, char *data)
|
||||||
{
|
{
|
||||||
if(log != NULL && filter(sub,id)){
|
char *mysub, *myid, *mydata;
|
||||||
strrepc(data,'\n',':');
|
|
||||||
strrepc(sub,':','@');
|
if(log != NULL && filter(sub,id)){
|
||||||
strrepc(id,':','@');
|
mysub = strdup(sub);
|
||||||
fprintf(log,"%s:%s:%lf:%s\n",sub,id,DoubleTime(),data);
|
myid = strdup(id);
|
||||||
}
|
mydata = strdup(data);
|
||||||
|
strrepc(mydata,'\n',':');
|
||||||
|
strrepc(mysub,':','@');
|
||||||
|
strrepc(myid,':','@');
|
||||||
|
fprintf(log,"%s:%s:%lf:%s\n",mysub,myid,DoubleTime(),mydata);
|
||||||
|
free(mysub);
|
||||||
|
free(myid);
|
||||||
|
free(mydata);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
/*-----------------------------------------------------------------*/
|
/*-----------------------------------------------------------------*/
|
||||||
void traceIO(char *id, char *format, ...)
|
void traceIO(char *id, char *format, ...)
|
||||||
|
38
ubcalc.c
38
ubcalc.c
@ -10,6 +10,10 @@
|
|||||||
Heavily reworked to fit into the new four circle system
|
Heavily reworked to fit into the new four circle system
|
||||||
|
|
||||||
Mark Koennecke, July 2008
|
Mark Koennecke, July 2008
|
||||||
|
|
||||||
|
Added UBfromCell
|
||||||
|
|
||||||
|
Mark Koennecke, March 2013
|
||||||
-----------------------------------------------------------------------*/
|
-----------------------------------------------------------------------*/
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
@ -252,7 +256,39 @@ static int calcUB(pUBCALC self, SConnection * pCon, char *ref1, char *ref2)
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
/*---------------------------------------------------------------------*/
|
||||||
|
static int UBFromCell(pUBCALC self, SConnection *pCon)
|
||||||
|
{
|
||||||
|
const double *cell;
|
||||||
|
lattice mycell;
|
||||||
|
MATRIX B;
|
||||||
|
double ub[9];
|
||||||
|
int i;
|
||||||
|
|
||||||
|
cell = SXGetCell();
|
||||||
|
mycell.a = cell[0];
|
||||||
|
mycell.b = cell[1];
|
||||||
|
mycell.c = cell[2];
|
||||||
|
mycell.alpha = cell[3];
|
||||||
|
mycell.beta = cell[4];
|
||||||
|
mycell.gamma = cell[5];
|
||||||
|
|
||||||
|
B = mat_creat(3,3,ZERO_MATRIX);
|
||||||
|
if(B == NULL){
|
||||||
|
SCWrite(pCon,"ERROR: out of memory in UBfromCell",eError);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
calculateBMatrix(mycell,B);
|
||||||
|
|
||||||
|
if(self->UB != NULL){
|
||||||
|
mat_free(self->UB);
|
||||||
|
}
|
||||||
|
self->UB = B;
|
||||||
|
|
||||||
|
SCSendOK(pCon);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
/*---------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------*/
|
||||||
static int sendUBToHKL(SConnection * pCon, SicsInterp * pSics,
|
static int sendUBToHKL(SConnection * pCon, SicsInterp * pSics,
|
||||||
pHKL hkl, MATRIX UB)
|
pHKL hkl, MATRIX UB)
|
||||||
@ -551,6 +587,8 @@ int UBCalcWrapper(SConnection * pCon, SicsInterp * pSics, void *pData,
|
|||||||
return sendUBToHKL(pCon, pSics, self->hkl, self->UB);
|
return sendUBToHKL(pCon, pSics, self->hkl, self->UB);
|
||||||
} else if (strcmp(argv[1], "index") == 0) {
|
} else if (strcmp(argv[1], "index") == 0) {
|
||||||
return findIndex(self, pCon, pSics, argc, argv);
|
return findIndex(self, pCon, pSics, argc, argv);
|
||||||
|
} else if (strcmp(argv[1], "fromcell") == 0) {
|
||||||
|
return UBFromCell(self, pCon);
|
||||||
} else {
|
} else {
|
||||||
if (argc > 2) {
|
if (argc > 2) {
|
||||||
return setUBCalcParameters(self, pCon, argv[1], argv[2]);
|
return setUBCalcParameters(self, pCon, argv[1], argv[2]);
|
||||||
|
2
ubfour.h
2
ubfour.h
@ -117,7 +117,7 @@ double angleBetweenReflections(MATRIX B, reflection r1, reflection r2);
|
|||||||
/**
|
/**
|
||||||
* calculate the length of the scattering vector belonging to r
|
* calculate the length of the scattering vector belonging to r
|
||||||
* @param B The B metric matrix to use
|
* @param B The B metric matrix to use
|
||||||
* @param r The reflction for which to calculate
|
* @param r The reflection for which to calculate
|
||||||
* @return The length of the scattering vector
|
* @return The length of the scattering vector
|
||||||
*/
|
*/
|
||||||
double scatteringVectorLength(MATRIX B, reflection r);
|
double scatteringVectorLength(MATRIX B, reflection r);
|
||||||
|
2
velo.c
2
velo.c
@ -802,7 +802,7 @@ int VelSelFactory(SConnection * pCon, SicsInterp * pSics, void *pData,
|
|||||||
}
|
}
|
||||||
pT = InterpGetTcl(pSics);
|
pT = InterpGetTcl(pSics);
|
||||||
site = getSite();
|
site = getSite();
|
||||||
if (site != NULL) {
|
if (site != NULL && site->CreateVelocitySelector != NULL) {
|
||||||
pDriv = site->CreateVelocitySelector(argv[3], argv[4], pT);
|
pDriv = site->CreateVelocitySelector(argv[3], argv[4], pT);
|
||||||
}
|
}
|
||||||
if (!pDriv) {
|
if (!pDriv) {
|
||||||
|
Reference in New Issue
Block a user