PSI sics-cvs-psi_pre-ansto
This commit is contained in:
27
.rfl
Normal file
27
.rfl
Normal file
@ -0,0 +1,27 @@
|
||||
1 14.0 1.0 -3.0 34.93 17.4662365.2f -120.3757635.2f 57.86 0.00 0.00
|
||||
2 25.0 20.0 3.0 121.37 60.6874285.2f -161.7680215.2f 151.81 0.00 0.00
|
||||
3 14.0 1.0 -1.0 30.08 15.0386245.2f -105.8243565.2f 57.33 0.00 0.00
|
||||
4 13.0 1.0 0.0 26.43 13.2171475.2f -97.0895085.2f 62.61 0.00 0.00
|
||||
5 13.0 1.0 -2.0 30.17 15.0827995.2f -114.8090905.2f 59.43 0.00 0.00
|
||||
6 0.0 7.0 1.0 38.10 19.0499325.2f 168.9476015.2f 154.39 0.00 0.00
|
||||
7 -1.0 7.0 1.0 39.00 19.4981695.2f 166.0153055.2f 154.70 0.00 0.00
|
||||
8 1.0 7.0 1.0 37.31 18.6574575.2f 172.0074465.2f 154.08 0.00 0.00
|
||||
9 1.0 2.0 2.0 13.43 6.7168745.2f 176.1939855.2f -170.37 0.00 0.00
|
||||
1 14.0 1.0 -3.0 34.93 17.47 -120.38 57.86 0.00 0.00
|
||||
2 25.0 20.0 3.0 121.37 60.69 -161.77 151.81 0.00 0.00
|
||||
3 14.0 1.0 -1.0 30.08 15.04 -105.82 57.33 0.00 0.00
|
||||
4 13.0 1.0 0.0 26.43 13.22 -97.09 62.61 0.00 0.00
|
||||
5 13.0 1.0 -2.0 30.17 15.08 -114.81 59.43 0.00 0.00
|
||||
6 0.0 7.0 1.0 38.10 19.05 168.95 154.39 0.00 0.00
|
||||
7 -1.0 7.0 1.0 39.00 19.50 166.02 154.70 0.00 0.00
|
||||
8 1.0 7.0 1.0 37.31 18.66 172.01 154.08 0.00 0.00
|
||||
9 1.0 2.0 2.0 13.43 6.72 176.19 -170.37 0.00 0.00
|
||||
1 14.0 1.0 -3.0 34.93 17.47 -120.38 57.86 0.00 0.00
|
||||
2 25.0 20.0 3.0 121.37 60.69 -161.77 151.81 0.00 0.00
|
||||
3 14.0 1.0 -1.0 30.08 15.04 -105.82 57.33 0.00 0.00
|
||||
4 13.0 1.0 0.0 26.43 13.22 -97.09 62.61 0.00 0.00
|
||||
5 13.0 1.0 -2.0 30.17 15.08 -114.81 59.43 0.00 0.00
|
||||
6 0.0 7.0 1.0 38.10 19.05 168.95 154.39 0.00 0.00
|
||||
7 -1.0 7.0 1.0 39.00 19.50 166.02 154.70 0.00 0.00
|
||||
8 1.0 7.0 1.0 37.31 18.66 172.01 154.08 0.00 0.00
|
||||
9 1.0 2.0 2.0 13.43 6.72 176.19 -170.37 0.00 0.00
|
344
A1931.c
Normal file
344
A1931.c
Normal file
@ -0,0 +1,344 @@
|
||||
/*-------------------------------------------------------------------------
|
||||
This is the implementation file for a driver for the Risoe A1931a
|
||||
temperature controller. This driver controls the device through a GPIB
|
||||
interface.
|
||||
|
||||
copyright: see file COPYRIGHT
|
||||
|
||||
Mark Koennecke, February 2003
|
||||
-------------------------------------------------------------------------*/
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include <time.h>
|
||||
#include <math.h>
|
||||
#include <assert.h>
|
||||
#include <unistd.h>
|
||||
#include "fortify.h"
|
||||
#include "sics.h"
|
||||
#include "obpar.h"
|
||||
#include "evcontroller.h"
|
||||
#include "evcontroller.i"
|
||||
#include "evdriver.i"
|
||||
#include "gpibcontroller.h"
|
||||
#include "A1931.h"
|
||||
|
||||
/*========================== private data structure ====================*/
|
||||
typedef struct {
|
||||
int sensor; /* the control sensor */
|
||||
pGPIB gpib; /* the GPIB interface to use in order to talk to the thing*/
|
||||
int gpibAddress; /* address on bus */
|
||||
int devID; /* deviceID of the controller on the GPIB */
|
||||
char errorBuffer[132]; /* a buffer for error messages from the thing*/
|
||||
char commandLine[132]; /* buffer to keep the offending command line */
|
||||
int errorCode; /* error indicator */
|
||||
}A1931, *pA1931;
|
||||
/*============================ defines ================================*/
|
||||
#define COMMERROR -300
|
||||
#define A1931ERROR -301
|
||||
#define FILEERROR -302
|
||||
/*====================================================================*/
|
||||
static char *A1931comm(pEVDriver pData, char *command){
|
||||
char buffer[256], *pPtr;
|
||||
int status;
|
||||
pA1931 self = NULL;
|
||||
Tcl_DString reply;
|
||||
|
||||
self = (pA1931)pData->pPrivate;
|
||||
assert(self);
|
||||
|
||||
/*
|
||||
send
|
||||
*/
|
||||
strncpy(buffer,command,250);
|
||||
strcat(buffer,"\n");
|
||||
status = GPIBsend(self->gpib,self->devID,buffer,(int)strlen(buffer));
|
||||
if(status < 0){
|
||||
self->errorCode = COMMERROR;
|
||||
GPIBerrorDescription(self->gpib,status,self->errorBuffer,131);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
read until > is found
|
||||
*/
|
||||
Tcl_DStringInit(&reply);
|
||||
while(1){
|
||||
pPtr = GPIBreadTillTerm(self->gpib,self->devID,10);
|
||||
if(strstr(pPtr,"GPIB READ ERROR") != NULL){
|
||||
free(pPtr);
|
||||
self->errorCode = COMMERROR;
|
||||
Tcl_DStringFree(&reply);
|
||||
return NULL;
|
||||
} else {
|
||||
Tcl_DStringAppend(&reply,pPtr,-1);
|
||||
if(strchr(pPtr,'>') != NULL){
|
||||
/*
|
||||
finished
|
||||
*/
|
||||
free(pPtr);
|
||||
break;
|
||||
}
|
||||
free(pPtr);
|
||||
}
|
||||
}
|
||||
pPtr = NULL;
|
||||
pPtr = strdup(Tcl_DStringValue(&reply));
|
||||
Tcl_DStringFree(&reply);
|
||||
if(pPtr[0] == '#'){
|
||||
/*
|
||||
error
|
||||
*/
|
||||
self->errorCode = A1931ERROR;
|
||||
strncpy(self->errorBuffer,pPtr,131);
|
||||
free(pPtr);
|
||||
return NULL;
|
||||
}
|
||||
return pPtr;
|
||||
}
|
||||
/*--------------------------------------------------------------------*/
|
||||
static int A1931command(pEVDriver pData, char *command, char *replyBuffer,
|
||||
int replyBufferLen){
|
||||
pA1931 self = NULL;
|
||||
char *pReply = NULL;
|
||||
|
||||
self = (pA1931)pData->pPrivate;
|
||||
assert(self);
|
||||
|
||||
pReply = A1931comm(pData,command);
|
||||
if(pReply != NULL){
|
||||
strncpy(replyBuffer,pReply,replyBufferLen);
|
||||
free(pReply);
|
||||
return 1;
|
||||
} else {
|
||||
strncpy(replyBuffer,self->errorBuffer,replyBufferLen);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
/*====================================================================*/
|
||||
static int A1931Init(pEVDriver pData){
|
||||
pA1931 self = NULL;
|
||||
|
||||
self = (pA1931)pData->pPrivate;
|
||||
assert(self);
|
||||
|
||||
self->devID = GPIBattach(self->gpib,0,self->gpibAddress,0,13,0,0);
|
||||
if(self->devID < 0){
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
/*====================================================================*/
|
||||
static int A1931Close(pEVDriver pData){
|
||||
pA1931 self = NULL;
|
||||
|
||||
self = (pA1931)pData->pPrivate;
|
||||
assert(self);
|
||||
|
||||
GPIBdetach(self->gpib,self->devID);
|
||||
self->devID = 0;
|
||||
return 1;
|
||||
}
|
||||
/*===================================================================*/
|
||||
static int A1931Get(pEVDriver pData,float *fPos){
|
||||
pA1931 self = NULL;
|
||||
char buffer[132], command[50];
|
||||
int status;
|
||||
|
||||
self = (pA1931)pData->pPrivate;
|
||||
assert(self);
|
||||
|
||||
sprintf(command,"?TEMP%1.1d",self->sensor);
|
||||
status = A1931command(pData,command,buffer,131);
|
||||
if(!status){
|
||||
return 0;
|
||||
}
|
||||
sscanf(buffer,"%f",fPos);
|
||||
return 1;
|
||||
}
|
||||
/*=====================================================================*/
|
||||
static int A1931Set(pEVDriver pData, float fNew){
|
||||
pA1931 self = NULL;
|
||||
char buffer[132], command[50];
|
||||
int status;
|
||||
|
||||
self = (pA1931)pData->pPrivate;
|
||||
assert(self);
|
||||
|
||||
sprintf(command,"SET%1.1d=%f",self->sensor,fNew);
|
||||
status = A1931command(pData,command,buffer,131);
|
||||
if(!status){
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
/*====================================================================*/
|
||||
static int A1931error(pEVDriver pData, int *iCode, char *errBuff, int bufLen){
|
||||
pA1931 self = NULL;
|
||||
char pError[256];
|
||||
|
||||
self = (pA1931)pData->pPrivate;
|
||||
assert(self);
|
||||
|
||||
*iCode = self->errorCode;
|
||||
sprintf(pError,"ERROR: %s",self->errorBuffer);
|
||||
strncpy(errBuff,pError,bufLen);
|
||||
return 1;
|
||||
}
|
||||
/*====================================================================*/
|
||||
static int A1931fix(pEVDriver pData, int iCode){
|
||||
pA1931 self = NULL;
|
||||
char pError[256];
|
||||
|
||||
self = (pA1931)pData->pPrivate;
|
||||
assert(self);
|
||||
|
||||
if(iCode == COMMERROR){
|
||||
GPIBclear(self->gpib,self->devID);
|
||||
return DEVREDO;
|
||||
}
|
||||
return DEVFAULT;
|
||||
}
|
||||
/*=====================================================================*/
|
||||
pEVDriver CreateA1931Driver(int argc, char *argv[]){
|
||||
pEVDriver self = NULL;
|
||||
pA1931 priv = NULL;
|
||||
|
||||
if(argc < 2){
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
allocate space
|
||||
*/
|
||||
self = CreateEVDriver(argc,argv);
|
||||
priv = (pA1931)malloc(sizeof(A1931));
|
||||
if(self == NULL || priv == NULL){
|
||||
return NULL;
|
||||
}
|
||||
memset(priv,0,sizeof(A1931));
|
||||
self->pPrivate = priv;
|
||||
self->KillPrivate = free;
|
||||
|
||||
/*
|
||||
initialize
|
||||
*/
|
||||
priv->gpib = (pGPIB)FindCommandData(pServ->pSics,argv[0],"GPIB");
|
||||
if(!priv->gpib){
|
||||
DeleteEVDriver(self);
|
||||
return NULL;
|
||||
}
|
||||
priv->sensor = 1;
|
||||
priv->gpibAddress = atoi(argv[1]);
|
||||
|
||||
/*
|
||||
initialize function pointers
|
||||
*/
|
||||
self->Send = A1931command;
|
||||
self->Init = A1931Init;
|
||||
self->Close = A1931Close;
|
||||
self->GetValue = A1931Get;
|
||||
self->SetValue = A1931Set;
|
||||
self->GetError = A1931error;
|
||||
self->TryFixIt = A1931fix;
|
||||
|
||||
return self;
|
||||
}
|
||||
/*=======================================================================*/
|
||||
static int downloadFile(pA1931 self, FILE *fd){
|
||||
char buffer[132], *pPtr;
|
||||
int status;
|
||||
|
||||
while(1){
|
||||
if(fgets(buffer,130,fd) == NULL){
|
||||
self->errorCode = FILEERROR;
|
||||
strcpy(self->errorBuffer,"Failed to read from file");
|
||||
return 0;
|
||||
}
|
||||
if(strstr(buffer,"$END") != NULL){
|
||||
break;
|
||||
}
|
||||
status = GPIBsend(self->gpib,self->devID,buffer,(int)strlen(buffer));
|
||||
if(status < 0){
|
||||
self->errorCode = COMMERROR;
|
||||
GPIBerrorDescription(self->gpib,status,self->errorBuffer,131);
|
||||
return 0;
|
||||
}
|
||||
pPtr = GPIBreadTillTerm(self->gpib,self->devID,10);
|
||||
if(pPtr[0] == '#'){
|
||||
self->errorCode = A1931ERROR;
|
||||
strncpy(self->errorBuffer,pPtr,131);
|
||||
strncpy(self->commandLine,buffer,131);
|
||||
free(pPtr);
|
||||
return 0;
|
||||
}
|
||||
free(pPtr);
|
||||
usleep(50);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
/*=======================================================================*/
|
||||
int A1931Action(SConnection *pCon, SicsInterp *pSics, void *pData,
|
||||
int argc, char *argv[]){
|
||||
pEVControl pEV = NULL;
|
||||
pA1931 self = NULL;
|
||||
char buffer[256];
|
||||
char error[132];
|
||||
FILE *fd = NULL;
|
||||
int status, iCode;
|
||||
|
||||
pEV = (pEVControl)pData;
|
||||
assert(pEV);
|
||||
self = (pA1931)pEV->pDriv->pPrivate;
|
||||
assert(self);
|
||||
|
||||
if(argc > 1){
|
||||
strtolower(argv[1]);
|
||||
if(strcmp(argv[1],"sensor") == 0){
|
||||
if(argc > 2){
|
||||
/* set case */
|
||||
if(!SCMatchRights(pCon,usUser)){
|
||||
return 0;
|
||||
}
|
||||
self->sensor = atoi(argv[2]);
|
||||
SCSendOK(pCon);
|
||||
return 1;
|
||||
} else {
|
||||
/* get case */
|
||||
sprintf(buffer,"%s.sensor = %d",argv[0],self->sensor);
|
||||
SCWrite(pCon,buffer,eValue);
|
||||
return 1;
|
||||
}
|
||||
}else if(strcmp(argv[1],"list") == 0){
|
||||
sprintf(buffer,"%s.sensor = %d",argv[0],self->sensor);
|
||||
SCWrite(pCon,buffer,eValue);
|
||||
return EVControlWrapper(pCon,pSics,pData,argc,argv);
|
||||
} else if(strcmp(argv[1],"file") == 0){
|
||||
if(!SCMatchRights(pCon,usUser)){
|
||||
return 0;
|
||||
}
|
||||
if(argc < 3){
|
||||
SCWrite(pCon,"ERROR: need filename argument",eError);
|
||||
return 0;
|
||||
}
|
||||
fd = fopen(argv[2],"r");
|
||||
if(fd == NULL){
|
||||
sprintf(buffer,"ERROR: failed to open %s", argv[2]);
|
||||
SCWrite(pCon,buffer,eError);
|
||||
return 0;
|
||||
}
|
||||
status = downloadFile(self,fd);
|
||||
fclose(fd);
|
||||
if(!status){
|
||||
A1931error(pEV->pDriv,&iCode,error,131);
|
||||
sprintf(buffer,"%s while transfering file", error);
|
||||
SCWrite(pCon,buffer,eError);
|
||||
sprintf(buffer,"Offending command: %s",self->commandLine);
|
||||
SCWrite(pCon,buffer,eError);
|
||||
return 0;
|
||||
}
|
||||
SCSendOK(pCon);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
return EVControlWrapper(pCon,pSics,pData,argc,argv);
|
||||
}
|
20
A1931.h
Normal file
20
A1931.h
Normal file
@ -0,0 +1,20 @@
|
||||
/*-------------------------------------------------------------------------
|
||||
This is the header file for a driver for the Risoe A1931a temperature
|
||||
controller. This driver controls the device through a GPIB interface.
|
||||
|
||||
copyright: see file COPYRIGHT
|
||||
|
||||
Mark Koennecke, February 2003
|
||||
-------------------------------------------------------------------------*/
|
||||
#ifndef A1931A
|
||||
#define A19131A
|
||||
|
||||
#include "sics.h"
|
||||
|
||||
pEVDriver CreateA1931Driver(int argc, char *argv[]);
|
||||
|
||||
int A1931Action(SConnection *pCon, SicsInterp *pSics, void *pData,
|
||||
int argc, char *argv[]);
|
||||
|
||||
|
||||
#endif
|
115
Busy.c
Normal file
115
Busy.c
Normal 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
28
Busy.h
Normal 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
41
Busy.w
Normal 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
|
||||
|
||||
@}
|
||||
|
||||
|
340
COPYRIGHT
Normal file
340
COPYRIGHT
Normal file
@ -0,0 +1,340 @@
|
||||
GNU GENERAL PUBLIC LICENSE
|
||||
Version 2, June 1991
|
||||
|
||||
Copyright (C) 1989, 1991 Free Software Foundation, Inc.
|
||||
59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
Everyone is permitted to copy and distribute verbatim copies
|
||||
of this license document, but changing it is not allowed.
|
||||
|
||||
Preamble
|
||||
|
||||
The licenses for most software are designed to take away your
|
||||
freedom to share and change it. By contrast, the GNU General Public
|
||||
License is intended to guarantee your freedom to share and change free
|
||||
software--to make sure the software is free for all its users. This
|
||||
General Public License applies to most of the Free Software
|
||||
Foundation's software and to any other program whose authors commit to
|
||||
using it. (Some other Free Software Foundation software is covered by
|
||||
the GNU Library General Public License instead.) You can apply it to
|
||||
your programs, too.
|
||||
|
||||
When we speak of free software, we are referring to freedom, not
|
||||
price. Our General Public Licenses are designed to make sure that you
|
||||
have the freedom to distribute copies of free software (and charge for
|
||||
this service if you wish), that you receive source code or can get it
|
||||
if you want it, that you can change the software or use pieces of it
|
||||
in new free programs; and that you know you can do these things.
|
||||
|
||||
To protect your rights, we need to make restrictions that forbid
|
||||
anyone to deny you these rights or to ask you to surrender the rights.
|
||||
These restrictions translate to certain responsibilities for you if you
|
||||
distribute copies of the software, or if you modify it.
|
||||
|
||||
For example, if you distribute copies of such a program, whether
|
||||
gratis or for a fee, you must give the recipients all the rights that
|
||||
you have. You must make sure that they, too, receive or can get the
|
||||
source code. And you must show them these terms so they know their
|
||||
rights.
|
||||
|
||||
We protect your rights with two steps: (1) copyright the software, and
|
||||
(2) offer you this license which gives you legal permission to copy,
|
||||
distribute and/or modify the software.
|
||||
|
||||
Also, for each author's protection and ours, we want to make certain
|
||||
that everyone understands that there is no warranty for this free
|
||||
software. If the software is modified by someone else and passed on, we
|
||||
want its recipients to know that what they have is not the original, so
|
||||
that any problems introduced by others will not reflect on the original
|
||||
authors' reputations.
|
||||
|
||||
Finally, any free program is threatened constantly by software
|
||||
patents. We wish to avoid the danger that redistributors of a free
|
||||
program will individually obtain patent licenses, in effect making the
|
||||
program proprietary. To prevent this, we have made it clear that any
|
||||
patent must be licensed for everyone's free use or not licensed at all.
|
||||
|
||||
The precise terms and conditions for copying, distribution and
|
||||
modification follow.
|
||||
|
||||
GNU GENERAL PUBLIC LICENSE
|
||||
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
|
||||
|
||||
0. This License applies to any program or other work which contains
|
||||
a notice placed by the copyright holder saying it may be distributed
|
||||
under the terms of this General Public License. The "Program", below,
|
||||
refers to any such program or work, and a "work based on the Program"
|
||||
means either the Program or any derivative work under copyright law:
|
||||
that is to say, a work containing the Program or a portion of it,
|
||||
either verbatim or with modifications and/or translated into another
|
||||
language. (Hereinafter, translation is included without limitation in
|
||||
the term "modification".) Each licensee is addressed as "you".
|
||||
|
||||
Activities other than copying, distribution and modification are not
|
||||
covered by this License; they are outside its scope. The act of
|
||||
running the Program is not restricted, and the output from the Program
|
||||
is covered only if its contents constitute a work based on the
|
||||
Program (independent of having been made by running the Program).
|
||||
Whether that is true depends on what the Program does.
|
||||
|
||||
1. You may copy and distribute verbatim copies of the Program's
|
||||
source code as you receive it, in any medium, provided that you
|
||||
conspicuously and appropriately publish on each copy an appropriate
|
||||
copyright notice and disclaimer of warranty; keep intact all the
|
||||
notices that refer to this License and to the absence of any warranty;
|
||||
and give any other recipients of the Program a copy of this License
|
||||
along with the Program.
|
||||
|
||||
You may charge a fee for the physical act of transferring a copy, and
|
||||
you may at your option offer warranty protection in exchange for a fee.
|
||||
|
||||
2. You may modify your copy or copies of the Program or any portion
|
||||
of it, thus forming a work based on the Program, and copy and
|
||||
distribute such modifications or work under the terms of Section 1
|
||||
above, provided that you also meet all of these conditions:
|
||||
|
||||
a) You must cause the modified files to carry prominent notices
|
||||
stating that you changed the files and the date of any change.
|
||||
|
||||
b) You must cause any work that you distribute or publish, that in
|
||||
whole or in part contains or is derived from the Program or any
|
||||
part thereof, to be licensed as a whole at no charge to all third
|
||||
parties under the terms of this License.
|
||||
|
||||
c) If the modified program normally reads commands interactively
|
||||
when run, you must cause it, when started running for such
|
||||
interactive use in the most ordinary way, to print or display an
|
||||
announcement including an appropriate copyright notice and a
|
||||
notice that there is no warranty (or else, saying that you provide
|
||||
a warranty) and that users may redistribute the program under
|
||||
these conditions, and telling the user how to view a copy of this
|
||||
License. (Exception: if the Program itself is interactive but
|
||||
does not normally print such an announcement, your work based on
|
||||
the Program is not required to print an announcement.)
|
||||
|
||||
These requirements apply to the modified work as a whole. If
|
||||
identifiable sections of that work are not derived from the Program,
|
||||
and can be reasonably considered independent and separate works in
|
||||
themselves, then this License, and its terms, do not apply to those
|
||||
sections when you distribute them as separate works. But when you
|
||||
distribute the same sections as part of a whole which is a work based
|
||||
on the Program, the distribution of the whole must be on the terms of
|
||||
this License, whose permissions for other licensees extend to the
|
||||
entire whole, and thus to each and every part regardless of who wrote it.
|
||||
|
||||
Thus, it is not the intent of this section to claim rights or contest
|
||||
your rights to work written entirely by you; rather, the intent is to
|
||||
exercise the right to control the distribution of derivative or
|
||||
collective works based on the Program.
|
||||
|
||||
In addition, mere aggregation of another work not based on the Program
|
||||
with the Program (or with a work based on the Program) on a volume of
|
||||
a storage or distribution medium does not bring the other work under
|
||||
the scope of this License.
|
||||
|
||||
3. You may copy and distribute the Program (or a work based on it,
|
||||
under Section 2) in object code or executable form under the terms of
|
||||
Sections 1 and 2 above provided that you also do one of the following:
|
||||
|
||||
a) Accompany it with the complete corresponding machine-readable
|
||||
source code, which must be distributed under the terms of Sections
|
||||
1 and 2 above on a medium customarily used for software interchange; or,
|
||||
|
||||
b) Accompany it with a written offer, valid for at least three
|
||||
years, to give any third party, for a charge no more than your
|
||||
cost of physically performing source distribution, a complete
|
||||
machine-readable copy of the corresponding source code, to be
|
||||
distributed under the terms of Sections 1 and 2 above on a medium
|
||||
customarily used for software interchange; or,
|
||||
|
||||
c) Accompany it with the information you received as to the offer
|
||||
to distribute corresponding source code. (This alternative is
|
||||
allowed only for noncommercial distribution and only if you
|
||||
received the program in object code or executable form with such
|
||||
an offer, in accord with Subsection b above.)
|
||||
|
||||
The source code for a work means the preferred form of the work for
|
||||
making modifications to it. For an executable work, complete source
|
||||
code means all the source code for all modules it contains, plus any
|
||||
associated interface definition files, plus the scripts used to
|
||||
control compilation and installation of the executable. However, as a
|
||||
special exception, the source code distributed need not include
|
||||
anything that is normally distributed (in either source or binary
|
||||
form) with the major components (compiler, kernel, and so on) of the
|
||||
operating system on which the executable runs, unless that component
|
||||
itself accompanies the executable.
|
||||
|
||||
If distribution of executable or object code is made by offering
|
||||
access to copy from a designated place, then offering equivalent
|
||||
access to copy the source code from the same place counts as
|
||||
distribution of the source code, even though third parties are not
|
||||
compelled to copy the source along with the object code.
|
||||
|
||||
4. You may not copy, modify, sublicense, or distribute the Program
|
||||
except as expressly provided under this License. Any attempt
|
||||
otherwise to copy, modify, sublicense or distribute the Program is
|
||||
void, and will automatically terminate your rights under this License.
|
||||
However, parties who have received copies, or rights, from you under
|
||||
this License will not have their licenses terminated so long as such
|
||||
parties remain in full compliance.
|
||||
|
||||
5. You are not required to accept this License, since you have not
|
||||
signed it. However, nothing else grants you permission to modify or
|
||||
distribute the Program or its derivative works. These actions are
|
||||
prohibited by law if you do not accept this License. Therefore, by
|
||||
modifying or distributing the Program (or any work based on the
|
||||
Program), you indicate your acceptance of this License to do so, and
|
||||
all its terms and conditions for copying, distributing or modifying
|
||||
the Program or works based on it.
|
||||
|
||||
6. Each time you redistribute the Program (or any work based on the
|
||||
Program), the recipient automatically receives a license from the
|
||||
original licensor to copy, distribute or modify the Program subject to
|
||||
these terms and conditions. You may not impose any further
|
||||
restrictions on the recipients' exercise of the rights granted herein.
|
||||
You are not responsible for enforcing compliance by third parties to
|
||||
this License.
|
||||
|
||||
7. If, as a consequence of a court judgment or allegation of patent
|
||||
infringement or for any other reason (not limited to patent issues),
|
||||
conditions are imposed on you (whether by court order, agreement or
|
||||
otherwise) that contradict the conditions of this License, they do not
|
||||
excuse you from the conditions of this License. If you cannot
|
||||
distribute so as to satisfy simultaneously your obligations under this
|
||||
License and any other pertinent obligations, then as a consequence you
|
||||
may not distribute the Program at all. For example, if a patent
|
||||
license would not permit royalty-free redistribution of the Program by
|
||||
all those who receive copies directly or indirectly through you, then
|
||||
the only way you could satisfy both it and this License would be to
|
||||
refrain entirely from distribution of the Program.
|
||||
|
||||
If any portion of this section is held invalid or unenforceable under
|
||||
any particular circumstance, the balance of the section is intended to
|
||||
apply and the section as a whole is intended to apply in other
|
||||
circumstances.
|
||||
|
||||
It is not the purpose of this section to induce you to infringe any
|
||||
patents or other property right claims or to contest validity of any
|
||||
such claims; this section has the sole purpose of protecting the
|
||||
integrity of the free software distribution system, which is
|
||||
implemented by public license practices. Many people have made
|
||||
generous contributions to the wide range of software distributed
|
||||
through that system in reliance on consistent application of that
|
||||
system; it is up to the author/donor to decide if he or she is willing
|
||||
to distribute software through any other system and a licensee cannot
|
||||
impose that choice.
|
||||
|
||||
This section is intended to make thoroughly clear what is believed to
|
||||
be a consequence of the rest of this License.
|
||||
|
||||
8. If the distribution and/or use of the Program is restricted in
|
||||
certain countries either by patents or by copyrighted interfaces, the
|
||||
original copyright holder who places the Program under this License
|
||||
may add an explicit geographical distribution limitation excluding
|
||||
those countries, so that distribution is permitted only in or among
|
||||
countries not thus excluded. In such case, this License incorporates
|
||||
the limitation as if written in the body of this License.
|
||||
|
||||
9. The Free Software Foundation may publish revised and/or new versions
|
||||
of the General Public License from time to time. Such new versions will
|
||||
be similar in spirit to the present version, but may differ in detail to
|
||||
address new problems or concerns.
|
||||
|
||||
Each version is given a distinguishing version number. If the Program
|
||||
specifies a version number of this License which applies to it and "any
|
||||
later version", you have the option of following the terms and conditions
|
||||
either of that version or of any later version published by the Free
|
||||
Software Foundation. If the Program does not specify a version number of
|
||||
this License, you may choose any version ever published by the Free Software
|
||||
Foundation.
|
||||
|
||||
10. If you wish to incorporate parts of the Program into other free
|
||||
programs whose distribution conditions are different, write to the author
|
||||
to ask for permission. For software which is copyrighted by the Free
|
||||
Software Foundation, write to the Free Software Foundation; we sometimes
|
||||
make exceptions for this. Our decision will be guided by the two goals
|
||||
of preserving the free status of all derivatives of our free software and
|
||||
of promoting the sharing and reuse of software generally.
|
||||
|
||||
NO WARRANTY
|
||||
|
||||
11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
|
||||
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
|
||||
OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
|
||||
PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
|
||||
OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
|
||||
TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
|
||||
PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
|
||||
REPAIR OR CORRECTION.
|
||||
|
||||
12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
|
||||
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
|
||||
REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
|
||||
INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
|
||||
OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
|
||||
TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
|
||||
YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
|
||||
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGES.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
How to Apply These Terms to Your New Programs
|
||||
|
||||
If you develop a new program, and you want it to be of the greatest
|
||||
possible use to the public, the best way to achieve this is to make it
|
||||
free software which everyone can redistribute and change under these terms.
|
||||
|
||||
To do so, attach the following notices to the program. It is safest
|
||||
to attach them to the start of each source file to most effectively
|
||||
convey the exclusion of warranty; and each file should have at least
|
||||
the "copyright" line and a pointer to where the full notice is found.
|
||||
|
||||
<one line to give the program's name and a brief idea of what it does.>
|
||||
Copyright (C) <year> <name of author>
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
|
||||
|
||||
Also add information on how to contact you by electronic and paper mail.
|
||||
|
||||
If the program is interactive, make it output a short notice like this
|
||||
when it starts in an interactive mode:
|
||||
|
||||
Gnomovision version 69, Copyright (C) year name of author
|
||||
Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
|
||||
This is free software, and you are welcome to redistribute it
|
||||
under certain conditions; type `show c' for details.
|
||||
|
||||
The hypothetical commands `show w' and `show c' should show the appropriate
|
||||
parts of the General Public License. Of course, the commands you use may
|
||||
be called something other than `show w' and `show c'; they could even be
|
||||
mouse-clicks or menu items--whatever suits your program.
|
||||
|
||||
You should also get your employer (if you work as a programmer) or your
|
||||
school, if any, to sign a "copyright disclaimer" for the program, if
|
||||
necessary. Here is a sample; alter the names:
|
||||
|
||||
Yoyodyne, Inc., hereby disclaims all copyright interest in the program
|
||||
`Gnomovision' (which makes passes at compilers) written by James Hacker.
|
||||
|
||||
<signature of Ty Coon>, 1 April 1989
|
||||
Ty Coon, President of Vice
|
||||
|
||||
This General Public License does not permit incorporating your program into
|
||||
proprietary programs. If your program is a subroutine library, you may
|
||||
consider it more useful to permit linking proprietary applications with the
|
||||
library. If this is what you want to do, use the GNU Library General
|
||||
Public License instead of this License.
|
161
Components.txt
Normal file
161
Components.txt
Normal file
@ -0,0 +1,161 @@
|
||||
|
||||
SICS components in this directory
|
||||
|
||||
|
||||
1.) SICS core
|
||||
|
||||
- SCinter.* SICS-Interpreter
|
||||
- Scommon.h common definitions
|
||||
- conman.* Connection object and management
|
||||
- devexec.* Device executor
|
||||
- ifile.* options database
|
||||
- interrupt.h Interrupt system
|
||||
intserv.c
|
||||
intcli.*
|
||||
- macro.* link between Sics and Tcl
|
||||
initcl.c
|
||||
- network.* network protocoll handling
|
||||
- obdes.* Object descriptor
|
||||
- ofac.* Object factory, creates objects at startup
|
||||
- passwd.* password database
|
||||
- script.* some commands to access SICS internals from
|
||||
Tcl-scripts.
|
||||
- nserver.* server startup and closing, main loop
|
||||
- servlog.* manages the server log
|
||||
- nserver.c server main program
|
||||
- interface.* object interface descriptions
|
||||
- event.* SICS event description
|
||||
- callback.* The callback system
|
||||
- costa.* Command stack used for queing commands.
|
||||
- ecode.* Text version of error codes.
|
||||
- task.* Cooperative multitasker.
|
||||
|
||||
|
||||
2.) SICS core Objects
|
||||
|
||||
- buffer.* LNS-RuenBueffer
|
||||
- ruli.* RuenBueffer stack management
|
||||
- configfu.h Prototype for some configuration commands
|
||||
- status.* Status handling object
|
||||
- sicsexit.* Exit command
|
||||
- commandlog.* The commandlog
|
||||
- danu.c The data file number management
|
||||
- emon.* Environment control monitoring
|
||||
- evcontroller.* General environment controller class.
|
||||
- evdriver.* General environement controller driver.
|
||||
- perfmon.* Performance measure.
|
||||
- token.* The token system for access control.
|
||||
- udpquieck.* send a UDP message when a data file changed.
|
||||
|
||||
|
||||
|
||||
3.) SICS Objects
|
||||
|
||||
- counter.* Single counter object
|
||||
- drive.* Drive command
|
||||
- motor.* logical motor
|
||||
- mumo.* multiple motor object (SANS)
|
||||
comentry.*
|
||||
mumoconf.*
|
||||
- o2t.* Omega2Theta variable for TOPSI
|
||||
- selector.* Handles a crystal monochromator with energy
|
||||
selvar.* and lambda variables
|
||||
- sicsvar.* primitive text, float or integer variables
|
||||
- histmem.* histogram memory object
|
||||
- nxdata.c some general NeXus data storage utilities
|
||||
and the DMC storage routine
|
||||
- nxutil.* NeXus utility routines.
|
||||
- velo.* The velocity selector
|
||||
- amor2t.* The AMOR Reflectometer two-theta movement
|
||||
- choco.* A generalized controller with driveable
|
||||
- chadapter.* parameters realized in chadapter.
|
||||
- dmc.c special command initialization for DMC
|
||||
- faverage.* Special command to average FOCUS-TOF data
|
||||
online for status display.
|
||||
- fitcenter.* Rough fitting and driving to center of
|
||||
peaks.
|
||||
- fowrite.* FOCUS TOF NeXus file writing.
|
||||
- hkl.* Four circle angle calculation and driving.
|
||||
- hklscan.* Scanning in reciprocal space for 4-circle.
|
||||
- integrate.* Gabe integrtaion of scanned peaks.
|
||||
- itc4.* Special things for ITC4, ITC-503 temperature
|
||||
controllers.
|
||||
- mesure.* Measuring reflection list on a 4-circle.
|
||||
- nextrics.* Writing NeXus files for TRICS in rotation
|
||||
camera mode.
|
||||
- optimse.* General automatic peak optimisation using
|
||||
center-of-gravity.
|
||||
- pimotor.* Physik Instrument DC-804 step motor controller,
|
||||
a child of motor.
|
||||
- sanswave.* wavelength calculation for SANS using a
|
||||
velocity selector.
|
||||
- scan.* General purpose scanning utility.
|
||||
- scontroller.* Access a serial port directly using SICS
|
||||
- serial.* ways.
|
||||
- sps.* Dealing with Siemens Siematic SPS controllers.
|
||||
Probably SINQ specific.
|
||||
- varlog.* log an environment controller
|
||||
- xytable.* A general purpose table of x-y values.
|
||||
- a2t. * AMOR two theta movement
|
||||
- amorstat.* AMOR status display support
|
||||
- nxamor.* AMOR data file writing
|
||||
- amorscan.* AMOR specific scan functions.
|
||||
|
||||
|
||||
4.) SICS Hardware driver
|
||||
|
||||
- countdriv.* EL737 counter driver
|
||||
- modriv.* EL734 motor driver
|
||||
el734driv.c
|
||||
el734dc.c
|
||||
- bruker.c Driver for the Bruker Magnet
|
||||
- simcter.c Simulated counter
|
||||
- simdriv.c Simulated motor
|
||||
- histsim.c Simualted histogram memory
|
||||
- histdriv.c histogram driver general
|
||||
- sinqhmdriv.c SinQ histogram memory driver
|
||||
- velosim.c Simulated velocity selector
|
||||
- velodornier.c Dornier velocity selector
|
||||
- dilludriv.* Driver for the old dillution cryostat
|
||||
- docho.* Dornier chopper control system
|
||||
- itc4driv.* Driver for ITC-4 - ITC-503 temperature
|
||||
controllers.
|
||||
- ltc11.* Driver for the Kyocera LTC-11 temperature
|
||||
controller.
|
||||
- pipiezo.* Driver for a Physik Instrument Piezo motor
|
||||
controller.
|
||||
- simchop.* simulated chopper.
|
||||
- simev.* simulated environment controller.
|
||||
- tclev.v necessary code for defining a environment
|
||||
controller driver in Tcl.
|
||||
|
||||
|
||||
5.) Utility
|
||||
|
||||
some of these are freeware files from the net
|
||||
|
||||
- Dbg.* Don Libbes Tcl-Debugger
|
||||
- bit.h Bit-Array handling macros
|
||||
- defines.h, lld*.* Linked list package
|
||||
- fortify.* memory debugging package
|
||||
ufortify.*
|
||||
- fupa.* helps interpreting object commands
|
||||
- obpar.* manages array of object parameters
|
||||
- splitter.* command analysis code
|
||||
- strdup.*, string duplication
|
||||
- strrepl.c string replacement
|
||||
- stringdict.* a String Dictionary
|
||||
- dynstring.* Dynamic Strings.
|
||||
- sdynar.* Dynmaic array.
|
||||
- uubuffer.* uuencode something into a buffer.
|
||||
|
||||
6.) Subdirectorys
|
||||
|
||||
- hardsup additional HW handling code
|
||||
- tcl SICS commands implemented in Tcl
|
||||
- user user documentation
|
||||
- user/general general SICS commands
|
||||
- user/DMC DMC specific commands
|
||||
- status status display clients
|
||||
- fourcircle four circle diffraction related stuff
|
||||
- ninx The ILL program INX modified for NeXus
|
46
Dbg.h
Normal file
46
Dbg.h
Normal file
@ -0,0 +1,46 @@
|
||||
/* Dbg.h - Tcl Debugger include file
|
||||
|
||||
Written by: Don Libes, NIST, 3/23/93
|
||||
|
||||
Design and implementation of this program was paid for by U.S. tax
|
||||
dollars. Therefore it is public domain. However, the author and NIST
|
||||
would appreciate credit if this program or parts of it are used.
|
||||
|
||||
*/
|
||||
|
||||
/* _DEBUG or _DBG is just too likely, use something more unique */
|
||||
#ifndef _NIST_DBG
|
||||
#define _NIST_DBG
|
||||
|
||||
#include "tcl.h"
|
||||
|
||||
typedef int (Dbg_InterProc) _ANSI_ARGS_((Tcl_Interp *interp));
|
||||
typedef int (Dbg_IgnoreFuncsProc) _ANSI_ARGS_((
|
||||
Tcl_Interp *interp,
|
||||
char *funcname));
|
||||
typedef void (Dbg_OutputProc) _ANSI_ARGS_((
|
||||
Tcl_Interp *interp,
|
||||
char *output));
|
||||
|
||||
EXTERN char *Dbg_VarName;
|
||||
EXTERN char *Dbg_DefaultCmdName;
|
||||
|
||||
/* trivial interface, creates a "debug" command in your interp */
|
||||
EXTERN int Dbg_Init _ANSI_ARGS_((Tcl_Interp *));
|
||||
|
||||
EXTERN void Dbg_On _ANSI_ARGS_((Tcl_Interp *interp,
|
||||
int immediate));
|
||||
EXTERN void Dbg_Off _ANSI_ARGS_((Tcl_Interp *interp));
|
||||
EXTERN char **Dbg_ArgcArgv _ANSI_ARGS_((int argc,char *argv[],
|
||||
int copy));
|
||||
EXTERN int Dbg_Active _ANSI_ARGS_((Tcl_Interp *interp));
|
||||
EXTERN Dbg_InterProc *Dbg_Interactor _ANSI_ARGS_((
|
||||
Tcl_Interp *interp,
|
||||
Dbg_InterProc *interactor));
|
||||
EXTERN Dbg_IgnoreFuncsProc *Dbg_IgnoreFuncs _ANSI_ARGS_((
|
||||
Tcl_Interp *interp,
|
||||
Dbg_IgnoreFuncsProc *));
|
||||
EXTERN Dbg_OutputProc *Dbg_Output _ANSI_ARGS_((
|
||||
Tcl_Interp *interp,
|
||||
Dbg_OutputProc *));
|
||||
#endif /* _NIST_DBG */
|
64
Dbg_cmd.c
Normal file
64
Dbg_cmd.c
Normal file
@ -0,0 +1,64 @@
|
||||
/* Dbg_cmd.c - Tcl Debugger default command, used if app writer wants a
|
||||
quick and reasonable default.
|
||||
|
||||
Written by: Don Libes, NIST, 3/23/93
|
||||
|
||||
Design and implementation of this program was paid for by U.S. tax
|
||||
dollars. Therefore it is public domain. However, the author and NIST
|
||||
would appreciate credit if this program or parts of it are used.
|
||||
|
||||
*/
|
||||
|
||||
#include "tclInt.h"
|
||||
#include "Dbg.h"
|
||||
|
||||
char *Dbg_DefaultCmdName = "debug";
|
||||
|
||||
/*ARGSUSED*/
|
||||
static int
|
||||
App_DebugCmd(clientData, interp, argc, argv)
|
||||
ClientData clientData;
|
||||
Tcl_Interp *interp;
|
||||
int argc;
|
||||
char **argv;
|
||||
{
|
||||
int now = 0; /* soon if 0, now if 1 */
|
||||
|
||||
if (argc > 3) goto usage;
|
||||
|
||||
argv++;
|
||||
|
||||
while (*argv) {
|
||||
if (0 == strcmp(*argv,"-now")) {
|
||||
now = 1;
|
||||
argv++;
|
||||
}
|
||||
else break;
|
||||
}
|
||||
|
||||
if (!*argv) {
|
||||
if (now) {
|
||||
Dbg_On(interp,1);
|
||||
} else {
|
||||
goto usage;
|
||||
}
|
||||
} else if (0 == strcmp(*argv,"0")) {
|
||||
Dbg_Off(interp);
|
||||
} else {
|
||||
Dbg_On(interp,now);
|
||||
}
|
||||
return(TCL_OK);
|
||||
usage:
|
||||
interp->result = "usage: [[-now] 1|0]";
|
||||
return TCL_ERROR;
|
||||
}
|
||||
|
||||
int
|
||||
Dbg_Init(interp)
|
||||
Tcl_Interp *interp;
|
||||
{
|
||||
Tcl_CreateCommand(interp,Dbg_DefaultCmdName,App_DebugCmd,
|
||||
(ClientData)0,(void (*)())0);
|
||||
return TCL_OK;
|
||||
}
|
||||
|
84
HistDriv.i
Normal file
84
HistDriv.i
Normal file
@ -0,0 +1,84 @@
|
||||
|
||||
#line 462 "histogram.w"
|
||||
|
||||
/*---------------------------------------------------------------------------
|
||||
H I S T D R I V
|
||||
internal header file which includes the definition of the Histogram memory
|
||||
driver structure.
|
||||
|
||||
Mark Koennecke, April 1997
|
||||
----------------------------------------------------------------------------*/
|
||||
#ifndef SICSHISTDRIV
|
||||
#define SICSHISTDRIV
|
||||
#include "hmdata.h"
|
||||
|
||||
|
||||
#line 89 "histogram.w"
|
||||
|
||||
typedef struct __HistDriver {
|
||||
pHMdata data;
|
||||
/* counting operations data */
|
||||
CounterMode eCount;
|
||||
float fCountPreset;
|
||||
/* status flags */
|
||||
int iReconfig;
|
||||
int iUpdate;
|
||||
/* interface functions */
|
||||
int (*Configure)(pHistDriver self,
|
||||
SConnection *pCon,
|
||||
pStringDict pOpt,
|
||||
SicsInterp *pSics);
|
||||
int (*Start)(pHistDriver self,
|
||||
SConnection *pCon);
|
||||
int (*Halt)(pHistDriver self);
|
||||
int (*GetCountStatus)(pHistDriver self,
|
||||
SConnection *pCon);
|
||||
int (*GetError)(pHistDriver self,
|
||||
int *iCode,
|
||||
char *perror,
|
||||
int iErrlen);
|
||||
int (*TryAndFixIt)(pHistDriver self,
|
||||
int iCode);
|
||||
int (*GetData)(pHistDriver self,
|
||||
SConnection *pCon);
|
||||
int (*GetHistogram)(pHistDriver self,
|
||||
SConnection *pCon,
|
||||
int i,
|
||||
int iStart, int iEnd,
|
||||
HistInt *pData);
|
||||
|
||||
int (*SetHistogram)(pHistDriver self,
|
||||
SConnection *pCon,
|
||||
int i,
|
||||
int iStart, int iEnd,
|
||||
HistInt *pData);
|
||||
long (*GetMonitor)(pHistDriver self,
|
||||
int i,
|
||||
SConnection *pCon);
|
||||
float (*GetTime)(pHistDriver self,
|
||||
SConnection *pCon);
|
||||
int (*Preset)(pHistDriver self,
|
||||
SConnection *pCon,
|
||||
HistInt iVal);
|
||||
int (*Pause)(pHistDriver self,
|
||||
SConnection *pCon);
|
||||
int (*Continue)(pHistDriver self,
|
||||
SConnection *pCon);
|
||||
int (*FreePrivate)(pHistDriver self);
|
||||
void *pPriv;
|
||||
} HistDriver;
|
||||
|
||||
#line 474 "histogram.w"
|
||||
|
||||
|
||||
#line 228 "histogram.w"
|
||||
|
||||
pHistDriver CreateHistDriver(pStringDict pDict);
|
||||
void DeleteHistDriver(pHistDriver self);
|
||||
int HistDriverConfig(pHistDriver self, pStringDict pOpt,
|
||||
SConnection *pCon);
|
||||
|
||||
#line 475 "histogram.w"
|
||||
|
||||
|
||||
#endif
|
100
HistMem.h
Normal file
100
HistMem.h
Normal file
@ -0,0 +1,100 @@
|
||||
|
||||
#line 435 "histogram.w"
|
||||
|
||||
/*--------------------------------------------------------------------------
|
||||
H I S T M E M
|
||||
|
||||
header for the histogram memory object for SICS.
|
||||
|
||||
copyright: see implementation file.
|
||||
Mark Koennecke, April 1997
|
||||
-----------------------------------------------------------------------------*/
|
||||
#ifndef SICSHISTMEM
|
||||
#define SICSHISTMEM
|
||||
#define MAXDIM 3
|
||||
|
||||
typedef struct __HistDriver *pHistDriver;
|
||||
typedef struct __HistMem *pHistMem;
|
||||
/*-------------------------------------------------------------------------*/
|
||||
typedef int HistInt;
|
||||
/*
|
||||
32 bit integer on a DigitalUnix
|
||||
*/
|
||||
|
||||
#line 9 "histogram.w"
|
||||
|
||||
typedef enum {
|
||||
eHTransparent,
|
||||
eHNormal,
|
||||
eHTOF,
|
||||
eHStrobo,
|
||||
eHRPT,
|
||||
ePSD,
|
||||
eSANSTOF
|
||||
} HistMode;
|
||||
|
||||
#line 36 "histogram.w"
|
||||
|
||||
typedef enum {
|
||||
eOIgnore,
|
||||
eOCeil,
|
||||
eOCount,
|
||||
eReflect
|
||||
} OverFlowMode;
|
||||
|
||||
#line 455 "histogram.w"
|
||||
|
||||
/*--------------------------------------------------------------------------*/
|
||||
|
||||
#line 287 "histogram.w"
|
||||
|
||||
pHistMem CreateHistMemory(char *drivername);
|
||||
void DeleteHistMemory(void *self);
|
||||
|
||||
#line 303 "histogram.w"
|
||||
|
||||
int HistGetOption(pHistMem self, char *name, char *result, int iResultLen);
|
||||
int HistSetOption(pHistMem self, char *name, char *value);
|
||||
int HistConfigure(pHistMem self, SConnection *pCon, SicsInterp *pSics);
|
||||
|
||||
#line 331 "histogram.w"
|
||||
|
||||
float GetHistPreset(pHistMem self);
|
||||
int SetHistPreset(pHistMem self, float fVal);
|
||||
CounterMode GetHistCountMode(pHistMem self);
|
||||
int SetHistCountMode(pHistMem self, CounterMode eNew);
|
||||
long GetHistMonitor(pHistMem self, int i, SConnection *pCon);
|
||||
const float *GetHistTimeBin(pHistMem self, int *iLength);
|
||||
int GetHistLength(pHistMem self);
|
||||
int GetHistDim(pHistMem self, int iDim[MAXDIM], int *nDim);
|
||||
float GetHistCountTime(pHistMem self,SConnection *pCon);
|
||||
int HistDoCount(pHistMem self, SConnection *pCon);
|
||||
int HistBlockCount(pHistMem self, SConnection *pCon);
|
||||
void HistDirty(pHistMem self);
|
||||
|
||||
|
||||
#line 361 "histogram.w"
|
||||
|
||||
int SetHistogram(pHistMem self, SConnection *pCon,
|
||||
int i,int iStart, int iEnd, HistInt *lData);
|
||||
int GetHistogram(pHistMem self, SConnection *pCon,
|
||||
int i,int iStart, int iEnd, HistInt *lData, int iDataLen);
|
||||
HistInt *GetHistogramPointer(pHistMem self,SConnection *pCon);
|
||||
int GetHistogramDirect(pHistMem self, SConnection *pCon,
|
||||
int i, int iStart, int iEnd,
|
||||
HistInt *lData, int iDataLen);
|
||||
int PresetHistogram(pHistMem self, SConnection *pCon, HistInt lVal);
|
||||
|
||||
#line 404 "histogram.w"
|
||||
|
||||
int MakeHistMemory(SConnection *pCon, SicsInterp *pSics, void *pData,
|
||||
int argc, char *argv[]);
|
||||
|
||||
int HistAction(SConnection *pCon, SicsInterp *pSics, void *pData,
|
||||
int argc, char *argv[]);
|
||||
|
||||
|
||||
#line 457 "histogram.w"
|
||||
|
||||
|
||||
#endif
|
30
HistMem.i
Normal file
30
HistMem.i
Normal file
@ -0,0 +1,30 @@
|
||||
|
||||
#line 480 "histogram.w"
|
||||
|
||||
/*---------------------------------------------------------------------------
|
||||
H I S T M E M -- Internal
|
||||
internal header file which includes the definition of the Histogram memory
|
||||
data structure.
|
||||
|
||||
Mark Koennecke, April 1997
|
||||
----------------------------------------------------------------------------*/
|
||||
#ifndef SICSHISTMEMINT
|
||||
#define SICSHISTMEMINT
|
||||
|
||||
#line 250 "histogram.w"
|
||||
|
||||
typedef struct __HistMem {
|
||||
pObjectDescriptor pDes;
|
||||
int iAccess;
|
||||
int iExponent;
|
||||
pHistDriver pDriv;
|
||||
int iInit;
|
||||
pICountable pCountInt;
|
||||
pICallBack pCall;
|
||||
pStringDict pOption;
|
||||
} HistMem;
|
||||
|
||||
#line 490 "histogram.w"
|
||||
|
||||
|
||||
#endif
|
131
Makefile
Normal file
131
Makefile
Normal file
@ -0,0 +1,131 @@
|
||||
#----------------------------------------------------------------------------
|
||||
# Makefile for SICS
|
||||
#
|
||||
# Mark Koennecke 1996-2001
|
||||
# Markus Zolliker March 2000: add tecs
|
||||
#---------------------------------------------------------------------------
|
||||
|
||||
|
||||
#------- comment or uncomment this if a fortified version is required.
|
||||
# Note: A -DFORTIFY needs to be added to the CFLAGS as well.
|
||||
#
|
||||
#FORTIFYOBJ = fortify.o strdup.o
|
||||
#----
|
||||
FORTIFYOBJ =
|
||||
#---------------------------------------------------------------------------
|
||||
|
||||
#==========================================================================
|
||||
# assign if the National Instrument GPIB driver is available
|
||||
#NI= -DHAVENI
|
||||
#NIOBJ= nigpib.o
|
||||
#NILIB=-lgpibenet
|
||||
NI=
|
||||
NIOBJ=
|
||||
NILIB=
|
||||
|
||||
#----- comment or uncomment if a difrac version is required
|
||||
# Do not forget to remove or add comments to ofac.c as well if changes
|
||||
# were made here.
|
||||
|
||||
DIFOBJ=
|
||||
DIFIL=
|
||||
#DIFOBJ=difrac.o -Ldifrac -ldif -lfor
|
||||
#----
|
||||
#DIFOBJ=difrac.o -Ldifrac -ldif
|
||||
#DIFIL= difrac.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 \
|
||||
sicsexit.o costa.o task.o $(FORTIFYOBJ)\
|
||||
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 buffer.o strrepl.o ruli.o lin2ang.o fomerge.o\
|
||||
script.o o2t.o alias.o napi45.o nxdata.o stringdict.o sdynar.o\
|
||||
histmem.o histdriv.o histsim.o sinqhmdriv.o interface.o callback.o \
|
||||
event.o emon.o evcontroller.o evdriver.o simev.o perfmon.o \
|
||||
danu.o itc4driv.o itc4.o nxdict.o nxsans.o varlog.o stptok.o nread.o \
|
||||
dilludriv.o scan.o fitcenter.o telnet.o token.o scontroller.o serial.o \
|
||||
tclev.o hkl.o integrate.o optimise.o dynstring.o nextrics.o nxutil.o \
|
||||
mesure.o uubuffer.o serialwait.o commandlog.o sps.o udpquieck.o \
|
||||
sanswave.o faverage.o bruker.o rmtrail.o fowrite.o ltc11.o \
|
||||
simchop.o choco.o chadapter.o docho.o trim.o eurodriv.o scaldate.o \
|
||||
hklscan.o xytable.o amor2t.o nxamor.o amorscan.o amorstat.o \
|
||||
circular.o el755driv.o maximize.o sicscron.o tecsdriv.o sanscook.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 motreg.o motreglist.o anticollider.o \
|
||||
s_rnge.o sig_die.o gpibcontroller.o $(NIOBJ) ecb.o ecbdriv.o \
|
||||
ecbcounter.o hmdata.o tdchm.o nxscript.o A1931.o frame.o
|
||||
|
||||
MOTOROBJ = motor.o el734driv.o simdriv.o el734dc.o pipiezo.o pimotor.o
|
||||
COUNTEROBJ = countdriv.o simcter.o counter.o
|
||||
DMCOBJ = dmc.o
|
||||
VELOOBJ = velo.o velosim.o velodorn.o velodornier.o
|
||||
|
||||
.SUFFIXES:
|
||||
.SUFFIXES: .tcl .htm .c .o
|
||||
|
||||
#----- comment or uncomment the following according to operating system
|
||||
|
||||
#------------- for Digital Unix
|
||||
BINTARGET = bin
|
||||
HDFROOT=/data/lnslib
|
||||
CC=cc
|
||||
EXTRA=
|
||||
CFLAGS = -I$(HDFROOT)/include -Ihardsup -DHDF4 -DHDF5 -I. -std1 \
|
||||
-check_bounds -g -warnprotos -c
|
||||
#CFLAGS = -I$(HDFROOT)/include -DFORTIFY -DHDF4 -DHDF5 -Ihardsup -g \
|
||||
# -std1 -warnprotos -c
|
||||
LIBS = -L$(HDFROOT)/lib -Lhardsup -lhlib -Lmatrix -lmatrix -Ltecs \
|
||||
-ltecsl -ltcl8.0 -lfor $(HDFROOT)/lib/libhdf5.a \
|
||||
$(HDFROOT)/lib/libLNSmfhdf.a $(HDFROOT)/lib/libLNSdf.a \
|
||||
$(HDFROOT)/lib/libLNSjpeg.a -lLNSz -lm -ll -lc
|
||||
|
||||
#------- for cygnus
|
||||
#HDFROOT=../HDF411
|
||||
#CC=gcc
|
||||
#EXTRA=
|
||||
#CFLAGS = -I$(HDFROOT)/include -Ihardsup -DFORTIFY -DCYGNUS -g -c
|
||||
#LIBS= -L$(HDFROOT)/lib -Lhardsup -lhlib -ltcl80 \
|
||||
# -lmfhdf -ldf -ljpeg -lz -lm
|
||||
|
||||
#---------- for linux
|
||||
#BINTARGET=../../bin
|
||||
#HDFROOT=$(SINQDIR)/linux
|
||||
#CC=gcc
|
||||
#CFLAGS = -I$(HDFROOT)/include -DHDF4 -DHDF5 $(NI) -Ihardsup \
|
||||
# -fwritable-strings -DCYGNUS -DNONINTF -g -c
|
||||
#CFLAGS = -I$(HDFROOT)/include -DFORTIFY -DHDF4 -DHDF5 $(NI) -Ihardsup \
|
||||
# -fwritable-strings -DCYGNUS -DNONINTF -g -c
|
||||
#LIBS= -L$(HDFROOT)/lib -Lhardsup -Ltecs -ltecsl -Lmatrix -lmatrix -lhlib \
|
||||
# $(NILIB) -ltcl -lhdf5 -lmfhdf -ldf -ljpeg -lz -lm -lg2c -ldl
|
||||
#EXTRA=nintf.o
|
||||
#---------------------------------
|
||||
|
||||
.c.o:
|
||||
$(CC) $(CFLAGS) $*.c
|
||||
|
||||
all: $(BINTARGET)/SICServer
|
||||
|
||||
$(BINTARGET)/SICServer: $(SOBJ) $(MOTOROBJ) \
|
||||
$(COUNTEROBJ) $(DMCOBJ) $(VELOOBJ) $(DIFIL) \
|
||||
$(EXTRA) tecs/libtecsl.a hardsup/libhlib.a \
|
||||
matrix/libmatrix.a
|
||||
$(CC) -g -o SICServer \
|
||||
$(SOBJ) $(MOTOROBJ) $(COUNTEROBJ) $(DMCOBJ) \
|
||||
$(VELOOBJ) $(DIFOBJ) $(EXTRA) $(LIBS)
|
||||
cp SICServer $(BINTARGET)
|
||||
|
||||
clean:
|
||||
- rm -f *.o
|
||||
- rm -f $(BINTARGET)/SICServer
|
||||
|
||||
Dbg.o: Dbg.c
|
||||
cc -g -I/data/koenneck/include -c Dbg.c
|
||||
Dbg_cmd.o: Dbg_cmd.c
|
||||
|
||||
|
569
SCinter.c
Normal file
569
SCinter.c
Normal file
@ -0,0 +1,569 @@
|
||||
/*---------------------------------------------------------------------------
|
||||
|
||||
Implementation file for the SICS-interpreter.
|
||||
|
||||
|
||||
|
||||
Mark Koennecke, November 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.
|
||||
|
||||
M. Zolliker, Sept 2000, introduced formal aliases, modifications marked M.Z
|
||||
Mark Koennecke, August 2001, modified SicsWriteStatus to write motor
|
||||
positions on demand.
|
||||
---------------------------------------------------------------------------*/
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <ctype.h>
|
||||
#include <assert.h>
|
||||
#include <string.h>
|
||||
#include <tcl.h>
|
||||
#include "fortify.h"
|
||||
#include "sics.h"
|
||||
#include "splitter.h"
|
||||
#include "servlog.h"
|
||||
#include "macro.h"
|
||||
#include "interface.h"
|
||||
#include "motor.h"
|
||||
#include "obdes.h"
|
||||
|
||||
/* M.Z. */
|
||||
#include "definealias.h"
|
||||
|
||||
|
||||
#define MAXLEN 256
|
||||
#define MAXPAR 100
|
||||
|
||||
/*--------------------------------------------------------------------------*/
|
||||
SicsInterp *InitInterp(void)
|
||||
{
|
||||
SicsInterp *pInter = NULL;
|
||||
int i;
|
||||
|
||||
pInter = (SicsInterp *)malloc(sizeof(SicsInterp));
|
||||
if(!pInter)
|
||||
{
|
||||
SICSLogWrite("Error allocating memory for Interpreter",eInternal);
|
||||
return NULL;
|
||||
}
|
||||
pInter->pCList = NULL;
|
||||
pInter->AList.pFirst = NULL; /* M.Z. */
|
||||
pInter->pTcl = (void *)MacroInit(pInter);
|
||||
if(!pInter->pTcl)
|
||||
{
|
||||
free(pInter);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
pInter->iDeleting = 0;
|
||||
return pInter;
|
||||
}
|
||||
/*------------------------------------------------------------------------*/
|
||||
int AddCommand(SicsInterp *pInterp, char *pName, ObjectFunc pFunc,
|
||||
KillFunc pKFunc, void *pData)
|
||||
{
|
||||
CommandList *pNew = NULL;
|
||||
char pBueffel[512];
|
||||
|
||||
assert(pName);
|
||||
assert(pFunc);
|
||||
assert(pInterp);
|
||||
|
||||
strcpy(pBueffel,pName);
|
||||
strtolower(pBueffel);
|
||||
RemoveAlias(&pInterp->AList,pBueffel); /* M.Z. */
|
||||
if(FindCommand(pInterp,pBueffel) != NULL)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* new memory */
|
||||
pNew = (CommandList *)malloc(sizeof(CommandList));
|
||||
if(!pNew)
|
||||
{
|
||||
sprintf(pBueffel,
|
||||
"Out of memory creating command - %s -", pName);
|
||||
SICSLogWrite(pBueffel,eInternal);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* if no data given, initialise with Dummy struct */
|
||||
if(!pData)
|
||||
{
|
||||
pData = (void *)CreateDummy(pBueffel);
|
||||
if(!pKFunc)
|
||||
{
|
||||
pKFunc = KillDummy;
|
||||
}
|
||||
}
|
||||
|
||||
/* initialise datastructures */
|
||||
pNew->pName = strdup(pBueffel);
|
||||
pNew->OFunc = pFunc;
|
||||
pNew->KFunc = pKFunc;
|
||||
pNew->pData = pData;
|
||||
pNew->pNext = pInterp->pCList;
|
||||
|
||||
|
||||
if(pInterp->pCList)
|
||||
{
|
||||
pInterp->pCList->pPrevious = pNew;
|
||||
}
|
||||
pNew->pPrevious = NULL;
|
||||
|
||||
/* update headpointer */
|
||||
pInterp->pCList = pNew;
|
||||
return 1;
|
||||
}
|
||||
/*------------------------------------------------------------------------*/
|
||||
int RemoveCommand(SicsInterp *pInterp, char *pName)
|
||||
{
|
||||
CommandList *pVictim = NULL;
|
||||
char pBueffel[256];
|
||||
|
||||
assert(pInterp);
|
||||
assert(pName);
|
||||
|
||||
strcpy(pBueffel,pName);
|
||||
strtolower(pBueffel);
|
||||
|
||||
if(pInterp->iDeleting)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* find our victim */
|
||||
pVictim = FindCommand(pInterp, pBueffel);
|
||||
if(!pVictim)
|
||||
return 0;
|
||||
|
||||
/* found, remove it */
|
||||
/* kall KillFunction first */
|
||||
if(pVictim->KFunc)
|
||||
{
|
||||
pVictim->KFunc(pVictim->pData);
|
||||
}
|
||||
|
||||
/* delete and unlink data */
|
||||
if(pVictim->pName)
|
||||
{
|
||||
free(pVictim->pName);
|
||||
}
|
||||
if(pVictim->pPrevious)
|
||||
{
|
||||
pVictim->pPrevious->pNext = pVictim->pNext;
|
||||
}
|
||||
if(pVictim->pNext)
|
||||
{
|
||||
pVictim->pNext->pPrevious = pVictim->pPrevious;
|
||||
}
|
||||
/* adjust headpointer if necessary */
|
||||
if(pVictim == pInterp->pCList)
|
||||
{
|
||||
pInterp->pCList = pVictim->pNext;
|
||||
}
|
||||
free(pVictim);
|
||||
return 1;
|
||||
}
|
||||
|
||||
#define MAXLEN 256
|
||||
#define MAXCOM 50
|
||||
extern char *stptok(char *s, char *tok, unsigned int toklen, char *brk);
|
||||
extern char *SkipSpace(char *pPtr);
|
||||
/*------------------------------------------------------------------------*/
|
||||
int InterpExecute(SicsInterp *self,SConnection *pCon, char *pText)
|
||||
{
|
||||
int iCount = 0;
|
||||
int iRet;
|
||||
int i, argc;
|
||||
char pBueffel[1024];
|
||||
CommandList *pCommand = NULL;
|
||||
char pBrk[] = {" \r\n\0"};
|
||||
char *pPtr;
|
||||
char **argv = NULL;
|
||||
|
||||
|
||||
assert(self);
|
||||
assert(pCon);
|
||||
|
||||
/* write info to Log */
|
||||
if(pCon->pSock)
|
||||
{
|
||||
sprintf(pBueffel,"Executing -> %s <- from socket %d",pText,
|
||||
pCon->pSock->sockid);
|
||||
SICSLogWrite(pBueffel,eCommand);
|
||||
}
|
||||
else
|
||||
{
|
||||
printf("Executing -> %s <- from dummy socket\n", pText);
|
||||
SICSLogWrite(pBueffel,eCommand);
|
||||
}
|
||||
|
||||
/* convert to argc, argv */
|
||||
argc = 0;
|
||||
Text2Arg(pText,&argc,&argv);
|
||||
|
||||
/* the first one must be the target object. If not given an empty
|
||||
command string was given which will be silently ignored */
|
||||
if(argc < 1)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
if(argv[0] == NULL)
|
||||
{
|
||||
SCWrite(pCon,"ERROR: failed to parse command",eError);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* find it */
|
||||
pCommand = FindCommand(self,argv[0]);
|
||||
if(!pCommand)
|
||||
{
|
||||
sprintf(pBueffel,"ERROR: Object -> %s <- NOT found",
|
||||
argv[0]);
|
||||
SCWrite(pCon,pBueffel,eError);
|
||||
return -1;
|
||||
|
||||
}
|
||||
|
||||
|
||||
/* invoke the command */
|
||||
self->eOut = eStatus;
|
||||
Tcl_ResetResult((Tcl_Interp *)self->pTcl);
|
||||
MacroPush(pCon);
|
||||
iRet = pCommand->OFunc(pCon, self, pCommand->pData, argc, argv);
|
||||
MacroPop();
|
||||
|
||||
/* delete argv */
|
||||
for(i = 0; i < argc; i++)
|
||||
{
|
||||
if(argv[i] != NULL)
|
||||
{
|
||||
free(argv[i]);
|
||||
}
|
||||
}
|
||||
free(argv);
|
||||
|
||||
return iRet;
|
||||
}
|
||||
/*------------------------------------------------------------------------*/
|
||||
CommandList *FindCommand(SicsInterp *self, char *pName)
|
||||
{
|
||||
CommandList *pCurrent = NULL;
|
||||
char pBueffel[256], *pCmd;
|
||||
|
||||
assert(self);
|
||||
|
||||
if(self->iDeleting)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
strcpy(pBueffel,pName);
|
||||
strtolower(pBueffel);
|
||||
|
||||
pCmd=TranslateAlias(&self->AList, pBueffel); /* M.Z. */
|
||||
|
||||
pCurrent = self->pCList;
|
||||
while(pCurrent)
|
||||
{
|
||||
if(pCurrent->pName != NULL)
|
||||
{
|
||||
if(strcmp(pCurrent->pName, pCmd) == 0 ) /* M.Z. */
|
||||
{
|
||||
return pCurrent;
|
||||
}
|
||||
}
|
||||
pCurrent = pCurrent->pNext;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
/*------------------------------------------------------------------------*/
|
||||
int WriteSicsStatus(SicsInterp *self, char *file, int iMot)
|
||||
{
|
||||
CommandList *pCurrent = NULL;
|
||||
FILE *fd = NULL;
|
||||
Dummy *pDum = NULL;
|
||||
float fVal;
|
||||
pIDrivable pDriv = NULL;
|
||||
void *pTest = NULL;
|
||||
|
||||
assert(self);
|
||||
assert(file);
|
||||
|
||||
/* open file */
|
||||
fd = fopen(file,"w");
|
||||
if(!fd)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
/* remove it, as I found garbage from previous runs in the
|
||||
status file
|
||||
*/
|
||||
fclose(fd);
|
||||
remove(file);
|
||||
|
||||
fd = fopen(file,"w");
|
||||
if(!fd)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* cycle through the list */
|
||||
pCurrent = self->pCList;
|
||||
while(pCurrent)
|
||||
{
|
||||
pDum = (Dummy *)pCurrent->pData;
|
||||
if(pDum)
|
||||
{
|
||||
pDum->pDescriptor->SaveStatus(pCurrent->pData,pCurrent->pName,fd);
|
||||
if(iMot)
|
||||
{
|
||||
/*
|
||||
save values of motors but not of environment devices as they
|
||||
may not be present the next time round
|
||||
*/
|
||||
pDriv = pDum->pDescriptor->GetInterface(pDum,DRIVEID);
|
||||
pTest = pDum->pDescriptor->GetInterface(pDum,ENVIRINTERFACE);
|
||||
if(pDriv && !pTest)
|
||||
{
|
||||
if(strcmp(pDum->pDescriptor->name,"Motor") == 0)
|
||||
{
|
||||
MotorGetSoftPosition((pMotor)pDum,pServ->dummyCon,&fVal);
|
||||
}
|
||||
else
|
||||
{
|
||||
fVal = pDriv->GetValue(pDum,pServ->dummyCon);
|
||||
}
|
||||
if(fVal > -990.)
|
||||
{
|
||||
fprintf(fd,"run %s %f\n",pCurrent->pName, fVal);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
pCurrent = pCurrent->pNext;
|
||||
}
|
||||
if(iMot)
|
||||
{
|
||||
fprintf(fd,"Success \n");
|
||||
}
|
||||
fclose(fd);
|
||||
return 1;
|
||||
}
|
||||
/*------------------------------------------------------------------------*/
|
||||
void DeleteInterp(SicsInterp *self)
|
||||
{
|
||||
CommandList *pCurrent = NULL;
|
||||
CommandList *pTemp;
|
||||
Tcl_Interp *pTcl = NULL;
|
||||
int i;
|
||||
|
||||
assert(self);
|
||||
self->iDeleting = 1;
|
||||
|
||||
/* delete Commandlist */
|
||||
pCurrent = self->pCList;
|
||||
while(pCurrent)
|
||||
{
|
||||
if(pCurrent->KFunc)
|
||||
{
|
||||
pCurrent->KFunc(pCurrent->pData);
|
||||
}
|
||||
if(pCurrent->pName)
|
||||
{
|
||||
/* printf("Deleting %s\n",pCurrent->pName); */
|
||||
free(pCurrent->pName);
|
||||
}
|
||||
pTemp = pCurrent->pNext;
|
||||
free(pCurrent);
|
||||
pCurrent = pTemp;
|
||||
}
|
||||
|
||||
FreeAliasList(&self->AList); /* M.Z. */
|
||||
|
||||
/* clear Tcl_Interpreter. Must be AFTER deleting command list because
|
||||
some devices may have Tcl drivers which need to be accessed for
|
||||
proper closing of devices.
|
||||
*/
|
||||
pTcl = (Tcl_Interp *)self->pTcl;
|
||||
if(pTcl)
|
||||
{
|
||||
Tcl_DeleteInterp(pTcl);
|
||||
}
|
||||
|
||||
free(self);
|
||||
}
|
||||
|
||||
/*--------------------------------------------------------------------------*/
|
||||
int ListObjects(SConnection *pCon, SicsInterp *pSics, void *pData,
|
||||
int argc, char *argv[])
|
||||
{
|
||||
CommandList *pCurrent;
|
||||
char pBueffel[256];
|
||||
int iNum = 0;
|
||||
|
||||
assert(pSics);
|
||||
assert(pCon);
|
||||
|
||||
pCurrent = pSics->pCList;
|
||||
while(pCurrent)
|
||||
{
|
||||
if(iNum == 0)
|
||||
{
|
||||
strcpy(pBueffel,pCurrent->pName);
|
||||
iNum++;
|
||||
}
|
||||
else if(iNum < 4)
|
||||
{
|
||||
strcat(pBueffel," ");
|
||||
strcat(pBueffel,pCurrent->pName);
|
||||
iNum++;
|
||||
}
|
||||
else
|
||||
{
|
||||
strcat(pBueffel," ");
|
||||
strcat(pBueffel,pCurrent->pName);
|
||||
strcat(pBueffel,"\r\n");
|
||||
SCWrite(pCon,pBueffel,eStatus);
|
||||
iNum = 0;
|
||||
}
|
||||
pCurrent = pCurrent->pNext;
|
||||
}
|
||||
|
||||
/* write final entries */
|
||||
if(strlen(pBueffel) > 2)
|
||||
{
|
||||
strcat(pBueffel,"\r\n");
|
||||
SCWrite(pCon,pBueffel,eStatus);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
int InterpWrite(SicsInterp *pSics, char *buffer)
|
||||
{
|
||||
Tcl_Interp *pTcl = NULL;
|
||||
|
||||
assert(pSics);
|
||||
pTcl = (Tcl_Interp *)pSics->pTcl;
|
||||
Tcl_SetResult(pTcl,buffer,TCL_VOLATILE);
|
||||
return 1;
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
Tcl_Interp *InterpGetTcl(SicsInterp *pSics)
|
||||
{
|
||||
Tcl_Interp *pTcl = NULL;
|
||||
|
||||
pTcl = (Tcl_Interp *)pSics->pTcl;
|
||||
return pTcl;
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
void strtolower(char *pText)
|
||||
{
|
||||
assert(pText);
|
||||
|
||||
while(*pText != '\0')
|
||||
{
|
||||
*pText = tolower(*pText);
|
||||
pText++;
|
||||
}
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
void argtolower(int argc, char *argv[])
|
||||
{
|
||||
int i;
|
||||
|
||||
for(i = 0; i < argc; i++)
|
||||
{
|
||||
strtolower(argv[i]);
|
||||
}
|
||||
}
|
||||
|
||||
/*------------------------------------------------------------------------*/
|
||||
char *FindAlias(SicsInterp *self, void *pData)
|
||||
{
|
||||
CommandList *pCurrent = NULL;
|
||||
|
||||
assert(self);
|
||||
|
||||
if(self->iDeleting)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
pCurrent = self->pCList;
|
||||
while(pCurrent)
|
||||
{
|
||||
if(pCurrent->pData == pData)
|
||||
{
|
||||
return pCurrent->pName;
|
||||
}
|
||||
pCurrent = pCurrent->pNext;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
void *FindCommandData(SicsInterp *pSics, char *name, char *cclass)
|
||||
{
|
||||
CommandList *pCom;
|
||||
pDummy pDum = NULL;
|
||||
|
||||
pCom = FindCommand(pSics,name);
|
||||
if(!pCom)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
if(!pCom->pData)
|
||||
return NULL;
|
||||
|
||||
pDum = (pDummy)pCom->pData;
|
||||
if(strcmp(pDum->pDescriptor->name,cclass) == 0)
|
||||
{
|
||||
return pCom->pData;
|
||||
}
|
||||
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;
|
||||
}
|
151
SCinter.h
Normal file
151
SCinter.h
Normal file
@ -0,0 +1,151 @@
|
||||
/*--------------------------------------------------------------------------
|
||||
|
||||
The SICS needs an interpreter. This is it.
|
||||
|
||||
Mark Koennecke, November 1996
|
||||
|
||||
copyright: see implementation file
|
||||
|
||||
---------------------------------------------------------------------------*/
|
||||
#ifndef SICSINTERPRETER
|
||||
#define SICSINTERPRETER
|
||||
#include "Scommon.h"
|
||||
#include <tcl.h>
|
||||
/* M.Z. */
|
||||
#include "definealias.i"
|
||||
|
||||
typedef struct __SConnection *pSConnection;
|
||||
typedef struct __SINTER *pSicsInterp;
|
||||
|
||||
|
||||
typedef int (*ObjectFunc)(pSConnection pCon, pSicsInterp pInter, void
|
||||
*pData, int argc, char *argv[]);
|
||||
|
||||
typedef void (*KillFunc)(void *pData);
|
||||
|
||||
typedef struct __Clist {
|
||||
char *pName;
|
||||
ObjectFunc OFunc;
|
||||
KillFunc KFunc;
|
||||
void *pData;
|
||||
struct __Clist *pNext;
|
||||
struct __Clist *pPrevious;
|
||||
} CommandList;
|
||||
|
||||
typedef struct __SINTER
|
||||
{
|
||||
CommandList *pCList;
|
||||
OutCode eOut;
|
||||
void *pTcl;
|
||||
int iDeleting;
|
||||
AliasList AList; /* M.Z. */
|
||||
}SicsInterp;
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
SicsInterp *InitInterp(void);
|
||||
/* makes a new interpreter. Returns him on success, else NULL
|
||||
*/
|
||||
/*------------------------------------------------------------------------*/
|
||||
int AddCommand(SicsInterp *pInterp, char *pName, ObjectFunc pFunc,
|
||||
KillFunc pKFunc, void *pData);
|
||||
/* adds a new command, Returns True or False, depending on success
|
||||
Parameters:
|
||||
pInterp : the interpreter to add the command to.
|
||||
pName : the commands name
|
||||
pFunc : the object function to call when this command is
|
||||
invoked. Definition of type: see above
|
||||
pKFunc : function to call in order to delete command data.
|
||||
type definition: above
|
||||
pData : pointer to the command's own datastructure. Will be
|
||||
passed as pData with each call to Ofunc.
|
||||
*/
|
||||
/*-------------------------------------------------------------------------*/
|
||||
int RemoveCommand(SicsInterp *pInterp, char *pName);
|
||||
/* kills the command name from the interpreter pInterp
|
||||
*/
|
||||
/*-------------------------------------------------------------------------*/
|
||||
int InterpExecute(SicsInterp *self,pSConnection pCon,char *pCommand);
|
||||
|
||||
/*
|
||||
executes a command in the interpreter self. Essentially converts
|
||||
pCommand in an argc, argv[] pair, sets various status things and
|
||||
invokes the object function. Takes care of status and error reporting
|
||||
afterwards.
|
||||
|
||||
Parameters:
|
||||
self : interpreter to invoke command in.
|
||||
The connection pCon will be used for I/O and status reporting.
|
||||
The command to invoke is the string pCommand.
|
||||
Returns -1 if the command can not be found.
|
||||
If the command is found, 1 is returned on success, 0 on failure in
|
||||
the command.
|
||||
----------------------------------------------------------------------------*/
|
||||
|
||||
CommandList *FindCommand(SicsInterp *pInterp, char *name);
|
||||
/*
|
||||
Searches the Interpreters pInterp command list for a command
|
||||
with name. Returns ist datastructure if found, NULL else
|
||||
*/
|
||||
/*-------------------------------------------------------------------------*/
|
||||
int WriteSicsStatus(SicsInterp *pSics,char *file, int iMot);
|
||||
/*
|
||||
SICS needs a way to save the status of each object into a file.
|
||||
This is done by invoking for each object the object descriptor
|
||||
function SaveStatus. This function does just that.
|
||||
|
||||
Parameters:
|
||||
pSics : the interpreter to use.
|
||||
file : the file to write the information to.
|
||||
iMot : flag if motor position shall be saved or not
|
||||
Returns: 1 on success, 0 on failure.
|
||||
---------------------------------------------------------------------------*/
|
||||
int InterpWrite(SicsInterp *pSics, char *buffer);
|
||||
/*
|
||||
writes result to Tcl, used for Macro mechanism.
|
||||
This is an internal function and should not be used.
|
||||
----------------------------------------------------------------------------*/
|
||||
|
||||
void DeleteInterp(SicsInterp *self);
|
||||
/*
|
||||
deletes the interpreter self aand clears all asoociated datastructures.
|
||||
self will no longer be valid after this.
|
||||
--------------------------------------------------------------------------- */
|
||||
void strtolower(char *pText);
|
||||
/*
|
||||
strtolower converts a string to lowercase
|
||||
--------------------------------------------------------------------------- */
|
||||
void argtolower(int argc, char *argv[]);
|
||||
/*
|
||||
converts an argc, argv[] pair to lowercase
|
||||
*/
|
||||
|
||||
/*--------------------------------------------------------------------------
|
||||
FindAlias tries to find an alias to the datastructure given as second
|
||||
parameter. Returns the command name on success, else NULL. Be warned, this
|
||||
is very special
|
||||
*/
|
||||
|
||||
char *FindAlias(SicsInterp *pSics, void *pData);
|
||||
|
||||
/*-------------------------------------------------------------------------
|
||||
FindCommandData finds a command with the name given. It tests the name in the
|
||||
ObjectDescriptor to be of name class. If all this succeeds a pointer
|
||||
to the commands data structure is retuned. Else NULL
|
||||
*/
|
||||
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);
|
||||
|
||||
/*-----------------------------------------------------------------------
|
||||
Get a copy of the Tcl interpreter
|
||||
------------------------------------------------------------------------*/
|
||||
Tcl_Interp *InterpGetTcl(SicsInterp *pSics);
|
||||
#endif
|
||||
|
87
SICSmain.c
Normal file
87
SICSmain.c
Normal file
@ -0,0 +1,87 @@
|
||||
/*--------------------------------------------------------------------------
|
||||
|
||||
THE SICS SERVER
|
||||
|
||||
|
||||
This file contains the main entry point into the world of SICS.
|
||||
|
||||
|
||||
|
||||
Mark Koennecke, October 1996
|
||||
|
||||
Copyright: see copyright.h
|
||||
|
||||
Labor fuer Neutronenstreuung
|
||||
Paul Scherrer Institut
|
||||
CH-5423 Villigen-PSI
|
||||
|
||||
|
||||
----------------------------------------------------------------------------*/
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include "nserver.h"
|
||||
|
||||
/***************************** Necessary Globals ****************************/
|
||||
|
||||
IPair *pSICSOptions = NULL;
|
||||
pServer pServ = NULL;
|
||||
|
||||
/* ========================= Less dreadful file statics =================== */
|
||||
|
||||
#define DEFAULTINIFILE "servo.tcl"
|
||||
|
||||
/*---------------------------------------------------------------------------
|
||||
The Servers Main program. May take one argument: the name of an
|
||||
initialisation file
|
||||
*/
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
int iRet;
|
||||
|
||||
/* initialise, will die on you if problems */
|
||||
if(argc >= 2)
|
||||
{
|
||||
iRet = InitServer(argv[1],&pServ);
|
||||
}
|
||||
else
|
||||
{
|
||||
iRet = InitServer(NULL,&pServ);
|
||||
}
|
||||
if(!iRet)
|
||||
{
|
||||
printf("Unrecoverable error on server startup, exiting.........");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
|
||||
RunServer(pServ);
|
||||
|
||||
StopServer(pServ);
|
||||
pServ = NULL;
|
||||
exit(0);
|
||||
}
|
||||
/*--------------------------------------------------------------------------*/
|
||||
SicsInterp *GetInterpreter(void)
|
||||
{
|
||||
return pServ->pSics;
|
||||
}
|
||||
/*--------------------------------------------------------------------------*/
|
||||
pExeList GetExecutor(void)
|
||||
{
|
||||
return pServ->pExecutor;
|
||||
}
|
||||
/*------------------------------------------------------------------------*/
|
||||
void StopExit(void)
|
||||
{
|
||||
if(pServ)
|
||||
{
|
||||
StopServer(pServ);
|
||||
}
|
||||
}
|
||||
/*-------------------------------------------------------------------------*/
|
||||
pTaskMan GetTasker(void)
|
||||
{
|
||||
return pServ->pTasker;
|
||||
}
|
82
Scommon.h
Normal file
82
Scommon.h
Normal file
@ -0,0 +1,82 @@
|
||||
/*-------------------------------------------------------------------------
|
||||
|
||||
Some common types and functions for SICS
|
||||
|
||||
|
||||
Mark Koennecke, October 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.
|
||||
----------------------------------------------------------------------------*/
|
||||
#ifndef SICSCOMMON
|
||||
#define SICSCOMMON
|
||||
|
||||
/* this enum defines the output types in SICS */
|
||||
typedef enum {
|
||||
eInternal,
|
||||
eCommand,
|
||||
eHWError,
|
||||
eInError,
|
||||
eStatus,
|
||||
eValue,
|
||||
eWarning,
|
||||
eError
|
||||
} OutCode;
|
||||
|
||||
#include "interrupt.h"
|
||||
|
||||
/* define some user rights codes */
|
||||
#define usInternal 0
|
||||
#define usMugger 1
|
||||
#define usUser 2
|
||||
#define usSpy 3
|
||||
|
||||
/* status and error codes */
|
||||
#define OKOK 1
|
||||
#define HWIdle 2
|
||||
#define HWBusy 3
|
||||
#define HWFault 4
|
||||
#define HWPosFault 5
|
||||
#define HWCrash 6
|
||||
#define NOMEMORY 7
|
||||
#define HWNoBeam 8
|
||||
#define HWPause 9
|
||||
#define HWWarn 10
|
||||
#define HWRedo 11
|
||||
|
||||
/*
|
||||
Sics uses some server options for some server configuration parameters.
|
||||
These options are held in the global variable pSICSOptions.
|
||||
*/
|
||||
#include "ifile.h"
|
||||
extern IPair *pSICSOptions;
|
||||
|
||||
#endif
|
||||
|
16
access.c
Normal file
16
access.c
Normal file
@ -0,0 +1,16 @@
|
||||
/* ------------------------------------------------------------------------
|
||||
The Accesscode names for SICS
|
||||
|
||||
Mark Koennecke, November 1996
|
||||
----------------------------------------------------------------------------*/
|
||||
#ifndef PCODE
|
||||
#define PCODE
|
||||
|
||||
static char *aCode[] = {
|
||||
"internal",
|
||||
"mugger",
|
||||
"user",
|
||||
"spy",
|
||||
NULL };
|
||||
static int iCodes = 4;
|
||||
#endif
|
214
alias.c
Normal file
214
alias.c
Normal file
@ -0,0 +1,214 @@
|
||||
/*-----------------------------------------------------------------------
|
||||
|
||||
A L I A S
|
||||
Copyright:
|
||||
|
||||
Labor fuer Neutronenstreuung
|
||||
Paul Scherrer Institut
|
||||
CH-5423 Villigen-PSI
|
||||
|
||||
First Version: 1998, Mark Koennecke
|
||||
updated: November 1999, Mark Koennecke
|
||||
|
||||
|
||||
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 <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <tcl.h>
|
||||
#include <assert.h>
|
||||
#include "fortify.h"
|
||||
#include "sics.h"
|
||||
#include "splitter.h"
|
||||
#include "alias.h"
|
||||
|
||||
/*
|
||||
Usage: SicsAlias object newname
|
||||
*/
|
||||
|
||||
int SicsAlias(SConnection *pCon, SicsInterp *pSics, void *pData,
|
||||
int argc, char *argv[])
|
||||
{
|
||||
CommandList *pCom = NULL;
|
||||
char pBueffel[256];
|
||||
int iRet;
|
||||
|
||||
if(!SCMatchRights(pCon,usMugger))
|
||||
{
|
||||
SCWrite(pCon,"ERROR: aliasing only allowed to Managers",
|
||||
eError);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if(argc < 3)
|
||||
{
|
||||
SCWrite(pCon,"ERROR: insufficient number of arguments to SicsAlias",
|
||||
eError);
|
||||
return 0;
|
||||
}
|
||||
|
||||
argtolower(argc,argv);
|
||||
/* first parameter should be an registered SICS object */
|
||||
pCom = FindCommand(pSics,argv[1]);
|
||||
if(!pCom)
|
||||
{
|
||||
sprintf(pBueffel,"ERROR: cannot find %s, no alias created",argv[1]);
|
||||
SCWrite(pCon,pBueffel,eError);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* alright: create the alias */
|
||||
iRet = AddCommand(pSics,argv[2],pCom->OFunc,NULL,pCom->pData);
|
||||
if(!iRet)
|
||||
{
|
||||
sprintf(pBueffel,"ERROR: duplicate command %s not created",argv[2]);
|
||||
SCWrite(pCon,pBueffel,eError);
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
/*--------------------------------------------------------------------
|
||||
Make Alias: a command which installs a general alias into SICS.
|
||||
*/
|
||||
|
||||
typedef struct {
|
||||
pObjectDescriptor pDes;
|
||||
char *pCommand;
|
||||
}Alias, *pAlias;
|
||||
/*----------------------------------------------------------------------*/
|
||||
static void FreeAlias(void *pData)
|
||||
{
|
||||
pAlias self = (pAlias)pData;
|
||||
if(!self)
|
||||
return;
|
||||
|
||||
if(self->pDes)
|
||||
DeleteDescriptor(self->pDes);
|
||||
|
||||
if(self->pCommand)
|
||||
free(self->pCommand);
|
||||
|
||||
free(self);
|
||||
}
|
||||
/*----------------------------------------------------------------------
|
||||
In order to make alias most general alias tries to find the interfaces
|
||||
defined by the object corresponding to the first word in the command.
|
||||
Note: does not work, the object pointer with which a interface function
|
||||
will be called refers to the alias and not the proper thing: core dump!
|
||||
Therefore disabled!
|
||||
*/
|
||||
static void *AliasInterface(void *pData, int iID)
|
||||
{
|
||||
CommandList *pCom = NULL;
|
||||
pDummy pDum = NULL;
|
||||
char *pPtr = NULL;
|
||||
pAlias self = (pAlias)pData;
|
||||
|
||||
assert(self);
|
||||
pPtr = strtok(self->pCommand," \t\n");
|
||||
pCom = FindCommand(pServ->pSics,pPtr);
|
||||
if(!pCom)
|
||||
return NULL;
|
||||
|
||||
pDum = (pDummy)pCom->pData;
|
||||
if(!pDum)
|
||||
return NULL;
|
||||
|
||||
return pDum->pDescriptor->GetInterface(pDum,iID);
|
||||
}
|
||||
/*-----------------------------------------------------------------------*/
|
||||
static int AliasAction(SConnection *pCon, SicsInterp *pSics,
|
||||
void *pData, int argc, char *argv[])
|
||||
{
|
||||
pAlias self = NULL;
|
||||
int status;
|
||||
char pLine[512];
|
||||
char *pPtr;
|
||||
Tcl_DString command;
|
||||
|
||||
self = (pAlias)pData;
|
||||
assert(self);
|
||||
|
||||
/*
|
||||
build command by appending the alias command and any possible
|
||||
arguments given.
|
||||
*/
|
||||
Tcl_DStringInit(&command);
|
||||
Tcl_DStringAppend(&command, self->pCommand,-1);
|
||||
Tcl_DStringAppend(&command," ",-1);
|
||||
Arg2Text(argc-1,&argv[1],pLine,511);
|
||||
Tcl_DStringAppend(&command,pLine,-1);
|
||||
|
||||
/* execute the command on the current connection */
|
||||
status = SCInvoke(pCon,pSics,Tcl_DStringValue(&command));
|
||||
|
||||
/* finish */
|
||||
Tcl_DStringFree(&command);
|
||||
return status;
|
||||
}
|
||||
/*-----------------------------------------------------------------------*/
|
||||
int MakeAlias(SConnection *pCon, SicsInterp *pSics, void *pData,
|
||||
int argc, char *argv[])
|
||||
{
|
||||
char pBueffel[512];
|
||||
int iRet;
|
||||
pAlias pNew = NULL;
|
||||
|
||||
if(argc < 3)
|
||||
{
|
||||
SCWrite(pCon,"ERROR: insufficient number of arguments to alias",
|
||||
eError);
|
||||
return 0;
|
||||
}
|
||||
|
||||
Arg2Text(argc-2,&argv[2],pBueffel,511);
|
||||
|
||||
/* create data structure */
|
||||
pNew = (pAlias)malloc(sizeof(Alias));
|
||||
if(!pNew)
|
||||
{
|
||||
SCWrite(pCon,"ERROR: out of memory while creating alias",eError);
|
||||
return 0;
|
||||
}
|
||||
pNew->pDes = CreateDescriptor("Alias");
|
||||
pNew->pCommand = strdup(pBueffel);
|
||||
if( !pNew->pDes || !pNew->pCommand)
|
||||
{
|
||||
SCWrite(pCon,"ERROR: out of memory while creating alias",eError);
|
||||
return 0;
|
||||
}
|
||||
|
||||
iRet = AddCommand(pSics,
|
||||
argv[1],
|
||||
AliasAction,
|
||||
FreeAlias,
|
||||
pNew);
|
||||
if(!iRet)
|
||||
{
|
||||
FreeAlias(pNew);
|
||||
SCWrite(pCon,"ERROR: duplicate object name NOT created",eError);
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
20
alias.h
Normal file
20
alias.h
Normal file
@ -0,0 +1,20 @@
|
||||
/*------------------------------------------------------------------------
|
||||
A L I A S
|
||||
|
||||
Implementation of the alias command. This is a configuration command
|
||||
which allows additional names "aliases" for an existing object.
|
||||
|
||||
Mark Koennecke, March 1997
|
||||
|
||||
copyright: see implementation file
|
||||
|
||||
-------------------------------------------------------------------------*/
|
||||
#ifndef SICSALIAS
|
||||
#define SICSALIAS
|
||||
|
||||
int SicsAlias(SConnection *pCon, SicsInterp *pSics, void *pData,
|
||||
int argc, char *argv[]);
|
||||
int MakeAlias(SConnection *pCon, SicsInterp *pSics, void *pData,
|
||||
int argc, char *argv[]);
|
||||
#endif
|
||||
|
245
amor.dic
Normal file
245
amor.dic
Normal file
@ -0,0 +1,245 @@
|
||||
##NXDICT-1.0
|
||||
#----------------------------------------------------------------------------
|
||||
# NeXus dictionary file for the SINQ instrument AMOR
|
||||
#
|
||||
# DO NOT EDIT WHEN YOU DO NOT KNOW WHAT YOU ARE DOING!
|
||||
# This file determines the placement of data items in the AMOR NeXus
|
||||
# data file. Your data may not be readable if this file is messed up.
|
||||
#
|
||||
# Mark Koennecke, September 1999
|
||||
#----------------------------------------------------------------------------
|
||||
# AMOR may have variable time binning. In order
|
||||
# to cope with that, we use NXDICT's text replacement feature and define
|
||||
# these things
|
||||
timebin=512
|
||||
detxsize=255
|
||||
detysize=128
|
||||
scanlength = 10
|
||||
chunk =
|
||||
#---------- NXentry level
|
||||
etitle=/entry1,NXentry/SDS title -type DFNT_CHAR -rank 1 -dim {132}
|
||||
estart=/entry1,NXentry/SDS start_time -type DFNT_CHAR -rank 1 -dim {132}
|
||||
eend=/entry1,NXentry/SDS end_time -type DFNT_CHAR -rank 1 -dim {132}
|
||||
#----------------- NXinstrument
|
||||
iname=/entry1,NXentry/reflectometer,NXinstrument/SDS name -type DFNT_CHAR \
|
||||
-rank 1 -dim {132}
|
||||
#----------------- NXsource
|
||||
sname=/entry1,NXentry/reflectometer,NXinstrument/SINQ,NXsource/SDS name \
|
||||
-type DFNT_CHAR -rank 1 -dim {132}
|
||||
stype=/entry1,NXentry/reflectometer,NXinstrument/SINQ,NXsource/SDS type \
|
||||
-type DFNT_CHAR -rank 1 -dim {132}
|
||||
#----------------- Chopper
|
||||
cname=/entry1,NXentry/reflectometer,NXinstrument/chopper,NXchopper/SDS name \
|
||||
-type DFNT_CHAR -rank 1 -dim {132}
|
||||
crot=/entry1,NXentry/reflectometer,NXinstrument/chopper,NXchopper/SDS \
|
||||
rotation_speed -attr {units,rpm}
|
||||
#---------------- frame overlap mirror
|
||||
fomname=/entry1,NXentry/reflectometer,NXinstrument/frame_overlap_mirror,NXfilter/SDS name \
|
||||
-type DFNT_CHAR -rank 1 -dim {132}
|
||||
fomh=/entry1,NXentry/reflectometer,NXinstrument/frame_overlap_mirror,NXfilter/SDS \
|
||||
omega_height -attr {units,mm}
|
||||
fomom=/entry1,NXentry/reflectometer,NXinstrument/frame_overlap_mirror,NXfilter/SDS \
|
||||
omega -attr {units,degree}
|
||||
fodist=/entry1,NXentry/reflectometer,NXinstrument/frame_overlap_mirror,NXfilter/SDS \
|
||||
distance -attr {units,mm}
|
||||
#-------------- first slit
|
||||
d1l=/entry1,NXentry/reflectometer,NXinstrument/diaphragm1,NXfilter/SDS left \
|
||||
-attr {units,mm}
|
||||
d1r=/entry1,NXentry/reflectometer,NXinstrument/diaphragm1,NXfilter/SDS right \
|
||||
-attr {units,mm}
|
||||
d1t=/entry1,NXentry/reflectometer,NXinstrument/diaphragm1,NXfilter/SDS top \
|
||||
-attr {units,mm}
|
||||
d1b=/entry1,NXentry/reflectometer,NXinstrument/diaphragm1,NXfilter/SDS bottom \
|
||||
-attr {units,mm}
|
||||
d1dist=/entry1,NXentry/reflectometer,NXinstrument/diaphragm1,NXfilter/SDS distance \
|
||||
-attr {units,mm}
|
||||
#---------- polarizing mirror
|
||||
polname=/entry1,NXentry/reflectometer,NXinstrument/polarizer,NXfilter/SDS name \
|
||||
-type DFNT_CHAR -rank 1 -dim {132}
|
||||
polz=/entry1,NXentry/reflectometer,NXinstrument/polarizer,NXfilter/SDS height \
|
||||
-attr {units,mm}
|
||||
polzom=/entry1,NXentry/reflectometer,NXinstrument/polarizer,NXfilter/SDS omega_height \
|
||||
-attr {units,mm}
|
||||
polom=/entry1,NXentry/reflectometer,NXinstrument/polarizer,NXfilter/SDS omega \
|
||||
-attr {units,degree}
|
||||
poly=/entry1,NXentry/reflectometer,NXinstrument/polarizer,NXfilter/SDS y_position \
|
||||
-attr {units,mm}
|
||||
poldist=/entry1,NXentry/reflectometer,NXinstrument/polarizer,NXfilter/SDS distance \
|
||||
-attr {units,mm}
|
||||
#-------------- second slit
|
||||
d2l=/entry1,NXentry/reflectometer,NXinstrument/diaphragm2,NXfilter/SDS left \
|
||||
-attr {units,mm}
|
||||
d2r=/entry1,NXentry/reflectometer,NXinstrument/diaphragm2,NXfilter/SDS right \
|
||||
-attr {units,mm}
|
||||
d2t=/entry1,NXentry/reflectometer,NXinstrument/diaphragm2,NXfilter/SDS top \
|
||||
-attr {units,mm}
|
||||
d2b=/entry1,NXentry/reflectometer,NXinstrument/diaphragm2,NXfilter/SDS bottom \
|
||||
-attr {units,mm}
|
||||
d2dist=/entry1,NXentry/reflectometer,NXinstrument/diaphragm2,NXfilter/SDS distance \
|
||||
-attr {units,mm}
|
||||
#-------------- third slit
|
||||
d3l=/entry1,NXentry/reflectometer,NXinstrument/diaphragm3,NXfilter/SDS left \
|
||||
-attr {units,mm}
|
||||
d3r=/entry1,NXentry/reflectometer,NXinstrument/diaphragm3,NXfilter/SDS right \
|
||||
-attr {units,mm}
|
||||
d3t=/entry1,NXentry/reflectometer,NXinstrument/diaphragm3,NXfilter/SDS top \
|
||||
-attr {units,mm}
|
||||
d3b=/entry1,NXentry/reflectometer,NXinstrument/diaphragm3,NXfilter/SDS bottom \
|
||||
-attr {units,mm}
|
||||
d3dist=/entry1,NXentry/reflectometer,NXinstrument/diaphragm3,NXfilter/SDS distance \
|
||||
-attr {units,mm}
|
||||
#---------------- sample table
|
||||
saname=/entry1,NXentry/sample,NXsample/SDS name \
|
||||
-type DFNT_CHAR -rank 1 -dim {132}
|
||||
baseheight=/entry1,NXentry/sample,NXsample/SDS base_height \
|
||||
-attr {units,mm}
|
||||
somheight=/entry1,NXentry/sample,NXsample/SDS omega_height \
|
||||
-attr {units,mm}
|
||||
schi=/entry1,NXentry/sample,NXsample/SDS chi \
|
||||
-attr {units,degree}
|
||||
somega=/entry1,NXentry/sample,NXsample/SDS omega \
|
||||
-attr {units,degree}
|
||||
stheight=/entry1,NXentry/sample,NXsample/SDS table_height \
|
||||
-attr {units,mm}
|
||||
stdist=/entry1,NXentry/sample,NXsample/SDS distance \
|
||||
-attr {units,mm}
|
||||
#------------ fourth slit
|
||||
d4l=/entry1,NXentry/reflectometer,NXinstrument/diaphragm4,NXfilter/SDS left \
|
||||
-attr {units,mm}
|
||||
d4r=/entry1,NXentry/reflectometer,NXinstrument/diaphragm4,NXfilter/SDS right \
|
||||
-attr {units,mm}
|
||||
d4t=/entry1,NXentry/reflectometer,NXinstrument/diaphragm4,NXfilter/SDS top \
|
||||
-attr {units,mm}
|
||||
d4b=/entry1,NXentry/reflectometer,NXinstrument/diaphragm4,NXfilter/SDS bottom \
|
||||
-attr {units,mm}
|
||||
d4dist=/entry1,NXentry/reflectometer,NXinstrument/diaphragm4,NXfilter/SDS \
|
||||
distance_to_sample -attr {units,mm}
|
||||
d4base =/entry1,NXentry/reflectometer,NXinstrument/diaphragm4,NXfilter/SDS \
|
||||
base_height -attr {units,mm}
|
||||
#------------ analyzer
|
||||
anname=/entry1,NXentry/reflectometer,NXinstrument/polarizer,NXfilter/SDS name \
|
||||
-type DFNT_CHAR -rank 1 -dim {132}
|
||||
anoz=/entry1,NXentry/reflectometer,NXinstrument/analyzer,NXfilter/SDS omega_height \
|
||||
-attr {units,mm}
|
||||
abase=/entry1,NXentry/reflectometer,NXinstrument/analyzer,NXfilter/SDS base_height \
|
||||
-attr {units,mm}
|
||||
adis=/entry1,NXentry/reflectometer,NXinstrument/analyzer,NXfilter/SDS \
|
||||
distance_to_sample -attr {units,mm}
|
||||
anom=/entry1,NXentry/reflectometer,NXinstrument/analyzer,NXfilter/SDS omega \
|
||||
-attr {units,degree}
|
||||
antz=/entry1,NXentry/reflectometer,NXinstrument/analyzer,NXfilter/SDS height \
|
||||
-attr {units,mm}
|
||||
andist=/entry1,NXentry/reflectometer,NXinstrument/analyzer,NXfilter/SDS distance \
|
||||
-attr {units,mm}
|
||||
#--------------- fifth slit!!
|
||||
d5l=/entry1,NXentry/reflectometer,NXinstrument/diaphragm5,NXfilter/SDS left \
|
||||
-attr {units,mm}
|
||||
d5r=/entry1,NXentry/reflectometer,NXinstrument/diaphragm5,NXfilter/SDS right \
|
||||
-attr {units,mm}
|
||||
d5t=/entry1,NXentry/reflectometer,NXinstrument/diaphragm5,NXfilter/SDS top \
|
||||
-attr {units,mm}
|
||||
d5b=/entry1,NXentry/reflectometer,NXinstrument/diaphragm5,NXfilter/SDS bottom \
|
||||
-attr {units,mm}
|
||||
d5dist=/entry1,NXentry/reflectometer,NXinstrument/diaphragm5,NXfilter/SDS \
|
||||
distance_to_sample -attr {units,mm}
|
||||
d5base =/entry1,NXentry/reflectometer,NXinstrument/diaphragm5,NXfilter/SDS \
|
||||
base_height -attr {units,mm}
|
||||
#---------- count control
|
||||
cnmode=/entry1,NXentry/reflectometer,NXinstrument/counter,NXmonitor/SDS count_mode \
|
||||
-type DFNT_CHAR -rank 1 -dim {30}
|
||||
cnpreset=/entry1,NXentry/reflectometer,NXinstrument/counter,NXmonitor/SDS preset \
|
||||
-attr {units,countsOrseconds}
|
||||
cntime=/entry1,NXentry/reflectometer,NXinstrument/counter,NXmonitor/SDS time \
|
||||
-attr {units,seconds}
|
||||
cnmon1=/entry1,NXentry/reflectometer,NXinstrument/counter,NXmonitor/SDS monitor1 \
|
||||
-type DFNT_INT32 -attr {units,counts}
|
||||
cnmon2=/entry1,NXentry/reflectometer,NXinstrument/counter,NXmonitor/SDS monitor2 \
|
||||
-type DFNT_INT32 -attr {units,counts}
|
||||
#-------------- detector-TOF mode
|
||||
dettype=/entry1,NXentry/reflectometer,NXinstrument/TOF,NXdetector/SDS type \
|
||||
-type DFNT_CHAR -rank 1 -dim {132}
|
||||
dety=/entry1,NXentry/reflectometer,NXinstrument/TOF,NXdetector/SDS y_detector \
|
||||
-type DFNT_FLOAT32 -rank 1 -dim {$(detysize)} -attr {axis,1} \
|
||||
-attr {units,mm}
|
||||
detxx=/entry1,NXentry/reflectometer,NXinstrument/TOF,NXdetector/SDS x_detector \
|
||||
-type DFNT_FLOAT32 -rank 1 -dim {$(detxsize)} -attr {axis,2} \
|
||||
-attr {units,mm}
|
||||
detz=/entry1,NXentry/reflectometer,NXinstrument/TOF,NXdetector/SDS z \
|
||||
-type DFNT_FLOAT32 -rank 1 -dim {$(detxsize)} -attr {axis,2} \
|
||||
-attr {units,mm}
|
||||
detx=/entry1,NXentry/reflectometer,NXinstrument/TOF,NXdetector/SDS x \
|
||||
-type DFNT_FLOAT32 -attr {units,mm}
|
||||
detom=/entry1,NXentry/reflectometer,NXinstrument/TOF,NXdetector/SDS omega \
|
||||
-type DFNT_FLOAT32 -attr {units,degree}
|
||||
detheight=/entry1,NXentry/reflectometer,NXinstrument/TOF,NXdetector/SDS height \
|
||||
-type DFNT_FLOAT32 -attr {units,mm}
|
||||
detdist=/entry1,NXentry/reflectometer,NXinstrument/TOF,NXdetector/SDS \
|
||||
distance_to_sample -type DFNT_FLOAT32 -attr {units,mm}
|
||||
detbase=/entry1,NXentry/reflectometer,NXinstrument/TOF,NXdetector/SDS \
|
||||
base_height -type DFNT_FLOAT32 -attr {units,mm}
|
||||
dettime=/entry1,NXentry/reflectometer,NXinstrument/TOF,NXdetector/SDS time_binning \
|
||||
-type DFNT_FLOAT32 -rank 1 -dim {$(timebin)} -attr {axis,3} \
|
||||
-attr {units,ms}
|
||||
spinup=/entry1,NXentry/reflectometer,NXinstrument/TOF,NXdetector/SDS spinup \
|
||||
-type DFNT_INT32 -rank 3 -dim {$(detxsize),$(detysize),$(timebin)} \
|
||||
-LZW $(chunk) -attr {signal,1}
|
||||
#spinup=/entry1,NXentry/reflectometer,NXinstrument/TOF,NXdetector/SDS spinup \
|
||||
# -type DFNT_INT32 -rank 3 -dim {$(detxsize),$(detysize),$(timebin)} \
|
||||
# $(chunk) -attr {signal,1}
|
||||
detchunk=/entry1,NXentry/reflectometer,NXinstrument/TOF,NXdetector/SDS \
|
||||
chunksize -type DFNT_INT32 -rank 1 -dim {3}
|
||||
spinup2d=/entry1,NXentry/reflectometer,NXinstrument/TOF,NXdetector/SDS spinup \
|
||||
-type DFNT_INT32 -rank 2 -dim {$(detxsize),$(detysize)} \
|
||||
-LZW $(chunk) -attr {signal,1}
|
||||
spindown=/entry1,NXentry/reflectometer,NXinstrument/TOF,NXdetector/SDS spindown \
|
||||
-type DFNT_INT32 -rank 3 -dim {$(detxsize),$(detysize),$(timebin)} \
|
||||
-LZW -attr {signal,1}
|
||||
#------------ single detectors TOF -------------------------------------
|
||||
singleup=/entry1,NXentry/reflectometer,NXinstrument/single,NXdetector/SDS \
|
||||
spinup -type DFNT_INT32 -rank 2 -dim {2, $(timebin)} -LZW \
|
||||
-attr {signal,1}
|
||||
singledown=/entry1,NXentry/reflectometer,NXinstrument/single,NXdetector/SDS \
|
||||
spinup -type DFNT_INT32 -rank 2 -dim {2, $(timebin)} -LZW \
|
||||
-attr {signal,1}
|
||||
singletime=/entry1,NXentry/reflectometer,NXinstrument/single,NXdetector/SDS \
|
||||
time_binning -type DFNT_FLOAT32 -rank 1 -dim {$(timebin)} \
|
||||
-attr {axis,2}
|
||||
singletofmon=/entry1,NXentry/reflectometer,NXinstrument/single,NXdetector/SDS \
|
||||
tof_monitor -type DFNT_INT32 -rank 1 -dim {$(timebin)}
|
||||
#------------ detector: scan mode
|
||||
scanroot=/entry1,NXentry/reflectometer,NXinstrument/scan,NXdetector/SDS
|
||||
sdetx=/entry1,NXentry/reflectometer,NXinstrument/scan,NXdetector/SDS x \
|
||||
-type DFNT_FLOAT32 -attr {units,mm}
|
||||
sdetom=/entry1,NXentry/reflectometer,NXinstrument/scan,NXdetector/SDS omega \
|
||||
-type DFNT_FLOAT32 -attr {units,degree}
|
||||
sdetheight=/entry1,NXentry/reflectometer,NXinstrument/scan,NXdetector/SDS height \
|
||||
-type DFNT_FLOAT32 -attr {units,mm}
|
||||
spinupup=/entry1,NXentry/reflectometer,NXinstrument/scan,NXdetector/SDS spinup_upper \
|
||||
-type DFNT_INT32 -rank 1 -dim {$(scanlength)} -attr {signal,1}
|
||||
spindownup=/entry1,NXentry/reflectometer,NXinstrument/scan,NXdetector/SDS \
|
||||
spindown_upper \
|
||||
-type DFNT_INT32 -rank 1 -dim {$(scanlength)} -attr {signal,2}
|
||||
spinuplo=/entry1,NXentry/reflectometer,NXinstrument/scan,NXdetector/SDS spinup_lower \
|
||||
-type DFNT_INT32 -rank 1 -dim {$(scanlength)} -attr {signal,3}
|
||||
spindownlo=/entry1,NXentry/reflectometer,NXinstrument/scan,NXdetector/SDS \
|
||||
spindown_lower \
|
||||
-type DFNT_INT32 -rank 1 -dim {$(scanlength)} -attr {signal,4}
|
||||
somega=/entry1,NXentry/reflectometer,NXinstrument/scan,NXdetector/SDS \
|
||||
omega -attr {units,degree} \
|
||||
-type DFNT_FLOAT32 -rank 1 -dim {$(scanlength)} -attr {axis,1}
|
||||
smonitor1=/entry1,NXentry/reflectometer,NXinstrument/scan,NXdetector/SDS \
|
||||
monitor1 \
|
||||
-type DFNT_INT32 -rank 1 -dim {$(scanlength)}
|
||||
smonitor2=/entry1,NXentry/reflectometer,NXinstrument/scan,NXdetector/SDS \
|
||||
monitor2 \
|
||||
-type DFNT_INT32 -rank 1 -dim {$(scanlength)}
|
||||
stime=/entry1,NXentry/reflectometer,NXinstrument/scan,NXdetector/SDS \
|
||||
time \
|
||||
-type DFNT_FLOAT32 -rank 1 -dim {$(scanlength)} -attr {units,s}
|
||||
sdetdist=/entry1,NXentry/reflectometer,NXinstrument/scan,NXdetector/SDS distance \
|
||||
-type DFNT_FLOAT32 -attr {units,mm}
|
||||
#------------------- data vGroup
|
||||
dana=/entry1,NXentry/TOF,NXdata/NXVGROUP
|
||||
singledana=/entry1,NXentry/single,NXdata/NXVGROUP
|
||||
sdana=/entry1,NXentry/scan,NXdata/NXVGROUP
|
||||
|
996
amor2t.c
Normal file
996
amor2t.c
Normal file
@ -0,0 +1,996 @@
|
||||
/*---------------------------------------------------------------------------
|
||||
A M O R 2 T
|
||||
|
||||
A class for controlling the two theta movement of the reflectometer
|
||||
AMOR at SINQ. It is not clear if this class may be useful for other
|
||||
reflectometers, too. At AMOR the two theta movement of the detector is
|
||||
realized by translating the detector along x and z. Also it can be
|
||||
tilted in omega. Furthermore the height of two diaphragms has to be
|
||||
adjusted when moving two theta as well. In polarizing mode the analyzer
|
||||
mirror has to be moved as well.
|
||||
|
||||
copyright: see copyright.h
|
||||
|
||||
Mark Koennecke, September 1999
|
||||
|
||||
Bugs fixed, analyzer included for A2T. Then there is a second thing:
|
||||
aoz2t which allows to scan the analyzer in two-theta during alignment
|
||||
of the instrument. As all the parameters are already held in the a2t
|
||||
structures this extra was added into this module.
|
||||
|
||||
Mark Koennecke, May-June 2000
|
||||
---------------------------------------------------------------------------*/
|
||||
#include <stdlib.h>
|
||||
#include <assert.h>
|
||||
#include <math.h>
|
||||
#include "fortify.h"
|
||||
#include <tcl.h>
|
||||
#include "sics.h"
|
||||
#include "motor.h"
|
||||
#include "obpar.h"
|
||||
|
||||
#define DEBUG 1
|
||||
|
||||
#define MAXMOT 13
|
||||
#define MAXPAR 13
|
||||
|
||||
#include "amor2t.i"
|
||||
#include "amor2t.h"
|
||||
|
||||
/*
|
||||
Defines for accessing various motors and variables. Definition of motor: see
|
||||
annotated AMOR drawing.
|
||||
*/
|
||||
|
||||
/* monochromator omega */
|
||||
#define MOTMOM 0
|
||||
/* sample omega */
|
||||
#define MOTSOM 1
|
||||
/* detector height movement */
|
||||
#define MOTCOZ 2
|
||||
/* detector movement along main axis */
|
||||
#define MOTCOX 3
|
||||
/* sample holder height movement */
|
||||
#define MOTSTZ 4
|
||||
/* whole sample table height movement */
|
||||
#define MOTSOZ 5
|
||||
/* lift for diaphragm 4*/
|
||||
#define MOTD4B 6
|
||||
/* lift for diaphragm 5 */
|
||||
#define MOTD5B 7
|
||||
/* detector omega movement */
|
||||
#define MOTCOM 8
|
||||
/* lift for analyzer */
|
||||
#define MOTAOZ 9
|
||||
/* analyzer omega */
|
||||
#define MOTAOM 10
|
||||
/* detector 2 movement */
|
||||
#define MOTC3Z 11
|
||||
|
||||
|
||||
/*======================================================================
|
||||
The core of it all: The calculation of the settings for the various
|
||||
motors.
|
||||
========================================================================*/
|
||||
static int CalculateAMORE(pAmor2T self, SConnection *pCon, float fNew)
|
||||
{
|
||||
float fMOM, fSOM, fSTZ, fSOZ, fAOM, fAOZ, fC3Z, fconstAOM;
|
||||
double fAngle, fX, fZ, fZ2, fBase, fPIR;
|
||||
float fCOZ, fCOX, fCOM;
|
||||
int iRet;
|
||||
#ifdef DEBUG
|
||||
char pBueffel[132];
|
||||
#endif
|
||||
|
||||
/* get the necessary angles first */
|
||||
iRet = MotorGetSoftPosition(self->aEngine[MOTMOM],pCon,&fMOM);
|
||||
if(iRet != 1)
|
||||
{
|
||||
return iRet;
|
||||
}
|
||||
iRet = MotorGetSoftPosition(self->aEngine[MOTSOM],pCon,&fSOM);
|
||||
if(iRet != 1)
|
||||
{
|
||||
return iRet;
|
||||
}
|
||||
iRet = MotorGetSoftPosition(self->aEngine[MOTSTZ],pCon,&fSTZ);
|
||||
if(iRet != 1)
|
||||
{
|
||||
return iRet;
|
||||
}
|
||||
iRet = MotorGetSoftPosition(self->aEngine[MOTSOZ],pCon,&fSOZ);
|
||||
if(iRet != 1)
|
||||
{
|
||||
return iRet;
|
||||
}
|
||||
|
||||
/* calculate base height of sample table */
|
||||
fBase = fSOZ + ObVal(self->aParameter,PARDH);
|
||||
fPIR = 180. / 3.1415926;
|
||||
|
||||
/* calculation for detector */
|
||||
fAngle = fNew - 2*fMOM;
|
||||
if(fAngle < 0)
|
||||
{
|
||||
fAngle = fAngle + 360.;
|
||||
}
|
||||
fAngle /= fPIR;
|
||||
fX = ObVal(self->aParameter,PARDS)*cos(fAngle);
|
||||
fZ = ObVal(self->aParameter,PARDS)*sin(fAngle);
|
||||
self->toStart[0].pMot = self->aEngine[MOTCOX];
|
||||
strcpy(self->toStart[0].pName,self->aEngine[MOTCOX]->name);
|
||||
self->toStart[0].fTarget = fX - ObVal(self->aParameter,PARDS);
|
||||
self->toStart[1].pMot = self->aEngine[MOTCOZ];
|
||||
strcpy(self->toStart[1].pName,self->aEngine[MOTCOZ]->name);
|
||||
self->toStart[1].fTarget = fZ + fBase -
|
||||
ObVal(self->aParameter,PARDDH);
|
||||
self->toStart[2].pMot = self->aEngine[MOTCOM];
|
||||
strcpy(self->toStart[2].pName,self->aEngine[MOTCOM]->name);
|
||||
self->toStart[2].fTarget = fNew - 2*fMOM;
|
||||
self->iStart = 3;
|
||||
|
||||
/* calculation for diaphragm 4 */
|
||||
fZ = ObVal(self->aParameter,PARDD4) * sin(fAngle);
|
||||
self->toStart[3].pMot = self->aEngine[MOTD4B];
|
||||
strcpy(self->toStart[3].pName,self->aEngine[MOTD4B]->name);
|
||||
self->toStart[3].fTarget = fBase + fZ -
|
||||
ObVal(self->aParameter,PARD4H);
|
||||
self->iStart = 4;
|
||||
|
||||
/* calculation for diaphragm 5 */
|
||||
fZ = ObVal(self->aParameter,PARDD5) * sin(fAngle);
|
||||
self->toStart[4].pMot = self->aEngine[MOTD5B];
|
||||
strcpy(self->toStart[4].pName,self->aEngine[MOTD5B]->name);
|
||||
self->toStart[4].fTarget = fBase + fZ -
|
||||
ObVal(self->aParameter,PARD5H);
|
||||
self->iStart = 5;
|
||||
#ifdef DEBUG
|
||||
sprintf(pBueffel,"2T COZ COX COM D4B D5B ");
|
||||
SCWrite(pCon,pBueffel,eValue);
|
||||
sprintf(pBueffel,"%6.2f %6.2f %6.2f %6.2f %6.2f %6.2f",
|
||||
fNew, self->toStart[1].fTarget, self->toStart[0].fTarget,
|
||||
self->toStart[2].fTarget, self->toStart[3].fTarget,
|
||||
self->toStart[4].fTarget);
|
||||
SCWrite(pCon,pBueffel,eValue);
|
||||
#endif
|
||||
|
||||
if(ObVal(self->aParameter,ANAFLAG) > 0)
|
||||
{
|
||||
/* the analyzer height */
|
||||
fZ = ObVal(self->aParameter,PARADIS)*sin(fAngle);
|
||||
fAOZ = fBase + fZ - ObVal(self->aParameter,PARANA);
|
||||
self->toStart[5].pMot = self->aEngine[MOTAOZ];
|
||||
strcpy(self->toStart[5].pName,self->aEngine[MOTAOZ]->name);
|
||||
self->toStart[5].fTarget = fAOZ;
|
||||
self->iStart = 6;
|
||||
|
||||
/* analyzer omega */
|
||||
self->toStart[6].pMot = self->aEngine[MOTAOM];
|
||||
strcpy(self->toStart[6].pName,self->aEngine[MOTAOM]->name);
|
||||
self->toStart[6].fTarget = fNew/2.
|
||||
+ ObVal(self->aParameter,PARAOM);
|
||||
self->iStart = 7;
|
||||
|
||||
/* C3Z */
|
||||
fZ2 = (ObVal(self->aParameter,PARDS) - ObVal(self->aParameter,
|
||||
PARADIS))*sin(fAngle + (fNew/fPIR) );
|
||||
|
||||
self->toStart[7].pMot = self->aEngine[MOTC3Z];
|
||||
strcpy(self->toStart[7].pName,self->aEngine[MOTC3Z]->name);
|
||||
self->toStart[7].fTarget = fBase + fZ + fZ2 -
|
||||
ObVal(self->aParameter,PARDDD) -
|
||||
self->toStart[1].fTarget;
|
||||
self->iStart = 8;
|
||||
#ifdef DEBUG
|
||||
sprintf(pBueffel,"2T AOZ AOM C3Z");
|
||||
SCWrite(pCon,pBueffel,eValue);
|
||||
sprintf(pBueffel,"%6.2f %6.2f %6.2f %6.2f",
|
||||
fNew, self->toStart[5].fTarget, self->toStart[6].fTarget,
|
||||
self->toStart[7].fTarget);
|
||||
SCWrite(pCon,pBueffel,eValue);
|
||||
#endif
|
||||
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
/*=======================================================================
|
||||
Calculations for Analyzer two theta
|
||||
=========================================================================*/
|
||||
static int CalculateANA2T(pAmor2T self, SConnection *pCon, float fNew)
|
||||
{
|
||||
double fBase, fPIR;
|
||||
float fAOZ, fIncident, fSOM, fMOM, fDiffracted, fDistance, fX, fZ;
|
||||
int iRet;
|
||||
#ifdef DEBUG
|
||||
char pBueffel[132];
|
||||
#endif
|
||||
|
||||
/* calculate base height of analyzer table */
|
||||
iRet = MotorGetSoftPosition(self->aEngine[MOTSOZ],pCon,&fAOZ);
|
||||
if(iRet != 1)
|
||||
{
|
||||
return iRet;
|
||||
}
|
||||
fBase = fAOZ + ObVal(self->aParameter,PARANA);
|
||||
fPIR = 180. / 3.1415926;
|
||||
|
||||
/* Calculate the incident angle at the analyzer */
|
||||
iRet = MotorGetSoftPosition(self->aEngine[MOTSOM],pCon,&fSOM);
|
||||
if(iRet != 1)
|
||||
{
|
||||
return iRet;
|
||||
}
|
||||
iRet = MotorGetSoftPosition(self->aEngine[MOTMOM],pCon,&fMOM);
|
||||
if(iRet != 1)
|
||||
{
|
||||
return iRet;
|
||||
}
|
||||
fIncident = fMOM + 2. * fSOM;
|
||||
|
||||
/* calculate the angle of the diffracted beam against the
|
||||
horizon at the analyzer.
|
||||
|
||||
fDiffracted = fIncident - 2. * AOM.
|
||||
|
||||
There is a problem here. We should read AOM in order to get the
|
||||
value. However in the context of an omega - two-theta scan on AOM
|
||||
and ana2t, it is fNew.
|
||||
*/
|
||||
fDiffracted = fIncident - fNew;
|
||||
|
||||
|
||||
/* calculation for detector */
|
||||
fDiffracted /= fPIR;
|
||||
fDistance = ObVal(self->aParameter,PARDS) -
|
||||
ObVal(self->aParameter, PARANA);
|
||||
fX = fDistance*cos(fDiffracted);
|
||||
fZ = fDistance*sin(fDiffracted);
|
||||
self->toStart[0].pMot = self->aEngine[MOTCOX];
|
||||
strcpy(self->toStart[0].pName,self->aEngine[MOTCOX]->name);
|
||||
self->toStart[0].fTarget = fX - fDistance;
|
||||
|
||||
self->toStart[1].pMot = self->aEngine[MOTCOZ];
|
||||
strcpy(self->toStart[1].pName,self->aEngine[MOTCOZ]->name);
|
||||
self->toStart[1].fTarget = fZ + fBase -
|
||||
ObVal(self->aParameter,PARDDH);
|
||||
|
||||
self->toStart[2].pMot = self->aEngine[MOTCOM];
|
||||
strcpy(self->toStart[2].pName,self->aEngine[MOTCOM]->name);
|
||||
self->toStart[2].fTarget = -fDiffracted*fPIR;
|
||||
self->iStart = 3;
|
||||
|
||||
/* calculation for diaphragm 5 */
|
||||
fZ = ObVal(self->aParameter,PARDD5) * sin(fDiffracted);
|
||||
self->toStart[3].pMot = self->aEngine[MOTD5B];
|
||||
strcpy(self->toStart[3].pName,self->aEngine[MOTD5B]->name);
|
||||
self->toStart[3].fTarget = fBase + fZ -
|
||||
ObVal(self->aParameter,PARD5H);
|
||||
self->iStart = 4;
|
||||
|
||||
#ifdef DEBUG
|
||||
sprintf(pBueffel,"2T COX COZ COM D5B ");
|
||||
SCWrite(pCon,pBueffel,eValue);
|
||||
sprintf(pBueffel,"%6.2f %6.2f %6.2f %6.2f %6.2f ",
|
||||
fNew, self->toStart[0].fTarget, self->toStart[1].fTarget,
|
||||
self->toStart[2].fTarget,self->toStart[3].fTarget);
|
||||
SCWrite(pCon,pBueffel,eValue);
|
||||
#endif
|
||||
|
||||
return 1;
|
||||
}
|
||||
/*========================================================================
|
||||
Definition of interface functions.
|
||||
=========================================================================*/
|
||||
static long A2TSetValue(void *pData, SConnection *pCon, float fNew)
|
||||
{
|
||||
int i, iRet;
|
||||
pIDrivable pDriv = NULL;
|
||||
pAmor2T self = (pAmor2T) pData;
|
||||
|
||||
assert(self);
|
||||
|
||||
/* calculation */
|
||||
iRet = CalculateAMORE(self,pCon,fNew);
|
||||
if(iRet != 1)
|
||||
{
|
||||
return iRet;
|
||||
}
|
||||
|
||||
/* start them all */
|
||||
for(i = 0; i < self->iStart; i++)
|
||||
{
|
||||
pDriv = self->toStart[i].pMot->pDescriptor->GetInterface(
|
||||
self->toStart[i].pMot,DRIVEID);
|
||||
if(pDriv != NULL)
|
||||
{
|
||||
iRet = pDriv->SetValue(self->toStart[i].pMot,pCon,
|
||||
self->toStart[i].fTarget);
|
||||
if(iRet != OKOK)
|
||||
{
|
||||
return iRet;
|
||||
}
|
||||
}
|
||||
}
|
||||
return OKOK;
|
||||
}
|
||||
/*--------------------------------------------------------------------*/
|
||||
static long ANA2TSetValue(void *pData, SConnection *pCon, float fNew)
|
||||
{
|
||||
int i, iRet;
|
||||
pIDrivable pDriv = NULL;
|
||||
pAmor2T self = (pAmor2T) pData;
|
||||
|
||||
assert(self);
|
||||
|
||||
/* calculation */
|
||||
iRet = CalculateANA2T(self,pCon,fNew);
|
||||
if(iRet != 1)
|
||||
{
|
||||
return iRet;
|
||||
}
|
||||
|
||||
/* start them all */
|
||||
for(i = 0; i < self->iStart; i++)
|
||||
{
|
||||
pDriv = self->toStart[i].pMot->pDescriptor->GetInterface(
|
||||
self->toStart[i].pMot,DRIVEID);
|
||||
if(pDriv != NULL)
|
||||
{
|
||||
iRet = pDriv->SetValue(self->toStart[i].pMot,pCon,
|
||||
self->toStart[i].fTarget);
|
||||
if(iRet != OKOK)
|
||||
{
|
||||
return iRet;
|
||||
}
|
||||
}
|
||||
}
|
||||
return OKOK;
|
||||
}
|
||||
/*-------------------------------------------------------------------------*/
|
||||
static int A2THalt(void *pData)
|
||||
{
|
||||
int i, iRet;
|
||||
pIDrivable pDriv = NULL;
|
||||
pAmor2T self = (pAmor2T) pData;
|
||||
|
||||
assert(self);
|
||||
|
||||
/* stop them all */
|
||||
for(i = 0; i < self->iStart; i++)
|
||||
{
|
||||
pDriv = self->toStart[i].pMot->pDescriptor->GetInterface(
|
||||
self->toStart[i].pMot,DRIVEID);
|
||||
if(pDriv != NULL)
|
||||
{
|
||||
iRet = pDriv->Halt(self->toStart[i].pMot);
|
||||
}
|
||||
}
|
||||
return OKOK;
|
||||
}
|
||||
/*-----------------------------------------------------------------------*/
|
||||
static int A2TCheck(void *pData, float fNew, char *error, int iErrLen)
|
||||
{
|
||||
int i, iRet;
|
||||
pIDrivable pDriv = NULL;
|
||||
pAmor2T self = (pAmor2T) pData;
|
||||
SConnection *pDumCon = NULL;
|
||||
|
||||
|
||||
assert(self);
|
||||
pDumCon = SCCreateDummyConnection(pServ->pSics);
|
||||
assert(pDumCon);
|
||||
|
||||
/* calculation */
|
||||
iRet = CalculateAMORE(self,pDumCon,fNew);
|
||||
SCDeleteConnection(pDumCon);
|
||||
if(iRet != 1)
|
||||
{
|
||||
return iRet;
|
||||
}
|
||||
|
||||
/* check them all */
|
||||
for(i = 0; i < self->iStart; i++)
|
||||
{
|
||||
pDriv = self->toStart[i].pMot->pDescriptor->GetInterface(
|
||||
self->toStart[i].pMot,DRIVEID);
|
||||
if(pDriv != NULL)
|
||||
{
|
||||
iRet = pDriv->CheckLimits(self->toStart[i].pMot,
|
||||
self->toStart[i].fTarget,
|
||||
error,iErrLen);
|
||||
if(iRet != 1)
|
||||
{
|
||||
return iRet;
|
||||
}
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
/*-------------------------------------------------------------------*/
|
||||
static int ANA2TCheck(void *pData, float fNew, char *error, int iErrLen)
|
||||
{
|
||||
int i, iRet;
|
||||
pIDrivable pDriv = NULL;
|
||||
pAmor2T self = (pAmor2T) pData;
|
||||
SConnection *pDumCon = NULL;
|
||||
|
||||
|
||||
assert(self);
|
||||
pDumCon = SCCreateDummyConnection(pServ->pSics);
|
||||
assert(pDumCon);
|
||||
|
||||
/* calculation */
|
||||
iRet = CalculateANA2T(self,pDumCon,fNew);
|
||||
SCDeleteConnection(pDumCon);
|
||||
if(iRet != 1)
|
||||
{
|
||||
return iRet;
|
||||
}
|
||||
|
||||
/* check them all */
|
||||
for(i = 0; i < self->iStart; i++)
|
||||
{
|
||||
pDriv = self->toStart[i].pMot->pDescriptor->GetInterface(
|
||||
self->toStart[i].pMot,DRIVEID);
|
||||
if(pDriv != NULL)
|
||||
{
|
||||
iRet = pDriv->CheckLimits(self->toStart[i].pMot,
|
||||
self->toStart[i].fTarget,
|
||||
error,iErrLen);
|
||||
if(iRet != 1)
|
||||
{
|
||||
return iRet;
|
||||
}
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
/*------------------------------------------------------------------------*/
|
||||
static int A2TStatus(void *pData, SConnection *pCon)
|
||||
{
|
||||
int i, iRet;
|
||||
pIDrivable pDriv = NULL;
|
||||
pAmor2T self = (pAmor2T) pData;
|
||||
|
||||
assert(self);
|
||||
|
||||
/* check them all */
|
||||
for(i = 0; i < self->iStart; i++)
|
||||
{
|
||||
pDriv = self->toStart[i].pMot->pDescriptor->GetInterface(
|
||||
self->toStart[i].pMot,DRIVEID);
|
||||
if(pDriv != NULL)
|
||||
{
|
||||
iRet = pDriv->CheckStatus(self->toStart[i].pMot,pCon);
|
||||
if( (iRet != OKOK) && (iRet != HWIdle) )
|
||||
{
|
||||
return iRet;
|
||||
}
|
||||
}
|
||||
}
|
||||
return iRet;
|
||||
}
|
||||
/*------------------------------------------------------------------------*/
|
||||
static float A2TGetValue(void *pData, SConnection *pCon)
|
||||
{
|
||||
float fVal, fMOM, fResult;
|
||||
int iRet;
|
||||
pAmor2T self = (pAmor2T) pData;
|
||||
|
||||
assert(self);
|
||||
|
||||
/* get COM */
|
||||
iRet = MotorGetSoftPosition(self->aEngine[MOTCOM], pCon, &fVal);
|
||||
if(!iRet)
|
||||
{
|
||||
return -9999.99;
|
||||
}
|
||||
/* get MOM */
|
||||
iRet = MotorGetSoftPosition(self->aEngine[MOTMOM], pCon, &fMOM);
|
||||
if(!iRet)
|
||||
{
|
||||
return -9999.99;
|
||||
}
|
||||
|
||||
/* retrocalculate 2 theta */
|
||||
fResult = fVal + 2*fMOM;
|
||||
return fResult;
|
||||
}
|
||||
/*------------------------------------------------------------------------*/
|
||||
static float ANA2TGetValue(void *pData, SConnection *pCon)
|
||||
{
|
||||
float fVal, fMOM, fResult;
|
||||
int iRet;
|
||||
pAmor2T self = (pAmor2T) pData;
|
||||
|
||||
assert(self);
|
||||
|
||||
/* get AOM */
|
||||
iRet = MotorGetSoftPosition(self->aEngine[MOTAOM], pCon, &fVal);
|
||||
if(!iRet)
|
||||
{
|
||||
return -9999.99;
|
||||
}
|
||||
|
||||
return 2. * fVal;
|
||||
|
||||
}
|
||||
/*-----------------------------------------------------------------------*/
|
||||
static void *A2TGetInterface(void *pData, int iID)
|
||||
{
|
||||
pAmor2T self = (pAmor2T) pData;
|
||||
|
||||
assert(self);
|
||||
if(iID == DRIVEID)
|
||||
{
|
||||
return self->pDriv;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
/*------------------------------------------------------------------------*/
|
||||
static int A2TSave(void *pData, char *name, FILE *fd)
|
||||
{
|
||||
int i;
|
||||
pAmor2T self = (pAmor2T) pData;
|
||||
|
||||
assert(self);
|
||||
|
||||
fprintf(fd,"%s detectord %f \n", name, ObVal(self->aParameter,PARDS));
|
||||
fprintf(fd,"%s sampleh %f \n", name, ObVal(self->aParameter,PARDH));
|
||||
fprintf(fd,"%s d4d %f \n", name, ObVal(self->aParameter,PARDD4));
|
||||
fprintf(fd,"%s d5d %f \n", name, ObVal(self->aParameter,PARDD5));
|
||||
fprintf(fd,"%s interrupt %f \n", name, ObVal(self->aParameter,PARINT));
|
||||
fprintf(fd,"%s detectorh %f \n", name, ObVal(self->aParameter,PARDDH));
|
||||
fprintf(fd,"%s d4h %f \n", name, ObVal(self->aParameter,PARD4H));
|
||||
fprintf(fd,"%s d5h %f \n", name, ObVal(self->aParameter,PARD5H));
|
||||
fprintf(fd,"%s anah %f \n", name, ObVal(self->aParameter,PARANA));
|
||||
fprintf(fd,"%s anad %f \n", name, ObVal(self->aParameter,PARADIS));
|
||||
fprintf(fd,"%s anaflag %f \n", name, ObVal(self->aParameter,ANAFLAG));
|
||||
fprintf(fd,"%s c2h %f \n", name, ObVal(self->aParameter,PARDDD));
|
||||
fprintf(fd,"%s aomconst %f \n", name, ObVal(self->aParameter,PARAOM));
|
||||
return 1;
|
||||
}
|
||||
/*------------------------------------------------------------------------*/
|
||||
static void A2TList(pAmor2T self, SConnection *pCon, char *name)
|
||||
{
|
||||
char pBueffel[132];
|
||||
Tcl_DString tString;
|
||||
|
||||
assert(pCon);
|
||||
assert(self);
|
||||
|
||||
Tcl_DStringInit(&tString);
|
||||
sprintf(pBueffel,
|
||||
"%s.detectord %f \n", name, ObVal(self->aParameter,PARDS));
|
||||
Tcl_DStringAppend(&tString,pBueffel,-1);
|
||||
sprintf(pBueffel,
|
||||
"%s.sampleh %f \n", name, ObVal(self->aParameter,PARDH));
|
||||
Tcl_DStringAppend(&tString,pBueffel,-1);
|
||||
sprintf(pBueffel,
|
||||
"%s.d4d %f \n", name, ObVal(self->aParameter,PARDD4));
|
||||
Tcl_DStringAppend(&tString,pBueffel,-1);
|
||||
sprintf(pBueffel,
|
||||
"%s.d5d %f \n", name, ObVal(self->aParameter,PARDD5));
|
||||
Tcl_DStringAppend(&tString,pBueffel,-1);
|
||||
sprintf(pBueffel,
|
||||
"%s.interrupt %f \n", name, ObVal(self->aParameter,PARINT));
|
||||
Tcl_DStringAppend(&tString,pBueffel,-1);
|
||||
sprintf(pBueffel,
|
||||
"%s.detectorh %f \n", name, ObVal(self->aParameter,PARDDH));
|
||||
Tcl_DStringAppend(&tString,pBueffel,-1);
|
||||
sprintf(pBueffel,
|
||||
"%s.d4h %f \n", name, ObVal(self->aParameter,PARD4H));
|
||||
Tcl_DStringAppend(&tString,pBueffel,-1);
|
||||
sprintf(pBueffel,
|
||||
"%s.d5h %f \n", name, ObVal(self->aParameter,PARD5H));
|
||||
Tcl_DStringAppend(&tString,pBueffel,-1);
|
||||
sprintf(pBueffel,
|
||||
"%s.anah %f \n", name, ObVal(self->aParameter,PARANA));
|
||||
Tcl_DStringAppend(&tString,pBueffel,-1);
|
||||
sprintf(pBueffel,
|
||||
"%s.anad %f \n", name, ObVal(self->aParameter,PARADIS));
|
||||
Tcl_DStringAppend(&tString,pBueffel,-1);
|
||||
sprintf(pBueffel,
|
||||
"%s.anaflag %f \n", name, ObVal(self->aParameter,ANAFLAG));
|
||||
Tcl_DStringAppend(&tString,pBueffel,-1);
|
||||
sprintf(pBueffel,
|
||||
"%s.c2h %f \n", name, ObVal(self->aParameter,PARDDD));
|
||||
Tcl_DStringAppend(&tString,pBueffel,-1);
|
||||
sprintf(pBueffel,
|
||||
"%s.aomconst %f \n", name, ObVal(self->aParameter,PARAOM));
|
||||
Tcl_DStringAppend(&tString,pBueffel,-1);
|
||||
SCWrite(pCon,Tcl_DStringValue(&tString),eValue);
|
||||
Tcl_DStringFree(&tString);
|
||||
}
|
||||
/*------------------------------------------------------------------------*/
|
||||
static void A2TKill(void *pData)
|
||||
{
|
||||
pAmor2T self = (pAmor2T) pData;
|
||||
|
||||
if(self == NULL)
|
||||
return;
|
||||
|
||||
if(self->pDes)
|
||||
DeleteDescriptor(self->pDes);
|
||||
|
||||
if(self->pDriv)
|
||||
free(self->pDriv);
|
||||
|
||||
if(self->aParameter)
|
||||
ObParDelete(self->aParameter);
|
||||
|
||||
free(self);
|
||||
}
|
||||
/*--------------------------------------------------------------------------
|
||||
Initialization: All is done from the Factory function. This takes an Tcl
|
||||
array as parameter which is supposed to hold the names of all motors.
|
||||
This must fail if one of the motors cannot be accessed.
|
||||
--------------------------------------------------------------------------*/
|
||||
int Amor2TFactory(SConnection *pCon, SicsInterp *pSics, void *pData,
|
||||
int argc, char *argv[])
|
||||
{
|
||||
pAmor2T pNew, pAOM = NULL;
|
||||
int i, iRet;
|
||||
char pBueffel[512];
|
||||
char *pMot = NULL;
|
||||
|
||||
if(argc < 4)
|
||||
{
|
||||
SCWrite(pCon,
|
||||
"ERROR: Insufficient number of arguments to Amor2tFactory",
|
||||
eError);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* allocate space ..............*/
|
||||
pNew = (pAmor2T)malloc(sizeof(Amor2T));
|
||||
if(!pNew)
|
||||
{
|
||||
SCWrite(pCon,"ERROR: out of memory in Amor2TFactory",eError);
|
||||
return 0;
|
||||
}
|
||||
memset(pNew,0,sizeof(Amor2T));
|
||||
pNew->pDes = CreateDescriptor("Amor2T");
|
||||
pNew->aParameter = ObParCreate(MAXPAR);
|
||||
pNew->pDriv = CreateDrivableInterface();
|
||||
if( (!pNew->pDes) || (!pNew->aParameter) || (!pNew->pDriv) )
|
||||
{
|
||||
SCWrite(pCon,"ERROR: out of memory in Amor2TFactory",eError);
|
||||
A2TKill(pNew);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* find the motors*/
|
||||
pMot = Tcl_GetVar2(pSics->pTcl,argv[2],"mom",TCL_GLOBAL_ONLY);
|
||||
if(!pMot)
|
||||
{
|
||||
SCWrite(pCon,"ERROR: no value for mom motr found",eError);
|
||||
A2TKill(pNew);
|
||||
return 0;
|
||||
}
|
||||
pNew->aEngine[MOTMOM] = FindMotor(pSics,pMot);
|
||||
if(!pNew->aEngine[MOTMOM])
|
||||
{
|
||||
sprintf(pBueffel,"ERROR: motor %s NOT found!", pMot);
|
||||
SCWrite(pCon,pBueffel,eError);
|
||||
A2TKill(pNew);
|
||||
return 0;
|
||||
}
|
||||
|
||||
pMot = Tcl_GetVar2(pSics->pTcl,argv[2],"som",TCL_GLOBAL_ONLY);
|
||||
if(!pMot)
|
||||
{
|
||||
SCWrite(pCon,"ERROR: no value for som motor found",eError);
|
||||
A2TKill(pNew);
|
||||
return 0;
|
||||
}
|
||||
pNew->aEngine[MOTSOM] = FindMotor(pSics,pMot);
|
||||
if(!pNew->aEngine[MOTSOM])
|
||||
{
|
||||
sprintf(pBueffel,"ERROR: motor %s NOT found!", pMot);
|
||||
SCWrite(pCon,pBueffel,eError);
|
||||
A2TKill(pNew);
|
||||
return 0;
|
||||
}
|
||||
|
||||
pMot = Tcl_GetVar2(pSics->pTcl,argv[2],"coz",TCL_GLOBAL_ONLY);
|
||||
if(!pMot)
|
||||
{
|
||||
SCWrite(pCon,"ERROR: no value for coz motor found",eError);
|
||||
A2TKill(pNew);
|
||||
return 0;
|
||||
}
|
||||
pNew->aEngine[MOTCOZ] = FindMotor(pSics,pMot);
|
||||
if(!pNew->aEngine[MOTCOZ])
|
||||
{
|
||||
sprintf(pBueffel,"ERROR: motor %s NOT found!", pMot);
|
||||
SCWrite(pCon,pBueffel,eError);
|
||||
A2TKill(pNew);
|
||||
return 0;
|
||||
}
|
||||
|
||||
pMot = Tcl_GetVar2(pSics->pTcl,argv[2],"cox",TCL_GLOBAL_ONLY);
|
||||
if(!pMot)
|
||||
{
|
||||
SCWrite(pCon,"ERROR: no value for cox motor found",eError);
|
||||
A2TKill(pNew);
|
||||
return 0;
|
||||
}
|
||||
pNew->aEngine[MOTCOX] = FindMotor(pSics,pMot);
|
||||
if(!pNew->aEngine[MOTCOX])
|
||||
{
|
||||
sprintf(pBueffel,"ERROR: motor %s NOT found!", pMot);
|
||||
SCWrite(pCon,pBueffel,eError);
|
||||
A2TKill(pNew);
|
||||
return 0;
|
||||
}
|
||||
|
||||
pMot = Tcl_GetVar2(pSics->pTcl,argv[2],"stz",TCL_GLOBAL_ONLY);
|
||||
if(!pMot)
|
||||
{
|
||||
SCWrite(pCon,"ERROR: no value for stz motor found",eError);
|
||||
A2TKill(pNew);
|
||||
return 0;
|
||||
}
|
||||
pNew->aEngine[MOTSTZ] = FindMotor(pSics,pMot);
|
||||
if(!pNew->aEngine[MOTSTZ])
|
||||
{
|
||||
sprintf(pBueffel,"ERROR: motor %s NOT found!", pMot);
|
||||
SCWrite(pCon,pBueffel,eError);
|
||||
A2TKill(pNew);
|
||||
return 0;
|
||||
}
|
||||
|
||||
pMot = Tcl_GetVar2(pSics->pTcl,argv[2],"soz",TCL_GLOBAL_ONLY);
|
||||
if(!pMot)
|
||||
{
|
||||
SCWrite(pCon,"ERROR: no value for soz motor found",eError);
|
||||
A2TKill(pNew);
|
||||
return 0;
|
||||
}
|
||||
pNew->aEngine[MOTSOZ] = FindMotor(pSics,pMot);
|
||||
if(!pNew->aEngine[MOTSOZ])
|
||||
{
|
||||
sprintf(pBueffel,"ERROR: motor %s NOT found!", pMot);
|
||||
SCWrite(pCon,pBueffel,eError);
|
||||
A2TKill(pNew);
|
||||
return 0;
|
||||
}
|
||||
|
||||
pMot = Tcl_GetVar2(pSics->pTcl,argv[2],"d4b",TCL_GLOBAL_ONLY);
|
||||
if(!pMot)
|
||||
{
|
||||
SCWrite(pCon,"ERROR: no value for d4b motor found",eError);
|
||||
A2TKill(pNew);
|
||||
return 0;
|
||||
}
|
||||
pNew->aEngine[MOTD4B] = FindMotor(pSics,pMot);
|
||||
if(!pNew->aEngine[MOTD4B])
|
||||
{
|
||||
sprintf(pBueffel,"ERROR: motor %s NOT found!", pMot);
|
||||
SCWrite(pCon,pBueffel,eError);
|
||||
A2TKill(pNew);
|
||||
return 0;
|
||||
}
|
||||
|
||||
pMot = Tcl_GetVar2(pSics->pTcl,argv[2],"d5b",TCL_GLOBAL_ONLY);
|
||||
if(!pMot)
|
||||
{
|
||||
SCWrite(pCon,"ERROR: no value for d5b motor found",eError);
|
||||
A2TKill(pNew);
|
||||
return 0;
|
||||
}
|
||||
pNew->aEngine[MOTD5B] = FindMotor(pSics,pMot);
|
||||
if(!pNew->aEngine[MOTD5B])
|
||||
{
|
||||
sprintf(pBueffel,"ERROR: motor %s NOT found!", pMot);
|
||||
SCWrite(pCon,pBueffel,eError);
|
||||
A2TKill(pNew);
|
||||
return 0;
|
||||
}
|
||||
|
||||
pMot = Tcl_GetVar2(pSics->pTcl,argv[2],"com",TCL_GLOBAL_ONLY);
|
||||
if(!pMot)
|
||||
{
|
||||
SCWrite(pCon,"ERROR: no value for com motor found",eError);
|
||||
A2TKill(pNew);
|
||||
return 0;
|
||||
}
|
||||
pNew->aEngine[MOTCOM] = FindMotor(pSics,pMot);
|
||||
if(!pNew->aEngine[MOTCOM])
|
||||
{
|
||||
sprintf(pBueffel,"ERROR: motor %s NOT found!", pMot);
|
||||
SCWrite(pCon,pBueffel,eError);
|
||||
A2TKill(pNew);
|
||||
return 0;
|
||||
}
|
||||
|
||||
pMot = Tcl_GetVar2(pSics->pTcl,argv[2],"aoz",TCL_GLOBAL_ONLY);
|
||||
if(!pMot)
|
||||
{
|
||||
SCWrite(pCon,"ERROR: no value for aoz motor found",eError);
|
||||
A2TKill(pNew);
|
||||
return 0;
|
||||
}
|
||||
pNew->aEngine[MOTAOZ] = FindMotor(pSics,pMot);
|
||||
if(!pNew->aEngine[MOTAOZ])
|
||||
{
|
||||
sprintf(pBueffel,"ERROR: motor %s NOT found!", pMot);
|
||||
SCWrite(pCon,pBueffel,eError);
|
||||
A2TKill(pNew);
|
||||
return 0;
|
||||
}
|
||||
|
||||
pMot = Tcl_GetVar2(pSics->pTcl,argv[2],"aom",TCL_GLOBAL_ONLY);
|
||||
if(!pMot)
|
||||
{
|
||||
SCWrite(pCon,"ERROR: no value for aom motor found",eError);
|
||||
A2TKill(pNew);
|
||||
return 0;
|
||||
}
|
||||
pNew->aEngine[MOTAOM] = FindMotor(pSics,pMot);
|
||||
if(!pNew->aEngine[MOTAOM])
|
||||
{
|
||||
sprintf(pBueffel,"ERROR: motor %s NOT found!", pMot);
|
||||
SCWrite(pCon,pBueffel,eError);
|
||||
A2TKill(pNew);
|
||||
return 0;
|
||||
}
|
||||
|
||||
pMot = Tcl_GetVar2(pSics->pTcl,argv[2],"c3z",TCL_GLOBAL_ONLY);
|
||||
if(!pMot)
|
||||
{
|
||||
SCWrite(pCon,"ERROR: no value for c3z motor found",eError);
|
||||
A2TKill(pNew);
|
||||
return 0;
|
||||
}
|
||||
pNew->aEngine[MOTC3Z] = FindMotor(pSics,pMot);
|
||||
if(!pNew->aEngine[MOTC3Z])
|
||||
{
|
||||
sprintf(pBueffel,"ERROR: motor %s NOT found!", pMot);
|
||||
SCWrite(pCon,pBueffel,eError);
|
||||
A2TKill(pNew);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/* initialize parameters */
|
||||
ObParInit(pNew->aParameter,PARDS,"detectord",1400.,usMugger);
|
||||
ObParInit(pNew->aParameter,PARDH,"sampleh",50.,usMugger);
|
||||
ObParInit(pNew->aParameter,PARDD4,"d4d",100.,usMugger);
|
||||
ObParInit(pNew->aParameter,PARDD5,"d5d",200.,usMugger);
|
||||
ObParInit(pNew->aParameter,PARINT,"interrupt",0.,usMugger);
|
||||
ObParInit(pNew->aParameter,PARDDH,"detectorh",40.,usMugger);
|
||||
ObParInit(pNew->aParameter,PARD4H,"d4h",40.,usMugger);
|
||||
ObParInit(pNew->aParameter,PARD5H,"d5h",400.,usMugger);
|
||||
ObParInit(pNew->aParameter,PARANA,"anah",400.,usMugger);
|
||||
ObParInit(pNew->aParameter,PARADIS,"anad",600.,usMugger);
|
||||
ObParInit(pNew->aParameter,ANAFLAG,"anaflag",-1.,usMugger);
|
||||
ObParInit(pNew->aParameter,PARDDD,"c2h",100.,usMugger);
|
||||
ObParInit(pNew->aParameter,PARAOM,"aomconst",3.,usMugger);
|
||||
|
||||
|
||||
/* initialize interfaces */
|
||||
pNew->pDes->GetInterface = A2TGetInterface;
|
||||
pNew->pDes->SaveStatus = A2TSave;
|
||||
pNew->pDriv->Halt = A2THalt;
|
||||
pNew->pDriv->CheckLimits = A2TCheck;
|
||||
pNew->pDriv->SetValue = A2TSetValue;
|
||||
pNew->pDriv->CheckStatus = A2TStatus;
|
||||
pNew->pDriv->GetValue = A2TGetValue;
|
||||
|
||||
/* copy data structure for second command for aom2t */
|
||||
pAOM = (pAmor2T)malloc(sizeof(Amor2T));
|
||||
if(!pAOM)
|
||||
{
|
||||
A2TKill(pNew);
|
||||
SCWrite(pCon,"ERROR: out of memory in Amor2TFactory",eError);
|
||||
return 0;
|
||||
}
|
||||
memcpy(pAOM,pNew,sizeof(Amor2T));
|
||||
pAOM->pDriv = CreateDrivableInterface();
|
||||
pAOM->pDes = CreateDescriptor("Amor2T");
|
||||
if(!pAOM->pDriv || !pAOM->pDes )
|
||||
{
|
||||
A2TKill(pNew);
|
||||
SCWrite(pCon,"ERROR: out of memory in Amor2TFactory",eError);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* set modified interface functions */
|
||||
pAOM->pDes->GetInterface = A2TGetInterface;
|
||||
pAOM->pDriv->Halt = A2THalt;
|
||||
pAOM->pDriv->CheckLimits = ANA2TCheck;
|
||||
pAOM->pDriv->SetValue = ANA2TSetValue;
|
||||
pAOM->pDriv->GetValue = ANA2TGetValue;
|
||||
pAOM->pDriv->CheckStatus = A2TStatus;
|
||||
|
||||
|
||||
/* install commands */
|
||||
iRet = AddCommand(pSics,argv[1],
|
||||
Amor2TAction,A2TKill,pNew);
|
||||
if(!iRet)
|
||||
{
|
||||
sprintf(pBueffel,"ERROR: duplicate command %s NOT created",
|
||||
argv[1]);
|
||||
SCWrite(pCon,pBueffel,eError);
|
||||
A2TKill(pNew);
|
||||
return 0;
|
||||
}
|
||||
iRet = AddCommand(pSics,argv[3],
|
||||
Amor2TAction,free,pAOM);
|
||||
if(!iRet)
|
||||
{
|
||||
sprintf(pBueffel,"ERROR: duplicate command %s NOT created",
|
||||
argv[1]);
|
||||
SCWrite(pCon,pBueffel,eError);
|
||||
A2TKill(pNew);
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
/*----------------------------------------------------------------------*/
|
||||
int Amor2TAction(SConnection *pCon, SicsInterp *pSics, void *pData,
|
||||
int argc, char *argv[])
|
||||
{
|
||||
pAmor2T self = (pAmor2T)pData;
|
||||
char pBueffel[256];
|
||||
float fVal;
|
||||
double dVal;
|
||||
ObPar *pPar = NULL;
|
||||
int iRet;
|
||||
|
||||
assert(self);
|
||||
|
||||
if(argc > 1)
|
||||
{
|
||||
strtolower(argv[1]);
|
||||
/* deal with list */
|
||||
if(strcmp(argv[1],"list") == 0)
|
||||
{
|
||||
A2TList(self,pCon,argv[0]);
|
||||
return 1;
|
||||
}
|
||||
/* otherwise it should be a parameter command */
|
||||
if(argc >= 3)
|
||||
{
|
||||
iRet = Tcl_GetDouble(pSics->pTcl,argv[2],&dVal);
|
||||
if(iRet != TCL_OK)
|
||||
{
|
||||
sprintf(pBueffel,"ERROR: failed to convert %s to number",
|
||||
argv[2]);
|
||||
SCWrite(pCon,pBueffel,eError);
|
||||
return 0;
|
||||
}
|
||||
iRet = ObParSet(self->aParameter,argv[0],argv[1],(float)dVal,pCon);
|
||||
if(iRet)
|
||||
{
|
||||
SCSendOK(pCon);
|
||||
}
|
||||
return iRet;
|
||||
}
|
||||
else
|
||||
{
|
||||
pPar = ObParFind(self->aParameter,argv[1]);
|
||||
if(!pPar)
|
||||
{
|
||||
sprintf(pBueffel,"ERROR: parameter %s NOT found",argv[1]);
|
||||
SCWrite(pCon,pBueffel,eError);
|
||||
return 0;
|
||||
}
|
||||
sprintf(pBueffel,"%s.%s = %f",argv[0],pPar->name, pPar->fVal);
|
||||
SCWrite(pCon,pBueffel,eValue);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
fVal = self->pDriv->GetValue(self,pCon);
|
||||
sprintf(pBueffel," %s = %f", argv[0], fVal);
|
||||
SCWrite(pCon,pBueffel,eValue);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
22
amor2t.h
Normal file
22
amor2t.h
Normal file
@ -0,0 +1,22 @@
|
||||
|
||||
/*-------------------------------------------------------------------------
|
||||
A m o r 2 T
|
||||
A class for controlling the two theta movement of a reflectometer.
|
||||
Especially the AMOR reflectometer at SINQ. For details see the file
|
||||
amor2t.tex. DO NOT TOUCH! This file is automatically created from amor2t.w
|
||||
with nuweb.
|
||||
|
||||
Mark Koennecke, September 1999
|
||||
---------------------------------------------------------------------------*/
|
||||
#ifndef AMOR2T
|
||||
#define AMOR2T
|
||||
|
||||
typedef struct __AMOR2T *pAmor2T;
|
||||
|
||||
int Amor2TFactory(SConnection *pCon, SicsInterp *pSics, void *pData,
|
||||
int argc, char *argv[]);
|
||||
int Amor2TAction(SConnection *pCon, SicsInterp *pSics, void *pData,
|
||||
int argc, char *argv[]);
|
||||
void Amor2TKill(void *pData);
|
||||
|
||||
#endif
|
55
amor2t.i
Normal file
55
amor2t.i
Normal file
@ -0,0 +1,55 @@
|
||||
|
||||
/*--------------------------------------------------------------------------
|
||||
A m o r 2 T . i
|
||||
Internal data structure definitions for Amor2T. For details see amor2t.tex.
|
||||
DO NOT TOUCH! This file is automatically created from amor2t.w.
|
||||
|
||||
Mark Koennecke, September 1999
|
||||
----------------------------------------------------------------------------*/
|
||||
|
||||
/* distance detector sample */
|
||||
#define PARDS 0
|
||||
/* constant height of sample: height = PARDH + MOTSOZ + MOTSTZ */
|
||||
#define PARDH 1
|
||||
/* distance diaphragm 4 - sample */
|
||||
#define PARDD4 2
|
||||
/* distance to diaphragm 5 */
|
||||
#define PARDD5 3
|
||||
/* interrupt to issue when a motor fails on this */
|
||||
#define PARINT 4
|
||||
/* base height of counter station */
|
||||
#define PARDDH 5
|
||||
/* height of D4 */
|
||||
#define PARD4H 6
|
||||
/* height of D5 */
|
||||
#define PARD5H 7
|
||||
/* base height of analyzer */
|
||||
#define PARANA 8
|
||||
/* distance of analyzer from sample */
|
||||
#define PARADIS 9
|
||||
/* flag analyzer calculation on/off */
|
||||
#define ANAFLAG 10
|
||||
/* constant for second detector */
|
||||
#define PARDDD 11
|
||||
/* constant part of AOM */
|
||||
#define PARAOM 12
|
||||
|
||||
|
||||
typedef struct {
|
||||
pMotor pMot;
|
||||
char pName[80];
|
||||
float fTarget;
|
||||
}MotEntry, *pMotEntry;
|
||||
|
||||
|
||||
|
||||
typedef struct __AMOR2T {
|
||||
pObjectDescriptor pDes;
|
||||
pIDrivable pDriv;
|
||||
pMotor aEngine[MAXMOT];
|
||||
MotEntry toStart[MAXMOT];
|
||||
int iStart;
|
||||
ObPar *aParameter;
|
||||
}Amor2T;
|
||||
|
||||
|
204
amor2t.tex
Normal file
204
amor2t.tex
Normal file
@ -0,0 +1,204 @@
|
||||
\subsection{AMOR Two Theta}
|
||||
AMOR is SINQ's new reflectometer. It has the peculiar feature that the
|
||||
two theta movement of the detector is expressed in translations along
|
||||
the reflectometer base axis and the detector height. Additionally the
|
||||
detector is tilted. The height of two diaphragms has to be adjusted as
|
||||
well. And, in polarizing mode, the analyzer has to be operated as
|
||||
well. Quite a complicated movement. I fear this module may only be
|
||||
useful for AMOR, but may be, other reflectometers may profit as well.
|
||||
This object implements this complex movement as a virtual motor.
|
||||
|
||||
The following formulas are used for the necessary calculations:
|
||||
\begin{eqnarray}
|
||||
delta height & = & h_{s} - \sin \alpha \\
|
||||
delta x & = & |x_{c} - x_{s}| - R \cos \alpha \\
|
||||
omega & = & -2 MOM + 2 SOM \\
|
||||
\end{eqnarray}
|
||||
with
|
||||
\begin{eqnarray}
|
||||
h_{s} & = & \tan(2MOM)|x_{c} - x_{s}| \\
|
||||
R & = & \sqrt{hs^{2} - |x_{c} - x_{s}|^{2}} \\
|
||||
\alpha & = & ATT - 2SOM \\
|
||||
\beta & = & 180 - 90 - 2MOM \\
|
||||
MOM & = & polarizer \omega \\
|
||||
SOM & = & sample \omega \\
|
||||
x_{c} & = & counter position \\
|
||||
x_{s} & = & sample position\\
|
||||
\end{eqnarray}
|
||||
The same equations hold true for the calculations of the diaphragm
|
||||
heights, just replace the distances. The equations for the analyzer
|
||||
are not yet known.
|
||||
|
||||
Due to this complicated movement this module needs to know about a lot
|
||||
of motors and a lot of parameters. The distances of the various
|
||||
components need to be modified at run time in order to allow for
|
||||
configuration changes. These are not motorized but must be entered
|
||||
manually.
|
||||
|
||||
\subsubsection{Data Structures}
|
||||
Consequently data structures are complex. The first data structure
|
||||
used is an entry in an array of motors to start:
|
||||
\begin{flushleft} \small
|
||||
\begin{minipage}{\linewidth} \label{scrap1}
|
||||
$\langle$putput {\footnotesize ?}$\rangle\equiv$
|
||||
\vspace{-1ex}
|
||||
\begin{list}{}{} \item
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@ typedef struct {@\\
|
||||
\mbox{}\verb@ pMotor pMot;@\\
|
||||
\mbox{}\verb@ char pName[80];@\\
|
||||
\mbox{}\verb@ float fTarget;@\\
|
||||
\mbox{}\verb@ }MotEntry, *pMotEntry;@\\
|
||||
\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}
|
||||
\begin{description}
|
||||
\item[pMot] is a pointer to the motors data structure.
|
||||
\item[pName] is the name of the motor to start.
|
||||
\item[fTarget] is the target value for the motor.
|
||||
\end{description}
|
||||
|
||||
The next data structure is the class data structure for amor2t:
|
||||
\begin{flushleft} \small
|
||||
\begin{minipage}{\linewidth} \label{scrap2}
|
||||
$\langle$amoredata {\footnotesize ?}$\rangle\equiv$
|
||||
\vspace{-1ex}
|
||||
\begin{list}{}{} \item
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@ typedef struct __AMOR2T {@\\
|
||||
\mbox{}\verb@ pObjectDescriptor pDes;@\\
|
||||
\mbox{}\verb@ pIDrivable pDriv;@\\
|
||||
\mbox{}\verb@ pMotor aEngine[MAXMOT];@\\
|
||||
\mbox{}\verb@ MotEntry toStart[MAXMOT];@\\
|
||||
\mbox{}\verb@ int iStart;@\\
|
||||
\mbox{}\verb@ ObPar *aParameter;@\\
|
||||
\mbox{}\verb@ }Amor2T;@\\
|
||||
\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}
|
||||
\begin{description}
|
||||
\item[pDes] The standard SICS object descriptor.
|
||||
\item[pDriv] The drivable interface. The functions defined for the
|
||||
drivable interface implement most of the work of this class.
|
||||
\item[aEngine] An array of pointers to the motor data structures this
|
||||
class has to deal with. The proper initialization of this is taken
|
||||
care of during the initialization of the object.
|
||||
\item[toStart] An array of motors to start when all calculations have
|
||||
been performed.
|
||||
\item[iStart] The number of valid entries in toStart.
|
||||
\item[aParameter] An array of parameters for this object.
|
||||
\end{description}
|
||||
|
||||
\subsubsection{The Interface}
|
||||
The interface to this module is quite primitive. Most of the
|
||||
functionality is hidden in the drivable interface. So there are only
|
||||
functions for interacting with the interpreter.
|
||||
|
||||
\begin{flushleft} \small
|
||||
\begin{minipage}{\linewidth} \label{scrap3}
|
||||
$\langle$amorinterface {\footnotesize ?}$\rangle\equiv$
|
||||
\vspace{-1ex}
|
||||
\begin{list}{}{} \item
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@ typedef struct __AMOR2T *pAmor2T;@\\
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@ int Amor2TFactory(SConnection *pCon, SicsInterp *pSics, void *pData,@\\
|
||||
\mbox{}\verb@ int argc, char *argv[]);@\\
|
||||
\mbox{}\verb@ int Amor2TAction(SConnection *pCon, SicsInterp *pSics, void *pData,@\\
|
||||
\mbox{}\verb@ int argc, char *argv[]);@\\
|
||||
\mbox{}\verb@ void Amor2TKill(void *pData); @\\
|
||||
\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}
|
||||
\begin{flushleft} \small
|
||||
\begin{minipage}{\linewidth} \label{scrap4}
|
||||
\verb@"amor2t.i"@ {\footnotesize ? }$\equiv$
|
||||
\vspace{-1ex}
|
||||
\begin{list}{}{} \item
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@/*--------------------------------------------------------------------------@\\
|
||||
\mbox{}\verb@ A m o r 2 T . i@\\
|
||||
\mbox{}\verb@ Internal data structure definitions for Amor2T. For details see amor2t.tex.@\\
|
||||
\mbox{}\verb@ DO NOT TOUCH! This file is automatically created from amor2t.w.@\\
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@ Mark Koennecke, September 1999@\\
|
||||
\mbox{}\verb@----------------------------------------------------------------------------*/@\\
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@/* distance detector sample */@\\
|
||||
\mbox{}\verb@#define PARDS 0@\\
|
||||
\mbox{}\verb@/* constant height of sample: height = PARDH + MOTSOZ + MOTSTZ */@\\
|
||||
\mbox{}\verb@#define PARDH 1@\\
|
||||
\mbox{}\verb@/* distance diaphragm 4 - sample */@\\
|
||||
\mbox{}\verb@#define PARDD4 2@\\
|
||||
\mbox{}\verb@/* distance to diaphragm 5 */@\\
|
||||
\mbox{}\verb@#define PARDD5 3@\\
|
||||
\mbox{}\verb@/* interrupt to issue when a motor fails on this */@\\
|
||||
\mbox{}\verb@#define PARINT 4@\\
|
||||
\mbox{}\verb@/* base height of counter station */@\\
|
||||
\mbox{}\verb@#define PARDDH 5@\\
|
||||
\mbox{}\verb@/* height of D4 */@\\
|
||||
\mbox{}\verb@#define PARD4H 6@\\
|
||||
\mbox{}\verb@/* height of D5 */@\\
|
||||
\mbox{}\verb@#define PARD5H 7@\\
|
||||
\mbox{}\verb@/* base height of analyzer */@\\
|
||||
\mbox{}\verb@#define PARANA 8@\\
|
||||
\mbox{}\verb@/* distance of analyzer from sample */@\\
|
||||
\mbox{}\verb@#define PARADIS 9@\\
|
||||
\mbox{}\verb@/* flag analyzer calculation on/off */@\\
|
||||
\mbox{}\verb@#define ANAFLAG 10@\\
|
||||
\mbox{}\verb@/* constant for second detector */@\\
|
||||
\mbox{}\verb@#define PARDDD 11@\\
|
||||
\mbox{}\verb@/* constant part of AOM */@\\
|
||||
\mbox{}\verb@#define PARAOM 12@\\
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@@$\langle$putput {\footnotesize ?}$\rangle$\verb@@\\
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@@$\langle$amoredata {\footnotesize ?}$\rangle$\verb@@\\
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@@$\diamond$
|
||||
\end{list}
|
||||
\vspace{-2ex}
|
||||
\end{minipage}\\[4ex]
|
||||
\end{flushleft}
|
||||
\begin{flushleft} \small
|
||||
\begin{minipage}{\linewidth} \label{scrap5}
|
||||
\verb@"amor2t.h"@ {\footnotesize ? }$\equiv$
|
||||
\vspace{-1ex}
|
||||
\begin{list}{}{} \item
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@/*-------------------------------------------------------------------------@\\
|
||||
\mbox{}\verb@ A m o r 2 T@\\
|
||||
\mbox{}\verb@ A class for controlling the two theta movement of a reflectometer. @\\
|
||||
\mbox{}\verb@ Especially the AMOR reflectometer at SINQ. For details see the file @\\
|
||||
\mbox{}\verb@ amor2t.tex. DO NOT TOUCH! This file is automatically created from amor2t.w@\\
|
||||
\mbox{}\verb@ with nuweb.@\\
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@ Mark Koennecke, September 1999@\\
|
||||
\mbox{}\verb@---------------------------------------------------------------------------*/@\\
|
||||
\mbox{}\verb@#ifndef AMOR2T@\\
|
||||
\mbox{}\verb@#define AMOR2T@\\
|
||||
\mbox{}\verb@@$\langle$amorinterface {\footnotesize ?}$\rangle$\verb@@\\
|
||||
\mbox{}\verb@#endif @\\
|
||||
\mbox{}\verb@@$\diamond$
|
||||
\end{list}
|
||||
\vspace{-2ex}
|
||||
\end{minipage}\\[4ex]
|
||||
\end{flushleft}
|
150
amor2t.w
Normal file
150
amor2t.w
Normal file
@ -0,0 +1,150 @@
|
||||
\subsection{AMOR Two Theta}
|
||||
AMOR is SINQ's new reflectometer. It has the peculiar feature that the
|
||||
two theta movement of the detector is expressed in translations along
|
||||
the reflectometer base axis and the detector height. Additionally the
|
||||
detector is tilted. The height of two diaphragms has to be adjusted as
|
||||
well. And, in polarizing mode, the analyzer has to be operated as
|
||||
well. Quite a complicated movement. I fear this module may only be
|
||||
useful for AMOR, but may be, other reflectometers may profit as well.
|
||||
This object implements this complex movement as a virtual motor.
|
||||
|
||||
The following formulas are used for the necessary calculations:
|
||||
\begin{eqnarray}
|
||||
delta height & = & h_{s} - \sin \alpha \\
|
||||
delta x & = & |x_{c} - x_{s}| - R \cos \alpha \\
|
||||
omega & = & -2 MOM + 2 SOM \\
|
||||
\end{eqnarray}
|
||||
with
|
||||
\begin{eqnarray}
|
||||
h_{s} & = & \tan(2MOM)|x_{c} - x_{s}| \\
|
||||
R & = & \sqrt{hs^{2} - |x_{c} - x_{s}|^{2}} \\
|
||||
\alpha & = & ATT - 2SOM \\
|
||||
\beta & = & 180 - 90 - 2MOM \\
|
||||
MOM & = & polarizer \omega \\
|
||||
SOM & = & sample \omega \\
|
||||
x_{c} & = & counter position \\
|
||||
x_{s} & = & sample position\\
|
||||
\end{eqnarray}
|
||||
The same equations hold true for the calculations of the diaphragm
|
||||
heights, just replace the distances. The equations for the analyzer
|
||||
are not yet known.
|
||||
|
||||
Due to this complicated movement this module needs to know about a lot
|
||||
of motors and a lot of parameters. The distances of the various
|
||||
components need to be modified at run time in order to allow for
|
||||
configuration changes. These are not motorized but must be entered
|
||||
manually.
|
||||
|
||||
\subsubsection{Data Structures}
|
||||
Consequently data structures are complex. The first data structure
|
||||
used is an entry in an array of motors to start:
|
||||
@d putput @{
|
||||
typedef struct {
|
||||
pMotor pMot;
|
||||
char pName[80];
|
||||
float fTarget;
|
||||
}MotEntry, *pMotEntry;
|
||||
@}
|
||||
\begin{description}
|
||||
\item[pMot] is a pointer to the motors data structure.
|
||||
\item[pName] is the name of the motor to start.
|
||||
\item[fTarget] is the target value for the motor.
|
||||
\end{description}
|
||||
|
||||
The next data structure is the class data structure for amor2t:
|
||||
@d amoredata @{
|
||||
typedef struct __AMOR2T {
|
||||
pObjectDescriptor pDes;
|
||||
pIDrivable pDriv;
|
||||
pMotor aEngine[MAXMOT];
|
||||
MotEntry toStart[MAXMOT];
|
||||
int iStart;
|
||||
ObPar *aParameter;
|
||||
}Amor2T;
|
||||
@}
|
||||
\begin{description}
|
||||
\item[pDes] The standard SICS object descriptor.
|
||||
\item[pDriv] The drivable interface. The functions defined for the
|
||||
drivable interface implement most of the work of this class.
|
||||
\item[aEngine] An array of pointers to the motor data structures this
|
||||
class has to deal with. The proper initialization of this is taken
|
||||
care of during the initialization of the object.
|
||||
\item[toStart] An array of motors to start when all calculations have
|
||||
been performed.
|
||||
\item[iStart] The number of valid entries in toStart.
|
||||
\item[aParameter] An array of parameters for this object.
|
||||
\end{description}
|
||||
|
||||
\subsubsection{The Interface}
|
||||
The interface to this module is quite primitive. Most of the
|
||||
functionality is hidden in the drivable interface. So there are only
|
||||
functions for interacting with the interpreter.
|
||||
|
||||
@d amorinterface @{
|
||||
typedef struct __AMOR2T *pAmor2T;
|
||||
|
||||
int Amor2TFactory(SConnection *pCon, SicsInterp *pSics, void *pData,
|
||||
int argc, char *argv[]);
|
||||
int Amor2TAction(SConnection *pCon, SicsInterp *pSics, void *pData,
|
||||
int argc, char *argv[]);
|
||||
void Amor2TKill(void *pData);
|
||||
@}
|
||||
|
||||
@o amor2t.i @{
|
||||
/*--------------------------------------------------------------------------
|
||||
A m o r 2 T . i
|
||||
Internal data structure definitions for Amor2T. For details see amor2t.tex.
|
||||
DO NOT TOUCH! This file is automatically created from amor2t.w.
|
||||
|
||||
Mark Koennecke, September 1999
|
||||
----------------------------------------------------------------------------*/
|
||||
|
||||
/* distance detector sample */
|
||||
#define PARDS 0
|
||||
/* constant height of sample: height = PARDH + MOTSOZ + MOTSTZ */
|
||||
#define PARDH 1
|
||||
/* distance diaphragm 4 - sample */
|
||||
#define PARDD4 2
|
||||
/* distance to diaphragm 5 */
|
||||
#define PARDD5 3
|
||||
/* interrupt to issue when a motor fails on this */
|
||||
#define PARINT 4
|
||||
/* base height of counter station */
|
||||
#define PARDDH 5
|
||||
/* height of D4 */
|
||||
#define PARD4H 6
|
||||
/* height of D5 */
|
||||
#define PARD5H 7
|
||||
/* base height of analyzer */
|
||||
#define PARANA 8
|
||||
/* distance of analyzer from sample */
|
||||
#define PARADIS 9
|
||||
/* flag analyzer calculation on/off */
|
||||
#define ANAFLAG 10
|
||||
/* constant for second detector */
|
||||
#define PARDDD 11
|
||||
/* constant part of AOM */
|
||||
#define PARAOM 12
|
||||
|
||||
@<putput@>
|
||||
|
||||
@<amoredata@>
|
||||
|
||||
@}
|
||||
|
||||
@o amor2t.h @{
|
||||
/*-------------------------------------------------------------------------
|
||||
A m o r 2 T
|
||||
A class for controlling the two theta movement of a reflectometer.
|
||||
Especially the AMOR reflectometer at SINQ. For details see the file
|
||||
amor2t.tex. DO NOT TOUCH! This file is automatically created from amor2t.w
|
||||
with nuweb.
|
||||
|
||||
Mark Koennecke, September 1999
|
||||
---------------------------------------------------------------------------*/
|
||||
#ifndef AMOR2T
|
||||
#define AMOR2T
|
||||
@<amorinterface@>
|
||||
#endif
|
||||
@}
|
||||
|
23
amorpar.tcl
Normal file
23
amorpar.tcl
Normal file
@ -0,0 +1,23 @@
|
||||
#--------------------------------------------------------------------------
|
||||
# A SICS-tcl-macro script for formatting the parameters for the
|
||||
# reflectometer AMOR's status display.
|
||||
#
|
||||
# Mark Koennecke, October 1999
|
||||
#-------------------------------------------------------------------------
|
||||
proc amorpar {} {
|
||||
lappend list "amorpar == "
|
||||
lappend list [lastscancommand] ";"
|
||||
catch {scan getvars} msg
|
||||
lappend list $msg ";"
|
||||
lappend list [xxxscan getfile] ";"
|
||||
lappend list [sicstime] ";"
|
||||
set ret [catch {temperature} msg]
|
||||
if {$ret == 0} {
|
||||
lappend list $msg
|
||||
}
|
||||
set ret [catch {magnet} msg]
|
||||
if {$ret == 0} {
|
||||
lappend list $msg
|
||||
}
|
||||
return [join $list]
|
||||
}
|
140
amorscan.c
Normal file
140
amorscan.c
Normal file
@ -0,0 +1,140 @@
|
||||
/*-------------------------------------------------------------------------
|
||||
A M O R S C A N
|
||||
|
||||
An adaption of the general scan routine to deal with special issues at
|
||||
the reflectometer AMOR at SINQ.
|
||||
|
||||
copyright: see copyright.h
|
||||
|
||||
Mark Koennecke, September 1999
|
||||
--------------------------------------------------------------------------*/
|
||||
#include <stdlib.h>
|
||||
#include <assert.h>
|
||||
#include "fortify.h"
|
||||
#include "sics.h"
|
||||
#include "scan.h"
|
||||
#include "scan.i"
|
||||
#include "HistMem.h"
|
||||
#include "nxamor.h"
|
||||
#include "amorscan.h"
|
||||
|
||||
/*--------------------------------------------------------------------*/
|
||||
static int AmorHeader(pScanData self)
|
||||
{
|
||||
return WriteAmorHeader(self->pFile, self->pCon);
|
||||
}
|
||||
/*--------------------------------------------------------------------*/
|
||||
static int AmorPoints(pScanData self, int iP)
|
||||
{
|
||||
/* write only at last scan point */
|
||||
if((iP+1) >= self->iNP)
|
||||
{
|
||||
return WriteAmorScan(self->pFile,self->pCon,self);
|
||||
}
|
||||
}
|
||||
/*--------------------------------------------------------------------*/
|
||||
static int AmorCollect(pScanData self, int iP)
|
||||
{
|
||||
pVarEntry pVar = NULL;
|
||||
void *pDings;
|
||||
int i, iRet, status;
|
||||
float fVal;
|
||||
char pStatus[512], pItem[20];
|
||||
char pHead[512];
|
||||
CountEntry sCount;
|
||||
|
||||
assert(self);
|
||||
assert(self->pCon);
|
||||
|
||||
/* prepare output header */
|
||||
sprintf(pHead,"%-5.5s","NP");
|
||||
sprintf(pStatus,"%-5d",iP);
|
||||
|
||||
/* loop over all scan variables */
|
||||
status = 1;
|
||||
for(i = 0; i < self->iScanVar; i++)
|
||||
{
|
||||
DynarGet(self->pScanVar,i,&pDings);
|
||||
pVar = (pVarEntry)pDings;
|
||||
if(pVar)
|
||||
{
|
||||
fVal = pVar->pInter->GetValue(pVar->pObject,self->pCon);
|
||||
pVar->fData[iP] = fVal;
|
||||
sprintf(pItem,"%-10.10s",pVar->Name);
|
||||
strcat(pHead,pItem);
|
||||
sprintf(pItem,"%-10.3f",fVal);
|
||||
strcat(pStatus,pItem);
|
||||
}
|
||||
}
|
||||
|
||||
/* store counter data */
|
||||
/* monitors */
|
||||
for(i = 1; i < 10; i++)
|
||||
{
|
||||
sCount.Monitors[i-1] = GetMonitor((pCounter)self->pCounterData,i,
|
||||
self->pCon);
|
||||
}
|
||||
if( self->iChannel != 0 && self->iChannel != -10 )
|
||||
{
|
||||
sCount.Monitors[self->iChannel - 1] =
|
||||
GetCounts((pCounter)self->pCounterData,
|
||||
self->pCon);
|
||||
}
|
||||
/* counter1 */
|
||||
strcat(pHead,"Counter1 ");
|
||||
sCount.lCount = GetCounts((pCounter)self->pCounterData,self->pCon);
|
||||
sprintf(pItem,"%-15d",sCount.lCount);
|
||||
strcat(pStatus,pItem);
|
||||
|
||||
/*
|
||||
WARNING
|
||||
Assignements have to be checked when the Schlumpfes are
|
||||
ready putting the counter box together.
|
||||
*/
|
||||
|
||||
/* counter2 */
|
||||
strcat(pHead,"Counter2 ");
|
||||
sCount.Monitors[0] = GetMonitor((pCounter)self->pCounterData,
|
||||
1,self->pCon);
|
||||
sprintf(pItem,"%-15d",sCount.Monitors[0]);
|
||||
strcat(pStatus,pItem);
|
||||
|
||||
/* monitors */
|
||||
sCount.Monitors[3] = GetMonitor((pCounter)self->pCounterData,
|
||||
2,self->pCon);
|
||||
sCount.Monitors[4] = GetMonitor((pCounter)self->pCounterData,
|
||||
3,self->pCon);
|
||||
|
||||
/* get time */
|
||||
sCount.fTime = GetCountTime((pCounter)self->pCounterData,
|
||||
self->pCon);
|
||||
strcat(pHead,"Monitor1 ");
|
||||
sprintf(pItem,"%-12d",sCount.Monitors[3]);
|
||||
strcat(pStatus,pItem);
|
||||
strcat(pHead,"Monitor2 ");
|
||||
sprintf(pItem,"%-12d",sCount.Monitors[4]);
|
||||
strcat(pStatus,pItem);
|
||||
strcat(pHead,"Time ");
|
||||
sprintf(pItem,"%-6.1f",sCount.fTime);
|
||||
strcat(pStatus,pItem);
|
||||
|
||||
/* write progress */
|
||||
strcat(pHead,"\n");
|
||||
strcat(pStatus,"\n");
|
||||
SCWrite(self->pCon,pHead,eWarning);
|
||||
SCWrite(self->pCon,pStatus,eWarning);
|
||||
|
||||
/* stow away */
|
||||
DynarReplace(self->pCounts,self->iCounts,&sCount,sizeof(CountEntry));
|
||||
self->iCounts++;
|
||||
return 1;
|
||||
}
|
||||
/*-----------------------------------------------------------------------*/
|
||||
int ConfigureAmor(pScanData self)
|
||||
{
|
||||
self->WriteHeader = AmorHeader;
|
||||
self->WriteScanPoints = AmorPoints;
|
||||
self->CollectScanData = AmorCollect;
|
||||
strcpy(self->ext,".hdf");
|
||||
return 1;
|
||||
}
|
15
amorscan.h
Normal file
15
amorscan.h
Normal file
@ -0,0 +1,15 @@
|
||||
|
||||
/*-----------------------------------------------------------------------
|
||||
A M O R S C A N
|
||||
Adaption of the scan command to do things specific to the
|
||||
reflectometer AMOR at SINQ.
|
||||
|
||||
Mark Koennecke, September 1999
|
||||
-----------------------------------------------------------------------*/
|
||||
#ifndef AMORSCAN
|
||||
#define AMORSCAN
|
||||
|
||||
int ConfigureAmor(pScanData pScan);
|
||||
|
||||
#endif
|
||||
|
71
amorscan.tex
Normal file
71
amorscan.tex
Normal file
@ -0,0 +1,71 @@
|
||||
\subsection{Amor Scan}
|
||||
This is a special adaption of the general scan routines for the
|
||||
reflectometer AMOR at SINQ. It works by replacing the configurable
|
||||
routines in the general scan command with special ones, suited to the
|
||||
reflectometers purpose. There are several adaptions to the standard
|
||||
scan command:
|
||||
\begin{itemize}
|
||||
\item Data is written to NeXus files instead of ASCII files.
|
||||
\item There are two counters to keep track of.
|
||||
\item Furthermore stubs are provided for dealing with spin flippers.
|
||||
\end{itemize}
|
||||
|
||||
In order to keep track of counters and monitors the following
|
||||
convention has been devised:
|
||||
\begin{itemize}
|
||||
\item GetCounts gets the main detector.
|
||||
\item GetMonitor 0 the second detector
|
||||
\item GetMonitor 1 the first detector other spin
|
||||
\item GetMonitor 2 the second detector other spin
|
||||
\item GetMonitor 3 the first monitor
|
||||
\item GetMonitor 4 the second monitor
|
||||
\end{itemize}
|
||||
Thus the monitor channels are used to keep the additional counter
|
||||
information.
|
||||
|
||||
This module provides only one external function:
|
||||
\begin{flushleft} \small
|
||||
\begin{minipage}{\linewidth} \label{scrap1}
|
||||
$\langle$amorscan {\footnotesize ?}$\rangle\equiv$
|
||||
\vspace{-1ex}
|
||||
\begin{list}{}{} \item
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@ int ConfigureAmor(pScanData pScan);@\\
|
||||
\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}
|
||||
which configures the variable fields and function pointers in pScan to
|
||||
functions defined in this module. These then do the right thing. This
|
||||
module is also an example of how the scan command can be configured to do
|
||||
tricks based on the syntax and hooks defined in scan.*.
|
||||
|
||||
|
||||
\begin{flushleft} \small
|
||||
\begin{minipage}{\linewidth} \label{scrap2}
|
||||
\verb@"amorscan.h"@ {\footnotesize ? }$\equiv$
|
||||
\vspace{-1ex}
|
||||
\begin{list}{}{} \item
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@/*-----------------------------------------------------------------------@\\
|
||||
\mbox{}\verb@ A M O R S C A N@\\
|
||||
\mbox{}\verb@ Adaption of the scan command to do things specific to the@\\
|
||||
\mbox{}\verb@ reflectometer AMOR at SINQ.@\\
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@ Mark Koennecke, September 1999@\\
|
||||
\mbox{}\verb@-----------------------------------------------------------------------*/@\\
|
||||
\mbox{}\verb@#ifndef AMORSCAN@\\
|
||||
\mbox{}\verb@#define AMORSCAN@\\
|
||||
\mbox{}\verb@@$\langle$amorscan {\footnotesize ?}$\rangle$\verb@@\\
|
||||
\mbox{}\verb@#endif@\\
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@@$\diamond$
|
||||
\end{list}
|
||||
\vspace{-2ex}
|
||||
\end{minipage}\\[4ex]
|
||||
\end{flushleft}
|
57
amorscan.w
Normal file
57
amorscan.w
Normal file
@ -0,0 +1,57 @@
|
||||
\subsection{Amor Scan}
|
||||
This is a special adaption of the general scan routines for the
|
||||
reflectometer AMOR at SINQ. It works by replacing the configurable
|
||||
routines in the general scan command with special ones, suited to the
|
||||
reflectometers purpose. There are several adaptions to the standard
|
||||
scan command:
|
||||
\begin{itemize}
|
||||
\item Data is written to NeXus files instead of ASCII files.
|
||||
\item There are two counters to keep track of.
|
||||
\item Furthermore stubs are provided for dealing with spin flippers.
|
||||
\end{itemize}
|
||||
|
||||
In order to keep track of counters and monitors the following
|
||||
convention has been devised:
|
||||
\begin{itemize}
|
||||
\item GetCounts gets the main detector.
|
||||
\item GetMonitor 0 the second detector
|
||||
\item GetMonitor 1 the first detector other spin
|
||||
\item GetMonitor 2 the second detector other spin
|
||||
\item GetMonitor 3 the first monitor
|
||||
\item GetMonitor 4 the second monitor
|
||||
\end{itemize}
|
||||
Thus the monitor channels are used to keep the additional counter
|
||||
information.
|
||||
|
||||
This module provides only one external function:
|
||||
@d amorscan @{
|
||||
int ConfigureAmor(pScanData pScan);
|
||||
@}
|
||||
which configures the variable fields and function pointers in pScan to
|
||||
functions defined in this module. These then do the right thing. This
|
||||
module is also an example of how the scan command can be configured to do
|
||||
tricks based on the syntax and hooks defined in scan.*.
|
||||
|
||||
|
||||
@o amorscan.h @{
|
||||
/*-----------------------------------------------------------------------
|
||||
A M O R S C A N
|
||||
Adaption of the scan command to do things specific to the
|
||||
reflectometer AMOR at SINQ.
|
||||
|
||||
Mark Koennecke, September 1999
|
||||
-----------------------------------------------------------------------*/
|
||||
#ifndef AMORSCAN
|
||||
#define AMORSCAN
|
||||
@<amorscan@>
|
||||
#endif
|
||||
|
||||
@}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
919
amorstat.c
Normal file
919
amorstat.c
Normal file
@ -0,0 +1,919 @@
|
||||
/*--------------------------------------------------------------------------
|
||||
A M O R S T A T U S
|
||||
|
||||
The implementation file for the amor status display facilitator module. The
|
||||
reflectometer AMOR needs some advanced feautures for its status display.
|
||||
These needs are taken care of here.
|
||||
|
||||
copyright: see copyright.h
|
||||
|
||||
Mark Koennecke, September 1999
|
||||
|
||||
As AMOR's histogram memory becomes too big in tof mode to transfer it
|
||||
for status information the collapse and subsample functionalities have
|
||||
been moved to the histogram memory. This code had to be modified to
|
||||
call SINQHMProject directly.
|
||||
|
||||
Mark Koennecke, August 2001
|
||||
--------------------------------------------------------------------------*/
|
||||
#include <stdlib.h>
|
||||
#include <assert.h>
|
||||
#include <stdio.h>
|
||||
#include <tcl.h>
|
||||
#include "fortify.h"
|
||||
#include "sics.h"
|
||||
#include "counter.h"
|
||||
#include "stringdict.h"
|
||||
#include "HistMem.h"
|
||||
#include "HistMem.i"
|
||||
#include "HistDriv.i"
|
||||
#include "hardsup/sinqhm.h"
|
||||
#include "sinqhmdriv.i"
|
||||
#include "scan.h"
|
||||
#include "lld.h"
|
||||
#include "amorstat.i"
|
||||
#include "amorstat.h"
|
||||
/*-------------------------------------------------------------------------
|
||||
A static which determines if we are in TOF or scan mode.
|
||||
*/
|
||||
static int iTOF = 0;
|
||||
static pHistMem pHMHM = NULL;
|
||||
/*-------------------------------------------------------------------------*/
|
||||
static int HMCountStartCallback(int iEvent, void *pEvent, void *pUser)
|
||||
{
|
||||
SConnection *pCon = (SConnection *)pUser;
|
||||
const float *fTime = NULL;
|
||||
int *iTime = NULL;
|
||||
int iLength, iRet, i;
|
||||
|
||||
assert(pCon);
|
||||
|
||||
if(iEvent == COUNTSTART)
|
||||
{
|
||||
/* send current time binning */
|
||||
iTOF = 1;
|
||||
fTime = GetHistTimeBin(pHMHM,&iLength);
|
||||
iTime = (int *)malloc((iLength+1)*sizeof(int));
|
||||
if( (!fTime) || (!iTime))
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
iTime[0] = htonl(iLength);
|
||||
for(i = 0 ; i < iLength; i++)
|
||||
{
|
||||
iTime[i+1] = htonl((int)((fTime[i]/10.)*65536.));
|
||||
}
|
||||
/* send new time binning to all clients */
|
||||
SCWrite(pCon,"TOFClear",eError);
|
||||
SCWriteUUencoded(pCon,"arrowaxis_time",iTime,
|
||||
(iLength+1)*sizeof(int));
|
||||
free(iTime);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
/*-------------------------------------------------------------------------*/
|
||||
static int ScanStartCallback(int iEvent, void *pEvent, void *pUser)
|
||||
{
|
||||
float *fAxis = NULL;
|
||||
int *iAxis = NULL;
|
||||
int iLength, iRet, i;
|
||||
char pBueffel[80], pName[40];
|
||||
SConnection *pCon = (SConnection *)pUser;
|
||||
pScanData pScan = (pScanData)pEvent;
|
||||
|
||||
assert(pCon);
|
||||
assert(pScan);
|
||||
|
||||
|
||||
if(iEvent == SCANSTART)
|
||||
{
|
||||
iTOF = 0;
|
||||
/* send current axis */
|
||||
iLength = GetScanNP(pScan);
|
||||
fAxis = (float *)malloc((iLength+1)*sizeof(float));
|
||||
iAxis = (int *)malloc((iLength+1)*sizeof(int));
|
||||
if( (!fAxis) || (!iAxis))
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
iAxis[0] = htonl(iLength);
|
||||
GetSoftScanVar(pScan,0,fAxis,iLength);
|
||||
GetScanVarName(pScan,0,pName,39);
|
||||
sprintf(pBueffel,"arrowaxis_%s",pName);
|
||||
for(i = 0 ; i < iLength; i++)
|
||||
{
|
||||
iAxis[i+1] = htonl((int)(fAxis[i]*65536.));
|
||||
}
|
||||
/* send new axis to client */
|
||||
SCWrite(pCon,"SCANClear",eError);
|
||||
SCWriteUUencoded(pCon,pBueffel,iAxis,
|
||||
(iLength+1)*sizeof(int));
|
||||
free(iAxis);
|
||||
free(fAxis);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
/*------------------------------------------------------------------------*/
|
||||
static int ScanPointCallback(int iEvent, void *pEvent, void *pUser)
|
||||
{
|
||||
long *lData = NULL;
|
||||
int *iData = NULL;
|
||||
int iLength, iRet, i;
|
||||
SConnection *pCon = (SConnection *)pUser;
|
||||
pScanData pScan = (pScanData)pEvent;
|
||||
|
||||
assert(pCon);
|
||||
assert(pScan);
|
||||
|
||||
|
||||
if( (iEvent == SCANPOINT) || (iEvent == SCANEND) )
|
||||
{
|
||||
/* send current data */
|
||||
iTOF = 0;
|
||||
iLength = GetScanNP(pScan);
|
||||
lData = (long *)malloc((iLength+1)*sizeof(long));
|
||||
iData = (int *)malloc((iLength+1)*sizeof(int));
|
||||
if( (!lData) || (!iData))
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
iData[0] = htonl(iLength);
|
||||
GetScanCounts(pScan,lData,iLength);
|
||||
for(i = 0 ; i < iLength; i++)
|
||||
{
|
||||
iData[i+1] = htonl((int)(lData[i]));
|
||||
}
|
||||
/* send counts to client */
|
||||
SCWriteUUencoded(pCon,"arrow_spinupup",iData,
|
||||
(iLength+1)*sizeof(int));
|
||||
/* send counts for other detector */
|
||||
GetScanMonitor(pScan,2,lData,iLength);
|
||||
for(i = 0 ; i < iLength; i++)
|
||||
{
|
||||
iData[i+1] = htonl((int)(lData[i]));
|
||||
}
|
||||
SCWriteUUencoded(pCon,"arrow_spinuplo",iData,
|
||||
(iLength+1)*sizeof(int));
|
||||
/* to do: check for polarization and send spinlo */
|
||||
free(iData);
|
||||
free(lData);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
/*------------------------------------------------------------------------*/
|
||||
static int SendLoadedData(pAmorStat self, SConnection *pCon)
|
||||
{
|
||||
int i, iRet, *iData = NULL;
|
||||
char pBueffel[80];
|
||||
UserData ud;
|
||||
|
||||
SCWrite(pCon,"loaded_CLEAR",eValue);
|
||||
iRet = LLDnodePtr2First(self->iUserList);
|
||||
while(iRet != 0)
|
||||
{
|
||||
LLDnodeDataTo(self->iUserList,&ud);
|
||||
iData = (int *)malloc((ud.iNP*2 + 1)*sizeof(int));
|
||||
if(!iData)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
iData[0] = htonl(ud.iNP);
|
||||
for(i = 0; i < ud.iNP; i++)
|
||||
{
|
||||
iData[i+1] = htonl((int)(ud.fX[i]*65536));
|
||||
iData[i+1+ud.iNP] = htonl((int)(ud.fY[i]*65536));
|
||||
}
|
||||
sprintf(pBueffel,"loaded_%s",ud.name);
|
||||
SCWriteUUencoded(pCon,pBueffel,iData,(ud.iNP*2+1)*sizeof(int));
|
||||
iRet = LLDnodePtr2Next(self->iUserList);
|
||||
}
|
||||
}
|
||||
/*------------------------------------------------------------------------*/
|
||||
static int LoadCallback(int iEvent, void *pEvent, void *pUser)
|
||||
{
|
||||
pAmorStat pAS = NULL;
|
||||
SConnection *pCon = NULL;
|
||||
|
||||
if(iEvent == FILELOADED)
|
||||
{
|
||||
pAS = (pAmorStat)pEvent;
|
||||
pCon = (SConnection *)pUser;
|
||||
assert(pAS);
|
||||
assert(pCon);
|
||||
SendLoadedData(pAS,pCon);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
/*-------------------------------------------------------------------------*/
|
||||
static void ClearUserData(pAmorStat self)
|
||||
{
|
||||
int iRet;
|
||||
UserData ud;
|
||||
|
||||
iRet = LLDnodePtr2First(self->iUserList);
|
||||
while(iRet != 0)
|
||||
{
|
||||
LLDnodeDataTo(self->iUserList,&ud);
|
||||
if(ud.fX != NULL)
|
||||
free(ud.fX);
|
||||
if(ud.fY != NULL)
|
||||
free(ud.fY);
|
||||
if(ud.name != NULL)
|
||||
free(ud.name);
|
||||
iRet = LLDnodePtr2Next(self->iUserList);
|
||||
}
|
||||
LLDdelete(self->iUserList);
|
||||
self->iUserList = LLDcreate(sizeof(UserData));
|
||||
}
|
||||
/*----------------------------------------------------------------------*/
|
||||
void KillAmorStatus(void *pData)
|
||||
{
|
||||
pAmorStat self = (pAmorStat)pData;
|
||||
|
||||
if(!self)
|
||||
return;
|
||||
|
||||
if(self->iUserList >= 0)
|
||||
{
|
||||
ClearUserData(self);
|
||||
LLDdelete(self->iUserList);
|
||||
}
|
||||
if(self->pDes)
|
||||
DeleteDescriptor(self->pDes);
|
||||
if(self->pCall)
|
||||
DeleteCallBackInterface(self->pCall);
|
||||
free(self);
|
||||
}
|
||||
/*------------------------------------------------------------------*/
|
||||
int AmorStatusFactory(SConnection *pCon, SicsInterp *pSics,
|
||||
void *pData, int argc, char *argv[])
|
||||
{
|
||||
pAmorStat pNew = NULL;
|
||||
CommandList *pCom = NULL;
|
||||
char pBueffel[256];
|
||||
int iRet;
|
||||
|
||||
/* check number of arguments */
|
||||
if(argc < 4)
|
||||
{
|
||||
sprintf(pBueffel,"ERROR: insufficient number of arguments to %s",
|
||||
argv[0]);
|
||||
SCWrite(pCon,pBueffel,eError);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* allocate a new data structure */
|
||||
pNew = (pAmorStat)malloc(sizeof(AmorStat));
|
||||
if(!pNew)
|
||||
{
|
||||
sprintf(pBueffel,"ERROR: out of memory in %s",argv[0]);
|
||||
SCWrite(pCon,pBueffel,eError);
|
||||
return 0;
|
||||
}
|
||||
memset(pNew,0,sizeof(AmorStat));
|
||||
pNew->pDes = CreateDescriptor("AmorStatus");
|
||||
pNew->iUserList = LLDcreate(sizeof(UserData));
|
||||
pNew->pCall = CreateCallBackInterface();
|
||||
if( (!pNew->pDes) || (pNew->iUserList < 0) || (!pNew->pCall) )
|
||||
{
|
||||
sprintf(pBueffel,"ERROR: out of memory in %s",argv[0]);
|
||||
SCWrite(pCon,pBueffel,eError);
|
||||
KillAmorStatus(pNew);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* to locate the HM and the scan object */
|
||||
pCom = FindCommand(pSics,argv[2]);
|
||||
if(pCom)
|
||||
{
|
||||
if(pCom->pData)
|
||||
{
|
||||
if(!iHasType(pCom->pData,"ScanObject"))
|
||||
{
|
||||
sprintf(pBueffel,"ERROR: %s is NO scan object",argv[2]);
|
||||
SCWrite(pCon,pBueffel,eError);
|
||||
KillAmorStatus(pNew);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
sprintf(pBueffel,"ERROR: %s is NO scan object",argv[2]);
|
||||
SCWrite(pCon,pBueffel,eError);
|
||||
KillAmorStatus(pNew);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
sprintf(pBueffel,"ERROR: %s NOT found",argv[2]);
|
||||
SCWrite(pCon,pBueffel,eError);
|
||||
KillAmorStatus(pNew);
|
||||
return 0;
|
||||
}
|
||||
pNew->pScan = (pScanData)pCom->pData;
|
||||
pCom = FindCommand(pSics,argv[3]);
|
||||
if(pCom)
|
||||
{
|
||||
if(pCom->pData)
|
||||
{
|
||||
if(!iHasType(pCom->pData,"HistMem"))
|
||||
{
|
||||
sprintf(pBueffel,"ERROR: %s is NO histogram memory object",
|
||||
argv[3]);
|
||||
SCWrite(pCon,pBueffel,eError);
|
||||
KillAmorStatus(pNew);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
sprintf(pBueffel,"ERROR: %s is NO histogram memory object",
|
||||
argv[3]);
|
||||
SCWrite(pCon,pBueffel,eError);
|
||||
KillAmorStatus(pNew);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
sprintf(pBueffel,"ERROR: %s NOT found",argv[3]);
|
||||
SCWrite(pCon,pBueffel,eError);
|
||||
KillAmorStatus(pNew);
|
||||
return 0;
|
||||
}
|
||||
pNew->pHM = (pHistMem)pCom->pData;
|
||||
pHMHM = (pHistMem)pCom->pData;
|
||||
|
||||
/* install command */
|
||||
iRet = AddCommand(pSics,argv[1],
|
||||
AmorStatusAction,KillAmorStatus,pNew);
|
||||
if(!iRet)
|
||||
{
|
||||
sprintf(pBueffel,"ERROR: duplicate command %s NOT created",
|
||||
argv[1]);
|
||||
SCWrite(pCon,pBueffel,eError);
|
||||
KillAmorStatus(pNew);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
return 1;
|
||||
}
|
||||
/*------------------------------------------------------------------*/
|
||||
static int RegisterInterest(pAmorStat self, SConnection *pCon)
|
||||
{
|
||||
long lID;
|
||||
pDummy pDum = NULL;
|
||||
pICallBack pCall = NULL;
|
||||
|
||||
assert(self);
|
||||
assert(pCon);
|
||||
|
||||
/* Register all the callbacks. Dependent on the state of
|
||||
iTOF invoke the apropriate callbacks in order to force
|
||||
an initial update.
|
||||
*/
|
||||
/* file load callback */
|
||||
lID = RegisterCallback(self->pCall, FILELOADED, LoadCallback,
|
||||
pCon, NULL);
|
||||
SCRegister(pCon,pServ->pSics, self->pCall,lID);
|
||||
SendLoadedData(self,pCon);
|
||||
|
||||
/* scan object */
|
||||
pDum = (pDummy)self->pScan;
|
||||
pCall = pDum->pDescriptor->GetInterface(pDum,CALLBACKINTERFACE);
|
||||
if(pCall)
|
||||
{
|
||||
lID = RegisterCallback(pCall,SCANSTART,ScanStartCallback,
|
||||
pCon, NULL);
|
||||
SCRegister(pCon,pServ->pSics,pCall,lID);
|
||||
lID = RegisterCallback(pCall,SCANPOINT,ScanPointCallback,
|
||||
pCon, NULL);
|
||||
SCRegister(pCon,pServ->pSics,pCall,lID);
|
||||
lID = RegisterCallback(pCall,SCANEND,ScanPointCallback,
|
||||
pCon, NULL);
|
||||
SCRegister(pCon,pServ->pSics,pCall,lID);
|
||||
if(iTOF == 0)
|
||||
{
|
||||
ScanStartCallback(SCANSTART,pDum,pCon);
|
||||
ScanPointCallback(SCANPOINT,pDum,pCon);
|
||||
}
|
||||
}
|
||||
pDum = (pDummy)self->pHM;
|
||||
pCall = pDum->pDescriptor->GetInterface(pDum,CALLBACKINTERFACE);
|
||||
if(pCall)
|
||||
{
|
||||
lID = RegisterCallback(pCall,COUNTSTART,HMCountStartCallback,
|
||||
pCon, NULL);
|
||||
SCRegister(pCon,pServ->pSics,pCall,lID);
|
||||
if(iTOF == 1)
|
||||
{
|
||||
HMCountStartCallback(COUNTSTART,pDum,pCon);
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
/*-----------------------------------------------------------------*/
|
||||
static int FileLoad(pAmorStat self, SConnection *pCon,
|
||||
char *name, double dScale)
|
||||
{
|
||||
char pBueffel[256], pDummy[50];
|
||||
FILE *fd = NULL;
|
||||
UserData ud;
|
||||
int iNP, i;
|
||||
float fDummy;
|
||||
|
||||
/* open the file */
|
||||
fd = fopen(name,"r");
|
||||
if(!fd)
|
||||
{
|
||||
sprintf(pBueffel,"ERROR: cannot open %s for reading",name);
|
||||
SCWrite(pCon,pBueffel,eError);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* skip first line */
|
||||
if(fgets(pBueffel,255,fd) == NULL)
|
||||
{
|
||||
SCWrite(pCon,"ERROR: premature end of file",eError);
|
||||
fclose(fd);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* read number of points in second line */
|
||||
if(fgets(pBueffel,255,fd) == NULL)
|
||||
{
|
||||
SCWrite(pCon,"ERROR: premature end of file",eError);
|
||||
fclose(fd);
|
||||
return 0;
|
||||
}
|
||||
sscanf(pBueffel,"%s %d",pDummy, &iNP);
|
||||
/* allocate data */
|
||||
ud.iNP = iNP;
|
||||
ud.fX = (float *)malloc(iNP*sizeof(float));
|
||||
ud.fY = (float *)malloc(iNP*sizeof(float));
|
||||
ud.name = strdup(name);
|
||||
|
||||
/* skip two lines */
|
||||
if(fgets(pBueffel,255,fd) == NULL)
|
||||
{
|
||||
SCWrite(pCon,"ERROR: premature end of file",eError);
|
||||
fclose(fd);
|
||||
return 0;
|
||||
}
|
||||
if(fgets(pBueffel,255,fd) == NULL)
|
||||
{
|
||||
SCWrite(pCon,"ERROR: premature end of file",eError);
|
||||
fclose(fd);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* loop reading data */
|
||||
for(i = 0; i < iNP; i++)
|
||||
{
|
||||
if(fgets(pBueffel,255,fd) == NULL)
|
||||
{
|
||||
SCWrite(pCon,"WARNING: premature end of file",eError);
|
||||
break;
|
||||
}
|
||||
sscanf(pBueffel," %f %f %f",&ud.fX[i],&fDummy, &ud.fY[i]);
|
||||
ud.fY[i] *= dScale;
|
||||
}
|
||||
fclose(fd);
|
||||
|
||||
/* enter ud into list */
|
||||
LLDnodeInsertFrom(self->iUserList,&ud);
|
||||
|
||||
return 1;
|
||||
}
|
||||
/*-----------------------------------------------------------------
|
||||
Collapse creates a 2D image from the detector by summing all time
|
||||
channels together in any given detector.
|
||||
*/
|
||||
|
||||
static int Collapse(pAmorStat self, SConnection *pCon)
|
||||
{
|
||||
HistInt *lData = NULL;
|
||||
int i, i2, i3, iDim[MAXDIM], iIdx, iSum, status, length;
|
||||
int *iImage = NULL, *iPtr;
|
||||
pSINQHM pHist;
|
||||
SinqHMDriv *pTata;
|
||||
int iMax = -999999;
|
||||
|
||||
/* get size of our problem */
|
||||
GetHistDim(self->pHM,iDim,&i3);
|
||||
/* assert(i3 == 3); */
|
||||
|
||||
/* allocate some data */
|
||||
length = 2 + iDim[0]*iDim[1];
|
||||
iImage = (int *)malloc(length*sizeof(int));
|
||||
if(iImage == NULL)
|
||||
{
|
||||
SCWrite(pCon,"ERROR: failed to allocate memory in Collapse",eError);
|
||||
return 0;
|
||||
}
|
||||
memset(iImage,0,(2 + iDim[0]*iDim[1])*sizeof(int));
|
||||
|
||||
/* first two numbers are the dimension of the image */
|
||||
iImage[0] = htonl(iDim[0]);
|
||||
iImage[1] = htonl(iDim[1]);
|
||||
|
||||
|
||||
if(isSINQHMDriv(self->pHM->pDriv))
|
||||
{
|
||||
/*
|
||||
send a Project request to the histogram memory
|
||||
*/
|
||||
pTata = (SinqHMDriv *)self->pHM->pDriv->pPriv;
|
||||
pHist = (pSINQHM)pTata->pMaster;
|
||||
/*
|
||||
The 3 in the following call has to be identical to
|
||||
PROJECT__COLL in sinqhm_def.h
|
||||
*/
|
||||
status = SINQHMProject(pHist, 3, 0, iDim[0],
|
||||
0, iDim[1], iImage+2, (length-2)*sizeof(int));
|
||||
/*
|
||||
Byte swapping
|
||||
*/
|
||||
for(i = 2; i < length; i++)
|
||||
{
|
||||
/*
|
||||
if(iImage[i] > iMax){
|
||||
iMax = iImage[i];
|
||||
}
|
||||
*/
|
||||
iImage[i] = htonl(iImage[i]);
|
||||
}
|
||||
/*
|
||||
printf("Collapsed maximum: %d\n",iMax);
|
||||
*/
|
||||
if(status != 1)
|
||||
{
|
||||
SCWrite(pCon,"ERROR: histogram memory refused to Collapse",eError);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/*
|
||||
we are in simulation and just create some random numbers
|
||||
*/
|
||||
for(i = 0; i < iDim[0]; i++)
|
||||
{
|
||||
for(i2 = 0; i2 < iDim[1]; i2++)
|
||||
{
|
||||
iIdx = i*iDim[1] + i2;
|
||||
iImage[iIdx+2] = htonl(random());
|
||||
/* iImage[iIdx+2] = htonl(77);*/
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* send image */
|
||||
SCWriteUUencoded(pCon,"arrow_image",iImage,
|
||||
((iDim[0]*iDim[1])+2)*sizeof(int));
|
||||
free(iImage);
|
||||
return 1;
|
||||
}
|
||||
/*-----------------------------------------------------------------
|
||||
SendSingleTOF sends single detector data for TOF mode
|
||||
*/
|
||||
|
||||
static int SendSingleTOF(pAmorStat self, SConnection *pCon)
|
||||
{
|
||||
HistInt *lData = NULL;
|
||||
int i, i2, i3, iDim[MAXDIM], iIdx, iSum, status, length, nTime;
|
||||
pSINQHM pHist;
|
||||
SinqHMDriv *pTata;
|
||||
int iMax = -999999;
|
||||
const float *timebin;
|
||||
HistInt *iData = NULL;
|
||||
int iStart;
|
||||
|
||||
/* get size of our problem */
|
||||
GetHistDim(self->pHM,iDim,&i3);
|
||||
|
||||
/* allocate some data */
|
||||
timebin = GetHistTimeBin(self->pHM, &nTime);
|
||||
if(nTime < 2) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
length = 1 + 2*nTime;
|
||||
iData = (HistInt *)malloc(length*sizeof(HistInt));
|
||||
if(iData == NULL){
|
||||
SCWrite(pCon,"ERROR: failed to allocate memory in SendSingleTOF",
|
||||
eError);
|
||||
return 0;
|
||||
}
|
||||
memset(iData,0,length*sizeof(int));
|
||||
|
||||
/* first number is the length of each single histogram */
|
||||
iData[0] = htonl(nTime);
|
||||
|
||||
|
||||
if(isSINQHMDriv(self->pHM->pDriv))
|
||||
{
|
||||
iStart = iDim[0]*iDim[1]*nTime;
|
||||
GetHistogramDirect(self->pHM,pCon,0,iStart,
|
||||
iStart + 2*nTime,&iData[1],2*nTime*sizeof(HistInt));
|
||||
for(i = 1; i < length; i++)
|
||||
{
|
||||
iData[i] = htonl(iData[i]);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/*
|
||||
we are in simulation and just create some random numbers
|
||||
*/
|
||||
for(i = 1; i < length; i++)
|
||||
{
|
||||
iData[i] = htonl(random());
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
send, with a little trick to do two histograms.
|
||||
*/
|
||||
SCWriteUUencoded(pCon,"SING1",iData,
|
||||
(nTime+1)*sizeof(int));
|
||||
iData[nTime] = htonl(nTime);
|
||||
SCWriteUUencoded(pCon,"SING2",&iData[nTime],
|
||||
(nTime+1)*sizeof(int));
|
||||
free(iData);
|
||||
return 1;
|
||||
}
|
||||
/*-------------------------------------------------------------------
|
||||
SubSample sums histogram data in the area defined by the rectangle
|
||||
x1,y1 x2, y2. Summing is along the time axis.
|
||||
*/
|
||||
static int SubSample(pAmorStat self, SConnection *pCon,
|
||||
char *name, int x1, int x2, int y1, int y2)
|
||||
{
|
||||
int iDim[MAXDIM], i, i2, i3, *iSum = NULL, iLang, *iPtr;
|
||||
HistInt *lData = NULL;
|
||||
int iLimit, status, nTime;
|
||||
char pBueffel[132];
|
||||
pSINQHM pHist;
|
||||
SinqHMDriv *pTata;
|
||||
const float *fTime;
|
||||
|
||||
/* get histogram dimensions */
|
||||
GetHistDim(self->pHM,iDim,&i3);
|
||||
fTime = GetHistTimeBin(self->pHM,&nTime);
|
||||
iDim[i3] = nTime;
|
||||
i3++;
|
||||
assert(i3 == 3);
|
||||
|
||||
/* check limits */
|
||||
if(x2 < x1){
|
||||
i = x1;
|
||||
x1 = x2;
|
||||
x2 = i +1;
|
||||
}
|
||||
if(y2 < y1){
|
||||
i = y1;
|
||||
y1 = y2;
|
||||
y2 = i + 1;
|
||||
}
|
||||
|
||||
iLimit = 0;
|
||||
if( x1 > iDim[0])
|
||||
{
|
||||
iLimit = 1;
|
||||
x1 = iDim[0] - 1;
|
||||
}
|
||||
if(x1 < 0)
|
||||
{
|
||||
iLimit = 1;
|
||||
x1 = 0;
|
||||
}
|
||||
if( x2 > iDim[0])
|
||||
{
|
||||
iLimit = 2;
|
||||
x2 = iDim[0] - 1;
|
||||
}
|
||||
if(x2 < 0)
|
||||
{
|
||||
iLimit = 2;
|
||||
x2 = 0;
|
||||
}
|
||||
if( y1 > iDim[1])
|
||||
{
|
||||
iLimit = 3;
|
||||
y1 = iDim[1] - 1;
|
||||
}
|
||||
if(y1 < 0)
|
||||
{
|
||||
iLimit = 3;
|
||||
y1 = 0;
|
||||
}
|
||||
if( y2 > iDim[1])
|
||||
{
|
||||
iLimit = 4;
|
||||
y2 = iDim[1] - 1;
|
||||
}
|
||||
if(y2 < 0)
|
||||
{
|
||||
iLimit = 4;
|
||||
y2 = 0;
|
||||
}
|
||||
if(iLimit != 0)
|
||||
{
|
||||
switch(iLimit)
|
||||
{
|
||||
case 1:
|
||||
strcpy(pBueffel,"WARNING: limit violation on x1");
|
||||
break;
|
||||
case 2:
|
||||
strcpy(pBueffel,"WARNING: limit violation on x2");
|
||||
break;
|
||||
case 3:
|
||||
strcpy(pBueffel,"WARNING: limit violation on y1");
|
||||
break;
|
||||
case 4:
|
||||
strcpy(pBueffel,"WARNING: limit violation on y2");
|
||||
break;
|
||||
}
|
||||
SCWrite(pCon,pBueffel,eWarning);
|
||||
}
|
||||
|
||||
/* allocate space for result */
|
||||
iSum = (int *)malloc((iDim[2]+1)*sizeof(int));
|
||||
if(!iSum)
|
||||
{
|
||||
SCWrite(pCon,"ERROR: out of memory in SubSample",eError);
|
||||
return 0;
|
||||
}
|
||||
memset(iSum,0,(iDim[2]+1)*sizeof(int));
|
||||
|
||||
iSum[0] = htonl(iDim[2]);
|
||||
if(isSINQHMDriv(self->pHM->pDriv))
|
||||
{
|
||||
/*
|
||||
send project message to histogram memory
|
||||
*/
|
||||
pTata = (SinqHMDriv *)self->pHM->pDriv->pPriv;
|
||||
pHist = (pSINQHM)pTata->pMaster;
|
||||
status = SINQHMProject(pHist, 4, x1, x2-x1,
|
||||
y1, y2-y1, iSum+1, iDim[2]*sizeof(int));
|
||||
/*
|
||||
convert to network byte order
|
||||
*/
|
||||
for(i = 1; i < iDim[2]+1; i++)
|
||||
{
|
||||
iSum[i] = htonl(iSum[i]);
|
||||
}
|
||||
if(status != 1)
|
||||
{
|
||||
SCWrite(pCon,"ERROR: histogram memory refused to SubSample",eError);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* do acouple of random numbers! */
|
||||
for(i = 1; i < iDim[2]+1; i++)
|
||||
{
|
||||
iSum[i] = htonl(random());
|
||||
}
|
||||
}
|
||||
|
||||
/* send */
|
||||
sprintf(pBueffel,"arrowsum_%s",name);
|
||||
SCWriteUUencoded(pCon,pBueffel,iSum,(iDim[2]+1)*sizeof(int));
|
||||
|
||||
free(iSum);
|
||||
return 1;
|
||||
}
|
||||
/*------------------------------------------------------------------*/
|
||||
int AmorStatusAction(SConnection *pCon, SicsInterp *pSics,
|
||||
void *pData, int argc, char *argv[])
|
||||
{
|
||||
pAmorStat self = (pAmorStat)pData;
|
||||
char pBueffel[512];
|
||||
double dScale;
|
||||
int iRet;
|
||||
int x1, x2, y1, y2;
|
||||
|
||||
assert(self);
|
||||
|
||||
if(argc < 2)
|
||||
{
|
||||
sprintf(pBueffel,"ERROR: need argument to %s",argv[0]);
|
||||
SCWrite(pCon,pBueffel,eError);
|
||||
return 0;
|
||||
}
|
||||
|
||||
strtolower(argv[1]);
|
||||
if(strcmp(argv[1],"interest") == 0)
|
||||
{
|
||||
RegisterInterest(self,pCon);
|
||||
SCSendOK(pCon);
|
||||
return 1;
|
||||
}
|
||||
else if(strcmp(argv[1],"load") == 0)
|
||||
{
|
||||
if(argc < 4)
|
||||
{
|
||||
sprintf(pBueffel,
|
||||
"ERROR: need filename and scale argument to %s load",
|
||||
argv[0]);
|
||||
SCWrite(pCon,pBueffel,eError);
|
||||
return 0;
|
||||
}
|
||||
iRet = Tcl_GetDouble(pSics->pTcl,argv[3],&dScale);
|
||||
if(iRet != TCL_OK)
|
||||
{
|
||||
sprintf(pBueffel,"ERROR: cannot convert %s to scale factor",
|
||||
argv[3]);
|
||||
SCWrite(pCon,pBueffel,eError);
|
||||
return 0;
|
||||
}
|
||||
FileLoad(self,pCon,argv[2],dScale);
|
||||
InvokeCallBack(self->pCall, FILELOADED,self);
|
||||
SCSendOK(pCon);
|
||||
}
|
||||
else if(strcmp(argv[1],"collapse") == 0)
|
||||
{
|
||||
iRet = Collapse(self,pCon);
|
||||
if(iRet)
|
||||
{
|
||||
SCSendOK(pCon);
|
||||
}
|
||||
return iRet;
|
||||
}
|
||||
else if(strcmp(argv[1],"sample") == 0)
|
||||
{
|
||||
if(argc < 7)
|
||||
{
|
||||
SCWrite(pCon,"ERROR: insufficent number of arguments to sample",
|
||||
eError);
|
||||
return 0;
|
||||
}
|
||||
iRet = Tcl_GetInt(pSics->pTcl,argv[3],&x1);
|
||||
if(iRet != TCL_OK)
|
||||
{
|
||||
sprintf(pBueffel,"ERROR: cannot convert %s to int", argv[3]);
|
||||
SCWrite(pCon,pBueffel,eError);
|
||||
return 0;
|
||||
}
|
||||
iRet = Tcl_GetInt(pSics->pTcl,argv[6],&y2);
|
||||
if(iRet != TCL_OK)
|
||||
{
|
||||
sprintf(pBueffel,"ERROR: cannot convert %s to int", argv[6]);
|
||||
SCWrite(pCon,pBueffel,eError);
|
||||
return 0;
|
||||
}
|
||||
iRet = Tcl_GetInt(pSics->pTcl,argv[4],&x2);
|
||||
if(iRet != TCL_OK)
|
||||
{
|
||||
sprintf(pBueffel,"ERROR: cannot convert %s to int", argv[4]);
|
||||
SCWrite(pCon,pBueffel,eError);
|
||||
return 0;
|
||||
}
|
||||
iRet = Tcl_GetInt(pSics->pTcl,argv[5],&y1);
|
||||
if(iRet != TCL_OK)
|
||||
{
|
||||
sprintf(pBueffel,"ERROR: cannot convert %s to int", argv[5]);
|
||||
SCWrite(pCon,pBueffel,eError);
|
||||
return 0;
|
||||
}
|
||||
iRet = SubSample(self,pCon,argv[2],x1,x2,y1,y2);
|
||||
if(iRet)
|
||||
SCSendOK(pCon);
|
||||
return iRet;
|
||||
}
|
||||
else if(strcmp(argv[1],"singletof") == 0)
|
||||
{
|
||||
return SendSingleTOF(self,pCon);
|
||||
}
|
||||
else if(strcmp(argv[1],"sendloaded") == 0)
|
||||
{
|
||||
SendLoadedData(self,pCon);
|
||||
return 1;
|
||||
}
|
||||
else if(strcmp(argv[1],"clear") == 0)
|
||||
{
|
||||
ClearUserData(self);
|
||||
InvokeCallBack(self->pCall, FILELOADED,self);
|
||||
SCSendOK(pCon);
|
||||
}
|
||||
else if(strcmp(argv[1],"tofmode") == 0)
|
||||
{
|
||||
HMCountStartCallback(COUNTSTART,NULL,pCon);
|
||||
return 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
sprintf(pBueffel,"ERROR: %s nor recognized as subcommand to %s",
|
||||
argv[1], argv[2]);
|
||||
SCWrite(pCon,pBueffel,eError);
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
21
amorstat.h
Normal file
21
amorstat.h
Normal file
@ -0,0 +1,21 @@
|
||||
|
||||
/*------------------------------------------------------------------------
|
||||
A M O R S T A T U S
|
||||
|
||||
Public definitions for the AMOR status display
|
||||
facilitator object. DO NOT CHANGE. This file is automatically
|
||||
created from amorstat.w.
|
||||
|
||||
Mark Koennecke, September 1999
|
||||
---------------------------------------------------------------------*/
|
||||
#ifndef AMORSTATUS
|
||||
#define AMORSTATUS
|
||||
|
||||
int AmorStatusFactory(SConnection *pCon, SicsInterp *pSics, void *pData,
|
||||
int argc, char *argv[]);
|
||||
int AmorStatusAction(SConnection *pCon, SicsInterp *pSics, void *pData,
|
||||
int argc, char *argv[]);
|
||||
void KillAmorStatus(void *pData);
|
||||
|
||||
#endif
|
||||
|
29
amorstat.i
Normal file
29
amorstat.i
Normal file
@ -0,0 +1,29 @@
|
||||
|
||||
/*------------------------------------------------------------------------
|
||||
A M O R S T A T U S
|
||||
|
||||
Internal data structure definitions for the AMOR status display
|
||||
facilitator object. DO NOT CHANGE. This file is automatically
|
||||
created from amorstat.w.
|
||||
|
||||
Mark Koennecke, September 1999
|
||||
---------------------------------------------------------------------*/
|
||||
|
||||
/*---------------------------------------------------------------------*/
|
||||
typedef struct {
|
||||
float *fX, *fY;
|
||||
int iNP;
|
||||
char *name;
|
||||
}UserData, *pUserData;
|
||||
/*---------------------------------------------------------------------*/
|
||||
typedef struct __AMORSTAT {
|
||||
pObjectDescriptor pDes;
|
||||
pICallBack pCall;
|
||||
int iUserList;
|
||||
pScanData pScan;
|
||||
pHistMem pHM;
|
||||
int iTOF;
|
||||
}AmorStat, *pAmorStat;
|
||||
|
||||
|
||||
|
138
amorstat.tex
Normal file
138
amorstat.tex
Normal file
@ -0,0 +1,138 @@
|
||||
\subsection{Amor Status Display Support}
|
||||
The reflectometer AMOR has a few unique status display requirements:
|
||||
\begin{itemize}
|
||||
\item In scan mode up to four detector counts curves must be shown for
|
||||
the two counters in spin-up or spin-down mode. This needs to be
|
||||
updated after each scan point.
|
||||
\item Additionally user defined curves may need to be displayed.
|
||||
\item The usual helper information muste be displayed.
|
||||
\item In TOF mode it must be possible to define a region on the
|
||||
detector whose summed counts are displayed versus the time
|
||||
binning. This must be sent on request.
|
||||
\end{itemize}
|
||||
In order to cover all this a special object within SICS is required
|
||||
which deals with all this and packages information in a status display
|
||||
compliant way.
|
||||
|
||||
In order to do this the amorstatus object registers callbacks both
|
||||
with the histogram memory and the scan object. These callback
|
||||
functions are then responsible for updating the status displays. In
|
||||
order for amorstatus to be able to do this, the client must register
|
||||
itself with a special command.
|
||||
|
||||
In order to achieve all this some data structures are needed:
|
||||
\begin{flushleft} \small
|
||||
\begin{minipage}{\linewidth} \label{scrap1}
|
||||
$\langle$asdata {\footnotesize ?}$\rangle\equiv$
|
||||
\vspace{-1ex}
|
||||
\begin{list}{}{} \item
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@/*---------------------------------------------------------------------*/@\\
|
||||
\mbox{}\verb@ typedef struct {@\\
|
||||
\mbox{}\verb@ float *fX, *fY;@\\
|
||||
\mbox{}\verb@ int iNP;@\\
|
||||
\mbox{}\verb@ char *name;@\\
|
||||
\mbox{}\verb@ }UserData, *pUserData; @\\
|
||||
\mbox{}\verb@/*---------------------------------------------------------------------*/@\\
|
||||
\mbox{}\verb@ typedef struct __AMORSTAT {@\\
|
||||
\mbox{}\verb@ pObjectDescriptor pDes;@\\
|
||||
\mbox{}\verb@ pICallBack pCall;@\\
|
||||
\mbox{}\verb@ int iUserList;@\\
|
||||
\mbox{}\verb@ pScanData pScan;@\\
|
||||
\mbox{}\verb@ pHistMem pHM;@\\
|
||||
\mbox{}\verb@ int iTOF;@\\
|
||||
\mbox{}\verb@ }AmorStat, *pAmorStat;@\\
|
||||
\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}
|
||||
The fourth data structure is the amor status object data structure. It
|
||||
has the following fields:
|
||||
\begin{description}
|
||||
\item[pDes] The standard SICS object descriptor.
|
||||
\item[pCall] The callback interface.
|
||||
\item[iUserList] A list of user data loaded data.
|
||||
\item[pScan] A pointer to the scan object.
|
||||
\item[pHM] A pointer to the histogram memory.
|
||||
\item[iTOF] A flag which is true if we are taking measurements in TOF
|
||||
mode.
|
||||
\end{description}
|
||||
|
||||
In terms of a function interface this object has not much to
|
||||
offer. Its main purpose is really as an interface to the status
|
||||
display clients and thus it is configured through the interpreter
|
||||
interface function. No need for other SICS objects to access it.
|
||||
|
||||
\begin{flushleft} \small
|
||||
\begin{minipage}{\linewidth} \label{scrap2}
|
||||
$\langle$asinter {\footnotesize ?}$\rangle\equiv$
|
||||
\vspace{-1ex}
|
||||
\begin{list}{}{} \item
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@ int AmorStatusFactory(SConnection *pCon, SicsInterp *pSics, void *pData,@\\
|
||||
\mbox{}\verb@ int argc, char *argv[]);@\\
|
||||
\mbox{}\verb@ int AmorStatusAction(SConnection *pCon, SicsInterp *pSics, void *pData,@\\
|
||||
\mbox{}\verb@ int argc, char *argv[]);@\\
|
||||
\mbox{}\verb@ void KillAmorStatus(void *pData);@\\
|
||||
\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}
|
||||
\begin{flushleft} \small
|
||||
\begin{minipage}{\linewidth} \label{scrap3}
|
||||
\verb@"amorstat.i"@ {\footnotesize ? }$\equiv$
|
||||
\vspace{-1ex}
|
||||
\begin{list}{}{} \item
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@/*------------------------------------------------------------------------@\\
|
||||
\mbox{}\verb@ A M O R S T A T U S@\\
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@ Internal data structure definitions for the AMOR status display @\\
|
||||
\mbox{}\verb@ facilitator object. DO NOT CHANGE. This file is automatically@\\
|
||||
\mbox{}\verb@ created from amorstat.w.@\\
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@ Mark Koennecke, September 1999@\\
|
||||
\mbox{}\verb@---------------------------------------------------------------------*/@\\
|
||||
\mbox{}\verb@@$\langle$asdata {\footnotesize ?}$\rangle$\verb@@\\
|
||||
\mbox{}\verb@ @\\
|
||||
\mbox{}\verb@@$\diamond$
|
||||
\end{list}
|
||||
\vspace{-2ex}
|
||||
\end{minipage}\\[4ex]
|
||||
\end{flushleft}
|
||||
\begin{flushleft} \small
|
||||
\begin{minipage}{\linewidth} \label{scrap4}
|
||||
\verb@"amorstat.h"@ {\footnotesize ? }$\equiv$
|
||||
\vspace{-1ex}
|
||||
\begin{list}{}{} \item
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@/*------------------------------------------------------------------------@\\
|
||||
\mbox{}\verb@ A M O R S T A T U S@\\
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@ Public definitions for the AMOR status display @\\
|
||||
\mbox{}\verb@ facilitator object. DO NOT CHANGE. This file is automatically@\\
|
||||
\mbox{}\verb@ created from amorstat.w.@\\
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@ Mark Koennecke, September 1999@\\
|
||||
\mbox{}\verb@---------------------------------------------------------------------*/@\\
|
||||
\mbox{}\verb@#ifndef AMORSTATUS@\\
|
||||
\mbox{}\verb@#define AMORSTATUS@\\
|
||||
\mbox{}\verb@@$\langle$asinter {\footnotesize ?}$\rangle$\verb@@\\
|
||||
\mbox{}\verb@#endif@\\
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@@$\diamond$
|
||||
\end{list}
|
||||
\vspace{-2ex}
|
||||
\end{minipage}\\[4ex]
|
||||
\end{flushleft}
|
102
amorstat.w
Normal file
102
amorstat.w
Normal file
@ -0,0 +1,102 @@
|
||||
\subsection{Amor Status Display Support}
|
||||
The reflectometer AMOR has a few unique status display requirements:
|
||||
\begin{itemize}
|
||||
\item In scan mode up to four detector counts curves must be shown for
|
||||
the two counters in spin-up or spin-down mode. This needs to be
|
||||
updated after each scan point.
|
||||
\item Additionally user defined curves may need to be displayed.
|
||||
\item The usual helper information muste be displayed.
|
||||
\item In TOF mode it must be possible to define a region on the
|
||||
detector whose summed counts are displayed versus the time
|
||||
binning. This must be sent on request.
|
||||
\end{itemize}
|
||||
In order to cover all this a special object within SICS is required
|
||||
which deals with all this and packages information in a status display
|
||||
compliant way.
|
||||
|
||||
In order to do this the amorstatus object registers callbacks both
|
||||
with the histogram memory and the scan object. These callback
|
||||
functions are then responsible for updating the status displays. In
|
||||
order for amorstatus to be able to do this, the client must register
|
||||
itself with a special command.
|
||||
|
||||
In order to achieve all this some data structures are needed:
|
||||
@d asdata @{
|
||||
/*---------------------------------------------------------------------*/
|
||||
typedef struct {
|
||||
float *fX, *fY;
|
||||
int iNP;
|
||||
char *name;
|
||||
}UserData, *pUserData;
|
||||
/*---------------------------------------------------------------------*/
|
||||
typedef struct __AMORSTAT {
|
||||
pObjectDescriptor pDes;
|
||||
pICallBack pCall;
|
||||
int iUserList;
|
||||
pScanData pScan;
|
||||
pHistMem pHM;
|
||||
int iTOF;
|
||||
}AmorStat, *pAmorStat;
|
||||
|
||||
@}
|
||||
|
||||
|
||||
The fourth data structure is the amor status object data structure. It
|
||||
has the following fields:
|
||||
\begin{description}
|
||||
\item[pDes] The standard SICS object descriptor.
|
||||
\item[pCall] The callback interface.
|
||||
\item[iUserList] A list of user data loaded data.
|
||||
\item[pScan] A pointer to the scan object.
|
||||
\item[pHM] A pointer to the histogram memory.
|
||||
\item[iTOF] A flag which is true if we are taking measurements in TOF
|
||||
mode.
|
||||
\end{description}
|
||||
|
||||
In terms of a function interface this object has not much to
|
||||
offer. Its main purpose is really as an interface to the status
|
||||
display clients and thus it is configured through the interpreter
|
||||
interface function. No need for other SICS objects to access it.
|
||||
|
||||
@d asinter @{
|
||||
int AmorStatusFactory(SConnection *pCon, SicsInterp *pSics, void *pData,
|
||||
int argc, char *argv[]);
|
||||
int AmorStatusAction(SConnection *pCon, SicsInterp *pSics, void *pData,
|
||||
int argc, char *argv[]);
|
||||
void KillAmorStatus(void *pData);
|
||||
@}
|
||||
|
||||
|
||||
@o amorstat.i @{
|
||||
/*------------------------------------------------------------------------
|
||||
A M O R S T A T U S
|
||||
|
||||
Internal data structure definitions for the AMOR status display
|
||||
facilitator object. DO NOT CHANGE. This file is automatically
|
||||
created from amorstat.w.
|
||||
|
||||
Mark Koennecke, September 1999
|
||||
---------------------------------------------------------------------*/
|
||||
@<asdata@>
|
||||
|
||||
@}
|
||||
|
||||
@o amorstat.h @{
|
||||
/*------------------------------------------------------------------------
|
||||
A M O R S T A T U S
|
||||
|
||||
Public definitions for the AMOR status display
|
||||
facilitator object. DO NOT CHANGE. This file is automatically
|
||||
created from amorstat.w.
|
||||
|
||||
Mark Koennecke, September 1999
|
||||
---------------------------------------------------------------------*/
|
||||
#ifndef AMORSTATUS
|
||||
#define AMORSTATUS
|
||||
@<asinter@>
|
||||
#endif
|
||||
|
||||
@}
|
||||
|
||||
|
||||
|
358
amortest.tcl
Normal file
358
amortest.tcl
Normal file
@ -0,0 +1,358 @@
|
||||
# --------------------------------------------------------------------------
|
||||
# Initialization script for a simulated AMOR instrument
|
||||
#
|
||||
#
|
||||
# Dr. Mark Koennecke September,1999 - ??, ????
|
||||
#---------------------------------------------------------------------------
|
||||
|
||||
#------------ our home
|
||||
set home /data/koenneck/src/sics
|
||||
|
||||
#----------- first all the server options are set
|
||||
|
||||
ServerOption ReadTimeOut 100
|
||||
# timeout when checking for commands. In the main loop SICS checks for
|
||||
# pending commands on each connection with the above timeout, has
|
||||
# PERFORMANCE impact!
|
||||
|
||||
ServerOption AcceptTimeOut 100
|
||||
# timeout when checking for connection req.
|
||||
# Similar to above, but for connections
|
||||
|
||||
ServerOption ReadUserPasswdTimeout 7000
|
||||
# time to wiat for a user/passwd to be sent from a client. Increase this
|
||||
# if there is a problem connecting to a server due to network overload\
|
||||
|
||||
ServerOption LogFileDir $home/tmp
|
||||
#LogFileDir is the directory where the command log is going
|
||||
|
||||
ServerOption LogFileBaseName $home/tmp/server
|
||||
# the path and base name of the internal server logfile to which all
|
||||
# activity will be logged.
|
||||
|
||||
ServerOption statusfile $home/tmp/sicsstatus.tcl
|
||||
|
||||
ServerOption ServerPort 2911
|
||||
# the port number the server is going to listen at. The client MUST know
|
||||
# this number in order to connect. It is in client.ini
|
||||
|
||||
ServerOption InterruptPort 2914
|
||||
# The UDP port where the server will wait for Interrupts from clients.
|
||||
# Obviously, clients wishing to interrupt need to know this number.
|
||||
|
||||
# Telnet options
|
||||
ServerOption TelnetPort 1301
|
||||
ServerOption TelWord sicslogin
|
||||
|
||||
ServerOption DefaultTclDirectory $home/tcl
|
||||
ServerOption DefaultCommandFile topsicom.tcl
|
||||
|
||||
#------ a port for broadcasting UDP messages
|
||||
ServerOption QuieckPort 2108
|
||||
|
||||
#---------------------------------------------------------------------------
|
||||
# U S E R S
|
||||
|
||||
# than the SICS users are specified
|
||||
# Syntax: SicsUser name password userRightsCode
|
||||
SicsUser Mugger Diethelm 1
|
||||
SicsUser User Rosy 2
|
||||
SicsUser Spy 007 1
|
||||
|
||||
#--------------------------------------------------------------------------
|
||||
# G E N E R A L V A R I A B L E S
|
||||
# now a few general variables are created
|
||||
# Syntax: VarMake name type access
|
||||
# type can be one of: Text, Int, Float
|
||||
#access can be one of: Internal, Mugger, user, Spy
|
||||
|
||||
VarMake Instrument Text Internal
|
||||
Instrument AMOR
|
||||
Instrument lock
|
||||
|
||||
|
||||
|
||||
VarMake Title Text User
|
||||
VarMake sample Text User
|
||||
sample "DanielSulfid"
|
||||
Title "Amore mio in SINQ"
|
||||
VarMake User Text User
|
||||
User The reflective looser
|
||||
|
||||
VarMake lastscancommand Text User
|
||||
|
||||
VarMake Adress Text User
|
||||
VarMake phone Text User
|
||||
VarMake fax Text User
|
||||
VarMake email Text User
|
||||
VarMake sample_mur Float User
|
||||
|
||||
#--------------------------------------------------------------------------
|
||||
# B u i l d i n g B l o c k s
|
||||
#--------------------------------------------------------------------------
|
||||
#
|
||||
#=================== Chopper
|
||||
VarMake chopperrotation Float User
|
||||
chopperrotation 10000.
|
||||
|
||||
ClientPut "Starting motor initialization ....."
|
||||
#=================== frame overlap mirror
|
||||
VarMake fomname Text Mugger
|
||||
fomname Super Duper Mirror
|
||||
fomname lock
|
||||
VarMake fomdist Float Mugger
|
||||
fomdist 120
|
||||
Motor FTZ SIM 0. 120. .1 2. # fom height
|
||||
Motor FOM SIM -30. 30. .1 2. # fom omega
|
||||
|
||||
#================== first diaphragm
|
||||
VarMake d1dist Float Mugger
|
||||
d1dist 200.
|
||||
Motor D1L SIM 0. 120. .1 2. # left
|
||||
Motor D1R SIM 0. 120. .1 2. # right
|
||||
Motor D1T SIM 0. 120. .1 2. # top
|
||||
Motor D1B SIM 0. 1000. .1 2. # bottom
|
||||
|
||||
#================== polarizer
|
||||
VarMake polname Text Mugger
|
||||
polname Daniels Special Edition Polarizer
|
||||
polname lock
|
||||
VarMake poldist Float Mugger
|
||||
fomdist 200
|
||||
Motor MOZ SIM 0. 1000. .1 2. # pol table height
|
||||
Motor MTY SIM -60. 60. .1 2. # pol y movement
|
||||
Motor MOM SIM -30. 30. .1 2. # pol omega
|
||||
Motor MTZ SIM -30. 30. .1 2. # pol omega height
|
||||
|
||||
#=================== diaphragm 2
|
||||
VarMake d2dist Float Mugger
|
||||
d2dist 200.
|
||||
Motor D2L SIM 0. 120. .1 2. # left
|
||||
Motor D2R SIM 0. 120. .1 2. # right
|
||||
Motor D2T SIM 0. 120. .1 2. # top
|
||||
Motor D2B SIM 0. 1000. .1 2. # bottom
|
||||
|
||||
#==================== diaphragm 3
|
||||
VarMake d3dist Float Mugger
|
||||
d3dist 200.
|
||||
Motor D3L SIM 0. 120. .1 2. # left
|
||||
Motor D3R SIM 0. 120. .1 2. # right
|
||||
Motor D3T SIM 0. 120. .1 2. # top
|
||||
Motor D3B SIM 0. 1000. .1 2. # bottom
|
||||
|
||||
#===================== sample table
|
||||
VarMake sampledist Float Mugger
|
||||
sampledist 200
|
||||
Motor STZ SIM -50. 50. .1 2. # sample height
|
||||
Motor SOM SIM -30. 30. .1 2. # sample omega
|
||||
Motor SCH SIM -30. 30. .1 2. # sample chi
|
||||
Motor SOZ SIM 0. 1000. .1 2. # table height
|
||||
|
||||
#====================== diaphragm 4
|
||||
VarMake d4dist Float Mugger
|
||||
d4dist 200.
|
||||
Motor D4L SIM 0. 120. .1 2. # left
|
||||
Motor D4R SIM 0. 120. .1 2. # right
|
||||
Motor D4T SIM 0. 120. .1 2. # top
|
||||
Motor D4B SIM 0. 1000. .1 2. # bottom
|
||||
|
||||
#======================= analyzer
|
||||
VarMake ananame Text Mugger
|
||||
ananame Daniels Special Edition Analyzer
|
||||
ananame lock
|
||||
VarMake anadist Float Mugger
|
||||
anadist 200
|
||||
Motor AOZ SIM 0. 1000. .1 2. # analyzer table height
|
||||
Motor AOM SIM -30. 30. .1 2. # analyzer omega
|
||||
Motor ATZ SIM -30. 30. .1 2. # analyzer omega height
|
||||
|
||||
#======================== diaphragm 5
|
||||
VarMake d5dist Float Mugger
|
||||
d5dist 200.
|
||||
Motor D5L SIM 0. 120. .1 2. # left
|
||||
Motor D5R SIM 0. 120. .1 2. # right
|
||||
Motor D5T SIM 0. 120. .1 2. # top
|
||||
Motor D5B SIM 0. 1000. .1 2. # bottom
|
||||
|
||||
#======================== counter
|
||||
VarMake detectordist Float Mugger
|
||||
detectordist 200.
|
||||
MakeCounter counter SIM .0001
|
||||
Motor COZ SIM 0. 1000. .1 2. # counter table height
|
||||
Motor C3Z SIM 0. 300. .1 2. # counter height
|
||||
Motor COM SIM -30. 30. .1 2. # counter omega
|
||||
Motor COX SIM -100. 100. .1 2. # counter x
|
||||
ClientPut "Motors initialized"
|
||||
|
||||
#======================== histogram memory
|
||||
#MakeHM hm SinqHM
|
||||
MakeHM hm SIM
|
||||
hm configure OverFlowMode Ceil
|
||||
hm configure HistMode PSD
|
||||
hm configure Rank 2
|
||||
hm configure dim0 128
|
||||
hm configure dim1 256
|
||||
hm configure xfac 10
|
||||
hm configure yfac 10
|
||||
hm configure xoff 64
|
||||
hm configure yoff 128
|
||||
hm configure BinWidth 4
|
||||
hm preset 100.
|
||||
hm CountMode Timer
|
||||
hm configure HMComputer psds03.psi.ch
|
||||
hm configure HMPort 2400
|
||||
hm configure Counter counter
|
||||
hm configure init 0
|
||||
hm genbin 0. 33 5
|
||||
hm init
|
||||
|
||||
ClientPut "Histogram Memory Initialized"
|
||||
#--------------------------------------------------------------------------
|
||||
# D a t a S t o r a g e
|
||||
#------------------------------------------------------------------------
|
||||
VarMake SicsDataPath Text Mugger
|
||||
SicsDataPath $home/
|
||||
SicsDataPath lock
|
||||
VarMake SicsDataPrefix Text Mugger
|
||||
SicsDataPrefix amortest
|
||||
SicsDataPrefix lock
|
||||
VarMake SicsDataPostFix Text Mugger
|
||||
SicsDataPostFix ".hdf"
|
||||
SicsDataPostFix lock
|
||||
|
||||
MakeDataNumber SicsDataNumber $home/danu.dat
|
||||
|
||||
|
||||
#--------------------------------------------------------------------------
|
||||
# C o m m a n d I n i t i a l i z a t i o n
|
||||
#-------------------------------------------------------------------------
|
||||
#======== Drive
|
||||
MakeDrive
|
||||
#======== scan
|
||||
source $home/object.tcl
|
||||
source $home/tcl/scancom.tcl
|
||||
MakeScanCommand xxxscan counter topsi.hdd recover.bin
|
||||
xxxscan configure amor
|
||||
#========== peak & center
|
||||
MakePeakCenter xxxscan
|
||||
source /data/koenneck/src/sics/countf.tcl
|
||||
#========== serial port general purpose
|
||||
SerialInit
|
||||
Publish serialport User
|
||||
Publish p1 User
|
||||
#=========== the optimiser
|
||||
MakeOptimise opti counter
|
||||
|
||||
#=========== Amor2T
|
||||
set a2t(mom) mom
|
||||
set a2t(som) som
|
||||
set a2t(coz) coz
|
||||
set a2t(cox) cox
|
||||
set a2t(stz) stz
|
||||
set a2t(soz) soz
|
||||
set a2t(d4b) d4b
|
||||
set a2t(d5b) d5b
|
||||
set a2t(com) com
|
||||
set a2t(aom) aom
|
||||
set a2t(aoz) aoz
|
||||
set a2t(c3z) c3z
|
||||
MakeAmor2T a2t a2t aom2t
|
||||
|
||||
MakeStoreAmor hm a2t
|
||||
|
||||
#=========== Status Display Support
|
||||
MakeAmorStatus amorstatus xxxscan hm
|
||||
source amorpar.tcl
|
||||
Publish amorpar Spy
|
||||
ClientPut "Done Initializing"
|
||||
|
||||
|
||||
scriptcallback connect xxxscan SCANSTART scanmode
|
||||
scriptcallback connect hm COUNTSTART tofmode
|
||||
sicsdatafactory new wwwdata
|
||||
|
||||
Publish getmode Spy
|
||||
Publish wwwgetdata Spy
|
||||
Publish wwwsics Spy
|
||||
Publish wwwgetaxis Spy
|
||||
|
||||
#-----------------------------------------------------------------
|
||||
set mode 0
|
||||
proc tofmode {} {
|
||||
global mode
|
||||
set mode 1
|
||||
}
|
||||
#---------------------------------------------------------------------
|
||||
proc scanmode {} {
|
||||
global mode
|
||||
set mode 0
|
||||
}
|
||||
#------------------------------------------------------------------
|
||||
proc getmode {} {
|
||||
global mode
|
||||
return $mode
|
||||
}
|
||||
#--------------------------------------------------------------------
|
||||
proc wwwgetdata {} {
|
||||
global mode
|
||||
if {$mode == 1} {
|
||||
wwwtofdata
|
||||
} else {
|
||||
wwwscandata
|
||||
}
|
||||
wwwdata writeuu wwwdata
|
||||
}
|
||||
#---------------------------------------------------------------------
|
||||
proc wwwscandata {} {
|
||||
wwwdata clear
|
||||
set np [string trim [SplitReply [xxxscan np]]]
|
||||
wwwdata putint 0 $np
|
||||
if {$np > 0} {
|
||||
wwwdata copyscanvar 1 xxxscan 0
|
||||
wwwdata copyscancounts [expr $np + 1] xxxscan
|
||||
wwwdata copyscanmon [expr $np*2 + 1] xxxscan 2
|
||||
}
|
||||
}
|
||||
#----------------------------------------------------------------------
|
||||
proc wwwtofdata {} {
|
||||
wwwdata clear
|
||||
set ntime [string trim [SplitReply [hm notimebin]]]
|
||||
set dim0 [string trim [SplitReply [hm configure dim0]]]
|
||||
set dim1 [string trim [SplitReply [hm configure dim1]]]
|
||||
wwwdata putint 0 $ntime
|
||||
wwwdata copytimebin 1 hm
|
||||
set start [expr $dim0*$dim1*$ntime]
|
||||
set end [expr $start + 2*$ntime]
|
||||
wwwdata copyhm [expr $ntime + 1] hm $start $end
|
||||
}
|
||||
#---------------------------------------------------------------------------
|
||||
proc wwwsics {} {
|
||||
global mode
|
||||
append result "<table BORDER=2>\n"
|
||||
append result "<tr><th>User</th> <td>" [SplitReply [user]] "</td></tr>\n"
|
||||
append result "<tr><th>Title</th> <td>"
|
||||
append result [SplitReply [title]] "</td></tr>\n"
|
||||
append result "<tr><th>Status</th> <td>"
|
||||
append result [SplitReply [status]] "</td></tr>\n"
|
||||
append result "<tr><th>Mode</th><td>"
|
||||
if {$mode == 1} {
|
||||
append result "time-of-flight"
|
||||
} else {
|
||||
append result "scan mode"
|
||||
}
|
||||
append result "</td></tr>\n"
|
||||
append result "</table>\n"
|
||||
}
|
||||
#-------------------------------------------------------------------------
|
||||
proc wwwgetaxis {} {
|
||||
global mode
|
||||
if {$mode == 1} {
|
||||
return time-of-flight
|
||||
} else {
|
||||
set res [scan info]
|
||||
set l [split $res ,]
|
||||
return [lindex $l 2]
|
||||
}
|
||||
}
|
||||
|
||||
|
374
anticollider.c
Normal file
374
anticollider.c
Normal file
@ -0,0 +1,374 @@
|
||||
/*----------------------------------------------------------------------
|
||||
This is the implementation file for the AntiCollider, a complex movements
|
||||
control module for SICS. See anticollider.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 devised 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);
|
||||
}
|
||||
|
||||
/*
|
||||
kill old collider sequence
|
||||
*/
|
||||
LLDdelete(self->sequenceList);
|
||||
self->sequenceList = LLDcreate(sizeof(Sequence));
|
||||
self->level = -1; /* otherwise level 0 will not be started */
|
||||
|
||||
/*
|
||||
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,usUser)){
|
||||
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
25
anticollider.h
Normal 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
|
||||
|
||||
|
||||
|
28
anticollider.i
Normal file
28
anticollider.i
Normal file
@ -0,0 +1,28 @@
|
||||
|
||||
/*-------------------------------------------------------------------------
|
||||
Anticollider internal data structure definition. Generated from
|
||||
anticollider.w. Do not edit.
|
||||
-------------------------------------------------------------------------*/
|
||||
|
||||
typedef struct __ANTICOLLIDER{
|
||||
pObjectDescriptor pDes;
|
||||
pIDrivable pDriv;
|
||||
int motorList;
|
||||
int sequenceList;
|
||||
char *colliderScript;
|
||||
int isDirty;
|
||||
int level;
|
||||
}AntiCollider, *pAntiCollider;
|
||||
|
||||
|
||||
typedef struct {
|
||||
int level;
|
||||
char pMotor[80];
|
||||
float target;
|
||||
}Sequence;
|
||||
|
||||
int StartLevel(int level, int sequenceList, int motorList,
|
||||
SConnection *pCon);
|
||||
|
||||
|
||||
|
275
anticollider.w
Normal file
275
anticollider.w
Normal 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
|
||||
|
||||
|
||||
|
||||
@}
|
7
ati.tcl
Normal file
7
ati.tcl
Normal file
@ -0,0 +1,7 @@
|
||||
drive mom 3.
|
||||
scan var a2t 0. .2
|
||||
scan var som 0. .1
|
||||
scan preset 1
|
||||
scan mode timer
|
||||
scan np 20
|
||||
scan run
|
46
author.txt
Normal file
46
author.txt
Normal file
@ -0,0 +1,46 @@
|
||||
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 <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <assert.h>
|
||||
#include <math.h>
|
||||
#include <tcl.h>
|
||||
#include "fortify.h"
|
||||
#include "lld.h"
|
||||
#include "lld_blob.h"
|
||||
#include "lld_str.h"
|
||||
#include "conman.h"
|
||||
#include "obdes.h"
|
||||
#include "fupa.h"
|
||||
#include "motor.h"
|
||||
#include "datadmc.h"
|
||||
#include "countdriv.h"
|
||||
#include "counter.h"
|
211
autofile.tcl
Normal file
211
autofile.tcl
Normal file
@ -0,0 +1,211 @@
|
||||
#----------------------------------------------------------------------------
|
||||
# This is part of the WWW-interface to SICS. This interface allows to
|
||||
# create batch files to be run automatically by SICS. These files are
|
||||
# stored in a special directory as files with the ending .sip by the
|
||||
# CGI-scripts or servlets creating them. Now, a system is needed which
|
||||
# checks this directory regularly for new files and executes them in SICS.
|
||||
# This is the purpose of the SICS-Tcl macros defined in this file.
|
||||
#
|
||||
# First edition: Mark Koennecke, December 1999
|
||||
#----------------------------------------------------------------------------
|
||||
|
||||
#----------- !!!! the path where the automatic files reside
|
||||
set autofpath "/data/koenneck/tmp/auto"
|
||||
|
||||
#------- a variable which defines if we should operate and the current file.
|
||||
set __autofile_run 0
|
||||
set __auto_exe_file ""
|
||||
|
||||
#!!!!!!!!!!!!!! WARNING !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
|
||||
# There is a name command between the Tcl internal scan command and the
|
||||
# SICS scan command. The Tcl internal has to be renamed. The following
|
||||
# variable defines the name of the Tcl scan command
|
||||
set tclscan stscan
|
||||
|
||||
#---------- do initializing things when called first time
|
||||
set ret [catch [catch {autofile} msg]
|
||||
if {$ret != 0} {
|
||||
VarMake autofilepath Text Mugger
|
||||
autofilepath $autofpath
|
||||
autofilepath lock
|
||||
Publish autofileexecute User
|
||||
Publish autofile Mugger
|
||||
Publish autostart User
|
||||
Publish autoadd User
|
||||
Publish autoend User
|
||||
#------- for automatic file name creation
|
||||
catch {MakeDataNumber autonumber $autofpath/autonumber.dat}
|
||||
#------- check any 30 seconds
|
||||
sicscron 30 autofileexecute
|
||||
}
|
||||
|
||||
#--------------------------------------------------------------------------
|
||||
proc autofile { {action null} } {
|
||||
upvar #0 __autofile_run ar
|
||||
|
||||
if { [string compare $action start] == 0} {
|
||||
set ar 1
|
||||
return OK
|
||||
} elseif { [string compare $action stop] == 0 } {
|
||||
set ar 0
|
||||
return OK
|
||||
} else {
|
||||
if {$ar == 1} {
|
||||
return on
|
||||
} else {
|
||||
return off
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#--------------------------------------------------------------------------
|
||||
proc autofileexecute { } {
|
||||
upvar #0 __autofile_run ar
|
||||
upvar #0 __auto_exe_file aef
|
||||
upvar #0 tclscan filescan
|
||||
#--------- no operation if not activated
|
||||
if {$ar != 1} {
|
||||
return
|
||||
}
|
||||
#--------- aquire a list of candidate batch files
|
||||
set tmp [autofilepath]
|
||||
set ltmp [split $tmp =]
|
||||
set tmp [lindex $ltmp 1]
|
||||
set tmp2 [string trim $tmp]/*.inp
|
||||
set ret [catch {set filelist [glob $tmp2]} msg]
|
||||
if {$ret != 0} {
|
||||
return "Nothing to do"
|
||||
}
|
||||
if { [llength $filelist] < 1 } {
|
||||
return "Nothing to do"
|
||||
}
|
||||
#--------- now, in each file the second line contains the order number,
|
||||
# find the lowest one which is the next one to execute
|
||||
set minnum 999999
|
||||
set file2exe null
|
||||
foreach fil $filelist {
|
||||
set f [open $fil r]
|
||||
gets $f
|
||||
set numline [gets $f]
|
||||
set ret [catch {$filescan $numline "# %d" numi} msg]
|
||||
close $f
|
||||
if { $ret == 0 } {
|
||||
if { $numi < $minnum } {
|
||||
set minnum $numi
|
||||
set file2exe $fil
|
||||
}
|
||||
} else {
|
||||
ClientPut $msg
|
||||
}
|
||||
}
|
||||
#------------ having found an input file, execute it
|
||||
if { [string compare $file2exe null] != 0 } {
|
||||
set aef $file2exe
|
||||
set ret [catch {interneval $file2exe} msg]
|
||||
#------ after execution rename it with a different extension
|
||||
set fil2 [file rootname $file2exe].old
|
||||
file rename -force $file2exe $fil2
|
||||
if {$ret != 0 } {
|
||||
error $msg
|
||||
} else {
|
||||
return $msg
|
||||
}
|
||||
}
|
||||
return "Invalid autobatch files"
|
||||
}
|
||||
|
||||
#=========================================================================
|
||||
# File management functions
|
||||
#
|
||||
# autostart creates a fresh file. The data is stored in a SICS runbuffer.
|
||||
# autoadd adds a line to the runbuffer
|
||||
# autoend writes the file to disk then.
|
||||
#=========================================================================
|
||||
|
||||
proc autostart {} {
|
||||
catch {buf del autobuffer}
|
||||
Buf new autobuffer
|
||||
}
|
||||
|
||||
proc autoadd args {
|
||||
autobuffer append $args
|
||||
}
|
||||
|
||||
proc autoend {} {
|
||||
upvar #0 autofpath ap
|
||||
autonumber incr
|
||||
set txt [autonumber]
|
||||
set l [split $txt =]
|
||||
set txt [string trim [lindex $l 1]]
|
||||
set fil [format "$ap/auto%7.7d.inp" $txt]
|
||||
set filnum [format "# %d" $txt]
|
||||
autobuffer ins 1 $filnum
|
||||
autobuffer save $fil
|
||||
Buf del autobuffer
|
||||
}
|
||||
|
||||
#============================================================================
|
||||
# file list management
|
||||
#============================================================================
|
||||
|
||||
proc buildsortedlist {filar} {
|
||||
upvar #0 autofpath ap
|
||||
upvar $filar list
|
||||
set i 0
|
||||
#----------- build arrays of all relevant files
|
||||
set ret [catch {set l1 [glob $ap/*.inp]}]
|
||||
if { $ret == 0 } {
|
||||
foreach fil $l1 {
|
||||
set list($i)
|
||||
incr i
|
||||
set f [open $fil r]
|
||||
set $fil(title) [gets $f]
|
||||
set txt [gets $f]
|
||||
close $f
|
||||
set ret [catch {$filescan $txt "# %d" numi} msg]
|
||||
if { $ret == 0} {
|
||||
set fil(no) $numi
|
||||
}else {
|
||||
set fil(no) -10
|
||||
}
|
||||
}
|
||||
}
|
||||
set ret [catch {set l1 [glob $ap/*.old]}]
|
||||
if { $ret == 0 } {
|
||||
foreach fil $l1 {
|
||||
set list($i)
|
||||
incr i
|
||||
set f [open $fil r]
|
||||
set $fil(title) [gets $f]
|
||||
set txt [gets $f]
|
||||
close $f
|
||||
set ret [catch {$filescan $txt "# %d" numi} msg]
|
||||
if { $ret == 0} {
|
||||
set fil(no) $numi
|
||||
}else {
|
||||
set fil(no) -10
|
||||
}
|
||||
}
|
||||
}
|
||||
set nfil i
|
||||
#--------- now selection sort this list
|
||||
for {set i 0} { i < $nfil} {incr i} {
|
||||
set min $i
|
||||
set ff $list($min)
|
||||
for {set j [expr $i + 1]} {$j < $nfil} {incr j} {
|
||||
set ff $list($j)
|
||||
set fff $list($min)
|
||||
if { $ff(no) < $fff(no)} {
|
||||
set min $j
|
||||
}
|
||||
}
|
||||
set t $list($min)
|
||||
set list($min) $list($min)
|
||||
set list($i) $t
|
||||
}
|
||||
}
|
||||
|
||||
proc autolist {} {
|
||||
|
||||
}
|
||||
|
137
backup.tcl
Normal file
137
backup.tcl
Normal file
@ -0,0 +1,137 @@
|
||||
# RuenBuffer Renate
|
||||
Buf new Renate
|
||||
Renate append Alle Fische sind schon da
|
||||
|
||||
Renate append Alle Nixen auch
|
||||
|
||||
Renate append Nur die dummen Neutronen kommen nicht
|
||||
|
||||
Renate append Und die Schluempfe kriegen es auch nicht gebacken
|
||||
|
||||
# RuenBuffer Kunigunde
|
||||
Buf new Kunigunde
|
||||
Kunigunde append Alle Fische sind schon da
|
||||
|
||||
Kunigunde append Alle Nixen auch
|
||||
|
||||
Kunigunde append Nur die dummen Neutronen kommen nicht
|
||||
|
||||
Kunigunde append Und die Schluempfe kriegen es auch nicht gebacken
|
||||
|
||||
# RuenBuffer Walter
|
||||
Buf new Walter
|
||||
Walter append Alle Fische sind schon da
|
||||
|
||||
Walter append Alle Nixen auch
|
||||
|
||||
Walter append Nur die dummen Neutronen kommen nicht
|
||||
|
||||
Walter append Und die Schluempfe kriegen es auch nicht gebacken
|
||||
|
||||
# RuenBuffer Willi
|
||||
Buf new Willi
|
||||
Willi append Alle Nixen auch
|
||||
Willi append Und die Schluempfe kriegen es auch nicht gebacken
|
||||
# RuenBuffer Heinz
|
||||
Buf new Heinz
|
||||
Heinz append GGG Fische sind schon da
|
||||
Heinz append GGG Nixen auch
|
||||
Heinz append Nur die dummen Neutronen kommen schon
|
||||
Heinz append Und die Schluempfe kriegen es auch schon gebacken
|
||||
|
||||
Curve SoftLowerLim 0.000000
|
||||
Curve SoftUpperLim 1000.000000
|
||||
Curve SoftZero 0.000000
|
||||
Curve Fixed -1.000000
|
||||
Curve InterruptMode 0.000000
|
||||
Curve AccessCode 2.000000
|
||||
TwoTheta SoftLowerLim -140.000000
|
||||
TwoTheta SoftUpperLim 140.000000
|
||||
TwoTheta SoftZero 0.000000
|
||||
TwoTheta Fixed -1.000000
|
||||
TwoTheta InterruptMode 0.000000
|
||||
TwoTheta AccessCode 2.000000
|
||||
Theta SoftLowerLim -70.000000
|
||||
Theta SoftUpperLim 70.000000
|
||||
Theta SoftZero 0.000000
|
||||
Theta Fixed -1.000000
|
||||
Theta InterruptMode 0.000000
|
||||
Theta AccessCode 2.000000
|
||||
bsy SoftLowerLim -50.000000
|
||||
bsy SoftUpperLim 50.000000
|
||||
bsy SoftZero 0.000000
|
||||
bsy Fixed -1.000000
|
||||
bsy InterruptMode 0.000000
|
||||
bsy AccessCode 2.000000
|
||||
bsx SoftLowerLim -50.000000
|
||||
bsx SoftUpperLim 50.000000
|
||||
bsx SoftZero 0.000000
|
||||
bsx Fixed -1.000000
|
||||
bsx InterruptMode 0.000000
|
||||
bsx AccessCode 2.000000
|
||||
dphi SoftLowerLim 0.000000
|
||||
dphi SoftUpperLim 360.000000
|
||||
dphi SoftZero 0.000000
|
||||
dphi Fixed -1.000000
|
||||
dphi InterruptMode 0.000000
|
||||
dphi AccessCode 2.000000
|
||||
dsy SoftLowerLim -50.000000
|
||||
dsy SoftUpperLim 50.000000
|
||||
dsy SoftZero 0.000000
|
||||
dsy Fixed -1.000000
|
||||
dsy InterruptMode 0.000000
|
||||
dsy AccessCode 2.000000
|
||||
dsd SoftLowerLim 0.000000
|
||||
dsd SoftUpperLim 18000.000000
|
||||
dsd SoftZero 0.000000
|
||||
dsd Fixed -1.000000
|
||||
dsd InterruptMode 0.000000
|
||||
dsd AccessCode 2.000000
|
||||
saz SoftLowerLim 0.000000
|
||||
saz SoftUpperLim 30.000000
|
||||
saz SoftZero 0.000000
|
||||
saz Fixed -1.000000
|
||||
saz InterruptMode 0.000000
|
||||
saz AccessCode 2.000000
|
||||
say SoftLowerLim -22.000000
|
||||
say SoftUpperLim 22.000000
|
||||
say SoftZero 0.000000
|
||||
say Fixed -1.000000
|
||||
say InterruptMode 0.000000
|
||||
say AccessCode 2.000000
|
||||
sax SoftLowerLim -30.000000
|
||||
sax SoftUpperLim 30.000000
|
||||
sax SoftZero 0.000000
|
||||
sax Fixed -1.000000
|
||||
sax InterruptMode 0.000000
|
||||
sax AccessCode 2.000000
|
||||
som SoftLowerLim -180.000000
|
||||
som SoftUpperLim 360.000000
|
||||
som SoftZero 0.000000
|
||||
som Fixed -1.000000
|
||||
som InterruptMode 0.000000
|
||||
som AccessCode 2.000000
|
||||
sphi SoftLowerLim -22.000000
|
||||
sphi SoftUpperLim 22.000000
|
||||
sphi SoftZero 0.000000
|
||||
sphi Fixed -1.000000
|
||||
sphi InterruptMode 0.000000
|
||||
sphi AccessCode 2.000000
|
||||
schi SoftLowerLim -22.000000
|
||||
schi SoftUpperLim 22.000000
|
||||
schi SoftZero 0.000000
|
||||
schi Fixed -1.000000
|
||||
schi InterruptMode 0.000000
|
||||
schi AccessCode 2.000000
|
||||
comment (null)
|
||||
comment setAccess 2
|
||||
environment (null)
|
||||
environment setAccess 2
|
||||
SubTitle (null)
|
||||
SubTitle setAccess 2
|
||||
User set
|
||||
User setAccess 2
|
||||
Title Alle meine Entchen sind schon da
|
||||
Title setAccess 2
|
||||
Instrument set
|
||||
Instrument setAccess 0
|
47
bare.tcl
Normal file
47
bare.tcl
Normal file
@ -0,0 +1,47 @@
|
||||
# --------------------------------------------------------------------------
|
||||
# Initialization script for a simulated TOPSI instrument
|
||||
#
|
||||
#
|
||||
# Dr. Mark Koennecke February, 1996
|
||||
#---------------------------------------------------------------------------
|
||||
# O P T I O N S
|
||||
|
||||
# --------------- Initialize Tcl internals --------------------------------
|
||||
|
||||
# first all the server options are set
|
||||
|
||||
ServerOption ReadTimeOut 10
|
||||
# timeout when checking for commands. In the main loop SICS checks for
|
||||
# pending commands on each connection with the above timeout, has
|
||||
# PERFORMANCE impact!
|
||||
|
||||
ServerOption AcceptTimeOut 10
|
||||
# timeout when checking for connection req.
|
||||
# Similar to above, but for connections
|
||||
|
||||
ServerOption ReadUserPasswdTimeout 500000
|
||||
# time to wiat for a user/passwd to be sent from a client. Increase this
|
||||
# if there is a problem connecting to a server due to network overload\
|
||||
|
||||
ServerOption LogFileBaseName /data/koenneck/src/sics/tmp/server
|
||||
# the path and base name of the internal server logfile to which all
|
||||
# activity will be logged.
|
||||
|
||||
ServerOption ServerPort 2910
|
||||
# the port number the server is going to listen at. The client MUST know
|
||||
# this number in order to connect. It is in client.ini
|
||||
|
||||
ServerOption InterruptPort 2913
|
||||
# The UDP port where the server will wait for Interrupts from clients.
|
||||
# Obviously, clients wishing to interrupt need to know this number.
|
||||
|
||||
|
||||
#---------------------------------------------------------------------------
|
||||
# U S E R S
|
||||
|
||||
# than the SICS users are specified
|
||||
# Syntax: SicsUser name password userRightsCode
|
||||
SicsUser Mugger Diethelm 1
|
||||
SicsUser User Rosy 2
|
||||
SicsUser Spy 007 3
|
||||
|
20
beam.tcl
Normal file
20
beam.tcl
Normal file
@ -0,0 +1,20 @@
|
||||
#------------------------------------------------------------------------
|
||||
# install a SPS-Controller
|
||||
MakeSPS sps1 lnsp25.psi.ch 4000 7
|
||||
|
||||
#----------------- the beam command
|
||||
proc beam {} {
|
||||
#---------- read the SPS
|
||||
set ret [catch {SPS1 adc 3} msg]
|
||||
if {$ret != 0} {
|
||||
ClientPut $msg
|
||||
ClientPut "ERROR: SPS reading failed"
|
||||
return
|
||||
}
|
||||
#--------- convert the data
|
||||
set l [split $msg "="]
|
||||
set raw [lindex $l 1]
|
||||
set val [expr $raw/13.96]
|
||||
return [format "beam = %f" $val]
|
||||
}
|
||||
Publish beam Spy
|
20
beamdt.tcl
Normal file
20
beamdt.tcl
Normal file
@ -0,0 +1,20 @@
|
||||
#------------------------------------------------------------------------
|
||||
# install a SPS-Controller
|
||||
MakeSPS sps1 lnsp23.psi.ch 4000 6
|
||||
|
||||
#----------------- the beam command
|
||||
proc beam {} {
|
||||
#---------- read the SPS
|
||||
set ret [catch {SPS1 adc 7} msg]
|
||||
if {$ret != 0} {
|
||||
ClientPut $msg
|
||||
ClientPut "ERROR: SPS reading failed"
|
||||
return
|
||||
}
|
||||
#--------- convert the data
|
||||
set l [split $msg "="]
|
||||
set raw [lindex $l 1]
|
||||
set val [expr $raw/13.96]
|
||||
return [format "beam = %f" $val]
|
||||
}
|
||||
Publish beam Spy
|
17
bit.h
Normal file
17
bit.h
Normal file
@ -0,0 +1,17 @@
|
||||
/*--------------------------------------------------------------------------
|
||||
|
||||
Macros for handling bits in a character array. Stolen somewhere on the
|
||||
internet. Working!
|
||||
|
||||
Dr. Mark Koennecke 15.6.1994
|
||||
|
||||
----------------------------------------------------------------------------*/
|
||||
|
||||
|
||||
#include <limits.h> /* for CHAR_BIT */
|
||||
|
||||
#define BITMASK(bit) (1 << ((bit) % CHAR_BIT))
|
||||
#define BITSLOT(bit) ((bit) / CHAR_BIT)
|
||||
#define BITSET(ary, bit) ((ary)[BITSLOT(bit)] |= BITMASK(bit))
|
||||
#define BITTEST(ary, bit) ((ary)[BITSLOT(bit)] & BITMASK(bit))
|
||||
#define BITUNSET(ary, bit) ((ary)[BITSLOT(bit)] ^= BITMASK(bit))
|
999
bruker.c
Normal file
999
bruker.c
Normal file
@ -0,0 +1,999 @@
|
||||
/*-------------------------------------------------------------------------
|
||||
B r u k e r
|
||||
|
||||
An environment control driver and an additonal wrapper function for
|
||||
controlling a Bruker B-EC-1 magnet controller. This controller can
|
||||
either control a current or control the current through an external hall
|
||||
sensor mesuring the magnetic field. In both cases both values: the field
|
||||
and the current must be readable.
|
||||
|
||||
copyright: see copyright.h
|
||||
|
||||
Mark Koennecke, October 1998
|
||||
---------------------------------------------------------------------------*/
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <time.h>
|
||||
#include <tcl.h>
|
||||
#include <math.h>
|
||||
#include <assert.h>
|
||||
#include "fortify.h"
|
||||
#include "sics.h"
|
||||
#include "obpar.h"
|
||||
#include "evcontroller.h"
|
||||
#include "evcontroller.i"
|
||||
#include "evdriver.i"
|
||||
#include "hardsup/serialsinq.h"
|
||||
#include "hardsup/el734_errcodes.h"
|
||||
#include "hardsup/el734fix.h"
|
||||
#include "bruker.h"
|
||||
|
||||
/*
|
||||
#define debug 1
|
||||
*/
|
||||
/*-----------------------------------------------------------------------
|
||||
The Bruker Data Structure
|
||||
*/
|
||||
typedef struct {
|
||||
void *pData;
|
||||
char *pHost;
|
||||
int iPort;
|
||||
int iChannel;
|
||||
int iMode;
|
||||
int iLastError;
|
||||
} BrukerDriv, *pBrukerDriv;
|
||||
/*-----------------------------------------------------------------------
|
||||
A couple of defines for Bruker modes and special error conditions
|
||||
*/
|
||||
#define FIELD 100
|
||||
#define CURRENT 200
|
||||
|
||||
/* errors */
|
||||
#define NOFUNC -1601
|
||||
#define BADARG -1602
|
||||
#define NOACCESS -1603
|
||||
#define BADRANGE -1604
|
||||
#define ERRPENDING -1605
|
||||
#define NOPOWER -1606
|
||||
#define NOTFIELD -1607
|
||||
#define BADINTERN -1608
|
||||
#define NOCONN -1609
|
||||
#define BTIMEOUT -1610
|
||||
#define NOPOLUNIT -1620
|
||||
|
||||
/* polarity */
|
||||
#define PPLUS 0
|
||||
#define PMINUS 1
|
||||
#define PBUSY 3
|
||||
|
||||
/* rmtrail.c */
|
||||
extern char *rmtrail(char *p);
|
||||
|
||||
/*---------------------------------------------------------------------------
|
||||
This Bruker thing has a lot of internal error conditions and a few nasty
|
||||
habits. Such as to lock up after an error ocurred until the error is reset.
|
||||
Or to switch the power off, when a current above the limit is requested
|
||||
after setting a bad value for the magnetic field. These problems can be
|
||||
detected by analysing the return values from the Bruker. Usually the Bruker
|
||||
returns the command given to the user plus additional values if requested.
|
||||
On an error a string of the type E0n is appended to the command echo with
|
||||
n being a small integer. In order to handle this all commands to the Bruker
|
||||
are processed through this special function which takes care of the error
|
||||
handling.
|
||||
*/
|
||||
static int BrukerCommand(pBrukerDriv self, char *pCommand,
|
||||
char *pReplyBuffer, int iReplyLen)
|
||||
{
|
||||
int iTest, iCode;
|
||||
char *pPtr;
|
||||
|
||||
assert(self);
|
||||
assert(iReplyLen > 20); /* so small a buffer will hide errors */
|
||||
|
||||
if(self->pData == NULL)
|
||||
{
|
||||
self->iLastError = NOCONN;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* send the command to the Bruker */
|
||||
rmtrail(pCommand);
|
||||
iTest = SerialWriteRead(&(self->pData), pCommand,pReplyBuffer, iReplyLen);
|
||||
#ifdef debug
|
||||
printf("Comm: %s , Reply %s\n",pCommand,pReplyBuffer);
|
||||
#endif
|
||||
if(iTest != 1) /* communication error */
|
||||
{
|
||||
self->iLastError = iTest;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* identify timeout */
|
||||
if(strstr(pReplyBuffer,"?TMO") != NULL)
|
||||
{
|
||||
self->iLastError = BTIMEOUT;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* try to find a E0 response indicating a Bruker error */
|
||||
if( (pPtr = strstr(pReplyBuffer,"E0")) == NULL)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* decode the error */
|
||||
sscanf(pPtr+1,"%x",&iCode);
|
||||
switch(iCode)
|
||||
{
|
||||
case 1:
|
||||
self->iLastError = NOFUNC;
|
||||
break;
|
||||
case 2:
|
||||
self->iLastError = BADARG;
|
||||
break;
|
||||
case 4:
|
||||
self->iLastError = NOACCESS;
|
||||
break;
|
||||
case 5:
|
||||
self->iLastError = BADRANGE;
|
||||
break;
|
||||
case 7:
|
||||
self->iLastError = ERRPENDING;
|
||||
break;
|
||||
case 9:
|
||||
self->iLastError = NOPOWER;
|
||||
break;
|
||||
case 10:
|
||||
self->iLastError = NOTFIELD;
|
||||
break;
|
||||
default:
|
||||
self->iLastError = BADINTERN;
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
/*-------------------------------------------------------------------------*/
|
||||
int BrukerReadField(pEVControl pEva, float *fField)
|
||||
{
|
||||
pBrukerDriv self = NULL;
|
||||
int iRet;
|
||||
char pBueffel[80];
|
||||
char pCommand[6];
|
||||
char *pPtr,*pSign;
|
||||
int iSign = 1;
|
||||
float fVal;
|
||||
|
||||
self = (pBrukerDriv)pEva->pDriv->pPrivate;
|
||||
assert(self);
|
||||
|
||||
if(self->pData == NULL)
|
||||
{
|
||||
self->iLastError = NOCONN;
|
||||
return 0;
|
||||
}
|
||||
|
||||
strcpy(pCommand,"FIE/");
|
||||
iRet = BrukerCommand(self,pCommand,pBueffel,79);
|
||||
if(!iRet)
|
||||
{
|
||||
*fField = -99;
|
||||
return 0;
|
||||
}
|
||||
|
||||
pPtr = pBueffel+4; /* skip over echo */
|
||||
/* deal with obstructing sign */
|
||||
if( (pSign = strchr(pPtr,'+')) != NULL)
|
||||
{
|
||||
*pSign = ' ';
|
||||
iSign = 1;
|
||||
}
|
||||
if( (pSign = strchr(pPtr,'-')) != NULL)
|
||||
{
|
||||
*pSign = ' ';
|
||||
iSign = -1;
|
||||
}
|
||||
sscanf(pPtr,"%f",&fVal);
|
||||
*fField = iSign * fVal;
|
||||
return 1;
|
||||
}
|
||||
/*-------------------------------------------------------------------------*/
|
||||
int BrukerReadCurrent(pEVControl pEva, float *fField)
|
||||
{
|
||||
pBrukerDriv self = NULL;
|
||||
int iRet, iSign = 1;
|
||||
char pBueffel[80];
|
||||
char pCommand[6];
|
||||
char *pPtr, *pSign = NULL;
|
||||
float fVal;
|
||||
|
||||
self = (pBrukerDriv)pEva->pDriv->pPrivate;
|
||||
assert(self);
|
||||
|
||||
if(self->pData == NULL)
|
||||
{
|
||||
self->iLastError = NOCONN;
|
||||
return 0;
|
||||
}
|
||||
|
||||
strcpy(pCommand,"CHN/");
|
||||
iRet = BrukerCommand(self,pCommand,pBueffel,79);
|
||||
if(!iRet)
|
||||
{
|
||||
*fField = -99;
|
||||
return 0;
|
||||
}
|
||||
|
||||
pPtr = pBueffel+4; /* skip over echo */
|
||||
/* deal with obstructing sign */
|
||||
if( (pSign = strchr(pPtr,'+')) != NULL)
|
||||
{
|
||||
*pSign = ' ';
|
||||
iSign = 1;
|
||||
}
|
||||
if( (pSign = strchr(pPtr,'-')) != NULL)
|
||||
{
|
||||
*pSign = ' ';
|
||||
iSign = -1;
|
||||
}
|
||||
sscanf(pPtr,"%f",&fVal);
|
||||
*fField = iSign * fVal;
|
||||
return 1;
|
||||
}
|
||||
/*-------------------------------------------------------------------------*/
|
||||
static int BrukerGet(pEVDriver pEva, float *fValue)
|
||||
{
|
||||
pBrukerDriv self = NULL;
|
||||
int iRet, iSign = 1;
|
||||
char pBueffel[80];
|
||||
char pCommand[6];
|
||||
char *pPtr, *pSign = NULL;
|
||||
float fVal;
|
||||
|
||||
self = (pBrukerDriv)pEva->pPrivate;
|
||||
assert(self);
|
||||
|
||||
if(self->pData == NULL)
|
||||
{
|
||||
self->iLastError = NOCONN;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if(self->iMode == FIELD)
|
||||
{
|
||||
strcpy(pCommand,"CUF/");
|
||||
iRet = BrukerCommand(self,pCommand,pBueffel,79);
|
||||
}
|
||||
else if(self->iMode == CURRENT)
|
||||
{
|
||||
strcpy(pCommand,"CUR/");
|
||||
iRet = BrukerCommand(self,pCommand,pBueffel,79);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* programming error */
|
||||
assert(1);
|
||||
}
|
||||
|
||||
if(!iRet)
|
||||
{
|
||||
*fValue = -99;
|
||||
return 0;
|
||||
}
|
||||
|
||||
pPtr = pBueffel+4; /* skip over echo */
|
||||
/* deal with obstructing sign */
|
||||
if( (pSign = strchr(pPtr,'+')) != NULL)
|
||||
{
|
||||
*pSign = ' ';
|
||||
iSign = 1;
|
||||
}
|
||||
if( (pSign = strchr(pPtr,'-')) != NULL)
|
||||
{
|
||||
*pSign = ' ';
|
||||
iSign = -1;
|
||||
}
|
||||
sscanf(pPtr,"%f",&fVal);
|
||||
*fValue = iSign * fVal;
|
||||
return 1;
|
||||
}
|
||||
/*-------------------------------------------------------------------------*/
|
||||
static int BrukerRun(pEVDriver pEva, float fVal)
|
||||
{
|
||||
pBrukerDriv self = NULL;
|
||||
int iRet;
|
||||
char pBueffel[80];
|
||||
char pCommand[40];
|
||||
char *pPtr;
|
||||
|
||||
self = (pBrukerDriv)pEva->pPrivate;
|
||||
assert(self);
|
||||
|
||||
if(self->pData == NULL)
|
||||
{
|
||||
self->iLastError = NOCONN;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if(self->iMode == FIELD)
|
||||
{
|
||||
sprintf(pCommand,"PTF=%-6.2f",fVal);
|
||||
iRet = BrukerCommand(self,pCommand,pBueffel,79);
|
||||
}
|
||||
else if(self->iMode == CURRENT)
|
||||
{
|
||||
sprintf(pCommand,"PNT=%-6.2f",fVal);
|
||||
iRet = BrukerCommand(self,pCommand,pBueffel,79);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* programming error */
|
||||
assert(1);
|
||||
}
|
||||
|
||||
if(!iRet)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
/*------------------------------------------------------------------------*/
|
||||
static int BrukerError(pEVDriver pEva, int *iCode, char *pError,
|
||||
int iErrLen)
|
||||
{
|
||||
pBrukerDriv self = NULL;
|
||||
|
||||
self = (pBrukerDriv)pEva->pPrivate;
|
||||
assert(self);
|
||||
|
||||
*iCode = self->iLastError;
|
||||
switch(*iCode)
|
||||
{
|
||||
case NOFUNC:
|
||||
strncpy(pError,
|
||||
"Function not supported",
|
||||
iErrLen);
|
||||
break;
|
||||
case BADINTERN:
|
||||
case BADARG:
|
||||
strncpy(pError,
|
||||
"Programming problem, reset Controller & contact Programmer",
|
||||
iErrLen);
|
||||
break;
|
||||
case NOTFIELD:
|
||||
strncpy(pError,"Bruker not switched to field mode",iErrLen);
|
||||
break;
|
||||
case BADRANGE:
|
||||
strncpy(pError,"Requested value out of range",iErrLen);
|
||||
break;
|
||||
case NOACCESS:
|
||||
strncpy(pError,"No Access, check key position at Controller",
|
||||
iErrLen);
|
||||
break;
|
||||
case ERRPENDING:
|
||||
strncpy(pError,"Error condition pending in Bruker Controller",
|
||||
iErrLen);
|
||||
break;
|
||||
case NOPOWER:
|
||||
strncpy(pError,
|
||||
"Power OFF as consequence of some error in Bruker Controller",
|
||||
iErrLen);
|
||||
break;
|
||||
case NOCONN:
|
||||
strncpy(pError,"No Connection to Bruker Controller",iErrLen);
|
||||
break;
|
||||
case BTIMEOUT:
|
||||
strncpy(pError,"Timeout at serial port",iErrLen);
|
||||
break;
|
||||
case NOPOLUNIT:
|
||||
strncpy(pError,"No polarity switching unit, try setting negative current",
|
||||
iErrLen);
|
||||
break;
|
||||
default:
|
||||
SerialError(*iCode,pError,iErrLen);
|
||||
break;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
static int BrukerSend(pEVDriver pEva, char *pCommand, char *pReply,
|
||||
int iReplyLen)
|
||||
{
|
||||
pBrukerDriv self = NULL;
|
||||
int iRet;
|
||||
|
||||
self = (pBrukerDriv)pEva->pPrivate;
|
||||
assert(self);
|
||||
|
||||
if(self->pData == NULL)
|
||||
{
|
||||
self->iLastError = NOCONN;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
iRet = SerialWriteRead(&(self->pData),pCommand, pReply, iReplyLen);
|
||||
if(iRet != 1)
|
||||
{
|
||||
self->iLastError = iRet;
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
/*--------------------------------------------------------------------------*/
|
||||
static int BrukerInit(pEVDriver pEva)
|
||||
{
|
||||
pBrukerDriv self = NULL;
|
||||
int iRet;
|
||||
char pBueffel[80], pCommand[20];
|
||||
|
||||
self = (pBrukerDriv)pEva->pPrivate;
|
||||
assert(self);
|
||||
|
||||
/* open port connection */
|
||||
self->pData = NULL;
|
||||
iRet = SerialOpen(&(self->pData),self->pHost, self->iPort, self->iChannel);
|
||||
if(iRet != 1)
|
||||
{
|
||||
self->iLastError = iRet;
|
||||
return 0;
|
||||
}
|
||||
/* configure serial port terminators */
|
||||
SerialSendTerm(&(self->pData),"\r");
|
||||
SerialATerm(&(self->pData),"1\r\n");
|
||||
|
||||
/* set power on */
|
||||
strcpy(pCommand,"DCP=1");
|
||||
iRet = SerialWriteRead(&(self->pData),pCommand,pBueffel,80);
|
||||
if(iRet != 1)
|
||||
{
|
||||
self->iLastError = iRet;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* switch to current mode as default init mode */
|
||||
self->iMode = CURRENT;
|
||||
strcpy(pCommand,"EXT=0");
|
||||
iRet = SerialWriteRead(&(self->pData),pCommand,pBueffel,80);
|
||||
if(iRet != 1)
|
||||
{
|
||||
self->iLastError = iRet;
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
/*-------------------------------------------------------------------------*/
|
||||
static int BrukerClose(pEVDriver pEva)
|
||||
{
|
||||
pBrukerDriv self = NULL;
|
||||
|
||||
self = (pBrukerDriv)pEva->pPrivate;
|
||||
assert(self);
|
||||
|
||||
SerialClose(&(self->pData));
|
||||
self->pData = 0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
static int BrukerFix(pEVDriver self, int iError)
|
||||
{
|
||||
pBrukerDriv pMe = NULL;
|
||||
int iRet;
|
||||
char pCommand[20], pBueffel[80];
|
||||
|
||||
assert(self);
|
||||
pMe = (pBrukerDriv )self->pPrivate;
|
||||
assert(pMe);
|
||||
|
||||
switch(iError)
|
||||
{
|
||||
/* network errors */
|
||||
case EL734__BAD_FLUSH:
|
||||
case EL734__BAD_RECV:
|
||||
case EL734__BAD_RECV_NET:
|
||||
case EL734__BAD_RECV_UNKN:
|
||||
case EL734__BAD_RECVLEN:
|
||||
case EL734__BAD_RECV1:
|
||||
case EL734__BAD_RECV1_PIPE:
|
||||
case EL734__BAD_RNG:
|
||||
case EL734__BAD_SEND:
|
||||
case EL734__BAD_SEND_PIPE:
|
||||
case EL734__BAD_SEND_NET:
|
||||
case EL734__BAD_SEND_UNKN:
|
||||
case EL734__BAD_SENDLEN:
|
||||
BrukerClose(self);
|
||||
iRet = BrukerInit(self);
|
||||
if(iRet)
|
||||
{
|
||||
return DEVREDO;
|
||||
}
|
||||
else
|
||||
{
|
||||
return DEVFAULT;
|
||||
}
|
||||
break;
|
||||
case EL734__FORCED_CLOSED:
|
||||
case NOCONN:
|
||||
iRet = BrukerInit(self);
|
||||
if(iRet)
|
||||
{
|
||||
return DEVREDO;
|
||||
}
|
||||
else
|
||||
{
|
||||
return DEVFAULT;
|
||||
}
|
||||
break;
|
||||
/* fixable Bruker Errors */
|
||||
case ERRPENDING:
|
||||
strcpy(pCommand,"RST=0");
|
||||
iRet = BrukerCommand(pMe,pCommand, pBueffel,79);
|
||||
if(iRet)
|
||||
{
|
||||
return DEVREDO;
|
||||
}
|
||||
else
|
||||
{
|
||||
return DEVFAULT;
|
||||
}
|
||||
break;
|
||||
case NOPOWER:
|
||||
strcpy(pCommand,"RST=0");
|
||||
iRet = BrukerCommand(pMe,pCommand, pBueffel,79);
|
||||
strcpy(pCommand,"DCP=1");
|
||||
iRet = BrukerCommand(pMe,pCommand, pBueffel,79);
|
||||
if(iRet)
|
||||
{
|
||||
return DEVREDO;
|
||||
}
|
||||
else
|
||||
{
|
||||
return DEVFAULT;
|
||||
}
|
||||
break;
|
||||
case NOTFIELD:
|
||||
strcpy(pCommand,"EXT=2");
|
||||
iRet = BrukerCommand(pMe,pCommand, pBueffel,79);
|
||||
if(iRet)
|
||||
{
|
||||
return DEVREDO;
|
||||
}
|
||||
else
|
||||
{
|
||||
return DEVFAULT;
|
||||
}
|
||||
break;
|
||||
/* handable protocoll errors */
|
||||
case EL734__BAD_TMO:
|
||||
case BTIMEOUT:
|
||||
case NOFUNC:
|
||||
return DEVREDO;
|
||||
break;
|
||||
default:
|
||||
return DEVFAULT;
|
||||
break;
|
||||
}
|
||||
return DEVFAULT;
|
||||
}
|
||||
/*------------------------------------------------------------------------*/
|
||||
void KillBruker(void *pData)
|
||||
{
|
||||
pBrukerDriv pMe = NULL;
|
||||
|
||||
pMe = (pBrukerDriv)pData;
|
||||
assert(pMe);
|
||||
|
||||
if(pMe->pHost)
|
||||
{
|
||||
free(pMe->pHost);
|
||||
}
|
||||
free(pMe);
|
||||
}
|
||||
/*------------------------------------------------------------------------*/
|
||||
pEVDriver CreateBrukerDriver(int argc, char *argv[])
|
||||
{
|
||||
pEVDriver pNew = NULL;
|
||||
pBrukerDriv pSim = NULL;
|
||||
|
||||
/* check for arguments */
|
||||
if(argc < 3)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
pNew = CreateEVDriver(argc,argv);
|
||||
pSim = (pBrukerDriv)malloc(sizeof(BrukerDriv));
|
||||
memset(pSim,0,sizeof(BrukerDriv));
|
||||
if(!pNew || !pSim)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
pNew->pPrivate = pSim;
|
||||
pNew->KillPrivate = KillBruker;
|
||||
|
||||
/* initalise pBrukerDriver */
|
||||
pSim->iLastError = 0;
|
||||
pSim->pHost = strdup(argv[0]);
|
||||
pSim->iPort = atoi(argv[1]);
|
||||
pSim->iChannel = atoi(argv[2]);
|
||||
|
||||
|
||||
/* initialise function pointers */
|
||||
pNew->SetValue = BrukerRun;
|
||||
pNew->GetValue = BrukerGet;
|
||||
pNew->Send = BrukerSend;
|
||||
pNew->GetError = BrukerError;
|
||||
pNew->TryFixIt = BrukerFix;
|
||||
pNew->Init = BrukerInit;
|
||||
pNew->Close = BrukerClose;
|
||||
|
||||
return pNew;
|
||||
}
|
||||
/*-------------------------------------------------------------------------*/
|
||||
int BrukerSetMode(pEVControl pEva, SConnection *pCon, int iMode)
|
||||
{
|
||||
pBrukerDriv self = NULL;
|
||||
int iRet;
|
||||
char pBueffel[80];
|
||||
char pCommand[6];
|
||||
char *pPtr;
|
||||
|
||||
self = (pBrukerDriv)pEva->pDriv->pPrivate;
|
||||
assert(self);
|
||||
|
||||
if(self->pData == NULL)
|
||||
{
|
||||
self->iLastError = NOCONN;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if(iMode == CURRENT)
|
||||
{
|
||||
strcpy(pCommand,"EXT=0");
|
||||
}
|
||||
else if(iMode == FIELD)
|
||||
{
|
||||
strcpy(pCommand,"EXT=2");
|
||||
}
|
||||
else
|
||||
{
|
||||
SCWrite(pCon,"ERROR: Internal: invalid mode for Bruker given",eError);
|
||||
return 0;
|
||||
}
|
||||
iRet = BrukerCommand(self,pCommand,pBueffel,79);
|
||||
if(!iRet)
|
||||
{
|
||||
strcpy(pBueffel,"ERROR:");
|
||||
BrukerError(pEva->pDriv,&iRet,(pBueffel+7),70);
|
||||
SCWrite(pCon,pBueffel,eError);
|
||||
return 0;
|
||||
}
|
||||
self->iMode = iMode;
|
||||
return 1;
|
||||
}
|
||||
/*-------------------------------------------------------------------------*/
|
||||
int BrukerGetPolarity(pEVControl pEva, SConnection *pCon, int *iMode)
|
||||
{
|
||||
pBrukerDriv self = NULL;
|
||||
int iRet;
|
||||
char pBueffel[80];
|
||||
char pCommand[6];
|
||||
char *pPtr;
|
||||
|
||||
self = (pBrukerDriv)pEva->pDriv->pPrivate;
|
||||
assert(self);
|
||||
|
||||
if(self->pData == NULL)
|
||||
{
|
||||
self->iLastError = NOCONN;
|
||||
return 0;
|
||||
}
|
||||
strcpy(pCommand,"POL/");
|
||||
iRet = BrukerCommand(self,pCommand,pBueffel,79);
|
||||
if(!iRet)
|
||||
{
|
||||
strcpy(pBueffel,"ERROR:");
|
||||
BrukerError(pEva->pDriv,&iRet,(pBueffel+7),70);
|
||||
SCWrite(pCon,pBueffel,eError);
|
||||
return 0;
|
||||
}
|
||||
pPtr = pBueffel+4;
|
||||
sscanf(pPtr,"%d",iMode);
|
||||
return 1;
|
||||
}
|
||||
/*------------------------------------------------------------------------*/
|
||||
int BrukerSetPolarity(pEVControl pEva, SConnection *pCon, int iMode)
|
||||
{
|
||||
pBrukerDriv self = NULL;
|
||||
int iRet;
|
||||
char pBueffel[80];
|
||||
char pCommand[6];
|
||||
char *pPtr;
|
||||
|
||||
self = (pBrukerDriv)pEva->pDriv->pPrivate;
|
||||
assert(self);
|
||||
|
||||
if(self->pData == NULL)
|
||||
{
|
||||
self->iLastError = NOCONN;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if(iMode == PPLUS)
|
||||
{
|
||||
strcpy(pCommand,"POL=0");
|
||||
}
|
||||
else if(iMode == PMINUS)
|
||||
{
|
||||
strcpy(pCommand,"POL=1");
|
||||
}
|
||||
else
|
||||
{
|
||||
assert(1); /* programming error */
|
||||
}
|
||||
|
||||
iRet = BrukerCommand(self,pCommand,pBueffel,79);
|
||||
if( (strstr(pBueffel,"POL=0E01") != NULL) ||
|
||||
(strstr(pBueffel,"POL=1E01") != NULL) )
|
||||
{
|
||||
self->iLastError = NOPOLUNIT;
|
||||
iRet = 0;
|
||||
}
|
||||
if(!iRet)
|
||||
{
|
||||
strcpy(pBueffel,"ERROR:");
|
||||
BrukerError(pEva->pDriv,&iRet,(pBueffel+6),70);
|
||||
SCWrite(pCon,pBueffel,eError);
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
/*--------------------------------------------------------------------------
|
||||
handle Bruker specific commands:
|
||||
- polarity for switching polarity
|
||||
- field for reading field
|
||||
- current for reading current
|
||||
- mode for setting and retrieving the current control mode
|
||||
- list append our own stuff to the rest
|
||||
in all other cases fall back and call EVControllerWrapper to handle it or
|
||||
eventually throw an error.
|
||||
*/
|
||||
int BrukerAction(SConnection *pCon, SicsInterp *pSics, void *pData,
|
||||
int argc, char *argv[])
|
||||
{
|
||||
|
||||
pEVControl self = NULL;
|
||||
int iRet, iMode;
|
||||
char pBueffel[256];
|
||||
pBrukerDriv pMe = NULL;
|
||||
float fVal;
|
||||
|
||||
self = (pEVControl)pData;
|
||||
assert(self);
|
||||
pMe = (pBrukerDriv)self->pDriv->pPrivate;
|
||||
assert(pMe);
|
||||
|
||||
if(argc > 1)
|
||||
{
|
||||
strtolower(argv[1]);
|
||||
/*------ polarity */
|
||||
if(strcmp(argv[1],"polarity") == 0)
|
||||
{
|
||||
if(argc > 2) /* set case */
|
||||
{
|
||||
strtolower(argv[2]);
|
||||
if(strcmp(argv[2],"plus") == 0)
|
||||
{
|
||||
iMode = PPLUS;
|
||||
}
|
||||
else if(strcmp(argv[2],"minus") == 0)
|
||||
{
|
||||
iMode = PMINUS;
|
||||
}
|
||||
else
|
||||
{
|
||||
sprintf(pBueffel,"ERROR: %s is no knwon polarity mode", argv[2]);
|
||||
SCWrite(pCon,pBueffel,eError);
|
||||
return 0;
|
||||
}
|
||||
/* check permission */
|
||||
if(!SCMatchRights(pCon,usUser))
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
/* do it */
|
||||
iRet = BrukerSetPolarity(self,pCon,iMode);
|
||||
if(iRet)
|
||||
{
|
||||
SCSendOK(pCon);
|
||||
return 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
else /* get case */
|
||||
{
|
||||
iRet = BrukerGetPolarity(self,pCon,&iMode);
|
||||
if(iRet)
|
||||
{
|
||||
if(iMode == PPLUS)
|
||||
{
|
||||
sprintf(pBueffel,"%s.polarity = plus",argv[0]);
|
||||
}
|
||||
else if (iMode == PMINUS)
|
||||
{
|
||||
sprintf(pBueffel,"%s.polarity = minus",argv[0]);
|
||||
}
|
||||
else
|
||||
{
|
||||
assert(1); /* programming problem */
|
||||
}
|
||||
SCWrite(pCon,pBueffel,eValue);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
/*-------- control mode */
|
||||
else if(strcmp(argv[1],"mode") == 0)
|
||||
{
|
||||
if(argc > 2) /* set case */
|
||||
{
|
||||
strtolower(argv[2]);
|
||||
if(strcmp(argv[2],"field") == 0)
|
||||
{
|
||||
iMode = FIELD;
|
||||
}
|
||||
else if(strcmp(argv[2],"current") == 0)
|
||||
{
|
||||
iMode = CURRENT;
|
||||
}
|
||||
else
|
||||
{
|
||||
sprintf(pBueffel,"ERROR: %s is no known control mode", argv[2]);
|
||||
SCWrite(pCon,pBueffel,eError);
|
||||
return 0;
|
||||
}
|
||||
/* check permission */
|
||||
if(!SCMatchRights(pCon,usUser))
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
/* do it */
|
||||
iRet = BrukerSetMode(self,pCon,iMode);
|
||||
if(iRet)
|
||||
{
|
||||
SCSendOK(pCon);
|
||||
return 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
else /* get case */
|
||||
{
|
||||
if(pMe->iMode == FIELD)
|
||||
{
|
||||
sprintf(pBueffel,"%s.mode = field",argv[0]);
|
||||
}
|
||||
else if (pMe->iMode == CURRENT)
|
||||
{
|
||||
sprintf(pBueffel,"%s.mode = current",argv[0]);
|
||||
}
|
||||
else
|
||||
{
|
||||
assert(1); /* programming problem */
|
||||
}
|
||||
SCWrite(pCon,pBueffel,eValue);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
/*-----------field */
|
||||
else if(strcmp(argv[1],"field") == 0)
|
||||
{
|
||||
iRet = BrukerReadField(self,&fVal);
|
||||
if(!iRet)
|
||||
{
|
||||
strcpy(pBueffel,"ERROR: ");
|
||||
self->pDriv->GetError(self->pDriv,&iMode,pBueffel+7,240);
|
||||
SCWrite(pCon,pBueffel,eError);
|
||||
return 0;
|
||||
}
|
||||
sprintf(pBueffel,"%s.field = %f Tesla",argv[0],fVal);
|
||||
SCWrite(pCon,pBueffel,eValue);
|
||||
return 1;
|
||||
}
|
||||
/*----------- current */
|
||||
else if(strcmp(argv[1],"current") == 0)
|
||||
{
|
||||
iRet = BrukerReadCurrent(self,&fVal);
|
||||
if(!iRet)
|
||||
{
|
||||
strcpy(pBueffel,"ERROR: ");
|
||||
self->pDriv->GetError(self->pDriv,&iMode,pBueffel+7,240);
|
||||
SCWrite(pCon,pBueffel,eError);
|
||||
return 0;
|
||||
}
|
||||
sprintf(pBueffel,"%s.current = %f A",argv[0],fVal);
|
||||
SCWrite(pCon,pBueffel,eValue);
|
||||
return 1;
|
||||
}
|
||||
/*--------- list */
|
||||
else if(strcmp(argv[1],"list") == 0)
|
||||
{
|
||||
/* print generals first */
|
||||
EVControlWrapper(pCon,pSics,pData,argc,argv);
|
||||
/* print our add on stuff */
|
||||
iRet = BrukerReadCurrent(self,&fVal);
|
||||
if(!iRet)
|
||||
{
|
||||
strcpy(pBueffel,"ERROR: ");
|
||||
self->pDriv->GetError(self->pDriv,&iMode,pBueffel+7,240);
|
||||
SCWrite(pCon,pBueffel,eError);
|
||||
}
|
||||
else
|
||||
{
|
||||
sprintf(pBueffel,"%s.current = %f A",argv[0],fVal);
|
||||
SCWrite(pCon,pBueffel,eValue);
|
||||
}
|
||||
iRet = BrukerReadField(self,&fVal);
|
||||
if(!iRet)
|
||||
{
|
||||
strcpy(pBueffel,"ERROR: ");
|
||||
self->pDriv->GetError(self->pDriv,&iMode,pBueffel+7,240);
|
||||
SCWrite(pCon,pBueffel,eError);
|
||||
}
|
||||
else
|
||||
{
|
||||
sprintf(pBueffel,"%s.field = %f Tesla",argv[0],fVal);
|
||||
SCWrite(pCon,pBueffel,eValue);
|
||||
}
|
||||
if(pMe->iMode == FIELD)
|
||||
{
|
||||
sprintf(pBueffel,"%s.mode = field",argv[0]);
|
||||
}
|
||||
else if (pMe->iMode == CURRENT)
|
||||
{
|
||||
sprintf(pBueffel,"%s.mode = current",argv[0]);
|
||||
}
|
||||
else
|
||||
{
|
||||
sprintf(pBueffel,"ERROR: Programming error");
|
||||
}
|
||||
SCWrite(pCon,pBueffel,eValue);
|
||||
iRet = BrukerGetPolarity(self,pCon,&iMode);
|
||||
if(iRet)
|
||||
{
|
||||
if(iMode == PPLUS)
|
||||
{
|
||||
sprintf(pBueffel,"%s.polarity = plus",argv[0]);
|
||||
}
|
||||
else if (iMode == PMINUS)
|
||||
{
|
||||
sprintf(pBueffel,"%s.polarity = minus",argv[0]);
|
||||
}
|
||||
else if(iMode == PBUSY)
|
||||
{
|
||||
sprintf(pBueffel,"%s.polarity = busy",argv[0]);
|
||||
}
|
||||
else
|
||||
{
|
||||
sprintf(pBueffel,"ERROR: Programming problem");
|
||||
}
|
||||
SCWrite(pCon,pBueffel,eValue);
|
||||
}
|
||||
else
|
||||
{
|
||||
SCWrite(pCon,"ERROR: cannot read polarity",eError);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
return EVControlWrapper(pCon,pSics,pData,argc,argv);
|
||||
}
|
||||
}
|
||||
return EVControlWrapper(pCon,pSics,pData,argc,argv);
|
||||
}
|
25
bruker.h
Normal file
25
bruker.h
Normal file
@ -0,0 +1,25 @@
|
||||
/*-------------------------------------------------------------------------
|
||||
B r u k e r
|
||||
|
||||
An environment control driver and an additonal wrapper function for
|
||||
controlling a Bruker B-EC-1 magnet controller. This controller can
|
||||
either control a current or control the current through an external hall
|
||||
sensor mesuring the magnetic field. In both cases both values: the field
|
||||
and the current must be readable.
|
||||
|
||||
copyright: see copyright.h
|
||||
|
||||
Mark Koennecke, October 1998
|
||||
---------------------------------------------------------------------------*/
|
||||
#ifndef BRUKERMAGNET
|
||||
#define BRUKERMAGNET
|
||||
|
||||
pEVDriver CreateBrukerDriver(int argc, char *argv[]);
|
||||
|
||||
int BrukerReadField(pEVControl self, float *fField);
|
||||
int BrukerReadCurrent(pEVControl self, float *fCurrent);
|
||||
|
||||
int BrukerAction(SConnection *pCon, SicsInterp *pSics, void *pData,
|
||||
int argc, char *argv[]);
|
||||
|
||||
#endif
|
64
bruker.tex
Normal file
64
bruker.tex
Normal file
@ -0,0 +1,64 @@
|
||||
\subsubsection{Bruker Magnet Controller B-EC-1}
|
||||
SANS is using a Bruker magnet controller. This controller is integrated
|
||||
into SICS as a derivate of an environment controller. The Bruker controller
|
||||
can be operated in two modes: in the first the current is controlled,
|
||||
in the second the current
|
||||
is controlled by an external hall sensor giving the magnetic field. Whatever
|
||||
is the controlling sensor, the magnetic field and the current need to be
|
||||
read. Furthermore this device supports switching the polarity. All this is
|
||||
achieved with a special driver and an additional wrapper function for
|
||||
handling extra commands. All this is implemented in the file bruker.h
|
||||
and bruker.c. The functions defined are:
|
||||
|
||||
\begin{verbatim}
|
||||
pEVDriver CreateBrukerDriver(int argc, char *argv[]);
|
||||
|
||||
int BrukerReadField(pEVControl self, float *fField);
|
||||
int BrukerReadCurrent(pEVControl self, float *fCurrent);
|
||||
|
||||
int BrukerAction(SConnection *pCon, SicsInterp *pSics, void *pData,
|
||||
int argc, char *argv[]);
|
||||
|
||||
\end{verbatim}
|
||||
|
||||
\begin{description}
|
||||
\item[CreateBrukerDriver] creates a driver for the bruker magnet
|
||||
controller.
|
||||
\item[BrukerReadField] reads the current magnetic field.
|
||||
\item[BrukerReadCurrent] reads the current current in Ampere.
|
||||
\item[BrukerAction] a special SICS interpreter wrapper function for
|
||||
the Bruker Magnet. This function handles the few special Bruker
|
||||
commands and passes everything else to the standard environment
|
||||
controller handler function.
|
||||
\end{description}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
64
bruker.w
Normal file
64
bruker.w
Normal file
@ -0,0 +1,64 @@
|
||||
\subsubsection{Bruker Magnet Controller B-EC-1}
|
||||
SANS is using a Bruker magnet controller. This controller is integrated
|
||||
into SICS as a derivate of an environment controller. The Bruker controller
|
||||
can be operated in two modes: in the first the current is controlled,
|
||||
in the second the current
|
||||
is controlled by an external hall sensor giving the magnetic field. Whatever
|
||||
is the controlling sensor, the magnetic field and the current need to be
|
||||
read. Furthermore this device supports switching the polarity. All this is
|
||||
achieved with a special driver and an additional wrapper function for
|
||||
handling extra commands. All this is implemented in the file bruker.h
|
||||
and bruker.c. The functions defined are:
|
||||
|
||||
\begin{verbatim}
|
||||
pEVDriver CreateBrukerDriver(int argc, char *argv[]);
|
||||
|
||||
int BrukerReadField(pEVControl self, float *fField);
|
||||
int BrukerReadCurrent(pEVControl self, float *fCurrent);
|
||||
|
||||
int BrukerAction(SConnection *pCon, SicsInterp *pSics, void *pData,
|
||||
int argc, char *argv[]);
|
||||
|
||||
\end{verbatim}
|
||||
|
||||
\begin{description}
|
||||
\item[CreateBrukerDriver] creates a driver for the bruker magnet
|
||||
controller.
|
||||
\item[BrukerReadField] reads the current magnetic field.
|
||||
\item[BrukerReadCurrent] reads the current current in Ampere.
|
||||
\item[BrukerAction] a special SICS interpreter wrapper function for
|
||||
the Bruker Magnet. This function handles the few special Bruker
|
||||
commands and passes everything else to the standard environment
|
||||
controller handler function.
|
||||
\end{description}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
584
buffer.c
Normal file
584
buffer.c
Normal file
@ -0,0 +1,584 @@
|
||||
/*--------------------------------------------------------------------------
|
||||
L N S R \"U N B U F F E R
|
||||
|
||||
|
||||
Mark Koennecke, January 1997
|
||||
|
||||
Copyright:
|
||||
|
||||
Labor fuer Neutronenstreuung
|
||||
Paul Scherrer Institut
|
||||
CH-5423 Villigen-PSI
|
||||
|
||||
|
||||
The authors hereby grant permission to use, copy, modify, distribute,
|
||||
and license this software and its documentation for any purpose, provided
|
||||
that existing copyright notices are retained in all copies and that this
|
||||
notice is included verbatim in any distributions. No written agreement,
|
||||
license, or royalty fee is required for any of the authorized uses.
|
||||
Modifications to this software may be copyrighted by their authors
|
||||
and need not follow the licensing terms described here, provided that
|
||||
the new terms are clearly indicated on the first page of each file where
|
||||
they apply.
|
||||
|
||||
IN NO EVENT SHALL THE AUTHORS OR DISTRIBUTORS BE LIABLE TO ANY PARTY
|
||||
FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
|
||||
ARISING OUT OF THE USE OF THIS SOFTWARE, ITS DOCUMENTATION, OR ANY
|
||||
DERIVATIVES THEREOF, EVEN IF THE AUTHORS HAVE BEEN ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
THE AUTHORS AND DISTRIBUTORS SPECIFICALLY DISCLAIM ANY WARRANTIES,
|
||||
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT. THIS SOFTWARE
|
||||
IS PROVIDED ON AN "AS IS" BASIS, AND THE AUTHORS AND DISTRIBUTORS HAVE
|
||||
NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR
|
||||
MODIFICATIONS.
|
||||
----------------------------------------------------------------------------*/
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <assert.h>
|
||||
#include <tcl.h>
|
||||
#include "fortify.h"
|
||||
#include "lld.h"
|
||||
#include "lld_blob.h"
|
||||
#include "lld_str.h"
|
||||
#include "conman.h"
|
||||
#include "obdes.h"
|
||||
#include "buffer.h"
|
||||
#include "fupa.h"
|
||||
#include "splitter.h"
|
||||
#include "ruli.h"
|
||||
/*-------------------------------------------------------------------------*/
|
||||
static int SaveBuffer(void *pData, char *name, FILE *fd)
|
||||
{
|
||||
pRuenBuffer self = NULL;
|
||||
int iRet;
|
||||
char *pPtr = NULL;
|
||||
|
||||
assert(fd);
|
||||
assert(pData);
|
||||
|
||||
self = (pRuenBuffer)pData;
|
||||
fprintf(fd,"# RuenBuffer %s\n",name);
|
||||
fprintf(fd,"Buf new %s\n",name);
|
||||
iRet = LLDnodePtr2First(self->iLineList);
|
||||
while(iRet != 0)
|
||||
{
|
||||
pPtr = (char *)LLDnodePtr(self->iLineList);
|
||||
fprintf(fd,"%s append %s\n",name,pPtr);
|
||||
iRet = LLDnodePtr2Next(self->iLineList);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*--------------------------------------------------------------------------*/
|
||||
pRuenBuffer CreateRuenBuffer(char *name)
|
||||
{
|
||||
pRuenBuffer pNew = NULL;
|
||||
|
||||
pNew = (pRuenBuffer)malloc(sizeof(RuenBuffer));
|
||||
if(!pNew)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
pNew->pDes = CreateDescriptor("SicsRuenBuffer");
|
||||
if(!pNew->pDes)
|
||||
{
|
||||
free(pNew);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
pNew->name = strdup(name);
|
||||
Fortify_CheckAllMemory();
|
||||
pNew->iLineList = LLDblobCreate();
|
||||
if(pNew->iLineList == -1)
|
||||
{
|
||||
DeleteDescriptor(pNew->pDes);
|
||||
free(pNew->name);
|
||||
free(pNew);
|
||||
return NULL;
|
||||
}
|
||||
pNew->pDes->SaveStatus = SaveBuffer;
|
||||
return pNew;
|
||||
}
|
||||
/*--------------------------------------------------------------------------*/
|
||||
static void DeleteLineBuffer(int iList)
|
||||
{
|
||||
int iRet;
|
||||
char *pPtr;
|
||||
|
||||
iRet = LLDnodePtr2First(iList);
|
||||
while(iRet != 0)
|
||||
{
|
||||
pPtr = (char *)LLDnodePtr(iList);
|
||||
free(pPtr);
|
||||
iRet = LLDnodePtr2Next(iList);
|
||||
}
|
||||
LLDdelete(iList);
|
||||
}
|
||||
/*-------------------------------------------------------------------------*/
|
||||
void DeleteRuenBuffer(void *self)
|
||||
{
|
||||
int iRet;
|
||||
pRuenBuffer pOld = (pRuenBuffer)self;
|
||||
|
||||
assert(pOld);
|
||||
/* delete line buffer */
|
||||
DeleteLineBuffer(pOld->iLineList);
|
||||
if(pOld->name)
|
||||
{
|
||||
free(pOld->name);
|
||||
}
|
||||
if(pOld->pDes)
|
||||
{
|
||||
DeleteDescriptor(pOld->pDes);
|
||||
}
|
||||
free(pOld);
|
||||
}
|
||||
/*--------------------------------------------------------------------------*/
|
||||
pRuenBuffer CopyRuenBuffer(pRuenBuffer pOld, char *name)
|
||||
{
|
||||
pRuenBuffer pNew = NULL;
|
||||
int iRet;
|
||||
char *pPtr;
|
||||
|
||||
pNew = CreateRuenBuffer(name);
|
||||
if(!pNew)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* copy list*/
|
||||
iRet = LLDnodePtr2First(pOld->iLineList);
|
||||
while(iRet != 0)
|
||||
{
|
||||
pPtr = (char *)LLDnodePtr(pOld->iLineList);
|
||||
LLDstringAdd(pNew->iLineList,pPtr);
|
||||
iRet = LLDnodePtr2Next(pOld->iLineList);
|
||||
}
|
||||
return pNew;
|
||||
}
|
||||
/*-------------------------------------------------------------------------*/
|
||||
int BufferAppendLine(pRuenBuffer self, char *line)
|
||||
{
|
||||
assert(self);
|
||||
|
||||
return LLDstringAppend(self->iLineList,line);
|
||||
}
|
||||
/*------------------------------------------------------------------------*/
|
||||
int BufferDel(pRuenBuffer self, int i)
|
||||
{
|
||||
int iNum;
|
||||
int iRet;
|
||||
|
||||
assert(self);
|
||||
|
||||
iRet = LLDnodePtr2First(self->iLineList);
|
||||
iNum = 0;
|
||||
while(iRet != 0)
|
||||
{
|
||||
if(iNum == i)
|
||||
{
|
||||
LLDstringDelete(self->iLineList);
|
||||
return 1;
|
||||
}
|
||||
iNum++;
|
||||
iRet = LLDnodePtr2Next(self->iLineList);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
/*------------------------------------------------------------------------*/
|
||||
int BufferInsertAfter(pRuenBuffer self, int i, char *line)
|
||||
{
|
||||
int iNum;
|
||||
int iRet;
|
||||
|
||||
assert(self);
|
||||
|
||||
iRet = LLDnodePtr2First(self->iLineList);
|
||||
iNum = 0;
|
||||
while(iRet != 0)
|
||||
{
|
||||
if(iNum == i)
|
||||
{
|
||||
LLDstringInsert(self->iLineList, line);
|
||||
return 1;
|
||||
}
|
||||
iNum++;
|
||||
iRet = LLDnodePtr2Next(self->iLineList);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
/*------------------------------------------------------------------------*/
|
||||
int BufferPrint(pRuenBuffer self, SConnection *pCon)
|
||||
{
|
||||
int iRet;
|
||||
char *pPtr = NULL;
|
||||
char pBueffel[512];
|
||||
int iCount = 1;
|
||||
|
||||
iRet = LLDnodePtr2First(self->iLineList);
|
||||
sprintf(pBueffel,"Listing for Bueffer %s",self->name);
|
||||
SCWrite(pCon,pBueffel,eValue);
|
||||
while(iRet != 0)
|
||||
{
|
||||
pPtr = (char *)LLDnodePtr(self->iLineList);
|
||||
sprintf(pBueffel,"[%d] %s",iCount,pPtr);
|
||||
SCWrite(pCon,pBueffel,eValue);
|
||||
iRet = LLDnodePtr2Next(self->iLineList);
|
||||
iCount++;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*------------------------------------------------------------------------*/
|
||||
extern char *StrReplace(char *str, char *old, char *pNew);
|
||||
/* realised in Strrepl.c
|
||||
*/
|
||||
|
||||
int BufferReplace(pRuenBuffer self, char *pattern, char *pReplace)
|
||||
{
|
||||
int iRet;
|
||||
char *pPtr = NULL;
|
||||
char pBueffel[1024];
|
||||
char *pRet;
|
||||
|
||||
iRet = LLDnodePtr2First(self->iLineList);
|
||||
while(iRet != 0)
|
||||
{
|
||||
pPtr = (char *)LLDnodePtr(self->iLineList);
|
||||
strcpy(pBueffel,pPtr);
|
||||
pRet = NULL;
|
||||
pRet = StrReplace(pBueffel,pattern,pReplace);
|
||||
if(pRet)
|
||||
{
|
||||
LLDstringDelete(self->iLineList);
|
||||
iRet = LLDnodePtr2Next(self->iLineList);
|
||||
LLDnodePtr2Prev(self->iLineList);
|
||||
if(iRet)
|
||||
{
|
||||
LLDstringInsert(self->iLineList,pBueffel);
|
||||
}
|
||||
else
|
||||
{
|
||||
LLDstringAppend(self->iLineList,pBueffel);
|
||||
}
|
||||
}
|
||||
iRet = LLDnodePtr2Next(self->iLineList);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
/*-----------------------------------------------------------------------*/
|
||||
int BufferRun(pRuenBuffer self, SConnection *pCon, SicsInterp *pSics)
|
||||
{
|
||||
int iRet;
|
||||
char *pPtr = NULL;
|
||||
int iInt, iRes;
|
||||
|
||||
iRes = 1;
|
||||
iRet = LLDnodePtr2First(self->iLineList);
|
||||
while(iRet != 0)
|
||||
{
|
||||
pPtr = (char *)LLDnodePtr(self->iLineList);
|
||||
iInt = InterpExecute(pSics,pCon,pPtr);
|
||||
if(!iInt)
|
||||
{
|
||||
iRes = 0;
|
||||
}
|
||||
iRet = LLDnodePtr2Next(self->iLineList);
|
||||
}
|
||||
return iRes;
|
||||
}
|
||||
/*------------------------------------------------------------------------*/
|
||||
int BufferSave(pRuenBuffer self, char *file)
|
||||
{
|
||||
int iRet;
|
||||
char *pPtr = NULL;
|
||||
FILE *fd = NULL;
|
||||
|
||||
fd = fopen(file,"w");
|
||||
if(fd == NULL)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
iRet = LLDnodePtr2First(self->iLineList);
|
||||
while(iRet != 0)
|
||||
{
|
||||
pPtr = (char *)LLDnodePtr(self->iLineList);
|
||||
fprintf(fd,"%s\n",pPtr);
|
||||
iRet = LLDnodePtr2Next(self->iLineList);
|
||||
}
|
||||
fclose(fd);
|
||||
return 1;
|
||||
}
|
||||
/*------------------------------------------------------------------------*/
|
||||
int BufferLoad(pRuenBuffer self, char *file)
|
||||
{
|
||||
int iRet;
|
||||
char *pPtr = NULL;
|
||||
FILE *fd = NULL;
|
||||
char pBueffel[256];
|
||||
|
||||
fd = fopen(file,"r");
|
||||
if(fd == NULL)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
pPtr = fgets(pBueffel,255,fd);
|
||||
while(pPtr != NULL)
|
||||
{
|
||||
LLDstringAppend(self->iLineList,pBueffel);
|
||||
pPtr = fgets(pBueffel,255,fd);
|
||||
}
|
||||
|
||||
fclose(fd);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*------------------------------------------------------------------------*/
|
||||
pRuenBuffer FindRuenBuffer(SicsInterp *pSics, char *name)
|
||||
{
|
||||
pRuenBuffer pBuf = NULL;
|
||||
CommandList *pCom = NULL;
|
||||
|
||||
pCom = FindCommand(pSics,name);
|
||||
if(!pCom)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
pBuf = (pRuenBuffer)pCom->pData;
|
||||
if(!pBuf)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
if(!pBuf->pDes)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
if(strcmp(pBuf->pDes->name,"SicsRuenBuffer") != 0)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
return pBuf;
|
||||
}
|
||||
/*-------------------------------------------------------------------------*/
|
||||
int InitBufferSys(SConnection *pCon, SicsInterp *pSics, void *pData,
|
||||
int argc, char *argv[])
|
||||
{
|
||||
pRuenStack pStack = NULL;
|
||||
|
||||
pStack = CreateRuenStack();
|
||||
if(!pStack)
|
||||
{
|
||||
SCWrite(pCon,"ERROR: No memory to create Ruen-Stack",eError);
|
||||
return 0;
|
||||
}
|
||||
AddCommand(pSics,"Buf",BufferCommand,NULL,NULL);
|
||||
AddCommand(pSics,"Stack",RuenStackAction,DeleteRuenStack,pStack);
|
||||
return 1;
|
||||
}
|
||||
/*------------------------------------------------------------------------*/
|
||||
int BufferCommand(SConnection *pCon, SicsInterp *pSics, void *pData,
|
||||
int argc, char *argv[])
|
||||
{
|
||||
int iRet, iRet2;
|
||||
char pBueffel[512];
|
||||
char **argx;
|
||||
FuPaResult PaRes;
|
||||
pRuenBuffer pBuf = NULL;
|
||||
FuncTemplate BufferTemplate[] = {
|
||||
{"new",1,{FUPATEXT} },
|
||||
{"del",1,{FUPATEXT} },
|
||||
{"copy",2,{FUPATEXT, FUPATEXT}},
|
||||
};
|
||||
|
||||
assert(pCon);
|
||||
assert(pSics);
|
||||
|
||||
/* minimum user to use this */
|
||||
if(!SCMatchRights(pCon,usUser))
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
/* parse function args */
|
||||
argtolower(argc,argv);
|
||||
argx = &argv[1];
|
||||
iRet = EvaluateFuPa((pFuncTemplate)&BufferTemplate,3,argc-1,argx,&PaRes);
|
||||
if(iRet < 0)
|
||||
{
|
||||
sprintf(pBueffel,"%s",PaRes.pError);
|
||||
SCWrite(pCon,pBueffel,eError);
|
||||
return 0;
|
||||
}
|
||||
|
||||
switch(iRet)
|
||||
{
|
||||
case 0: /* new */
|
||||
pBuf = CreateRuenBuffer(PaRes.Arg[0].text);
|
||||
if(!pBuf)
|
||||
{
|
||||
SCWrite(pCon, "ERROR: Out of memory allocating buffer",eError);
|
||||
return 0;
|
||||
}
|
||||
iRet2 = AddCommand(pSics,pBuf->name,BufferAction,DeleteRuenBuffer,
|
||||
(void *)pBuf);
|
||||
if(!iRet2)
|
||||
{
|
||||
sprintf(pBueffel,"ERROR: duplicate command %s not created",pBuf->name);
|
||||
SCWrite(pCon,pBueffel,eError);
|
||||
DeleteRuenBuffer((void *)pBuf);
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
break;
|
||||
case 1: /* del */
|
||||
return RemoveCommand(pSics,PaRes.Arg[0].text);
|
||||
break;
|
||||
case 2: /* copy */
|
||||
pBuf = FindRuenBuffer(pSics,PaRes.Arg[0].text);
|
||||
if(!pBuf)
|
||||
{
|
||||
sprintf(pBueffel,"ERROR: Buffer %s not found",
|
||||
PaRes.Arg[0].text);
|
||||
SCWrite(pCon,pBueffel,eError);
|
||||
return 0;
|
||||
}
|
||||
pBuf = CopyRuenBuffer(pBuf,PaRes.Arg[1].text);
|
||||
if(!pBuf)
|
||||
{
|
||||
sprintf(pBueffel,"ERROR: creating buffer %s ",
|
||||
PaRes.Arg[1].text);
|
||||
SCWrite(pCon,pBueffel,eError);
|
||||
return 0;
|
||||
}
|
||||
iRet2 = AddCommand(pSics,pBuf->name,BufferAction,DeleteRuenBuffer,
|
||||
(void *)pBuf);
|
||||
if(!iRet2)
|
||||
{
|
||||
sprintf(pBueffel,"ERROR: duplicate command %s not created",pBuf->name);
|
||||
SCWrite(pCon,pBueffel,eError);
|
||||
DeleteRuenBuffer((void *)pBuf);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
break;
|
||||
default:
|
||||
assert(0);
|
||||
break;
|
||||
|
||||
}
|
||||
assert(0);
|
||||
}
|
||||
/*-------------------------------------------------------------------------*/
|
||||
int BufferAction(SConnection *pCon, SicsInterp *pSics, void *pData,
|
||||
int argc, char *argv[])
|
||||
{
|
||||
int iRet, iRet2;
|
||||
char pBueffel[512];
|
||||
char **argx;
|
||||
FuPaResult PaRes;
|
||||
pRuenBuffer pBuf = NULL;
|
||||
FuncTemplate BufferTemplate[] = {
|
||||
{"append",0,{FUPATEXT} },
|
||||
{"del",1,{FUPAINT} },
|
||||
{"ins",1,{FUPAINT}},
|
||||
{"save",1,{FUPATEXT}},
|
||||
{"load",1,{FUPATEXT}},
|
||||
{"subst",2,{FUPATEXT,FUPATEXT}},
|
||||
{"print",0,{0,0}},
|
||||
{"run",0,{0,0}},
|
||||
NULL
|
||||
};
|
||||
|
||||
assert(pCon);
|
||||
assert(pSics);
|
||||
pBuf = (pRuenBuffer)pData;
|
||||
assert(pBuf);
|
||||
|
||||
|
||||
/* You need to be user in order to do this */
|
||||
if(!SCMatchRights(pCon,usUser))
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
/* parse function args */
|
||||
argx = &argv[1];
|
||||
strtolower(argx[0]);
|
||||
iRet = EvaluateFuPa((pFuncTemplate)&BufferTemplate,8,argc-1,argx,&PaRes);
|
||||
if(iRet < 0)
|
||||
{
|
||||
sprintf(pBueffel,"%s",PaRes.pError);
|
||||
SCWrite(pCon,pBueffel,eError);
|
||||
return 0;
|
||||
}
|
||||
|
||||
switch(iRet)
|
||||
{
|
||||
case 0: /* append */
|
||||
argx = &argv[2];
|
||||
Arg2Text(argc-2,argx,pBueffel,511);
|
||||
BufferAppendLine(pBuf,pBueffel);
|
||||
SCSendOK(pCon);
|
||||
return 1;
|
||||
break;
|
||||
case 1: /* del */
|
||||
iRet2 = BufferDel(pBuf,PaRes.Arg[0].iVal);
|
||||
if(iRet2)
|
||||
SCSendOK(pCon);
|
||||
break;
|
||||
case 2: /* ins */
|
||||
argx = &argv[3];
|
||||
Arg2Text(argc-3,argx,pBueffel,511);
|
||||
iRet2 = BufferInsertAfter(pBuf,PaRes.Arg[0].iVal,pBueffel);
|
||||
if(iRet2)
|
||||
SCSendOK(pCon);
|
||||
return iRet2;
|
||||
break;
|
||||
case 3: /* save */
|
||||
iRet2 = BufferSave(pBuf,PaRes.Arg[0].text);
|
||||
if(!iRet2)
|
||||
{
|
||||
sprintf(pBueffel,"ERROR: cannot open %s for writing",
|
||||
PaRes.Arg[0].text);
|
||||
SCWrite(pCon,pBueffel,eError);
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
SCSendOK(pCon);
|
||||
return 1;
|
||||
}
|
||||
break;
|
||||
case 4: /* load */
|
||||
iRet2 = BufferLoad(pBuf,PaRes.Arg[0].text);
|
||||
if(!iRet2)
|
||||
{
|
||||
sprintf(pBueffel,"ERROR: cannot open %s for reading ",
|
||||
PaRes.Arg[0].text);
|
||||
SCWrite(pCon,pBueffel,eError);
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
SCSendOK(pCon);
|
||||
return 1;
|
||||
}
|
||||
break;
|
||||
case 5: /* subst */
|
||||
iRet2 = BufferReplace(pBuf,PaRes.Arg[0].text,PaRes.Arg[1].text);
|
||||
if(iRet2)
|
||||
SCSendOK(pCon);
|
||||
break;
|
||||
case 6: /* print */
|
||||
return BufferPrint(pBuf,pCon);
|
||||
break;
|
||||
case 7: /* run */
|
||||
return BufferRun(pBuf,pCon,pSics);
|
||||
default:
|
||||
assert(0);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
94
buffer.h
Normal file
94
buffer.h
Normal file
@ -0,0 +1,94 @@
|
||||
/*---------------------------------------------------------------------------
|
||||
|
||||
T H E L N S R \" U N B U F F E R
|
||||
|
||||
The LNS has devised a special scheme to operate an instrument
|
||||
via R\"un sequeneces and buffers. A R\"unbuffer is a series of
|
||||
commands which are collected in a buffer. This buffer is
|
||||
implemented here. A buffer can be added to, printed loaded from
|
||||
a file etc. and can be executed.
|
||||
|
||||
The next schem is the R\"unlist which is a stack of R\"unbuffers.
|
||||
That list can be exeuted as well. It gets a buffer from the
|
||||
bottom of the stack and executes it and does so until the stack
|
||||
is empty. While this is happening you are able to add other
|
||||
buffers to the top of the stack. This schem is implemented in module
|
||||
ruli.
|
||||
|
||||
So, here is all necessary to deal with an individual buffer.
|
||||
For Lists A. Reitsma's lld package will be used. This package
|
||||
identifies a list by an integer handle.
|
||||
|
||||
Mark Koennecke, January 1996
|
||||
|
||||
copyright: see implementation file
|
||||
----------------------------------------------------------------------------*/
|
||||
#ifndef RUENBUFFER
|
||||
#define RUENBUFFER
|
||||
|
||||
typedef struct {
|
||||
pObjectDescriptor pDes; /* needed */
|
||||
char *name; /* BufferName */
|
||||
int iLineList; /* Handle to the Line List */
|
||||
} RuenBuffer, *pRuenBuffer;
|
||||
|
||||
/*--------------------- live & death ----------------------------------- */
|
||||
pRuenBuffer CreateRuenBuffer(char *name);
|
||||
void DeleteRuenBuffer(void *pSelf);
|
||||
pRuenBuffer CopyRuenBuffer(pRuenBuffer pOld, char *NewName);
|
||||
|
||||
/*--------------------- operations --------------------------------------*/
|
||||
|
||||
int BufferAppendLine(pRuenBuffer self, char *line);
|
||||
int BufferDel(pRuenBuffer self, int iLine);
|
||||
/*
|
||||
deletes line iLine from the RuenBuffer self
|
||||
|
||||
-------------------------------------------------------------------------*/
|
||||
int BufferInsertAfter(pRuenBuffer self, int iLine, char *line);
|
||||
/*
|
||||
inserts line line AFTER line number iLine in the RuenBuffer self
|
||||
------------------------------------------------------------------------- */
|
||||
int BufferPrint(pRuenBuffer self, SConnection *pCon);
|
||||
/*
|
||||
lists the contents of the RuenBuffer on the Connection pCon
|
||||
------------------------------------------------------------------------ */
|
||||
int BufferReplace(pRuenBuffer self, char *pattern, char *pReplace);
|
||||
/*
|
||||
replaces all occurences of the string pattern in the whole RuenBuffer
|
||||
by the replacement string pReplace.
|
||||
------------------------------------------------------------------------- */
|
||||
int BufferRun(pRuenBuffer self, SConnection *pCon, SicsInterp *pSics);
|
||||
/*
|
||||
executes the lines of the Ruenbuffer one by one.
|
||||
Returns 1 on success, 0 on error.
|
||||
------------------------------------------------------------------------- */
|
||||
int BufferSave(pRuenBuffer self, char *file);
|
||||
/*
|
||||
writes the contents of Ruenbuffer self to the file specified by
|
||||
file.
|
||||
Returns 1 on success, 0 on error.
|
||||
--------------------------------------------------------------------------*/
|
||||
int BufferLoad(pRuenBuffer self, char *file);
|
||||
/*
|
||||
reads the contents of file into the RuenBuffer self.
|
||||
Returns 1 on success, 0 on error.
|
||||
*/
|
||||
/* ------------------------ object functions ----------------------------*/
|
||||
int InitBufferSys(SConnection *pCon, SicsInterp *pSics, void *pData,
|
||||
int argc, char *argv[]);
|
||||
int BufferCommand(SConnection *pCon, SicsInterp *pSics, void *pData,
|
||||
int argc, char *argv[]);
|
||||
int BufferAction(SConnection *pCon, SicsInterp *pSics, void *pData,
|
||||
int argc, char *argv[]);
|
||||
|
||||
/* ----------------------- utility --------------------------------------*/
|
||||
pRuenBuffer FindRuenBuffer(SicsInterp *pSics, char *name);
|
||||
/*
|
||||
similar to FindCommand in SCinter.h. But checks the object found if
|
||||
it is a RuenBuffer.
|
||||
Returns NULL if no RuenBuffer with this name could be found.
|
||||
Returns a pointer to the RuenBuffer, when a RuenBuffer of this
|
||||
name could be found in the interpreter pSics
|
||||
----------------------------------------------------------------------------*/
|
||||
#endif
|
29
build
Executable file
29
build
Executable file
@ -0,0 +1,29 @@
|
||||
#!/bin/sh
|
||||
#---------------------------------------------------------------------------
|
||||
# build SICS from Scratch
|
||||
#
|
||||
# Mark Koennecke, September 2000
|
||||
#--------------------------------------------------------------------------
|
||||
|
||||
#----- build hardsup
|
||||
cd hardsup
|
||||
make
|
||||
cd ..
|
||||
|
||||
#------- build tecs
|
||||
cd tecs
|
||||
make
|
||||
cd ..
|
||||
|
||||
#----- build difrac
|
||||
#cd difrac
|
||||
#make
|
||||
#cd ..
|
||||
#
|
||||
#---- build matrix
|
||||
cd matrix
|
||||
make
|
||||
cd ..
|
||||
|
||||
#------- finally build SICS
|
||||
make
|
370
callback.c
Normal file
370
callback.c
Normal file
@ -0,0 +1,370 @@
|
||||
/*--------------------------------------------------------------------------
|
||||
|
||||
S I C S C A L L B A C K
|
||||
|
||||
Functions needed to deal with the SICSCallback interface. Description is
|
||||
in file interface.h, interface.w and interface.w.
|
||||
|
||||
Mark Koennecke, Juli 1997
|
||||
|
||||
Added ScriptCallback, Mark Koennecke, June 2003
|
||||
|
||||
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 <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <assert.h>
|
||||
#include <tcl.h>
|
||||
#include "fortify.h"
|
||||
#include "lld.h"
|
||||
#include "sics.h"
|
||||
#include "macro.h"
|
||||
|
||||
|
||||
#define CALLBACK 17777
|
||||
|
||||
|
||||
/*--------------------- The interface datastructure ---------------------*/
|
||||
typedef struct __ICallBack {
|
||||
int iID;
|
||||
int iList;
|
||||
} ICallBack;
|
||||
|
||||
/*-------------- The data stored for a single callback ------------------*/
|
||||
typedef struct {
|
||||
long iID;
|
||||
SICSCallBack pFunc;
|
||||
void *pUserData;
|
||||
KillFuncIT pKill;
|
||||
int iEvent;
|
||||
} CallBackItem, *pCallBackItem;
|
||||
/*------------------------------------------------------------------------*/
|
||||
static int CheckPointer(pICallBack self)
|
||||
{
|
||||
if(self == NULL) return 0;
|
||||
if(self->iID != CALLBACK)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
/*-------------------------------------------------------------------------*/
|
||||
|
||||
pICallBack CreateCallBackInterface(void)
|
||||
{
|
||||
pICallBack pNew = NULL;
|
||||
|
||||
pNew = (pICallBack)malloc(sizeof(ICallBack));
|
||||
if(!pNew)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
pNew->iID = CALLBACK;
|
||||
pNew->iList = LLDcreate(sizeof(CallBackItem));
|
||||
if(pNew->iList < 0)
|
||||
{
|
||||
free(pNew);
|
||||
return NULL;
|
||||
}
|
||||
return pNew;
|
||||
}
|
||||
/*--------------------------------------------------------------------------*/
|
||||
void DeleteCallBackInterface(pICallBack self)
|
||||
{
|
||||
int iRet;
|
||||
CallBackItem sItem;
|
||||
|
||||
if(!CheckPointer(self))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
/* kill all userdata associated with callbacks */
|
||||
iRet = LLDnodePtr2First(self->iList);
|
||||
while(iRet != 0)
|
||||
{
|
||||
LLDnodeDataTo(self->iList,&sItem);
|
||||
if(sItem.pKill != NULL)
|
||||
{
|
||||
sItem.pKill(sItem.pUserData);
|
||||
}
|
||||
iRet = LLDnodePtr2Next(self->iList);
|
||||
}
|
||||
|
||||
LLDdelete(self->iList);
|
||||
free(self);
|
||||
}
|
||||
/*--------------------------------------------------------------------------*/
|
||||
int InvokeCallBack(pICallBack self, int iEvent, void *pEventData)
|
||||
{
|
||||
CallBackItem sItem;
|
||||
int iCurrent, iRet;
|
||||
int iResult = 1;
|
||||
|
||||
if(!CheckPointer(self))
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
iCurrent = LLDnodePtr2First(self->iList);
|
||||
while(iCurrent != 0)
|
||||
{
|
||||
LLDnodeDataTo(self->iList,&sItem);
|
||||
if(sItem.iEvent == iEvent)
|
||||
{
|
||||
iRet = sItem.pFunc(iEvent, pEventData,sItem.pUserData);
|
||||
if(!iRet)
|
||||
{
|
||||
iResult = 0;
|
||||
}
|
||||
}
|
||||
iCurrent = LLDnodePtr2Next(self->iList);
|
||||
}
|
||||
return iResult;
|
||||
}
|
||||
/*--------------------------------------------------------------------------*/
|
||||
static long lCount = 1L;
|
||||
|
||||
long RegisterCallback(pICallBack self, int iEvent,
|
||||
SICSCallBack pFunc,
|
||||
void *pUserData, KillFunc pKFunc)
|
||||
{
|
||||
CallBackItem sItem;
|
||||
|
||||
if(!CheckPointer(self))
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
sItem.iID = lCount++;
|
||||
assert(pFunc);
|
||||
sItem.pFunc = pFunc;
|
||||
sItem.iEvent = iEvent;
|
||||
sItem.pUserData = pUserData;
|
||||
sItem.pKill = pKFunc;
|
||||
|
||||
LLDnodeAppendFrom(self->iList,&sItem);
|
||||
return sItem.iID;
|
||||
}
|
||||
/*-------------------------------------------------------------------------*/
|
||||
int RemoveCallback(pICallBack self, long lID)
|
||||
{
|
||||
CallBackItem sItem;
|
||||
int iCurrent;
|
||||
|
||||
if(!CheckPointer(self))
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
iCurrent = LLDnodePtr2First(self->iList);
|
||||
while(iCurrent != 0)
|
||||
{
|
||||
LLDnodeDataTo(self->iList,&sItem);
|
||||
if(sItem.iID == lID)
|
||||
{
|
||||
if(sItem.pKill != NULL)
|
||||
{
|
||||
sItem.pKill(sItem.pUserData);
|
||||
}
|
||||
LLDnodeDelete(self->iList);
|
||||
return 1;
|
||||
}
|
||||
iCurrent = LLDnodePtr2Next(self->iList);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
/*--------------------------------------------------------------------------*/
|
||||
int RemoveCallback2(pICallBack self, void *pUserData)
|
||||
{
|
||||
CallBackItem sItem;
|
||||
int iCurrent;
|
||||
|
||||
if(!CheckPointer(self))
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
iCurrent = LLDnodePtr2First(self->iList);
|
||||
while(iCurrent != 0)
|
||||
{
|
||||
LLDnodeDataTo(self->iList,&sItem);
|
||||
if(sItem.pUserData == pUserData)
|
||||
{
|
||||
if(sItem.pKill != NULL)
|
||||
{
|
||||
sItem.pKill(sItem.pUserData);
|
||||
}
|
||||
LLDnodeDelete(self->iList);
|
||||
}
|
||||
iCurrent = LLDnodePtr2Next(self->iList);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
/*-------------------------------------------------------------------
|
||||
a write function for the connection which writes to stdout
|
||||
-------------------------------------------------------------------*/
|
||||
static int CallbackWrite(SConnection *pCon,char *message, int outCode)
|
||||
{
|
||||
if(outCode >= eWarning)
|
||||
{
|
||||
fputs(message,stdout);
|
||||
fputs("\n",stdout);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
/*-----------------------------------------------------------------------
|
||||
the actual callback function invoking the script
|
||||
------------------------------------------------------------------------*/
|
||||
static int ScriptCallback(int iEvent, void *pEventData, void *pUserData)
|
||||
{
|
||||
SConnection *pCon = NULL;
|
||||
Tcl_Interp *pTcl;
|
||||
int status;
|
||||
|
||||
pCon = SCCreateDummyConnection(pServ->pSics);
|
||||
if(!pCon)
|
||||
{
|
||||
fprintf(stdout,"ERROR: failed to create dummy connection\n");
|
||||
return 0;
|
||||
}
|
||||
if(pUserData == NULL)
|
||||
{
|
||||
fprintf(stdout,"ERROR: ScriptCallback: no script to execute\n");
|
||||
return 0;
|
||||
}
|
||||
SCSetWriteFunc(pCon,CallbackWrite);
|
||||
MacroPush(pCon);
|
||||
pTcl = InterpGetTcl(pServ->pSics);
|
||||
status = Tcl_GlobalEval(pTcl,(char *)pUserData);
|
||||
if(status != TCL_OK)
|
||||
{
|
||||
fprintf(stdout,"ERROR: in CallbackScript: %s\n",(char *)pUserData);
|
||||
fprintf(stdout,"Tcl-error: %s\n",pTcl->result);
|
||||
}
|
||||
MacroPop();
|
||||
SCDeleteConnection(pCon);
|
||||
return 1;
|
||||
}
|
||||
/*------------------------------------------------------------------------*/
|
||||
int CallbackScript(SConnection *pCon, SicsInterp *pSics, void *pData,
|
||||
int argc, char *argv[])
|
||||
{
|
||||
long lID;
|
||||
int iEvent, status;
|
||||
pICallBack pCall = NULL;
|
||||
CommandList *pCom = NULL;
|
||||
char pBuffer[132];
|
||||
|
||||
if(argc < 2)
|
||||
{
|
||||
SCWrite(pCon,"ERROR: insufficient number of arguments to callbackScript",
|
||||
eError);
|
||||
return 0;
|
||||
}
|
||||
/*
|
||||
only managers may do this
|
||||
*/
|
||||
if(!SCMatchRights(pCon,usMugger))
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
strtolower(argv[1]);
|
||||
if(strcmp(argv[1],"connect") == 0)
|
||||
{
|
||||
if(argc < 5)
|
||||
{
|
||||
SCWrite(pCon,"ERROR: not enough arguments to CallbackScript connect",
|
||||
eError);
|
||||
return 0;
|
||||
}
|
||||
strtolower(argv[2]);
|
||||
pCom = FindCommand(pSics,argv[2]);
|
||||
if(!pCom)
|
||||
{
|
||||
SCWrite(pCon,"ERROR: object to connect to not found",eError);
|
||||
return 0;
|
||||
}
|
||||
pCall = GetCallbackInterface(pCom->pData);
|
||||
if(!pCall)
|
||||
{
|
||||
SCWrite(pCon,"ERROR: object has no callback interface",eError);
|
||||
return 0;
|
||||
}
|
||||
iEvent = Text2Event(argv[3]);
|
||||
if(iEvent < 0)
|
||||
{
|
||||
SCWrite(pCon,"ERROR: event type not known",eError);
|
||||
return 0;
|
||||
}
|
||||
lID = RegisterCallback(pCall,iEvent,ScriptCallback,
|
||||
strdup(argv[4]),free);
|
||||
sprintf(pBuffer,"callback = %ld", lID);
|
||||
SCWrite(pCon,pBuffer,eValue);
|
||||
return 1;
|
||||
}
|
||||
else if(strcmp(argv[1],"remove") == 0)
|
||||
{
|
||||
if(argc < 4)
|
||||
{
|
||||
SCWrite(pCon,"ERROR: not enough arguments to CallbackScript remove",
|
||||
eError);
|
||||
return 0;
|
||||
}
|
||||
strtolower(argv[2]);
|
||||
pCom = FindCommand(pSics,argv[2]);
|
||||
if(!pCom)
|
||||
{
|
||||
SCWrite(pCon,"ERROR: object to remove to not found",eError);
|
||||
return 0;
|
||||
}
|
||||
pCall = GetCallbackInterface(pCom->pData);
|
||||
if(!pCall)
|
||||
{
|
||||
SCWrite(pCon,"ERROR: object has no callback interface",eError);
|
||||
return 0;
|
||||
}
|
||||
status = Tcl_GetInt(InterpGetTcl(pSics),argv[3],&iEvent);
|
||||
if(status != TCL_OK)
|
||||
{
|
||||
SCWrite(pCon,"ERROR: failed to convert callback ID to int",eError);
|
||||
return 0;
|
||||
}
|
||||
RemoveCallback(pCall,(long)iEvent);
|
||||
SCSendOK(pCon);
|
||||
return 1;
|
||||
}
|
||||
|
||||
SCWrite(pCon,"ERROR: subcommand to CallbackScript not known",eError);
|
||||
return 0;
|
||||
}
|
79
center.tex
Normal file
79
center.tex
Normal file
@ -0,0 +1,79 @@
|
||||
\subsection{Fit and Center}
|
||||
This is a fit routine for SICS. It takes a scan and tries to find a peak and
|
||||
its position. Trials showed that fitting a gauss function is not robust
|
||||
enough for this facility which has to cope with bizarre peak shapes, half
|
||||
finished measurements and the like. The algorithm choosen tries to find the
|
||||
center of gravity of the peak. It does this by searching for the maximum
|
||||
point in the diagram first. Then the points where the peak is below
|
||||
half maximum are searched for either side of the peak. Within these
|
||||
limits the COG is calculated. When this is done fit will print some
|
||||
info about the peak.
|
||||
|
||||
Center will the drive the scan variable to the COG of the peak.
|
||||
|
||||
The interface to this simple facility is simple:
|
||||
|
||||
\begin{flushleft} \small
|
||||
\begin{minipage}{\linewidth} \label{scrap1}
|
||||
$\langle$fitinter {\footnotesize ?}$\rangle\equiv$
|
||||
\vspace{-1ex}
|
||||
\begin{list}{}{} \item
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@ typedef struct __FitCenter *pFit;@\\
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@/*--------------------------------------------------------------------------*/@\\
|
||||
\mbox{}\verb@ pFit CreateFitCenter(pScanData pScan);@\\
|
||||
\mbox{}\verb@ void DeleteFitCenter(void *pData);@\\
|
||||
\mbox{}\verb@/*-------------------------------------------------------------------------*/@\\
|
||||
\mbox{}\verb@ int CalculateFit(pFit self);@\\
|
||||
\mbox{}\verb@ /* @\\
|
||||
\mbox{}\verb@ CalcluateFit returns: -1 when left FWHM could not be found@\\
|
||||
\mbox{}\verb@ -2 when right FWHM could not be found@\\
|
||||
\mbox{}\verb@ 1 on success@\\
|
||||
\mbox{}\verb@ */@\\
|
||||
\mbox{}\verb@ int CalculateFitFromData(pFit self, float fAxis[], long lSum[], @\\
|
||||
\mbox{}\verb@ int iLen);@\\
|
||||
\mbox{}\verb@ void GetFitResults(pFit self, float *fNewCenter, float *fStdDev,@\\
|
||||
\mbox{}\verb@ float *FWHM, float *fMax);@\\
|
||||
\mbox{}\verb@ int DriveCenter(pFit self, SConnection *pCon, SicsInterp *pSics);@\\
|
||||
\mbox{}\verb@/*-------------------------------------------------------------------------*/@\\
|
||||
\mbox{}\verb@ int FitFactory(SConnection *pCon,SicsInterp *pSics, void *pData,@\\
|
||||
\mbox{}\verb@ int argc, char *argv[]);@\\
|
||||
\mbox{}\verb@ int FitWrapper(SConnection *pCon,SicsInterp *pSics, void *pData,@\\
|
||||
\mbox{}\verb@ int argc, char *argv[]);@\\
|
||||
\mbox{}\verb@ int CenterWrapper(SConnection *pCon,SicsInterp *pSics, void *pData,@\\
|
||||
\mbox{}\verb@ int argc, char *argv[]);@\\
|
||||
\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}
|
||||
\begin{flushleft} \small
|
||||
\begin{minipage}{\linewidth} \label{scrap2}
|
||||
\verb@"fitcenter.h"@ {\footnotesize ? }$\equiv$
|
||||
\vspace{-1ex}
|
||||
\begin{list}{}{} \item
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@/*---------------------------------------------------------------------------@\\
|
||||
\mbox{}\verb@ F I T C E N T E R@\\
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@ A simple peak finding and center of gravity determination facility for@\\
|
||||
\mbox{}\verb@ SICS.@\\
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@ copyright: see copyright.h@\\
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@ Mark Koennecke, October 1997@\\
|
||||
\mbox{}\verb@----------------------------------------------------------------------------*/@\\
|
||||
\mbox{}\verb@#ifndef SICSFITCENTER@\\
|
||||
\mbox{}\verb@#define SICSFITCENTER@\\
|
||||
\mbox{}\verb@@$\langle$fitinter {\footnotesize ?}$\rangle$\verb@@\\
|
||||
\mbox{}\verb@#endif@\\
|
||||
\mbox{}\verb@@$\diamond$
|
||||
\end{list}
|
||||
\vspace{-2ex}
|
||||
\end{minipage}\\[4ex]
|
||||
\end{flushleft}
|
58
center.w
Normal file
58
center.w
Normal file
@ -0,0 +1,58 @@
|
||||
\subsection{Fit and Center}
|
||||
This is a fit routine for SICS. It takes a scan and tries to find a peak and
|
||||
its position. Trials showed that fitting a gauss function is not robust
|
||||
enough for this facility which has to cope with bizarre peak shapes, half
|
||||
finished measurements and the like. The algorithm choosen tries to find the
|
||||
center of gravity of the peak. It does this by searching for the maximum
|
||||
point in the diagram first. Then the points where the peak is below
|
||||
half maximum are searched for either side of the peak. Within these
|
||||
limits the COG is calculated. When this is done fit will print some
|
||||
info about the peak.
|
||||
|
||||
Center will the drive the scan variable to the COG of the peak.
|
||||
|
||||
The interface to this simple facility is simple:
|
||||
|
||||
@d fitinter @{
|
||||
typedef struct __FitCenter *pFit;
|
||||
|
||||
/*--------------------------------------------------------------------------*/
|
||||
pFit CreateFitCenter(pScanData pScan);
|
||||
void DeleteFitCenter(void *pData);
|
||||
/*-------------------------------------------------------------------------*/
|
||||
int CalculateFit(pFit self);
|
||||
/*
|
||||
CalcluateFit returns: -1 when left FWHM could not be found
|
||||
-2 when right FWHM could not be found
|
||||
1 on success
|
||||
*/
|
||||
int CalculateFitFromData(pFit self, float fAxis[], long lSum[],
|
||||
int iLen);
|
||||
void GetFitResults(pFit self, float *fNewCenter, float *fStdDev,
|
||||
float *FWHM, float *fMax);
|
||||
int DriveCenter(pFit self, SConnection *pCon, SicsInterp *pSics);
|
||||
/*-------------------------------------------------------------------------*/
|
||||
int FitFactory(SConnection *pCon,SicsInterp *pSics, void *pData,
|
||||
int argc, char *argv[]);
|
||||
int FitWrapper(SConnection *pCon,SicsInterp *pSics, void *pData,
|
||||
int argc, char *argv[]);
|
||||
int CenterWrapper(SConnection *pCon,SicsInterp *pSics, void *pData,
|
||||
int argc, char *argv[]);
|
||||
@}
|
||||
|
||||
@o fitcenter.h @{
|
||||
/*---------------------------------------------------------------------------
|
||||
F I T C E N T E R
|
||||
|
||||
A simple peak finding and center of gravity determination facility for
|
||||
SICS.
|
||||
|
||||
copyright: see copyright.h
|
||||
|
||||
Mark Koennecke, October 1997
|
||||
----------------------------------------------------------------------------*/
|
||||
#ifndef SICSFITCENTER
|
||||
#define SICSFITCENTER
|
||||
@<fitinter@>
|
||||
#endif
|
||||
@}
|
511
chadapter.c
Normal file
511
chadapter.c
Normal file
@ -0,0 +1,511 @@
|
||||
/*-------------------------------------------------------------------------
|
||||
C h o c o A d a p t e r
|
||||
|
||||
This is a drivable adapter for the ChopperController object (or also generic
|
||||
controller object). It allows to modify one of the variables supported by
|
||||
the controller through the normal SICS drive command. For more information
|
||||
see file choco.w or choco.tex.
|
||||
|
||||
|
||||
Mark Koennecke, January 1998
|
||||
---------------------------------------------------------------------------*/
|
||||
#include <stdlib.h>
|
||||
#include <assert.h>
|
||||
#include <tcl.h>
|
||||
#include "fortify.h"
|
||||
#include "sics.h"
|
||||
#define CHOCOINTERNAL
|
||||
#include "choco.h"
|
||||
#include "evcontroller.h"
|
||||
#include "evdriver.i"
|
||||
#define CHADAINTERNAL
|
||||
#include "chadapter.h"
|
||||
|
||||
#define NOTIMPLEMENTED -11555
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
static void *AdapterGetInterface(void *pData, int iID)
|
||||
{
|
||||
pCHAdapter self = NULL;
|
||||
|
||||
self = (pCHAdapter)pData;
|
||||
assert(self);
|
||||
if(iID == DRIVEID)
|
||||
{
|
||||
return self->pInt;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
/*-------------------------------------------------------------------------*/
|
||||
static int CHHalt(void *pData)
|
||||
{
|
||||
pCHAdapter self = NULL;
|
||||
|
||||
self = (pCHAdapter)pData;
|
||||
assert(self);
|
||||
|
||||
self->pDriv->Halt(self->pDriv);
|
||||
|
||||
return 1;
|
||||
}
|
||||
/*-------------------------------------------------------------------------*/
|
||||
static int CHLimits(void *pData, float fVal, char *error, int iErrlen)
|
||||
{
|
||||
pCHAdapter self = NULL;
|
||||
|
||||
self = (pCHAdapter)pData;
|
||||
assert(self);
|
||||
|
||||
if(fVal < self->fLower)
|
||||
{
|
||||
strncpy(error,"Lower limit violated",iErrlen);
|
||||
return 0;
|
||||
}
|
||||
if(fVal > self->fUpper)
|
||||
{
|
||||
strncpy(error,"Upper limit violated",iErrlen);
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
/*------------------------------------------------------------------------*/
|
||||
static float CHGetValue(void *pData, SConnection *pCon)
|
||||
{
|
||||
pCHAdapter self = NULL;
|
||||
float fVal;
|
||||
int iRet;
|
||||
char pBueffel[80];
|
||||
|
||||
self = (pCHAdapter)pData;
|
||||
assert(self);
|
||||
|
||||
iRet = self->pDriv->GetPar(self->pDriv,self->pParName,pBueffel,79);
|
||||
if(!iRet)
|
||||
{
|
||||
fVal = -9999999.99;
|
||||
self->pDriv->GetError(self->pDriv,&iRet,pBueffel,79);
|
||||
SCWrite(pCon,pBueffel,eError);
|
||||
return fVal;
|
||||
}
|
||||
sscanf(pBueffel,"%f",&fVal);
|
||||
return fVal;
|
||||
}
|
||||
/*-----------------------------------------------------------------------*/
|
||||
static int CHStatus(void *pData, SConnection *pCon)
|
||||
{
|
||||
pCHAdapter self = NULL;
|
||||
int iRet, iCode;
|
||||
static int iRetry = 0;
|
||||
char pBueffel[80], pError[132];
|
||||
|
||||
self = (pCHAdapter)pData;
|
||||
assert(self);
|
||||
|
||||
iRet = self->pDriv->CheckPar(self->pDriv,self->pParName);
|
||||
switch(iRet)
|
||||
{
|
||||
case OKOK:
|
||||
case HWIdle:
|
||||
iRetry = 0;
|
||||
return HWIdle;
|
||||
case HWFault:
|
||||
self->pDriv->GetError(self->pDriv,&iCode,pBueffel,79);
|
||||
iRet = self->pDriv->TryFixIt(self->pDriv,iCode);
|
||||
sprintf(pError,"ERROR: %s",pBueffel);
|
||||
SCWrite(pCon,pError,eError);
|
||||
if(iRet == CHFAIL || iRetry >= 3)
|
||||
{
|
||||
iRetry = 0;
|
||||
return HWFault;
|
||||
}
|
||||
else
|
||||
{
|
||||
iRetry++;
|
||||
self->pDriv->SetPar(self->pDriv,self->pParName,
|
||||
self->fTarget);
|
||||
return HWBusy;
|
||||
}
|
||||
break;
|
||||
case HWBusy:
|
||||
return HWBusy;
|
||||
}
|
||||
return HWFault;
|
||||
}
|
||||
/*-------------------------------------------------------------------------*/
|
||||
static long CHSetValue(void *pData, SConnection *pCon, float fValue)
|
||||
{
|
||||
pCHAdapter self = NULL;
|
||||
char pBueffel[80], pError[132];
|
||||
int iRet, iCode, i;
|
||||
|
||||
self = (pCHAdapter)pData;
|
||||
assert(self);
|
||||
|
||||
/* check privilege */
|
||||
if(!SCMatchRights(pCon,usUser))
|
||||
{
|
||||
SCWrite(pCon,"ERROR: Insufficient privilege for driving",eError);
|
||||
return 0;
|
||||
}
|
||||
|
||||
for(i = 0; i < 3; i++)
|
||||
{
|
||||
iRet = self->pDriv->SetPar(self->pDriv,self->pParName,fValue);
|
||||
if(iRet)
|
||||
{
|
||||
self->fTarget = fValue;
|
||||
return 1;
|
||||
}
|
||||
self->pDriv->GetError(self->pDriv,&iCode,pBueffel,79);
|
||||
sprintf(pError,"ERROR: %s",pBueffel);
|
||||
SCWrite(pCon,pError,eError);
|
||||
iRet = self->pDriv->TryFixIt(self->pDriv,iCode);
|
||||
if(iRet == CHFAIL)
|
||||
return 0;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
/*------------------------------------------------------------------------*/
|
||||
static void KillAdapter(void *pData)
|
||||
{
|
||||
pCHAdapter self = NULL;
|
||||
|
||||
self = (pCHAdapter)pData;
|
||||
if(!self)
|
||||
return;
|
||||
|
||||
if(self->pDes)
|
||||
DeleteDescriptor(self->pDes);
|
||||
|
||||
if(self->pInt)
|
||||
free(self->pInt);
|
||||
|
||||
if(self->pParName);
|
||||
free(self->pParName);
|
||||
|
||||
free(self);
|
||||
}
|
||||
/*-----------------------------------------------------------------------
|
||||
Syntax: ChopperAdapter name choppercontroller parname upper lower
|
||||
*/
|
||||
int CHAdapterFactory(SConnection *pCon, SicsInterp *pSics, void *pData,
|
||||
int argc, char *argv[])
|
||||
{
|
||||
char pBueffel[256];
|
||||
pCHAdapter pNew = NULL;
|
||||
pChoco pChopper = NULL;
|
||||
CommandList *pCom = NULL;
|
||||
pDummy pDum = NULL;
|
||||
double dUpper, dLower;
|
||||
int iRet;
|
||||
|
||||
/* do we have enough arguments? */
|
||||
if(argc < 6)
|
||||
{
|
||||
SCWrite(pCon,
|
||||
"ERROR: Insufficient number of arguments to ChopperAdapter",
|
||||
eError);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* find the chopper first */
|
||||
pCom = FindCommand(pSics,argv[2]);
|
||||
if(pCom)
|
||||
{
|
||||
pDum = (pDummy)pCom->pData;
|
||||
if(pDum)
|
||||
{
|
||||
if(strcmp(pDum->pDescriptor->name,"Chopper") == 0)
|
||||
{
|
||||
pChopper = (pChoco)pCom->pData;
|
||||
}
|
||||
}
|
||||
}
|
||||
if(!pChopper)
|
||||
{
|
||||
sprintf(pBueffel,"ERROR: %s is NO chopper controller",
|
||||
argv[3]);
|
||||
SCWrite(pCon,pBueffel,eError);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* interpret limits */
|
||||
iRet = Tcl_GetDouble(pSics->pTcl,argv[5],&dUpper);
|
||||
if(iRet != TCL_OK)
|
||||
{
|
||||
sprintf(pBueffel,
|
||||
"ERROR: expected numeric argument for upper limit, got %s",
|
||||
argv[4]);
|
||||
SCWrite(pCon,pBueffel,eError);
|
||||
return 0;
|
||||
}
|
||||
iRet = Tcl_GetDouble(pSics->pTcl,argv[4],&dLower);
|
||||
if(iRet != TCL_OK)
|
||||
{
|
||||
sprintf(pBueffel,
|
||||
"ERROR: expected numeric argument for lower limit, got %s",
|
||||
argv[5]);
|
||||
SCWrite(pCon,pBueffel,eError);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* allocate new adapter data structure */
|
||||
pNew = (pCHAdapter)malloc(sizeof(CHAdapter));
|
||||
if(!pNew)
|
||||
{
|
||||
SCWrite(pCon,"ERROR: out of memory in ChopperAdapter",eError);
|
||||
return 0;
|
||||
}
|
||||
memset(pNew,0,sizeof(CHAdapter));
|
||||
|
||||
pNew->pDes = CreateDescriptor("ChopperAdapter");
|
||||
pNew->pDriv = CHGetDriver(pChopper);
|
||||
pNew->pInt = CreateDrivableInterface();
|
||||
pNew->pParName = strdup(argv[3]);
|
||||
if( !pNew->pDes || !pNew->pDriv || !pNew->pInt || !pNew->pParName)
|
||||
{
|
||||
SCWrite(pCon,"ERROR: out of memory in ChopperAdapter",eError);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* initialize other fields */
|
||||
pNew->fTarget = 0.;
|
||||
pNew->fLower = (float)dLower;
|
||||
pNew->fUpper = (float)dUpper;
|
||||
pNew->pDes->GetInterface = AdapterGetInterface;
|
||||
pNew->pInt->Halt = CHHalt;
|
||||
pNew->pInt->CheckLimits = CHLimits;
|
||||
pNew->pInt->SetValue = CHSetValue;
|
||||
pNew->pInt->CheckStatus = CHStatus;
|
||||
pNew->pInt->GetValue = CHGetValue;
|
||||
|
||||
/* install command */
|
||||
iRet = AddCommand(pSics, argv[1],CHAdapterAction,KillAdapter,pNew);
|
||||
if(!iRet)
|
||||
{
|
||||
sprintf(pBueffel,
|
||||
"ERROR: duplicate ChopperAdapter command %s NOT created",
|
||||
argv[1]);
|
||||
SCWrite(pCon,pBueffel,eError);
|
||||
KillAdapter(pNew);
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
/*------------------------------------------------------------------------*/
|
||||
int CHAdapterAction(SConnection *pCon, SicsInterp *pSics, void *pData,
|
||||
int argc, char *argv[])
|
||||
{
|
||||
pCHAdapter self = NULL;
|
||||
int iRet;
|
||||
char pBueffel[132];
|
||||
float fValue;
|
||||
|
||||
self = (pCHAdapter)pData;
|
||||
assert(self);
|
||||
|
||||
/* only action: get value */
|
||||
fValue = CHGetValue(self,pCon);
|
||||
if(fValue < -99000)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
sprintf(pBueffel,"%s = %f",argv[0],fValue);
|
||||
SCWrite(pCon,pBueffel,eValue);
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
/*=========================================================================
|
||||
An environment driver based on top of a controller object.
|
||||
-------------------------------------------------------------------------*/
|
||||
static int AVEVSetValue(pEVDriver self, float fNew)
|
||||
{
|
||||
pCHev myData;
|
||||
|
||||
assert(self);
|
||||
myData = (pCHev)self->pPrivate;
|
||||
assert(myData);
|
||||
myData->iLastError = 0;
|
||||
|
||||
return myData->pDriv->SetPar(myData->pDriv,myData->pParName,fNew);
|
||||
}
|
||||
/*-----------------------------------------------------------------------*/
|
||||
static int AVEVGetValue(pEVDriver self, float *fNew)
|
||||
{
|
||||
pCHev myData;
|
||||
int iRet;
|
||||
char pBueffel[80];
|
||||
|
||||
assert(self);
|
||||
myData = (pCHev)self->pPrivate;
|
||||
assert(myData);
|
||||
|
||||
iRet = myData->pDriv->GetPar(myData->pDriv,myData->pParName,
|
||||
pBueffel,79);
|
||||
sscanf(pBueffel,"%f",fNew);
|
||||
return iRet;
|
||||
}
|
||||
/*-----------------------------------------------------------------------*/
|
||||
static int AVEVSend(pEVDriver self, char *pCommand,
|
||||
char *pReply, int iLen)
|
||||
{
|
||||
pCHev myData;
|
||||
|
||||
assert(self);
|
||||
myData = (pCHev)self->pPrivate;
|
||||
assert(myData);
|
||||
myData->iLastError = NOTIMPLEMENTED;
|
||||
|
||||
return 0;
|
||||
}
|
||||
/*-----------------------------------------------------------------------*/
|
||||
static int AVEVGetError(pEVDriver self, int *iCode,
|
||||
char *pReply, int iLen)
|
||||
{
|
||||
pCHev myData;
|
||||
|
||||
assert(self);
|
||||
myData = (pCHev)self->pPrivate;
|
||||
assert(myData);
|
||||
|
||||
if(myData->iLastError == NOTIMPLEMENTED)
|
||||
{
|
||||
strncpy(pReply,"ERROR: Not Implemented here!", iLen);
|
||||
*iCode = NOTIMPLEMENTED;
|
||||
myData->iLastError = 0;
|
||||
return 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
return myData->pDriv->GetError(myData->pDriv, iCode,
|
||||
pReply, iLen);
|
||||
}
|
||||
}
|
||||
/*------------------------------------------------------------------------*/
|
||||
static int AVEVTryFixIt(pEVDriver self, int iCode)
|
||||
{
|
||||
pCHev myData;
|
||||
|
||||
assert(self);
|
||||
myData = (pCHev)self->pPrivate;
|
||||
assert(myData);
|
||||
|
||||
if(iCode == NOTIMPLEMENTED)
|
||||
{
|
||||
return DEVFAULT;
|
||||
}
|
||||
else
|
||||
{
|
||||
return myData->pDriv->TryFixIt(myData->pDriv, iCode);
|
||||
}
|
||||
}
|
||||
/*---------------------------------------------------------------------*/
|
||||
static int AVEVInit(pEVDriver self)
|
||||
{
|
||||
pCHev myData;
|
||||
|
||||
assert(self);
|
||||
myData = (pCHev)self->pPrivate;
|
||||
assert(myData);
|
||||
|
||||
return myData->pDriv->Init(myData->pDriv);
|
||||
}
|
||||
/*---------------------------------------------------------------------*/
|
||||
static int AVEVClose(pEVDriver self)
|
||||
{
|
||||
pCHev myData;
|
||||
|
||||
assert(self);
|
||||
myData = (pCHev)self->pPrivate;
|
||||
assert(myData);
|
||||
|
||||
return myData->pDriv->Close(myData->pDriv);
|
||||
}
|
||||
/*----------------------------------------------------------------------*/
|
||||
static void AVEVKillPrivate(void *pData)
|
||||
{
|
||||
pCHev myData;
|
||||
|
||||
if(pData != NULL)
|
||||
{
|
||||
myData = (pCHev)pData;
|
||||
if(myData != NULL)
|
||||
{
|
||||
if(myData->pParName)
|
||||
free(myData->pParName);
|
||||
free(myData);
|
||||
}
|
||||
}
|
||||
}
|
||||
/*---------------------------------------------------------------------*/
|
||||
pEVDriver MakeControllerEnvironmentDriver(int argc, char *argv[])
|
||||
{
|
||||
pEVDriver pNew = NULL;
|
||||
pCHev myData = NULL;
|
||||
CommandList *pCom = NULL;
|
||||
pDummy pDum = NULL;
|
||||
pChoco pChop;
|
||||
|
||||
/*
|
||||
Two arguments are needed: the name of the controller and the
|
||||
name of the parameter
|
||||
*/
|
||||
if(argc < 2)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
pCom = FindCommand(pServ->pSics,argv[0]);
|
||||
if(!pCom)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
pDum = pCom->pData;
|
||||
if(!pDum)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
if(strcmp(pDum->pDescriptor->name,"Chopper") != 0)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* alright: I think we got a controller now, let us create our
|
||||
act
|
||||
*/
|
||||
pNew = CreateEVDriver(argc,argv);
|
||||
if(!pNew)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
myData = (pCHev)malloc(sizeof(CHev));
|
||||
if(!myData)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
pChop = (pChoco)pCom->pData;
|
||||
myData->iLastError = 0;
|
||||
myData->pDriv = pChop->pDriv;
|
||||
myData->pParName = strdup(argv[1]);
|
||||
pNew->pPrivate = myData;
|
||||
pNew->SetValue =AVEVSetValue;
|
||||
pNew->GetValue =AVEVGetValue;
|
||||
pNew->Send = AVEVSend;
|
||||
pNew->GetError =AVEVGetError;
|
||||
pNew->TryFixIt =AVEVTryFixIt;
|
||||
pNew->Init =AVEVInit;
|
||||
pNew->Close =AVEVClose;
|
||||
pNew->KillPrivate =AVEVKillPrivate;
|
||||
|
||||
return pNew;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
47
chadapter.h
Normal file
47
chadapter.h
Normal file
@ -0,0 +1,47 @@
|
||||
|
||||
/*------------------------------------------------------------------------
|
||||
C H a d a p t e r
|
||||
|
||||
This is the header file for a drive adapter for collaboration with a
|
||||
general device controller as implemented in choco.*
|
||||
|
||||
Mark Koennecke, January 1998
|
||||
--------------------------------------------------------------------------*/
|
||||
#ifndef SICSCHADA
|
||||
#define SICSCHADA
|
||||
#include "codri.h"
|
||||
|
||||
typedef struct __CHADAPTER *pCHAdapter;
|
||||
/*-----------------------------------------------------------------------*/
|
||||
int CHAdapterFactory(SConnection *pCon, SicsInterp *pSics,
|
||||
void *pData,
|
||||
int argc, char *argv[]);
|
||||
|
||||
int CHAdapterAction(SConnection *pCon, SicsInterp *pSics,
|
||||
void *pData,
|
||||
int argc, char *argv[]);
|
||||
|
||||
pEVDriver MakeControllerEnvironmentDriver(int argc, char *argv[]);
|
||||
|
||||
|
||||
#ifdef CHADAINTERNAL
|
||||
|
||||
typedef struct __CHADAPTER {
|
||||
pObjectDescriptor pDes;
|
||||
pCodri pDriv;
|
||||
pIDrivable pInt;
|
||||
float fUpper;
|
||||
float fLower;
|
||||
float fTarget;
|
||||
char *pParName;
|
||||
}CHAdapter;
|
||||
|
||||
|
||||
typedef struct __CHEV {
|
||||
char *pParName;
|
||||
pCodri pDriv;
|
||||
int iLastError;
|
||||
}CHev, *pCHev;
|
||||
|
||||
#endif
|
||||
#endif
|
311
choco.c
Normal file
311
choco.c
Normal file
@ -0,0 +1,311 @@
|
||||
/*------------------------------------------------------------------------
|
||||
C h o p p e r C o n t r o l l e r
|
||||
|
||||
Implementation file for the SICS chopper controller and general controller
|
||||
device. For details about this object and its relation with the SICS system
|
||||
see choco.w or choco.tex.
|
||||
|
||||
Mark Koennecke, January 1998
|
||||
-------------------------------------------------------------------------*/
|
||||
#include <stdlib.h>
|
||||
#include <tcl.h>
|
||||
#include <assert.h>
|
||||
#include "fortify.h"
|
||||
#include "sics.h"
|
||||
#define CHOCOINTERNAL
|
||||
#include "choco.h"
|
||||
|
||||
|
||||
|
||||
/*------------------------------------------------------------------------*/
|
||||
int CHGetParameter(pChoco self, char *parname, char *pParValue,
|
||||
int iBuflen)
|
||||
{
|
||||
int iRet, iCode;
|
||||
|
||||
assert(self);
|
||||
|
||||
iRet = self->pDriv->GetPar(self->pDriv, parname, pParValue,
|
||||
iBuflen);
|
||||
if(!iRet)
|
||||
{
|
||||
iRet = 0;
|
||||
self->pDriv->GetError(self->pDriv,&iCode,pParValue, iBuflen);
|
||||
}
|
||||
return iRet;
|
||||
}
|
||||
/*------------------------------------------------------------------------*/
|
||||
pCodri CHGetDriver(pChoco self)
|
||||
{
|
||||
assert(self);
|
||||
|
||||
return self->pDriv;
|
||||
}
|
||||
/*------------------------------------------------------------------------*/
|
||||
int CHList(pChoco self, SConnection *pCon, char *name)
|
||||
{
|
||||
char *pPar, *pCopy = NULL;
|
||||
char pValue[80];
|
||||
char pMessage[256];
|
||||
int iRet, iLen;
|
||||
Tcl_DString tlist;
|
||||
|
||||
assert(self);
|
||||
|
||||
/* copy pParList as it will be destroyed by strtok */
|
||||
iLen = strlen(self->pDriv->pParList);
|
||||
pCopy = (char *)malloc((iLen+10)*sizeof(char));
|
||||
if(!pCopy)
|
||||
{
|
||||
SCWrite(pCon,"ERROR: out of memory in CHList",eError);
|
||||
return 0;
|
||||
}
|
||||
memset(pCopy,0,iLen+10);
|
||||
strcpy(pCopy,self->pDriv->pParList);
|
||||
Tcl_DStringInit(&tlist);
|
||||
|
||||
pPar = strtok(pCopy,",");
|
||||
while(pPar != NULL)
|
||||
{
|
||||
iRet = CHGetParameter(self,pPar,pValue,79);
|
||||
if(iRet)
|
||||
{
|
||||
sprintf(pMessage,"%s.%s = %s \n",name,pPar,pValue);
|
||||
}
|
||||
else
|
||||
{
|
||||
sprintf(pMessage,"ERROR: %s : while reading parameter %s \n",
|
||||
pValue,pPar);
|
||||
}
|
||||
Tcl_DStringAppend(&tlist, pMessage,-1);
|
||||
pPar = strtok(NULL,",");
|
||||
}
|
||||
SCWrite(pCon,Tcl_DStringValue(&tlist),eValue);
|
||||
Tcl_DStringFree(&tlist);
|
||||
free(pCopy);
|
||||
return 1;
|
||||
}
|
||||
/*-----------------------------------------------------------------------*/
|
||||
int ChocoAction(SConnection *pCon, SicsInterp *pSics, void *pData,
|
||||
int argc, char *argv[])
|
||||
{
|
||||
pChoco self = NULL;
|
||||
char pValue[80], pMessage[256];
|
||||
int iRet;
|
||||
|
||||
self = (pChoco)pData;
|
||||
assert(self);
|
||||
|
||||
if(argc < 2)
|
||||
{
|
||||
sprintf(pMessage, "ERROR: Ragument required for %s",argv[0]);
|
||||
SCWrite(pCon,pMessage,eError);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* argument can either be list or parameter name */
|
||||
strtolower(argv[1]);
|
||||
if(strcmp(argv[1],"list") == 0)
|
||||
{
|
||||
return CHList(self,pCon,argv[0]);
|
||||
}
|
||||
else
|
||||
{
|
||||
if(argc > 2)
|
||||
{
|
||||
/* set case */
|
||||
iRet = self->pDriv->SetPar2(self->pDriv,argv[1],argv[2]);
|
||||
if(!iRet)
|
||||
{
|
||||
self->pDriv->GetError(self->pDriv,&iRet,pValue,79);
|
||||
sprintf(pMessage,"ERROR: %s",pValue);
|
||||
SCWrite(pCon,pMessage,eError);
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
SCSendOK(pCon);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* get case */
|
||||
iRet = CHGetParameter(self,argv[1],pValue,79);
|
||||
if(iRet)
|
||||
{
|
||||
sprintf(pMessage,"%s.%s = %s",argv[0],argv[1],pValue);
|
||||
}
|
||||
else
|
||||
{
|
||||
sprintf(pMessage,"ERROR: %s : while reading parameter %s",
|
||||
pValue,argv[1]);
|
||||
}
|
||||
SCWrite(pCon,pMessage,eValue);
|
||||
return iRet;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
/*----------------------------------------------------------------------*/
|
||||
static void KillChoco(void *pData)
|
||||
{
|
||||
pChoco self = NULL;
|
||||
|
||||
self = (pChoco)pData;
|
||||
if(!self)
|
||||
return;
|
||||
|
||||
if(self->pDriv)
|
||||
{
|
||||
self->pDriv->Close(self->pDriv);
|
||||
self->pDriv->Delete(self->pDriv);
|
||||
if(self->pDriv->pParList)
|
||||
free(self->pDriv->pParList);
|
||||
free(self->pDriv);
|
||||
}
|
||||
if(self->pDes)
|
||||
DeleteDescriptor(self->pDes);
|
||||
|
||||
free(self);
|
||||
}
|
||||
/*-----------------------------------------------------------------------
|
||||
DRIVERS
|
||||
*/
|
||||
|
||||
extern pCodri MakeSimChopper(void);
|
||||
extern pCodri MakeDoChoDriver(char *pHost, int iPort, int iChannel,
|
||||
int iSingle);
|
||||
extern pCodri MakeCookerDriver(char *pHost, int iPort, int iChannel);
|
||||
/*-----------------------------------------------------------------------*/
|
||||
int ChocoFactory(SConnection *pCon, SicsInterp *pSics, void *pData,
|
||||
int argc, char *argv[])
|
||||
{
|
||||
pChoco pNew = NULL;
|
||||
pCodri pDriv = NULL;
|
||||
pObjectDescriptor pDes = NULL;
|
||||
char pBueffel[132];
|
||||
int iRet, iPort, iChannel;
|
||||
int iSingle = 0;
|
||||
|
||||
if(argc < 3)
|
||||
{
|
||||
SCWrite(pCon,
|
||||
"ERROR: Insufficient number of arguments to MakeController",
|
||||
eError);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/* first try to get everything done */
|
||||
pNew = (pChoco)malloc(sizeof(Choco));
|
||||
pDes = CreateDescriptor("Chopper");
|
||||
/* do driver */
|
||||
strtolower(argv[2]);
|
||||
if(strcmp(argv[2],"sim") == 0)
|
||||
{
|
||||
pDriv = MakeSimChopper();
|
||||
}
|
||||
else if(strcmp(argv[2],"docho") == 0)
|
||||
{
|
||||
if(argc < 6)
|
||||
{
|
||||
SCWrite(pCon,
|
||||
"ERROR: Insufficient number of arguments to install Dornier Chopper driver",
|
||||
eError);
|
||||
return 0;
|
||||
}
|
||||
iRet = Tcl_GetInt(pSics->pTcl,argv[4],&iPort);
|
||||
if(iRet != TCL_OK)
|
||||
{
|
||||
sprintf(pBueffel,"ERROR: expected integer as port number, got %s",
|
||||
argv[4]);
|
||||
SCWrite(pCon,pBueffel,eError);
|
||||
return 0;
|
||||
}
|
||||
iRet = Tcl_GetInt(pSics->pTcl,argv[5],&iChannel);
|
||||
if(iRet != TCL_OK)
|
||||
{
|
||||
sprintf(pBueffel,"ERROR: expected integer as channel number, got %s",
|
||||
argv[4]);
|
||||
SCWrite(pCon,pBueffel,eError);
|
||||
return 0;
|
||||
}
|
||||
if(argc > 6)
|
||||
{
|
||||
iRet = Tcl_GetInt(pSics->pTcl,argv[6],&iSingle);
|
||||
if(iRet != TCL_OK)
|
||||
{
|
||||
sprintf(pBueffel,
|
||||
"ERROR: expected integer as single flag, got %s",
|
||||
argv[6]);
|
||||
SCWrite(pCon,pBueffel,eError);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
pDriv = MakeDoChoDriver(argv[3],iPort,iChannel,iSingle);
|
||||
}
|
||||
else if(strcmp(argv[2],"sanscook") == 0)
|
||||
{
|
||||
if(argc < 6)
|
||||
{
|
||||
SCWrite(pCon,
|
||||
"ERROR: Insufficient number of arguments to install SANS Cooker driver",
|
||||
eError);
|
||||
return 0;
|
||||
}
|
||||
iRet = Tcl_GetInt(pSics->pTcl,argv[4],&iPort);
|
||||
if(iRet != TCL_OK)
|
||||
{
|
||||
sprintf(pBueffel,"ERROR: expected integer as port number, got %s",
|
||||
argv[4]);
|
||||
SCWrite(pCon,pBueffel,eError);
|
||||
return 0;
|
||||
}
|
||||
iRet = Tcl_GetInt(pSics->pTcl,argv[5],&iChannel);
|
||||
if(iRet != TCL_OK)
|
||||
{
|
||||
sprintf(pBueffel,"ERROR: expected integer as channel number, got %s",
|
||||
argv[4]);
|
||||
SCWrite(pCon,pBueffel,eError);
|
||||
return 0;
|
||||
}
|
||||
pDriv = MakeCookerDriver(argv[3],iPort,iChannel);
|
||||
}
|
||||
else
|
||||
{
|
||||
sprintf(pBueffel,"ERROR: Driver %s NOT supported for MakeController",
|
||||
argv[2]);
|
||||
SCWrite(pCon,pBueffel,eError);
|
||||
return 0;
|
||||
}
|
||||
if( (pNew == NULL) || (pDes == NULL) || (pDriv == NULL) )
|
||||
{
|
||||
SCWrite(pCon,"ERROR: No memory left to create controller",eError);
|
||||
return 0;
|
||||
}
|
||||
pNew->pDes = pDes;
|
||||
pNew->pDriv = pDriv;
|
||||
|
||||
/* initialize driver */
|
||||
iRet = pDriv->Init(pDriv);
|
||||
if(!iRet)
|
||||
{
|
||||
SCWrite(pCon,"ERROR: Failed to initialize driver",eError);
|
||||
KillChoco(pNew);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* install as command */
|
||||
iRet = AddCommand(pSics, argv[1],ChocoAction,KillChoco,pNew);
|
||||
if(!iRet)
|
||||
{
|
||||
sprintf(pBueffel,"ERROR: duplicate command %s NOT created",
|
||||
argv[1]);
|
||||
SCWrite(pCon,pBueffel,eError);
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
36
choco.h
Normal file
36
choco.h
Normal file
@ -0,0 +1,36 @@
|
||||
|
||||
/*-----------------------------------------------------------------------
|
||||
C h o p p e r C o n t r o l l e r
|
||||
|
||||
This is both the header file for a general controller and a SICS
|
||||
chopper controller.
|
||||
|
||||
Mark Koennecke, January 1998
|
||||
--------------------------------------------------------------------------*/
|
||||
#ifndef CHOCOSICS
|
||||
#define CHOCOSICS
|
||||
#include "codri.h"
|
||||
|
||||
typedef struct __CHOCO *pChoco;
|
||||
/*------------------------------------------------------------------------*/
|
||||
int CHGetParameter(pChoco self, char *pParName,
|
||||
char *pParValue, int iBuflen);
|
||||
|
||||
pCodri CHGetDriver(pChoco self);
|
||||
int CHList(pChoco self, SConnection *pCon, char *name);
|
||||
/*------------------------------------------------------------------------*/
|
||||
int ChocoAction(SConnection *pCon, SicsInterp *pSics, void *pData,
|
||||
int argc, char *argv[]);
|
||||
int ChocoFactory(SConnection *pCon, SicsInterp *pSics, void *pData,
|
||||
int argc, char *argv[]);
|
||||
|
||||
|
||||
#ifdef CHOCOINTERNAL
|
||||
|
||||
typedef struct __CHOCO {
|
||||
pObjectDescriptor pDes;
|
||||
pCodri pDriv;
|
||||
} Choco;
|
||||
|
||||
#endif
|
||||
#endif
|
380
choco.tex
Normal file
380
choco.tex
Normal file
@ -0,0 +1,380 @@
|
||||
\subsection{Chopper Controller}
|
||||
Yet another way to deal with a controller has been devised for
|
||||
SICS. This uses the concept of a general controller which can have
|
||||
parameters enquired and set. Furthermore it may have parameters which
|
||||
may be driven like a motor or environment controller through special
|
||||
adapters . This scheme is
|
||||
used for the chopper controller for FOCUS.
|
||||
\begin{itemize}
|
||||
\item A driver for a particular controller which allows to set and get
|
||||
parameters.
|
||||
\item The general controller object which holds things together.
|
||||
\item An adapter object which allows to drive special parameters in a general
|
||||
controller. Such adapter objects can be configured for each drivable parameter
|
||||
in a controller.
|
||||
\item An adapter to an environment controller driver.
|
||||
\end{itemize}
|
||||
The test case for this way of doing things is a controller for running
|
||||
choppers. This is why it gets the name.
|
||||
|
||||
The chopper system in question is the FOCUS chopper system. There are two
|
||||
choppers, a fermi chopper and a disk chopper. This system can be run in two
|
||||
different modes: In synchronous mode both choppers run at a
|
||||
predefined ratio of speeds. For instance the fermi chopper is two
|
||||
times faster then the disk chopper. This means, that setting a new
|
||||
value for one chopper also changes the speed of the other chopper. In
|
||||
asynchronous mode both choppers operate independently. Also the ration
|
||||
to use for synchronous mode can be changed. Another parameter which
|
||||
frequently changes is the phase of the two choppers. In order to
|
||||
compensate for the fligh path between the two choppers there is a
|
||||
small angular displacement of the choppers against each other which
|
||||
varies with wavelength.
|
||||
|
||||
\subsubsection{The Controller Driver}
|
||||
The controller driver is represented by the following data structure:
|
||||
\begin{flushleft} \small
|
||||
\begin{minipage}{\linewidth} \label{scrap1}
|
||||
$\langle$codri {\footnotesize ?}$\rangle\equiv$
|
||||
\vspace{-1ex}
|
||||
\begin{list}{}{} \item
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@ typedef struct __CODRI *pCodri;@\\
|
||||
\mbox{}\verb@ typedef struct __CODRI {@\\
|
||||
\mbox{}\verb@ int (*Init)(pCodri self);@\\
|
||||
\mbox{}\verb@ int (*Close)(pCodri self);@\\
|
||||
\mbox{}\verb@ int (*Delete)(pCodri self);@\\
|
||||
\mbox{}\verb@ int (*SetPar)(pCodri self, @\\
|
||||
\mbox{}\verb@ char *parname,@\\
|
||||
\mbox{}\verb@ float fValue);@\\
|
||||
\mbox{}\verb@ int (*SetPar2)(pCodri self, @\\
|
||||
\mbox{}\verb@ char *parname,@\\
|
||||
\mbox{}\verb@ char *value);@\\
|
||||
\mbox{}\verb@ int (*GetPar)(pCodri self,@\\
|
||||
\mbox{}\verb@ char *parname,@\\
|
||||
\mbox{}\verb@ char *pBuffer,@\\
|
||||
\mbox{}\verb@ int iBufLen);@\\
|
||||
\mbox{}\verb@ int (*CheckPar)(pCodri self, @\\
|
||||
\mbox{}\verb@ char *parname);@\\
|
||||
\mbox{}\verb@ int (*GetError)(pCodri self, int *iCode,@\\
|
||||
\mbox{}\verb@ char *pError, @\\
|
||||
\mbox{}\verb@ int iErrLen);@\\
|
||||
\mbox{}\verb@ int (*TryFixIt)(pCodri self, int iCode);@\\
|
||||
\mbox{}\verb@ int (*Halt)(pCodri self);@\\
|
||||
\mbox{}\verb@ char *pParList;@\\
|
||||
\mbox{}\verb@ void *pPrivate;@\\
|
||||
\mbox{}\verb@ }Codri;@\\
|
||||
\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}
|
||||
All functions take a pointer to the controller driver itself as a
|
||||
parameter. All functions except TryFixIt and CheckPar
|
||||
return 0 on failure and 1 for success.
|
||||
\begin{description}
|
||||
\item[Init] initializes the controller driver. The parameters argc,
|
||||
argv are main() style parameters for the initialization of the
|
||||
controller driver.
|
||||
\item[Close] closes the connection to the controller but does not delete a thing.
|
||||
\item[Delete] closes the connection to the controller and deletes private data structures. Called when deleting the controller.
|
||||
\item[SetPar] tries to set the parameter parname to the value
|
||||
fValue. The last is floating point which covers the frequent
|
||||
occurence of numeric values.
|
||||
\item[SetPar2] The same as SetPar but uses test string as input for
|
||||
parameter setting.
|
||||
\item[GetPar] retrieves the parameter parname formatted as text. The
|
||||
value is put into the buffer pBuffer. iBufLen is the maximum number of
|
||||
bytes permissable for pBuffer.
|
||||
\item[CheckPar] When parameters are driven a means is needed to find
|
||||
out about the progress of operations and errors during the
|
||||
operation. This is done by CheckPar for the parameter parname. The
|
||||
return value of this function must be one of the HWBusy, HWError,
|
||||
HWDone family documented in the motor driver object description.
|
||||
\item[GetError] retrieves the last error. An integer error code is
|
||||
placed into iCode and a textual description of the problem is written
|
||||
to pError. Maximum iErrLen bytes are copied to pError.
|
||||
\item[TryFixIt] tries to fix the error condition specified by iCode in
|
||||
software if this possible. TryFisIt returns HWRedo if the last command
|
||||
needs to resent, HWFault if the problem could not be fixed and HWOK if
|
||||
the error can be ignored or was fully resolved.
|
||||
\item[pParList] is text string containing a comma separated list of
|
||||
all parameters understood by this driver.
|
||||
\item[pPrivate] Is a pointer to a driver specific specific data
|
||||
structure. This data structure will not be messed with by upper level code.
|
||||
\end{description}
|
||||
|
||||
\subsubsection{The Controller Object}
|
||||
This is the general controller object visible from the SICS
|
||||
interpreter. This object allows to list all possible
|
||||
parameters. Internal functions are provided for setting
|
||||
parameters. But this is meant to be operated through a drive adapter
|
||||
object (see below) in SICS. Thus the interface to this object
|
||||
includes:
|
||||
\begin{flushleft} \small
|
||||
\begin{minipage}{\linewidth} \label{scrap2}
|
||||
$\langle$chocoint {\footnotesize ?}$\rangle\equiv$
|
||||
\vspace{-1ex}
|
||||
\begin{list}{}{} \item
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@ typedef struct __CHOCO *pChoco;@\\
|
||||
\mbox{}\verb@/*------------------------------------------------------------------------*/@\\
|
||||
\mbox{}\verb@ int CHGetParameter(pChoco self, char *pParName, @\\
|
||||
\mbox{}\verb@ char *pParValue, int iBuflen); @\\
|
||||
\mbox{}\verb@ @\\
|
||||
\mbox{}\verb@ pCodri CHGetDriver(pChoco self);@\\
|
||||
\mbox{}\verb@ int CHList(pChoco self, SConnection *pCon, char *name);@\\
|
||||
\mbox{}\verb@/*------------------------------------------------------------------------*/@\\
|
||||
\mbox{}\verb@ int ChocoAction(SConnection *pCon, SicsInterp *pSics, void *pData,@\\
|
||||
\mbox{}\verb@ int argc, char *argv[]);@\\
|
||||
\mbox{}\verb@ int ChocoFactory(SConnection *pCon, SicsInterp *pSics, void *pData,@\\
|
||||
\mbox{}\verb@ int argc, char *argv[]);@\\
|
||||
\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}
|
||||
\begin{description}
|
||||
\item[CHGetParameter] retrieves the value of the parameter ParName
|
||||
converted to text. Maximum iBufLen of result or error text are copied into the
|
||||
buffer pParvalue.
|
||||
\item[CHGetDriver] returns a pointer to the controller driver. This
|
||||
function will be used by the drive adapters for interfacing with the
|
||||
driver directly.
|
||||
\item[CHList] prints a listing of all parameters to the client
|
||||
described by pCon. name is the name of the controller.
|
||||
\item[ChocoAction] is the SICS interpreter interface function for the
|
||||
controller.
|
||||
\item[ChocoFactory] is the SICS interpreter interface function which
|
||||
installs a controller into SICS.
|
||||
\end{description}
|
||||
|
||||
Most of the actual work of the controller is left to the driver. Thus
|
||||
the internal data structure for a controller object is very simple:
|
||||
\begin{flushleft} \small
|
||||
\begin{minipage}{\linewidth} \label{scrap3}
|
||||
$\langle$chocodata {\footnotesize ?}$\rangle\equiv$
|
||||
\vspace{-1ex}
|
||||
\begin{list}{}{} \item
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@ typedef struct __CHOCO {@\\
|
||||
\mbox{}\verb@ pObjectDescriptor pDes;@\\
|
||||
\mbox{}\verb@ pCodri pDriv;@\\
|
||||
\mbox{}\verb@ } Choco;@\\
|
||||
\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}
|
||||
It consists just of the standard SICS object descriptor and a pointer
|
||||
to the driver.
|
||||
|
||||
\subsubsection{The Drive And Environment Adapters}
|
||||
Most of the work of the drive adaptor is hidden in the functions
|
||||
implementing the drivable interface. Thus the interface to the
|
||||
DriveAdapter is fairly simple:
|
||||
\begin{flushleft} \small
|
||||
\begin{minipage}{\linewidth} \label{scrap4}
|
||||
$\langle$adapter {\footnotesize ?}$\rangle\equiv$
|
||||
\vspace{-1ex}
|
||||
\begin{list}{}{} \item
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@ typedef struct __CHADAPTER *pCHAdapter;@\\
|
||||
\mbox{}\verb@/*-----------------------------------------------------------------------*/@\\
|
||||
\mbox{}\verb@ int CHAdapterFactory(SConnection *pCon, SicsInterp *pSics, @\\
|
||||
\mbox{}\verb@ void *pData,@\\
|
||||
\mbox{}\verb@ int argc, char *argv[]);@\\
|
||||
\mbox{}\verb@ @\\
|
||||
\mbox{}\verb@ int CHAdapterAction(SConnection *pCon, SicsInterp *pSics, @\\
|
||||
\mbox{}\verb@ void *pData,@\\
|
||||
\mbox{}\verb@ int argc, char *argv[]);@\\
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@ pEVDriver MakeControllerEnvironmentDriver(int argc, char *argv[]);@\\
|
||||
\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}
|
||||
\begin{description}
|
||||
\item[CHAdapterFactory] is the SICS interpreter factory function for
|
||||
creating a drive adapter.
|
||||
\item[CHAdapterAction] is the SICS interpreter function for
|
||||
representing the object in SICS. Just a single action is supported:
|
||||
request the value of the parameter.
|
||||
\item[MakeControllerEnvironmentDriver] creates an environment control
|
||||
driver for a parameter in a general controller object.
|
||||
\end{description}
|
||||
|
||||
The data structure for the drive adapter is slightly more interesting:
|
||||
\begin{flushleft} \small
|
||||
\begin{minipage}{\linewidth} \label{scrap5}
|
||||
$\langle$adadata {\footnotesize ?}$\rangle\equiv$
|
||||
\vspace{-1ex}
|
||||
\begin{list}{}{} \item
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@ typedef struct __CHADAPTER {@\\
|
||||
\mbox{}\verb@ pObjectDescriptor pDes;@\\
|
||||
\mbox{}\verb@ pCodri pDriv;@\\
|
||||
\mbox{}\verb@ pIDrivable pInt;@\\
|
||||
\mbox{}\verb@ float fUpper;@\\
|
||||
\mbox{}\verb@ float fLower;@\\
|
||||
\mbox{}\verb@ float fTarget;@\\
|
||||
\mbox{}\verb@ char *pParName;@\\
|
||||
\mbox{}\verb@ }CHAdapter;@\\
|
||||
\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}
|
||||
\begin{description}
|
||||
\item[pDes] is the standard object descriptor.
|
||||
\item[pDriv] is a pointer to the controller driver.
|
||||
\item[pInt] is a pointer to the drivable interface implemented by the
|
||||
adapter.
|
||||
\item[fUpper] upper limit for the parameter.
|
||||
\item[fLower] lower limit for the parameter.
|
||||
\item[pParName] is the name of the parameter which is driven through
|
||||
this adapter.
|
||||
\end{description}
|
||||
|
||||
This is the data structure for the private part of the environment
|
||||
controller driver:
|
||||
\begin{flushleft} \small
|
||||
\begin{minipage}{\linewidth} \label{scrap6}
|
||||
$\langle$evada {\footnotesize ?}$\rangle\equiv$
|
||||
\vspace{-1ex}
|
||||
\begin{list}{}{} \item
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@ typedef struct __CHEV {@\\
|
||||
\mbox{}\verb@ char *pParName;@\\
|
||||
\mbox{}\verb@ pCodri pDriv;@\\
|
||||
\mbox{}\verb@ int iLastError;@\\
|
||||
\mbox{}\verb@ }CHev, *pCHev;@\\
|
||||
\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}
|
||||
\begin{flushleft} \small
|
||||
\begin{minipage}{\linewidth} \label{scrap7}
|
||||
\verb@"codri.h"@ {\footnotesize ? }$\equiv$
|
||||
\vspace{-1ex}
|
||||
\begin{list}{}{} \item
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@/*-------------------------------------------------------------------------@\\
|
||||
\mbox{}\verb@ C o n t r o l l e r D r i v e r@\\
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@ This file contains the description of the data structure for a@\\
|
||||
\mbox{}\verb@ general controller driver.@\\
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@ Mark Koennecke, January 1998@\\
|
||||
\mbox{}\verb@--------------------------------------------------------------------------*/@\\
|
||||
\mbox{}\verb@#ifndef CODRIV@\\
|
||||
\mbox{}\verb@#define CODRIV@\\
|
||||
\mbox{}\verb@#define CHFAIL -1@\\
|
||||
\mbox{}\verb@#define CHREDO -2@\\
|
||||
\mbox{}\verb@#define CHOK -3@\\
|
||||
\mbox{}\verb@@$\langle$codri {\footnotesize ?}$\rangle$\verb@@\\
|
||||
\mbox{}\verb@#endif@\\
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@@$\diamond$
|
||||
\end{list}
|
||||
\vspace{-2ex}
|
||||
\end{minipage}\\[4ex]
|
||||
\end{flushleft}
|
||||
\begin{flushleft} \small
|
||||
\begin{minipage}{\linewidth} \label{scrap8}
|
||||
\verb@"choco.h"@ {\footnotesize ? }$\equiv$
|
||||
\vspace{-1ex}
|
||||
\begin{list}{}{} \item
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@/*-----------------------------------------------------------------------@\\
|
||||
\mbox{}\verb@ C h o p p e r C o n t r o l l e r@\\
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@ This is both the header file for a general controller and a SICS@\\
|
||||
\mbox{}\verb@ chopper controller.@\\
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@ Mark Koennecke, January 1998@\\
|
||||
\mbox{}\verb@--------------------------------------------------------------------------*/@\\
|
||||
\mbox{}\verb@#ifndef CHOCOSICS@\\
|
||||
\mbox{}\verb@#define CHOCOSICS@\\
|
||||
\mbox{}\verb@#include "codri.h"@\\
|
||||
\mbox{}\verb@@$\langle$chocoint {\footnotesize ?}$\rangle$\verb@@\\
|
||||
\mbox{}\verb@#ifdef CHOCOINTERNAL@\\
|
||||
\mbox{}\verb@@$\langle$chocodata {\footnotesize ?}$\rangle$\verb@@\\
|
||||
\mbox{}\verb@#endif@\\
|
||||
\mbox{}\verb@#endif @\\
|
||||
\mbox{}\verb@@$\diamond$
|
||||
\end{list}
|
||||
\vspace{-2ex}
|
||||
\end{minipage}\\[4ex]
|
||||
\end{flushleft}
|
||||
\begin{flushleft} \small
|
||||
\begin{minipage}{\linewidth} \label{scrap9}
|
||||
\verb@"chadapter.h"@ {\footnotesize ? }$\equiv$
|
||||
\vspace{-1ex}
|
||||
\begin{list}{}{} \item
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@/*------------------------------------------------------------------------@\\
|
||||
\mbox{}\verb@ C H a d a p t e r@\\
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@ This is the header file for a drive adapter for collaboration with a@\\
|
||||
\mbox{}\verb@ general device controller as implemented in choco.*@\\
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@ Mark Koennecke, January 1998@\\
|
||||
\mbox{}\verb@--------------------------------------------------------------------------*/@\\
|
||||
\mbox{}\verb@#ifndef SICSCHADA@\\
|
||||
\mbox{}\verb@#define SICSCHADA@\\
|
||||
\mbox{}\verb@#include "codri.h"@\\
|
||||
\mbox{}\verb@@$\langle$adapter {\footnotesize ?}$\rangle$\verb@@\\
|
||||
\mbox{}\verb@#ifdef CHADAINTERNAL@\\
|
||||
\mbox{}\verb@@$\langle$adadata {\footnotesize ?}$\rangle$\verb@@\\
|
||||
\mbox{}\verb@@$\langle$evada {\footnotesize ?}$\rangle$\verb@@\\
|
||||
\mbox{}\verb@#endif@\\
|
||||
\mbox{}\verb@#endif@\\
|
||||
\mbox{}\verb@@$\diamond$
|
||||
\end{list}
|
||||
\vspace{-2ex}
|
||||
\end{minipage}\\[4ex]
|
||||
\end{flushleft}
|
||||
\subsubsection{To Do}
|
||||
This scheme seems to be quite promising for handling many SICS
|
||||
objects. The following enhancements could be considered. Allow to set
|
||||
certain primitive parameters without a drivable interface. And add an
|
||||
adapter for an environment variable in the controller.
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
281
choco.w
Normal file
281
choco.w
Normal file
@ -0,0 +1,281 @@
|
||||
\subsection{Chopper Controller}
|
||||
Yet another way to deal with a controller has been devised for
|
||||
SICS. This uses the concept of a general controller which can have
|
||||
parameters enquired and set. Furthermore it may have parameters which
|
||||
may be driven like a motor or environment controller through special
|
||||
adapters . This scheme is
|
||||
used for the chopper controller for FOCUS.
|
||||
\begin{itemize}
|
||||
\item A driver for a particular controller which allows to set and get
|
||||
parameters.
|
||||
\item The general controller object which holds things together.
|
||||
\item An adapter object which allows to drive special parameters in a general
|
||||
controller. Such adapter objects can be configured for each drivable parameter
|
||||
in a controller.
|
||||
\item An adapter to an environment controller driver.
|
||||
\end{itemize}
|
||||
The test case for this way of doing things is a controller for running
|
||||
choppers. This is why it gets the name.
|
||||
|
||||
The chopper system in question is the FOCUS chopper system. There are two
|
||||
choppers, a fermi chopper and a disk chopper. This system can be run in two
|
||||
different modes: In synchronous mode both choppers run at a
|
||||
predefined ratio of speeds. For instance the fermi chopper is two
|
||||
times faster then the disk chopper. This means, that setting a new
|
||||
value for one chopper also changes the speed of the other chopper. In
|
||||
asynchronous mode both choppers operate independently. Also the ration
|
||||
to use for synchronous mode can be changed. Another parameter which
|
||||
frequently changes is the phase of the two choppers. In order to
|
||||
compensate for the fligh path between the two choppers there is a
|
||||
small angular displacement of the choppers against each other which
|
||||
varies with wavelength.
|
||||
|
||||
\subsubsection{The Controller Driver}
|
||||
The controller driver is represented by the following data structure:
|
||||
@d codri @{
|
||||
typedef struct __CODRI *pCodri;
|
||||
typedef struct __CODRI {
|
||||
int (*Init)(pCodri self);
|
||||
int (*Close)(pCodri self);
|
||||
int (*Delete)(pCodri self);
|
||||
int (*SetPar)(pCodri self,
|
||||
char *parname,
|
||||
float fValue);
|
||||
int (*SetPar2)(pCodri self,
|
||||
char *parname,
|
||||
char *value);
|
||||
int (*GetPar)(pCodri self,
|
||||
char *parname,
|
||||
char *pBuffer,
|
||||
int iBufLen);
|
||||
int (*CheckPar)(pCodri self,
|
||||
char *parname);
|
||||
int (*GetError)(pCodri self, int *iCode,
|
||||
char *pError,
|
||||
int iErrLen);
|
||||
int (*TryFixIt)(pCodri self, int iCode);
|
||||
int (*Halt)(pCodri self);
|
||||
char *pParList;
|
||||
void *pPrivate;
|
||||
}Codri;
|
||||
|
||||
@}
|
||||
All functions take a pointer to the controller driver itself as a
|
||||
parameter. All functions except TryFixIt and CheckPar
|
||||
return 0 on failure and 1 for success.
|
||||
\begin{description}
|
||||
\item[Init] initializes the controller driver. The parameters argc,
|
||||
argv are main() style parameters for the initialization of the
|
||||
controller driver.
|
||||
\item[Close] closes the connection to the controller but does not delete a thing.
|
||||
\item[Delete] closes the connection to the controller and deletes private data structures. Called when deleting the controller.
|
||||
\item[SetPar] tries to set the parameter parname to the value
|
||||
fValue. The last is floating point which covers the frequent
|
||||
occurence of numeric values.
|
||||
\item[SetPar2] The same as SetPar but uses test string as input for
|
||||
parameter setting.
|
||||
\item[GetPar] retrieves the parameter parname formatted as text. The
|
||||
value is put into the buffer pBuffer. iBufLen is the maximum number of
|
||||
bytes permissable for pBuffer.
|
||||
\item[CheckPar] When parameters are driven a means is needed to find
|
||||
out about the progress of operations and errors during the
|
||||
operation. This is done by CheckPar for the parameter parname. The
|
||||
return value of this function must be one of the HWBusy, HWError,
|
||||
HWDone family documented in the motor driver object description.
|
||||
\item[GetError] retrieves the last error. An integer error code is
|
||||
placed into iCode and a textual description of the problem is written
|
||||
to pError. Maximum iErrLen bytes are copied to pError.
|
||||
\item[TryFixIt] tries to fix the error condition specified by iCode in
|
||||
software if this possible. TryFisIt returns HWRedo if the last command
|
||||
needs to resent, HWFault if the problem could not be fixed and HWOK if
|
||||
the error can be ignored or was fully resolved.
|
||||
\item[pParList] is text string containing a comma separated list of
|
||||
all parameters understood by this driver.
|
||||
\item[pPrivate] Is a pointer to a driver specific specific data
|
||||
structure. This data structure shall not be messed with by upper level code.
|
||||
\end{description}
|
||||
|
||||
\subsubsection{The Controller Object}
|
||||
This is the general controller object visible from the SICS
|
||||
interpreter. This object allows to list all possible
|
||||
parameters. Internal functions are provided for setting
|
||||
parameters. But this is meant to be operated through a drive adapter
|
||||
object (see below) in SICS. Thus the interface to this object
|
||||
includes:
|
||||
@d chocoint @{
|
||||
typedef struct __CHOCO *pChoco;
|
||||
/*------------------------------------------------------------------------*/
|
||||
int CHGetParameter(pChoco self, char *pParName,
|
||||
char *pParValue, int iBuflen);
|
||||
|
||||
pCodri CHGetDriver(pChoco self);
|
||||
int CHList(pChoco self, SConnection *pCon, char *name);
|
||||
/*------------------------------------------------------------------------*/
|
||||
int ChocoAction(SConnection *pCon, SicsInterp *pSics, void *pData,
|
||||
int argc, char *argv[]);
|
||||
int ChocoFactory(SConnection *pCon, SicsInterp *pSics, void *pData,
|
||||
int argc, char *argv[]);
|
||||
|
||||
@}
|
||||
\begin{description}
|
||||
\item[CHGetParameter] retrieves the value of the parameter ParName
|
||||
converted to text. Maximum iBufLen of result or error text are copied into the
|
||||
buffer pParvalue.
|
||||
\item[CHGetDriver] returns a pointer to the controller driver. This
|
||||
function will be used by the drive adapters for interfacing with the
|
||||
driver directly.
|
||||
\item[CHList] prints a listing of all parameters to the client
|
||||
described by pCon. name is the name of the controller.
|
||||
\item[ChocoAction] is the SICS interpreter interface function for the
|
||||
controller.
|
||||
\item[ChocoFactory] is the SICS interpreter interface function which
|
||||
installs a controller into SICS.
|
||||
\end{description}
|
||||
|
||||
Most of the actual work of the controller is left to the driver. Thus
|
||||
the internal data structure for a controller object is very simple:
|
||||
@d chocodata @{
|
||||
typedef struct __CHOCO {
|
||||
pObjectDescriptor pDes;
|
||||
pCodri pDriv;
|
||||
} Choco;
|
||||
@}
|
||||
It consists just of the standard SICS object descriptor and a pointer
|
||||
to the driver.
|
||||
|
||||
\subsubsection{The Drive And Environment Adapters}
|
||||
Most of the work of the drive adaptor is hidden in the functions
|
||||
implementing the drivable interface. Thus the interface to the
|
||||
DriveAdapter is fairly simple:
|
||||
@d adapter @{
|
||||
typedef struct __CHADAPTER *pCHAdapter;
|
||||
/*-----------------------------------------------------------------------*/
|
||||
int CHAdapterFactory(SConnection *pCon, SicsInterp *pSics,
|
||||
void *pData,
|
||||
int argc, char *argv[]);
|
||||
|
||||
int CHAdapterAction(SConnection *pCon, SicsInterp *pSics,
|
||||
void *pData,
|
||||
int argc, char *argv[]);
|
||||
|
||||
pEVDriver MakeControllerEnvironmentDriver(int argc, char *argv[]);
|
||||
|
||||
@}
|
||||
\begin{description}
|
||||
\item[CHAdapterFactory] is the SICS interpreter factory function for
|
||||
creating a drive adapter.
|
||||
\item[CHAdapterAction] is the SICS interpreter function for
|
||||
representing the object in SICS. Just a single action is supported:
|
||||
request the value of the parameter.
|
||||
\item[MakeControllerEnvironmentDriver] creates an environment control
|
||||
driver for a parameter in a general controller object.
|
||||
\end{description}
|
||||
|
||||
The data structure for the drive adapter is slightly more interesting:
|
||||
@d adadata @{
|
||||
typedef struct __CHADAPTER {
|
||||
pObjectDescriptor pDes;
|
||||
pCodri pDriv;
|
||||
pIDrivable pInt;
|
||||
float fUpper;
|
||||
float fLower;
|
||||
float fTarget;
|
||||
char *pParName;
|
||||
}CHAdapter;
|
||||
@}
|
||||
\begin{description}
|
||||
\item[pDes] is the standard object descriptor.
|
||||
\item[pDriv] is a pointer to the controller driver.
|
||||
\item[pInt] is a pointer to the drivable interface implemented by the
|
||||
adapter.
|
||||
\item[fUpper] upper limit for the parameter.
|
||||
\item[fLower] lower limit for the parameter.
|
||||
\item[pParName] is the name of the parameter which is driven through
|
||||
this adapter.
|
||||
\end{description}
|
||||
|
||||
This is the data structure for the private part of the environment
|
||||
controller driver:
|
||||
@d evada @{
|
||||
typedef struct __CHEV {
|
||||
char *pParName;
|
||||
pCodri pDriv;
|
||||
int iLastError;
|
||||
}CHev, *pCHev;
|
||||
@}
|
||||
|
||||
@o codri.h @{
|
||||
/*-------------------------------------------------------------------------
|
||||
C o n t r o l l e r D r i v e r
|
||||
|
||||
This file contains the description of the data structure for a
|
||||
general controller driver.
|
||||
|
||||
Mark Koennecke, January 1998
|
||||
--------------------------------------------------------------------------*/
|
||||
#ifndef CODRIV
|
||||
#define CODRIV
|
||||
#define CHFAIL -1
|
||||
#define CHREDO -2
|
||||
#define CHOK -3
|
||||
@<codri@>
|
||||
#endif
|
||||
|
||||
@}
|
||||
|
||||
@o choco.h @{
|
||||
/*-----------------------------------------------------------------------
|
||||
C h o p p e r C o n t r o l l e r
|
||||
|
||||
This is both the header file for a general controller and a SICS
|
||||
chopper controller.
|
||||
|
||||
Mark Koennecke, January 1998
|
||||
--------------------------------------------------------------------------*/
|
||||
#ifndef CHOCOSICS
|
||||
#define CHOCOSICS
|
||||
#include "codri.h"
|
||||
@<chocoint@>
|
||||
#ifdef CHOCOINTERNAL
|
||||
@<chocodata@>
|
||||
#endif
|
||||
#endif
|
||||
@}
|
||||
|
||||
|
||||
@o chadapter.h @{
|
||||
/*------------------------------------------------------------------------
|
||||
C H a d a p t e r
|
||||
|
||||
This is the header file for a drive adapter for collaboration with a
|
||||
general device controller as implemented in choco.*
|
||||
|
||||
Mark Koennecke, January 1998
|
||||
--------------------------------------------------------------------------*/
|
||||
#ifndef SICSCHADA
|
||||
#define SICSCHADA
|
||||
#include "codri.h"
|
||||
@<adapter@>
|
||||
#ifdef CHADAINTERNAL
|
||||
@<adadata@>
|
||||
@<evada@>
|
||||
#endif
|
||||
#endif
|
||||
@}
|
||||
|
||||
|
||||
\subsubsection{To Do}
|
||||
This scheme seems to be quite promising for handling many SICS
|
||||
objects. The following enhancements could be considered. Allow to set
|
||||
certain primitive parameters without a drivable interface. And add an
|
||||
adapter for an environment variable in the controller.
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
122
circular.c
Normal file
122
circular.c
Normal file
@ -0,0 +1,122 @@
|
||||
/*-----------------------------------------------------------------------
|
||||
Implementation file for a circular buffer facility.
|
||||
|
||||
Mark Koennecke, October 1999
|
||||
-------------------------------------------------------------------------*/
|
||||
#include <stdlib.h>
|
||||
#include <assert.h>
|
||||
#include "fortify.h"
|
||||
#include "circular.h"
|
||||
|
||||
/*========================================================================
|
||||
Definitions of Structures
|
||||
*/
|
||||
|
||||
typedef struct __CircularItem {
|
||||
void *pData;
|
||||
struct __CircularItem *next;
|
||||
struct __CircularItem *previous;
|
||||
}CircularItem, *pCircularItem;
|
||||
|
||||
|
||||
typedef struct __CIRCULAR {
|
||||
pCircularItem pPointer;
|
||||
CirKillFunc killer;
|
||||
}Circular;
|
||||
|
||||
/*=========================================================================
|
||||
Functions for Birth and Death
|
||||
*/
|
||||
pCircular createCircular(int iSize, CirKillFunc kf)
|
||||
{
|
||||
pCircular pNew = NULL;
|
||||
pCircularItem pItem = NULL, pFirst = NULL;
|
||||
int i;
|
||||
|
||||
|
||||
assert(iSize > 0);
|
||||
|
||||
/* create data structure */
|
||||
pNew = (pCircular)malloc(sizeof(Circular));
|
||||
if(!pNew)
|
||||
return NULL;
|
||||
memset(pNew,0,sizeof(Circular));
|
||||
|
||||
/* create all the members of the circular buffer */
|
||||
pItem = (pCircularItem)malloc(sizeof(CircularItem));
|
||||
if(!pItem)
|
||||
return NULL;
|
||||
memset(pItem,0,sizeof(CircularItem));
|
||||
pNew->pPointer = pItem;
|
||||
pFirst = pItem;
|
||||
for(i = 1; i < iSize; i++)
|
||||
{
|
||||
pItem = (pCircularItem)malloc(sizeof(CircularItem));
|
||||
if(!pItem)
|
||||
return NULL;
|
||||
memset(pItem,0,sizeof(CircularItem));
|
||||
pItem->previous = pNew->pPointer;
|
||||
pNew->pPointer->next = pItem;
|
||||
pNew->pPointer = pItem;
|
||||
}
|
||||
pItem->next = pFirst;
|
||||
pFirst->previous = pItem;
|
||||
pNew->killer = kf;
|
||||
return pNew;
|
||||
}
|
||||
/*---------------------------------------------------------------------*/
|
||||
void deleteCircular(pCircular self)
|
||||
{
|
||||
pCircularItem pNext = NULL, pCurrent = NULL;
|
||||
|
||||
assert(self);
|
||||
|
||||
self->pPointer->previous->next = NULL;
|
||||
pNext = self->pPointer;
|
||||
while(pNext != NULL)
|
||||
{
|
||||
pCurrent = pNext;
|
||||
pNext = pCurrent->next;
|
||||
if(pCurrent->pData && self->killer)
|
||||
{
|
||||
self->killer(pCurrent->pData);
|
||||
}
|
||||
free(pCurrent);
|
||||
}
|
||||
free(self);
|
||||
}
|
||||
/*========================================================================
|
||||
Data Manipulation functions
|
||||
*/
|
||||
void setCircular(pCircular self, void *pData)
|
||||
{
|
||||
assert(self);
|
||||
|
||||
/* delete if present */
|
||||
if(self->pPointer->pData && self->killer)
|
||||
{
|
||||
self->killer(self->pPointer->pData);
|
||||
}
|
||||
self->pPointer->pData = pData;
|
||||
}
|
||||
/*----------------------------------------------------------------------*/
|
||||
void *getCircular(pCircular self)
|
||||
{
|
||||
assert(self);
|
||||
return self->pPointer->pData;
|
||||
}
|
||||
/*========================================================================
|
||||
Pointer movement
|
||||
*/
|
||||
void nextCircular(pCircular self)
|
||||
{
|
||||
assert(self);
|
||||
self->pPointer = self->pPointer->next;
|
||||
}
|
||||
/*---------------------------------------------------------------------*/
|
||||
void previousCircular(pCircular self)
|
||||
{
|
||||
assert(self);
|
||||
self->pPointer = self->pPointer->previous;
|
||||
}
|
||||
|
31
circular.h
Normal file
31
circular.h
Normal file
@ -0,0 +1,31 @@
|
||||
/*--------------------------------------------------------------------------
|
||||
C I R C U L A R
|
||||
|
||||
This is the implementation of a general purpose circular buffer facility.
|
||||
|
||||
Mark Koennecke, October 1999
|
||||
--------------------------------------------------------------------------*/
|
||||
#ifndef CIRCULAR
|
||||
#define CIRCULAR
|
||||
|
||||
typedef struct __CIRCULAR *pCircular;
|
||||
typedef void (*CirKillFunc)(void *pData);
|
||||
|
||||
/* ----------------- birth and death -----------------------------------*/
|
||||
pCircular createCircular(int iSize,CirKillFunc kf);
|
||||
/*
|
||||
iSize is the size of the circular Buffer.
|
||||
KillFunc is a function which can safely delete the data item held
|
||||
as content of the circular buffer.
|
||||
*/
|
||||
void deleteCircular(pCircular self);
|
||||
|
||||
/*-------------- access and modify data item at current position ----------*/
|
||||
void setCircular(pCircular self, void *pData);
|
||||
void *getCircular(pCircular self);
|
||||
|
||||
/*---------------- pointer movement --------------------------------------*/
|
||||
void nextCircular(pCircular self);
|
||||
void previousCircular(pCircular self);
|
||||
|
||||
#endif
|
44
codri.h
Normal file
44
codri.h
Normal file
@ -0,0 +1,44 @@
|
||||
|
||||
/*-------------------------------------------------------------------------
|
||||
C o n t r o l l e r D r i v e r
|
||||
|
||||
This file contains the description of the data structure for a
|
||||
general controller driver.
|
||||
|
||||
Mark Koennecke, January 1998
|
||||
--------------------------------------------------------------------------*/
|
||||
#ifndef CODRIV
|
||||
#define CODRIV
|
||||
#define CHFAIL -1
|
||||
#define CHREDO -2
|
||||
#define CHOK -3
|
||||
|
||||
typedef struct __CODRI *pCodri;
|
||||
typedef struct __CODRI {
|
||||
int (*Init)(pCodri self);
|
||||
int (*Close)(pCodri self);
|
||||
int (*Delete)(pCodri self);
|
||||
int (*SetPar)(pCodri self,
|
||||
char *parname,
|
||||
float fValue);
|
||||
int (*SetPar2)(pCodri self,
|
||||
char *parname,
|
||||
char *value);
|
||||
int (*GetPar)(pCodri self,
|
||||
char *parname,
|
||||
char *pBuffer,
|
||||
int iBufLen);
|
||||
int (*CheckPar)(pCodri self,
|
||||
char *parname);
|
||||
int (*GetError)(pCodri self, int *iCode,
|
||||
char *pError,
|
||||
int iErrLen);
|
||||
int (*TryFixIt)(pCodri self, int iCode);
|
||||
int (*Halt)(pCodri self);
|
||||
char *pParList;
|
||||
void *pPrivate;
|
||||
}Codri;
|
||||
|
||||
|
||||
#endif
|
||||
|
229
coll.tcl
Normal file
229
coll.tcl
Normal file
@ -0,0 +1,229 @@
|
||||
#----------------------------------------------------------------------------
|
||||
# This file implements the collimator commands for SANS. It requires an
|
||||
# SPS named sps2 within SICS.
|
||||
#
|
||||
# Mark Koennecke, March 1999
|
||||
#----------------------------------------------------------------------------
|
||||
proc coll args {
|
||||
#-------- set case
|
||||
if { [llength $args] > 0 ] } {
|
||||
set length [lindex $args 0]
|
||||
switch $length {
|
||||
18 {
|
||||
set command "sps2 push 200 0"
|
||||
break
|
||||
}
|
||||
15 {
|
||||
set command "sps2 push 200 1"
|
||||
break
|
||||
}
|
||||
11 {
|
||||
set command "sps2 push 200 2"
|
||||
break
|
||||
}
|
||||
8 {
|
||||
set command "sps2 push 200 3"
|
||||
break
|
||||
}
|
||||
6 {
|
||||
set command "sps2 push 200 4"
|
||||
break
|
||||
}
|
||||
4.5 {
|
||||
set command "sps2 push 200 5"
|
||||
break
|
||||
}
|
||||
3 {
|
||||
set command "sps2 push 200 6"
|
||||
break
|
||||
}
|
||||
2 {
|
||||
set command "sps2 push 200 7"
|
||||
break
|
||||
}
|
||||
1.4 {
|
||||
set command "sps2 push 201 0"
|
||||
break
|
||||
}
|
||||
1 {
|
||||
set command "sps2 push 201 1"
|
||||
break
|
||||
}
|
||||
default {
|
||||
append text \
|
||||
[format "ERROR: collimation length %s invalid\n" $length]
|
||||
append text "Possible length are: 18,15,11,8,6,4.5,3,2,1.4,1\n"
|
||||
append text \
|
||||
"Extraneous . or other characters will yield this error too\n"
|
||||
append text "SPS programming courtesy Enzo Manfrin\n"
|
||||
return $text
|
||||
}
|
||||
#------- command has been built, execute it!
|
||||
set ret [catch {$command} msg]
|
||||
if {$ret != 0} {
|
||||
error $msg
|
||||
}
|
||||
setstatus Driving
|
||||
#------- wait till finish, check for interrupts on the way
|
||||
set exe 1
|
||||
while {$exe} {
|
||||
set ret [catch {sps2 colli} msg]
|
||||
if {$ret != 0 } {
|
||||
setstatus Eager
|
||||
error $msg
|
||||
}
|
||||
set l [split $msg =]
|
||||
set cval [lindex $l 1]
|
||||
if { [expr $cval - $length] < 0.2 } {
|
||||
set exe 0
|
||||
}
|
||||
set rupt [getint]
|
||||
if {[string compare $rupt continue] != 0 } {
|
||||
setstatus Eager
|
||||
error "ERROR: driving collimator interrupted"
|
||||
}
|
||||
}
|
||||
setstatus Eager
|
||||
return OK
|
||||
} else {
|
||||
#-------- get case
|
||||
set ret [catch {sps2 colli} msg]
|
||||
if {$ret != 0} {
|
||||
error $msg
|
||||
}
|
||||
return $msg
|
||||
}
|
||||
}
|
||||
#--------------------------------------------------------------------------
|
||||
# Another procedure for handling the attenuator.
|
||||
#
|
||||
# Mark Koennecke, March 1999
|
||||
#--------------------------------------------------------------------------
|
||||
proc findatt { } {
|
||||
#----------- find the current attenuator
|
||||
set ret [catch {sps2 stat2 9 5} msg]
|
||||
if { $ret != 0 } {
|
||||
error $msg
|
||||
}
|
||||
set l [split $msg =]
|
||||
if { [lindex $l 1] == 1} {
|
||||
return 0
|
||||
}
|
||||
set ret [catch {sps2 stat2 9 6} msg]
|
||||
if { $ret != 0 } {
|
||||
error $msg
|
||||
}
|
||||
set l [split $msg =]
|
||||
if { [lindex $l 1] == 1} {
|
||||
return 1
|
||||
}
|
||||
set ret [catch {sps2 stat2 9 7} msg]
|
||||
if { $ret != 0 } {
|
||||
error $msg
|
||||
}
|
||||
set l [split $msg =]
|
||||
if { [lindex $l 1] == 1} {
|
||||
return 2
|
||||
}
|
||||
set ret [catch {sps2 stat2 10 0} msg]
|
||||
if { $ret != 0 } {
|
||||
error $msg
|
||||
}
|
||||
set l [split $msg =]
|
||||
if { [lindex $l 1] == 1} {
|
||||
return 3
|
||||
}
|
||||
set ret [catch {sps2 stat2 10 1} msg]
|
||||
if { $ret != 0 } {
|
||||
error $msg
|
||||
}
|
||||
set l [split $msg =]
|
||||
if { [lindex $l 1] == 1} {
|
||||
return 4
|
||||
}
|
||||
set ret [catch {sps2 stat2 10 2} msg]
|
||||
if { $ret != 0 } {
|
||||
error $msg
|
||||
}
|
||||
set l [split $msg =]
|
||||
if { [lindex $l 1] == 1} {
|
||||
return 5
|
||||
}
|
||||
}
|
||||
#--------------------------------------------------------------------------
|
||||
proc att args {
|
||||
if [ llength $args] > 0} {
|
||||
#------- set case
|
||||
set aat [lindex $args 0]
|
||||
switch $aat {
|
||||
0 {
|
||||
set command "sps2 push 210 7"
|
||||
break
|
||||
}
|
||||
1 {
|
||||
set command "sps2 push 220 0"
|
||||
break
|
||||
}
|
||||
2 {
|
||||
set command "sps2 push 220 1"
|
||||
break
|
||||
}
|
||||
3 {
|
||||
set command "sps2 push 230 0"
|
||||
break
|
||||
}
|
||||
4 {
|
||||
set command "sps2 push 230 1"
|
||||
break
|
||||
}
|
||||
5 {
|
||||
set command "sps2 push 230 2"
|
||||
break
|
||||
}
|
||||
default {
|
||||
error [format "ERROR: attenuator %s unknown" $aat]
|
||||
}
|
||||
}
|
||||
#-----send command
|
||||
set ret [catch {$command} msg]
|
||||
if {$ret != 0} {
|
||||
error $msg
|
||||
}
|
||||
#------ wait till done
|
||||
setstatus Driving
|
||||
set exe 1
|
||||
while {$exe} {
|
||||
set ret [catch {findatt} msg]
|
||||
if {$ret != 0 } {
|
||||
setstatus Eager
|
||||
error $msg
|
||||
}
|
||||
if { [expr $msg - $aat] < 0.2 } {
|
||||
set exe 0
|
||||
}
|
||||
set rupt [getint]
|
||||
if {[string compare $rupt continue] != 0 } {
|
||||
setstatus Eager
|
||||
error "ERROR: driving attenuator interrupted"
|
||||
}
|
||||
}
|
||||
setstatus Eager
|
||||
return OK
|
||||
} else {
|
||||
#----------- get case
|
||||
set ret [catch {findatt} msg]
|
||||
if {$ret != 0 } {
|
||||
error $msg
|
||||
} else {
|
||||
return [format "att = %s" $msg]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
79
collidertest.tcl
Normal file
79
collidertest.tcl
Normal file
@ -0,0 +1,79 @@
|
||||
#--------------------------------------------------------------------------
|
||||
# test and example script for the anticollider
|
||||
#
|
||||
# Mark Koennecke, August 2002
|
||||
#------------------------------------------------------------------------
|
||||
|
||||
proc testlimits tg {
|
||||
upvar $tg targets
|
||||
if { abs( $targets(om) - $targets(stt)) < 30 } {
|
||||
error "!!!!! two theta - omega CRASH!!!!!!!"
|
||||
}
|
||||
if {$targets(chi) > 190.} {
|
||||
error "chi upperlimit crashed"
|
||||
}
|
||||
if { $targets(om) > -90 && $targets(om) <= -81.5 && $targets(chi) < 152} {
|
||||
error "!!!!!! chi - omega CRASH aborted !!!!!"
|
||||
}
|
||||
if { $targets(om) > -81.5 && $targets(om) <= -55 && $targets(chi) < 137} {
|
||||
error "!!!!!! chi - omega CRASH aborted !!!!!"
|
||||
}
|
||||
if { $targets(om) > -55 && $targets(om) <= -52 && $targets(chi) < 132} {
|
||||
error "!!!!!! chi - omega CRASH aborted !!!!!"
|
||||
}
|
||||
if { $targets(om) > -52 && $targets(om) <= -30 && $targets(chi) < 75} {
|
||||
error "!!!!!! chi - omega CRASH aborted !!!!!"
|
||||
}
|
||||
return
|
||||
}
|
||||
#-------------------------------------------------------------------------
|
||||
proc chiFirst? tg {
|
||||
upvar $tg targets
|
||||
set om [SplitReply [om]]
|
||||
set chi [SplitReply [chi]]
|
||||
if {$chi < $targets(chi) } {
|
||||
return 1
|
||||
} else {
|
||||
return 0
|
||||
}
|
||||
}
|
||||
#---------------------------------------------------------------------------
|
||||
proc collidertest args {
|
||||
#----------- read command line targets
|
||||
set entries [expr [llength $args] / 2]
|
||||
for {set i 0} {$i < $entries} {incr i} {
|
||||
set ind [expr $i * 2]
|
||||
set targets([lindex $args $ind]) [lindex $args [expr $ind +1]]
|
||||
}
|
||||
#--------- check if all motors are there. If not get targets from
|
||||
# current position
|
||||
if { [info exists targets(om)] == 0} {
|
||||
set targets(om) [SplitReply [om]]
|
||||
}
|
||||
if { [info exists targets(stt)] == 0} {
|
||||
set targets(stt) [SplitReply [stt]]
|
||||
}
|
||||
if { [info exists targets(chi)] == 0} {
|
||||
set targets(chi) [SplitReply [chi]]
|
||||
}
|
||||
if { [info exists targets(phi)] == 0} {
|
||||
set targets(phi) [SplitReply [phi]]
|
||||
}
|
||||
#---------- proceed to real collision detection hydraulics
|
||||
# first: test complex limits
|
||||
set ret [catch {testlimits targets} msg]
|
||||
if {$ret != 0} {
|
||||
clientput [format "ERROR %s" $msg]
|
||||
error $msg
|
||||
}
|
||||
anticollision add 1 stt $targets(stt)
|
||||
|
||||
if { [chiFirst? targets] == 1} {
|
||||
anticollision add 2 chi $targets(chi)
|
||||
anticollision add 3 om $targets(om)
|
||||
} else {
|
||||
anticollision add 2 om $targets(om)
|
||||
anticollision add 3 chi $targets(chi)
|
||||
}
|
||||
anticollision add 3 phi $targets(phi)
|
||||
}
|
54
comentry.h
Normal file
54
comentry.h
Normal file
@ -0,0 +1,54 @@
|
||||
/*---------------------------------------------------------------------------
|
||||
|
||||
C O M E N T R Y
|
||||
|
||||
some helper stuff for implementing MultiMotors. Functions in mumo.c
|
||||
|
||||
Mark Koennecke, February 1997
|
||||
---------------------------------------------------------------------------*/
|
||||
#ifndef COMENTRY
|
||||
#define COMENTRY
|
||||
|
||||
#define MAXDEV 10
|
||||
typedef struct {
|
||||
void *pData;
|
||||
char name[80];
|
||||
pObjectDescriptor pDescriptor;
|
||||
float fVal;
|
||||
int iCount;
|
||||
} DevEntry;
|
||||
|
||||
/* -------------------The Entry per registered command --------------------*/
|
||||
typedef struct __ComEntry {
|
||||
char name[10];
|
||||
char *pCommand;
|
||||
int iDevice;
|
||||
DevEntry pDevice[MAXDEV];
|
||||
struct __ComEntry *pNext;
|
||||
struct __ComEntry *pPrevious;
|
||||
}ComEntry, *pComEntry;
|
||||
|
||||
typedef struct __NAMPOS {
|
||||
char *name; /* the name */
|
||||
pComEntry pCom; /* the positions */
|
||||
char *text; /* explanatory text */
|
||||
struct __NAMPOS *pNext;
|
||||
struct __NAMPOS *pPrevious;
|
||||
} NamPos, *pNamPos;
|
||||
|
||||
typedef struct __NAMMAP {
|
||||
char *alias;
|
||||
char *motname;
|
||||
pMotor pMot;
|
||||
} NamMap, *pNamMap;
|
||||
|
||||
int CheckComEntryBounds(pComEntry self, SConnection *pCon);
|
||||
int AddExeEntry(pExeList self, pComEntry pNew, SConnection *pCon);
|
||||
pComEntry CreateComEntry(void);
|
||||
pComEntry CopyComEntry(pComEntry pOld);
|
||||
int AddDevEntry(pComEntry pCom, char *name, void *pData, pObjectDescriptor pDes,
|
||||
float fVal);
|
||||
pNamPos LinkNamPos(pNamPos pHead, pNamPos pNew);
|
||||
pNamPos UnlinkNamPos(pNamPos pHead, pNamPos pOld);
|
||||
#endif
|
||||
|
476
commandlog.c
Normal file
476
commandlog.c
Normal file
@ -0,0 +1,476 @@
|
||||
/*--------------------------------------------------------------------------
|
||||
C O M M A N D L O G
|
||||
|
||||
A much requested facility for writing only user and manager level commands
|
||||
in a transcript file. This is it.
|
||||
|
||||
Mark Koennecke, June 1998
|
||||
|
||||
Extended to support Heinz Heers autolog-file
|
||||
Mark Koennecke, April-May 1999
|
||||
|
||||
Added a tail facility
|
||||
Mark Koennecke, October 1999
|
||||
--------------------------------------------------------------------------*/
|
||||
#include <stdlib.h>
|
||||
#include <assert.h>
|
||||
#include <stdio.h>
|
||||
#include <time.h>
|
||||
#include <tcl.h>
|
||||
#include "sics.h"
|
||||
#include "ifile.h"
|
||||
#include "sicsvar.h"
|
||||
#include "scaldate.h"
|
||||
#include "network.h"
|
||||
#include "circular.h"
|
||||
|
||||
|
||||
/* in conman.c */
|
||||
int TelnetWrite(mkChannel *pSock, char *pText);
|
||||
|
||||
|
||||
/*-------------------- the command log file pointer ---------------------*/
|
||||
static FILE *fd = NULL;
|
||||
static FILE *fauto = NULL;
|
||||
static char pFile[256];
|
||||
/*-------------------- the tail buffer ---------------------------------*/
|
||||
static pCircular pTail = NULL;
|
||||
#define MAXTAIL 1000
|
||||
/*----------------------------------------------------------------------*/
|
||||
void WriteToCommandLog(char *prompt,char *text)
|
||||
{
|
||||
int iNL = 0, iPos;
|
||||
char *pPtr = NULL, *pCopy = NULL, *pText = NULL;
|
||||
char myBuffer[1024];
|
||||
|
||||
/*
|
||||
we change the text, so we need to make a local copy. A copy
|
||||
is dynamically allocated only if it does not fit into
|
||||
myBuffer.
|
||||
*/
|
||||
if(strlen(text) > 1023){
|
||||
pCopy = (char *)malloc((strlen(text)+2)*sizeof(char));
|
||||
if(pCopy == NULL){
|
||||
return;
|
||||
}
|
||||
memset(pCopy,0,(strlen(text)+2)*sizeof(char));
|
||||
strcpy(pCopy,text);
|
||||
pText = pCopy;
|
||||
} else {
|
||||
strcpy(myBuffer,text);
|
||||
pText = myBuffer;
|
||||
}
|
||||
|
||||
/* figure out if we have to do a newline with pText as well */
|
||||
pPtr = strrchr(pText,'\n');
|
||||
if(pPtr != NULL)
|
||||
{
|
||||
iPos = pPtr - pText;
|
||||
if(iPos >= (strlen(pText) - 2) )
|
||||
{
|
||||
iNL = 1;
|
||||
}
|
||||
}
|
||||
|
||||
/* supress status messages */
|
||||
if(strstr(pText,"status =") != NULL)
|
||||
{
|
||||
if(pCopy != NULL){
|
||||
free(pCopy);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
/* suppress TRANSACTIONFINISHED as well in order to make the WWW
|
||||
commandlog work
|
||||
*/
|
||||
if(strstr(pText,"TRANSACTIONFINISHED") != NULL)
|
||||
{
|
||||
if(pCopy != NULL){
|
||||
free(pCopy);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
/* create tail buffer as needed */
|
||||
if(!pTail)
|
||||
{
|
||||
pTail = createCircular(MAXTAIL,free);
|
||||
}
|
||||
|
||||
/* user file */
|
||||
if(fd != NULL)
|
||||
{
|
||||
if(iNL)
|
||||
{
|
||||
fprintf(fd,"%s %s",prompt, pText);
|
||||
}
|
||||
else
|
||||
{
|
||||
fprintf(fd,"%s %s\n",prompt, pText);
|
||||
}
|
||||
}
|
||||
/* automatic file */
|
||||
if(fauto != NULL)
|
||||
{
|
||||
if(iNL)
|
||||
{
|
||||
fprintf(fauto,"%s %s",prompt, pText);
|
||||
}
|
||||
else
|
||||
{
|
||||
fprintf(fauto,"%s %s\n",prompt, pText);
|
||||
}
|
||||
}
|
||||
/* tail buffer */
|
||||
if(pTail != NULL)
|
||||
{
|
||||
if(iNL)
|
||||
{
|
||||
pPtr = strrchr(pText,'\n');
|
||||
*pPtr = ' ';
|
||||
}
|
||||
setCircular(pTail,strdup(pText));
|
||||
nextCircular(pTail);
|
||||
}
|
||||
if(pCopy != NULL){
|
||||
free(pCopy);
|
||||
}
|
||||
}
|
||||
/*------------------------------------------------------------------------*/
|
||||
static void PrintTail(int iNum, SConnection *pCon)
|
||||
{
|
||||
char *pPtr = NULL;
|
||||
int i;
|
||||
|
||||
if(pTail == NULL)
|
||||
{
|
||||
SCWrite(pCon,"Nothing to print",eError);
|
||||
return;
|
||||
}
|
||||
|
||||
/* step back */
|
||||
for(i = 0; i < iNum; i++)
|
||||
{
|
||||
previousCircular(pTail);
|
||||
}
|
||||
|
||||
/* now step ahead and print. I have to use a trick here: I do not
|
||||
want the tail stuff to show up in log files. Thus I write it
|
||||
directly to the connection socket.
|
||||
*/
|
||||
for(i = 0; i < iNum; i++)
|
||||
{
|
||||
pPtr = (char *)getCircular(pTail);
|
||||
if(pCon->pSock)
|
||||
{
|
||||
TelnetWrite(pCon->pSock, pPtr);
|
||||
}
|
||||
nextCircular(pTail);
|
||||
}
|
||||
}
|
||||
/*------------------------------------------------------------------------*/
|
||||
void CLFormatTime(char *pBuffer, int iBufLen)
|
||||
{
|
||||
time_t iDate;
|
||||
struct tm *psTime;
|
||||
|
||||
/* make time string */
|
||||
iDate = time(NULL);
|
||||
psTime = localtime(&iDate);
|
||||
memset(pBuffer,0,iBufLen);
|
||||
strftime(pBuffer,iBufLen,"%Y-%m-%d@%H-%M-%S",psTime);
|
||||
}
|
||||
/*----------------------------------------------------------------------
|
||||
Build an automatically generated log file name and open it.
|
||||
*/
|
||||
static void AutoLog(void)
|
||||
{
|
||||
char pBueffel[1024];
|
||||
char pTime[80];
|
||||
pSicsVariable pInst = NULL;
|
||||
char *pPtr = NULL;
|
||||
SConnection *pIntern = NULL;
|
||||
|
||||
if(fauto)
|
||||
{
|
||||
fclose(fauto);
|
||||
fauto = NULL;
|
||||
}
|
||||
|
||||
/* find path */
|
||||
pPtr = IFindOption(pSICSOptions,"LogFileDir");
|
||||
if(!pPtr)
|
||||
{
|
||||
pPtr = strdup("~/log");
|
||||
printf("WARNING: Required SICS option LogFileDir not found");
|
||||
}
|
||||
|
||||
/* get time */
|
||||
CLFormatTime(pTime,79);
|
||||
|
||||
/* build file name */
|
||||
sprintf(pBueffel,"%s/auto%s.log",pPtr,pTime);
|
||||
|
||||
/* open file */
|
||||
fauto = fopen(pBueffel,"w");
|
||||
if(!fauto)
|
||||
{
|
||||
ServerWriteGlobal("ERROR: failed to open autolog file",eError);
|
||||
}
|
||||
|
||||
/* write the instrument name to it for identification */
|
||||
pInst = FindVariable(pServ->pSics,"instrument");
|
||||
if(pInst)
|
||||
{
|
||||
sprintf(pBueffel,"Logfile started at instument %s at %s",
|
||||
pInst->text,pTime);
|
||||
WriteToCommandLog("SYS>> ", pBueffel);
|
||||
}
|
||||
|
||||
/* if a file to execute is configured, execute it */
|
||||
pPtr = NULL;
|
||||
pPtr = IFindOption(pSICSOptions,"logstartfile");
|
||||
if(pPtr != NULL)
|
||||
{
|
||||
pIntern = SCCreateDummyConnection(pServ->pSics);
|
||||
if(!pIntern)
|
||||
{
|
||||
return;
|
||||
}
|
||||
SCnoSock(pIntern);
|
||||
SCSetRights(pIntern,usUser);
|
||||
sprintf(pBueffel,"fileeval %s",pPtr);
|
||||
InterpExecute(pServ->pSics,pIntern,pBueffel);
|
||||
SCDeleteConnection(pIntern);
|
||||
}
|
||||
}
|
||||
/*----------------------------------------------------------------------
|
||||
AutoTask puts a time stamp into the auto log file any hour and
|
||||
creates a new log file any 24 hours
|
||||
*/
|
||||
static time_t tLogfile = 0;
|
||||
static time_t tStamp = 0;
|
||||
static int iEnd = 1;
|
||||
static int iAutoActive = 0;
|
||||
static int iIntervall = 60;
|
||||
|
||||
static int AutoTask(void *pData)
|
||||
{
|
||||
time_t tNow;
|
||||
char pTime[80];
|
||||
struct tm *sTime;
|
||||
long julian;
|
||||
unsigned yr, mo, dd;
|
||||
|
||||
tNow = time(NULL);
|
||||
if(tNow > tLogfile)
|
||||
{
|
||||
AutoLog();
|
||||
sTime = localtime(&tNow);
|
||||
/* find next day, do so by converting to julian Date, add one
|
||||
and calculate back. The (stolen) julian calculations will
|
||||
take care of all the leaps and month and year etc.
|
||||
*/
|
||||
julian = ymd_to_scalar(sTime->tm_year+1900, sTime->tm_mon+1,
|
||||
sTime->tm_mday);
|
||||
julian++;
|
||||
scalar_to_ymd(julian, &yr, &mo, &dd);
|
||||
sTime->tm_sec = 0;
|
||||
sTime->tm_min = 1;
|
||||
sTime->tm_hour = 0;
|
||||
sTime->tm_mday = dd;
|
||||
sTime->tm_mon = mo - 1;
|
||||
sTime->tm_year = yr - 1900;
|
||||
tLogfile = mktime(sTime);
|
||||
if(tLogfile < 0)
|
||||
tLogfile = tNow + 60*60*24;
|
||||
}
|
||||
if(tNow > tStamp)
|
||||
{
|
||||
CLFormatTime(pTime,79);
|
||||
WriteToCommandLog("TIMESTAMP>> ",pTime);
|
||||
sTime = localtime(&tNow);
|
||||
sTime->tm_sec = 0;
|
||||
sTime->tm_min += iIntervall;
|
||||
if(sTime->tm_min >= 60)
|
||||
{
|
||||
sTime->tm_min = 0;
|
||||
sTime->tm_hour++;
|
||||
}
|
||||
if(sTime->tm_hour >= 24)
|
||||
sTime->tm_hour = 0;
|
||||
tStamp = mktime(sTime);
|
||||
if((tStamp < 0) || ( (tStamp-tNow) < 100) )
|
||||
{
|
||||
tStamp = tNow + iIntervall*60;
|
||||
}
|
||||
if(fauto)
|
||||
fflush(fauto);
|
||||
}
|
||||
|
||||
return iEnd;
|
||||
}
|
||||
/*----------- a command to configure the log --------------------------*/
|
||||
int CommandLog(SConnection *pCon, SicsInterp *pSics, void *pData,
|
||||
int argc, char *argv[])
|
||||
{
|
||||
char *pPtr = NULL;
|
||||
char pBueffel[1024];
|
||||
int iVal, iRet;
|
||||
|
||||
if(argc == 1)
|
||||
{
|
||||
if(fd)
|
||||
{
|
||||
sprintf(pBueffel,"Command log ACTIVE at %s",pFile);
|
||||
SCWrite(pCon,pBueffel,eValue);
|
||||
return 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
SCWrite(pCon,"Command logging DISABLED",eValue);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
/* handle tail */
|
||||
strtolower(argv[1]);
|
||||
if(strcmp(argv[1],"tail") == 0)
|
||||
{
|
||||
/* check for optional number of lines argument */
|
||||
iVal = 20;
|
||||
if(argc >= 3)
|
||||
{
|
||||
iRet = Tcl_GetInt(pSics->pTcl,argv[2],&iVal);
|
||||
if(iRet != TCL_OK)
|
||||
iVal = 20;
|
||||
}
|
||||
PrintTail(iVal,pCon);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* check rights */
|
||||
if(!SCMatchRights(pCon,usMugger))
|
||||
{
|
||||
SCWrite(pCon,"ERROR: only managers may configure the logfile",
|
||||
eError);
|
||||
SCWrite(pCon,"ERROR: Request refused",eError);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* check no of args */
|
||||
if(argc < 2)
|
||||
{
|
||||
SCWrite(pCon,
|
||||
"ERROR: Insufficient number or arguments to commandlog",
|
||||
eError);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if(strcmp(argv[1],"new") == 0) /* new command */
|
||||
{
|
||||
if(argc < 3)
|
||||
{
|
||||
SCWrite(pCon,
|
||||
"ERROR: Insufficient number or arguments to commandlog new",
|
||||
eError);
|
||||
return 0;
|
||||
}
|
||||
if(fd)
|
||||
{
|
||||
fclose(fd);
|
||||
fd = NULL;
|
||||
}
|
||||
/* make the filename */
|
||||
pPtr = IFindOption(pSICSOptions,"LogFileDir");
|
||||
if(!pPtr)
|
||||
{
|
||||
SCWrite(pCon,"WARNING: no log file directory specified",eWarning);
|
||||
sprintf(pBueffel,"%s",argv[2]);
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
sprintf(pBueffel,"%s/%s",pPtr,argv[2]);
|
||||
}
|
||||
fd = fopen(pBueffel,"w");
|
||||
if(!fd)
|
||||
{
|
||||
sprintf(pBueffel,"ERROR: cannot open %s/%s for writing",pPtr,
|
||||
argv[2]);
|
||||
SCWrite(pCon,pBueffel,eError);
|
||||
return 0;
|
||||
}
|
||||
strcpy(pFile,argv[2]);
|
||||
SCSendOK(pCon);
|
||||
return 1;
|
||||
}
|
||||
else if(strcmp(argv[1],"auto") == 0)
|
||||
{
|
||||
if(iAutoActive)
|
||||
{
|
||||
SCWrite(pCon,"ERROR: autologging is already active",eError);
|
||||
return 0;
|
||||
}
|
||||
TaskRegister(pServ->pTasker,
|
||||
AutoTask,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
1);
|
||||
SCSendOK(pCon);
|
||||
iAutoActive = 1;
|
||||
return 1;
|
||||
}
|
||||
else if(strcmp(argv[1],"intervall") == 0)
|
||||
{
|
||||
if(argc > 2)
|
||||
{
|
||||
iRet = Tcl_GetInt(pSics->pTcl,argv[2],&iVal);
|
||||
if(iRet != TCL_OK)
|
||||
{
|
||||
SCWrite(pCon,"ERROR: failed to convert new intervall to number",
|
||||
eError);
|
||||
return 0;
|
||||
}
|
||||
iIntervall = iVal;
|
||||
SCSendOK(pCon);
|
||||
return 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
sprintf(pBueffel,"autolog.intervall = %d", iIntervall);
|
||||
SCWrite(pCon,pBueffel,eValue);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
else if(strcmp(argv[1],"close") == 0) /* close command */
|
||||
{
|
||||
fclose(fd);
|
||||
fd = NULL;
|
||||
SCSendOK(pCon);
|
||||
return 1;
|
||||
}
|
||||
sprintf(pBueffel,"ERROR: subcommand %s to commandlog unknown",
|
||||
argv[1]);
|
||||
SCWrite(pCon,pBueffel,eError);
|
||||
return 0;
|
||||
}
|
||||
/*-------------------------------------------------------------------------*/
|
||||
void CommandLogClose(void *pData)
|
||||
{
|
||||
if(fd)
|
||||
{
|
||||
fclose(fd);
|
||||
}
|
||||
if(fauto)
|
||||
fclose(fauto);
|
||||
if(pData)
|
||||
KillDummy(pData);
|
||||
if(pTail)
|
||||
deleteCircular(pTail);
|
||||
}
|
||||
|
||||
|
||||
|
19
commandlog.h
Normal file
19
commandlog.h
Normal file
@ -0,0 +1,19 @@
|
||||
/*--------------------------------------------------------------------------
|
||||
C O M M A N D L O G
|
||||
|
||||
A much requested facility for writing only user an manager level commands
|
||||
in a transcript file. This is it.
|
||||
|
||||
Mark Koennecke, June 1998
|
||||
|
||||
--------------------------------------------------------------------------*/
|
||||
#ifndef COMMANDLOG
|
||||
#define COMMANDLOG
|
||||
void WriteToCommandLog(char *prompt,char *pText);
|
||||
int CommandLog(SConnection *pCon, SicsInterp *pSics, void *pData,
|
||||
int argc, char *argv[]);
|
||||
|
||||
void CommandLogClose(void *pData);
|
||||
#endif
|
||||
|
||||
|
26
configfu.h
Normal file
26
configfu.h
Normal file
@ -0,0 +1,26 @@
|
||||
/*--------------------------------------------------------------------------
|
||||
` This is a common header for rarely used configuration
|
||||
functions. Implementations are distributed across several
|
||||
files. Therefor they are mentioned in a comment.
|
||||
Mark Koennecke, December 1996
|
||||
|
||||
copyrights: see implementation files
|
||||
--------------------------------------------------------------------------*/
|
||||
#ifndef SICSCONFIG
|
||||
#define SICSCONFIG
|
||||
|
||||
int AddHalt(SConnection *pCon, SicsInterp *pSics, void *pData,
|
||||
int argc, char *argv[]);
|
||||
/* configuration command: enters argv objects into Halt List of Interrupt.
|
||||
This is the means how the server knows which hardware to halt in an
|
||||
case of emergency. Implemented in intserv.c
|
||||
*/
|
||||
|
||||
|
||||
int ListObjects(SConnection *pCon, SicsInterp *pSics, void *pData,
|
||||
int argc, char *argv[]);
|
||||
|
||||
/*
|
||||
lists all avialable objects. Realised in Scinter.c
|
||||
*/
|
||||
#endif
|
130
conman.h
Normal file
130
conman.h
Normal file
@ -0,0 +1,130 @@
|
||||
|
||||
/*--------------------------------------------------------------------------
|
||||
C O N N E C T I O N O B J E C T
|
||||
|
||||
This file defines the connection object data structure and the interface to
|
||||
this data structure. This is one of the most important SICS components.
|
||||
|
||||
|
||||
Substantially revised from a prior version.
|
||||
|
||||
Mark Koennecke, September 1997
|
||||
|
||||
copyright: see copyright.h
|
||||
----------------------------------------------------------------------------*/
|
||||
#ifndef SICSCONNECT
|
||||
#define SICSCONNECT
|
||||
#include <stdio.h>
|
||||
#include "costa.h"
|
||||
#include "SCinter.h"
|
||||
#include "network.h"
|
||||
#include "obdes.h"
|
||||
|
||||
#define MAXLOGFILES 10
|
||||
|
||||
typedef int (*writeFunc)(struct __SConnection *pCon,
|
||||
char *pMessage, int iCode);
|
||||
|
||||
typedef struct __SConnection {
|
||||
/* object basics */
|
||||
pObjectDescriptor pDes;
|
||||
char *pName;
|
||||
long lMagic;
|
||||
|
||||
/* I/O control */
|
||||
mkChannel *pSock;
|
||||
FILE *pFiles[MAXLOGFILES];
|
||||
int iMacro;
|
||||
int iTelnet;
|
||||
int iOutput;
|
||||
int iFiles;
|
||||
writeFunc write;
|
||||
mkChannel *pDataSock;
|
||||
char *pDataComp;
|
||||
int iDataPort;
|
||||
|
||||
/* execution context */
|
||||
int eInterrupt;
|
||||
int iUserRights;
|
||||
int inUse;
|
||||
int iGrab;
|
||||
SicsInterp *pSics;
|
||||
|
||||
/* flag for parameter change */
|
||||
int parameterChange;
|
||||
|
||||
/* a FIFO */
|
||||
pCosta pStack;
|
||||
|
||||
/* callback registry */
|
||||
int iList;
|
||||
|
||||
/* Tasking Stuff */
|
||||
int iEnd;
|
||||
/* for keeping track of the login
|
||||
process on a non telnet connection.
|
||||
Should only be used in SCTaskFunction
|
||||
*/
|
||||
int iLogin;
|
||||
time_t conStart;
|
||||
}SConnection;
|
||||
|
||||
#include "nserver.h"
|
||||
|
||||
/*------------------------------ live & death ----------------------------*/
|
||||
SConnection *SCreateConnection(SicsInterp *pSics, mkChannel *pSock,
|
||||
int iUserRights);
|
||||
SConnection *SCCreateDummyConnection(SicsInterp *pSics);
|
||||
void SCDeleteConnection(void *pVictim);
|
||||
|
||||
/*------------------------------- tasking --------------------------------*/
|
||||
int SCTaskFunction(void *pCon);
|
||||
void SCSignalFunction(void *pCon, int iSignal, void *pSigData);
|
||||
/* ***************************** I/O ************************************** */
|
||||
int SCAddLogFile(SConnection *self, char *name);
|
||||
int SCDelLogFile(SConnection *pCon, int iFile);
|
||||
void SCSetOutputClass(SConnection *self, int iClass);
|
||||
int SCWrite(SConnection *self, char *pBuffer, int iOut);
|
||||
int SCRead(SConnection *self, char *pBuffer, int iBufLen);
|
||||
int SCPrompt(SConnection *pCon, char *pPrompt, char *pResult, int iLen);
|
||||
int SCSendOK(SConnection *self);
|
||||
int SCnoSock(SConnection *pCon);
|
||||
int SCWriteUUencoded(SConnection *pCon, char *pName, void *iData, int iLen);
|
||||
int SCWriteZipped(SConnection *pCon, char *pName, void *pData, int iDataLen);
|
||||
writeFunc SCGetWriteFunc(SConnection *pCon);
|
||||
void SCSetWriteFunc(SConnection *pCon, writeFunc x);
|
||||
int SCOnlySockWrite(SConnection *self, char *buffer, int iOut);
|
||||
int SCNotWrite(SConnection *self, char *buffer, int iOut);
|
||||
/************************* CallBack *********************************** */
|
||||
int SCRegister(SConnection *pCon, SicsInterp *pSics,
|
||||
void *pInter, long lID);
|
||||
int SCUnregister(SConnection *pCon, void *pInter);
|
||||
/******************************* Interrupt *********************************/
|
||||
void SCSetInterrupt(SConnection *self, int eCode);
|
||||
int SCGetInterrupt(SConnection *self);
|
||||
/****************************** Macro ***************************************/
|
||||
int SCinMacro(SConnection *pCon);
|
||||
int SCsetMacro(SConnection *pCon, int iMode);
|
||||
/************************** parameters changed ? **************************/
|
||||
void SCparChange(SConnection *pCon);
|
||||
/* *************************** Info *************************************** */
|
||||
int SCGetRights(SConnection *self);
|
||||
int SCSetRights(SConnection *pCon, int iNew);
|
||||
int SCMatchRights(SConnection *pCon, int iCode);
|
||||
int SCGetOutClass(SConnection *self);
|
||||
int SCGetGrab(SConnection *pCon);
|
||||
/********************* simulation mode ************************************/
|
||||
void SCSetSimMode(SConnection *pCon, int value);
|
||||
int SCinSimMode(SConnection *pCon);
|
||||
/* **************************** Invocation ******************************** */
|
||||
int SCInvoke(SConnection *self,SicsInterp *pInter,char *pCommand);
|
||||
|
||||
/*************************** User Command **********************************/
|
||||
int ConfigCon(SConnection *pCon, SicsInterp *pSics, void *pData,
|
||||
int argc, char *argv[]);
|
||||
int ConSicsAction(SConnection *pCon, SicsInterp *pSics, void *pData,
|
||||
int argc, char *argv[]);
|
||||
|
||||
|
||||
|
||||
#endif
|
31
copyright.h
Normal file
31
copyright.h
Normal file
@ -0,0 +1,31 @@
|
||||
/*----------------------------------------------------------------------------
|
||||
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.
|
||||
|
||||
Author: Mark Koennecke
|
||||
Laboratory for Neutron Scattering
|
||||
Paul Scherrer Institut
|
||||
CH-5232 Villigen-PSI
|
||||
Switzerland
|
||||
Mark.Koennecke@psi.ch
|
||||
-----------------------------------------------------------------------------*/
|
198
costa.c
Normal file
198
costa.c
Normal file
@ -0,0 +1,198 @@
|
||||
/*----------------------------------------------------------------------------
|
||||
C O S T A
|
||||
|
||||
Implementation of a command stack for use with connection objects in
|
||||
SICS
|
||||
|
||||
Mark Koennecke, Septemeber 1997
|
||||
|
||||
Copyright:
|
||||
|
||||
Labor fuer Neutronenstreuung
|
||||
Paul Scherrer Institut
|
||||
CH-5423 Villigen-PSI
|
||||
|
||||
|
||||
The authors hereby grant permission to use, copy, modify, distribute,
|
||||
and license this software and its documentation for any purpose, provided
|
||||
that existing copyright notices are retained in all copies and that this
|
||||
notice is included verbatim in any distributions. No written agreement,
|
||||
license, or royalty fee is required for any of the authorized uses.
|
||||
Modifications to this software may be copyrighted by their authors
|
||||
and need not follow the licensing terms described here, provided that
|
||||
the new terms are clearly indicated on the first page of each file where
|
||||
they apply.
|
||||
|
||||
IN NO EVENT SHALL THE AUTHORS OR DISTRIBUTORS BE LIABLE TO ANY PARTY
|
||||
FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
|
||||
ARISING OUT OF THE USE OF THIS SOFTWARE, ITS DOCUMENTATION, OR ANY
|
||||
DERIVATIVES THEREOF, EVEN IF THE AUTHORS HAVE BEEN ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
THE AUTHORS AND DISTRIBUTORS SPECIFICALLY DISCLAIM ANY WARRANTIES,
|
||||
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT. THIS SOFTWARE
|
||||
IS PROVIDED ON AN "AS IS" BASIS, AND THE AUTHORS AND DISTRIBUTORS HAVE
|
||||
NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR
|
||||
MODIFICATIONS.
|
||||
----------------------------------------------------------------------------*/
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <limits.h>
|
||||
#include <assert.h>
|
||||
#include "fortify.h"
|
||||
#include "lld.h"
|
||||
#include "costa.h"
|
||||
#include "costa.i"
|
||||
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
pCosta CreateCommandStack(void)
|
||||
{
|
||||
pCosta pNew = NULL;
|
||||
|
||||
pNew = (pCosta)malloc(sizeof(Costa));
|
||||
if(!pNew)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
memset(pNew,0,sizeof(Costa));
|
||||
pNew->iList = LLDcreate(sizeof(char *));
|
||||
if(pNew->iList < 0)
|
||||
{
|
||||
free(pNew);
|
||||
return NULL;
|
||||
}
|
||||
pNew->iCount = 0;
|
||||
pNew->iMaxSize = INT_MAX;
|
||||
return pNew;
|
||||
}
|
||||
/*-------------------------------------------------------------------------*/
|
||||
void DeleteCommandStack(pCosta self)
|
||||
{
|
||||
int iRet;
|
||||
char *pPtr;
|
||||
|
||||
assert(self);
|
||||
|
||||
iRet = LLDnodePtr2First(self->iList);
|
||||
while(iRet != 0)
|
||||
{
|
||||
pPtr = NULL;
|
||||
LLDnodeDataTo(self->iList,&pPtr);
|
||||
if(pPtr)
|
||||
{
|
||||
free(pPtr);
|
||||
}
|
||||
iRet = LLDnodePtr2Next(self->iList);
|
||||
}
|
||||
LLDdelete(self->iList);
|
||||
free(self);
|
||||
}
|
||||
/*--------------------------------------------------------------------------*/
|
||||
int SetCommandStackMaxSize(pCosta self, int iNew)
|
||||
{
|
||||
assert(self);
|
||||
|
||||
if(iNew > 0)
|
||||
{
|
||||
self->iMaxSize = iNew;
|
||||
return 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
/*--------------------------------------------------------------------------*/
|
||||
int CostaTop(pCosta self, char *pCommand)
|
||||
{
|
||||
char *pPtr = NULL;
|
||||
int iRet, iRes = 1;
|
||||
|
||||
assert(self);
|
||||
|
||||
/* check for lock */
|
||||
if(self->iLock)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
/* check Size */
|
||||
if(self->iCount >= self->iMaxSize)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* do not want 0 commands */
|
||||
if(strlen(pCommand) < 1)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
pPtr = strdup(pCommand);
|
||||
iRet = LLDnodeAppendFrom(self->iList,&pPtr);
|
||||
if(iRet < 0)
|
||||
{
|
||||
iRes = 0;
|
||||
}
|
||||
self->iCount++;
|
||||
return iRes;
|
||||
}
|
||||
/*--------------------------------------------------------------------------*/
|
||||
int CostaBottom(pCosta self, char *pCommand)
|
||||
{
|
||||
char *pPtr = NULL;
|
||||
int iRet, iRes = 1;
|
||||
assert(self);
|
||||
|
||||
/* check for lock */
|
||||
if(self->iLock)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* do not want 0 commands */
|
||||
if(strlen(pCommand) < 1)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
pPtr = strdup(pCommand);
|
||||
iRet = LLDnodePrependFrom(self->iList,&pPtr);
|
||||
if(iRet < 0)
|
||||
{
|
||||
iRes = 0;
|
||||
}
|
||||
self->iCount++;
|
||||
return iRes;
|
||||
}
|
||||
/*--------------------------------------------------------------------------*/
|
||||
int CostaPop(pCosta self, char **pBuf)
|
||||
{
|
||||
char *pPtr = NULL;
|
||||
int iRet;
|
||||
|
||||
assert(self);
|
||||
iRet = LLDnodePtr2First(self->iList);
|
||||
if(iRet != 0)
|
||||
{
|
||||
LLDnodeDataTo(self->iList,&pPtr);
|
||||
*pBuf = pPtr;
|
||||
LLDnodeDelete(self->iList);
|
||||
self->iCount--;
|
||||
return 1;
|
||||
}
|
||||
*pBuf = NULL;
|
||||
return 0;
|
||||
}
|
||||
/*--------------------------------------------------------------------------*/
|
||||
void CostaLock(pCosta self)
|
||||
{
|
||||
self->iLock = 1;
|
||||
}
|
||||
/*--------------------------------------------------------------------------*/
|
||||
void CostaUnlock(pCosta self)
|
||||
{
|
||||
self->iLock = 0;
|
||||
}
|
||||
|
29
costa.h
Normal file
29
costa.h
Normal file
@ -0,0 +1,29 @@
|
||||
|
||||
/*-------------------------------------------------------------------------
|
||||
C O S T A
|
||||
|
||||
A command stack implementation for SICS. To be used by each connection.
|
||||
|
||||
Mark Koennecke, September 1997
|
||||
|
||||
copyright: see implementation file.
|
||||
|
||||
----------------------------------------------------------------------------*/
|
||||
#ifndef SICSCOSTA
|
||||
#define SICSCOSTA
|
||||
|
||||
typedef struct __costa *pCosta;
|
||||
|
||||
/*----------------------------- live & death ----------------------------*/
|
||||
pCosta CreateCommandStack(void);
|
||||
void DeleteCommandStack(pCosta self);
|
||||
int SetCommandStackMaxSize(pCosta self, int iNewSize);
|
||||
/*----------------------------------------------------------------------*/
|
||||
int CostaTop(pCosta self, char *pCommand);
|
||||
int CostaBottom(pCosta self, char *pCommand);
|
||||
int CostaPop(pCosta self,char **pPtr);
|
||||
/*----------------------------------------------------------------------*/
|
||||
void CostaLock(pCosta self);
|
||||
void CostaUnlock(pCosta self);
|
||||
|
||||
#endif
|
15
costa.i
Normal file
15
costa.i
Normal file
@ -0,0 +1,15 @@
|
||||
|
||||
/*---------------------------------------------------------------------------
|
||||
C O S T A
|
||||
Internal data structures for the command stack.
|
||||
--------------------------------------------------------------------------*/
|
||||
|
||||
|
||||
/*------------------------------------------------------------------------*/
|
||||
typedef struct __costa {
|
||||
int iLock;
|
||||
int iList;
|
||||
int iMaxSize;
|
||||
int iCount;
|
||||
} Costa;
|
||||
|
108
costa.tex
Normal file
108
costa.tex
Normal file
@ -0,0 +1,108 @@
|
||||
\subsection{The Command Stack}
|
||||
This is a helper class to the connection class.
|
||||
Each connection to a client has a command stack associated with it. The
|
||||
command stack is a stack of command strings as generated by the SICS
|
||||
clients. Commands are added to the top of the command queue by the network
|
||||
reader. Each time the task associated with a connection runs one command
|
||||
is popped from the command stack and executed. During execution the command
|
||||
stack must be locked in order to prevent commands being accepted by tasks
|
||||
busy waiting for some other process to finish.
|
||||
|
||||
Correspondingly, the interface to the command stack looks like this:
|
||||
|
||||
\begin{flushleft} \small
|
||||
\begin{minipage}{\linewidth} \label{scrap1}
|
||||
$\langle$costaint {\footnotesize ?}$\rangle\equiv$
|
||||
\vspace{-1ex}
|
||||
\begin{list}{}{} \item
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@ typedef struct __costa *pCosta;@\\
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@/*----------------------------- live & death ----------------------------*/@\\
|
||||
\mbox{}\verb@ pCosta CreateCommandStack(void);@\\
|
||||
\mbox{}\verb@ void DeleteCommandStack(pCosta self);@\\
|
||||
\mbox{}\verb@ int SetCommandStackMaxSize(pCosta self, int iNewSize);@\\
|
||||
\mbox{}\verb@/*----------------------------------------------------------------------*/@\\
|
||||
\mbox{}\verb@ int CostaTop(pCosta self, char *pCommand);@\\
|
||||
\mbox{}\verb@ int CostaBottom(pCosta self, char *pCommand);@\\
|
||||
\mbox{}\verb@ int CostaPop(pCosta self,char **pPtr);@\\
|
||||
\mbox{}\verb@/*----------------------------------------------------------------------*/@\\
|
||||
\mbox{}\verb@ void CostaLock(pCosta self);@\\
|
||||
\mbox{}\verb@ void CostaUnlock(pCosta self);@\\
|
||||
\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}
|
||||
Internally, two data structure need to be defined, the first for the
|
||||
list implementing the command stack, the second for the command stack
|
||||
itself.
|
||||
|
||||
\begin{flushleft} \small
|
||||
\begin{minipage}{\linewidth} \label{scrap2}
|
||||
$\langle$costadat {\footnotesize ?}$\rangle\equiv$
|
||||
\vspace{-1ex}
|
||||
\begin{list}{}{} \item
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@/*------------------------------------------------------------------------*/@\\
|
||||
\mbox{}\verb@ typedef struct __costa {@\\
|
||||
\mbox{}\verb@ int iLock;@\\
|
||||
\mbox{}\verb@ int iList;@\\
|
||||
\mbox{}\verb@ int iMaxSize;@\\
|
||||
\mbox{}\verb@ int iCount;@\\
|
||||
\mbox{}\verb@ } Costa;@\\
|
||||
\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}
|
||||
\begin{flushleft} \small
|
||||
\begin{minipage}{\linewidth} \label{scrap3}
|
||||
\verb@"costa.h"@ {\footnotesize ? }$\equiv$
|
||||
\vspace{-1ex}
|
||||
\begin{list}{}{} \item
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@/*-------------------------------------------------------------------------@\\
|
||||
\mbox{}\verb@ C O S T A@\\
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@ A command stack implementation for SICS. To be used by each connection.@\\
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@ Mark Koennecke, September 1997@\\
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@ copyright: see implementation file.@\\
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@----------------------------------------------------------------------------*/@\\
|
||||
\mbox{}\verb@#ifndef SICSCOSTA@\\
|
||||
\mbox{}\verb@#define SICSCOSTA@\\
|
||||
\mbox{}\verb@@$\langle$costaint {\footnotesize ?}$\rangle$\verb@@\\
|
||||
\mbox{}\verb@#endif@\\
|
||||
\mbox{}\verb@@$\diamond$
|
||||
\end{list}
|
||||
\vspace{-2ex}
|
||||
\end{minipage}\\[4ex]
|
||||
\end{flushleft}
|
||||
\begin{flushleft} \small
|
||||
\begin{minipage}{\linewidth} \label{scrap4}
|
||||
\verb@"costa.i"@ {\footnotesize ? }$\equiv$
|
||||
\vspace{-1ex}
|
||||
\begin{list}{}{} \item
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@/*---------------------------------------------------------------------------@\\
|
||||
\mbox{}\verb@ C O S T A@\\
|
||||
\mbox{}\verb@ Internal data structures for the command stack.@\\
|
||||
\mbox{}\verb@--------------------------------------------------------------------------*/@\\
|
||||
\mbox{}\verb@@$\langle$costadat {\footnotesize ?}$\rangle$\verb@@\\
|
||||
\mbox{}\verb@@$\diamond$
|
||||
\end{list}
|
||||
\vspace{-2ex}
|
||||
\end{minipage}\\[4ex]
|
||||
\end{flushleft}
|
68
costa.w
Normal file
68
costa.w
Normal file
@ -0,0 +1,68 @@
|
||||
\subsection{The Command Stack}
|
||||
This is a helper class to the connection class.
|
||||
Each connection to a client has a command stack associated with it. The
|
||||
command stack is a stack of command strings as generated by the SICS
|
||||
clients. Commands are added to the top of the command queue by the network
|
||||
reader. Each time the task associated with a connection runs one command
|
||||
is popped from the command stack and executed. During execution the command
|
||||
stack must be locked in order to prevent commands being accepted by tasks
|
||||
busy waiting for some other process to finish.
|
||||
|
||||
Correspondingly, the interface to the command stack looks like this:
|
||||
|
||||
@d costaint @{
|
||||
typedef struct __costa *pCosta;
|
||||
|
||||
/*----------------------------- live & death ----------------------------*/
|
||||
pCosta CreateCommandStack(void);
|
||||
void DeleteCommandStack(pCosta self);
|
||||
int SetCommandStackMaxSize(pCosta self, int iNewSize);
|
||||
/*----------------------------------------------------------------------*/
|
||||
int CostaTop(pCosta self, char *pCommand);
|
||||
int CostaBottom(pCosta self, char *pCommand);
|
||||
int CostaPop(pCosta self,char **pPtr);
|
||||
/*----------------------------------------------------------------------*/
|
||||
void CostaLock(pCosta self);
|
||||
void CostaUnlock(pCosta self);
|
||||
@}
|
||||
|
||||
Internally, two data structure need to be defined, the first for the
|
||||
list implementing the command stack, the second for the command stack
|
||||
itself.
|
||||
|
||||
@d costadat @{
|
||||
|
||||
/*------------------------------------------------------------------------*/
|
||||
typedef struct __costa {
|
||||
int iLock;
|
||||
int iList;
|
||||
int iMaxSize;
|
||||
int iCount;
|
||||
} Costa;
|
||||
@}
|
||||
|
||||
|
||||
@o costa.h @{
|
||||
/*-------------------------------------------------------------------------
|
||||
C O S T A
|
||||
|
||||
A command stack implementation for SICS. To be used by each connection.
|
||||
|
||||
Mark Koennecke, September 1997
|
||||
|
||||
copyright: see implementation file.
|
||||
|
||||
----------------------------------------------------------------------------*/
|
||||
#ifndef SICSCOSTA
|
||||
#define SICSCOSTA
|
||||
@<costaint@>
|
||||
#endif
|
||||
@}
|
||||
|
||||
@o costa.i @{
|
||||
/*---------------------------------------------------------------------------
|
||||
C O S T A
|
||||
Internal data structures for the command stack.
|
||||
--------------------------------------------------------------------------*/
|
||||
@<costadat@>
|
||||
@}
|
37
cotop.tcl
Normal file
37
cotop.tcl
Normal file
@ -0,0 +1,37 @@
|
||||
#--------------------------------------------------------------------------
|
||||
# A MAD lookalike co command for TOPSI
|
||||
# All arguments are optional. The current values will be used if not
|
||||
# specified
|
||||
# Dr. Mark Koennecke, November 1999
|
||||
#--------------------------------------------------------------------------
|
||||
proc SplitReply { text } {
|
||||
set l [split $text =]
|
||||
return [lindex $l 1]
|
||||
}
|
||||
#--------------------------------------------------------------------------
|
||||
proc co { {mode NULL } { preset NULL } } {
|
||||
starttime [sicstime]
|
||||
#----- deal with mode
|
||||
set mode2 [string toupper $mode]
|
||||
set mode3 [string trim $mode2]
|
||||
set mc [string index $mode2 0]
|
||||
if { [string compare $mc T] == 0 } {
|
||||
counter setMode Timer
|
||||
} elseif { [string compare $mc M] == 0 } {
|
||||
counter setMode Monitor
|
||||
}
|
||||
#------ deal with preset
|
||||
if { [string compare $preset NULL] != 0 } {
|
||||
set pre $preset
|
||||
} else {
|
||||
set pre [SplitReply [counter getpreset]]
|
||||
}
|
||||
#------ count
|
||||
set ret [catch {counter count $pre} msg]
|
||||
if { $ret != 0 } {
|
||||
error [format "Counting ended with error: %s" $msg]
|
||||
} else {
|
||||
set cts [SplitReply [counter getcounts]]
|
||||
}
|
||||
return $cts
|
||||
}
|
752
countdriv.c
Normal file
752
countdriv.c
Normal file
@ -0,0 +1,752 @@
|
||||
/*------------------------------------------------------------------------
|
||||
G E N C O U N T
|
||||
|
||||
Some general stuff for handling a CounterDriver.
|
||||
|
||||
|
||||
Mark Koennecke, January 1997
|
||||
|
||||
Copyright:
|
||||
|
||||
Labor fuer Neutronenstreuung
|
||||
Paul Scherrer Institut
|
||||
CH-5423 Villigen-PSI
|
||||
|
||||
|
||||
The authors hereby grant permission to use, copy, modify, distribute,
|
||||
and license this software and its documentation for any purpose, provided
|
||||
that existing copyright notices are retained in all copies and that this
|
||||
notice is included verbatim in any distributions. No written agreement,
|
||||
license, or royalty fee is required for any of the authorized uses.
|
||||
Modifications to this software may be copyrighted by their authors
|
||||
and need not follow the licensing terms described here, provided that
|
||||
the new terms are clearly indicated on the first page of each file where
|
||||
they apply.
|
||||
|
||||
IN NO EVENT SHALL THE AUTHORS OR DISTRIBUTORS BE LIABLE TO ANY PARTY
|
||||
FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
|
||||
ARISING OUT OF THE USE OF THIS SOFTWARE, ITS DOCUMENTATION, OR ANY
|
||||
DERIVATIVES THEREOF, EVEN IF THE AUTHORS HAVE BEEN ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
THE AUTHORS AND DISTRIBUTORS SPECIFICALLY DISCLAIM ANY WARRANTIES,
|
||||
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT. THIS SOFTWARE
|
||||
IS PROVIDED ON AN "AS IS" BASIS, AND THE AUTHORS AND DISTRIBUTORS HAVE
|
||||
NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR
|
||||
MODIFICATIONS.
|
||||
----------------------------------------------------------------------------*/
|
||||
#include <stdlib.h>
|
||||
#include <assert.h>
|
||||
#include <math.h>
|
||||
#include "fortify.h"
|
||||
#include <string.h>
|
||||
#include "sics.h"
|
||||
#include "countdriv.h"
|
||||
#include "hardsup/sinq_prototypes.h"
|
||||
#include "hardsup/el737_def.h"
|
||||
#include "hardsup/el737fix.h"
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
pCounterDriver CreateCounterDriver(char *name, char *type)
|
||||
{
|
||||
pCounterDriver pRes = NULL;
|
||||
|
||||
pRes = (pCounterDriver)malloc(sizeof(CounterDriver));
|
||||
if(!pRes)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
memset(pRes,0,sizeof(CounterDriver));
|
||||
|
||||
pRes->name = strdup(name);
|
||||
pRes->type = strdup(type);
|
||||
pRes->eMode = eTimer;
|
||||
pRes->fPreset = 1000.;
|
||||
pRes->fTime = 0.;
|
||||
pRes->iNoOfMonitors = 0;
|
||||
pRes->iPause = 0;
|
||||
pRes->Start = NULL;
|
||||
pRes->GetStatus = NULL;
|
||||
pRes->ReadValues = NULL;
|
||||
pRes->GetError = NULL;
|
||||
pRes->TryAndFixIt = NULL;
|
||||
pRes->Halt = NULL;
|
||||
pRes->pData = NULL;
|
||||
pRes->Pause = NULL;
|
||||
pRes->Continue = NULL;
|
||||
|
||||
return pRes;
|
||||
}
|
||||
/*-------------------------------------------------------------------------*/
|
||||
void DeleteCounterDriver(pCounterDriver self)
|
||||
{
|
||||
assert(self);
|
||||
if(self->name)
|
||||
{
|
||||
free(self->name);
|
||||
}
|
||||
if(self->type)
|
||||
{
|
||||
free(self->type);
|
||||
}
|
||||
if(self->pData)
|
||||
{
|
||||
free(self->pData);
|
||||
}
|
||||
free(self);
|
||||
}
|
||||
/*----------------------------- EL737 ------------------------------------*/
|
||||
typedef struct {
|
||||
char *host;
|
||||
int iPort;
|
||||
int iChannel;
|
||||
void *pData;
|
||||
int finishCount;
|
||||
} EL737st;
|
||||
/*------------------------------------------------------------------------*/
|
||||
static int EL737GetStatus(struct __COUNTER *self, float *fControl)
|
||||
{
|
||||
int iRet;
|
||||
int iC1, iC2, iC3,iC4,iRS;
|
||||
float fTime;
|
||||
EL737st *pEL737;
|
||||
|
||||
assert(self);
|
||||
pEL737 = (EL737st *)self->pData;
|
||||
assert(pEL737);
|
||||
iRet = EL737_GetStatus(&pEL737->pData,&iC1,&iC2,&iC3,&iC4,&fTime,&iRS);
|
||||
if(self->eMode == eTimer)
|
||||
{
|
||||
*fControl = fTime;
|
||||
}
|
||||
else
|
||||
{
|
||||
*fControl = iC1;
|
||||
}
|
||||
/* store time */
|
||||
self->fTime = fTime;
|
||||
|
||||
if(iRet != 1)
|
||||
{
|
||||
return HWFault;
|
||||
}
|
||||
self->lCounts[0] = iC2;
|
||||
self->lCounts[1] = iC1;
|
||||
self->lCounts[2] = iC3;
|
||||
self->lCounts[3] = iC4;
|
||||
|
||||
/* get extra counters for 8-fold counter boxes */
|
||||
iRet = EL737_GetStatusExtra(&pEL737->pData,&iC1,&iC2,&iC3,&iC4);
|
||||
self->lCounts[4] = iC1;
|
||||
self->lCounts[5] = iC2;
|
||||
self->lCounts[6] = iC3;
|
||||
self->lCounts[7] = iC4;
|
||||
if(iRS == 0)
|
||||
{
|
||||
pEL737->finishCount++;
|
||||
if(pEL737->finishCount >= 2)
|
||||
{
|
||||
return HWIdle;
|
||||
}
|
||||
else
|
||||
{
|
||||
return HWBusy;
|
||||
}
|
||||
}
|
||||
else if((iRS == 1) || (iRS == 2))
|
||||
{
|
||||
pEL737->finishCount = 0;
|
||||
return HWBusy;
|
||||
}
|
||||
else if( (iRS == 5) || (iRS == 6))
|
||||
{
|
||||
pEL737->finishCount = 0;
|
||||
return HWNoBeam;
|
||||
}
|
||||
else
|
||||
{
|
||||
pEL737->finishCount = 0;
|
||||
return HWPause;
|
||||
}
|
||||
}
|
||||
#ifdef NONINTF
|
||||
extern float nintf(float f);
|
||||
#endif
|
||||
/*-------------------------------------------------------------------------*/
|
||||
static int EL737Start(struct __COUNTER *self)
|
||||
{
|
||||
int iRet, iRS;
|
||||
EL737st *pEL737;
|
||||
|
||||
assert(self);
|
||||
pEL737 = (EL737st *)self->pData;
|
||||
assert(pEL737);
|
||||
|
||||
|
||||
self->fTime = 0.;
|
||||
|
||||
if(self->eMode == ePreset)
|
||||
{
|
||||
iRet = EL737_StartCnt(&pEL737->pData,(int)nintf(self->fPreset),&iRS);
|
||||
if(iRet == 1)
|
||||
{
|
||||
pEL737->finishCount = 0;
|
||||
return OKOK;
|
||||
}
|
||||
else
|
||||
{
|
||||
return HWFault;
|
||||
}
|
||||
}
|
||||
else if(self->eMode == eTimer)
|
||||
{
|
||||
iRet = EL737_StartTime(&pEL737->pData,self->fPreset,&iRS);
|
||||
if(iRet == 1)
|
||||
{
|
||||
pEL737->finishCount = 0;
|
||||
return OKOK;
|
||||
}
|
||||
else
|
||||
{
|
||||
return HWFault;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
/*-------------------------------------------------------------------------*/
|
||||
static int EL737Pause(struct __COUNTER *self)
|
||||
{
|
||||
int iRet, iRS;
|
||||
EL737st *pEL737;
|
||||
|
||||
assert(self);
|
||||
pEL737 = (EL737st *)self->pData;
|
||||
assert(pEL737);
|
||||
|
||||
|
||||
iRet = EL737_Pause(&pEL737->pData,&iRS);
|
||||
if(iRet == 1)
|
||||
{
|
||||
return OKOK;
|
||||
}
|
||||
else
|
||||
{
|
||||
return HWFault;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
/*-------------------------------------------------------------------------*/
|
||||
static int EL737Continue(struct __COUNTER *self)
|
||||
{
|
||||
int iRet, iRS;
|
||||
EL737st *pEL737;
|
||||
|
||||
assert(self);
|
||||
pEL737 = (EL737st *)self->pData;
|
||||
assert(pEL737);
|
||||
|
||||
|
||||
iRet = EL737_Continue(&pEL737->pData,&iRS);
|
||||
if(iRet == 1)
|
||||
{
|
||||
return OKOK;
|
||||
}
|
||||
else
|
||||
{
|
||||
return HWFault;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
/*--------------------------------------------------------------------------*/
|
||||
static int EL737Halt(struct __COUNTER *self)
|
||||
{
|
||||
int iRet, iC1, iC2, iC3, iC4,iRS;
|
||||
float fPreset;
|
||||
EL737st *pEL737;
|
||||
|
||||
assert(self);
|
||||
pEL737 = (EL737st *)self->pData;
|
||||
assert(pEL737);
|
||||
|
||||
|
||||
|
||||
iRet = EL737_Stop(&pEL737->pData,&iC1, &iC2,&iC3,&iC4,&fPreset,&iRS);
|
||||
if(iRet == 1)
|
||||
{
|
||||
self->lCounts[0] = iC2;
|
||||
self->lCounts[1] = iC1;
|
||||
self->lCounts[2] = iC3;
|
||||
self->lCounts[3] = iC4;
|
||||
return OKOK;
|
||||
}
|
||||
return HWFault;
|
||||
}
|
||||
/*--------------------------------------------------------------------------*/
|
||||
static int EL737ReadValues(struct __COUNTER *self)
|
||||
{
|
||||
int iRet;
|
||||
int iC1, iC2, iC3,iC4,iRS;
|
||||
float fTime;
|
||||
EL737st *pEL737;
|
||||
|
||||
assert(self);
|
||||
pEL737 = (EL737st *)self->pData;
|
||||
assert(pEL737);
|
||||
|
||||
|
||||
iRet = EL737_GetStatus(&pEL737->pData,&iC1,&iC2,&iC3,&iC4,&fTime,&iRS);
|
||||
if(iRet != 1)
|
||||
{
|
||||
return HWFault;
|
||||
}
|
||||
self->fTime = fTime;
|
||||
|
||||
self->lCounts[0] = iC2;
|
||||
self->lCounts[1] = iC1;
|
||||
self->lCounts[2] = iC3;
|
||||
self->lCounts[3] = iC4;
|
||||
/* get extra counters for 8-fold counter boxes */
|
||||
iRet = EL737_GetStatusExtra(&pEL737->pData,&iC1,&iC2,&iC3,&iC4);
|
||||
self->lCounts[4] = iC1;
|
||||
self->lCounts[5] = iC2;
|
||||
self->lCounts[6] = iC3;
|
||||
self->lCounts[7] = iC4;
|
||||
|
||||
return OKOK;
|
||||
}
|
||||
/*---------------------------------------------------------------------------
|
||||
|
||||
EL737Error2Text converts between an EL734 error code to text
|
||||
-----------------------------------------------------------------------------*/
|
||||
static void EL737Error2Text(char *pBuffer, int iErr)
|
||||
{
|
||||
switch(iErr)
|
||||
{
|
||||
case EL737__BAD_ADR:
|
||||
strcpy(pBuffer,"EL737__BAD_ADR");
|
||||
break;
|
||||
case EL737__BAD_OVFL:
|
||||
strcpy(pBuffer,"EL737__BAD_OVFL");
|
||||
break;
|
||||
case EL737__BAD_BSY:
|
||||
strcpy(pBuffer,"EL737__BAD_BSY");
|
||||
break;
|
||||
case EL737__BAD_SNTX:
|
||||
strcpy(pBuffer,"EL737__BAD_SNTX");
|
||||
break;
|
||||
case EL737__BAD_CONNECT:
|
||||
strcpy(pBuffer,"EL737__BAD_CONNECT");
|
||||
break;
|
||||
case EL737__BAD_FLUSH:
|
||||
strcpy(pBuffer,"EL737__BAD_FLUSH");
|
||||
break;
|
||||
case EL737__BAD_DEV:
|
||||
strcpy(pBuffer,"EL734__BAD_DEV");
|
||||
break;
|
||||
case EL737__BAD_ID:
|
||||
strcpy(pBuffer,"EL737__BAD_ID");
|
||||
break;
|
||||
case EL737__BAD_ILLG:
|
||||
strcpy(pBuffer,"EL737__BAD_ILLG");
|
||||
break;
|
||||
case EL737__BAD_LOC:
|
||||
strcpy(pBuffer,"EL737__BAD_LOC");
|
||||
break;
|
||||
case EL737__BAD_MALLOC:
|
||||
strcpy(pBuffer,"EL737__BAD_MALLOC");
|
||||
break;
|
||||
case EL737__BAD_NOT_BCD:
|
||||
strcpy(pBuffer,"EL737__BAD_NOT_BCD");
|
||||
break;
|
||||
case EL737__BAD_OFL:
|
||||
strcpy(pBuffer,"EL737__BAD_OFL");
|
||||
break;
|
||||
case EL737__BAD_PAR:
|
||||
strcpy(pBuffer,"EL737__BAD_PAR");
|
||||
break;
|
||||
|
||||
case EL737__BAD_RECV:
|
||||
strcpy(pBuffer,"EL737__BAD_RECV");
|
||||
break;
|
||||
case EL737__BAD_RECV_NET:
|
||||
strcpy(pBuffer,"EL737__BAD_RECV_NET");
|
||||
break;
|
||||
case EL737__BAD_RECV_PIPE:
|
||||
strcpy(pBuffer,"EL737__BAD_RECV_PIPE");
|
||||
break;
|
||||
case EL737__BAD_RECV_UNKN:
|
||||
strcpy(pBuffer,"EL737__BAD_RECV_UNKN");
|
||||
break;
|
||||
case EL737__BAD_RECVLEN:
|
||||
strcpy(pBuffer,"EL737__BAD_RECVLEN");
|
||||
break;
|
||||
case EL737__BAD_RECV1:
|
||||
strcpy(pBuffer,"EL737__BAD_RECV1");
|
||||
break;
|
||||
case EL737__BAD_RECV1_NET:
|
||||
strcpy(pBuffer,"EL737__BAD_RECV1_NET");
|
||||
break;
|
||||
case EL737__BAD_RECV1_PIPE:
|
||||
strcpy(pBuffer,"EL737__BAD_RECV1_PIPE");
|
||||
break;
|
||||
case EL737__BAD_RNG:
|
||||
strcpy(pBuffer,"EL737__BAD_RNG");
|
||||
break;
|
||||
case EL737__BAD_SEND:
|
||||
strcpy(pBuffer,"EL737__BAD_SEND");
|
||||
break;
|
||||
case EL737__BAD_SEND_PIPE:
|
||||
strcpy(pBuffer,"EL737__BAD_SEND_PIPE");
|
||||
break;
|
||||
case EL737__BAD_SEND_NET:
|
||||
strcpy(pBuffer,"EL737__BAD_SEND_NET");
|
||||
break;
|
||||
case EL737__BAD_SEND_UNKN:
|
||||
strcpy(pBuffer,"EL737__BAD_SEND_UNKN");
|
||||
break;
|
||||
case EL737__BAD_SENDLEN:
|
||||
strcpy(pBuffer,"EL737__BAD_SENDLEN");
|
||||
break;
|
||||
case EL737__BAD_SOCKET:
|
||||
strcpy(pBuffer,"EL737__BAD_SOCKET");
|
||||
break;
|
||||
case EL737__BAD_TMO:
|
||||
strcpy(pBuffer,"EL737__BAD_TMO");
|
||||
break;
|
||||
case EL737__FORCED_CLOSED:
|
||||
strcpy(pBuffer,"EL737__FORCED_CLOSED");
|
||||
break;
|
||||
case EL737__BAD_ASYNSRV:
|
||||
strcpy(pBuffer,"EL737__BAD_ASYNSRV");
|
||||
break;
|
||||
default:
|
||||
sprintf(pBuffer,"Unknown EL737 error %d", iErr);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/*--------------------------------------------------------------------------*/
|
||||
static int EL737GetError(struct __COUNTER *self, int *iCode,
|
||||
char *error, int iErrLen)
|
||||
{
|
||||
char *pErr = NULL;
|
||||
int iC1, iC2, iC3;
|
||||
char pBueffel[256];
|
||||
|
||||
if(self->iErrorCode == UNKNOWNPAR)
|
||||
{
|
||||
strncpy(error,"unknown internal parameter code",iErrLen);
|
||||
*iCode = self->iErrorCode;
|
||||
self->iErrorCode = 0;
|
||||
return 1;
|
||||
}
|
||||
else if(self->iErrorCode == BADCOUNTER)
|
||||
{
|
||||
strncpy(error,"monitor cannot be selected",iErrLen);
|
||||
*iCode = self->iErrorCode;
|
||||
self->iErrorCode = 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
EL737_ErrInfo(&pErr,&iC1,&iC2, &iC3);
|
||||
EL737Error2Text(pBueffel,iC1);
|
||||
|
||||
strncpy(error,pBueffel,iErrLen);
|
||||
*iCode = iC1;
|
||||
return 1;
|
||||
}
|
||||
/*--------------------------------------------------------------------------*/
|
||||
static int EL737TryAndFixIt(struct __COUNTER *self, int iCode)
|
||||
{
|
||||
EL737st *pEL737;
|
||||
int iRet;
|
||||
char pCommand[50], pReply[50];
|
||||
|
||||
assert(self);
|
||||
pEL737 = (EL737st *)self->pData;
|
||||
assert(pEL737);
|
||||
|
||||
switch(iCode)
|
||||
{
|
||||
case EL737__BAD_ILLG:
|
||||
case EL737__BAD_ADR:
|
||||
case EL737__BAD_PAR:
|
||||
case EL737__BAD_TMO:
|
||||
case EL737__BAD_REPLY:
|
||||
case EL737__BAD_SNTX:
|
||||
case EL737__BAD_OVFL:
|
||||
return COREDO;
|
||||
break;
|
||||
case EL737__BAD_BSY:
|
||||
strcpy(pCommand,"S \r");
|
||||
iRet = EL737_SendCmnd(&pEL737->pData,pCommand,pReply,49);
|
||||
if(iRet < 0)
|
||||
{
|
||||
return COTERM;
|
||||
}
|
||||
else
|
||||
{
|
||||
return COREDO;
|
||||
}
|
||||
break;
|
||||
case EL737__BAD_LOC:
|
||||
strcpy(pCommand,"rmt 1\r");
|
||||
iRet = EL737_SendCmnd(&pEL737->pData,pCommand,pReply,49);
|
||||
if(iRet < 0)
|
||||
{
|
||||
return COTERM;
|
||||
}
|
||||
strcpy(pCommand,"echo 2\r");
|
||||
iRet = EL737_SendCmnd(&pEL737->pData,pCommand,pReply,49);
|
||||
if(iRet < 0)
|
||||
{
|
||||
return COTERM;
|
||||
}
|
||||
strcpy(pCommand,"ra\r");
|
||||
iRet = EL737_SendCmnd(&pEL737->pData,pCommand,pReply,49);
|
||||
if(iRet < 0)
|
||||
{
|
||||
return COTERM;
|
||||
}
|
||||
return COREDO;
|
||||
break;
|
||||
case EL737__BAD_DEV:
|
||||
case EL737__BAD_ID:
|
||||
case EL737__BAD_NOT_BCD:
|
||||
case UNKNOWNPAR:
|
||||
case BADCOUNTER:
|
||||
return COTERM;
|
||||
break;
|
||||
case EL737__FORCED_CLOSED:
|
||||
iRet = EL737_Open(&pEL737->pData,pEL737->host, pEL737->iPort,
|
||||
pEL737->iChannel);
|
||||
if(iRet == 1)
|
||||
{
|
||||
return COREDO;
|
||||
}
|
||||
else
|
||||
{
|
||||
return COTERM;
|
||||
}
|
||||
break;
|
||||
case EL737__BAD_OFL:
|
||||
EL737_Close(&pEL737->pData,0);
|
||||
iRet = EL737_Open(&pEL737->pData,pEL737->host, pEL737->iPort,
|
||||
pEL737->iChannel);
|
||||
if(iRet == 1)
|
||||
{
|
||||
return COREDO;
|
||||
}
|
||||
else
|
||||
{
|
||||
return COTERM;
|
||||
}
|
||||
break;
|
||||
/* case EL737__BAD_ASYNSRV:
|
||||
EL737_Close(&pEL737->pData,1);
|
||||
return COREDO;
|
||||
*/ default:
|
||||
/* try to reopen connection */
|
||||
|
||||
EL737_Close(&pEL737->pData,1);
|
||||
iRet = EL737_Open(&pEL737->pData,pEL737->host, pEL737->iPort,
|
||||
pEL737->iChannel);
|
||||
if(iRet == 1)
|
||||
{
|
||||
return COREDO;
|
||||
}
|
||||
else
|
||||
{
|
||||
return COTERM;
|
||||
}
|
||||
break;
|
||||
}
|
||||
return COTERM;
|
||||
}
|
||||
/*-------------------------------------------------------------------------*/
|
||||
static int EL737Set(struct __COUNTER *self, char *name, int iCter,
|
||||
float fVal)
|
||||
{
|
||||
int iRet;
|
||||
EL737st *pEL737;
|
||||
char pCommand[80],pReply[80];
|
||||
|
||||
assert(self);
|
||||
pEL737 = (EL737st *)self->pData;
|
||||
assert(pEL737);
|
||||
|
||||
if(strcmp(name,"threshold") == 0)
|
||||
{
|
||||
sprintf(pCommand,"DL %1.1d %f\r",iCter,fVal);
|
||||
iRet = EL737_SendCmnd(&pEL737->pData,pCommand,pReply,79);
|
||||
if(iRet == 1)
|
||||
{
|
||||
if(pCommand[0] == '?')
|
||||
{
|
||||
self->iErrorCode = BADCOUNTER;
|
||||
return HWFault;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
return HWFault;
|
||||
}
|
||||
sprintf(pCommand,"DR %1.1d \r",iCter);
|
||||
iRet = EL737_SendCmnd(&pEL737->pData,pCommand,pReply,79);
|
||||
if(iRet == 1)
|
||||
{
|
||||
if(pCommand[0] == '?')
|
||||
{
|
||||
self->iErrorCode = BADCOUNTER;
|
||||
return HWFault;
|
||||
}
|
||||
return OKOK;
|
||||
}
|
||||
else
|
||||
{
|
||||
return HWFault;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
self->iErrorCode = UNKNOWNPAR;
|
||||
return HWFault;
|
||||
}
|
||||
}
|
||||
/*-------------------------------------------------------------------------*/
|
||||
static int EL737Get(struct __COUNTER *self, char *name, int iCter,
|
||||
float *fVal)
|
||||
{
|
||||
int iRet;
|
||||
EL737st *pEL737;
|
||||
char pCommand[80],pReply[80];
|
||||
|
||||
assert(self);
|
||||
pEL737 = (EL737st *)self->pData;
|
||||
assert(pEL737);
|
||||
|
||||
if(strcmp(name,"threshold") == 0)
|
||||
{
|
||||
sprintf(pCommand,"DL %1.1d\r",iCter);
|
||||
iRet = EL737_SendCmnd(&pEL737->pData,pCommand,pReply,79);
|
||||
if(iRet == 1)
|
||||
{
|
||||
if(pReply[0] == '?')
|
||||
{
|
||||
self->iErrorCode = BADCOUNTER;
|
||||
return HWFault;
|
||||
}
|
||||
sscanf(pReply,"%f",fVal);
|
||||
return OKOK;
|
||||
}
|
||||
else
|
||||
{
|
||||
return HWFault;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
self->iErrorCode = UNKNOWNPAR;
|
||||
return HWFault;
|
||||
}
|
||||
}
|
||||
/*-------------------------------------------------------------------------*/
|
||||
static int EL737Send(struct __COUNTER *self, char *pText, char *pReply,
|
||||
int iReplyLen)
|
||||
{
|
||||
EL737st *pEL737;
|
||||
char pBuffer[256];
|
||||
|
||||
assert(self);
|
||||
pEL737 = (EL737st *)self->pData;
|
||||
assert(pEL737);
|
||||
|
||||
/* ensure a \r at the end of the text */
|
||||
if(strlen(pText) > 254)
|
||||
{
|
||||
strncpy(pReply,"Command to long",iReplyLen);
|
||||
return 1;
|
||||
}
|
||||
strcpy(pBuffer,pText);
|
||||
if(strchr(pBuffer,(int)'\r') == NULL)
|
||||
{
|
||||
strcat(pBuffer,"\r");
|
||||
}
|
||||
|
||||
return EL737_SendCmnd(&pEL737->pData,pBuffer,pReply,iReplyLen);
|
||||
}
|
||||
/*--------------------------------------------------------------------------*/
|
||||
pCounterDriver NewEL737Counter(char *name, char *host, int iPort, int iChannel)
|
||||
{
|
||||
pCounterDriver pRes = NULL;
|
||||
EL737st *pData = NULL;
|
||||
int iRet;
|
||||
int iC1, iC2, iC3;
|
||||
char *pErr;
|
||||
char pBueffel[132];
|
||||
|
||||
pRes = CreateCounterDriver(name, "EL737");
|
||||
if(!pRes)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* open connection to counter */
|
||||
pData = (EL737st *)malloc(sizeof(EL737st));
|
||||
if(!pData)
|
||||
{
|
||||
DeleteCounterDriver(pRes);
|
||||
return NULL;
|
||||
}
|
||||
pData->host = strdup(host);
|
||||
pData->iPort = iPort;
|
||||
pData->iChannel = iChannel;
|
||||
pData->pData = NULL;
|
||||
iRet = EL737_Open(&(pData->pData), host,iPort,iChannel);
|
||||
if(iRet != 1)
|
||||
{
|
||||
EL737_ErrInfo(&pErr,&iC1,&iC2, &iC3);
|
||||
DeleteCounterDriver(pRes);
|
||||
if(pData->host)
|
||||
{
|
||||
free(pData->host);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
pRes->pData = (void *)pData;
|
||||
|
||||
/* assign functions */
|
||||
pRes->GetStatus = EL737GetStatus;
|
||||
pRes->Start = EL737Start;
|
||||
pRes->Halt = EL737Halt;
|
||||
pRes->ReadValues = EL737ReadValues;
|
||||
pRes->GetError = EL737GetError;
|
||||
pRes->TryAndFixIt = EL737TryAndFixIt;
|
||||
pRes->Pause = EL737Pause;
|
||||
pRes->Continue = EL737Continue;
|
||||
pRes->Set = EL737Set;
|
||||
pRes->Get = EL737Get;
|
||||
pRes->Send = EL737Send;
|
||||
pRes->iNoOfMonitors = 7;
|
||||
pRes->fTime = 0.;
|
||||
|
||||
return pRes;
|
||||
}
|
||||
/*--------------------------------------------------------------------------*/
|
||||
void KillEL737Counter(pCounterDriver self)
|
||||
{
|
||||
EL737st *pEL737 = NULL;
|
||||
|
||||
assert(self);
|
||||
pEL737 = (EL737st *)self->pData;
|
||||
assert(pEL737);
|
||||
|
||||
EL737_Close(&pEL737->pData,0);
|
||||
if(pEL737->host)
|
||||
{
|
||||
free(pEL737->host);
|
||||
}
|
||||
DeleteCounterDriver(self);
|
||||
}
|
||||
|
84
countdriv.h
Normal file
84
countdriv.h
Normal file
@ -0,0 +1,84 @@
|
||||
/*---------------------------------------------------------------------------
|
||||
C O U N T E R D R I V E R
|
||||
|
||||
|
||||
This is the interface to a Sics-Counter driver. This means a
|
||||
single counter managing possibly several monitors in one go.
|
||||
|
||||
A counter can run for a predefined time or until a predefined
|
||||
monitor count has been reached.
|
||||
|
||||
Mark Koennecke, January 1996
|
||||
|
||||
General parameter setting added:
|
||||
Mark Koennecke, April 1999
|
||||
|
||||
copyright: see implementation file.
|
||||
|
||||
---------------------------------------------------------------------------*/
|
||||
#ifndef SICSCOUNTERDRIVER
|
||||
#define SICSCOUNTERDRIVER
|
||||
|
||||
#define COTERM 0
|
||||
#define COREDO 1
|
||||
|
||||
#define MAXCOUNT 9 /* No of monitors + actual counter */
|
||||
|
||||
|
||||
/* Parameter codes for the Set/Get pair of routines */
|
||||
/*-------- threshold */
|
||||
#define PARTHRESHOLD 1
|
||||
|
||||
/* counter driver additional error codes*/
|
||||
#define UNKNOWNPAR -5000
|
||||
#define BADCOUNTER -5001
|
||||
|
||||
typedef struct __COUNTER {
|
||||
/* variables */
|
||||
char *name;
|
||||
char *type;
|
||||
CounterMode eMode;
|
||||
float fPreset;
|
||||
float fLastCurrent;
|
||||
float fTime;
|
||||
int iNoOfMonitors;
|
||||
long lCounts[MAXCOUNT];
|
||||
int iPause;
|
||||
int iErrorCode;
|
||||
/* functions */
|
||||
int (*GetStatus)(struct __COUNTER *self, float *fControl);
|
||||
int (*Start)(struct __COUNTER *self);
|
||||
int (*Pause)(struct __COUNTER *self);
|
||||
int (*Continue)(struct __COUNTER *self);
|
||||
int (*Halt)(struct __COUNTER *self);
|
||||
int (*ReadValues)(struct __COUNTER *self);
|
||||
int (*GetError)(struct __COUNTER *self, int *iCode,
|
||||
char *error, int iErrLen);
|
||||
int (*TryAndFixIt)(struct __COUNTER *self, int iCode);
|
||||
int (*Set)(struct __COUNTER *self,char *name,
|
||||
int iCter, float fVal);
|
||||
int (*Get)(struct __COUNTER *self,char *name,
|
||||
int iCter, float *fVal);
|
||||
int (*Send)(struct __COUNTER *self, char *pText,
|
||||
char *pReply, int iReplyLen);
|
||||
void *pData; /* counter specific data goes here, ONLY for
|
||||
internal driver use!
|
||||
*/
|
||||
} CounterDriver, *pCounterDriver;
|
||||
|
||||
/*------------------------------------------------------------------------*/
|
||||
|
||||
/* countdriv.c */
|
||||
pCounterDriver CreateCounterDriver(char *name, char *type);
|
||||
void DeleteCounterDriver(pCounterDriver self);
|
||||
|
||||
/* PSI EL737 Counter */
|
||||
pCounterDriver NewEL737Counter(char *name, char *host, int iPort,
|
||||
int iChannel);
|
||||
void KillEL737Counter(pCounterDriver self);
|
||||
|
||||
/* PSI Simulation counter, if you have no hardware */
|
||||
/* simcter.c */
|
||||
pCounterDriver NewSIMCounter(char *name, float fVal);
|
||||
void KillSIMCounter(pCounterDriver self);
|
||||
#endif
|
57
counter.h
Normal file
57
counter.h
Normal file
@ -0,0 +1,57 @@
|
||||
/*-------------------------------------------------------------------------
|
||||
|
||||
C O U N T E R
|
||||
|
||||
The SICS Interface to a single detector and his associated
|
||||
monitors.
|
||||
|
||||
Mark Koennecke, January 1996
|
||||
|
||||
copyright: see implementation file.
|
||||
----------------------------------------------------------------------------*/
|
||||
#ifndef SICSCOUNTER
|
||||
#define SICSCOUNTER
|
||||
#include "countdriv.h"
|
||||
|
||||
typedef struct {
|
||||
pObjectDescriptor pDes;
|
||||
char *name;
|
||||
int isUpToDate;
|
||||
int iExponent;
|
||||
pICountable pCountInt;
|
||||
pCounterDriver pDriv;
|
||||
pICallBack pCall;
|
||||
unsigned long tStart;
|
||||
int iCallbackCounter;
|
||||
} Counter, *pCounter;
|
||||
|
||||
/*----------------------------- birth & death -----------------------------*/
|
||||
|
||||
pCounter CreateCounter(char *name, pCounterDriver pDriv);
|
||||
void DeleteCounter(void *self);
|
||||
int MakeCounter(SConnection *pCon, SicsInterp *pSics, void *pData,
|
||||
int argc, char *argv[]);
|
||||
/*------------------------- set/get Parameters ----------------------------*/
|
||||
int SetCounterMode(pCounter self, CounterMode eNew);
|
||||
CounterMode GetCounterMode(pCounter self);
|
||||
|
||||
int SetCounterPreset(pCounter self, float fVal);
|
||||
float GetCounterPreset(pCounter self);
|
||||
|
||||
long GetCounts(pCounter self, SConnection *pCon);
|
||||
long GetMonitor(pCounter self, int iNum, SConnection *pCon);
|
||||
int GetNMonitor(pCounter self);
|
||||
float GetCountTime(pCounter self, SConnection *pCon);
|
||||
|
||||
int DoCount(pCounter self,float fPreset, SConnection *pCon,
|
||||
int iBlock);
|
||||
|
||||
/*-------------------------------------------------------------------------
|
||||
the real action: starting and checking is packaged with the
|
||||
ObjectDescriptor.
|
||||
*/
|
||||
|
||||
int CountAction(SConnection *pCon, SicsInterp *pSics, void *pData,
|
||||
int argc, char *argv[]);
|
||||
|
||||
#endif
|
50
countf.tcl
Normal file
50
countf.tcl
Normal file
@ -0,0 +1,50 @@
|
||||
#--------------------------------------------------------------------------
|
||||
# A count command for FOCUS
|
||||
# All arguments are optional. The current values will be used if not
|
||||
# specified
|
||||
# Dr. Mark Koennecke, Juli 1997
|
||||
#--------------------------------------------------------------------------
|
||||
proc SplitReply { text } {
|
||||
set l [split $text =]
|
||||
return [lindex $l 1]
|
||||
}
|
||||
#--------------------------------------------------------------------------
|
||||
proc count { {mode NULL } { preset NULL } } {
|
||||
starttime [sicstime]
|
||||
#----- deal with mode
|
||||
set mode2 [string toupper $mode]
|
||||
set mode3 [string trim $mode2]
|
||||
set mc [string index $mode2 0]
|
||||
if { [string compare $mc T] == 0 } {
|
||||
hm CountMode Timer
|
||||
} elseif { [string compare $mc M] == 0 } {
|
||||
hm CountMode Monitor
|
||||
}
|
||||
#------ deal with preset
|
||||
if { [string compare $preset NULL] != 0 } {
|
||||
hm preset $preset
|
||||
}
|
||||
#------ prepare a count message
|
||||
set a [hm preset]
|
||||
set aa [SplitReply $a]
|
||||
set b [hm CountMode]
|
||||
set bb [SplitReply $b]
|
||||
ClientPut [format " Starting counting in %s mode with a preset of %s" \
|
||||
$bb $aa]
|
||||
#------- count
|
||||
# hm InitVal 0
|
||||
wait 1
|
||||
set ret [catch {hm countblock} msg]
|
||||
#------- StoreData
|
||||
storefocus update
|
||||
# wait 5
|
||||
if { $ret != 0 } {
|
||||
error [format "Counting ended with error: %s" $msg]
|
||||
}
|
||||
}
|
||||
#---------------- Repeat -----------------------------------------------
|
||||
proc repeat { num {mode NULL} {preset NULL} } {
|
||||
for { set i 0 } { $i < $num } { incr i } {
|
||||
count $mode $preset
|
||||
}
|
||||
}
|
16
cron.tex
Normal file
16
cron.tex
Normal file
@ -0,0 +1,16 @@
|
||||
\subsection{cron}
|
||||
This module allows to install commands into SICS which will be repeated
|
||||
periodically. The syntax is: sicscron intervall command. intervall is
|
||||
the time intervall and command is the command to execute. A problem
|
||||
is I/O becasue the original connection which installed the cron job
|
||||
may be lost. Therefore cron commands are executed within the context
|
||||
of special connection which does not do socket output. All I/O will be
|
||||
logged into the command log though for control. As
|
||||
this is a single system facility all data structure will be defined
|
||||
in the implementation file. The public interface to this is just the
|
||||
installation routine. This stuff is implemented in the files
|
||||
sicscron.h and sicscron.c.
|
||||
|
||||
The installation routine installs another task into the SICS system
|
||||
which will invoke the command to be executed at the predefined
|
||||
intervalls.
|
16
cron.w
Normal file
16
cron.w
Normal file
@ -0,0 +1,16 @@
|
||||
\subsection{cron}
|
||||
This module allows to install commands into SICS which will be repeated
|
||||
periodically. The syntax is: sicscron intervall command. intervall is
|
||||
the time intervall and command is the command to execute. A problem
|
||||
is I/O becasue the original connection which installed the cron job
|
||||
may be lost. Therefore cron commands are executed within the context
|
||||
of special connection which does not do socket output. All I/O will be
|
||||
logged into the command log though for control. As
|
||||
this is a single system facility all data structure will be defined
|
||||
in the implementation file. The public interface to this is just the
|
||||
installation routine. This stuff is implemented in the files
|
||||
sicscron.h and sicscron.c.
|
||||
|
||||
The installation routine installs another task into the SICS system
|
||||
which will invoke the command to be executed at the predefined
|
||||
intervalls.
|
538
crysconv.c
Normal file
538
crysconv.c
Normal file
@ -0,0 +1,538 @@
|
||||
/* crysconv.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 {
|
||||
doublereal s[16] /* was [4][4] */, sinv[16] /* was [4][4] */;
|
||||
integer iok;
|
||||
} osolem_;
|
||||
|
||||
#define osolem_1 osolem_
|
||||
|
||||
/* ================ */
|
||||
|
||||
/* dec$ Ident 'V01A' */
|
||||
/* ------------------------------------------------------------------ */
|
||||
/* Updates: */
|
||||
/* V01A 7-May-1996 DM. Put error output to IOLUN, use IMPLICIT NONE and */
|
||||
/* get the code indented so that it is readable! */
|
||||
/* made F77 compliant. Mark Koennecke July 1996 */
|
||||
/* ------------------------------------------------------------------ */
|
||||
/* Routines to deal with the reciprocical lattice PB */
|
||||
/* ------------------------------------------------------------------ */
|
||||
/* Entry points in this file: */
|
||||
|
||||
/* SETRLP : CALCULATION OF S AND INVS , ORIENTATION MATRIX */
|
||||
/* RL2SPV : TRANSFO FROM RECIP LAT TO SCAT PLANE */
|
||||
/* SP2RLV : TRANSFO FROM SCAT PLANE TO RECIP LAT */
|
||||
/* INVS : INVERT MATRIX S, GENERATED BY SETRLP. */
|
||||
/* ERRESO : DEAL ITH ERROR MESSAGES FOR ALL MODULES */
|
||||
|
||||
/* SUBROUTINE SETRLP(SAM,IER) */
|
||||
/* SUBROUTINE RL2SPV(QHKL,QT,QM,QS,IER) */
|
||||
/* SUBROUTINE SP2RLV(QHKL,QT,QM,QS,IER) */
|
||||
/* SUBROUTINE INVS(S,SINV,IER) */
|
||||
/* SUBROUTINE ERRESO(MODULE,IER) */
|
||||
/* ------------------------------------------------------------------ */
|
||||
/* Subroutine */ int setrlp_(doublereal *sam, integer *ier)
|
||||
{
|
||||
/* System generated locals */
|
||||
doublereal d__1;
|
||||
|
||||
/* Builtin functions */
|
||||
double cos(doublereal), sin(doublereal), sqrt(doublereal), atan(
|
||||
doublereal);
|
||||
|
||||
/* Local variables */
|
||||
static doublereal alfa[3], cosa[3], cosb[3];
|
||||
static integer imod;
|
||||
static doublereal sina[3], sinb[3], aspv[6] /* was [3][2] */;
|
||||
extern /* Subroutine */ int invs_(doublereal *, doublereal *, integer *);
|
||||
static doublereal a[3], b[3], c__[3], bb[9] /* was [3][3] */, cc;
|
||||
static integer id, ie, jd, je, jf, kg, lf, lh, md, me, ne;
|
||||
static doublereal zp, vv[9] /* was [3][3] */;
|
||||
extern /* Subroutine */ int erreso_(integer *, integer *);
|
||||
static doublereal rlb[6] /* was [3][2] */;
|
||||
|
||||
/* ============================ */
|
||||
|
||||
/* SETRLP: Computation of matrix S which transforms (QH,QK,QL) to */
|
||||
/* vector (Q1,Q2) in scattering plane (defined by vectors A1,A2) */
|
||||
/* and SINV matrix for the inverse transformation */
|
||||
|
||||
/* INPUT SAM SAMPLE CHARACTERISTICS */
|
||||
/* SAM(1)=AS LATTICE PARAMETERS */
|
||||
/* SAM(2)=BS ------------------ */
|
||||
/* SAM(3)=CS ------------------ */
|
||||
/* SAM(4)=AA LATTICE ANGLES */
|
||||
/* SAM(5)=BB -------------- */
|
||||
/* SAM(6)=CC -------------- */
|
||||
/* SAM(7)=AX VECTOR A IN SCATTERING PLANE */
|
||||
/* SAM(8)=AY ---------------------------- */
|
||||
/* SAM(9)=AZ ---------------------------- */
|
||||
/* SAM(10)=BX VECTOR B IN SCATTERING PLANE */
|
||||
/* SAM(11)=BY ---------------------------- */
|
||||
/* SAM(12)=BZ ---------------------------- */
|
||||
/* OUTPUT IER ERROR RETURN TO BE TREATED BY ERRESO */
|
||||
/* IER=1 ERROR ON LATTICE PARAMETERS */
|
||||
/* IER=2 ERROR ON LATTICE ANGLES */
|
||||
/* IER=3 ERROR ON VECTORS A1, A2 */
|
||||
/* ------------------------------------------------------------------ */
|
||||
|
||||
/* ------------------------------------------------------------------ */
|
||||
/* Define the dummy arguments */
|
||||
/* ------------------------------------------------------------------ */
|
||||
/* DO NOT EXPORT THE FOLLOWING COMMON ! */
|
||||
/* IT IS JUST FOR PERMANENT STORAGE USE */
|
||||
|
||||
/* ----------------------------------------------------------------------- */
|
||||
|
||||
/* ----------------------------------------------------------------------- */
|
||||
/* SOME TESTS AND INIT OF CALCUALTION */
|
||||
|
||||
/* Parameter adjustments */
|
||||
--sam;
|
||||
|
||||
/* Function Body */
|
||||
*ier = 0;
|
||||
imod = 1;
|
||||
zp = 6.2831853071795862;
|
||||
osolem_1.iok = 0;
|
||||
for (id = 1; id <= 3; ++id) {
|
||||
a[id - 1] = sam[id];
|
||||
alfa[id - 1] = sam[id + 3];
|
||||
aspv[id - 1] = sam[id + 6];
|
||||
aspv[id + 2] = sam[id + 9];
|
||||
/* L10: */
|
||||
}
|
||||
|
||||
for (id = 1; id <= 3; ++id) {
|
||||
*ier = 1;
|
||||
if ((d__1 = a[id - 1], abs(d__1)) <= 1e-8) {
|
||||
goto L999;
|
||||
}
|
||||
*ier = 0;
|
||||
/* L20: */
|
||||
}
|
||||
for (id = 1; id <= 3; ++id) {
|
||||
a[id - 1] /= zp;
|
||||
alfa[id - 1] /= 57.29577951308232087679815481410517;
|
||||
cosa[id - 1] = cos(alfa[id - 1]);
|
||||
sina[id - 1] = sin(alfa[id - 1]);
|
||||
/* L30: */
|
||||
}
|
||||
cc = cosa[0] * cosa[0] + cosa[1] * cosa[1] + cosa[2] * cosa[2];
|
||||
cc = cosa[0] * 2. * cosa[1] * cosa[2] + 1. - cc;
|
||||
*ier = 2;
|
||||
if (cc <= .1) {
|
||||
goto L999;
|
||||
}
|
||||
*ier = 0;
|
||||
cc = sqrt(cc);
|
||||
je = 2;
|
||||
kg = 3;
|
||||
for (id = 1; id <= 3; ++id) {
|
||||
b[id - 1] = sina[id - 1] / (a[id - 1] * cc);
|
||||
cosb[id - 1] = (cosa[je - 1] * cosa[kg - 1] - cosa[id - 1]) / (sina[
|
||||
je - 1] * sina[kg - 1]);
|
||||
sinb[id - 1] = sqrt(1. - cosb[id - 1] * cosb[id - 1]);
|
||||
rlb[id + 2] = (d__1 = atan(sinb[id - 1] / cosb[id - 1]), abs(d__1)) *
|
||||
57.29577951308232087679815481410517;
|
||||
je = kg;
|
||||
kg = id;
|
||||
/* L40: */
|
||||
}
|
||||
bb[0] = b[0];
|
||||
bb[1] = 0.;
|
||||
bb[2] = 0.;
|
||||
bb[3] = b[1] * cosb[2];
|
||||
bb[4] = b[1] * sinb[2];
|
||||
bb[5] = 0.;
|
||||
bb[6] = b[2] * cosb[1];
|
||||
bb[7] = -b[2] * sinb[1] * cosa[0];
|
||||
bb[8] = 1. / a[2];
|
||||
|
||||
for (id = 1; id <= 3; ++id) {
|
||||
rlb[id - 1] = 0.;
|
||||
for (je = 1; je <= 3; ++je) {
|
||||
/* Computing 2nd power */
|
||||
d__1 = bb[je + id * 3 - 4];
|
||||
rlb[id - 1] += d__1 * d__1;
|
||||
/* L60: */
|
||||
}
|
||||
*ier = 1;
|
||||
if ((d__1 = rlb[id - 1], abs(d__1)) <= 1e-8) {
|
||||
goto L999;
|
||||
}
|
||||
*ier = 0;
|
||||
rlb[id - 1] = sqrt(rlb[id - 1]);
|
||||
/* L50: */
|
||||
}
|
||||
/* ----------------------------------------------------------------------- */
|
||||
/* GENERATION OF S ORIENTATION MATRIX REC. LATTICE TO SCATTERING PLANE */
|
||||
|
||||
for (kg = 1; kg <= 2; ++kg) {
|
||||
for (ie = 1; ie <= 3; ++ie) {
|
||||
vv[kg + ie * 3 - 4] = 0.;
|
||||
for (jf = 1; jf <= 3; ++jf) {
|
||||
vv[kg + ie * 3 - 4] += bb[ie + jf * 3 - 4] * aspv[jf + kg * 3
|
||||
- 4];
|
||||
/* L90: */
|
||||
}
|
||||
/* L80: */
|
||||
}
|
||||
/* L70: */
|
||||
}
|
||||
for (md = 3; md >= 2; --md) {
|
||||
for (ne = 1; ne <= 3; ++ne) {
|
||||
id = md % 3 + 1;
|
||||
je = (md + 1) % 3 + 1;
|
||||
kg = ne % 3 + 1;
|
||||
lh = (ne + 1) % 3 + 1;
|
||||
vv[md + ne * 3 - 4] = vv[id + kg * 3 - 4] * vv[je + lh * 3 - 4] -
|
||||
vv[id + lh * 3 - 4] * vv[je + kg * 3 - 4];
|
||||
/* L110: */
|
||||
}
|
||||
/* L100: */
|
||||
}
|
||||
|
||||
for (id = 1; id <= 3; ++id) {
|
||||
c__[id - 1] = 0.;
|
||||
for (je = 1; je <= 3; ++je) {
|
||||
/* Computing 2nd power */
|
||||
d__1 = vv[id + je * 3 - 4];
|
||||
c__[id - 1] += d__1 * d__1;
|
||||
/* L130: */
|
||||
}
|
||||
*ier = 3;
|
||||
if ((d__1 = c__[id - 1], abs(d__1)) <= 1e-6) {
|
||||
goto L999;
|
||||
}
|
||||
*ier = 0;
|
||||
c__[id - 1] = sqrt(c__[id - 1]);
|
||||
/* L120: */
|
||||
}
|
||||
|
||||
for (id = 1; id <= 3; ++id) {
|
||||
for (je = 1; je <= 3; ++je) {
|
||||
vv[je + id * 3 - 4] /= c__[je - 1];
|
||||
/* L160: */
|
||||
}
|
||||
/* L150: */
|
||||
}
|
||||
for (kg = 1; kg <= 3; ++kg) {
|
||||
for (me = 1; me <= 3; ++me) {
|
||||
osolem_1.s[kg + (me << 2) - 5] = 0.;
|
||||
for (lf = 1; lf <= 3; ++lf) {
|
||||
osolem_1.s[kg + (me << 2) - 5] += vv[kg + lf * 3 - 4] * bb[lf
|
||||
+ me * 3 - 4];
|
||||
/* L190: */
|
||||
}
|
||||
/* L180: */
|
||||
}
|
||||
/* L170: */
|
||||
}
|
||||
osolem_1.s[15] = 1.;
|
||||
for (jd = 1; jd <= 3; ++jd) {
|
||||
osolem_1.s[(jd << 2) - 1] = 0.;
|
||||
osolem_1.s[jd + 11] = 0.;
|
||||
/* L200: */
|
||||
}
|
||||
/* ----------------------------------------------------------------------- */
|
||||
/* INVERT TRANSFORMATION MATRIX S AND PU RESULT IN SINV */
|
||||
|
||||
*ier = 3;
|
||||
invs_(osolem_1.s, osolem_1.sinv, ier);
|
||||
*ier = 0;
|
||||
if (*ier != 0) {
|
||||
goto L999;
|
||||
}
|
||||
osolem_1.iok = 123;
|
||||
/* --------------------------------------------------------------------------- */
|
||||
/* SORTIE */
|
||||
|
||||
L999:
|
||||
if (*ier != 0) {
|
||||
erreso_(&imod, ier);
|
||||
}
|
||||
return 0;
|
||||
} /* setrlp_ */
|
||||
|
||||
/* =========================================================================== */
|
||||
/* Subroutine */ int rl2spv_(doublereal *qhkl, doublereal *qt, doublereal *qm,
|
||||
doublereal *qs, integer *ier)
|
||||
{
|
||||
/* System generated locals */
|
||||
doublereal d__1;
|
||||
|
||||
/* Builtin functions */
|
||||
double sqrt(doublereal);
|
||||
|
||||
/* Local variables */
|
||||
static integer id, je;
|
||||
|
||||
/* ========================================= */
|
||||
|
||||
/* ------------------------------------------------------------------ */
|
||||
/* INPUT QHKL QHKL -> QT */
|
||||
/* A Q-VECTOR TO BE TRANSFORM FROM RECIP LATTICE TO SCATTERING PLANE */
|
||||
/* CHECK THAT Q-VECTOR IS IN THE PLANE */
|
||||
|
||||
/* INPUT Q-VECTOR QHKL(3) Q-VECTOR IN RECIPROCICAL LATTICVE */
|
||||
|
||||
/* OUTPUT Q-VECTOR QT(3) Q-VECTOR IN SCATTERING PLANE */
|
||||
/* OUTPUT QM AND QS QMODULUS AND ITS SQUARE ( TO BE VERIFIED ) */
|
||||
/* OUTPUT ERROR IER */
|
||||
/* IER=1 MATRIX S NOT OK */
|
||||
/* IER=2 Q NOT IN SCATTERING PLANE */
|
||||
/* IER=3 Q MODULUS TOO SMALL */
|
||||
/* ------------------------------------------------------------------ */
|
||||
|
||||
/* ------------------------------------------------------------------ */
|
||||
/* Define the dummy arguments */
|
||||
/* ------------------------------------------------------------------ */
|
||||
/* DO NOT EXPORT THE FOLLWING COOMON ! */
|
||||
/* IT IS JUST FOR PERMANENT STORAGE USE */
|
||||
|
||||
/* --------------------------------------------------------------------------- */
|
||||
/* --------------------------------------------------------------------------- */
|
||||
/* INIT AND TEST IF TRANSFO MATRICES ARE OK */
|
||||
/* Parameter adjustments */
|
||||
--qt;
|
||||
--qhkl;
|
||||
|
||||
/* Function Body */
|
||||
*ier = 1;
|
||||
if (osolem_1.iok != 123) {
|
||||
goto L999;
|
||||
}
|
||||
*ier = 0;
|
||||
/* ----------------------------------------------------------------------- */
|
||||
|
||||
for (id = 1; id <= 3; ++id) {
|
||||
qt[id] = 0.;
|
||||
for (je = 1; je <= 3; ++je) {
|
||||
qt[id] += qhkl[je] * osolem_1.s[id + (je << 2) - 5];
|
||||
/* L20: */
|
||||
}
|
||||
/* L10: */
|
||||
}
|
||||
*ier = 2;
|
||||
if (abs(qt[3]) > 1e-4) {
|
||||
goto L999;
|
||||
}
|
||||
*ier = 0;
|
||||
*qs = 0.;
|
||||
for (id = 1; id <= 3; ++id) {
|
||||
/* Computing 2nd power */
|
||||
d__1 = qt[id];
|
||||
*qs += d__1 * d__1;
|
||||
/* L30: */
|
||||
}
|
||||
if (*qs < 1e-8) {
|
||||
*ier = 3;
|
||||
} else {
|
||||
*qm = sqrt(*qs);
|
||||
}
|
||||
/* --------------------------------------------------------------------------- */
|
||||
|
||||
L999:
|
||||
return 0;
|
||||
} /* rl2spv_ */
|
||||
|
||||
/* =========================================================================== */
|
||||
/* Subroutine */ int sp2rlv_(doublereal *qhkl, doublereal *qt, doublereal *qm,
|
||||
doublereal *qs, integer *ier)
|
||||
{
|
||||
/* System generated locals */
|
||||
doublereal d__1;
|
||||
|
||||
/* Builtin functions */
|
||||
double sqrt(doublereal);
|
||||
|
||||
/* Local variables */
|
||||
static integer id, je;
|
||||
|
||||
/* ========================================= */
|
||||
|
||||
/* ------------------------------------------------------------------ */
|
||||
/* INPUT QT QHKL <- QT */
|
||||
/* A Q-VECTOR TO BE TRANSFORM FROM SCATTERING PLANE TO RECIP LATTICE */
|
||||
/* CHECK THAT Q, D & G VECTORS ARE IN THE SCATTERING PLANE */
|
||||
|
||||
/* INPUT Q-VECTOR QT(3) Q-VECTOR IN SCATTERING PLANE */
|
||||
|
||||
/* OUTPUT Q-VECTOR QHKL(3) Q-VECTOR IN RECIPROCICAL LATTICVE */
|
||||
/* OUTPUT QM AND QS QMODULUS AND ITS SQUARE ( TO BE VERIFIED ) */
|
||||
/* OUTPUT ERROR IER */
|
||||
/* IER=1 MATRIX S NOT OK */
|
||||
/* IER=2 Q NOT IN SCATTERING PLANE */
|
||||
/* IER=3 Q MODULUS TOO SMALL */
|
||||
/* ------------------------------------------------------------------ */
|
||||
|
||||
/* ------------------------------------------------------------------ */
|
||||
/* Define the dummy arguments */
|
||||
/* ------------------------------------------------------------------ */
|
||||
/* DO NOT EXPORT THE FOLLWING COOMON ! */
|
||||
/* IT IS JUST FOR PERMANENT STORAGE USE */
|
||||
|
||||
/* --------------------------------------------------------------------------- */
|
||||
/* --------------------------------------------------------------------------- */
|
||||
/* INIT AND TEST IF TRANSFO MATRICES ARE OK */
|
||||
/* Parameter adjustments */
|
||||
--qt;
|
||||
--qhkl;
|
||||
|
||||
/* Function Body */
|
||||
*ier = 1;
|
||||
if (osolem_1.iok != 123) {
|
||||
goto L999;
|
||||
}
|
||||
*ier = 2;
|
||||
if (abs(qt[3]) > 1e-4) {
|
||||
goto L999;
|
||||
}
|
||||
*ier = 0;
|
||||
/* ----------------------------------------------------------------------- */
|
||||
*qs = 0.;
|
||||
for (id = 1; id <= 3; ++id) {
|
||||
/* Computing 2nd power */
|
||||
d__1 = qt[id];
|
||||
*qs += d__1 * d__1;
|
||||
/* L10: */
|
||||
}
|
||||
if (*qs < 1e-8) {
|
||||
*ier = 3;
|
||||
} else {
|
||||
*qm = sqrt(*qs);
|
||||
}
|
||||
/* ----------------------------------------------------------------------- */
|
||||
|
||||
for (id = 1; id <= 3; ++id) {
|
||||
qhkl[id] = 0.;
|
||||
for (je = 1; je <= 3; ++je) {
|
||||
qhkl[id] += osolem_1.sinv[id + (je << 2) - 5] * qt[je];
|
||||
/* L30: */
|
||||
}
|
||||
/* L20: */
|
||||
}
|
||||
/* --------------------------------------------------------------------------- */
|
||||
|
||||
L999:
|
||||
return 0;
|
||||
} /* sp2rlv_ */
|
||||
|
||||
/* ========================================================================== */
|
||||
/* Subroutine */ int invs_(doublereal *s, doublereal *sinv, integer *ier)
|
||||
{
|
||||
/* Initialized data */
|
||||
|
||||
static integer m[3] = { 2,3,1 };
|
||||
static integer n[3] = { 3,1,2 };
|
||||
|
||||
static integer id, je, mi, mj, ni, nj;
|
||||
static doublereal det;
|
||||
|
||||
/* ============================== */
|
||||
|
||||
/* ------------------------------------------------------------------ */
|
||||
/* ROUTINE TO INVERT MATRIX S, GENERATED BY SETRLP, WHICH TRANSFORMS */
|
||||
/* (QH,QK,QL) TO (Q1,Q2) IN THE SCATTERING PLANE */
|
||||
/* INPUT MATRIX DOUBLE PRECISION S(4,4) */
|
||||
/* OUTPUT MATRIX DOUBLE PRECISION SINV(4,4) */
|
||||
/* OUTPUT ERROR IER */
|
||||
/* IER=1 DETERMINANT OF MATRIX S TOO SMALL */
|
||||
/* ------------------------------------------------------------------ */
|
||||
|
||||
/* ------------------------------------------------------------------ */
|
||||
/* Define the dummy arguments */
|
||||
/* ------------------------------------------------------------------ */
|
||||
|
||||
/* Parameter adjustments */
|
||||
sinv -= 5;
|
||||
s -= 5;
|
||||
|
||||
/* Function Body */
|
||||
/* ------------------------------------------------------------------ */
|
||||
*ier = 0;
|
||||
for (id = 1; id <= 4; ++id) {
|
||||
for (je = 1; je <= 4; ++je) {
|
||||
sinv[id + (je << 2)] = 0.;
|
||||
/* L20: */
|
||||
}
|
||||
/* L10: */
|
||||
}
|
||||
det = 0.;
|
||||
for (id = 1; id <= 3; ++id) {
|
||||
for (je = 1; je <= 3; ++je) {
|
||||
mi = m[id - 1];
|
||||
mj = m[je - 1];
|
||||
ni = n[id - 1];
|
||||
nj = n[je - 1];
|
||||
sinv[je + (id << 2)] = s[mi + (mj << 2)] * s[ni + (nj << 2)] - s[
|
||||
ni + (mj << 2)] * s[mi + (nj << 2)];
|
||||
/* L40: */
|
||||
}
|
||||
det += s[id + 4] * sinv[(id << 2) + 1];
|
||||
/* L30: */
|
||||
}
|
||||
if (abs(det) < 1e-6) {
|
||||
*ier = 1;
|
||||
} else {
|
||||
for (id = 1; id <= 3; ++id) {
|
||||
for (je = 1; je <= 3; ++je) {
|
||||
sinv[id + (je << 2)] /= det;
|
||||
/* L70: */
|
||||
}
|
||||
/* L60: */
|
||||
}
|
||||
}
|
||||
sinv[20] = 1.;
|
||||
return 0;
|
||||
} /* invs_ */
|
||||
|
||||
/* ========================================================================= */
|
||||
/* Subroutine */ int erreso_(integer *module, integer *ier)
|
||||
{
|
||||
|
||||
/* System generated locals */
|
||||
integer i__1;
|
||||
|
||||
/* Local variables */
|
||||
static integer lmod, lier;
|
||||
|
||||
/* ============================= */
|
||||
|
||||
/* ------------------------------------------------------------------ */
|
||||
/* SUBROUTINE TO TREAT ERRORS FROM RESOLUTION CALCULATIONS */
|
||||
/* MODULE = 1 -> SETRLP */
|
||||
/* MODULE = 2 -> RL2SPV */
|
||||
/* MODULE = 3 -> EX_CASE */
|
||||
/* ------------------------------------------------------------------ */
|
||||
|
||||
|
||||
/* INCLUDE 'MAD_DEF:IOLSDDEF.INC' */
|
||||
/* ------------------------------------------------------------------ */
|
||||
/* Define the dummy arguments */
|
||||
/* ------------------------------------------------------------------ */
|
||||
|
||||
|
||||
/* --------------------------------------------------------------------------- */
|
||||
/* Computing MIN */
|
||||
i__1 = max(*ier,1);
|
||||
lier = min(i__1,4);
|
||||
/* Computing MIN */
|
||||
i__1 = max(*module,1);
|
||||
lmod = min(i__1,3);
|
||||
/* WRITE(6,501) MESER(LIER,LMOD) */
|
||||
/* 501 FORMAT(A) */
|
||||
return 0;
|
||||
} /* erreso_ */
|
||||
|
||||
|
||||
|
114
cryst.c
Normal file
114
cryst.c
Normal file
@ -0,0 +1,114 @@
|
||||
/*---------------------------------------------------------------------------
|
||||
C r y s t
|
||||
|
||||
This is a library of crystallographic utility routines for four
|
||||
circle diffractometers. It deals with all sorts of rotations and
|
||||
stuff. This is based on code originally developed by John Allibon
|
||||
at ILL and reimplemented in C using a matrix-library.
|
||||
|
||||
Mark Koennecke, July 2000
|
||||
----------------------------------------------------------------------------*/
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <assert.h>
|
||||
#include <math.h>
|
||||
#include "matrix/matrix.h"
|
||||
#include "cryst.h"
|
||||
|
||||
#define PIR 57.30
|
||||
|
||||
/*-------------------------------------------------------------------------
|
||||
chimat, calculate chi rotation matrix. The input angle is in degrees.
|
||||
The setting is Busing & Levy.
|
||||
--------------------------------------------------------------------------*/
|
||||
|
||||
MATRIX chimat(double dAngle)
|
||||
{
|
||||
MATRIX res;
|
||||
double dChi;
|
||||
|
||||
res = mat_creat(3,3,ZERO_MATRIX);
|
||||
dChi = dAngle/PIR;
|
||||
|
||||
res[0][0] = cos(dChi);
|
||||
res[0][2] = sin(dChi);
|
||||
res[1][1] = 1.;
|
||||
res[2][0] = -res[0][2];
|
||||
res[2][2] = res[0][0];
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
/*-------------------------------------------------------------------------
|
||||
phimat, calculate phi rotation matrix. The input angle is in degrees.
|
||||
The setting is Busing & Levy.
|
||||
--------------------------------------------------------------------------*/
|
||||
|
||||
MATRIX phimat(double dAngle)
|
||||
{
|
||||
MATRIX res;
|
||||
double dPhi;
|
||||
|
||||
res = mat_creat(3,3,ZERO_MATRIX);
|
||||
dPhi = dAngle/PIR;
|
||||
|
||||
res[0][0] = cos(dPhi);
|
||||
res[0][1] = sin(dChi);
|
||||
res[2][2] = 1.;
|
||||
res[1][0] = -res[0][1];
|
||||
res[1][1] = res[0][0];
|
||||
|
||||
return res;
|
||||
}
|
||||
/*-------------------------------------------------------------------------
|
||||
psimat, calculate psi rotation matrix. The input angle is in degrees.
|
||||
The setting is Busing & Levy.
|
||||
--------------------------------------------------------------------------*/
|
||||
|
||||
MATRIX psimat(double dAngle)
|
||||
{
|
||||
MATRIX res;
|
||||
double dPsi;
|
||||
|
||||
res = mat_creat(3,3,ZERO_MATRIX);
|
||||
dPsi = dAngle/PIR;
|
||||
|
||||
res[0][0] = 1.;
|
||||
res[1][1] = cos(dPsi);
|
||||
res[1][2] = -sin(dPsi);
|
||||
res[2][1] = -res[1][2];
|
||||
res[2][2] = res[1][1];
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
/*-------------------------------------------------------------------------
|
||||
diffFromAngles calculates the diffraction vector from two theta, omega
|
||||
chi and phi. The angled need not be bissecting but it is assumed that
|
||||
the diffraction vector is in the equatorial plane.
|
||||
--------------------------------------------------------------------------*/
|
||||
|
||||
MATRIX diffFromAngles(double wave, double tth, double om,
|
||||
double chi, double phi)
|
||||
{
|
||||
MATRIX res, rot, dum, z;
|
||||
double dTh;
|
||||
|
||||
dTh = (tth/2.)/PIR;
|
||||
res = mat_creat(3,1,ZERO_MATRIX);
|
||||
res[0][0] = (2.*sin(dTh)*cos(dTh))/wave;
|
||||
res[1][0] = (-2. *sin(dTh)*sin(dTh))/wave;
|
||||
|
||||
/* undo omega rotation */
|
||||
rot = phimat(om);
|
||||
dum = mat_tran(rot);
|
||||
mat_free(rot);
|
||||
z = mat_mul(dum,res);
|
||||
mat_free(dum);
|
||||
mat_free(res);
|
||||
|
||||
/* result is now z */
|
||||
|
||||
}
|
||||
|
46
d_mod.c
Normal file
46
d_mod.c
Normal file
@ -0,0 +1,46 @@
|
||||
#include "f2c.h"
|
||||
|
||||
#ifdef KR_headers
|
||||
#ifdef IEEE_drem
|
||||
double drem();
|
||||
#else
|
||||
double floor();
|
||||
#endif
|
||||
double d_mod(x,y) doublereal *x, *y;
|
||||
#else
|
||||
#ifdef IEEE_drem
|
||||
double drem(double, double);
|
||||
#else
|
||||
#undef abs
|
||||
#include "math.h"
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
#endif
|
||||
double d_mod(doublereal *x, doublereal *y)
|
||||
#endif
|
||||
{
|
||||
#ifdef IEEE_drem
|
||||
double xa, ya, z;
|
||||
if ((ya = *y) < 0.)
|
||||
ya = -ya;
|
||||
z = drem(xa = *x, ya);
|
||||
if (xa > 0) {
|
||||
if (z < 0)
|
||||
z += ya;
|
||||
}
|
||||
else if (z > 0)
|
||||
z -= ya;
|
||||
return z;
|
||||
#else
|
||||
double quotient;
|
||||
if( (quotient = *x / *y) >= 0)
|
||||
quotient = floor(quotient);
|
||||
else
|
||||
quotient = -floor(-quotient);
|
||||
return(*x - (*y) * quotient );
|
||||
#endif
|
||||
}
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
18
d_sign.c
Normal file
18
d_sign.c
Normal file
@ -0,0 +1,18 @@
|
||||
#include "f2c.h"
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#ifdef KR_headers
|
||||
double d_sign(a,b) doublereal *a, *b;
|
||||
#else
|
||||
double d_sign(doublereal *a, doublereal *b)
|
||||
#endif
|
||||
{
|
||||
double x;
|
||||
x = (*a >= 0 ? *a : - *a);
|
||||
return( *b >= 0 ? x : -x);
|
||||
}
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
293
danu.c
Normal file
293
danu.c
Normal file
@ -0,0 +1,293 @@
|
||||
/*-----------------------------------------------------------------------
|
||||
D A T A N U M B E R
|
||||
|
||||
Implementation file for the data number module.
|
||||
|
||||
Mark Koennecke, Juli 1997
|
||||
|
||||
Copyright:
|
||||
|
||||
Labor fuer Neutronenstreuung
|
||||
Paul Scherrer Institut
|
||||
CH-5423 Villigen-PSI
|
||||
|
||||
|
||||
The authors hereby grant permission to use, copy, modify, distribute,
|
||||
and license this software and its documentation for any purpose, provided
|
||||
that existing copyright notices are retained in all copies and that this
|
||||
notice is included verbatim in any distributions. No written agreement,
|
||||
license, or royalty fee is required for any of the authorized uses.
|
||||
Modifications to this software may be copyrighted by their authors
|
||||
and need not follow the licensing terms described here, provided that
|
||||
the new terms are clearly indicated on the first page of each file where
|
||||
they apply.
|
||||
|
||||
IN NO EVENT SHALL THE AUTHORS OR DISTRIBUTORS BE LIABLE TO ANY PARTY
|
||||
FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
|
||||
ARISING OUT OF THE USE OF THIS SOFTWARE, ITS DOCUMENTATION, OR ANY
|
||||
DERIVATIVES THEREOF, EVEN IF THE AUTHORS HAVE BEEN ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
THE AUTHORS AND DISTRIBUTORS SPECIFICALLY DISCLAIM ANY WARRANTIES,
|
||||
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT. THIS SOFTWARE
|
||||
IS PROVIDED ON AN "AS IS" BASIS, AND THE AUTHORS AND DISTRIBUTORS HAVE
|
||||
NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR
|
||||
MODIFICATIONS.
|
||||
----------------------------------------------------------------------------*/
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <time.h>
|
||||
#include <assert.h>
|
||||
#include "fortify.h"
|
||||
#include "conman.h"
|
||||
#include "obdes.h"
|
||||
#include "danu.h"
|
||||
|
||||
/* ------------------ the data structure ----------------------------------*/
|
||||
typedef struct __DataNumber {
|
||||
pObjectDescriptor pDes;
|
||||
char *pFileName;
|
||||
} DataNumber;
|
||||
/*-------------------------------------------------------------------------*/
|
||||
pDataNumber CreateDataNumber(char *pFileName)
|
||||
{
|
||||
pDataNumber pNew = NULL;
|
||||
FILE *fd = NULL;
|
||||
|
||||
pNew = (pDataNumber)malloc(sizeof(DataNumber));
|
||||
if(!pNew)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
memset(pNew,0,sizeof(DataNumber));
|
||||
|
||||
pNew->pDes = CreateDescriptor("DataNumber");
|
||||
if(!pNew->pDes)
|
||||
{
|
||||
free(pNew);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* check filename */
|
||||
fd = fopen(pFileName,"r");
|
||||
if(!fd)
|
||||
{
|
||||
printf("Serious error: cannot open file for Data Number!!!!\n");
|
||||
printf("I continue, but you should not write data files!\n");
|
||||
pNew->pFileName = strdup("default.num");
|
||||
return pNew;
|
||||
}
|
||||
fclose(fd);
|
||||
pNew->pFileName = strdup(pFileName);
|
||||
return pNew;
|
||||
}
|
||||
/*--------------------------------------------------------------------------*/
|
||||
void DeleteDataNumber(void *pData)
|
||||
{
|
||||
pDataNumber self = NULL;
|
||||
|
||||
self = (pDataNumber)pData;
|
||||
assert(self);
|
||||
|
||||
if(self->pDes)
|
||||
{
|
||||
DeleteDescriptor(self->pDes);
|
||||
}
|
||||
if(self->pFileName)
|
||||
{
|
||||
free(self->pFileName);
|
||||
}
|
||||
free(self);
|
||||
}
|
||||
/*-------------------------------------------------------------------------*/
|
||||
int IncrementDataNumber(pDataNumber self, int *iYear)
|
||||
{
|
||||
FILE *fd = NULL;
|
||||
int iNum;
|
||||
time_t iTime;
|
||||
struct tm *psTime;
|
||||
|
||||
/* open file */
|
||||
fd = fopen(self->pFileName,"r");
|
||||
if(!fd)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
/* get and increment number */
|
||||
fscanf(fd,"%d",&iNum);
|
||||
iNum++;
|
||||
fclose(fd);
|
||||
|
||||
/* reopen for rewriting */
|
||||
fd = fopen(self->pFileName,"w");
|
||||
if(fd == NULL)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* write file and leave */
|
||||
fprintf(fd," %d \n",iNum);
|
||||
fprintf(fd,"NEVER, EVER modify or delete this file\n");
|
||||
fprintf(fd,"You'll risk eternal damnation and a reincarnation as a cockroach!|n");
|
||||
fclose(fd);
|
||||
|
||||
/* get year */
|
||||
iTime = time(NULL);
|
||||
psTime = localtime(&iTime);
|
||||
*iYear = psTime->tm_year + 1900;
|
||||
|
||||
return iNum;
|
||||
}
|
||||
/*-------------------------------------------------------------------------*/
|
||||
int DecrementDataNumber(pDataNumber self)
|
||||
{
|
||||
FILE *fd = NULL;
|
||||
int iNum;
|
||||
|
||||
/* open file */
|
||||
fd = fopen(self->pFileName,"r");
|
||||
if(!fd)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
/* get and decrement number */
|
||||
fscanf(fd,"%d",&iNum);
|
||||
iNum--;
|
||||
if(iNum < 0)
|
||||
iNum = 0;
|
||||
fclose(fd);
|
||||
|
||||
/* reopen for rewriting */
|
||||
fd = fopen(self->pFileName,"w");
|
||||
|
||||
/* write file and leave */
|
||||
fprintf(fd," %d \n",iNum);
|
||||
fprintf(fd,"NEVER, EVER modify or delete this file\n");
|
||||
fprintf(fd,"You'll risk eternal damnation and a reincarnation as a cockroach!|n");
|
||||
fclose(fd);
|
||||
|
||||
return iNum;
|
||||
}
|
||||
/*-------------------------------------------------------------------------*/
|
||||
int DNWrapper(SConnection *pCon, SicsInterp *pSics, void *pData,
|
||||
int argc, char *argv[])
|
||||
{
|
||||
pDataNumber self = NULL;
|
||||
FILE *fd = NULL;
|
||||
int iNum, iYear;
|
||||
char pBueffel[512];
|
||||
|
||||
self = (pDataNumber)pData;
|
||||
assert(self);
|
||||
assert(pCon);
|
||||
|
||||
argtolower(argc,argv);
|
||||
if(argc < 2) /* value request */
|
||||
{
|
||||
fd = fopen(self->pFileName,"r");
|
||||
if(!fd)
|
||||
{
|
||||
sprintf(pBueffel,"ERROR: cannot open file %s",self->pFileName);
|
||||
SCWrite(pCon,pBueffel,eError);
|
||||
return 0;
|
||||
}
|
||||
fscanf(fd,"%d",&iNum);
|
||||
fclose(fd);
|
||||
sprintf(pBueffel,"%s = %d",argv[0],iNum);
|
||||
SCWrite(pCon,pBueffel,eValue);
|
||||
return 1;
|
||||
}
|
||||
|
||||
if(strcmp(argv[1],"incr") == 0)
|
||||
{
|
||||
iNum = IncrementDataNumber(self,&iYear);
|
||||
if(iNum > 0)
|
||||
{
|
||||
SCSendOK(pCon);
|
||||
return 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
sprintf(pBueffel,"ERROR: cannot increment %s",argv[0]);
|
||||
SCWrite(pCon,pBueffel,eError);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
sprintf(pBueffel,"ERROR: unknown command %s supplied to %s",
|
||||
argv[1], argv[0]);
|
||||
SCWrite(pCon,pBueffel,eError);
|
||||
return 0;
|
||||
}
|
||||
/*------------------------------------------------------------------------*/
|
||||
int DEWrapper(SConnection *pCon, SicsInterp *pSics, void *pData,
|
||||
int argc, char *argv[])
|
||||
{
|
||||
pDataNumber self = NULL;
|
||||
int iNum;
|
||||
char pBueffel[512];
|
||||
|
||||
self = (pDataNumber)pData;
|
||||
assert(self);
|
||||
assert(pCon);
|
||||
|
||||
if(SCMatchRights(pCon,usMugger))
|
||||
{
|
||||
DecrementDataNumber(self);
|
||||
SCWrite(pCon,"Data file killed",eWarning);
|
||||
return 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
SCWrite(pCon,"ERROR: you are not authorized to kill data files",
|
||||
eError);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
int DNFactory(SConnection *pCon, SicsInterp *pSics, void *pData,
|
||||
int argc, char *argv[])
|
||||
{
|
||||
pDataNumber self = NULL;
|
||||
char pBueffel[512];
|
||||
int iRet;
|
||||
|
||||
if(argc < 3)
|
||||
{
|
||||
SCWrite(pCon,
|
||||
"ERROR: not enough arguments provided to make DataNumber",eError);
|
||||
return 0;
|
||||
}
|
||||
|
||||
self = CreateDataNumber(argv[2]);
|
||||
if(!self)
|
||||
{
|
||||
SCWrite(pCon,"ERROR: no memory to create data number",eError);
|
||||
return 0;
|
||||
}
|
||||
|
||||
iRet = AddCommand(pSics, argv[1],DNWrapper, DeleteDataNumber, self);
|
||||
if(!iRet)
|
||||
{
|
||||
sprintf(pBueffel,"ERROR: duplicate command %s not created",argv[1]);
|
||||
SCWrite(pCon,pBueffel,eError);
|
||||
return 0;
|
||||
}
|
||||
iRet = AddCommand(pSics,"killfile",DEWrapper,NULL, self);
|
||||
if(!iRet)
|
||||
{
|
||||
sprintf(pBueffel,"ERROR: duplicate command %s not created",argv[1]);
|
||||
SCWrite(pCon,pBueffel,eError);
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
3
danu.dat
Normal file
3
danu.dat
Normal file
@ -0,0 +1,3 @@
|
||||
286
|
||||
NEVER, EVER modify or delete this file
|
||||
You'll risk eternal damnation and a reincarnation as a cockroach!|n
|
41
danu.h
Normal file
41
danu.h
Normal file
@ -0,0 +1,41 @@
|
||||
|
||||
#line 53 "danu.w"
|
||||
|
||||
/*-----------------------------------------------------------------------
|
||||
D A T A N U M B E R
|
||||
|
||||
A module to provide a unique data number for data file writing.
|
||||
|
||||
Mark Koennecke, Juli 1997
|
||||
|
||||
copyright: see implementation file.
|
||||
|
||||
---------------------------------------------------------------------------*/
|
||||
#ifndef SICSDATANUMBER
|
||||
#define SICSDATANUMBER
|
||||
|
||||
|
||||
#line 15 "danu.w"
|
||||
|
||||
typedef struct __DataNumber *pDataNumber;
|
||||
|
||||
pDataNumber CreateDataNumber(char *pFilename);
|
||||
void DeleteDataNumber(void *pData);
|
||||
|
||||
int IncrementDataNumber(pDataNumber self, int *iYear);
|
||||
|
||||
int DecrementDataNumber(pDataNumber self);
|
||||
|
||||
int DNWrapper(SConnection *pCon, SicsInterp *pSics, void *pData,
|
||||
int argc, char *argv[]);
|
||||
|
||||
int DEWrapper(SConnection *pCon, SicsInterp *pSics, void *pData,
|
||||
int argc, char *argv[]);
|
||||
|
||||
int DNFactory(SConnection *pCon, SicsInterp *pSics, void *pData,
|
||||
int argc, char *argv[]);
|
||||
|
||||
#line 67 "danu.w"
|
||||
|
||||
|
||||
#endif
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user