- SICS cleanup: removed unused code

This commit is contained in:
koennecke
2010-01-19 12:55:41 +00:00
parent 85070df11d
commit b67bd76031
29 changed files with 11 additions and 8325 deletions

962
amor2t.c
View File

@ -1,962 +0,0 @@
/*---------------------------------------------------------------------------
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
Introduced DIAFLAG to switch off diaphragm calculation.
Mark Koennecke, July 2005
---------------------------------------------------------------------------*/
#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 14
#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 void clearRunFlags(pAmor2T self)
{
int i;
for (i = 0; i < MAXMOT; i++) {
self->toStart[i].pMot = NULL;
}
}
/*---------------------------------------------------------------------*/
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;
clearRunFlags(self);
/* 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;
if (ObVal(self->aParameter, DIAFLAG) > .0) {
/* 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);
/* 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);
#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;
/* 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);
/* 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;
#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;
clearRunFlags(self);
/* 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;
/* calculation for diaphragm 5 */
if (ObVal(self->aParameter, DIAFLAG) > .0) {
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);
}
#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 < MAXMOT; i++) {
if (self->toStart[i].pMot == NULL) {
continue;
}
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 < MAXMOT; i++) {
if (self->toStart[i].pMot == NULL) {
continue;
}
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 < MAXMOT; i++) {
if (self->toStart[i].pMot == NULL) {
continue;
}
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 < MAXMOT; i++) {
if (self->toStart[i].pMot == NULL) {
continue;
}
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 < MAXMOT; i++) {
if (self->toStart[i].pMot == NULL) {
continue;
}
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 < MAXMOT; i++) {
if (self->toStart[i].pMot == NULL) {
continue;
}
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));
fprintf(fd, "%s diaflag %f \n", name, ObVal(self->aParameter, DIAFLAG));
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);
sprintf(pBueffel,
"%s.diaflag %f \n", name, ObVal(self->aParameter, DIAFLAG));
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];
const 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, (char *) 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, (char *) 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, (char *) 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, (char *) 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, (char *) 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, (char *) 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, (char *) 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, (char *) 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, (char *) 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, (char *) 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, (char *) 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, (char *) 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);
ObParInit(pNew->aParameter, DIAFLAG, "diaflag", 1., 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;
}
}

View File

@ -1,21 +0,0 @@
/*-------------------------------------------------------------------------
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[]);
#endif

View File

@ -1,56 +0,0 @@
/*--------------------------------------------------------------------------
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
/* flag for diaphragms */
#define DIAFLAG 13
typedef struct {
pMotor pMot;
char pName[80];
float fTarget;
}MotEntry, *pMotEntry;
typedef struct __AMOR2T {
pObjectDescriptor pDes;
pIDrivable pDriv;
pMotor aEngine[MAXMOT];
MotEntry toStart[MAXMOT];
ObPar *aParameter;
}Amor2T;

View File

@ -1,205 +0,0 @@
\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.
\item[run] A flag which determines if this motor is to be run.
\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@ 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@@$\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@/* flag for diaphragms */@\\
\mbox{}\verb@#define DIAFLAG 13@\\
\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}

151
amor2t.w
View File

@ -1,151 +0,0 @@
\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.
\item[run] A flag which determines if this motor is to be run.
\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];
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[]);
@}
@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
/* flag for diaphragms */
#define DIAFLAG 13
@<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
@}

View File

@ -1,136 +0,0 @@
/*-------------------------------------------------------------------------
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);
}
return 1;
}
/*--------------------------------------------------------------------*/
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);
AppendScanVar(pVar, fVal);
sprintf(pItem, " %-9.9s", pVar->Name);
strcat(pHead, pItem);
sprintf(pItem, " %-9.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, " %-14ld", 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, " %-14ld", 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, " %-11ld", sCount.Monitors[3]);
strcat(pStatus, pItem);
strcat(pHead, "Monitor2 ");
sprintf(pItem, " %-11ld", sCount.Monitors[4]);
strcat(pStatus, pItem);
strcat(pHead, "Time ");
sprintf(pItem, " %-5.1f", sCount.fTime);
strcat(pStatus, pItem);
/* write progress */
strcat(pHead, "\n");
strcat(pStatus, "\n");
SCWrite(self->pCon, pHead, eLog);
SCWrite(self->pCon, pStatus, eLog);
/* 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;
return 1;
}

View File

@ -1,14 +0,0 @@
/*-----------------------------------------------------------------------
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

View File

@ -1,57 +0,0 @@
\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
@}

View File

@ -1,265 +0,0 @@
/*--------------------------------------------------------------------------
D I L L U D R I V
This file contains the implementation of a driver for the Oxford
Instruments dillution cryostat using the CC0-510/AVSI temperature
controller.
Mark Koennecke, October 1997
Copyright: see copyright.h
----------------------------------------------------------------------------*/
#include <string.h>
#include <stdlib.h>
#include <time.h>
#include <math.h>
#include <assert.h>
#include <fortify.h>
#include <conman.h>
#include <servlog.h>
#include <fortify.h>
#include "evdriver.h"
#include "hardsup/dillutil.h"
#include "hardsup/el734_def.h"
#include "hardsup/el734fix.h"
#include "dilludriv.h"
/*-----------------------------------------------------------------------*/
typedef struct {
pDILLU pData;
char *pHost;
int iPort;
int iChannel;
int iLastError;
char *pTranslationFile;
} DILLUDriv, *pDILLUDriv;
/*----------------------------------------------------------------------------*/
static int GetDILLUPos(pEVDriver self, float *fPos)
{
pDILLUDriv pMe = NULL;
int iRet;
assert(self);
pMe = (pDILLUDriv) self->pPrivate;
assert(pMe);
iRet = DILLU_Read(&pMe->pData, fPos);
if (iRet != 1) {
pMe->iLastError = iRet;
return 0;
}
if ((*fPos < 0) || (*fPos > 1000)) {
*fPos = -999.;
return 0;
}
return 1;
}
/*----------------------------------------------------------------------------*/
static int DILLURun(pEVDriver self, float fVal)
{
pDILLUDriv pMe = NULL;
int iRet;
assert(self);
pMe = (pDILLUDriv) self->pPrivate;
assert(pMe);
iRet = DILLU_Set(&pMe->pData, fVal);
if (iRet != 1) {
pMe->iLastError = iRet;
return 0;
}
return 1;
}
/*--------------------------------------------------------------------------*/
static int DILLUError(pEVDriver self, int *iCode, char *error, int iErrLen)
{
pDILLUDriv pMe = NULL;
assert(self);
pMe = (pDILLUDriv) self->pPrivate;
assert(pMe);
*iCode = pMe->iLastError;
DILLU_Error2Text(&pMe->pData, pMe->iLastError, error, iErrLen);
return 1;
}
/*--------------------------------------------------------------------------*/
static int DILLUSend(pEVDriver self, char *pCommand, char *pReply,
int iLen)
{
pDILLUDriv pMe = NULL;
int iRet;
assert(self);
pMe = (pDILLUDriv) self->pPrivate;
assert(pMe);
iRet = DILLU_Send(&pMe->pData, pCommand, pReply, iLen);
if (iRet != 1) {
pMe->iLastError = iRet;
return 0;
}
return 1;
}
/*--------------------------------------------------------------------------*/
static int DILLUInit(pEVDriver self)
{
pDILLUDriv pMe = NULL;
int iRet;
assert(self);
pMe = (pDILLUDriv) self->pPrivate;
assert(pMe);
pMe->pData = NULL;
iRet = DILLU_Open(&pMe->pData, pMe->pHost, pMe->iPort, pMe->iChannel,
0, pMe->pTranslationFile);
if (iRet != 1) {
pMe->iLastError = iRet;
return 0;
}
DILLU_Config(&pMe->pData, 1000);
return 1;
}
/*--------------------------------------------------------------------------*/
static int DILLUClose(pEVDriver self)
{
pDILLUDriv pMe = NULL;
int iRet;
assert(self);
pMe = (pDILLUDriv) self->pPrivate;
assert(pMe);
DILLU_Close(&pMe->pData);
return 1;
}
/*---------------------------------------------------------------------------*/
static int DILLUFix(pEVDriver self, int iError)
{
pDILLUDriv pMe = NULL;
int iRet;
assert(self);
pMe = (pDILLUDriv) 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:
DILLUClose(self);
iRet = DILLUInit(self);
if (iRet) {
return DEVREDO;
} else {
return DEVFAULT;
}
break;
/* handable protocoll errors */
case EL734__BAD_TMO:
return DEVREDO;
break;
case DILLU__NODILLFILE:
case DILLU__ERRORTABLE:
case DILLU__READONLY:
case DILLU__OUTOFRANGE:
case DILLU__BADMALLOC:
case DILLU__FILENOTFOUND:
return DEVFAULT;
case DILLU__BADREAD:
case DILLU__SILLYANSWER:
return DEVREDO;
default:
return DEVFAULT;
break;
}
return DEVFAULT;
}
/*--------------------------------------------------------------------------*/
static int DILLUHalt(pEVDriver * self)
{
assert(self);
return 1;
}
/*------------------------------------------------------------------------*/
void KillDILLU(void *pData)
{
pDILLUDriv pMe = NULL;
pMe = (pDILLUDriv) pData;
assert(pMe);
if (pMe->pHost) {
free(pMe->pHost);
}
if (pMe->pTranslationFile) {
free(pMe->pTranslationFile);
}
free(pMe);
}
/*------------------------------------------------------------------------*/
pEVDriver CreateDILLUDriv(int argc, char *argv[])
{
pEVDriver pNew = NULL;
pDILLUDriv pSim = NULL;
/* check for arguments */
if (argc < 3) {
return NULL;
}
pNew = CreateEVDriver(argc, argv);
pSim = (pDILLUDriv) malloc(sizeof(DILLUDriv));
memset(pSim, 0, sizeof(DILLUDriv));
if (!pNew || !pSim) {
return NULL;
}
pNew->pPrivate = pSim;
pNew->KillPrivate = KillDILLU;
/* initalise pDILLUDriver */
pSim->iLastError = 0;
pSim->pHost = strdup(argv[0]);
pSim->iPort = atoi(argv[1]);
pSim->iChannel = atoi(argv[2]);
pSim->pTranslationFile = strdup(argv[3]);
/* initialise function pointers */
pNew->SetValue = DILLURun;
pNew->GetValue = GetDILLUPos;
pNew->Send = DILLUSend;
pNew->GetError = DILLUError;
pNew->TryFixIt = DILLUFix;
pNew->Init = DILLUInit;
pNew->Close = DILLUClose;
return pNew;
}

View File

@ -1,15 +0,0 @@
/*------------------------------------------------------------------------
D I L L U D R I V
A SICS driver for thedillution cryostat using the CCO-510/AVSI
controller.
Mark Koennecke, October 1997
copyright: see copyright.h
---------------------------------------------------------------------------*/
#ifndef DILLUDRIV
#define DILLUDRIV
pEVDriver CreateDILLUDriv(int argc, char *argv[]);
#endif

54
dmc.c
View File

@ -1,54 +0,0 @@
/*-------------------------------------------------------------------------
D M C
this modules purpose is solely to initialise the commands specific to
the powder diffractometer DMC.
Mark Koenencke, March 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 "fortify.h"
#include "conman.h"
#include "obdes.h"
#include "napi.h"
#include "nxdata.h"
#include "dmc.h"
int InitDmc(SConnection * pCon, SicsInterp * pSics, void *pData,
int argc, char *argv[])
{
AddCommand(pSics, "StoreData", SNStoreDMC, NULL, NULL);
return 1;
}

19
dmc.h
View File

@ -1,19 +0,0 @@
/*-------------------------------------------------------------------------
D M C
this modules purpose is solely to initialise the commands specific to
the powder diffractometer DMC.
Mark Koenencke, March 1997
copyright: see implementation file.
--------------------------------------------------------------------------*/
#ifndef SICSDMC
#define SICSDMC
int InitDmc(SConnection * pCon, SicsInterp * pSics, void *pData,
int argc, char *argv[]);
#endif

27
dmc.w
View File

@ -1,27 +0,0 @@
\subsection{DMC module}
This module initialises all DMC specific commands. Currently there is only
one: StoreData. This does not do much, it is just here as a container for
things to come.
@d Protos @{
int InitDmc(SConnection *pCon, SicsInterp *pSics, void *pData,
int argc, char *argv[]);
@}
@o dmc.h @{
/*-------------------------------------------------------------------------
D M C
this modules purpose is solely to initialise the commands specific to
the powder diffractometer DMC.
Mark Koenencke, March 1997
copyright: see implementation file.
--------------------------------------------------------------------------*/
#ifndef SICSDMC
#define SICSDMC
@< Protos @>
#endif
@}

1076
fowrite.c

File diff suppressed because it is too large Load Diff

View File

@ -1,20 +0,0 @@
/*--------------------------------------------------------------------------
F O W R I T E
fowrite is an object for writing FOCUS data files.
copyright: see copyright.h
Mark Koennecke, November 1998
----------------------------------------------------------------------------*/
#ifndef FOWRITE
#define FOWRITE
int FoInstall(SConnection * pCon, SicsInterp * pSics,
void *pData, int argc, char *argv[]);
int FoAction(SConnection * pCon, SicsInterp * pSics,
void *pData, int argc, char *argv[]);
#endif

View File

