- First working version of the TRICS collision protection module

This commit is contained in:
cvs
2002-08-14 14:24:00 +00:00
parent a59f15d5f0
commit 3ba5f28b65
35 changed files with 1427 additions and 77 deletions

115
Busy.c Normal file
View File

@ -0,0 +1,115 @@
/*------------------------------------------------------------------------
A busy flag module for SICS.
Mark Koennecke, July 2002
-------------------------------------------------------------------------*/
#include <stdlib.h>
#include <assert.h>
#include "fortify.h"
#include "sics.h"
/*----------------------------------------------------------------------*/
typedef struct BUSY__ {
pObjectDescriptor pDes;
int iBusy;
}Busy;
/*---------------------------------------------------------------------*/
busyPtr makeBusy(void){
busyPtr result = NULL;
result = (busyPtr)malloc(sizeof(Busy));
if(!result){
return NULL;
}
result->pDes = CreateDescriptor("BusyFlag");
if(!result->pDes){
free(result);
return NULL;
}
result->iBusy = 0;
return result;
}
/*---------------------------------------------------------------------*/
void killBusy(void *self){
busyPtr busy;
if(self != NULL){
busy = (busyPtr)self;
if(busy->pDes != NULL){
DeleteDescriptor(busy->pDes);
}
free(busy);
}
}
/*---------------------------------------------------------------------*/
void incrementBusy(busyPtr self){
assert(self != NULL);
self->iBusy++;
}
/*--------------------------------------------------------------------*/
void decrementBusy(busyPtr self){
assert(self != NULL);
self->iBusy--;
if(self->iBusy < 0){
self->iBusy = 0;
}
}
/*--------------------------------------------------------------------*/
void clearBusy(busyPtr self){
assert(self != NULL);
self->iBusy = 0;
}
/*--------------------------------------------------------------------*/
void setBusy(busyPtr self, int val){
assert(self != NULL);
self->iBusy = val;
}
/*--------------------------------------------------------------------*/
int isBusy(busyPtr self){
assert(self != NULL);
return self->iBusy;
}
/*--------------------------------------------------------------------*/
int BusyAction(SConnection *pCon,SicsInterp *pSics, void *pData,
int argc, char *argv[]){
busyPtr self = NULL;
char pBuffer[80];
self = (busyPtr)pData;
assert(self != NULL);
if(argc > 1){
strtolower(argv[1]);
if(usUser < SCGetRights(pCon)){
SCWrite(pCon,"ERROR: no privilege to manipulate busy flag",eError);
return 0;
}
if(strcmp(argv[1],"incr") == 0){
incrementBusy(self);
SCSendOK(pCon);
return 1;
} else if(strcmp(argv[1],"decr") == 0){
decrementBusy(self);
SCSendOK(pCon);
return 1;
} else if(strcmp(argv[1],"clear") == 0){
clearBusy(self);
SCSendOK(pCon);
return 1;
}
}
sprintf(pBuffer,"Busy = %d", isBusy(self));
SCWrite(pCon,pBuffer,eValue);
return 1;
}
/*---------------------------------------------------------------------*/
busyPtr findBusy(SicsInterp *pInter){
CommandList *pCom = NULL;
pCom = FindCommand(pInter,"busy");
if(pCom != NULL){
return (busyPtr)pCom->pData;
}
}

28
Busy.h Normal file
View File

@ -0,0 +1,28 @@
/*------------------------------------------------------------------------
A busy flag module for SICS.
Mark Koennecke, July 2002
-------------------------------------------------------------------------*/
#ifndef SICSBUSY
#define SICSBUSY
typedef struct BUSY__ *busyPtr;
busyPtr makeBusy(void);
void killBusy(void *self);
void incrementBusy(busyPtr self);
void decrementBusy(busyPtr self);
void clearBusy(busyPtr self);
void setBusy(busyPtr self, int val);
int isBusy(busyPtr self);
int BusyAction(SConnection *pCon, SicsInterp *pSics, void *pData,
int argc, char *argv[]);
busyPtr findBusy(SicsInterp *pInter);
#endif

41
Busy.w Normal file
View File

@ -0,0 +1,41 @@
\subsection{Busy}
This class implements a busy flag which should be set when the interpreter
is busy doing something, like scanning for instance. The primary use
is for AMOR where operations are possible while writing data. This is
not caught by the normal device executor logic. In the long run, this
should become the standard way to control access to the
interpreter. In order to ensure access control, a test for the busy
flag is included into the SCMatchRights procedure. The busy flag is
installed into the interpreter.
@o Busy.h @{
/*------------------------------------------------------------------------
A busy flag module for SICS.
Mark Koennecke, July 2002
-------------------------------------------------------------------------*/
#ifndef SICSBUSY
#define SICSBUSY
typedef struct BUSY__ *busyPtr;
busyPtr makeBusy(void);
void killBusy(void *self);
void incrementBusy(busyPtr self);
void decrementBusy(busyPtr self);
void clearBusy(busyPtr self);
void setBusy(busyPtr self, int val);
int isBusy(busyPtr self);
int BusyAction(SConnection *pCon, SicsInterp *pSics, void *pData,
int argc, char *argv[]);
busyPtr findBusy(SicsInterp *pInter);
#endif
@}

View File

@ -49,7 +49,7 @@ SOBJ = network.o ifile.o conman.o SCinter.o splitter.o passwd.o \
tasinit.o tasutil.o t_rlp.o t_conv.o d_sign.o d_mod.o \
tasdrive.o tasscan.o synchronize.o definealias.o swmotor.o t_update.o \
hmcontrol.o userscan.o slsmagnet.o rs232controller.o lomax.o \
polterwrite.o fourlib.o
polterwrite.o fourlib.o motreg.o motreglist.o anticollider.o
MOTOROBJ = motor.o el734driv.o simdriv.o el734dc.o pipiezo.o pimotor.o
COUNTEROBJ = countdriv.o simcter.o counter.o

View File

@ -51,9 +51,13 @@
#include "splitter.h"
#include "servlog.h"
#include "macro.h"
#include "interface.h"
#include "obdes.h"
/* M.Z. */
#include "definealias.h"
#define MAXLEN 256
#define MAXPAR 100
@ -545,4 +549,19 @@ extern char *SkipSpace(char *pPtr);
}
return NULL;
}
/*------------------------------------------------------------------------*/
void *FindDrivable(SicsInterp *pSics, char *name){
pIDrivable pDriv;
pDummy pDum = NULL;
CommandList *pCom = NULL;
pCom = FindCommand(pSics,name);
if(pCom != NULL){
pDum = (pDummy)pCom->pData;
if(pDum != NULL){
return pDum->pDescriptor->GetInterface(pDum,DRIVEID);
}
}
return NULL;
}

View File

@ -133,5 +133,13 @@ typedef struct __SINTER
*/
void *FindCommandData(SicsInterp *pSics, char *name, char *comclass);
/*------------------------------------------------------------------------
FindDrivable tries to find Drivable object by the name given. Returns a
pointer to the drivable interface in the case of success, NULL in
case of failure. In order to save me fixing header files the pointer must
be cast to the drivable interface pointer.
------------------------------------------------------------------------*/
void *FindDrivable(SicsInterp *pics, char *name);
#endif

375
anticollider.c Normal file
View File

