- 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 "servlog.h"
|
||||
|
||||
extern void KeepStartupCommands(); /* ofac.c */
|
||||
/***************************** Necessary Globals ****************************/
|
||||
|
||||
IPair *pSICSOptions = NULL;
|
||||
@ -47,6 +48,8 @@ int main(int argc, char *argv[])
|
||||
for (i = 1; i < argc; i++) {
|
||||
if (strcmp(argv[i], "-nolog") == 0) {
|
||||
SICSLogEnable(0);
|
||||
}else if(strcmp(argv[i],"-keepstartup") == 0){
|
||||
KeepStartupCommands();
|
||||
} else if (file == NULL) {
|
||||
file = argv[i];
|
||||
}
|
||||
|
@ -14,14 +14,14 @@
|
||||
- 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
|
||||
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.
|
||||
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
|
||||
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
|
||||
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.
|
||||
|
||||
Mark Koennecke, April 2012
|
||||
|
@ -61,7 +61,7 @@ typedef struct {
|
||||
char *pName;
|
||||
} MonEvent, *pMonEvent;
|
||||
|
||||
/*--------------------------------------------------------------------------*/
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
static int Halt(void *pData)
|
||||
{
|
||||
pCounter self = NULL;
|
||||
@ -444,12 +444,13 @@ int MakeCounter(SConnection * pCon, SicsInterp * pSics, void *pData,
|
||||
assert(pCon);
|
||||
assert(pSics);
|
||||
|
||||
argtolower(argc, argv);
|
||||
if (argc < 3) {
|
||||
SCWrite(pCon, "ERROR: insuficient number of arguments to MakeCounter",
|
||||
eError);
|
||||
return 0;
|
||||
}
|
||||
strtolower(argv[1]);
|
||||
strtolower(argv[2]);
|
||||
site = getSite();
|
||||
if (site != NULL) {
|
||||
pDriv = site->CreateCounterDriver(pCon, argc, argv);
|
||||
|
@ -184,5 +184,7 @@
|
||||
*/
|
||||
void *GetExecutorCallback(pExeList self);
|
||||
/*----------------------- 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
|
||||
|
@ -373,7 +373,9 @@ to the global SICS device executor.
|
||||
\mbox{}\verb@ */ @\\
|
||||
\mbox{}\verb@ void *GetExecutorCallback(pExeList self);@\\
|
||||
\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@@$\Diamond$
|
||||
\end{list}
|
||||
|
@ -319,7 +319,9 @@ to the global SICS device executor.
|
||||
*/
|
||||
void *GetExecutorCallback(pExeList self);
|
||||
/*----------------------- 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
|
||||
@}
|
||||
|
||||
|
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 */
|
||||
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);
|
||||
return 0;
|
||||
}
|
||||
@ -168,7 +168,7 @@ int Start2Run(SConnection * pCon, SicsInterp * pInter, char *name,
|
||||
/* first try to find the thing to drive */
|
||||
pObject = FindCommand(pInter, name);
|
||||
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);
|
||||
return 0;
|
||||
}
|
||||
@ -179,7 +179,7 @@ int Start2Run(SConnection * pCon, SicsInterp * pInter, char *name,
|
||||
pDum = (Dummy *) pObject->pData;
|
||||
pDes = pDum->pDescriptor;
|
||||
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);
|
||||
return 0;
|
||||
}
|
||||
@ -189,14 +189,14 @@ int Start2Run(SConnection * pCon, SicsInterp * pInter, char *name,
|
||||
*/
|
||||
pInt = pDes->GetInterface(pDum, DRIVEID);
|
||||
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);
|
||||
return 0;
|
||||
}
|
||||
if (pInt) {
|
||||
iRet = pInt->CheckLimits(pDum, fNew, pBueffel, 511);
|
||||
if (!iRet) {
|
||||
SCWrite(pCon, pBueffel, eError);
|
||||
SCPrintf(pCon, eError, "ERROR: %s", pBueffel);
|
||||
SCSetInterrupt(pCon, eAbortOperation);
|
||||
return 0;
|
||||
}
|
||||
@ -207,7 +207,7 @@ int Start2Run(SConnection * pCon, SicsInterp * pInter, char *name,
|
||||
return 1;
|
||||
}
|
||||
} else {
|
||||
snprintf(pBueffel,511, "%s is NOT drivable", pDes->name);
|
||||
snprintf(pBueffel,511, "ERROR: %s is NOT drivable", pDes->name);
|
||||
SCWrite(pCon, pBueffel, eError);
|
||||
return 0;
|
||||
}
|
||||
@ -426,7 +426,72 @@ int RunWrapper(SConnection * pCon, SicsInterp * pSics, void *pData,
|
||||
}
|
||||
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 argc, char *argv[])
|
||||
@ -457,5 +522,17 @@ int MakeDrive(SConnection * pCon, SicsInterp * pSics, void *pData,
|
||||
SCWrite(pCon, pBueffel, eError);
|
||||
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;
|
||||
}
|
||||
|
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",
|
||||
"NEWTARGET",
|
||||
"DIMCHANGE",
|
||||
"PAUSE",
|
||||
"CONTINUE",
|
||||
NULL
|
||||
};
|
||||
|
||||
|
12
event.h
12
event.h
@ -1,5 +1,5 @@
|
||||
|
||||
#line 103 "event.w"
|
||||
#line 108 "event.w"
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
E V E N T
|
||||
@ -18,7 +18,7 @@
|
||||
|
||||
int Text2Event(char *pText);
|
||||
|
||||
#line 116 "event.w"
|
||||
#line 121 "event.w"
|
||||
|
||||
|
||||
|
||||
@ -49,8 +49,10 @@
|
||||
#define STEND 22
|
||||
#define NEWTARGET 23
|
||||
#define DIMCHANGE 24
|
||||
#define IPAUSE 25
|
||||
#define CONTINUE 26
|
||||
|
||||
#line 118 "event.w"
|
||||
#line 123 "event.w"
|
||||
|
||||
|
||||
/*----------------- event data structure for the NEWTARGET event ---------*/
|
||||
@ -60,7 +62,7 @@ typedef struct {
|
||||
} NewTarget, *pNewTarget;
|
||||
/*--------------- Signals for the Signalfunction of each task ------------*/
|
||||
|
||||
#line 85 "event.w"
|
||||
#line 90 "event.w"
|
||||
|
||||
#define SICSINT 300
|
||||
#define SICSBROADCAST 301
|
||||
@ -69,6 +71,6 @@ typedef struct {
|
||||
#define COMLOG 304
|
||||
#define CRONLIST 305
|
||||
|
||||
#line 126 "event.w"
|
||||
#line 131 "event.w"
|
||||
|
||||
#endif
|
||||
|
@ -60,6 +60,8 @@ $\langle$VE {\footnotesize ?}$\rangle\equiv$
|
||||
\mbox{}\verb@#define STEND 22@\\
|
||||
\mbox{}\verb@#define NEWTARGET 23@\\
|
||||
\mbox{}\verb@#define DIMCHANGE 24@\\
|
||||
\mbox{}\verb@#define IPAUSE 25@\\
|
||||
\mbox{}\verb@#define CONTINUE 26@\\
|
||||
\mbox{}\verb@@$\Diamond$
|
||||
\end{list}
|
||||
\vspace{-1ex}
|
||||
@ -99,8 +101,11 @@ operation.
|
||||
\item[HDBVAL] The Hdb is notified of a value change. The eventData will be
|
||||
the object on which the data changed.
|
||||
\item[NEWTARGET] is invoked when a new target has been set on a drivable.
|
||||
\item[PAUSE] Pause counting
|
||||
\item[CONTINUE] Continue counting
|
||||
\end{description}
|
||||
|
||||
|
||||
Furthermore event contains system wide signal codes which are interpreted in
|
||||
the signal functions provided by each SICS task. These code are
|
||||
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 NEWTARGET 23
|
||||
#define DIMCHANGE 24
|
||||
#define IPAUSE 25
|
||||
#define CONTINUE 26
|
||||
@}
|
||||
\begin{description}
|
||||
\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
|
||||
the object on which the data changed.
|
||||
\item[NEWTARGET] is invoked when a new target has been set on a drivable.
|
||||
\item[PAUSE] Pause counting
|
||||
\item[CONTINUE] Continue counting
|
||||
\end{description}
|
||||
|
||||
|
||||
Furthermore event contains system wide signal codes which are interpreted in
|
||||
the signal functions provided by each SICS task. These code are
|
||||
evaluated by the TaskSignalFunction which may be configured for each
|
||||
|
21
hdbtable.c
21
hdbtable.c
@ -17,6 +17,10 @@
|
||||
* copyright: see file COPYRIGHT
|
||||
*
|
||||
* Mark Koennecke, March 2009
|
||||
*
|
||||
* Added CountTblCmd
|
||||
*
|
||||
* Mark Koennecke, march 2013
|
||||
*/
|
||||
#include <stdlib.h>
|
||||
#include "sicshipadaba.h"
|
||||
@ -75,6 +79,20 @@ static int ClearTblCmd(pSICSOBJ self, SConnection *pCon, pHdb commandNode,
|
||||
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,
|
||||
pHdb par[], int nPar)
|
||||
{
|
||||
@ -470,6 +488,9 @@ pSICSOBJ MakeHdbTable(char *name, char *hdbclass)
|
||||
SetHdbProperty(node,"priv","user");
|
||||
AddHipadabaChild(cmd,node, NULL);
|
||||
|
||||
cmd = AddSICSHdbPar(result->objectNode, "count", usSpy,
|
||||
MakeSICSFunc(CountTblCmd));
|
||||
|
||||
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);
|
||||
if (iRet == OKOK) {
|
||||
/* send a COUNTSTART event */
|
||||
clearHMData(self->pDriv->data);
|
||||
InvokeCallBack(self->pCall, COUNTSTART, pCon);
|
||||
updateHMData(self->pDriv->data);
|
||||
return iRet;
|
||||
} else {
|
||||
iRet = self->pDriv->GetError(self->pDriv, &iErr, pError, 79);
|
||||
@ -350,9 +350,9 @@ static int HistCountStatus(void *pData, SConnection * pCon)
|
||||
return HWBusy;
|
||||
}
|
||||
}
|
||||
if (eCt == HWBusy){
|
||||
updateHMData(self->pDriv->data);
|
||||
}
|
||||
/* if (eCt == HWBusy){ */
|
||||
/* updateHMData(self->pDriv->data); */
|
||||
/* } */
|
||||
|
||||
if (eCt == HWIdle) {
|
||||
/* force an update of local histogram data with next
|
||||
@ -879,7 +879,7 @@ int GetHistogram(pHistMem self, SConnection * pCon,
|
||||
eWarning);
|
||||
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 {
|
||||
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) {
|
||||
HMListOption(self, pCon);
|
||||
return 1;
|
||||
@ -1798,4 +1814,5 @@ int HistAction(SConnection * pCon, SicsInterp * pSics, void *pData,
|
||||
SCWrite(pCon, pBueffel, eError);
|
||||
return 0;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
49
hkl.c
49
hkl.c
@ -26,6 +26,10 @@
|
||||
Heavily reworked to fit into the new four circle setup
|
||||
|
||||
Mark Koennecke, July 2008
|
||||
|
||||
Added calculation of angles between reflection
|
||||
|
||||
Mark Koennecke, March 2013
|
||||
-----------------------------------------------------------------------------*/
|
||||
#include <math.h>
|
||||
#include <ctype.h>
|
||||
@ -687,6 +691,47 @@ static int HKLCalculateTheta(pHKL self, float fHKL[3], double *stt)
|
||||
*stt = 2. * theta;
|
||||
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[])
|
||||
{
|
||||
@ -993,6 +1038,10 @@ int HKLAction(SConnection * pCon, SicsInterp * pSics, void *pData,
|
||||
SCPrintf(pCon, eValue, "two-theta = %lf", stt);
|
||||
return 1;
|
||||
}
|
||||
/*--------------- calculate angle */
|
||||
else if (strcmp(argv[1], "angle") == 0) {
|
||||
return HKLAngle(pCon,argc,argv);
|
||||
}
|
||||
/*------------------ run */
|
||||
else if (strcmp(argv[1], "run") == 0) {
|
||||
if (!SCMatchRights(pCon, usUser)) {
|
||||
|
3
hmdata.c
3
hmdata.c
@ -59,6 +59,7 @@ void clearHMData(pHMdata self)
|
||||
size *= getNoOfTimebins(self);
|
||||
}
|
||||
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) {
|
||||
return 1;
|
||||
} else {
|
||||
} else {
|
||||
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
|
||||
|
||||
|
||||
@ -12,6 +12,11 @@
|
||||
Paul Scherrer Institut
|
||||
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,
|
||||
and license this software and its documentation for any purpose, provided
|
||||
@ -42,6 +47,7 @@
|
||||
#include "fortify.h"
|
||||
#include "sics.h"
|
||||
#include "motor.h"
|
||||
#include <status.h>
|
||||
/*=========================================================================
|
||||
Empty driveable interface functions
|
||||
==========================================================================*/
|
||||
@ -168,7 +174,107 @@ int GetDrivablePosition(void *pObject, SConnection * pCon, float *fPos)
|
||||
*fPos = value;
|
||||
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)
|
||||
{
|
||||
@ -201,6 +307,112 @@ int isRunning(pICountable self)
|
||||
{
|
||||
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)
|
||||
|
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
|
||||
@ -30,107 +30,113 @@
|
||||
#line 121 "interface.w"
|
||||
|
||||
|
||||
typedef struct {
|
||||
int ID;
|
||||
int (*Halt) (void *self);
|
||||
int (*CheckLimits) (void *self, float fVal, char *error, int iErrLen);
|
||||
long (*SetValue) (void *self, SConnection * pCon, float fVal);
|
||||
int (*CheckStatus) (void *self, SConnection * pCon);
|
||||
float (*GetValue) (void *self, SConnection * pCon);
|
||||
int iErrorCount;
|
||||
int drivableStatus;
|
||||
} IDrivable, *pIDrivable;
|
||||
typedef struct {
|
||||
int ID;
|
||||
int (*Halt)(void *self);
|
||||
int (*CheckLimits)(void *self, float fVal,
|
||||
char *error, int iErrLen);
|
||||
long (*SetValue)(void *self, SConnection *pCon,
|
||||
float fVal);
|
||||
int (*CheckStatus)(void *self, SConnection *pCon);
|
||||
float (*GetValue)(void *self, SConnection *pCon);
|
||||
int iErrorCount;
|
||||
int drivableStatus;
|
||||
} IDrivable, *pIDrivable;
|
||||
|
||||
pIDrivable GetDrivableInterface(void *pObject);
|
||||
int GetDrivablePosition(void *pObject, SConnection * pCon, float *fPos);
|
||||
pIDrivable GetDrivableInterface(void *pObject);
|
||||
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 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
|
||||
|
@ -154,6 +154,8 @@ $\langle$driv {\footnotesize ?}$\rangle\equiv$
|
||||
\mbox{}\verb@ int GetDrivablePosition(void *pObject, SConnection *pCon,@\\
|
||||
\mbox{}\verb@ float *fPos);@\\
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@ long StartDriveTask(void *self, SConnection *pCon, char *name, float fTarget);@\\
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@@$\Diamond$
|
||||
\end{list}
|
||||
\vspace{-1ex}
|
||||
@ -206,6 +208,11 @@ will be returned.
|
||||
object. If the device is a motor corrections for zero points and signs
|
||||
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}
|
||||
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@ void ReleaseCountLock(pICountable self);@\\
|
||||
\mbox{}\verb@ int isRunning(pICountable self);@\\
|
||||
\mbox{}\verb@ long StartCountTask(void *self, SConnection *pCon, char *name);@\\
|
||||
\mbox{}\verb@@$\Diamond$
|
||||
\end{list}
|
||||
\vspace{-1ex}
|
||||
@ -273,6 +281,11 @@ will be returned.
|
||||
{\bf ReleaseCountLock} release the count lock.
|
||||
|
||||
{\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}
|
||||
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,
|
||||
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
|
||||
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
|
||||
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}
|
||||
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);
|
||||
void ReleaseCountLock(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.
|
||||
@ -236,6 +244,11 @@ will be returned.
|
||||
{\bf ReleaseCountLock} release the count lock.
|
||||
|
||||
{\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}
|
||||
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
|
||||
Revised: Mark Koennecke, September 1997
|
||||
|
||||
Removed unused UDP interrupt port stuff
|
||||
|
||||
Mark Koennecke, February 2013
|
||||
|
||||
Copyright: see copyright.h
|
||||
|
||||
@ -22,10 +26,7 @@
|
||||
#include <strlutil.h>
|
||||
|
||||
#include "fortify.h"
|
||||
#include "conman.h"
|
||||
#include "SCinter.h"
|
||||
#include "nserver.h"
|
||||
#include "obdes.h"
|
||||
#include "sics.h"
|
||||
#include "network.h"
|
||||
#include "interrupt.h"
|
||||
#include "status.h"
|
||||
@ -40,8 +41,6 @@
|
||||
#define MAXINTERRUPT 7
|
||||
#define INTERUPTWAIT 5
|
||||
|
||||
static mkChannel *IntPort = NULL;
|
||||
static pTaskMan pTask = NULL;
|
||||
/*----------------------------------------------------------------------------*/
|
||||
static char *pIntText[] = {
|
||||
"continue",
|
||||
@ -53,35 +52,6 @@ static char *pIntText[] = {
|
||||
"end",
|
||||
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)
|
||||
{
|
||||
@ -89,7 +59,7 @@ void SetInterrupt(int 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
|
||||
#---------------------------------------------------------------------------
|
||||
|
||||
EPICSOBJ=epicsmotor.o
|
||||
|
||||
COBJ = Sclient.o network.o ifile.o intcli.o $(FORTIFYOBJ)
|
||||
SOBJ = network.o ifile.o conman.o SCinter.o splitter.o passwd.o \
|
||||
servlog.o sicvar.o nserver.o SICSmain.o motorlist.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 \
|
||||
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 \
|
||||
@ -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 \
|
||||
rwpuffer.o asynnet.o background.o countersec.o hdbtable.o velosec.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
|
||||
COUNTEROBJ = countdriv.o simcter.o counter.o
|
||||
VELOOBJ = velo.o velosim.o
|
||||
|
||||
OBJ = $(SOBJ) $(MOTOROBJ) $(COUNTEROBJ) $(VELOOBJ) $(DIFIL) $(EXTRA)
|
||||
OBJ = $(SOBJ) $(MOTOROBJ) $(COUNTEROBJ) $(VELOOBJ) $(DIFIL) $(EXTRA) $(EPICSOBJ)
|
||||
|
||||
.SUFFIXES:
|
||||
.SUFFIXES: .tcl .htm .c .o .tc
|
||||
@ -65,7 +67,7 @@ all: libmat libhlib libtecsl libpsi SICServer
|
||||
full: purge all
|
||||
|
||||
SICServer: $(OBJ) $(SUBLIBS)
|
||||
$(CC) -g -o SICServer $(OBJ) $(LIBS)
|
||||
$(CC) $(DBG) -o SICServer $(OBJ) $(LIBS)
|
||||
|
||||
matrix/libmatrix.a: libmat
|
||||
|
||||
|
@ -11,19 +11,21 @@ NI= -DHAVENI
|
||||
NIOBJ= nigpib.o
|
||||
NILIB=$(SINQDIR)/sl6/lib/cib.o
|
||||
|
||||
EPICSLIBS=-L$(SINQDIR)/sl6/lib/linux-x86 -lezca -lca -lCom
|
||||
|
||||
include sllinux_def
|
||||
|
||||
CC = gcc
|
||||
CFLAGS = -I$(HDFROOT)/include -DNXXML -DHDF5 $(NI) \
|
||||
-Ipsi/hardsup -I. -MMD \
|
||||
-Werror -DCYGNUS -DNONINTF -g $(DFORTIFY) \
|
||||
-Werror -DCYGNUS -DNONINTF $(DBG) $(DFORTIFY) \
|
||||
-Wall -Wno-unused -Wunused-value -Wno-comment -Wno-switch
|
||||
|
||||
BINTARGET = bin
|
||||
EXTRA=nintf.o
|
||||
SUBLIBS = psi/libpsi.a psi/hardsup/libhlib.a matrix/libmatrix.a \
|
||||
psi/tecs/libtecsl.a
|
||||
LIBS = -L$(HDFROOT)/lib $(SUBLIBS) $(NILIB)\
|
||||
LIBS = -L$(HDFROOT)/lib $(SUBLIBS) $(NILIB) $(EPICSLIBS) \
|
||||
-ltcl $(HDFROOT)/lib/libhdf5.a \
|
||||
$(HDFROOT)/lib/libsz.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 *epicsMakeMotorDriver(char *baseName);
|
||||
|
||||
int MotorCreate(SConnection * pCon, SicsInterp * pSics, void *pData,
|
||||
int argc, char *argv[])
|
||||
@ -1052,6 +1053,23 @@ int MotorCreate(SConnection * pCon, SicsInterp * pSics, void *pData,
|
||||
SCWrite(pCon, pBueffel, eLogError);
|
||||
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 {
|
||||
site = getSite();
|
||||
if (site != NULL) {
|
||||
|
@ -37,6 +37,7 @@ typedef struct {
|
||||
pICountable slaves[MAXSLAVE];
|
||||
char *transferScript;
|
||||
int nSlaves;
|
||||
int checkSlaves;
|
||||
} MultiCounter, *pMultiCounter;
|
||||
/*--------------------------------------------------------------------------*/
|
||||
static void KillMultiDriver(struct __COUNTER *data)
|
||||
@ -106,10 +107,12 @@ static int MMCCStart(void *pData, SConnection * pCon)
|
||||
pCount->isUpToDate = 0;
|
||||
pCount->tStart = time(NULL);
|
||||
InvokeCallBack(pCount->pCall, COUNTSTART, pCon);
|
||||
self->checkSlaves = 0;
|
||||
return OKOK;
|
||||
}
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
|
||||
static int MMCCStatus(void *pData, SConnection * pCon)
|
||||
{
|
||||
int status, i;
|
||||
@ -129,25 +132,46 @@ static int MMCCStatus(void *pData, SConnection * pCon)
|
||||
return HWFault;
|
||||
}
|
||||
|
||||
status = self->slaves[0]->CheckCountStatus(self->slaveData[0], pCon);
|
||||
pMaster = (pCounter)self->slaveData[0];
|
||||
pCount->pDriv->fLastCurrent = GetControlValue(pMaster);
|
||||
if (status == HWIdle || status == HWFault) {
|
||||
/*
|
||||
stop counting on slaves when finished or when an error
|
||||
occurred.
|
||||
*/
|
||||
InvokeCallBack(pCount->pCall, COUNTEND, pCon);
|
||||
MMCCHalt(pCount);
|
||||
}
|
||||
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]);
|
||||
if(self->checkSlaves == 0) {
|
||||
status = self->slaves[0]->CheckCountStatus(self->slaveData[0], pCon);
|
||||
if (status == HWIdle || status == HWFault) {
|
||||
/*
|
||||
stop counting on slaves when finished or when an error
|
||||
occurred.
|
||||
*/
|
||||
MMCCHalt(pData);
|
||||
ReleaseCountLock(pCount->pCountInt);
|
||||
self->checkSlaves = 1;
|
||||
status = HWBusy;
|
||||
}
|
||||
} 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;
|
||||
}
|
||||
|
19
nserver.c
19
nserver.c
@ -39,10 +39,6 @@
|
||||
#include "sicshipadaba.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 */
|
||||
|
||||
@ -236,10 +232,6 @@ int InitServer(char *file, pServer * pServ)
|
||||
IFDeleteOptions(pSICSOptions);
|
||||
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 */
|
||||
AddUser("Achterbahn", "Kiel", usInternal);
|
||||
|
||||
@ -346,10 +338,6 @@ void StopServer(pServer self)
|
||||
/* remove the in memory password database */
|
||||
KillPasswd();
|
||||
|
||||
|
||||
/* close Interrupt system */
|
||||
ServerStopInterrupt();
|
||||
|
||||
/* Remove Status Callback */
|
||||
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)
|
||||
{
|
||||
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"
|
||||
@ -25,19 +25,19 @@
|
||||
#include <ifile.h>
|
||||
#include <hipadaba.h>
|
||||
|
||||
typedef struct {
|
||||
char *name;
|
||||
int (*SaveStatus) (void *self, char *name, FILE * fd);
|
||||
void *(*GetInterface) (void *self, int iInterfaceID);
|
||||
IPair *pKeys;
|
||||
pHdb parNode;
|
||||
} ObjectDescriptor, *pObjectDescriptor;
|
||||
typedef struct {
|
||||
char *name;
|
||||
int (*SaveStatus)(void *self, char *name,FILE *fd);
|
||||
void *(*GetInterface)(void *self, int iInterfaceID);
|
||||
IPair *pKeys;
|
||||
pHdb parNode;
|
||||
} ObjectDescriptor, *pObjectDescriptor;
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
pObjectDescriptor CreateDescriptor(char *name);
|
||||
void DeleteDescriptor(pObjectDescriptor self);
|
||||
pObjectDescriptor FindDescriptor(void *pData);
|
||||
|
||||
pObjectDescriptor CreateDescriptor(char *name);
|
||||
void DeleteDescriptor(pObjectDescriptor self);
|
||||
pObjectDescriptor FindDescriptor(void *pData);
|
||||
|
||||
/*============================================================================
|
||||
Objects which do not carry data need a dummy descriptor. Otherwise
|
||||
drive or scan will protection fault when trying to drive something
|
||||
@ -45,26 +45,26 @@ pObjectDescriptor FindDescriptor(void *pData);
|
||||
*/
|
||||
|
||||
typedef struct {
|
||||
pObjectDescriptor pDescriptor;
|
||||
} Dummy, *pDummy;
|
||||
pObjectDescriptor pDescriptor;
|
||||
}Dummy, *pDummy;
|
||||
|
||||
|
||||
pDummy CreateDummy(char *name);
|
||||
void KillDummy(void *pData);
|
||||
|
||||
pDummy CreateDummy(char *name);
|
||||
void KillDummy(void *pData);
|
||||
int iHasType(void *pData, char *Type);
|
||||
|
||||
#endif
|
||||
|
||||
int iHasType(void *pData, char *Type);
|
||||
|
||||
#endif
|
||||
|
||||
#line 386 "interface.w"
|
||||
#line 399 "interface.w"
|
||||
|
||||
/*--------------------------------------------------------------------------*/
|
||||
/* Additional properties used by the ANSTO site to provide more information
|
||||
* about each object instance, especially devices.
|
||||
*/
|
||||
void SetDescriptorKey(pObjectDescriptor self, char *keyName, char *value);
|
||||
void SetDescriptorGroup(pObjectDescriptor self, char *group);
|
||||
void SetDescriptorDescription(pObjectDescriptor self, char *description);
|
||||
char *GetDescriptorKey(pObjectDescriptor self, char *keyName);
|
||||
char *GetDescriptorGroup(pObjectDescriptor self);
|
||||
char *GetDescriptorDescription(pObjectDescriptor self);
|
||||
void SetDescriptorKey(pObjectDescriptor self, char *keyName, char *value);
|
||||
void SetDescriptorGroup(pObjectDescriptor self, char *group);
|
||||
void SetDescriptorDescription(pObjectDescriptor self, char *description);
|
||||
char * GetDescriptorKey(pObjectDescriptor self, char *keyName);
|
||||
char * GetDescriptorGroup(pObjectDescriptor self);
|
||||
char * GetDescriptorDescription(pObjectDescriptor self);
|
||||
|
15
ofac.c
15
ofac.c
@ -17,6 +17,8 @@
|
||||
#include "site.h"
|
||||
#include "sicshipadaba.h"
|
||||
|
||||
static unsigned int killStartupCommands = 1;
|
||||
|
||||
extern void DevExecInit(void); /* devexec.c */
|
||||
/*--------------------------------------------------------------------------*/
|
||||
static void InitGeneral(void)
|
||||
@ -44,6 +46,7 @@ static void InitGeneral(void)
|
||||
INIT(AddGenBinProtocoll);
|
||||
INIT(AddSyncedProt);
|
||||
INIT(MakeTrace);
|
||||
INIT(InitTaskOBJ);
|
||||
INIT(SiteInit); /* site specific initializations */
|
||||
}
|
||||
|
||||
@ -111,6 +114,7 @@ static void InitIniCommands(SicsInterp * pInter)
|
||||
PCMD("TclReplaceDrivable", TclReplaceDrivable);
|
||||
PCMD("transact", TransactAction);
|
||||
PCMD("wait", UserWait);
|
||||
PCMD("yield", UserYield);
|
||||
PCMD("checksum", CheckSum);
|
||||
|
||||
/* startup commands in alphabetic order */
|
||||
@ -169,7 +173,6 @@ static void InitIniCommands(SicsInterp * pInter)
|
||||
SCMD("SicsAlias", SicsAlias);
|
||||
SCMD("SicsUser", PWSicsUser);
|
||||
SCMD("TokenInit", TokenInit);
|
||||
SCMD("MakeTask", TaskOBJFactory);
|
||||
SCMD("UpdateFactory", UpdateFactory);
|
||||
SCMD("VarMake", VarFactory);
|
||||
SCMD("VelocitySelector", VelSelFactory);
|
||||
@ -229,7 +232,13 @@ int InitObjectCommands(pServer pServ, char *file)
|
||||
if (site != NULL && site->RemoveSiteCommands != NULL) {
|
||||
site->RemoveSiteCommands(pSics);
|
||||
}
|
||||
|
||||
RemoveStartupCommands();
|
||||
if(killStartupCommands){
|
||||
RemoveStartupCommands();
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
void KeepStartupCommands()
|
||||
{
|
||||
killStartupCommands = 0;
|
||||
}
|
||||
|
1
ofac.h
1
ofac.h
@ -21,5 +21,4 @@
|
||||
#include "sics.h"
|
||||
|
||||
int InitObjectCommands(pServer pServ, char *file);
|
||||
|
||||
#endif
|
||||
|
@ -24,6 +24,10 @@
|
||||
static char undef[] = "Undefined";
|
||||
#define IDXFMT " %8.4f"
|
||||
#define ANGFMT " %8.2f"
|
||||
|
||||
int CountTblCmd(pSICSOBJ self, SConnection *pCon, pHdb commandNode,
|
||||
pHdb par[], int nPar); /* from hdbtable.c */
|
||||
|
||||
/*----------------------------------------------------------------------*/
|
||||
typedef struct {
|
||||
int idxCount;
|
||||
@ -549,6 +553,10 @@ pSICSOBJ CreateReflectionList(SConnection * pCon, SicsInterp * pSics,
|
||||
SetHdbProperty(cmd,"priv","user");
|
||||
AddSICSHdbPar(cmd, "id", usUser, MakeHdbText(""));
|
||||
|
||||
|
||||
cmd = AddSICSHdbPar(pNew->objectNode, "count", usUser,
|
||||
MakeSICSFunc(CountTblCmd));
|
||||
|
||||
AddCommand(pSics, name, InterInvokeSICSOBJ, KillSICSOBJ, 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;
|
||||
}
|
||||
|
||||
self->iActive = 1;
|
||||
self->iNP = iNP;
|
||||
self->iMode = iMode;
|
||||
self->fPreset = fPreset;
|
||||
@ -661,7 +662,6 @@ int DoScan(pScanData self, int iNP, int iMode, float fPreset,
|
||||
}
|
||||
|
||||
|
||||
self->iActive = 1;
|
||||
iRet = ScanLoop(self);
|
||||
ScriptScanFinish(self);
|
||||
InvokeCallBack(self->pCall, SCANEND, self);
|
||||
|
@ -148,7 +148,7 @@ static long SCTDRIVSetValue(void *data, SConnection * pCon, float val)
|
||||
}
|
||||
pPriv->pCon = SCCopyConnection(pCon);
|
||||
|
||||
StopByData(pServ->pExecutor, data);
|
||||
/* StopByData(pServ->pExecutor, data); */
|
||||
|
||||
v = MakeHdbFloat(val);
|
||||
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);
|
||||
return 0;
|
||||
}
|
||||
GetHistogramDirect(pHist, pCon, 0, start, end, iData,
|
||||
if(end > GetHistLength(pHist)){
|
||||
GetHistogramDirect(pHist, pCon, 0, start, end, iData,
|
||||
(end - start) * sizeof(int));
|
||||
} else {
|
||||
GetHistogram(pHist, pCon, 0, start, end, iData,
|
||||
(end - start) * sizeof(int));
|
||||
}
|
||||
assignType(self, pos, pos + (end - start), INTTYPE);
|
||||
SCSendOK(pCon);
|
||||
return 1;
|
||||
|
@ -284,7 +284,7 @@ static hdbCallbackReturn SetModeCB(pHdb node, void *userData,
|
||||
priv->mode = Bisecting;
|
||||
initializeSingleBisectingOrion(priv->diffractometer);
|
||||
free(set->v->v.text);
|
||||
set->v->v.text = strdup("bi");
|
||||
set->v->v.text = strdup("bio");
|
||||
return hdbContinue;
|
||||
break;
|
||||
case NB:
|
||||
|
@ -10,4 +10,6 @@
|
||||
MFLAGS=-f makefile_linux$(DUMMY)
|
||||
|
||||
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) {
|
||||
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) {
|
||||
pDriv = GetDrivableInterface(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
|
||||
*/
|
||||
InvokeNewTarget(pServ->pExecutor, name, target);
|
||||
writeMotPos(pCon, silent, name, val, target);
|
||||
}
|
||||
writeMotPos(pCon, silent, name, val, target);
|
||||
return status;
|
||||
}
|
||||
|
||||
@ -313,39 +322,43 @@ static int startMotors(ptasMot self, tasAngles angles,
|
||||
/*
|
||||
monochromator
|
||||
*/
|
||||
status = startTASMotor(self->math->motors[A1], pCon, "a1",
|
||||
angles.monochromator_two_theta / 2., silent, stopFixed);
|
||||
if (status != OKOK) {
|
||||
/* status = startTASMotor(self->math->motors[A1], pCon, "a1", */
|
||||
/* angles.monochromator_two_theta / 2., silent, stopFixed); */
|
||||
/* 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;
|
||||
}
|
||||
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
|
||||
@ -491,24 +504,24 @@ static int calculateAndDrive(ptasMot self, SConnection * pCon)
|
||||
|
||||
switch (status) {
|
||||
case ENERGYTOBIG:
|
||||
SCWrite(pCon, "ERROR: desired energy to big", eError);
|
||||
SCWrite(pCon, "ERROR: desired energy to big", eLogError);
|
||||
return HWFault;
|
||||
break;
|
||||
case UBNOMEMORY:
|
||||
SCWrite(pCon, "ERROR: out of memory calculating angles", eError);
|
||||
SCWrite(pCon, "ERROR: out of memory calculating angles", eLogError);
|
||||
driveQ = 0;
|
||||
break;
|
||||
case BADRMATRIX:
|
||||
SCWrite(pCon, "ERROR: bad crystallographic parameters or bad UB",
|
||||
eError);
|
||||
eLogError);
|
||||
driveQ = 0;
|
||||
break;
|
||||
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;
|
||||
break;
|
||||
case TRIANGLENOTCLOSED:
|
||||
SCWrite(pCon, "ERROR: cannot close scattering triangle", eError);
|
||||
SCWrite(pCon, "ERROR: cannot close scattering triangle", eLogError);
|
||||
driveQ = 0;
|
||||
break;
|
||||
}
|
||||
@ -546,7 +559,7 @@ static int calculateAndDrive(ptasMot self, SConnection * pCon)
|
||||
|
||||
if (driveQ == 0 && self->math->mustDriveQ == 1) {
|
||||
SCWrite(pCon, "WARNING: NOT driving Q-vector because of errors",
|
||||
eError);
|
||||
eLogError);
|
||||
}
|
||||
/*
|
||||
* reset the Q flag
|
||||
@ -577,7 +590,20 @@ static int checkMotors(ptasMot self, SConnection * pCon)
|
||||
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){
|
||||
busy[i] = 0;
|
||||
} else {
|
||||
@ -635,35 +661,39 @@ static int startQMMotors(ptasMot self, tasAngles angles,
|
||||
/*
|
||||
monochromator
|
||||
*/
|
||||
status = startTASMotor(self->math->motors[A1], pCon, "a1",
|
||||
angles.monochromator_two_theta / 2., silent,stopFixed);
|
||||
if (status != OKOK) {
|
||||
return status;
|
||||
}
|
||||
status = startTASMotor(self->math->motors[A2], pCon, "a2",
|
||||
angles.monochromator_two_theta, silent,stopFixed);
|
||||
if (status != OKOK) {
|
||||
return status;
|
||||
}
|
||||
/* status = startTASMotor(self->math->motors[A1], pCon, "a1", */
|
||||
/* angles.monochromator_two_theta / 2., silent,stopFixed); */
|
||||
/* 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) {
|
||||
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) { */
|
||||
/* return status; */
|
||||
/* } */
|
||||
/* } */
|
||||
|
||||
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) {
|
||||
return status;
|
||||
}
|
||||
/* 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) { */
|
||||
/* 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->pData = pData;
|
||||
pNew->pKill = pKill;
|
||||
pNew->lID = lIDMama++;
|
||||
lIDMama++;
|
||||
pNew->lID = lIDMama;
|
||||
pNew->iStatus = READY;
|
||||
|
||||
if(lIDMama < 0){
|
||||
@ -455,6 +456,25 @@ int isTaskRunning(pTaskMan self, char *name)
|
||||
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)
|
||||
{
|
||||
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)
|
||||
{
|
||||
lIDMama++;
|
||||
|
23
task.h
23
task.h
@ -6,7 +6,10 @@
|
||||
a yield and a primitive form of inter task communication is implemented.
|
||||
|
||||
Mark Koennecke, September 1997
|
||||
|
||||
|
||||
extended to suuport task groups
|
||||
Mark Koennecke, December 2012
|
||||
|
||||
copyright: see implementation file
|
||||
-----------------------------------------------------------------------------*/
|
||||
#ifndef TASKOMAT
|
||||
@ -144,6 +147,11 @@ int TaskSignal(pTaskMan self, int iSignal, void *pSigData);
|
||||
/*
|
||||
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:
|
||||
|
||||
@ -177,6 +185,19 @@ char *TaskDescription(pTaskHead it);
|
||||
get a description of the task at the current iterator
|
||||
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
|
||||
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;
|
||||
}
|
||||
|
||||
if(!SCMatchRights(pCon,usMugger)){
|
||||
return 0;
|
||||
}
|
||||
|
||||
status = StopTask(pServ->pTasker,par[0]->value.v.text);
|
||||
if(status == 0) {
|
||||
SCWrite(pCon,"ERROR: cannot commit suicide!", eError);
|
||||
@ -183,3 +187,37 @@ int TaskOBJFactory(SConnection *pCon, SicsInterp *pSics, void *pData,
|
||||
|
||||
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 "tasdrive.h"
|
||||
#include "vector.h"
|
||||
#include "tasmono.h"
|
||||
/*------------------- motor indexes in motor data structure ---------*/
|
||||
#define A1 0
|
||||
#define A2 1
|
||||
@ -173,6 +174,8 @@ static ptasUB MakeTasUB()
|
||||
pNew->actualEn = .0;
|
||||
pNew->outOfPlaneAllowed = 1;
|
||||
pNew->mustRecalculate = 1;
|
||||
pNew->mono = MakeTasMono();
|
||||
pNew->monoData = pNew;
|
||||
|
||||
return pNew;
|
||||
}
|
||||
@ -198,6 +201,9 @@ static void KillTasUB(void *pData)
|
||||
if(self->updater != NULL){
|
||||
free(self->updater);
|
||||
}
|
||||
if(self->mono != NULL){
|
||||
free(self->mono);
|
||||
}
|
||||
free(self);
|
||||
}
|
||||
|
||||
|
3
tasub.h
3
tasub.h
@ -30,6 +30,9 @@
|
||||
int mustDriveQ;
|
||||
pMotor motors[12];
|
||||
tasReflection r1, r2;
|
||||
pIDrivable mono;
|
||||
long monoTaskID;
|
||||
void *monoData;
|
||||
int ubValid;
|
||||
int silent;
|
||||
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)
|
||||
{
|
||||
if(log != NULL && filter(sub,id)){
|
||||
strrepc(data,'\n',':');
|
||||
strrepc(sub,':','@');
|
||||
strrepc(id,':','@');
|
||||
fprintf(log,"%s:%s:%lf:%s\n",sub,id,DoubleTime(),data);
|
||||
}
|
||||
char *mysub, *myid, *mydata;
|
||||
|
||||
if(log != NULL && filter(sub,id)){
|
||||
mysub = strdup(sub);
|
||||
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, ...)
|
||||
|
38
ubcalc.c
38
ubcalc.c
@ -10,6 +10,10 @@
|
||||
Heavily reworked to fit into the new four circle system
|
||||
|
||||
Mark Koennecke, July 2008
|
||||
|
||||
Added UBfromCell
|
||||
|
||||
Mark Koennecke, March 2013
|
||||
-----------------------------------------------------------------------*/
|
||||
#include <stdlib.h>
|
||||
#include <assert.h>
|
||||
@ -252,7 +256,39 @@ static int calcUB(pUBCALC self, SConnection * pCon, char *ref1, char *ref2)
|
||||
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,
|
||||
pHKL hkl, MATRIX UB)
|
||||
@ -551,6 +587,8 @@ int UBCalcWrapper(SConnection * pCon, SicsInterp * pSics, void *pData,
|
||||
return sendUBToHKL(pCon, pSics, self->hkl, self->UB);
|
||||
} else if (strcmp(argv[1], "index") == 0) {
|
||||
return findIndex(self, pCon, pSics, argc, argv);
|
||||
} else if (strcmp(argv[1], "fromcell") == 0) {
|
||||
return UBFromCell(self, pCon);
|
||||
} else {
|
||||
if (argc > 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
|
||||
* @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
|
||||
*/
|
||||
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);
|
||||
site = getSite();
|
||||
if (site != NULL) {
|
||||
if (site != NULL && site->CreateVelocitySelector != NULL) {
|
||||
pDriv = site->CreateVelocitySelector(argv[3], argv[4], pT);
|
||||
}
|
||||
if (!pDriv) {
|
||||
|
Reference in New Issue
Block a user