@ -9,18 +9,18 @@
.tc.c:
tjxp $*.tc $*.c
OBJ=psi.o buffer.o ruli.o dmc.o nxsans.o nextrics.o sps.o pimotor.o \
pipiezo.o sanswave.o faverage.o fowrite.o amor2t.o nxamor.o \
OBJ=psi.o buffer.o ruli.o sps.o pimotor.o \
pipiezo.o sanswave.o faverage.o \
amorstat.o tasinit.o ptasdrive.o tasutil.o tasscan.o swmotor.o \
polterwrite.o ecb.o frame.o el734driv.o el734dc.o ecbdriv.o \
ecbcounter.o el737driv.o sinqhmdriv.o tdchm.o velodorn.o \
velodornier.o docho.o sanscook.o tecsdriv.o itc4driv.o itc4.o\
bruker.o ltc11.o A1931.o dilludriv.o eurodriv.o slsmagnet.o \
el755driv.o amorscan.o serial.o scontroller.o t_update.o \
bruker.o ltc11.o A1931.o eurodriv.o slsmagnet.o \
el755driv.o serial.o scontroller.o t_update.o \
t_rlp.o t_conv.o el737hpdriv.o dornier2.o el734hp.o \
el737hpv2driv.o swmotor2.o tricssupport.o amorcomp.o \
$(MZOBJ) amordrive.o amorset.o tcpdornier.o sinqhttp.o\
dgrambroadcast.o sinq.o tabledrive.o tcpdocho.o julcho.o \
$(MZOBJ) amordrive.o amorset.o sinqhttp.o\
dgrambroadcast.o sinq.o tabledrive.o julcho.o \
ritastorage.o poldizug.o audinelib.o delcam.o el737hpdrivsps.o \
rebin.o sanslirebin.o lmd200.o slsvme.o julprot.o sinqhttpprot.o \
pmacprot.o pfeifferprot.o termprot.o phytron.o autowin.o

View File

@ -7,12 +7,13 @@
# Mark Koennecke, December 2009
#==========================================================================
include ../linux_def
#include ../linux_def
include ../sllinux_def
CC = gcc
CFLAGS = -I$(HDFROOT)/include -DHDF4 -DHDF5 $(NI) -I$(TCLINC) -Ihardsup \
-I.. -MMD -DCYGNUS -DNONINTF -g $(DFORTIFY) \
-I.. -I. -MMD -DCYGNUS -DNONINTF -g $(DFORTIFY) \
-Wall -Wno-unused -Wunused-value -Wno-comment -Wno-switch -Werror
EXTRA=nintf.o

1369
nextrics.c

File diff suppressed because it is too large Load Diff

View File

@ -1,38 +0,0 @@
/*----------------------------------------------------------------------------
N E X T R I C S
An object for writing NeXus data files for the four ciclre diffractometer
TRICS at PSI. Can be used as basis for writing files for other four
circles equiped with a PSD as well.
copyright: see copyright.h
Mark Koennecke, April 1998
------------------------------------------------------------------------------*/
#ifndef NEXTRICS
#define NEXTRICS
#include <danu.h>
typedef struct __NexTrics *pNexTrics;
/*----------------------------- live & death -----------------------------*/
pNexTrics CreateNexTrics(pDataNumber pNum, char *pRoot, char *pDict,
SicsInterp * pSics);
void DeleteNexTrics(void *pData);
int NexTricsFactory(SConnection * pCon, SicsInterp * pSics, void *pData,
int argc, char *argv[]);
/*----------------------------- interaction ------------------------------*/
int StartFile(pNexTrics self, SConnection * pCon);
int ReopenFile(pNexTrics self, char *filename);
int DumpFrame(pNexTrics self, SConnection * pCon);
int NexTricsAction(SConnection * pCon, SicsInterp * pSics, void *pData,
int argc, char *argv[]);
#endif

775
nxamor.c
View File