@ -0,0 +1,375 @@
/*----------------------------------------------------------------------
This is the implementation file for the AntiCollider, a complex movements
control module for SICS. See anticoliider.tex for more information.
copyright: see file copyright
Mark Koennecke, August 2002
------------------------------------------------------------------------*/
#include <stdlib.h>
#include <assert.h>
#include <tcl.h>
#include "fortify.h"
#include "lld.h"
#include "motreglist.h"
#include "anticollider.i"
#include "anticollider.h"
/*---------------------------------------------------------------------
As there should be only one AntiCollider in a system, I use a static
pointer to the AntiCollider here in order to facilitate access.
Otherwise more complex mechanisms must be divised in order to pass this
pointer into ColliderSetValue and ColliderCheckStatus
----------------------------------------------------------------------*/
static pAntiCollider myCollider = NULL;
/*--------------------------------------------------------------------
the replacement function for the motor's drivable interface SetValue
function. It enters the new target into the motor list.
---------------------------------------------------------------------*/
static long ReplacementSetValue(void *pData, SConnection *pCon, float fTarget){
pMotReg pMot = NULL;
assert(myCollider != NULL);
pMot = FindMotFromDataStructure(myCollider->motorList,pData);
if(pMot != NULL){
SetRegMotTarget(pMot,fTarget);
myCollider->isDirty = 1;
} else {
return 0;
}
return 1;
}
/*---------------------------------------------------------------------
The replacement CheckStatus function for controlled motors.
Start AntiCollider if not running and finish. Rest of work done by
AntiCollider.
-----------------------------------------------------------------------*/
static int ReplacementCheckStatus(void *pData, SConnection *pCon){
pMotReg pMot = NULL;
assert(myCollider != NULL);
if(myCollider->isDirty == 1){
myCollider->isDirty = 0;
StartDevice(pServ->pExecutor,
"anticollider",
myCollider->pDes,
myCollider,
pCon,
77.77);
return HWIdle;
} else {
return HWIdle;
}
}
/*------------------------------------------------------------------------
The collider SetValue function
-------------------------------------------------------------------------*/
static long ColliderSetValue(void *pData, SConnection *pCon, float fTarget){
pAntiCollider self = (pAntiCollider) pData;
int iRet;
pMotReg pMot = NULL;
char pBueffel[80];
char *ruenBuffer = NULL;
Tcl_DString command;
/*
build command list
*/
if(self->colliderScript == NULL){
SCWrite(pCon,"ERROR: no collider script defined",eError);
return 0;
}
Tcl_DStringInit(&command);
Tcl_DStringAppend(&command,self->colliderScript,-1);
iRet = LLDnodePtr2First(self->motorList);
while(iRet != 0){
LLDnodeDataTo(self->motorList,&pMot);
if(pMot != NULL){
if(pMot->iActive){
CreateTargetString(pMot,pBueffel);
Tcl_DStringAppend(&command, pBueffel,-1);
pMot->iActive = 0;
}
}
iRet = LLDnodePtr2Next(self->motorList);
}
printf("%s\n", Tcl_DStringValue(&command));
/*
kill old collider sequence
*/
LLDdelete(self->sequenceList);
self->sequenceList = LLDcreate(sizeof(Sequence));
self->level = 0;
/*
evaluate colliderScript
*/
iRet = Tcl_Eval(pServ->pSics->pTcl,Tcl_DStringValue(&command));
if(iRet != TCL_OK){
SCWrite(pCon,"ERROR: Movement not possible or bad collider script",eError);
/*
SCWrite(pCon,pServ->pSics->pTcl->result,eError);
*/
SCSetInterrupt(pCon,eAbortOperation);
return 0;
}
/*
we are set
*/
Tcl_DStringFree(&command);
return 1;
}
/*----------------------------------------------------------------------
The Collider CheckStatus function
-----------------------------------------------------------------------*/
static int ColliderCheckStatus(void *pData, SConnection *pCon){
int count = 0;
pAntiCollider self = (pAntiCollider) pData;
assert(self);
if(SCGetInterrupt(pCon) != eContinue){
return HWIdle;
}
count = CheckAllMotors(self->motorList,pCon);
if(count == 0){
self->level++;
count = StartLevel(self->level,
self->sequenceList,
self->motorList,
pCon);
if(count == 0){
/*
no more levels. All done
*/
return HWIdle;
} else {
return HWBusy;
}
} else {
return HWBusy;
}
}
/*----------------------------------------------------------------------
Most of these are dummies........
-----------------------------------------------------------------------*/
static int ColliderHalt(void *pData){
StopExe(pServ->pExecutor,"all");
return 1;
}
/*---------------------------------------------------------------------*/
static int ColliderLimits(void *self, float fVal, char *error,
int iErren){
return 1;
}
/*--------------------------------------------------------------------*/
static float ColliderGetValue(void *self, SConnection *pCon){
return 77.77;
}
/*--------------------------------------------------------------------*/
int StartLevel(int level, int sequenceList, int motorList, SConnection *pCon){
Sequence seq;
pMotReg pMot = NULL;
int iRet;
int count = 0;
char pBueffel[132];
iRet = LLDnodePtr2First(sequenceList);
while(iRet != 0){
LLDnodeDataTo(sequenceList,&seq);
if(seq.level == level){
pMot = FindMotEntry(motorList,seq.pMotor);
if(pMot){
StartRegMot(pMot,pCon,seq.target);
count++;
} else {
sprintf(pBueffel,"ERROR: motor %s, requested from anticollider script",
seq.pMotor);
SCWrite(pCon,pBueffel,eError);
SCWrite(pCon,"ERROR: motor NOT found, fix script!",eError);
}
}
iRet = LLDnodePtr2Next(sequenceList);
}
return count;
}
/*--------------------------------------------------------------------*/
static void ListSequence(int sequenceList, SConnection *pCon){
Sequence seq;
int iRet;
char pBueffel[132];
SCWrite(pCon,"level motor target",eValue);
iRet = LLDnodePtr2First(sequenceList);
while(iRet != 0){
LLDnodeDataTo(sequenceList,&seq);
sprintf(pBueffel,"%d %s %f",seq.level,seq.pMotor,seq.target);
SCWrite(pCon,pBueffel,eValue);
iRet = LLDnodePtr2Next(sequenceList);
}
}
/*-------------------------------------------------------------------------*/
static void *ColliderGetInterface(void *pData, int iID) {
pAntiCollider self = NULL;
self = (pAntiCollider)pData;
assert(self);
if(iID == DRIVEID){
return self->pDriv;
}
return NULL;
}
/*----------------------------------------------------------------------*/
void KillCollider(void *pData){
pAntiCollider self = (pAntiCollider)pData;
if(self == NULL){
return;
}
if(self->pDes != NULL){
DeleteDescriptor(self->pDes);
}
if(self->pDriv != NULL){
free(self->pDriv);
}
if(self->colliderScript != NULL){
free(self->colliderScript);
}
if(self->motorList > 0){
KillMotList(self->motorList);
}
if(self->sequenceList > 0){
LLDdelete(self->sequenceList);
}
free(self);
myCollider = NULL;
}
/*-----------------------------------------------------------------------*/
int AntiColliderFactory(SConnection *pCon, SicsInterp *pSics,
void *pData,
int argc, char *argv[]){
myCollider = (pAntiCollider)malloc(sizeof(AntiCollider));
if(myCollider == NULL){
SCWrite(pCon,"ERROR: out of memory when generating AntiCollider",eError);
return 0;
}
memset(myCollider,0,sizeof(AntiCollider));
myCollider->pDes = CreateDescriptor("AntiCollider");
myCollider->pDriv = CreateDrivableInterface();
if(!myCollider->pDes || !myCollider->pDriv){
KillCollider(myCollider);
SCWrite(pCon,"ERROR: out of memory when generating AntiCollider",eError);
return 0;
}
myCollider->pDes->GetInterface = ColliderGetInterface;
myCollider->pDriv->Halt = ColliderHalt;
myCollider->pDriv->CheckLimits = ColliderLimits;
myCollider->pDriv->SetValue = ColliderSetValue;
myCollider->pDriv->CheckStatus = ColliderCheckStatus;
myCollider->pDriv->GetValue = ColliderGetValue;
myCollider->motorList = LLDcreate(sizeof(void *));
myCollider->sequenceList = LLDcreate(sizeof(Sequence));
AddCommand(pSics,"anticollision",AntiColliderAction,
KillCollider,
myCollider);
return 1;
}
/*------------------------------------------------------------------------*/
int AntiColliderAction(SConnection *pCon, SicsInterp *pSics,
void *pData,
int argc, char *argv[]){
pAntiCollider self = (pAntiCollider)pData;
Sequence seq;
char pBueffel[256];
pMotReg pMot = NULL;
assert(self != NULL);
if(argc > 1){
if(strcmp(argv[1],"clear") == 0){
if(!SCMatchRights(pCon,usMugger)){
return 0;
}
LLDdelete(self->sequenceList);
self->sequenceList = LLDcreate(sizeof(Sequence));
SCSendOK(pCon);
return 1;
} else if(strcmp(argv[1],"list") == 0){
ListSequence(self->sequenceList,pCon);
return 1;
}
}
if(argc < 3){
SCWrite(pCon,"ERROR : insufficient number of arguments to anticollision",
eError);
return 0;
}
strtolower(argv[1]);
if(strcmp(argv[1],"script") == 0){
if(!SCMatchRights(pCon,usMugger)){
return 0;
}
if(self->colliderScript != NULL){
free(self->colliderScript);
}
self->colliderScript = strdup(argv[2]);
SCSendOK(pCon);
return 1;
} else if(strcmp(argv[1],"register") == 0){
if(!SCMatchRights(pCon,usMugger)){
return 0;
}
if(FindDrivable(pSics,argv[2]) == NULL){
sprintf(pBueffel,"ERROR: %s is NOT drivable, cannot register",argv[2]);
SCWrite(pCon,pBueffel,eError);
return 0;
}
pMot = RegisterMotor(argv[2],pSics,
ReplacementSetValue,
ReplacementCheckStatus);
if(pMot){
LLDnodeAppendFrom(self->motorList,&pMot);
SCSendOK(pCon);
return 1;
} else {
SCWrite(pCon,"ERROR: out of memory registering motor",eError);
return 0;
}
} else if(strcmp(argv[1],"add") == 0){
if(argc < 5){
SCWrite(pCon,
"ERROR: InsUfficient number of arguments to anticollicion add",
eError);
return 0;
}
seq.level = atoi(argv[2]);
strncpy(seq.pMotor,argv[3],79);
seq.target = atof(argv[4]);
LLDnodeAppendFrom(self->sequenceList,&seq);
SCSendOK(pCon);
return 1;
}
SCWrite(pCon,"ERROR: anticollider command not understood",eError);
return 0;
}