@ -1,775 +0,0 @@
/*--------------------------------------------------------------------------
N X A M O R
Routines for writing NeXus files for the reflectometer AMOR at PSI.
copyright: see copyright.h
Mark Koennecke, September 1999
Updated, Mark Koennecke, August 2001
Updated to store TOF-monitor, Mark Koennecke, September 2002
--------------------------------------------------------------------------*/
#include <stdlib.h>
#include <assert.h>
#include "fortify.h"
#include "sics.h"
#include "nxdict.h"
#include "nxutil.h"
#include "scan.h"
#include "scan.i"
#include "HistMem.h"
#include "counter.h"
#include "nxamor.h"
#include "obpar.h"
#include "motor.h"
#include "status.h"
#define MAXMOT 13 /* must be same as in amor2t.c */
#include "amor2t.i"
#include "amor2t.h"
/* some defines for some names */
static char AMORDICT[1024] = "/home/amor/amor_sics/amor.dic";
#define INSTNAME "AMOR at SINQ, PSI"
#define SOURCENAME "Spallation source SINQ"
#define SOURCETYPE "Continous flux spallation source"
#define CHOPPERNAME "Dornier Chopper System"
/*
The rough size of each detector chunk to write in TOF mode
(currently 16MB)
#define TOFBLOCK 8192000
#define TOFBLOCK 16384000
*/
#define TOFBLOCK 65536000
/*
a pointer to amor2t which we need for a couple of parameters
*/
pAmor2T pAmor = NULL;
/*
if to save psd data in TOF mode or not. This is in order to save time
when measureing TOF with a single detector only.
*/
static int psdSave = 1;
/*------------------------------------------------------------------------*/
static void WriteDiaphragm(NXhandle hfil, NXdict hdict, int i,
SConnection * pCon)
{
char pThing[30];
sprintf(pThing, "d%1.1dt", i);
SNXSPutMotor(pServ->pSics, pCon, hfil, hdict, pThing, pThing);
sprintf(pThing, "d%1.1db", i);
SNXSPutMotor(pServ->pSics, pCon, hfil, hdict, pThing, pThing);
sprintf(pThing, "d%1.1dl", i);
SNXSPutMotor(pServ->pSics, pCon, hfil, hdict, pThing, pThing);
sprintf(pThing, "d%1.1dr", i);
SNXSPutMotor(pServ->pSics, pCon, hfil, hdict, pThing, pThing);
}
/*----------------------------------------------------------------------*/
int WriteAmorHeader(char *file, SConnection * pCon)
{
NXhandle hfil;
NXdict hdict;
int iRet;
char pBueffel[512], pThing[80];
CounterMode eMode;
CommandList *pCom = NULL;
float fVal;
/* open files */
NXsetcache(TOFBLOCK);
iRet = NXopen(file, NXACC_CREATE5, &hfil);
if (iRet != NX_OK) {
snprintf(pBueffel, 511, "ERROR: cannot open file %s for writing",
file);
SCWrite(pCon, pBueffel, eError);
return 0;
}
iRet = NXDinitfromfile(AMORDICT, &hdict);
if (iRet != NX_OK) {
snprintf(pBueffel, 511, "ERROR: cannot open dictionary file %s",
AMORDICT);
SCWrite(pCon, pBueffel, eError);
return 0;
}
snprintf(pBueffel, 511, "Writing to: %s", file);
SCWrite(pCon, pBueffel, eWarning);
/* put some global information */
SNXSPutGlobals(hfil, file, "AMOR", pCon);
SNXSPutVariable(pServ->pSics, pCon, hfil, hdict, "etitle", "title");
SNXFormatTime(pBueffel, 512);
NXDputalias(hfil, hdict, "estart", pBueffel);
/* instrument vGroup */
NXDputalias(hfil, hdict, "iname", INSTNAME);
/* source */
NXDputalias(hfil, hdict, "sname", SOURCENAME);
NXDputalias(hfil, hdict, "stype", SOURCETYPE);
/* chopper */
NXDputalias(hfil, hdict, "cname", CHOPPERNAME);
SNXSPutDrivable(pServ->pSics, pCon, hfil, hdict, "chopperspeed", "crot");
SNXSPutDrivable(pServ->pSics, pCon, hfil, hdict, "chopper1phase",
"cphase1");
SNXSPutDrivable(pServ->pSics, pCon, hfil, hdict, "chopper2phase",
"cphase2");
SNXSPutVariable(pServ->pSics, pCon, hfil, hdict, "crot",
"chopperrotation");
/* frame overlap mirror */
SNXSPutVariable(pServ->pSics, pCon, hfil, hdict, "fomname", "fomname");
SNXSPutVariable(pServ->pSics, pCon, hfil, hdict, "fodist", "fomdist");
SNXSPutMotor(pServ->pSics, pCon, hfil, hdict, "fomh", "ftz");
SNXSPutMotor(pServ->pSics, pCon, hfil, hdict, "fomom", "fom");
/* first Diaphragm */
WriteDiaphragm(hfil, hdict, 1, pCon);
sprintf(pThing, "d%1.1ddist", 1);
SNXSPutVariable(pServ->pSics, pCon, hfil, hdict, pThing, pThing);
/* polarizing, monochromating mirror */
SNXSPutVariable(pServ->pSics, pCon, hfil, hdict, "polname", "polname");
SNXSPutVariable(pServ->pSics, pCon, hfil, hdict, "poldist", "poldist");
SNXSPutMotor(pServ->pSics, pCon, hfil, hdict, "polz", "moz");
SNXSPutMotor(pServ->pSics, pCon, hfil, hdict, "polom", "mom");
SNXSPutMotor(pServ->pSics, pCon, hfil, hdict, "poly", "mty");
SNXSPutMotor(pServ->pSics, pCon, hfil, hdict, "polzom", "mtz");
/* second Diaphragm */
WriteDiaphragm(hfil, hdict, 2, pCon);
sprintf(pThing, "d%1.1ddist", 2);
SNXSPutVariable(pServ->pSics, pCon, hfil, hdict, pThing, pThing);
/* third Diaphragm */
WriteDiaphragm(hfil, hdict, 3, pCon);
sprintf(pThing, "d%1.1ddist", 3);
SNXSPutVariable(pServ->pSics, pCon, hfil, hdict, pThing, pThing);
/* sample table */
SNXSPutVariable(pServ->pSics, pCon, hfil, hdict, "saname", "sample");
SNXSPutVariable(pServ->pSics, pCon, hfil, hdict, "stdist", "sampledist");
SNXSPutMotor(pServ->pSics, pCon, hfil, hdict, "somheight", "stz");
SNXSPutMotor(pServ->pSics, pCon, hfil, hdict, "schi", "sch");
SNXSPutMotor(pServ->pSics, pCon, hfil, hdict, "somega", "som");
SNXSPutMotor(pServ->pSics, pCon, hfil, hdict, "stheight", "soz");
fVal = ObVal(pAmor->aParameter, PARDH);
NXDputalias(hfil, hdict, "baseheight", &fVal);
/* fourth Diaphragm */
WriteDiaphragm(hfil, hdict, 4, pCon);
fVal = ObVal(pAmor->aParameter, PARDD4);
NXDputalias(hfil, hdict, "d4dist", &fVal);
fVal = ObVal(pAmor->aParameter, PARD4H);
NXDputalias(hfil, hdict, "d4base", &fVal);
/* analyzer */
SNXSPutVariable(pServ->pSics, pCon, hfil, hdict, "anname", "ananame");
SNXSPutVariable(pServ->pSics, pCon, hfil, hdict, "andist", "anadist");
SNXSPutMotor(pServ->pSics, pCon, hfil, hdict, "anoz", "atz");
SNXSPutMotor(pServ->pSics, pCon, hfil, hdict, "anom", "aom");
SNXSPutMotor(pServ->pSics, pCon, hfil, hdict, "antz", "aoz");
fVal = ObVal(pAmor->aParameter, PARADIS);
NXDputalias(hfil, hdict, "adis", &fVal);
fVal = ObVal(pAmor->aParameter, PARANA);
NXDputalias(hfil, hdict, "abase", &fVal);
/* fifth Diaphragm!!!!!!!!! */
WriteDiaphragm(hfil, hdict, 5, pCon);
fVal = ObVal(pAmor->aParameter, PARDD5);
NXDputalias(hfil, hdict, "d5dist", &fVal);
fVal = ObVal(pAmor->aParameter, PARD5H);
NXDputalias(hfil, hdict, "d5base", &fVal);
/* counting data */
pCom = FindCommand(pServ->pSics, "counter");
if (pCom) {
if (pCom->pData) {
eMode = GetCounterMode((pCounter) pCom->pData);
if (eMode == eTimer) {
strcpy(pBueffel, "timer");
} else {
strcpy(pBueffel, "monitor");
}
NXDputalias(hfil, hdict, "cnmode", pBueffel);
fVal = GetCounterPreset((pCounter) pCom->pData);
NXDputalias(hfil, hdict, "cnpreset", &fVal);
}
} else {
SCWrite(pCon, "WARNING: failed to find counter!", eWarning);
}
NXclose(&hfil);
NXDclose(hdict, NULL);
return 1;
}
/*------------------------------------------------------------------------*/
int WriteAmorScan(char *file, SConnection * pCon, pScanData pScan)
{
NXhandle hfil;
NXdict hdict;
int iRet, i;
char pBueffel[512], pDefinition[1024];
CommandList *pCom = NULL;
float fVal;
float *fAxis = NULL;
long *lData = NULL;
int *iData = NULL;
/* open files */
iRet = NXopen(file, NXACC_RDWR, &hfil);
if (iRet != NX_OK) {
sprintf(pBueffel, "ERROR: cannot open file %s for writing", file);
SCWrite(pCon, pBueffel, eError);
return 0;
}
iRet = NXDinitfromfile(AMORDICT, &hdict);
if (iRet != NX_OK) {
sprintf(pBueffel, "ERROR: cannot open dictionary file %s", AMORDICT);
SCWrite(pCon, pBueffel, eError);
return 0;
}
/* allocate memory for writing scan data */
fAxis = (float *) malloc(pScan->iNP * sizeof(float));
lData = (long *) malloc(pScan->iNP * sizeof(long));
iData = (int *) malloc(pScan->iNP * sizeof(int));
if ((!fAxis) || (!lData) || (!iData)) {
SCWrite(pCon, "ERROR: out of memory in WriteAmorScan", eError);
return 0;
}
memset(fAxis, 0, pScan->iNP * sizeof(float));
memset(lData, 0, pScan->iNP * sizeof(long));
memset(iData, 0, pScan->iNP * sizeof(int));
/* write scan variables */
for (i = 0; i < pScan->iScanVar; i++) {
/* build definition string */
NXDget(hdict, "scanroot", pBueffel, 512);
strcpy(pDefinition, pBueffel);
strcat(pDefinition, " ");
GetScanVarName(pScan, i, pBueffel, 512);
strcat(pDefinition, pBueffel);
sprintf(pBueffel, " -rank 1 -dim {%d} ", pScan->iNP);
strcat(pDefinition, pBueffel);
if (i == 0) {
strcat(pDefinition, " -attr {axis,1}");
}
/* get data and write */
GetScanVar(pScan, i, fAxis, pScan->iNP);
NXDputdef(hfil, hdict, pDefinition, fAxis);
if (i == 0) {
NXDget(hdict, "sdana", pBueffel, 512);
NXDdeflink(hfil, hdict, pBueffel, pDefinition);
}
}
/*
Write counted data: Here there is a convention which has to be
valid in amorscan as well: GetCounts gets the main detector.
GetMonitor 0 the second detector, GetMonitor 1 the first detector
other spin, GetMonitor 2, the second detector the other spin,
getMonitor 3, the first monitor, getMonitor 4 the second monitor
*/
sprintf(pBueffel, "%d", pScan->iNP);
NXDupdate(hdict, "scanlength", pBueffel);
GetScanCounts(pScan, lData, pScan->iNP);
for (i = 0; i < pScan->iNP; i++) {
iData[i] = (int) lData[i];
}
NXDputalias(hfil, hdict, "spinupup", iData);
NXDaliaslink(hfil, hdict, "sdana", "spinupup");
GetScanMonitor(pScan, 0, lData, pScan->iNP);
for (i = 0; i < pScan->iNP; i++) {
iData[i] = (int) lData[i];
}
NXDputalias(hfil, hdict, "spinuplo", iData);
NXDaliaslink(hfil, hdict, "sdana", "spinuplo");
/* monitors */
GetScanMonitor(pScan, 3, lData, pScan->iNP);
for (i = 0; i < pScan->iNP; i++) {
iData[i] = (int) lData[i];
}
NXDputalias(hfil, hdict, "smonitor1", iData);
GetScanMonitor(pScan, 4, lData, pScan->iNP);
for (i = 0; i < pScan->iNP; i++) {
iData[i] = (int) lData[i];
}
NXDputalias(hfil, hdict, "smonitor2", iData);
/* to be added: polarizing mode, possibly coz, cox, com etc. */
/* a few motors which may or may not be useful */
SNXSPutMotor(pServ->pSics, pCon, hfil, hdict, "sdetx", "cox");
SNXSPutMotor(pServ->pSics, pCon, hfil, hdict, "sdetom", "com");
SNXSPutMotor(pServ->pSics, pCon, hfil, hdict, "sdetheight", "coz");
/* close and go */
NXclose(&hfil);
NXDclose(hdict, NULL);
free(fAxis);
free(lData);
free(iData);
return 1;
}
/*-----------------------------------------------------------------------
WriteTOFDetector writes the histogram memory data in TOF mode. As
the histogram memory can become quite large at AMOR, the data is
read and stored in chunks if it is to big. All this is handled
in this routine.
-------------------------------------------------------------------------*/
static int WriteTOFDetector(char *name, pHistMem pHM, int *iDim,
NXhandle hfil, NXdict hdict,
SConnection * pCon)
{
int nChunk, chunkSize, iChunk[3], i, iStart[3], nTime, iRet;
long iLength;
HistInt *lData = NULL;
char pBueffel[132];
const float *fTime;
int start;
fTime = GetHistTimeBin(pHM, &nTime);
iDim[2] = nTime;
iLength = iDim[0] * iDim[1] * iDim[2];
if ((iLength * 4) < TOFBLOCK) {
sprintf(pBueffel, " -chunk {%d,%d,%d} ", iDim[0], iDim[1], iDim[2]);
NXDupdate(hdict, "chunk", pBueffel);
lData = (HistInt *) malloc(iLength * sizeof(HistInt));
if (!lData) {
SCWrite(pCon,
"ERROR: out of memory, failed to write histogram", eError);
SCSetInterrupt(pCon, eAbortBatch);
return 0;
}
memset(lData, 0, iLength * sizeof(HistInt));
iRet = GetHistogramDirect(pHM, pCon,
0, 0, iLength, lData,
iLength * sizeof(HistInt));
if (!iRet) {
SCWrite(pCon, "ERROR: failed to read Hm data", eError);
SCSetInterrupt(pCon, eAbortBatch);
free(lData);
return 0;
}
SicsWait(2);
NXDputalias(hfil, hdict, name, lData);
NXDputalias(hfil, hdict, "detchunk", iDim);
NXDaliaslink(hfil, hdict, "dana", name);
} else {
/*
implement chunked writing. We strive to write layers in Y. The
number of chunks needs to fulfill three conditions then:
- multiple of xSize* timeBin;
- close to TOFBLOCK in size
- divide Y without remainder.
*/
iChunk[0] = iDim[0];
iChunk[2] = iDim[2];
iChunk[1] = 1;
chunkSize = iDim[0] * iDim[2];
for (i = 1; i < 64; i++) {
if ((iDim[1] % i) == 0) {
if (i * chunkSize * sizeof(HistInt) < TOFBLOCK) {
iChunk[1] = i;
}
}
}
sprintf(pBueffel, "Segmented TOF data in %d chunks",
iDim[1] / iChunk[1]);
SCWrite(pCon, pBueffel, eWarning);
/*
now we have a chunkSize, lets go and write!
*/
NXDputalias(hfil, hdict, "detchunk", iChunk);
chunkSize = iChunk[1] * iChunk[0] * iChunk[2];
sprintf(pBueffel, " -chunk {%d,%d,%d} ", iChunk[0], iChunk[1],
iChunk[2]);
NXDupdate(hdict, "chunk", pBueffel);
lData = (HistInt *) malloc(chunkSize * sizeof(HistInt));
if (!lData) {
SCWrite(pCon, "ERROR: out of memory while writing TOF data", eError);
SCSetInterrupt(pCon, eAbortBatch);
return 0;
}
NXDopenalias(hfil, hdict, name);
for (i = 0; i < iDim[1] / iChunk[1]; i++) {
memset(lData, 0, chunkSize * sizeof(HistInt));
iRet = GetHistogramDirect(pHM, pCon,
0, i * chunkSize, (i + 1) * chunkSize,
lData, chunkSize * sizeof(HistInt));
if (!iRet) {
SCWrite(pCon, "ERROR: failed to read HM data", eError);
SCSetInterrupt(pCon, eAbortBatch);
free(lData);
return 0;
}
/*
yield a little in order to allow other clients to receive a
response. Also allow for interrupting.
*/
SicsWait(2);
iStart[0] = 0;
iStart[1] = i * iChunk[1];
iStart[2] = 0;
NXputslab(hfil, lData, iStart, iChunk);
sprintf(pBueffel, "Wrote chunk %d", i);
SCWrite(pCon, pBueffel, eWarning);
/*
yield a little in order to allow other clients to receive a
response. Also allow for interrupting.
*/
SicsWait(2);
}
/*
close groups till root
*/
NXclosedata(hfil);
NXclosegroup(hfil);
NXclosegroup(hfil);
NXclosegroup(hfil);
/*
make link
*/
NXDaliaslink(hfil, hdict, "dana", name);
NXDaliaslink(hfil, hdict, "dana", "detchunk");
}
if (lData)
free(lData);
return 1;
}
/*-----------------------------------------------------------------------*/
int WriteAmorTOF(char *file, SConnection * pCon, pHistMem pHM)
{
NXhandle hfil;
NXdict hdict;
int iRet, i, iLength;
char pBueffel[512];
float fVal, *fAxis = NULL, *fTime2 = NULL;
CommandList *pCom = NULL;
const float *fTime;
HistInt *lData = NULL, lVal;
int detxsize, detysize, iDim[MAXDIM];
/* open files */
iRet = NXopen(file, NXACC_RDWR, &hfil);
if (iRet != NX_OK) {
sprintf(pBueffel, "ERROR: cannot open file %s for writing", file);
SCWrite(pCon, pBueffel, eError);
return 0;
}
iRet = NXDinitfromfile(AMORDICT, &hdict);
if (iRet != NX_OK) {
sprintf(pBueffel, "ERROR: cannot open dictionary file %s", AMORDICT);
SCWrite(pCon, pBueffel, eError);
return 0;
}
/* a few motors which may or may not be useful */
SNXSPutMotor(pServ->pSics, pCon, hfil, hdict, "detx", "cox");
SNXSPutMotor(pServ->pSics, pCon, hfil, hdict, "detom", "com");
SNXSPutMotor(pServ->pSics, pCon, hfil, hdict, "detheight", "coz");
/* write counter related stuff */
pCom = FindCommand(pServ->pSics, "counter");
if (pCom) {
if (pCom->pData) {
fVal = GetCountTime((pCounter) pCom->pData, pCon);
NXDputalias(hfil, hdict, "cntime", &fVal);
/* the assignment of monitors has to be checked once
the Schlumpf is done
*/
lVal = GetMonitor((pCounter) pCom->pData, 1, pCon);
NXDputalias(hfil, hdict, "cnmon1", &lVal);
lVal = GetMonitor((pCounter) pCom->pData, 4, pCon);
NXDputalias(hfil, hdict, "cnmon2", &lVal);
}
} else {
SCWrite(pCon, "WARNING: failed to find counter!", eWarning);
}
/*
find dimensions of detector
*/
GetHistDim(pHM, iDim, &iLength);
detxsize = iDim[0];
detysize = iDim[1];
/* update detector size */
sprintf(pBueffel, "%d", detxsize);
NXDupdate(hdict, "detxsize", pBueffel);
sprintf(pBueffel, "%d", detysize);
NXDupdate(hdict, "detysize", pBueffel);
/* write two axis */
if (detxsize > detysize)
iLength = detxsize;
else
iLength = detysize;
fAxis = (float *) malloc(iLength * sizeof(float));
if (!fAxis) {
SCWrite(pCon, "ERROR: out of memory in WriteAmorTOF", eError);
return 0;
}
for (i = 0; i < detxsize; i++) {
fAxis[i] = (float) i;
}
NXDputalias(hfil, hdict, "detxx", fAxis);
for (i = 0; i < detysize; i++) {
fAxis[i] = (float) i;
}
NXDputalias(hfil, hdict, "dety", fAxis);
NXDaliaslink(hfil, hdict, "dana", "detxx");
NXDaliaslink(hfil, hdict, "dana", "dety");
free(fAxis);
/* add height and distances */
fVal = ObVal(pAmor->aParameter, PARDS);
NXDputalias(hfil, hdict, "detdist", &fVal);
fVal = ObVal(pAmor->aParameter, PARDDH);
NXDputalias(hfil, hdict, "detbase", &fVal);
/* deal with time binning */
fTime = GetHistTimeBin(pHM, &iLength);
iDim[2] = iLength;
fTime2 = (float *) malloc(iLength * sizeof(float));
if (fTime2) {
for (i = 0; i < iLength; i++) {
fTime2[i] = fTime[i] / 10.;
}
sprintf(pBueffel, "%d", iLength);
NXDupdate(hdict, "timebin", pBueffel);
NXDputalias(hfil, hdict, "dettime", fTime2);
NXDputalias(hfil, hdict, "singletime", fTime2);
NXDaliaslink(hfil, hdict, "dana", "dettime");
free(fTime2);
fTime2 = NULL;
} else {
SCWrite(pCon, "ERROR: out of memory while writing time binning",
eError);
SCSetInterrupt(pCon, eAbortBatch);
NXclose(&hfil);
NXDclose(hdict, NULL);
return 0;
}
/* finally get histogram */
if (iDim[2] == 2) { /* 2D data, no time binning on this detector */
iLength = detxsize * detysize;
lData = (HistInt *) malloc(iLength * sizeof(HistInt));
if (!lData) {
SCWrite(pCon,
"ERROR: out of memory, failed to write histogram", eError);
NXclose(&hfil);
NXDclose(hdict, NULL);
SCSetInterrupt(pCon, eAbortBatch);
return 0;
}
memset(lData, 0, iLength * sizeof(HistInt));
iRet = GetHistogram(pHM, pCon, 0, 0, iLength,
lData, iLength * sizeof(HistInt));
if (!iRet) {
SCWrite(pCon, "ERROR: failed to read HM", eError);
SCSetInterrupt(pCon, eAbortBatch);
NXclose(&hfil);
NXDclose(hdict, NULL);
return 0;
}
NXDputalias(hfil, hdict, "spinup2d", lData);
NXDaliaslink(hfil, hdict, "dana", "spinup2d");
} else {
if (psdSave) {
iRet = WriteTOFDetector("spinup", pHM, iDim, hfil, hdict, pCon);
if (!iRet) {
NXclose(&hfil);
NXDclose(hdict, NULL);
return 0;
}
} else {
SCWrite(pCon, "PSD writing supressed!", eWarning);
}
#define MAXSINGLE 3
/*
now get and write single detectors
*/
iLength = iDim[0] * iDim[1] * iDim[2];
lData = (HistInt *) malloc(MAXSINGLE * iDim[2] * sizeof(HistInt));
if (!lData) {
SCWrite(pCon, "ERROR: out of memory while writing single detectors",
eError);
SCSetInterrupt(pCon, eAbortBatch);
NXclose(&hfil);
NXDclose(hdict, NULL);
return 0;
} else {
memset(lData, 0, MAXSINGLE * iDim[2] * sizeof(HistInt));
iRet = GetHistogramDirect(pHM, pCon, 0, iLength,
iLength + MAXSINGLE * iDim[2],
lData,
MAXSINGLE * iDim[2] * sizeof(HistInt));
if (!iRet) {
SCWrite(pCon, "ERROR: failed to read single detector HM data",
eError);
SCSetInterrupt(pCon, eAbortBatch);
free(lData);
NXclose(&hfil);
NXDclose(hdict, NULL);
return 0;
}
NXDputalias(hfil, hdict, "singleup", lData);
NXDaliaslink(hfil, hdict, "singledana", "singleup");
NXDaliaslink(hfil, hdict, "singledana", "singletime");
/*
the TOF monitor
*/
NXDputalias(hfil, hdict, "singletofmon", lData + 2 * iDim[2]);
NXDaliaslink(hfil, hdict, "dana", "singletofmon");
NXDaliaslink(hfil, hdict, "singledana", "singletofmon");
}
}
/* to do: add polarizing code */
if (lData)
free(lData);
NXclose(&hfil);
NXDclose(hdict, NULL);
return 1;
}
/*-----------------------------------------------------------------------*/
static pHistMem pMeme = NULL;
int AmorStore(SConnection * pCon, SicsInterp * pSics, void *pData,
int argc, char *argv[])
{
char pBueffel[512], *pFile = NULL;
int iRet, iFlag;
Status oldStatus;
/*
if arguments, check for psdsave
*/
if (argc > 1) {
strtolower(argv[1]);
if (strcmp(argv[1], "psdsave") == 0) {
if (argc > 2) {
psdSave = atof(argv[2]);
SCSendOK(pCon);
return 1;
} else {
sprintf(pBueffel, "storeamor.psdSave = %d", psdSave);
SCWrite(pCon, pBueffel, eValue);
return 1;
}
}
}
pFile = SNXMakeFileName(pSics, pCon);
sprintf(pBueffel, "Writing file %s .....", pFile);
SCWrite(pCon, pBueffel, eWarning);
oldStatus = GetStatus();
SetStatus(eWriting);
LockDeviceExecutor(pServ->pExecutor);
iRet = WriteAmorHeader(pFile, pCon);
if (iRet) {
iRet = WriteAmorTOF(pFile, pCon, pMeme);
}
SetStatus(oldStatus);
UnlockDeviceExecutor(pServ->pExecutor);
free(pFile);
SCSendOK(pCon);
return iRet;
}
/*---------------------------------------------------------------------*/
int AmorStoreMake(SConnection * pCon, SicsInterp * pSics, void *pData,
int argc, char *argv[])
{
CommandList *pCom = NULL;
char pBueffel[512];
int iRet;
if (argc < 3) {
SCWrite(pCon,
"ERROR: insufficient number of arguments to AmorStoreMake",
eError);
return 0;
}
/* we need a parameter which is the name of the histogram memory */
pCom = FindCommand(pServ->pSics, argv[1]);
if (!pCom) {
sprintf(pBueffel, "ERROR: Histogram memory %s NOT found", argv[1]);
SCWrite(pCon, pBueffel, eError);
return 0;
}
if (!pCom->pData) {
sprintf(pBueffel, "ERROR: Histogram memory %s NOT found", argv[1]);
SCWrite(pCon, pBueffel, eError);
return 0;
}
pMeme = (pHistMem) pCom->pData;
/* we need another parameter which is the name of the
2theta calculation module
*/
pCom = FindCommand(pServ->pSics, argv[2]);
if (!pCom) {
sprintf(pBueffel, "ERROR: amor2T module %s NOT found", argv[2]);
SCWrite(pCon, pBueffel, eError);
return 0;
}
if (!pCom->pData) {
sprintf(pBueffel, "ERROR: amor2t module %s NOT found", argv[2]);
SCWrite(pCon, pBueffel, eError);
return 0;
}
pAmor = (pAmor2T) pCom->pData;
if (argc > 3) {
strncpy(AMORDICT, argv[3], 1023);
}
/* install command */
iRet = AddCommand(pSics, "storeamor", AmorStore, NULL, NULL);
if (!iRet) {
sprintf(pBueffel, "ERROR: duplicate command amorstore NOT created");
SCWrite(pCon, pBueffel, eError);
return 0;
}
return 1;
}