25
anticollider.h Normal file
View File

@ -0,0 +1,25 @@
/*----------------------------------------------------------------------
This is the header file for the AntiCollider, a complex movements
control module for SICS. See anticoliider.tex for more information.
copyright: see file copyright
Mark Koennecke, August 2002
------------------------------------------------------------------------*/
#ifndef ANTICOLLIDER
#define ANTICOLLIDER
int AntiColliderFactory(SConnection *pCon, SicsInterp *pSics,
void *pData,
int argc, char *argv[]);
int AntiColliderAction(SConnection *pCon, SicsInterp *pSics,
void *pData,
int argc, char *argv[]);
#endif

275
anticollider.w Normal file
View File

@ -0,0 +1,275 @@
\subsubsection{The Anti Collider}
In some cases certain instrument positions can only be reached through
special sequences of drive instructions. Usually because some concrete
blocks or unduly bulky sample environment devices are in the path of
the instrument. Such cases can not be handled through primitive motor
limits. Handling such cases is the objective of the Anti Collider.
The first thing needed is that motors involved with such complex
movements are registered with the Anti Collider. In this stage the
Anti Collider will take over the SetValue and CheckStatus functions of
the drivable interface of the motor. SetValue will be replaced by a
function which will register the drive request with the Anti
Collider. CheckStatus will be replaced by a version which checks with
the Anti Collider if the complex movement has finished.
It is expected that coordinated and complex movements are initiated
within a single command. The first checkpoint where the complex
movement can be analyzed and coordinated the is when the device
executor calls CheckStatus for the first time. CheckStatus will detect
this condition and proceeds to call a Tcl procedure which then has to
create a r\"unb\"uffer which holds the necessary commands to drive the
complex movement. Or returns an error if the movement is not
possible. This scheme allows the instrument scientist to adapt the
way how the instrument moves to new sample environment devices, new
ideas or the growth of experience. Moreover this scheme allows to
handle all instruments with just a single module. As the Anti Collider
has taken over the SetValue method of the drivable interface of the
motor a command is provided which allows to start the actual motor.
The user supplied Tcl script receives as arguments a list of motor and
target values to be driven. The script then has to return either an
error if the movement is not possible or the name of a r\"unb\"uffer
which performs the movement.
The first thing needed for all this is a data structure which holds
the registration information and status of the controlled motor. This
information will be kept in a list holding the data tsrucutre given
below:
@d motreg @{
typedef struct __MOTREG {
void *motorData;
char *motorName;
float targetPosition;
long (*originalSetValue)(void *motorData,
SConnection *pCon,
float fTarget);
int (*originalCheckStatus)(void *motorData,
SConnection *pCon);
int iActive;
} MotReg, *pMotReg;
@}
The fields are:
\begin{description}
\item[motorData] The motor data structure.
\item[motorName] The name of the motor operating.
\item[targetPosition] The requested target position for this motor.
\item[originalSetValue] the original motor starting function.
\item[originalCheckStatus] The original status checking function.
\item[iActive] A flag denoting if the motor has been started by the
Anti Collider. This causes the motors status to be checked which
checking status. If the motor becomes idle, this is set to 0 again.
\end{description}
The following interface functions are defined for this datastructure:
@d motregint @{
pMotReg RegisterMotor(char *name, SicsInterp *pSics,
long (*SetValue)(void *pData, SConnection *pCon, float
fTarget),
int (*CheckStatus)(void *pData, SConnection *pCon));
void KillRegMot(void *self);
void SetRegMotTarget(pMotReg self, float target);
void CreateTargetString(pMotReg self, char pBueffel[80]);
int RegMotMatch(pMotReg self, char *name);
int StartRegMot(pMotReg self, SConnection *pCon, float fValue);
int CheckRegMot(pMotReg self, SConnection *pCon);
@}
The functions in detail:
\begin{description}
\item[RegisterMotor] tries to find the motor name in the interpreter
pSics. Then all necessary manipulations are performed in order to
register the motor. In ths case of success a pointer to a new RegMot
data structure is returned. In the event of failure, NULL is
returned. Of course this function has to take the function pointers to
the drivable interface functions to replace as parameters.
\item[KillRegMot] kills a RegMot structure.
\item[SetRegMotTarget] sets a new target for a complex movement.
\item[CreateTragetString] creates in pBueffel this motors contribution
to a complex movement.
\item[RegMotMatch] returns 1 (true) if the string name matches the name stored
for this motor. Else 0. This will be used when searching for a
registered motor in the list.
\item[StartRegMot] will actually cause a real motor to start driving
towards the target given in fValue. The return value is the result of
the original motors SetValue method.
\item[CheckRegMot] checks for error conditions on the motor.
\end{description}
Moreover it is convenient to define a couple of convenience functions
for handling the list of registered motors. The actual list is
managed through the lld functions as everywhere within SICS.
@d motlist @{
int MakeMotList();
pMotReg FindMotEntry(int iList,char *name);
pMotReg FindMotFromDataStructure(int iList, void *pData);
int CheckAllMotors(int iList, SConnection *pCon);
void KillMotList(int iList);
@}
The functions:
\begin{description}
\item[MakeMotList] creates a new list for MotReg structures and
returns the handle for it.
\item[FindMotEntry] locates a motor in the list by name. If a matching
motor can be found, this function returns a pointer to the motors
MotReg structure. In the case of failure NULL is returned.
\item[FindMotFromDataStructure] locates a motor in the list through
the pointer to its data structure. . If a matching
motor can be found, this function returns a pointer to the motors
MotReg structure. In the case of failure NULL is returned.
\item[CheckAllMotors] checks all the active motors for the finished
condition. The number of running motors is returned. 0 if none is running.
\item[KillMotList] kills the list and all entries in it.
\end{description}
In order to know how the anticollider has to run the motors a means is
needed to hold the sequence of motors to drive. This information must
be configured from the anticollider script. The information is held in
another list in a special data structure.
@d seqlist @{
typedef struct {
int level;
char pMotor[80];
float target;
}Sequence;
int StartLevel(int level, int sequenceList, int motorList,
SConnection *pCon);
@}
The fields and functions are:
\begin{description}
\item[level] The level at which this motor shall be started.
\item[pMotor] The name of the motor to start.
\item[target] The target value for the motor.
\item[StartLevel] starts all motors belonging to a the level
specified. Returns the number of motors started or ) if none is
started. This last condition is also the condition when levels are
exhausted and we need to finish running the anticollider.
\end{description}
The anticollider itself is characterized through the following data
structure:
@d antidat @{
typedef struct __ANTICOLLIDER{
pObjectDescriptor pDes;
pIDrivable pDriv;
int motorList;
int sequenceList;
char *colliderScript;
int isDirty;
int level;
}AntiCollider, *pAntiCollider;
@}
The fields are:
\begin{description}
\item[pDes] The object descriptor required by SICS.
\item[motorList] The list of registered motors.
\item[colliderScript] the Tcl script called to calculate the movement.
\item[iDirty] a flag which is set to 1 (true) when a new movement must
be calculated.
\end{description}
Most of the anticolliders functionality is implemented in interface
functions. The interface to the outside world is purely defined
through the interpreter functions.
@d antiint @{
int AntiColliderFactory(SConnection *pCon, SicsInterp *pSics,
void *pData,
int argc, char *argv[]);
int AntiColliderAction(SConnection *pCon, SicsInterp *pSics,
void *pData,
int argc, char *argv[]);
@}
@o motreg.h @{
/*-------------------------------------------------------------------------
R e g M o t
This is a helper module for the Anti Collider. It handles all the
stuff necessary for dealing with a single motor. For more
information see the file anticollider.tex.
copyright: see file copyright
Mark Koennecke, August 2002
-----------------------------------------------------------------------*/
#ifndef REGMOT
#define REGMOT
#include "sics.h"
@<motreg@>
/*----------------------------------------------------------------------*/
@<motregint@>
#endif
@}
@o motreglist.h @{
/*-----------------------------------------------------------------------
A couple of utility functions for handling a list of MotReg
structures . This is a helper module for the anticollider collision
control system. See anticollider.tex for more details.
copyright: see file copyright
Mark Koennecke, August 2002
-------------------------------------------------------------------------*/
#ifndef MOTREGLIST
#define MOTREGLIST
#include "motreg.h"
@<motlist@>
#endif
@}
@o anticollider.i @{
/*-------------------------------------------------------------------------
Anticollider internal data structure definition. Generated from
anticollider.w. Do not edit.
-------------------------------------------------------------------------*/
@<antidat@>
@<seqlist@>
@}
@o anticollider.h @{
/*----------------------------------------------------------------------
This is the header file for the AntiCollider, a complex movements
control module for SICS. See anticoliider.tex for more information.
copyright: see file copyright
Mark Koennecke, August 2002
------------------------------------------------------------------------*/
#ifndef ANTICOLLIDER
#define ANTICOLLIDER
@<antiint@>
#endif
@}