View File

@ -1,29 +0,0 @@
/*------------------------------------------------------------------------
N X A M O R
Some routines for writing NeXus files for the reflectometer AMOR at
SINQ.
copyright: see copyright.h
Mark Koennecke, September 1999
----------------------------------------------------------------------*/
#ifndef NXAMOR
#define NXAMOR
#include <scan.h>
#include <HistMem.h>
int WriteAmorHeader(char *file, SConnection * pCon);
int WriteAmorScan(char *file, SConnection * pCon, pScanData pScan);
int WriteAmorTOF(char *file, SConnection * pCon, pHistMem pHM);
int AmorStore(SConnection * pCon, SicsInterp * pSics, void *pData,
int argc, char *argv[]);
int AmorStoreMake(SConnection * pCon, SicsInterp * pSics, void *pData,
int argc, char *argv[]);
#endif

View File

@ -1,71 +0,0 @@
\subsection{AMOR NeXus Routines}
This module implements a few functions for writing NeXus data files
for the reflectoemter AMOR at SINQ, PSI. Nothing very exciting here:
this is mostly boring repetetive code. Three functions are defined:
\begin{flushleft} \small
\begin{minipage}{\linewidth} \label{scrap1}
$\langle$namor {\footnotesize ?}$\rangle\equiv$
\vspace{-1ex}
\begin{list}{}{} \item
\mbox{}\verb@@\\
\mbox{}\verb@ int WriteAmorHeader(char *file, SConnection *pCon);@\\
\mbox{}\verb@@\\
\mbox{}\verb@ int WriteAmorScan(char *file, SConnection *pCon, pScanData pScan);@\\
\mbox{}\verb@@\\
\mbox{}\verb@ int WriteAmorTOF(char *file, SConnection *pCon, pHistMem pHM);@\\
\mbox{}\verb@@\\
\mbox{}\verb@ int AmorStore(SConnection *pCon, SicsInterp *pSics, void *pData,@\\
\mbox{}\verb@ int argc, char *argv[]);@\\
\mbox{}\verb@ int AmorStoreMake(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[WriteAmorHeader] writes all the AMOR header information and the
zillions of motors.
\item[WriteAmorScan] writes data when AMOR was operated in scanning
mode.
\item[WriteAmorTOF] writes AMOR data when used with the PSD in
time-of-flight mode.
\item[AmorStore] the command function implementing the storeamor
command.
\item[AmorStoreMake] the initialization function which creates the
storeamor command.
\end{description}
\begin{flushleft} \small
\begin{minipage}{\linewidth} \label{scrap2}
\verb@"nxamor.h"@ {\footnotesize ? }$\equiv$
\vspace{-1ex}
\begin{list}{}{} \item
\mbox{}\verb@@\\
\mbox{}\verb@/*------------------------------------------------------------------------@\\
\mbox{}\verb@ N X A M O R@\\
\mbox{}\verb@@\\
\mbox{}\verb@ Some routines for writing NeXus files for the reflectometer AMOR at@\\
\mbox{}\verb@ SINQ.@\\
\mbox{}\verb@ @\\
\mbox{}\verb@ copyright: see copyright.h@\\
\mbox{}\verb@@\\
\mbox{}\verb@ Mark Koennecke, September 1999@\\
\mbox{}\verb@----------------------------------------------------------------------*/@\\
\mbox{}\verb@#ifndef NXAMOR@\\
\mbox{}\verb@#define NXAMOR@\\
\mbox{}\verb@#include <scan.h>@\\
\mbox{}\verb@#include <HistMem.h>@\\
\mbox{}\verb@@$\langle$namor {\footnotesize ?}$\rangle$\verb@@\\
\mbox{}\verb@#endif@\\
\mbox{}\verb@@$\diamond$
\end{list}
\vspace{-2ex}
\end{minipage}\\[4ex]
\end{flushleft}

View File

@ -1,50 +0,0 @@
\subsection{AMOR NeXus Routines}
This module implements a few functions for writing NeXus data files
for the reflectoemter AMOR at SINQ, PSI. Nothing very exciting here:
this is mostly boring repetetive code. Three functions are defined:
@d namor @{
int WriteAmorHeader(char *file, SConnection *pCon);
int WriteAmorScan(char *file, SConnection *pCon, pScanData pScan);
int WriteAmorTOF(char *file, SConnection *pCon, pHistMem pHM);
int AmorStore(SConnection *pCon, SicsInterp *pSics, void *pData,
int argc, char *argv[]);
int AmorStoreMake(SConnection *pCon, SicsInterp *pSics, void *pData,
int argc, char *argv[]);
@}
\begin{description}
\item[WriteAmorHeader] writes all the AMOR header information and the
zillions of motors.
\item[WriteAmorScan] writes data when AMOR was operated in scanning
mode.
\item[WriteAmorTOF] writes AMOR data when used with the PSD in
time-of-flight mode.
\item[AmorStore] the command function implementing the storeamor
command.
\item[AmorStoreMake] the initialization function which creates the
storeamor command.
\end{description}
@o nxamor.h @{
/*------------------------------------------------------------------------
N X A M O R
Some routines for writing NeXus files for the reflectometer AMOR at
SINQ.
copyright: see copyright.h
Mark Koennecke, September 1999
----------------------------------------------------------------------*/
#ifndef NXAMOR
#define NXAMOR
#include <scan.h>
#include <HistMem.h>
@<namor@>
#endif
@}

705
nxsans.c
View File

@ -1,705 +0,0 @@
/*--------------------------------------------------------------------------
N X S A N S
a module of utility functions which serve to write Nexus
data files for SANS.
Mark Koennecke, August 1997 - November 1998
Updated to support the larger detector resolution and possible
TOF and stroboscopic modes, Mark Koennecke, February 2001
Added additional monitors for stroboscopic gummi mode,
Mark Koennecke, September 2002
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 <time.h>
#include "fortify.h"
#include "sics.h"
#include "sicsvar.h"
#include "napi.h"
#include "nxdict.h"
#include "modriv.h"
#include "motor.h"
#include "nxutil.h"
#include "nxdata.h"
#include "countdriv.h"
#include "counter.h"
#include "danu.h"
#include "HistMem.h"
#include "velo.h"
#include "sps.h"
#include "udpquieck.h"
#include "mumo.h"
#include "sanswave.h"
#define HISTNAME "banana"
#define SAMPLETABLE "sampletable"
static int gummiFlag = 0; /* a flag indicating stroboscopic, or gummi mode */
/*-----------------------------------------------------------------------*/
static void SNError(void *pData, char *text)
{
SConnection *pCon;
assert(pData);
pCon = (SConnection *) pData;
SCWrite(pCon, text, eError);
}
/*-------------------------------------------------------------------------*/
NXhandle SNXStartSANS(SConnection * pCon, SicsInterp * pSics)
{
NXhandle pFile = NULL;
char *filename = NULL;
pSicsVariable pVar = NULL;
int iStat;
char pBueffel[512];
/* get a filename */
filename = SNXMakeFileName(pSics, pCon);
if (!filename) {
return NULL;
}
/* create a Nexus file */
NXopen(filename, NXACC_CREATE, &pFile);
if (!pFile) {
SCWrite(pCon, "ERROR: cannot create data file ", eError);
return NULL;
}
/* tell Uwe User what we are doing */
sprintf(pBueffel, "Writing %s ......", filename);
SCWrite(pCon, pBueffel, eWarning);
/* store global attributes */
iStat = NXputattr(pFile, "file_name", filename,
strlen(filename) + 1, NX_CHAR);
if (iStat == NX_ERROR) {
SCWrite(pCon, "ERROR: writing file_name attribute to Nexus file",
eError);
}
/* throw away filename, no longer needed */
free(filename);
/* write creation time */
SNXFormatTime(pBueffel, 512);
iStat = NXputattr(pFile, "file_time", pBueffel,
strlen(pBueffel) + 1, NX_CHAR);
if (iStat == NX_ERROR) {
SCWrite(pCon, "ERROR: writing date attribute to Nexus file", eError);
}
pVar = FindVariable(pSics, "instrument");
if (pVar) {
iStat = NXputattr(pFile, "instrument", pVar->text,
strlen(pVar->text) + 1, NX_CHAR);
if (iStat == NX_ERROR) {
SCWrite(pCon, "ERROR: writing instrument attribute to Nexus file",
eError);
}
}
pVar = NULL;
pVar = FindVariable(pSics, "user");
if (pVar) {
iStat = NXputattr(pFile, "owner", pVar->text,
strlen(pVar->text) + 1, NX_CHAR);
if (iStat == NX_ERROR) {
SCWrite(pCon, "ERROR: writing owner attribute to Nexus file",
eError);
}
}
pVar = NULL;
pVar = FindVariable(pSics, "adress");
if (pVar) {
iStat = NXputattr(pFile, "owner_adress", pVar->text,
strlen(pVar->text) + 1, NX_CHAR);
if (iStat == NX_ERROR) {
SCWrite(pCon, "ERROR: writing owner_adress attribute to Nexus file",
eError);
}
}
pVar = NULL;
pVar = FindVariable(pSics, "phone");
if (pVar) {
iStat = NXputattr(pFile, "owner_telephone_number", pVar->text,
strlen(pVar->text) + 1, NX_CHAR);
if (iStat == NX_ERROR) {
SCWrite(pCon,
"ERROR: writing owner_telephone_number attribute to Nexus file",
eError);
}
}
pVar = NULL;
pVar = FindVariable(pSics, "fax");
if (pVar) {
iStat = NXputattr(pFile, "owner_fax_number", pVar->text,
strlen(pVar->text) + 1, NX_CHAR);
if (iStat == NX_ERROR) {
SCWrite(pCon,
"ERROR: writing owner_fax_number attribute to Nexus file",
eError);
}
}
pVar = NULL;
pVar = FindVariable(pSics, "email");
if (pVar) {
iStat = NXputattr(pFile, "owner_email", pVar->text,
strlen(pVar->text) + 1, NX_CHAR);
if (iStat == NX_ERROR) {
SCWrite(pCon, "ERROR: writing owner_email attribute to Nexus file",
eError);
}
}
pVar = NULL;
return pFile;
}
/*--------------------------------------------------------------------------*/
int SNMakeSANS(SConnection * pCon, SicsInterp * pSics, NXdict pDict)
{
NXhandle Nfil = NULL;
char pBueffel[512];
float fVal;
int iVal, iSet;
int iAxis[256];
int i, iRet;
long lVal;
HistInt *lData = NULL;
const float *fTime = NULL;
CommandList *pCom = NULL;
pHistMem self = NULL;
CounterMode eMode;
pVelSel pVelo = NULL;
pSPS pSiem = NULL;
const char *pNamPos = NULL;
float fRot, fTilt, fLambda;
pDummy pDum;
pIDrivable pDrive;
int iDim[MAXDIM], nDim, histSize, iStart;
/* start file */
Nfil = SNXStartSANS(pCon, pSics);
if (!Nfil) {
return 0;
}
/*
during all this, no extensive error checking will be done,
just write the error and continue, save at all cost
*/
/* put all this global information */
SNXSPutVariable(pSics, pCon, Nfil, pDict, "etitle", "title");
SNXSPutVariable(pSics, pCon, Nfil, pDict, "etime", "starttime");
SNXFormatTime(pBueffel, 511);
NXDputalias(Nfil, pDict, "endtime", pBueffel);
strcpy(pBueffel, "SANS at SINQ,PSI");
NXDputalias(Nfil, pDict, "iname", pBueffel);
strcpy(pBueffel, "SINQ at PSI,Villigen, Switzerland");
NXDputalias(Nfil, pDict, "sname", pBueffel);
strcpy(pBueffel, "Spallation");
NXDputalias(Nfil, pDict, "stype", pBueffel);
/* put the velocity selector data */
NXDputalias(Nfil, pDict, "vname", "Dornier Velocity Selector");
fRot = 0.;
fTilt = 0.;
pCom = FindCommand(pSics, "nvs");
if (pCom) {
pVelo = (pVelSel) pCom->pData;
if (!pVelo) {
SCWrite(pCon, "WARNING: Velocity Selctor not found", eWarning);
}
iRet = VSGetRotation(pVelo, &fVal);
if (!iRet) {
SCWrite(pCon, "WARNING: failed to read velocity selector speed",
eWarning);
} else {
fRot = fVal;
NXDputalias(Nfil, pDict, "vrot", &fVal);
}
iRet = VSGetTilt(pVelo, &fTilt);
if (!iRet) {
SCWrite(pCon, "WARNING: failed to read velocity selector tilt angle",
eWarning);
}
}
SNXSPutMotor(pSics, pCon, Nfil, pDict, "vtilt", "tilt");
CalculateLambda(fRot, fTilt, &fLambda);
NXDputalias(Nfil, pDict, "vlambda", &fLambda);
/* monitor 1 */
pCom = FindCommand(pSics, HISTNAME);
if (!pCom) {
sprintf(pBueffel, "ERROR: histogram memory %s not found", HISTNAME);
SCWrite(pCon, pBueffel, eError);
return 0;
}
self = (pHistMem) pCom->pData;
assert(self);
lVal = GetHistMonitor(self, 0, pCon);
iVal = (int) lVal;
NXDputalias(Nfil, pDict, "m1counts", &iVal);
lVal = GetHistMonitor(self, 4, pCon);
iVal = (int) lVal;
NXDputalias(Nfil, pDict, "pbcounts", &iVal);
/* the collimator */
pCom = FindCommand(pSics, "sps2");
if (!pCom) {
SCWrite(pCon, "WARNING: sps-unit for reading collimator NOT found",
eWarning);
} else {
pSiem = (pSPS) pCom->pData;
if (!pSiem) {
SCWrite(pCon, "WARNING: sps-unit for reading collimator NOT found",
eWarning);
} else {
iRet = SPSGetSANS(pSiem, &fVal);
if (iRet <= 0) {
SCWrite(pCon, "WARNING: Failed to read SPS", eWarning);
} else {
NXDputalias(Nfil, pDict, "colli", &fVal);
}
/* as we got the sps, get the attenuator as well */
iRet = SPSGetStatus(pSiem, 38, &iSet);
if (iRet < 0) {
SCWrite(pCon, "WARNING: Failed to read SPS", eWarning);
} else {
if (iSet) {
iVal = 0;
}
}
iRet = SPSGetStatus(pSiem, 39, &iSet);
if (iRet < 0) {
SCWrite(pCon, "WARNING: Failed to read SPS", eWarning);
} else {
if (iSet) {
iVal = 1;
}
}
iRet = SPSGetStatus(pSiem, 40, &iSet);
if (iRet < 0) {
SCWrite(pCon, "WARNING: Failed to read SPS", eWarning);
} else {
if (iSet) {
iVal = 2;
}
}
iRet = SPSGetStatus(pSiem, 41, &iSet);
if (iRet < 0) {
SCWrite(pCon, "WARNING: Failed to read SPS", eWarning);
} else {
if (iSet) {
iVal = 3;
}
}
iRet = SPSGetStatus(pSiem, 42, &iSet);
if (iRet < 0) {
SCWrite(pCon, "WARNING: Failed to read SPS", eWarning);
} else {
if (iSet) {
iVal = 4;
}
}
iRet = SPSGetStatus(pSiem, 43, &iSet);
if (iRet < 0) {
SCWrite(pCon, "WARNING: Failed to read SPS", eWarning);
} else {
if (iSet) {
iVal = 5;
}
}
NXDputalias(Nfil, pDict, "atti", &iVal);
}
}
/* the sample */
SNXSPutVariable(pSics, pCon, Nfil, pDict, "san", "sample");
SNXSPutVariable(pSics, pCon, Nfil, pDict, "saenv", "environment");
SNXSPutMotor(pSics, pCon, Nfil, pDict, "sax", "sax");
SNXSPutMotor(pSics, pCon, Nfil, pDict, "say", "say");
SNXSPutMotor(pSics, pCon, Nfil, pDict, "saz", "saz");
SNXSPutMotorNull(pSics, pCon, Nfil, pDict, "saxn", "sax");
SNXSPutMotorNull(pSics, pCon, Nfil, pDict, "sayn", "say");
SNXSPutMotorNull(pSics, pCon, Nfil, pDict, "sazn", "saz");
/* goniometer */
SNXSPutMotor(pSics, pCon, Nfil, pDict, "gphi", "gphi");
SNXSPutMotor(pSics, pCon, Nfil, pDict, "gtheta", "gtheta");
SNXSPutMotorNull(pSics, pCon, Nfil, pDict, "gphin", "gphi");
SNXSPutMotorNull(pSics, pCon, Nfil, pDict, "gthetan", "gtheta");
SNXSPutMotor(pSics, pCon, Nfil, pDict, "saom", "som");
SNXSPutMotorNull(pSics, pCon, Nfil, pDict, "saomn", "som");
SNXSPutMotor(pSics, pCon, Nfil, pDict, "sapos", "spos");
SNXSPutMotorNull(pSics, pCon, Nfil, pDict, "saposn", "spos");
pCom = FindCommand(pSics, SAMPLETABLE);
if (pCom) {
if (pCom->pData) {
pNamPos = FindNamPos((pMulMot) pCom->pData, pCon);
if (pNamPos) {
NXDputalias(Nfil, pDict, "sanampos", (char *) pNamPos);
}
}
}
/* write sample environment here */
pCom = FindCommand(pSics, "temperature");
if (pCom) {
pDum = (pDummy) pCom->pData;
pDrive = pDum->pDescriptor->GetInterface(pDum, DRIVEID);
if (pDrive) { /* a proper environment device */
fVal = pDrive->GetValue(pDum, pCon);
NXDputalias(Nfil, pDict, "satemp", &fVal);
}
}
pCom = FindCommand(pSics, "magnet");
if (pCom) {
pDum = (pDummy) pCom->pData;
pDrive = pDum->pDescriptor->GetInterface(pDum, DRIVEID);
if (pDrive) { /* a proper environment device */
fVal = pDrive->GetValue(pDum, pCon);
NXDputalias(Nfil, pDict, "samag", &fVal);
}
}
/* magnet motors. This instrument has motorized magnets crawling
through the hall */
pCom = FindCommand(pSics, "mom");
if (pCom) {
SNXSPutMotor(pSics, pCon, Nfil, pDict, "mom", "mom");
}
pCom = FindCommand(pSics, "mz");
if (pCom) {
SNXSPutMotor(pSics, pCon, Nfil, pDict, "mz", "mz");
}
/* put Beam Stop */
/* read beamstop number */
iVal = 1;
pCom = FindCommand(pSics, "sps1");
if (!pCom) {
SCWrite(pCon, "WARNING: sps-unit for reading beamstop NOT found",
eWarning);
} else {
pSiem = (pSPS) pCom->pData;
if (!pSiem) {
SCWrite(pCon, "WARNING: sps-unit for reading beamstop NOT found",
eWarning);
} else {
iRet = SPSGetStatus(pSiem, 8, &iSet);
if (iRet < 0) {
SCWrite(pCon, "WARNING: Failed to read SPS", eWarning);
} else {
if (iSet) {
iVal = 2;
}
}
iRet = SPSGetStatus(pSiem, 9, &iSet);
if (iRet < 0) {
SCWrite(pCon, "WARNING: Failed to read SPS", eWarning);
} else {
if (iSet) {
iVal = 3;
}
}
iRet = SPSGetStatus(pSiem, 10, &iSet);
if (iRet < 0) {
SCWrite(pCon, "WARNING: Failed to read SPS", eWarning);
} else {
if (iSet) {
iVal = 4;
}
}
}
}
NXDputalias(Nfil, pDict, "bst", &iVal);
SNXSPutMotor(pSics, pCon, Nfil, pDict, "vsx", "BeamStopX");
SNXSPutMotor(pSics, pCon, Nfil, pDict, "vsy", "BeamStopY");
SNXSPutMotorNull(pSics, pCon, Nfil, pDict, "vsxnull", "BeamStopX");
SNXSPutMotorNull(pSics, pCon, Nfil, pDict, "vsynull", "BeamStopY");
/* what this is all about: the detector */
SNXSPutMotor(pSics, pCon, Nfil, pDict, "ddx", "DetectorX");
SNXSPutMotor(pSics, pCon, Nfil, pDict, "ddy", "DetectorY");
SNXSPutMotorNull(pSics, pCon, Nfil, pDict, "ddxn", "DetectorX");
SNXSPutMotorNull(pSics, pCon, Nfil, pDict, "ddyn", "DetectorY");
SNXSPutMotor(pSics, pCon, Nfil, pDict, "ddchi", "DetectorRotation");
pCom = FindCommand(pSics, HISTNAME);
if (!pCom) {
sprintf(pBueffel, "ERROR: histogram memory %s not found", HISTNAME);
SCWrite(pCon, pBueffel, eError);
return 0;
}
self = (pHistMem) pCom->pData;
assert(self);
eMode = GetHistCountMode(self);
if (eMode == eTimer) {
strcpy(pBueffel, "Timer");
} else {
strcpy(pBueffel, "Monitor");
}
NXDputalias(Nfil, pDict, "ddm", pBueffel);
fVal = GetHistPreset(self);
NXDputalias(Nfil, pDict, "ddp", &fVal);
lVal = GetHistMonitor(self, 1, pCon);
iVal = (int) lVal;
NXDputalias(Nfil, pDict, "ddmo", &iVal);
fVal = GetHistCountTime(self, pCon);
NXDputalias(Nfil, pDict, "ddtime", &fVal);
/*
Deal with actual histogram. Due to stroboscopic modes and the
new detector electronics we need to find out about the size
ourselves now. And possibly write time binning information.
*/
GetHistDim(self, iDim, &nDim);
/*
handle time binning
*/
fTime = GetHistTimeBin(self, &iVal);
if (iVal > 2) {
NXDputalias(Nfil, pDict, "ddtb", (void *) fTime);
nDim = 3;
iDim[2] = iVal;
}
histSize = 1;
for (i = 0; i < nDim; i++) {
histSize *= iDim[i];
}
lData = (HistInt *) malloc(histSize * sizeof(HistInt));
if (!lData) {
SCWrite(pCon,
"ERROR: out of memory, FAILED to store data, file corrupt",
eError);
NXclose(&Nfil);
return 0;
}
GetHistogram(self, pCon, 0, 0, histSize, lData,
histSize * sizeof(HistInt));
sprintf(pBueffel, " %d ", iDim[0]);
NXDupdate(pDict, "dim1", pBueffel);
sprintf(pBueffel, " %d ", iDim[1]);
NXDupdate(pDict, "dim2", pBueffel);
if (nDim == 2) {
sprintf(pBueffel, " -rank 2 -dim {%d,%d} ", iDim[0], iDim[1]);
NXDupdate(pDict, "countdim", pBueffel);
} else if (nDim == 3) {
sprintf(pBueffel, " -rank 3 -dim {%d,%d,%d} ", iDim[0], iDim[1],
iDim[2]);
NXDupdate(pDict, "countdim", pBueffel);
sprintf(pBueffel, " %d ", iDim[2]);
NXDupdate(pDict, "timedim", pBueffel);
}
NXDputalias(Nfil, pDict, "ddcounts", lData);
free(lData);
/* write x and y axis */
for (i = 0; i < iDim[0]; i++) {
iAxis[i] = i;
}
NXDputalias(Nfil, pDict, "ddcx", iAxis);
for (i = 0; i < iDim[1]; i++) {
iAxis[i] = i;
}
NXDputalias(Nfil, pDict, "ddcy", iAxis);
/*
write gummi monitors when apropriate
*/
if (nDim == 3 && gummiFlag != 0) {
histSize = 3 * iDim[2];
lData = (HistInt *) malloc(histSize * sizeof(HistInt));
if (lData == NULL) {
SCWrite(pCon, "WARNING: failed to allocate memory for monitors",
eWarning);
} else {
memset(lData, 0, histSize * sizeof(HistInt));
iStart = iDim[0] * iDim[1] * iDim[2];
GetHistogramDirect(self, pCon, 0, iStart, iStart + histSize,
lData, histSize * sizeof(HistInt));
NXDputalias(Nfil, pDict, "gummimon1", lData);
NXDputalias(Nfil, pDict, "gummimon2", lData + iDim[2]);
NXDputalias(Nfil, pDict, "gummimon3", lData + 2 * iDim[2]);
free(lData);
}
}
/*
write detector temperature. It is a hot one............
*/
if (pSiem) {
iRet = SPSGetADC(pSiem, 1, &iVal);
if (iRet) {
fVal = iVal / 269.9;
NXDputalias(Nfil, pDict, "ddtemp", &fVal);
}
}
/* do the linking in th data vgroup */
NXDaliaslink(Nfil, pDict, "dan", "ddcounts");
NXDaliaslink(Nfil, pDict, "dan", "ddcx");
NXDaliaslink(Nfil, pDict, "dan", "ddcy");
NXDaliaslink(Nfil, pDict, "dan", "ddmo");
NXDaliaslink(Nfil, pDict, "dan", "vlambda");
if (nDim == 3) {
NXDaliaslink(Nfil, pDict, "dan", "ddtb");
}
/* send quieck message for automatic copying */
i = 131;
iVal = NX_CHAR;
NXgetattr(Nfil, "file_name", pBueffel, &i, &iVal);
SendQuieck(QUIECK, pBueffel);
/* close this and go ............. */
NXclose(&Nfil);
return 1;
}
/*------------------- The Mechanics for setting Up ------------------------*/
typedef struct {
pObjectDescriptor pDes;
NXdict pDict;
} DictStruct, *pDictStruct;
/*-------------------------------------------------------------------------*/
static pDictStruct MakeDictStruct(char *pFile)
{
pDictStruct pNew = NULL;
int iRet;
pNew = (pDictStruct) malloc(sizeof(DictStruct));
if (!pNew) {
return NULL;
}
memset(pNew, 0, sizeof(DictStruct));
pNew->pDes = CreateDescriptor("StoreData");
if (!pNew->pDes) {
free(pNew);
return NULL;
}
iRet = NXDinitfromfile(pFile, &(pNew->pDict));
if (iRet != NX_OK) {
DeleteDescriptor(pNew->pDes);
free(pNew);
return NULL;
}
return pNew;
}
/*--------------------------------------------------------------------------*/
static void KillDictStruct(void *pData)
{
pDictStruct self = NULL;
self = (pDictStruct) pData;
assert(self);
if (self->pDes) {
DeleteDescriptor(self->pDes);
}
if (self->pDict) {
NXDclose(self->pDict, NULL);
}
free(self);
}
/*--------------------------------------------------------------------------*/
int SNStoreSANS(SConnection * pCon, SicsInterp * pSics, void *pData,
int argc, char *argv[])
{
char pBueffel[80];
pDictStruct self = NULL;
self = (pDictStruct) pData;
assert(self);
assert(pCon);
assert(pSics);
if (argc > 1) {
strtolower(argv[1]);
if (strcmp(argv[1], "gummi") == 0) {
if (argc > 2) {
if (!SCMatchRights(pCon, usMugger)) {
return 0;
}
gummiFlag = atoi(argv[2]);
SCSendOK(pCon);
return 1;
} else {
sprintf(pBueffel, "%s.gummi = %d", argv[0], gummiFlag);
SCWrite(pCon, pBueffel, eValue);
return 1;
}
}
}
return SNMakeSANS(pCon, pSics, self->pDict);
}
/*--------------------------------------------------------------------------*/
int InitSANS(SConnection * pCon, SicsInterp * pSics, void *pData,
int argc, char *argv[])
{
pDictStruct pNew = NULL;
char pBueffel[512];
if (argc < 2) {
SCWrite(pCon, "ERROR: not enough arguments for IniSANS", eError);
return 0;
}
pNew = MakeDictStruct(argv[1]);
if (!pNew) {
sprintf(pBueffel, "ERROR: failed to initialise NXDDL from file %s",
argv[1]);
SCWrite(pCon, pBueffel, eError);
return 0;
}
AddCommand(pSics, "StoreData", SNStoreSANS, KillDictStruct, pNew);
return 1;
}

View File

@ -1,17 +0,0 @@
/*-------------------------------------------------------------------------
N X S A N S
Prototypes for some more useful functions from the SANS data writing
module which may ne used in other parts of SICS.
Mark Koennecke, December 1997
---------------------------------------------------------------------------*/
#ifndef NXSANS
#define NXSANS
int InitSANS(SConnection * pCon, SicsInterp * pSics, void *pData,
int argc, char *argv[]);
int SNStoreSANS(SConnection * pCon, SicsInterp * pSics, void *pData,
int argc, char *argv[]);
#endif

View File

@ -23,6 +23,7 @@
#include "sicsvar.h"
#include "polterwrite.h"
#include "sicsvar.h"
#include "nxscript.h"
/*
diaphragm1 - chopper
@ -233,7 +234,7 @@ static void PoldiStart(pPolterdi self, SConnection * pCon)
pCounter pCount;
/* create filename */
self->pFile = SNXMakeFileName(pServ->pSics, pCon);
self->pFile = makeFilename(pServ->pSics, pCon);
if (!self->pFile) {
SCWrite(pCon, "ERROR: Extra severe: failed to create data file name",
eError);

44
psi.c
View File

@ -16,16 +16,10 @@
#include <tcl.h>
#include <site.h>
#include "buffer.h"
#include "dmc.h"
#include "nxsans.h"
#include "nextrics.h"
#include "sps.h"
#include "pimotor.h"
#include "sanswave.h"
#include "faverage.h"
#include "fowrite.h"
#include "amor2t.h"
#include "nxamor.h"
#include "amorstat.h"
#include "tas.h"
#include "swmotor.h"
@ -42,11 +36,9 @@
#include "bruker.h"
#include "ltc11.h"
#include "A1931.h"
#include "dilludriv.h"
#include "eurodriv.h"
#include "el755driv.h"
#include <evdriver.i>
#include "amorscan.h"
#include "serial.h"
#include "fomerge.h"
#include "remob.h"
@ -57,11 +49,6 @@
#include "sinqhttp.h"
#include "poldizug.h"
#include "autowin.h"
/*
from tcpdornier.c
*/
extern int VelSelTcpFactory(SConnection * pCon, SicsInterp * pSics,
void *pData, int argc, char *argv[]);
/*
* from julcho.c
*/
@ -128,17 +115,11 @@ static pSite sitePSI = NULL;
static void AddPsiCommands(SicsInterp * pInter)
{
AddCommand(pInter, "MakeRuenBuffer", InitBufferSys, NULL, NULL);
AddCommand(pInter, "InitDMC", InitDmc, NULL, NULL);
AddCommand(pInter, "InitSANS", InitSANS, NULL, NULL);
AddCommand(pInter, "MakeTRICSNEXUS", NexTricsFactory, NULL, NULL);
AddCommand(pInter, "MakeTRICSSupport", MakeTricsSupport, NULL, NULL);
AddCommand(pInter, "MakeSPS", SPSFactory, NULL, NULL);
AddCommand(pInter, "MakePIMotor", PIMotorFactory, NULL, NULL);
AddCommand(pInter, "MakeSANSWave", MakeSANSWave, NULL, NULL);
AddCommand(pInter, "MakeFocusAverager", MakeFA, NULL, NULL);
AddCommand(pInter, "FocusInstall", FoInstall, NULL, NULL);
AddCommand(pInter, "MakeAmor2T", Amor2TFactory, NULL, NULL);
AddCommand(pInter, "MakeStoreAmor", AmorStoreMake, NULL, NULL);
AddCommand(pInter, "MakeAmorStatus", AmorStatusFactory, NULL, NULL);
AddCommand(pInter, "MakeTAS", TASFactory, NULL, NULL);
AddCommand(pInter, "MakeSWMotor", MakeSWMotor, NULL, NULL);
@ -152,7 +133,6 @@ static void AddPsiCommands(SicsInterp * pInter)
AddCommand(pInter, "MakeSinq", SinqFactory, NULL, NULL);
AddCommand(pInter, "MakeTableDrive", TableDriveFactory, NULL, NULL);
AddCommand(pInter, "MakeAmorSet", AmorSetFactory, NULL, NULL);
AddCommand(pInter, "MakeTCPSelector", VelSelTcpFactory, NULL, NULL);
AddCommand(pInter, "MakeJulCho", JulChoFactory, NULL, NULL);
AddCommand(pInter, "MakeRitaFix", MakeRitaFix, NULL, NULL);
AddCommand(pInter, "MakePoldiReiss", MakePoldiReiss, NULL, NULL);
@ -167,9 +147,6 @@ static void AddPsiCommands(SicsInterp * pInter)
/*---------------------------------------------------------------------*/
static void RemovePsiCommands(SicsInterp * pSics)
{
RemoveCommand(pSics, "InitDMC");
RemoveCommand(pSics, "InitSANS");
RemoveCommand(pSics, "MakeTRICSNEXUS");
RemoveCommand(pSics, "MakeTRICSSupport");
RemoveCommand(pSics, "MakeSPS");
RemoveCommand(pSics, "MakePIMotor");
@ -177,10 +154,8 @@ static void RemovePsiCommands(SicsInterp * pSics)
RemoveCommand(pSics, "MakeFocusAverager");
RemoveCommand(pSics, "FocusInstall");
RemoveCommand(pSics, "InstallFocusMerge");
RemoveCommand(pSics, "MakeAmor2T");
RemoveCommand(pSics, "MakeStoreAmor");
RemoveCommand(pSics, "MakeAmorStatus");
RemoveCommand(pSics, "MakeTCPSelector");
RemoveCommand(pSics, "MakeJulCho");
RemoveCommand(pSics, "MakeRitaFix");
RemoveCommand(pSics, "MakePoldiReiss");
@ -370,7 +345,6 @@ static pVelSelDriv CreatePsiVelSelDriv(char *name, char *array,
extern pCodri MakeDoChoDriver(char *pHost, int iPort, int iChannel,
int iSingle);
extern pCodri MakeCookerDriver(char *pHost, int iPort, int iChannel);
extern pCodri MakeTcpDoChoDriver(char *tclArray, SConnection * pCon);
/*-------------------------------------------------------------------*/
static pCodri CreatePsiController(SConnection * pCon, int argc,
char *argv[])
@ -412,14 +386,6 @@ static pCodri CreatePsiController(SConnection * pCon, int argc,
}
}
pNew = MakeDoChoDriver(argv[1], iPort, iChannel, iSingle);
} else if (strcmp(argv[0], "tcpdocho") == 0) {
if (argc < 2) {
SCWrite(pCon,
"ERROR: insufficient number of argumets for creating TcpDoCho",
eError);
return NULL;
}
return MakeTcpDoChoDriver(argv[1], pCon);
} else if (strcmp(argv[0], "sanscook") == 0) {
if (argc < 4) {
SCWrite(pCon,
@ -545,12 +511,6 @@ static pEVControl InstallPsiEnvironmentController(SicsInterp * pSics,
commandInstalled = 1;
}
}
} else if (strcmp(argv[3], "dillu") == 0) {
checkError = 1;
pDriv = CreateDILLUDriv(argc - 4, &argv[4]);
if (pDriv != NULL) {
pNew = CreateEVController(pDriv, argv[2], &status);
}
} else if (strcmp(argv[3], "euro") == 0) {
checkError = 1;
pDriv = CreateEURODriv(argc - 4, &argv[4]);
@ -613,10 +573,6 @@ static pEVControl InstallPsiEnvironmentController(SicsInterp * pSics,
/*-----------------------------------------------------------------*/
static int ConfigurePsiScan(pScanData self, char *option)
{
if (strcmp(option, "amor") == 0) {
ConfigureAmor(self);
return 1;
}
return 0;
}

View File

@ -1,971 +0,0 @@
/*--------------------------------------------------------------
This is a driver for the newer Astrium == Dornier chopper
systems which use a TCP/IP server for communication.
This driver has to take care of some ugliness:
- As of december 2005, the communication is in unicode!
To go from ASCII to unicode and back one has to
add a 0x00 before each character or to remove it.
- The controller is slow in responding and the controller
must be watched in the environment monitor. This is taken
care of by a special SICS task which updates the status
regularly and returning cached values anytime else.
Inititial Implementation: Mark Koennecke, December 2005
------------------------------------------------------------*/
#include <stdlib.h>
#include <assert.h>
#include <time.h>
#include <fortify.h>
#include <sics.h>
#include <stringdict.h>
#include <rs232controller.h>
#include <codri.h>
#include <stptok.h>
#include <commandlog.h>
/*========================================================================
Our private data structure
========================================================================*/
#define ASYNMODE 0
#define SYNCMODE 1
typedef struct {
prs232 controller;
int iRefreshIntervall;
time_t nextRefresh;
long lTask;
pStringDict parameters;
int lastError;
int numChoppers;
int mode;
int timeout;
char user[132];
char pword[132];
int stop;
int busy;
char *config;
} TcpDoCho, *pTcpDoCho;
/*-----------------------------------------------------------------------
Error codes:
-----------------------------------------------------------------------*/
#define WRONGMODE -8301
#define BADCONVERSION -8302
#define FAILEDCOMMAND -8303
#define BADWRITE -8304
#define BADRESPONSE -8306
#define UNDRIVABLE -8307
#define BADPAR -8308
#define ESTOP -8309
extern char *trim(char *str);
#define ABS(x) (x < 0 ? -(x) : (x))
#define SPEEDTOL 2
#define PHASETOL .5
/*=============== support functions ===================================*/
static int asciiToUnicode(char *input, char **output)
{
int len, i;
char *result = NULL;
len = strlen(input);
result = (char *) malloc(2 * len * sizeof(char));
if (result == NULL) {
return 0;
}
memset(result, 0, 2 * len * sizeof(char));
for (i = 0; i < len; i++) {
result[i * 2] = input[i];
}
*output = result;
return 2 * len;
}
/*-------------------------------------------------------------------*/
static int unicodeToAscii(char *input, int len, char **output)
{
int i, alen;
char *result = NULL;
alen = len / 2;
result = (char *) malloc((alen + 1) * sizeof(char));
if (result == NULL) {
return 0;
}
memset(result, 0, (alen + 1) * sizeof(char));
for (i = 0; i < alen; i++) {
result[i] = input[i * 2];
}
*output = result;
return alen;
}
/*----------------------------------------------------------------*/
static int tcpDoChoSend(pTcpDoCho self, char *command, int choNum,
char *value)
{
char buffer[1024];
int sendlen, status;
/*
format and send command
*/
self->lastError = 0;
if (choNum < 0) {
snprintf(buffer, 1023, "#SOS#%s \r\n", command);
} else if (value != NULL) {
snprintf(buffer, 1023, "#SOS#%s%1.1d: %s\r\n", command, choNum, value);
} else {
snprintf(buffer, 1023, "#SOS#%s%1.1d:\r\n", command, choNum);
}
sendlen = strlen(buffer);
if (sendlen == 0) {
self->lastError = BADCONVERSION;
return 0;
}
status = send(self->controller->pSock->sockid, buffer, sendlen, 0);
if (status < 0) {
self->lastError = BADWRITE;
return 0;
}
return 1;
}
/*----------------------------------------------------------------*/
static int statusComplete(char *statusMessage)
{
char *pPtr = NULL;
/*
currently the status message has no terminator. I try to find
the last component of the message which happens to be TIME and
the last # after that
*/
pPtr = strstr(statusMessage, "TIME");
if (pPtr != NULL) {
pPtr = strstr(pPtr + 6, "#");
if (pPtr != NULL) {
return 1;
} else {
return 0;
}
} else {
return 0;
}
}
/*---------------------------------------------------------------*/
static int readChopperNum(char *entry)
{
int num;
char *pPtr = NULL;
pPtr = strstr(entry, "CH");
if (pPtr == NULL) {
return -1;
}
sscanf(pPtr + 3, "%d", &num);
return num;
}
/*---------------------------------------------------------------*/
static void addEntry(pTcpDoCho self, int choNum, char *entry)
{
char name[80], value[80], *pPtr = NULL;
char num[5];
memset(name, 0, 80);
memset(value, 0, 80);
snprintf(num, 5, "_%1.1d", choNum);
pPtr = strstr(entry, "=");
if (pPtr != NULL) {
strncpy(name, entry, pPtr - entry);
strncat(trim(name), num, 80 - strlen(trim(name)));
strcpy(value, pPtr + 1);
if (StringDictExists(self->parameters, name)) {
StringDictUpdate(self->parameters, name, trim(value));
} else {
StringDictAddPair(self->parameters, name, trim(value));
}
}
}
/*----------------------------------------------------------------*/
static int parseStatus(pTcpDoCho self, char *statusMessage)
{
int choNum;
char entry[80], *pPtr;
pPtr = statusMessage;
/* skip over SOS */
pPtr = stptok(pPtr, entry, 79, "#");
pPtr = stptok(pPtr, entry, 79, "#");
pPtr = stptok(pPtr, entry, 79, "#");
choNum = readChopperNum(entry);
if (choNum < 0) {
self->lastError = BADRESPONSE;
return 0;
}
while ((pPtr = stptok(pPtr, entry, 79, "#")) != NULL) {
addEntry(self, choNum, entry);
memset(entry, 0, 80);
}
return 1;
}
/*-----------------------------------------------------------------*/
static int tcpDoChoReceive(pTcpDoCho self)
{
char buffer[1024];
int len, bytesRead, bufferStart, status;
time_t endTime;
endTime = time(NULL) + self->timeout;
bufferStart = 0;
bytesRead = 0;
memset(buffer, 0, 1024 * sizeof(char));
while (time(NULL) < endTime) {
if (availableRS232(self->controller)) {
bytesRead +=
recv(self->controller->pSock->sockid, buffer + bufferStart,
1024 - bytesRead, 0);
if (bytesRead < 0) {
self->lastError = BADREAD;
return 0;
}
if (strstr(buffer, "State") != NULL) {
if (statusComplete(buffer) == 0) {
continue;
} else {
status = parseStatus(self, buffer);
return status;
}
}
if (strstr(buffer, "ACCEPT") != NULL) {
return 1;
} else if (strstr(buffer, "NCCEPT") != NULL) {
self->lastError = FAILEDCOMMAND;
return 0;
} else {
self->lastError = BADRESPONSE;
return 0;
}
} else {
SicsWait(1);
}
}
self->lastError = TIMEOUT;
return 0;
}
/*-----------------------------------------------------------------*/
static int tcpDoChoCommand(pTcpDoCho self, char *command, int choNum,
char *value)
{
int status;
status = tcpDoChoSend(self, command, choNum, value);
if (status == 0) {
return 0;
}
return tcpDoChoReceive(self);
}
/*---------------------------------------------------------------*/
static int TcpDoChoConnect(pTcpDoCho self)
{
int status, sendLen, readLen;
char buffer[256];
status = initRS232(self->controller);
if (status != 1) {
self->lastError = status;
return 0;
}
setRS232Timeout(self->controller, 5);
readLen = 255;
readRS232(self->controller, (void *) buffer, &readLen);
/*
user name
*/
snprintf(buffer, 255, "user:%s\r\n", self->user);
sendLen = strlen(buffer);
if (sendLen == 0) {
self->lastError = BADCONVERSION;
return 0;
}
status = send(self->controller->pSock->sockid, buffer, sendLen, 0);
if (status < 0) {
self->lastError = BADSEND;
return 0;
}
readLen = 255;
readRS232(self->controller, (void *) buffer, &readLen);
/*
password
*/
snprintf(buffer, 255, "password:%s\r\n", self->pword);
sendLen = strlen(buffer);
if (sendLen == 0) {
self->lastError = BADCONVERSION;
return 0;
}
status = send(self->controller->pSock->sockid, buffer, sendLen, 0);
if (status < 0) {
self->lastError = BADSEND;
return 0;
}
readLen = 255;
readRS232(self->controller, (void *) buffer, &readLen);
/*
TODO: responses should be checked to test for a valid login.
I do not know at this time how the controller reacts upon a
bad login.
*/
return 1;
}
/*==================== actual driver implementation code ==================*/
static int TcpChopperTask(void *pData)
{
pCodri self = NULL;
pTcpDoCho pPriv = NULL;
int status, code, i;
char buffer[80];
char error[512];
self = (pCodri) pData;
assert(self);
pPriv = (pTcpDoCho) self->pPrivate;
assert(pPriv);
if (pPriv->stop == 1) {
return 0;
}
if (time(NULL) > pPriv->nextRefresh) {
if (pPriv->lastError != 0) {
self->GetError(self, &code, buffer, 79);
snprintf(error, 511, "WARNING: chopper tries to fix: %s", buffer);
WriteToCommandLog("Chopper-task:>>", error);
status = self->TryFixIt(self, code);
if (status == CHFAIL) {
pPriv->nextRefresh = time(NULL) + pPriv->iRefreshIntervall;
return 1;
}
} else {
pPriv->busy = 1;
for (i = 0; i < pPriv->numChoppers; i++) {
status = tcpDoChoCommand(pPriv, "STATE ", i + 1, NULL);
if (status != 1) {
/*
force error correction
*/
return 1;
}
}
pPriv->nextRefresh = time(NULL) + pPriv->iRefreshIntervall;
pPriv->busy = 0;
}
}
return 1;
}
/*------------------------------------------------------------------------------*/
static int TcpDoChoKill(pCodri self)
{
pTcpDoCho pPriv = NULL;
pPriv = (pTcpDoCho) self->pPrivate;
if (!pPriv)
return 1;
if (pPriv->controller != NULL) {
KillRS232(pPriv->controller);
}
if (pPriv->parameters != NULL) {
DeleteStringDict(pPriv->parameters);
}
if (pPriv->config != NULL) {
free(pPriv->config);
}
free(pPriv);
return 1;
}
/*-------------------------------------------------------------------*/
static int TcpDoChoConfigure(pCodri pDriv)
{
pTcpDoCho self = NULL;
int status;
char *pPtr = NULL;
char command[80];
assert(pDriv != NULL);
self = (pTcpDoCho) pDriv->pPrivate;
assert(self != NULL);
if (self->config != NULL) {
pPtr = self->config;
while ((pPtr = stptok(pPtr, command, 79, "\n")) != NULL) {
status = tcpDoChoCommand(self, command, -1, NULL);
if (status != 1) {
return 0;
}
}
}
return 1;
}
/*---------------------------------------------------------------------*/
static int TcpDoChoInit(pCodri pDriv)
{
pTcpDoCho self = NULL;
int status;
assert(pDriv != NULL);
self = (pTcpDoCho) pDriv->pPrivate;
assert(self != NULL);
self->lastError = 0;
self->stop = 0;
self->nextRefresh = 0;
status = TcpDoChoConnect(self);
if (status != 1) {
return 0;
}
status = TcpDoChoConfigure(pDriv);
if (status != 1) {
return 0;
}
/* start the update task */
if (self->lTask == 0) {
self->lTask = TaskRegister(pServ->pTasker,
TcpChopperTask, NULL, NULL, pDriv, 1);
}
return 1;
}
/*-------------------------------------------------------------------*/
static void waitForBusy(pTcpDoCho self)
{
time_t endTime;
endTime = time(NULL) + 10 * 60; /* max 10 min */
while (time(NULL) < endTime) {
if (self->busy == 1) {
SicsWait(3);
} else {
return;
}
}
WriteToCommandLog("Chopper-task>> ",
"WARNING: timeout on busy flag, flag forced");
self->busy = 0;
}
/*----------------------------------------------------------------------*/
static int TcpDoChoClose(pCodri pDriv)
{
pTcpDoCho self = NULL;
int status;
assert(pDriv != NULL);
self = (pTcpDoCho) pDriv->pPrivate;
assert(self != NULL);
self->stop = 1;
if (self->controller != NULL) {
KillRS232(self->controller);
self->controller = NULL;
}
return 1;
}
/*----------------------------------------------------------------------*/
static int dissectName(char *name, char par[80], int *num)
{
char *pPtr = NULL;
pPtr = strrchr(name, (int) '_');
if (pPtr == NULL) {
return 0;
}
memset(par, 0, 80 * sizeof(char));
strncpy(par, name, pPtr - name);
if (sscanf(pPtr + 1, "%d", num) != 1) {
return 0;
}
return 1;
}
/*----------------------------------------------------------------------*/
static int TcpDoChoSetPar2(pCodri pDriv, char *parname, char *value)
{
pTcpDoCho self = NULL;
int status, choNum;
char par[80], buffer[80], state[80];
assert(pDriv != NULL);
self = (pTcpDoCho) pDriv->pPrivate;
assert(self != NULL);
/*
force status requests right after setting something in order
to make the stored status represent the new target values
*/
if (dissectName(parname, par, &choNum)) {
/*
check for emergency stop
*/
snprintf(buffer, 79, "State_%1.1d", choNum);
memset(state, 0, 80 * sizeof(char));
StringDictGet(self->parameters, buffer, state, 79);
if (strstr(state, "E-Stop") != NULL) {
self->lastError = ESTOP;
return 0;
}
if (strcmp(par, "speed") == 0) {
waitForBusy(self);
status = tcpDoChoCommand(self, "SPEED ", choNum, trim(value));
tcpDoChoCommand(self, "STATE ", choNum, NULL);
if (status != 1) {
return 0;
} else {
return 1;
}
} else if (strcmp(par, "phase") == 0) {
waitForBusy(self);
status = tcpDoChoCommand(self, "PHASE ", choNum, trim(value));
tcpDoChoCommand(self, "STATE ", choNum, NULL);
if (status != 1) {
return 0;
} else {
return 1;
}
}
}
self->lastError = UNDRIVABLE;
return 0;
}
/*-----------------------------------------------------------------------*/
static int TcpDoChoHalt(pCodri pDriv)
{
pTcpDoCho self = NULL;
int status;
assert(pDriv != NULL);
self = (pTcpDoCho) pDriv->pPrivate;
assert(self != NULL);
waitForBusy(self);
tcpDoChoCommand(self, "ESTOP :", -1, NULL);
return 1;
}
/*-----------------------------------------------------------------------*/
static int TcpDoChoSetPar(pCodri pDriv, char *parname, float fValue)
{
pTcpDoCho self = NULL;
int status, choNum;
char value[80];
char par[80];
assert(pDriv != NULL);
self = (pTcpDoCho) pDriv->pPrivate;
assert(self != NULL);
if (dissectName(parname, par, &choNum)) {
if (strcmp(par, "speed") == 0) {
snprintf(value, 79, "%5.1f", fValue);
return TcpDoChoSetPar2(pDriv, parname, value);
} else if (strcmp(par, "phase") == 0) {
snprintf(value, 79, "%6.2f", fValue);
return TcpDoChoSetPar2(pDriv, parname, value);
}
}
if (strcmp(parname, "updateintervall") == 0) {
sprintf(value, "%d", (int) fValue);
StringDictUpdate(self->parameters, "updateintervall", value);
self->iRefreshIntervall = (int) fValue;
return 1;
} else {
snprintf(value, 79, "%f", fValue);
return TcpDoChoSetPar2(pDriv, parname, value);
}
}
/*---------------------------------------------------------------------*/
static int TcpDoChoGetPar(pCodri pDriv, char *parname,
char *pBuffer, int iBuflen)
{
pTcpDoCho self = NULL;
int status = 0, choNum;
char par[80], buffer[80];
float val;
assert(pDriv != NULL);
self = (pTcpDoCho) pDriv->pPrivate;
assert(self != NULL);
memset(par, 0, 80);
dissectName(parname, par, &choNum);
if (strcmp(par, "speed") == 0) {
snprintf(buffer, 80, "ASPEED_%1.1d", choNum);
status = StringDictGet(self->parameters, buffer, pBuffer, iBuflen);
} else if (strcmp(par, "phase") == 0) {
snprintf(buffer, 80, "APHASE_%1.1d", choNum);
status = StringDictGet(self->parameters, buffer, pBuffer, iBuflen);
} else {
status = StringDictGet(self->parameters, parname, pBuffer, iBuflen);
}
return status;
}
/*----------------------------------------------------------------------*/
static int TcpDoChoCheckPar(pCodri pDriv, char *parname)
{
pTcpDoCho self = NULL;
int status = 0, choNum;
float val, soll, delta;
char value[80], csoll[80], par[80], buffer[80], state[80];
assert(pDriv != NULL);
self = (pTcpDoCho) pDriv->pPrivate;
assert(self != NULL);
/*
check for flags first
*/
if (self->busy) {
return HWBusy;
}
if (self->lastError != 0) {
return HWFault;
}
/*
updateintervall is always Idle
*/
if (strcmp(parname, "updateintervall") == 0) {
return HWIdle;
}
/*
check for emergency stop
*/
snprintf(buffer, 79, "State_%1.1d", choNum);
memset(state, 0, 80 * sizeof(char));
StringDictGet(self->parameters, buffer, state, 79);
if (strstr(state, "E-Stop") != NULL) {
self->lastError = HWFault;
return 0;
}
memset(par, 0, 80);
dissectName(parname, par, &choNum);
if (strcmp(par, "speed") == 0) {
snprintf(buffer, 79, "RSPEED_%1.1d", choNum);
StringDictGet(self->parameters, buffer, csoll, 79);
sscanf(csoll, "%f", &soll);
snprintf(buffer, 79, "ASPEED_%1.1d", choNum);
StringDictGet(self->parameters, buffer, value, 79);
sscanf(value, "%f", &val);
delta = ABS(soll - val);
if (delta > SPEEDTOL) {
return HWBusy;
} else {
return HWIdle;
}
} else if (strcmp(par, "phase") == 0) {
snprintf(buffer, 79, "RPHASE_%1.1d", choNum);
StringDictGet(self->parameters, buffer, csoll, 79);
sscanf(value, "%f", &soll);
snprintf(buffer, 79, "APHASE_%1.1d", choNum);
StringDictGet(self->parameters, buffer, value, 79);
sscanf(value, "%f", &val);
delta = ABS(soll - val);
if (delta > PHASETOL) {
return HWBusy;
} else {
return HWIdle;
}
}
self->lastError = BADPAR;
return HWFault;
}
/*---------------------------------------------------------------------------*/
static int TcpDoChoError(pCodri pDriv, int *iCode, char *pError, int iLen)
{
pTcpDoCho self = NULL;
int status = 0;
float val, soll, delta;
char value[80];
assert(pDriv != NULL);
self = (pTcpDoCho) pDriv->pPrivate;
assert(self != NULL);
*iCode = self->lastError;
switch (self->lastError) {
case WRONGMODE:
strncpy(pError, "Chopper in wrong mode", iLen);
break;
case BADCONVERSION:
strncpy(pError, "Bad ASCII to unicode conversion", iLen);
break;
case FAILEDCOMMAND:
strncpy(pError, "Command not accepted", iLen);
break;
case BADWRITE:
strncpy(pError, "Failed to write to chopper controller", iLen);
break;
case BADRESPONSE:
strncpy(pError, "Chopper controller send invalid command", iLen);
break;
case UNDRIVABLE:
strncpy(pError, "Parameter cannot be changed", iLen);
break;
case BADPAR:
strncpy(pError, "No such parameter", iLen);
break;
case ESTOP:
strncpy(pError, "Emergency stop is engaged", iLen);
break;
default:
getRS232Error(self->lastError, pError, iLen);
break;
}
return 1;
}
/*---------------------------------------------------------------------*/
static int TcpDoChoFix(pCodri pDriv, int iCode)
{
pTcpDoCho self = NULL;
int status = 0;
float val, soll, delta;
char value[80];
assert(pDriv != NULL);
self = (pTcpDoCho) pDriv->pPrivate;
assert(self != NULL);
self->lastError = 0;
switch (iCode) {
case BADCONVERSION:
case BADRESPONSE:
return CHREDO;
break;
case WRONGMODE:
case FAILEDCOMMAND:
case UNDRIVABLE:
case BADPAR:
case ESTOP:
return CHFAIL;
break;
default:
closeRS232(self->controller);
status = TcpDoChoConnect(self);
if (status == 1) {
return CHREDO;
} else {
return CHFAIL;
}
break;
}
return CHFAIL;
}
/*-------------------------------------------------------------------*/
pCodri MakeTcpDoChoDriver(char *tclArray, SConnection * pCon)
{
pCodri pNew = NULL;
pTcpDoCho self = NULL;
const char *pPtr = NULL;
char buffer[132];
int port, i, count;
Tcl_DString pars;
char *parnames[] = { "State",
"ASPEED",
"RSPEED",
"APHASE",
"RPHASE",
"AVETO",
"DIR",
"MONIT",
"FLOWR",
"WTEMP",
"MTEMP",
"MVIBR",
"MVACU",
"speed",
"phase",
NULL,
};
/*
allocate memory
*/
pNew = (pCodri) malloc(sizeof(Codri));
self = (pTcpDoCho) malloc(sizeof(TcpDoCho));
if (!pNew || !self) {
return NULL;
}
memset(pNew, 0, sizeof(Codri));
memset(self, 0, sizeof(TcpDoCho));
/* port and host name */
pPtr =
Tcl_GetVar2(pServ->pSics->pTcl, tclArray, "port", TCL_GLOBAL_ONLY);
if (!pPtr) {
SCWrite(pCon,
"ERROR: port not found in configuration array for TCP Dornier Chopper",
eError);
free(pNew);
free(self);
return NULL;
}
sscanf(pPtr, "%d", &port);
pPtr =
Tcl_GetVar2(pServ->pSics->pTcl, tclArray, "host", TCL_GLOBAL_ONLY);
if (!pPtr) {
SCWrite(pCon,
"ERROR: host not found in configuration array for TCP Dornier Chopper",
eError);
free(pNew);
free(self);
return NULL;
}
memset(buffer, 0, 132);
strncpy(buffer, pPtr, 131);
self->controller = createRS232(buffer, port);
/* number of choppers */
pPtr =
Tcl_GetVar2(pServ->pSics->pTcl, tclArray, "nchopper",
TCL_GLOBAL_ONLY);
if (!pPtr) {
SCWrite(pCon,
"ERROR: nchopper not found in configuration array for TCP Dornier Chopper",
eError);
free(pNew);
free(self);
return NULL;
}
sscanf(pPtr, "%d", &port);
if (port < 0 || port > 8) {
SCWrite(pCon, "ERROR: number of choppers not in range 1 - 8", eError);
free(pNew);
free(self);
}
self->numChoppers = port;
/* timeout */
pPtr =
Tcl_GetVar2(pServ->pSics->pTcl, tclArray, "timeout",
TCL_GLOBAL_ONLY);
if (!pPtr) {
SCWrite(pCon,
"ERROR: timeout not found in configuration array for TCP Dornier Chopper",
eError);
free(pNew);
free(self);
return NULL;
}
sscanf(pPtr, "%d", &port);
self->timeout = port;
/* username and password */
pPtr =
Tcl_GetVar2(pServ->pSics->pTcl, tclArray, "user", TCL_GLOBAL_ONLY);
if (!pPtr) {
SCWrite(pCon,
"ERROR: user not found in configuration array for TCP Dornier Chopper",
eError);
free(pNew);
free(self);
return NULL;
}
strncpy(self->user, pPtr, 131);
pPtr =
Tcl_GetVar2(pServ->pSics->pTcl, tclArray, "password",
TCL_GLOBAL_ONLY);
if (!pPtr) {
SCWrite(pCon,
"ERROR: password not found in configuration array for TCP Dornier Chopper",
eError);
free(pNew);
free(self);
return NULL;
}
strncpy(self->pword, pPtr, 131);
/*
chopper configuration
*/
pPtr =
Tcl_GetVar2(pServ->pSics->pTcl, tclArray, "config", TCL_GLOBAL_ONLY);
if (pPtr != NULL) {
self->config = strdup(pPtr);
}
/* initialize some more */
self->parameters = CreateStringDict();
if (self->parameters == NULL || self->controller == NULL) {
SCWrite(pCon, "ERROR: out of memory in MakeTcpDoCho", eError);
free(pNew);
free(self);
return NULL;
}
self->iRefreshIntervall = 60;
pNew->Init = TcpDoChoInit;
pNew->Close = TcpDoChoClose;
pNew->Delete = TcpDoChoKill;
pNew->SetPar = TcpDoChoSetPar;
pNew->SetPar2 = TcpDoChoSetPar2;
pNew->GetPar = TcpDoChoGetPar;
pNew->CheckPar = TcpDoChoCheckPar;
pNew->GetError = TcpDoChoError;
pNew->TryFixIt = TcpDoChoFix;
pNew->Halt = TcpDoChoHalt;
StringDictAddPair(self->parameters, "updateintervall", "60");
pNew->pPrivate = self;
/*
create parameter list
*/
Tcl_DStringInit(&pars);
count = 0;
Tcl_DStringAppend(&pars, "updateintervall", 15);
while (parnames[count] != NULL) {
for (i = 0; i < self->numChoppers; i++) {
snprintf(buffer, 131, ",%s_%1.1d", parnames[count], i + 1);
Tcl_DStringAppend(&pars, buffer, strlen(buffer));
}
count++;
}
pNew->pParList = strdup(Tcl_DStringValue(&pars));
Tcl_DStringFree(&pars);
return pNew;
}

File diff suppressed because it is too large Load Diff