View File

@ -1,3 +1,3 @@
226
231
NEVER, EVER modify or delete this file
You'll risk eternal damnation and a reincarnation as a cockroach!|n

View File

@ -7,6 +7,7 @@
Substantial rewrite: Mark Koennecke, February 1997
revised: Mark Koennecke, June 1997
revised for use with tasker: Mark Koennecke, September 1997
Locking added: Mark Koennecke, August 2002
Copyright:
@ -103,6 +104,7 @@
int iEnd;
long lTask;
pTaskMan pTask;
int iLock;
} ExeList;
static pExeList pExecutor = NULL;
@ -136,6 +138,7 @@
pRes->iStatus = DEVDONE;
pRes->pTask = pTask;
pRes->lTask = -1;
pRes->iLock = 0;
return pRes;
}
/*-------------------------------------------------------------------------*/
@ -181,6 +184,11 @@
{
self->pOwner = pCon;
}
if(self->iLock == 1)
{
SCWrite(pCon,"ERROR: instrument is locked",eError);
return 0;
}
/* well create a new entry */
self->iStop = 0;
@ -478,7 +486,7 @@
/* do nothing if not running */
if(self->lTask < 0)
{
printf("Wait4Success finished very, very badly\n");
printf("Nothing to wait for....\n");
return self->iStatus;
}
@ -749,6 +757,7 @@
self->iEnd = 1;
self->lTask = -1;
self->iRun = 0;
self->iLock = 0;
}
/*-------------------------------------------------------------------------*/
int StopCommand(SConnection *pCon, SicsInterp *pSics, void *pData,
@ -922,6 +931,18 @@
}
}
}
/*--------------------------------------------------------------------*/
void LockDeviceExecutor(pExeList self)
{
assert(self);
self->iLock = 1;
}
/*--------------------------------------------------------------------*/
void UnlockDeviceExecutor(pExeList self)
{
assert(self);
self->iLock = 0;
}

View File

@ -1,5 +1,5 @@
#line 184 "devexec.w"
#line 195 "devexec.w"
/*----------------------------------------------------------------------------
@ -54,7 +54,7 @@
int StartCounter(pExeList self, SicsInterp *pSics, SConnection *pCon,
char *name);
#line 228 "devexec.w"
#line 239 "devexec.w"
/*------------------------------------------------------------------------*/
@ -73,7 +73,7 @@
void DevExecSignal(void *pEL, int iSignal, void *pSigData);
#line 230 "devexec.w"
#line 241 "devexec.w"
/*
@ -115,7 +115,7 @@
int ContinueExecution(pExeList self);
#line 248 "devexec.w"
#line 259 "devexec.w"
/*-------------------------- Commands ------------------------------------*/
int StopCommand(SConnection *pCon, SicsInterp *pSics, void *pData,
@ -137,6 +137,15 @@
connection with non blocking operation such as motors started
with run.
*/
/*--------------------------- Locking ---------------------------------*/
#line 183 "devexec.w"
void LockDeviceExecutor(pExeList self);
void UnlockDeviceExecutor(pExeList self);
#line 281 "devexec.w"
/* -------------------------- Executor management -------------------------*/

View File

@ -212,6 +212,29 @@ take care of invoking the apropriate commands on all registered counting
devices.
\subsubsection{Locking the Device Executor}
In some instances user code may wish to lock the device executor. An
example is a long running data saving operation. In order to do this
two functions are provided:
\begin{flushleft} \small
\begin{minipage}{\linewidth} \label{scrap4}
$\langle$devlock {\footnotesize ?}$\rangle\equiv$
\vspace{-1ex}
\begin{list}{}{} \item
\mbox{}\verb@@\\
\mbox{}\verb@ void LockDeviceExecutor(pExeList self);@\\
\mbox{}\verb@ void UnlockDeviceExecutor(pExeList self);@\\
\mbox{}\verb@@\\
\mbox{}\verb@@$\diamond$
\end{list}
\vspace{-1ex}
\footnotesize\addtolength{\baselineskip}{-1ex}
\begin{list}{}{\setlength{\itemsep}{-\parsep}\setlength{\itemindent}{-\leftmargin}}
\item Macro referenced in scrap ?.
\end{list}
\end{minipage}\\[4ex]
\end{flushleft}
\subsubsection{The Rest}
The rest of the interface includes initialisation and deletion routines
and some access routines. With the devexec being such an important system
@ -219,7 +242,7 @@ component a function {\bf GetExecutor} is provided which retrieves a pointer
to the global SICS device executor.
\begin{flushleft} \small
\begin{minipage}{\linewidth} \label{scrap4}
\begin{minipage}{\linewidth} \label{scrap5}
\verb@"devexec.h"@ {\footnotesize ? }$\equiv$
\vspace{-1ex}
\begin{list}{}{} \item
@ -308,7 +331,8 @@ to the global SICS device executor.
\mbox{}\verb@ connection with non blocking operation such as motors started@\\
\mbox{}\verb@ with run.@\\
\mbox{}\verb@ */@\\
\mbox{}\verb@ @\\
\mbox{}\verb@/*--------------------------- Locking ---------------------------------*/@\\
\mbox{}\verb@ @$\langle$devlock {\footnotesize ?}$\rangle$\verb@ @\\
\mbox{}\verb@/* -------------------------- Executor management -------------------------*/@\\
\mbox{}\verb@ @\\
\mbox{}\verb@ pExeList GetExecutor(void);@\\

View File

@ -175,6 +175,17 @@ take care of invoking the apropriate commands on all registered counting
devices.
\subsubsection{Locking the Device Executor}
In some instances user code may wish to lock the device executor. An
example is a long running data saving operation. In order to do this
two functions are provided:
@d devlock @{
void LockDeviceExecutor(pExeList self);
void UnlockDeviceExecutor(pExeList self);
@}
\subsubsection{The Rest}
The rest of the interface includes initialisation and deletion routines
and some access routines. With the devexec being such an important system
@ -266,7 +277,8 @@ to the global SICS device executor.
connection with non blocking operation such as motors started
with run.
*/
/*--------------------------- Locking ---------------------------------*/
@<devlock@>
/* -------------------------- Executor management -------------------------*/
pExeList GetExecutor(void);

View File

@ -237,7 +237,7 @@
}
}
/*-------------------------------------------------------------------------
This is meant to be called specially from DriveWrapper at at stage when
This is meant to be called specially from DriveWrapper at a stage when
we already know, that name is a drivable motor. Thus no error checking
is performed. Do not use this in any other context!!!!
*/
@ -253,7 +253,7 @@
char pBueffel[132];
/*
treat motors separatetly in order to correct for zero points
treat motors separately in order to correct for zero points
Sighh.........
*/
pMot = FindMotor(pSics,name);

View File

@ -26,6 +26,7 @@
#define VALUECHANGE 0
#define MOTDRIVE 1
#define MOTEND 13
#define MONITOR 2
#define ROTSTART 3
#define ROTMOVE 4

View File

@ -1,5 +1,5 @@
#line 345 "interface.w"
#line 346 "interface.w"
/*---------------------------------------------------------------------------
I N T E R F A C E S
@ -26,7 +26,7 @@
/* ----------------------- The drivable interface -----------------------*/
#line 116 "interface.w"
#line 117 "interface.w"
typedef struct {
@ -44,14 +44,14 @@
pIDrivable GetDrivableInterface(void *pObject);
#line 370 "interface.w"
#line 371 "interface.w"
pIDrivable CreateDrivableInterface(void);
/* ------------------------ The countable interface ---------------------*/
#line 176 "interface.w"
#line 177 "interface.w"
typedef struct {
int ID;
@ -68,23 +68,23 @@
pICountable GetCountableInterface(void *pObject);
#line 375 "interface.w"
#line 376 "interface.w"
pICountable CreateCountableInterface(void);
/* ------------------------- The CallBack Interface --------------------*/
#line 229 "interface.w"
#line 230 "interface.w"
typedef void (*KillFuncIT)(void *pData);
typedef int (*SICSCallBack)(int iEvent, void *pEventData,
void *pUserData);
#line 380 "interface.w"
#line 381 "interface.w"
#line 251 "interface.w"
#line 252 "interface.w"
typedef struct __ICallBack *pICallBack;
@ -99,11 +99,11 @@
int RemoveCallback(pICallBack pInterface, long iID);
int RemoveCallback2(pICallBack pInterface, void *pUserData);
#line 381 "interface.w"
#line 382 "interface.w"
/*---------------------- The Environment Interface --------------------*/
#line 309 "interface.w"
#line 310 "interface.w"
typedef enum { EVIdle, EVDrive, EVMonitor, EVError } EVMode;
typedef struct {
@ -113,13 +113,13 @@
int (*HandleError)(void *self);
} EVInterface, *pEVInterface;
#line 383 "interface.w"
#line 384 "interface.w"
#line 335 "interface.w"
#line 336 "interface.w"
pEVInterface CreateEVInterface(void);
#line 384 "interface.w"
#line 385 "interface.w"
#endif

View File

@ -60,6 +60,7 @@ $\langle$obdes {\footnotesize ?}$\rangle\equiv$
\mbox{}\verb@ /*---------------------------------------------------------------------------*/@\\
\mbox{}\verb@ pObjectDescriptor CreateDescriptor(char *name);@\\
\mbox{}\verb@ void DeleteDescriptor(pObjectDescriptor self);@\\
\mbox{}\verb@ pObjectDescriptor FindDescriptor(void *pData);@\\
\mbox{}\verb@ @\\
\mbox{}\verb@/*============================================================================@\\
\mbox{}\verb@ Objects which do not carry data need a dummy descriptor. Otherwise@\\

View File

@ -55,6 +55,7 @@ Let's start with the objectdescriptor:
/*---------------------------------------------------------------------------*/
pObjectDescriptor CreateDescriptor(char *name);
void DeleteDescriptor(pObjectDescriptor self);
pObjectDescriptor FindDescriptor(void *pData);
/*============================================================================
Objects which do not carry data need a dummy descriptor. Otherwise

64
motor.c
View File

@ -9,6 +9,7 @@
Mark Koennecke, November 1996
revised: Mark Koennecke, June 1997
callback added: Mark Koennecke, August 1997
endscript facility added: Mark Koennecke, August 2002
Copyright:
@ -195,7 +196,9 @@
SCSetInterrupt(pCon,iVal);
}
}
/*--------------------------------------------------------------------------*/
/*--------------------------------------------------------------------------
Refactor
--------------------------------------------------------------------------*/
static int MotorStatus(void *sulf, SConnection *pCon)
{
float fHard;
@ -250,6 +253,8 @@
/* motor thinks he is done */
if( (iRet == OKOK) || (iRet == HWIdle))
{
MotorGetSoftPosition(self,pCon,&sCall.fVal);
InvokeCallBack(self->pCall, MOTEND, &sCall);
self->fPosition = fHard;
if(absf(fHard - self->fTarget) > ObVal(self->ParArray,PREC))
{
@ -342,8 +347,7 @@
iRetry = 0;
return iRet;
}
/*---------------------------------------------------------------------------*/
pMotor MotorInit(char *drivername, char *name, MotorDriver *pDriv)
/*---------------------------------------------------------------------------*/ pMotor MotorInit(char *drivername, char *name, MotorDriver *pDriv)
{
pMotor pM = NULL;
@ -380,6 +384,7 @@
ObParInit(pM->ParArray,ECOUNT,"failafter",3.0,usMugger);
pDriv->GetPosition(pDriv,&(pM->fPosition));
pM->fTarget = pM->fPosition;
pM->endScriptID = 0;
/* copy arguments */
pM->pDriver = pDriv;
@ -1027,7 +1032,32 @@ extern MotorDriver *MakePiPiezo(Tcl_Interp *pTcl, char *pArray);
SCWrite(pInfo->pCon,pBueffel,eValue);
return 1;
}
/*------------------------------------------------------------------------*/
static void KillScript(void *pData)
{
if(pData != NULL)
{
free(pData);
}
}
/*------------------------ The endscript callback function ----------------*/
static int EndScriptCallback(int iEvent, void *pEvent, void *pUser)
{
char *pScript = NULL;
MotCallback *psCall;
char pCommand[1024];
int iRet;
assert(pEvent);
assert(pUser);
psCall = (MotCallback *)pEvent;
pScript = (char *)pUser;
sprintf(pCommand,"%s %f",pScript,psCall->fVal);
iRet = Tcl_Eval(pServ->pSics->pTcl,pCommand);
return iRet;
}
/*----------------------------------------------------------------------------
The wrapper function for a motor. Commands currently supported are:
@ -1037,6 +1067,8 @@ extern MotorDriver *MakePiPiezo(Tcl_Interp *pTcl, char *pArray);
motorname reset : puts softlimits to default
motorname interest : starts sending automatic
notifications when driving
motorname endscript : script to call when motor
finishes driving
-----------------------------------------------------------------------------*/
int MotorAction(SConnection *pCon, SicsInterp *pSics, void *pData,
int argc, char *argv[])
@ -1122,7 +1154,6 @@ extern MotorDriver *MakePiPiezo(Tcl_Interp *pTcl, char *pArray);
DeleteTokenList(pList);
SCSendOK(pCon);
return 1;
}
else if(strcmp(pCurrent->text,"uninterest") == 0)
{
@ -1131,6 +1162,31 @@ extern MotorDriver *MakePiPiezo(Tcl_Interp *pTcl, char *pArray);
DeleteTokenList(pList);
return 1;
}
else if(strcmp(pCurrent->text,"endscript") == 0) /* endscript */
{
if(!SCMatchRights(pCon,usMugger))
{
return 0;
}
if(self->endScriptID != 0)
{
RemoveCallback(self->pCall, self->endScriptID);
self->endScriptID = 0;
}
pCurrent = pCurrent->pNext;
if(!pCurrent)
{
SCWrite(pCon,"ERROR: scriptname argument missing",eError);
return 0;
}
self->endScriptID =
RegisterCallback(self->pCall, MOTEND, EndScriptCallback,
strdup(pCurrent->text), KillScript);
SCRegister(pCon,pSics, self->pCall,self->endScriptID);
DeleteTokenList(pList);
SCSendOK(pCon);
return 1;
}
else /* one of the parameter commands or error left now */
{
pName = pCurrent;

View File

@ -24,6 +24,7 @@
MotorDriver *pDriver;
float fTarget;
float fPosition;
long endScriptID;
} Motor;
typedef Motor *pMotor;
/*-------------------------------------------------------------------------*/

125
motreg.c Normal file
View File

@ -0,0 +1,125 @@
/*-------------------------------------------------------------------------
R e g M o t
This is a helper module for the Anti Collider. It handles all the
stuff necessary for dealing with a single motor. For more
information see the file anticollider.tex.
copyright: see file copyright
Mark Koennecke, August 2002
-----------------------------------------------------------------------*/
#include <stdlib.h>
#include <assert.h>
#include "fortify.h"
#include "motreg.h"
/*--------------------------------------------------------------------*/
pMotReg RegisterMotor(char *name, SicsInterp *pSics,
long (*NewSetValue)(void *pData, SConnection *pCon,
float farget),
int (*NewCheckStatus)(void *pData,SConnection *pCon) ){
CommandList *pCom = NULL;
pIDrivable pDriv = NULL;
pMotReg pNew = NULL;
/*
find motor data structures
*/
pCom = FindCommand(pSics,name);
if(pCom == NULL){
return NULL;
}
pDriv = GetDrivableInterface(pCom->pData);
if(pDriv == NULL){
return NULL;
}
/*
everything seems OK. Allocate data structure and initialize
*/
pNew = (pMotReg)malloc(sizeof(MotReg));
if(pNew == NULL){
return NULL;
}
memset(pNew,0,sizeof(MotReg));
pNew->motorData = pCom->pData;
pNew->motorName = strdup(name);
pNew->originalSetValue = pDriv->SetValue;
pNew->originalCheckStatus = pDriv->CheckStatus;
pNew->iActive = 0;
pDriv->SetValue = NewSetValue;
pDriv->CheckStatus = NewCheckStatus;
return pNew;
}
/*---------------------------------------------------------------------*/
void KillRegMot(void *pData){
pMotReg self = (pMotReg)pData;
if(self == NULL){
return;
}
if(self->motorName != NULL){
free(self->motorName);
}
free(self);
}
/*------------------------------------------------------------------------*/
void SetRegMotTarget(pMotReg self, float fValue){
assert(self);
self->targetPosition = fValue;
self->iActive = 1;
}
/*------------------------------------------------------------------------*/
void CreateTargetString(pMotReg self, char pBueffel[80]) {
assert(self);
if(strlen(self->motorName) + 20 < 80) {
sprintf(pBueffel," %s %12.4f ", self->motorName, self->targetPosition);
}
}
/*-----------------------------------------------------------------------*/
int RegMotMatch(pMotReg self, char *name){
assert(self);
if(strcmp(self->motorName, name) == 0) {
return 1;
}
return 0;
}
/*----------------------------------------------------------------------*/
int StartRegMot(pMotReg self, SConnection *pCon, float fValue){
int ret;
long (*oldSet)(void *pmotorData, SConnection *pCon, float fValue);
pIDrivable pDriv = NULL;
assert(self);
pDriv = GetDrivableInterface(self->motorData);
assert(pDriv);
oldSet = pDriv->SetValue;
pDriv->SetValue = self->originalSetValue;
ret = StartDevice(pServ->pExecutor, self->motorName,
FindDescriptor(self->motorData),
self->motorData,
pCon,
fValue);
pDriv->SetValue = oldSet;
self->iActive = 1;
return ret;
}
/*----------------------------------------------------------------------*/
int CheckRegMot(pMotReg self, SConnection *pCon){
int stat;
assert(self);
stat = self->originalCheckStatus(self->motorData,pCon);
if(stat != HWBusy){
self->iActive = 0;
}
return stat;
}

52
motreg.h Normal file
View File

@ -0,0 +1,52 @@
/*-------------------------------------------------------------------------
R e g M o t
This is a helper module for the Anti Collider. It handles all the
stuff necessary for dealing with a single motor. For more
information see the file anticollider.tex.
copyright: see file copyright
Mark Koennecke, August 2002
-----------------------------------------------------------------------*/
#ifndef REGMOT
#define REGMOT
#include "sics.h"
typedef struct __MOTREG {
void *motorData;
char *motorName;
float targetPosition;
long (*originalSetValue)(void *motorData,
SConnection *pCon,
float fTarget);
int (*originalCheckStatus)(void *motorData,
SConnection *pCon);
int iActive;
} MotReg, *pMotReg;
/*----------------------------------------------------------------------*/
pMotReg RegisterMotor(char *name, SicsInterp *pSics,
long (*SetValue)(void *pData, SConnection *pCon, float
fTarget),
int (*CheckStatus)(void *pData, SConnection *pCon));
void KillRegMot(void *self);
void SetRegMotTarget(pMotReg self, float target);
void CreateTargetString(pMotReg self, char pBueffel[80]);
int RegMotMatch(pMotReg self, char *name);
int StartRegMot(pMotReg self, SConnection *pCon, float fValue);
int CheckRegMot(pMotReg self, SConnection *pCon);
#endif

86
motreglist.c Normal file
View File

@ -0,0 +1,86 @@
/*-----------------------------------------------------------------------
A couple of utility functions for handling a list of MotReg
structures . This is a helper module for the anticollider collision
control system. See anticollider.tex for more details.
copyright: see file copyright
Mark Koennecke, August 2002
-------------------------------------------------------------------------*/
#include <stdlib.h>
#include <assert.h>
#include "fortify.h"
#include "lld.h"
#include "motreglist.h"
/*-----------------------------------------------------------------------*/
int MakeMotList(){
return LLDcreate(sizeof(pMotReg));
}
/*----------------------------------------------------------------------*/
pMotReg FindMotEntry(int iList, char *name){
int iRet;
pMotReg pMot = NULL;
iRet = LLDnodePtr2First(iList);
while(iRet != 0){
LLDnodeDataTo(iList,&pMot);
if(pMot != NULL){
if(RegMotMatch(pMot,name)){
return pMot;
}
}
iRet = LLDnodePtr2Next(iList);
}
return NULL;
}
/*-----------------------------------------------------------------------*/
pMotReg FindMotFromDataStructure(int iList, void *pData){
int iRet;
pMotReg pMot = NULL;
iRet = LLDnodePtr2First(iList);
while(iRet != 0){
LLDnodeDataTo(iList,&pMot);
if(pMot != NULL){
if(pMot->motorData == pData){
return pMot;
}
}
iRet = LLDnodePtr2Next(iList);
}
return NULL;
}
/*----------------------------------------------------------------------*/
int CheckAllMotors(int iList, SConnection *pCon){
int iRet, count = 0;
pMotReg pMot = NULL;
iRet = LLDnodePtr2First(iList);
while(iRet != 0){
LLDnodeDataTo(iList,&pMot);
if(pMot != NULL){
CheckRegMot(pMot,pCon);
if(pMot->iActive){
count++;
}
}
iRet = LLDnodePtr2Next(iList);
}
return count;
}
/*----------------------------------------------------------------------*/
void KillMotList(int iList){
int iRet;
pMotReg pMot = NULL;
iRet = LLDnodePtr2First(iList);
while(iRet != 0){
LLDnodeDataTo(iList,&pMot);
if(pMot != NULL){
KillRegMot(pMot);
}
iRet = LLDnodePtr2Next(iList);
}
LLDdelete(iList);
}

27
motreglist.h Normal file
View File

@ -0,0 +1,27 @@
/*-----------------------------------------------------------------------
A couple of utility functions for handling a list of MotReg
structures . This is a helper module for the anticollider collision
control system. See anticollider.tex for more details.
copyright: see file copyright
Mark Koennecke, August 2002
-------------------------------------------------------------------------*/
#ifndef MOTREGLIST
#define MOTREGLIST
#include "motreg.h"
int MakeMotList();
pMotReg FindMotEntry(int iList,char *name);
pMotReg FindMotFromDataStructure(int iList, void *pData);
int CheckAllMotors(int iList, SConnection *pCon);
void KillMotList(int iList);
#endif

View File

@ -24,6 +24,7 @@
#include "nxamor.h"
#include "obpar.h"
#include "motor.h"
#include "status.h"
#define MAXMOT 13 /* must be same as in amor2t.c */
#include "amor2t.i"
@ -662,6 +663,7 @@ static int WriteTOFDetector(char *name, pHistMem pHM, int *iDim,
{
char pBueffel[512], *pFile = NULL;
int iRet, iFlag;
Status oldStatus;
/*
if arguments, check for psdsave
@ -685,11 +687,17 @@ static int WriteTOFDetector(char *name, pHistMem pHM, int *iDim,
pFile = SNXMakeFileName(pSics,pCon);
sprintf(pBueffel,"Writing file %s .....",pFile);
SCWrite(pCon,pBueffel,eWarning);
oldStatus = GetStatus();
SetStatus(eWriting);
LockDeviceExecutor(pServ->pExecutor);
iRet = WriteAmorHeader(pFile,pCon);
if(iRet)
{
iRet = WriteAmorTOF(pFile,pCon,pMeme);
}
SetStatus(oldStatus);
UnlockDeviceExecutor(pServ->pExecutor);
free(pFile);
SCSendOK(pCon);
return iRet;

View File

@ -133,3 +133,12 @@
}
return 0;
}
/*------------------------------------------------------------------------*/
pObjectDescriptor FindDescriptor(void *pData)
{
pDummy pDum = NULL;
assert(pData);
pDum = (pDummy)pData;
return pDum->pDescriptor;
}

View File

@ -1,5 +1,5 @@
#line 341 "interface.w"
#line 342 "interface.w"
#line 29 "interface.w"
@ -32,6 +32,7 @@
/*---------------------------------------------------------------------------*/
pObjectDescriptor CreateDescriptor(char *name);
void DeleteDescriptor(pObjectDescriptor self);
pObjectDescriptor FindDescriptor(void *pData);
/*============================================================================
Objects which do not carry data need a dummy descriptor. Otherwise
@ -51,5 +52,5 @@ typedef struct {
#endif
#line 342 "interface.w"
#line 343 "interface.w"

View File

@ -167,7 +167,7 @@
eStat = GetStatus();
if(!((eStat == eEager) || (eStat == eBatch)) )
{
sprintf(pBueffel,"ERROR: Cannot cahnge parameter while running");
sprintf(pBueffel,"ERROR: Cannot change parameter while running");
SCWrite(pCon, pBueffel,eError);
return 0;
}

3
ofac.c
View File

@ -107,6 +107,7 @@
#include "rs232controller.h"
#include "lomax.h"
#include "polterwrite.h"
#include "anticollider.h"
/*----------------------- Server options creation -------------------------*/
static int IFServerOption(SConnection *pCon, SicsInterp *pSics, void *pData,
int argc, char *argv[])
@ -289,6 +290,7 @@
AddCommand(pInter,"MakeRS232Controller",RS232Factory,NULL,NULL);
AddCommand(pInter,"MakeMaxDetector",LoMaxFactory,NULL,NULL);
AddCommand(pInter,"PolterInstall",PolterInstall,NULL,NULL);
AddCommand(pInter,"AntiCollisionInstall",AntiColliderFactory,NULL,NULL);
}
/*---------------------------------------------------------------------------*/
static void KillIniCommands(SicsInterp *pSics)
@ -348,6 +350,7 @@
RemoveCommand(pSics,"MakeRS232Controller");
RemoveCommand(pSics,"MakeMaxDetector");
RemoveCommand(pSics,"PolterInstall");
RemoveCommand(pSics,"AntiColliderInstall");
}

View File

@ -489,8 +489,8 @@ static int PoldiStart(pPolterdi self, SConnection *pCon)
long lVal;
/* open everything again */
NXopen(self->pFile,NXACC_RDWR,&hfil);
if(!self->pFile)
status = NXopen(self->pFile,NXACC_RDWR,&hfil);
if(status != NX_OK)
{
SCWrite(pCon,"ERROR: cannot reopen data file ",eError);
return;

1
sics.h
View File

@ -29,6 +29,7 @@
#include "emon.h"
#include "nserver.h"
#include "servlog.h"
extern pServer pServ;

View File

@ -1,48 +1,75 @@
a5l.length 80.000000
flightpathlength 0.000000
flightpathlength setAccess 1
flightpath 0.000000
flightpath setAccess 1
delay 2500.000000
delay setAccess 1
hm CountMode timer
hm preset 100.000000
hm genbin 120.000000 35.000000 512
hm init
datafile focus-1001848.hdf
datafile setAccess 3
yfactor 1.420000
yfactor setAccess 1
xfactor 0.715000
xfactor setAccess 1
ps.listfile peaksearch.dat
ps.listfile setAccess 2
ps.scansteps 24
ps.scansteps setAccess 2
ps.scanpreset 1000000.000000
ps.scanpreset setAccess 2
ps.preset 1000.000000
ps.preset setAccess 2
ps.countmode monitor
ps.countmode setAccess 2
ps.cogcontour 0.200000
ps.cogcontour setAccess 2
ps.cogwindow 60
ps.cogwindow setAccess 2
ps.window 7
ps.window setAccess 2
ps.steepness 3
ps.steepness setAccess 2
ps.threshold 30
ps.threshold setAccess 2
ps.sttstep 3.000000
ps.sttstep setAccess 2
ps.sttend 70.000000
ps.sttend setAccess 2
ps.sttstart 5.000000
ps.sttstart setAccess 2
ps.omstep 3.000000
ps.omstep setAccess 2
ps.omend 30.000000
ps.omend setAccess 2
ps.omstart 0.000000
ps.omstart setAccess 2
ps.chistep 12.000000
ps.chistep setAccess 2
ps.chiend 180.000000
ps.chiend setAccess 2
ps.chistart 0.000000
ps.chistart setAccess 2
ps.phistep 3.000000
ps.phistep setAccess 2
ps.phiend 180.000000
ps.phiend setAccess 2
ps.phistart 0.000000
ps.phistart setAccess 2
hm3 CountMode timer
hm3 preset 10.000000
hm2 CountMode timer
hm2 preset 3600.000000
hm2 preset 10.000000
hm1 CountMode timer
hm1 preset 3600.000000
dbfile UNKNOWN
dbfile setAccess 2
# Motor th
th sign 1.000000
th SoftZero 0.000000
th SoftLowerLim 4.000000
th SoftUpperLim 113.000000
th Fixed -1.000000
th InterruptMode 0.000000
th AccessCode 2.000000
hm1 preset 10.000000
#Crystallographic Settings
hkl lambda 1.179000
hkl setub -0.017880 -0.074923 0.028280 -0.007008 -0.036800 -0.057747 0.160912 -0.009928 0.000627
hkl hm 0
det3dist 300.000000
det3dist setAccess 1
detdist3 0.000000
detdist3 setAccess 1
det3zeroy 128.000000
det3zeroy setAccess 1
det3zerox 128.000000
det3zerox setAccess 1
det2dist 300.000000
det2dist setAccess 1
detdist2 0.000000
detdist2 setAccess 1
det2zeroy 128.000000
det2zeroy setAccess 1
det2zerox 128.000000
det2zerox setAccess 1
det1dist 300.000000
det1dist setAccess 1
detdist1 0.000000
detdist1 setAccess 1
det1zeroy 128.000000
det1zeroy setAccess 1
det1zerox 128.000000
@ -71,7 +98,7 @@ stt AccessCode 2.000000
ch sign 1.000000
ch SoftZero 0.000000
ch SoftLowerLim 0.000000
ch SoftUpperLim 212.000000
ch SoftUpperLim 190.000000
ch Fixed -1.000000
ch InterruptMode 0.000000
ch AccessCode 1.000000
@ -127,7 +154,7 @@ phi AccessCode 2.000000
chi sign 1.000000
chi SoftZero 0.000000
chi SoftLowerLim 0.000000
chi SoftUpperLim 212.000000
chi SoftUpperLim 190.000000
chi Fixed -1.000000
chi InterruptMode 0.000000
chi AccessCode 1.000000
@ -149,8 +176,6 @@ twotheta InterruptMode 0.000000
twotheta AccessCode 2.000000
lastscancommand cscan a4 10. .1 10 5
lastscancommand setAccess 2
banana CountMode timer
banana preset 100.000000
sample_mur 0.000000
sample_mur setAccess 2
email UNKNOWN
@ -428,13 +453,11 @@ a1 SoftUpperLim 120.000000
a1 Fixed -1.000000
a1 InterruptMode 0.000000
a1 AccessCode 2.000000
batchroot /data/koenneck/src/sics
batchroot setAccess 2
user Uwe Filges
user setAccess 2
sample D20 30K SNP Okt 2001 GS
sample setAccess 2
title snp gs apd 30K
title endtest called with 23.000000 :Driving:
title setAccess 2
starttime 2002-04-23 10:49:18
starttime 2002-08-07 08:09:45
starttime setAccess 2

View File

@ -59,6 +59,7 @@
"Driving",
"Running",
"Running a scan",
"Writing data",
"Processing a batch file",
"Halted",
"Dead",
@ -74,6 +75,7 @@
"driving",
"running",
"scanning",
"writing",
"batch",
"halt",
"dead",

View File

@ -17,6 +17,7 @@
eDriving,
eRunning,
eScanning,
eWriting,
eBatch,
eHalted,
eDead,