- SICS cleanup: removed unused code

SKIPPED:
	psi/make_gen
	psi/makefile_linux
	psi/polterwrite.c
	psi/psi.c
This commit is contained in:
koennecke
2010-01-19 12:55:40 +00:00
parent c3b3ab1f06
commit be13da8a03
19 changed files with 11 additions and 3712 deletions

114
cryst.c
View File

@ -1,114 +0,0 @@
/*---------------------------------------------------------------------------
C r y s t
This is a library of crystallographic utility routines for four
circle diffractometers. It deals with all sorts of rotations and
stuff. This is based on code originally developed by John Allibon
at ILL and reimplemented in C using a matrix-library.
Mark Koennecke, July 2000
----------------------------------------------------------------------------*/
#include <stdlib.h>
#include <stdio.h>
#include <assert.h>
#include <math.h>
#include "matrix/matrix.h"
#include "cryst.h"
#define PIR 57.30
/*-------------------------------------------------------------------------
chimat, calculate chi rotation matrix. The input angle is in degrees.
The setting is Busing & Levy.
--------------------------------------------------------------------------*/
MATRIX chimat(double dAngle)
{
MATRIX res;
double dChi;
res = mat_creat(3, 3, ZERO_MATRIX);
dChi = dAngle / PIR;
res[0][0] = cos(dChi);
res[0][2] = sin(dChi);
res[1][1] = 1.;
res[2][0] = -res[0][2];
res[2][2] = res[0][0];
return res;
}
/*-------------------------------------------------------------------------
phimat, calculate phi rotation matrix. The input angle is in degrees.
The setting is Busing & Levy.
--------------------------------------------------------------------------*/
MATRIX phimat(double dAngle)
{
MATRIX res;
double dPhi;
res = mat_creat(3, 3, ZERO_MATRIX);
dPhi = dAngle / PIR;
res[0][0] = cos(dPhi);
res[0][1] = sin(dChi);
res[2][2] = 1.;
res[1][0] = -res[0][1];
res[1][1] = res[0][0];
return res;
}
/*-------------------------------------------------------------------------
psimat, calculate psi rotation matrix. The input angle is in degrees.
The setting is Busing & Levy.
--------------------------------------------------------------------------*/
MATRIX psimat(double dAngle)
{
MATRIX res;
double dPsi;
res = mat_creat(3, 3, ZERO_MATRIX);
dPsi = dAngle / PIR;
res[0][0] = 1.;
res[1][1] = cos(dPsi);
res[1][2] = -sin(dPsi);
res[2][1] = -res[1][2];
res[2][2] = res[1][1];
return res;
}
/*-------------------------------------------------------------------------
diffFromAngles calculates the diffraction vector from two theta, omega
chi and phi. The angled need not be bissecting but it is assumed that
the diffraction vector is in the equatorial plane.
--------------------------------------------------------------------------*/
MATRIX diffFromAngles(double wave, double tth, double om,
double chi, double phi)
{
MATRIX res, rot, dum, z;
double dTh;
dTh = (tth / 2.) / PIR;
res = mat_creat(3, 1, ZERO_MATRIX);
res[0][0] = (2. * sin(dTh) * cos(dTh)) / wave;
res[1][0] = (-2. * sin(dTh) * sin(dTh)) / wave;
/* undo omega rotation */
rot = phimat(om);
dum = mat_tran(rot);
mat_free(rot);
z = mat_mul(dum, res);
mat_free(dum);
mat_free(res);
/* result is now z */
}

View File

@ -1,642 +0,0 @@
/**
* This is a generic controller for devices in SICS. It is configurable via Tcl
* scripts.
*
* copyright: see file COPYRIGHT
*
* Mark Koennecke, November 2007
*/
#include <stdlib.h>
#include <assert.h>
#include <tcl.h>
#include <sics.h>
#include <macro.h>
#include <sicshipadaba.h>
#include <sicsobj.h>
#include <dynstring.h>
#include <genericcontroller.h>
/*--------------------------------------------------------------------------*/
static hdbCallbackReturn GenConSetCallback(pHdb node, void *userData,
pHdbMessage message)
{
pSICSOBJ self = (pSICSOBJ) userData;
SConnection *pCon = NULL;
pGenController priv = NULL;
char command[1024];
char value[80];
int status, privilege;
pDynString data;
pHdbDataMessage mm = NULL;
assert(self != NULL);
if ((mm = GetHdbSetMessage(message)) == NULL) {
return hdbContinue;
}
priv = (pGenController) self->pPrivate;
pCon = mm->callData;
/*
* check rights
*/
memset(value, 0, 80);
if (GetHdbProperty(node, "priv", value, 80) && pCon != NULL) {
privilege = usInternal;
if (strcmp(value, "manager") == 0) {
privilege = usMugger;
}
if (strcmp(value, "user") == 0) {
privilege = usUser;
}
if (!SCMatchRights(pCon, privilege)) {
return hdbAbort;
}
}
/*
* check writeCommand
*/
memset(value, 0, 80);
GetHdbProperty(node, "writeCommand", value, 80);
if (strlen(value) < 2) {
if (pCon != NULL) {
SCWrite(pCon, "ERROR: parameter is read-only", eError);
return hdbAbort;
}
return hdbAbort;
}
/*
* check status
*/
memset(value, 0, 80);
GetHdbProperty(node, "status", value, 80);
if (strstr(value, "idle") == NULL) {
return hdbAbort;
}
SetHdbProperty(node, "status", "setting");
data = formatValue(*(mm->v), node);
if (data != NULL) {
SetHdbProperty(node, "target", GetCharArray(data));
DeleteDynString(data);
}
/*
* issue command
*/
if (priv->enqueueNodeHead != NULL) {
priv->enqueueNodeHead(self, pCon, node);
} else {
if (pCon != NULL) {
SCWrite(pCon, "ERROR: generic controller NOT configured", eError);
}
return hdbAbort;
}
return hdbContinue;
}
/*--------------------------------------------------------------------------*/
static hdbCallbackReturn GenConGetCallback(pHdb node, void *userData,
pHdbMessage message)
{
pSICSOBJ self = (pSICSOBJ) userData;
SConnection *pCon = NULL;
pGenController priv = NULL;
char command[1024];
char value[256];
int status, privilege;
pHdbDataMessage mm = NULL;
assert(self != NULL);
if ((mm = GetHdbGetMessage(message)) == NULL) {
return hdbContinue;
}
pCon = mm->callData;
priv = (pGenController) self->pPrivate;
/*
* check status
*/
memset(value, 0, 80);
GetHdbProperty(node, "status", value, 80);
if (strstr(value, "idle") == NULL) {
return hdbContinue;
}
SetHdbProperty(node, "status", "getting");
/*
* check readCommand
*/
memset(value, 0, 256);
GetHdbProperty(node, "readCommand", value, 255);
if (strlen(value) < 2) {
return hdbAbort;
} else {
if (priv->enqueueNode != NULL) {
priv->enqueueNode(self, pCon, node);
} else {
if (pCon != NULL) {
SCWrite(pCon,
"ERROR: generic controller connection NOT configured",
eError);
}
return hdbAbort;
}
}
/*
* Upper Level GetHipadabaPar will automatically return the
* node value. Which should have been updated through an update
* during the execution of enqueueNode
*/
return hdbContinue;
}
/*---------------------------------------------------------------------------*/
static pHdb MakeGenConPar(pSICSOBJ self, char *name, int type, int length)
{
pHdb result = NULL;
pHdbCallback kalle = NULL;
result = MakeHipadabaNode(name, type, length);
if (result == NULL) {
return NULL;
}
kalle = MakeHipadabaCallback(GenConSetCallback, self, NULL);
if (kalle == NULL) {
return NULL;
}
AppendHipadabaCallback(result, kalle);
kalle = MakeHipadabaCallback(GenConGetCallback, self, NULL);
if (kalle == NULL) {
return NULL;
}
AppendHipadabaCallback(result, kalle);
SetHdbProperty(result, "priv", "manager");
SetHdbProperty(result, "readCommand", "");
SetHdbProperty(result, "writeCommand", "");
SetHdbProperty(result, "replyCommand", "");
SetHdbProperty(result, "status", "idle");
return result;
}
/*---------------------------------------------------------------------------*/
static int MakeGenPar(pSICSOBJ self, SConnection * pCon,
char *argv[], int argc)
{
char buffer[2048];
int type, length = 1;
pHdb node = NULL, parent;
char *pPtr = NULL;
if (argc < 5) {
snprintf(buffer, 2048, "ERROR: insufficient arguments to %s makepar",
argv[0]);
SCWrite(pCon, buffer, eError);
return 0;
}
type = convertHdbType(argv[4]);
if (argc > 5) {
length = atoi(argv[5]);
}
strncpy(buffer, argv[3], 2047);
pPtr = strrchr(buffer, '/');
if (pPtr == NULL) {
node = MakeGenConPar(self, argv[3], type, length);
parent = self->objectNode;
} else {
*pPtr = '\0';
pPtr++;
node = MakeGenConPar(self, pPtr, type, length);
parent = GetHipadabaNode(self->objectNode, buffer);
}
if (node == NULL || parent == NULL) {
SCWrite(pCon, "ERROR: failed to create node or parent not found",
eError);
return 0;
}
AddHipadabaChild(parent, node, pCon);
SCSendOK(pCon);
return 1;
}
/*=============================== ==========================================
* This stuff is for the Tcl - AsynQueue implementation of GenericController
* ==========================================================================*/
typedef struct {
pHdb node;
pSICSOBJ obj;
SConnection *pCon;
pGenController priv;
pAsyncUnit assi;
pAsyncTxn trans;
char replyCommand[2048];
} GenContext, *pGenContext;
/*--------------------------------------------------------------------------
* This is called by AsyncQueue when a reply has been received.
* -------------------------------------------------------------------------*/
static int GenConTxnHandler(pAsyncTxn pTxn)
{
pGenContext genCon = NULL;
char reply[10240];
genCon = (pGenContext) pTxn->cntx;
assert(genCon != NULL);
memset(reply, 0, 10240 * sizeof(char));
switch (pTxn->txn_state) {
case ATX_NULL:
case ATX_ACTIVE:
return 1;
break;
case ATX_TIMEOUT:
strcpy(reply, "TIMEOUT");
break;
case ATX_DISCO:
strcpy(reply, "DISCONNECTED");
break;
case ATX_COMPLETE:
strncpy(reply, pTxn->inp_buf, 10240);
break;
}
genCon->priv->replyCallback(genCon->obj, genCon->pCon,
genCon->node, genCon->replyCommand, reply,
strlen(reply));
if (genCon->pCon != NULL) {
SCDeleteConnection(genCon->pCon);
}
free(genCon);
return 1;
}
/*--------------------------------------------------------------------------*/
static char *formatCommand(pHdb node, SConnection * pCon)
{
pDynString com = NULL;
char value[512];
Tcl_Interp *pTcl = NULL;
int status;
com = CreateDynString(256, 128);
if (com == NULL) {
return NULL;
}
memset(value, 0, 512);
GetHdbProperty(node, "status", value, 512);
if (strstr(value, "set") != NULL) {
memset(value, 0, 512);
GetHdbProperty(node, "writeCommand", value, 512);
DynStringConcat(com, value);
DynStringConcatChar(com, ' ');
memset(value, 0, 512);
GetHdbProperty(node, "target", value, 512);
DynStringConcat(com, value);
} else {
memset(value, 0, 512);
GetHdbProperty(node, "readCommand", value, 512);
DynStringConcat(com, value);
}
pTcl = InterpGetTcl(pServ->pSics);
if (pCon != NULL) {
MacroPush(pCon);
}
status = Tcl_Eval(pTcl, GetCharArray(com));
if (pCon != NULL) {
MacroPop();
}
DeleteDynString(com);
if (status != TCL_OK) {
SetHdbProperty(node, "result", (char *) Tcl_GetStringResult(pTcl));
return NULL;
}
return strdup(Tcl_GetStringResult(pTcl));
}
/*--------------------------------------------------------------------------*/
static pGenContext PrepareToEnque(pSICSOBJ self, SConnection * pCon,
pHdb node)
{
pGenContext result = NULL;
char *command = NULL;
pGenController priv = NULL;
priv = (pGenController) self->pPrivate;
assert(priv != NULL);
command = formatCommand(node, pCon);
if (command == NULL) {
return NULL;
}
result = malloc(sizeof(GenContext));
if (result == NULL) {
return NULL;
}
memset(result, 0, sizeof(GenContext));
if (!GetHdbProperty(node, "replyCommand", result->replyCommand, 2048)) {
if (pCon != NULL) {
SCWrite(pCon, "ERROR: no replyCommand found", eError);
}
free(result);
return NULL;
}
result->assi = AsyncUnitFromQueue((pAsyncQueue) priv->comContext);
if (result->assi == NULL) {
return NULL;
}
result->trans = AsyncUnitPrepareTxn(result->assi,
command, strlen(command),
GenConTxnHandler, result, 2048);
if (result->trans == NULL) {
return NULL;
}
result->node = node;
result->priv = priv;
result->obj = self;
result->pCon = SCCopyConnection(pCon);
priv->comError = GCOK;
free(command);
return result;
}
/*---------------------------------------------------------------------------*/
static int AsyncEnqueueNode(pSICSOBJ self, SConnection * pCon, pHdb node)
{
pGenContext genCon = NULL;
genCon = PrepareToEnque(self, pCon, node);
if (genCon == NULL) {
return 0;
}
return AsyncUnitEnqueueTxn(genCon->assi, genCon->trans);
}
/*---------------------------------------------------------------------------*/
static int AsyncEnqueueNodeHead(pSICSOBJ self, SConnection * pCon,
pHdb node)
{
pGenContext genCon = NULL;
genCon = PrepareToEnque(self, pCon, node);
if (genCon == NULL) {
return 0;
}
return AsyncUnitEnqueueHead(genCon->assi, genCon->trans);
}
/*---------------------------------------------------------------------------*/
static int AsyncReply(pSICSOBJ self, SConnection * pCon, pHdb node,
char *replyCommand, char *reply, int replylen)
{
pDynString com = NULL;
Tcl_Interp *pTcl;
int status;
SetHdbProperty(node, "result", reply);
com = CreateDynString(256, 128);
if (com == NULL) {
return 0;
}
DynStringConcat(com, replyCommand);
DynStringConcat(com, " \"");
DynStringConcat(com, reply);
DynStringConcat(com, "\"\0");
if (pCon != NULL) {
MacroPush(pCon);
}
pTcl = InterpGetTcl(pServ->pSics);
status = Tcl_Eval(pTcl, GetCharArray(com));
if (pCon != NULL) {
MacroPop();
}
DeleteDynString(com);
if (status != TCL_OK) {
SetHdbProperty(node, "lastError", (char *) Tcl_GetStringResult(pTcl));
}
return status;
}
/*============= GenController Object Functions ==============================*/
static int ConnectAsync(pSICSOBJ self, SConnection * pCon,
char *argv[], int argc)
{
pGenController priv = NULL;
pAsyncQueue assi = NULL;
char buffer[2048];
pAsyncUnit uni = NULL;
priv = (pGenController) self->pPrivate;
assert(priv != NULL);
if (argc < 4) {
snprintf(buffer, 2048,
"ERROR: insufficient arguments to %s asynconnect", argv[0]);
SCWrite(pCon, buffer, eError);
return 0;
}
assi =
(pAsyncQueue) FindCommandData(pServ->pSics, argv[3], "AsyncQueue");
if (assi == NULL) {
snprintf(buffer, 2048, "ERROR: %s not found or no AsyncQueue",
argv[3]);
SCWrite(pCon, buffer, eError);
return 0;
}
priv->comContext = assi;
priv->killComContext = NULL; /* not ours, cleaned up by AsyncQueue module */
priv->enqueueNode = AsyncEnqueueNode;
priv->enqueueNodeHead = AsyncEnqueueNodeHead;
priv->replyCallback = AsyncReply;
priv->comError = GCOK;
/*
* This unit is solely for the purpose of receiving event notifications
*/
uni = AsyncUnitFromQueue(assi);
SCSendOK(pCon);
return 1;
}
/*---------------------------------------------------------------------------*/
int GenControllerConfigure(SConnection * pCon, SicsInterp * pSics,
void *pData, int argc, char *argv[])
{
pSICSOBJ controller = NULL;
pGenController self = NULL;
char buffer[2048];
if (argc < 3) {
snprintf(buffer, 2048, "ERROR: insufficient arguments to %s", argv[0]);
SCWrite(pCon, buffer, eError);
return 0;
}
controller =
(pSICSOBJ) FindCommandData(pSics, argv[2], "GenericController");
if (controller == NULL) {
snprintf(buffer, 2048, "ERROR: controller %s not found", argv[2]);
SCWrite(pCon, buffer, eError);
return 0;
}
strtolower(argv[1]);
if (strcmp(argv[1], "makepar") == 0) {
return MakeGenPar(controller, pCon, argv, argc);
} else if (strcmp(argv[1], "asynconnect") == 0) {
return ConnectAsync(controller, pCon, argv, argc);
} else {
SCWrite(pCon, "ERROR: argument to GenControllerConfigure not found",
eError);
return 0;
}
return 1;
}
/*---------------------------------------------------------------------------*/
static void killGeneric(void *data)
{
pGenController self = (pGenController) data;
if (self == NULL) {
return;
}
if (self->comContext != NULL && self->killComContext != NULL) {
self->killComContext(self->comContext);
}
free(self);
}
/*---------------------------------------------------------------------------*/
static int EnqueFunc(pSICSOBJ self, SConnection * pCon, pHdb commandNode,
pHdb par[], int nPar)
{
pGenController priv = NULL;
pHdb node = NULL;
char buffer[512];
priv = (pGenController) self->pPrivate;
assert(priv != NULL);
assert(nPar >= 1);
node = GetHipadabaNode(self->objectNode, par[0]->value.v.text);
if (node == NULL) {
snprintf(buffer, 511, "ERROR: node %s to enqueue not found",
par[0]->value.v.text);
SCWrite(pCon, buffer, eError);
return 0;
}
if (priv->enqueueNode != NULL) {
priv->enqueueNode(self, pCon, node);
} else {
SCWrite(pCon, "ERROR: GenController NOT configured", eError);
return 0;
}
return 1;
}
/*---------------------------------------------------------------------------*/
static int EnqueHeadFunc(pSICSOBJ self, SConnection * pCon,
Hdb commandNode, pHdb par[], int nPar)
{
pGenController priv = NULL;
pHdb node = NULL;
char buffer[512];
priv = (pGenController) self->pPrivate;
assert(priv != NULL);
assert(nPar >= 1);
node = GetHipadabaNode(self->objectNode, par[0]->value.v.text);
if (node == NULL) {
snprintf(buffer, 511, "ERROR: node %s to enqueue not found",
par[0]->value.v.text);
SCWrite(pCon, buffer, eError);
return 0;
}
if (priv->enqueueNodeHead != NULL) {
priv->enqueueNodeHead(self, pCon, node);
} else {
SCWrite(pCon, "ERROR: GenController NOT configured", eError);
return 0;
}
return 1;
}
/*---------------------------------------------------------------------------*/
int GenControllerFactory(SConnection * pCon, SicsInterp * pSics,
void *pData, int argc, char *argv[])
{
pSICSOBJ pNew = NULL;
pGenController priv = NULL;
hdbValue funcValue, textValue;
pHdb node = NULL;
char line[132];
int status;
if (argc < 2) {
SCWrite(pCon,
"ERROR: insufficient number of arguments to GenControllerFactrory",
eError);
return 0;
}
priv = malloc(sizeof(GenController));
if (priv == NULL) {
SCWrite(pCon, "ERROR: out of memory in GenControllerFactory", eError);
return 0;
}
memset(priv, 0, sizeof(GenController));
pNew = MakeSICSOBJ(argv[1], "GenericController");
if (pNew == NULL) {
SCWrite(pCon, "ERROR: out of memory in GenControllerFactory", eError);
return 0;
}
pNew->pPrivate = priv;
pNew->KillPrivate = killGeneric;
textValue = MakeHdbText("Undefined");
funcValue = MakeHdbFunc((voidFunc *) EnqueFunc);
node = MakeSICSHdbPar("enqueue", usUser, funcValue);
AddSICSHdbPar(node, "node", usUser, textValue);
AppendHipadabaCallback(node, MakeSICSFuncCallback(pNew));
AddHipadabaChild(pNew->objectNode, node, NULL);
funcValue = MakeHdbFunc((voidFunc *) EnqueHeadFunc);
node = MakeSICSHdbPar("enqueuehead", usUser, funcValue);
AddSICSHdbPar(node, "node", usUser, textValue);
AppendHipadabaCallback(node, MakeSICSFuncCallback(pNew));
AddHipadabaChild(pNew->objectNode, node, NULL);
status = AddCommand(pSics, argv[1], InvokeSICSOBJ, KillSICSOBJ, pNew);
if (status != 1) {
KillSICSOBJ(pNew);
SCPrintf(pCon, eError, "ERROR: failed create duplicate command %s",
argv[1]);
return 0;
}
SCSendOK(pCon);
return 1;
}

View File

@ -1,37 +0,0 @@
/**
* This is a generic controller for devices in SICS. In its default configuration it
* will be configurable via Tcl scripts and used AsynqQueue for communication. But
* it is suitably generic to support other mechanisms as well.
*
* copyright: see file COPYRIGHT
*
* Mark Koennecke, November 2007
*/
#ifndef GENERICCONTROLLER_H_
#define GENERICCONTROLLER_H_
#include <asyncqueue.h>
#include <sicshipadaba.h>
#define GCTIMEOUT 5001
#define GCDISCONNECT 5002
#define GCOK 5000
#define GCRECONNECT 5003
#define GCRETRY 5004
typedef struct {
int (*enqueueNode) (pSICSOBJ self, SConnection * pCon, pHdb node);
int (*enqueueNodeHead) (pSICSOBJ self, SConnection * pCon, pHdb node);
int (*replyCallback) (pSICSOBJ self, SConnection * pCon, pHdb node,
char *replyCommand, char *reply, int replylen);
void *comContext;
void (*killComContext) (void *data);
int comError;
} GenController, *pGenController;
/*---------------------------------------------------------------------------*/
int GenControllerFactory(SConnection * pCon, SicsInterp * pSics,
void *pData, int argc, char *argv[]);
/*---------------------------------------------------------------------------*/
int GenControllerConfigure(SConnection * pCon, SicsInterp * pSics,
void *pData, int argc, char *argv[]);
#endif /*GENERICCONTROLLER_H_ */

View File

@ -1,524 +0,0 @@
/**
* This is the new Hipadaba based queuing system in support of the MountainGum
* user interface.
*
* copyright: see file COPYRIGHT
*
* Mark Koennecke, July 2007
*/
#include <stdlib.h>
#include <assert.h>
#include <sics.h>
#include "sicsobj.h"
#include "hdbqueue.h"
#include "sicshipadaba.h"
#include "dynstring.h"
#include "exeman.h"
#include "macro.h"
/*--------------------------------------------------------------------------*/
typedef struct {
int iStop;
int isRunning;
SConnection *pCon;
} HdbQueue, *pHdbQueue;
/*--------------------------------------------------------------------------*/
static pHdbCallback CopyCallbackChain(pHdbCallback source)
{
pHdbCallback current = NULL;
pHdbCallback result = NULL;
pHdbCallback head = NULL;
pHdbCallback tail = NULL;
current = source;
while (current != NULL) {
result = MakeHipadabaCallback(current->userCallback,
current->userData,
NULL, current->id, current->internalID);
if (head == NULL) {
head = result;
tail = result;
} else {
tail->next = result;
result->previous = tail;
tail = result;
}
current = current->next;
}
return head;
}
/*---------------------------------------------------------------------------*/
static pHdb MakeNewEntry(char *name, pHdbCallback update)
{
pHdb entry = NULL, child = NULL;
hdbValue v;
v = MakeHdbText("Undefined");
entry = MakeHipadabaNode(name, HIPNONE, 1);
entry->updateCallbacks = CopyCallbackChain(update);
child = MakeSICSHdbPar("description", usUser, v);
child->updateCallbacks = CopyCallbackChain(update);
AddHipadabaChild(entry, child, NULL);
child = MakeSICSHdbPar("commands", usUser, v);
child->updateCallbacks = CopyCallbackChain(update);
AddHipadabaChild(entry, child, NULL);
child = MakeSICSHdbPar("log", usUser, v);
child->updateCallbacks = CopyCallbackChain(update);
AddHipadabaChild(entry, child, NULL);
return entry;
}
/*---------------------------------------------------------------------------*/
static int EnqueFunc(pSICSOBJ self, SConnection * pCon, Hdb commandNode,
pHdb par[], int nPar)
{
pHdb entry = NULL;
pHdb work = NULL;
char name[80];
hdbValue v;
if (nPar < 1) {
SCWrite(pCon, "ERROR: internal: not enough parameters to EnqueFunc",
eError);
return 0;
}
/*
* new entry
*/
memset(&v, 0, sizeof(hdbValue));
work = GetHipadabaNode(self->objectNode, "control/maxEntry");
assert(work != NULL);
snprintf(name, 80, "%3.3d", work->value.v.intValue);
entry = MakeNewEntry(name, work->updateCallbacks);
if (entry == NULL) {
SCWrite(pCon, "ERROR: out of memory in EnqueFunc", eError);
return 0;
}
/*
* Update maxEntry
*/
cloneHdbValue(&work->value, &v);
v.v.intValue++;
UpdateHipadabaPar(work, v, pCon);
work = GetHipadabaNode(self->objectNode, "queue");
assert(work != NULL);
AddHipadabaChild(work, entry, pCon);
/*
* save description
*/
work = GetHipadabaNode(entry, "description");
assert(work != NULL);
UpdateHipadabaPar(work, par[0]->value, pCon);
return 1;
}
/*---------------------------------------------------------------------------*/
static int AddCmdData(pSICSOBJ self, SConnection * pCon, Hdb comNode,
pHdb par[], int nPar)
{
pHdb work = NULL;
pHdb commandNode = NULL;
char name[80];
pDynString txt = NULL;
if (nPar < 1) {
SCWrite(pCon, "ERROR: internal: not enough parameters to AddCmdData",
eError);
return 0;
}
work = GetHipadabaNode(self->objectNode, "control/maxEntry");
assert(work != NULL);
snprintf(name, 80, "queue/%3.3d/commands", work->value.v.intValue - 1);
commandNode = GetHipadabaNode(self->objectNode, name);
if (commandNode == NULL) {
SCWrite(pCon, "ERROR: Internal error in AddCommand", eError);
return 0;
}
txt = CreateDynString(80, 80);
if (strstr(commandNode->value.v.text, "Undefined") == NULL) {
DynStringCopy(txt, commandNode->value.v.text);
}
DynStringConcat(txt, par[0]->value.v.text);
DynStringConcat(txt, "\n");
free(commandNode->value.v.text);
commandNode->value.v.text = strdup(GetCharArray(txt));
NotifyHipadabaPar(commandNode, pCon);
DeleteDynString(txt);
return 1;
}
/*--------------------------------------------------------------------------*/
static void sequentialNames(pHdb obj, SConnection * pCon)
{
pHdb work = NULL;
pHdb current = NULL;
int count = 0;
char name[80];
work = GetHipadabaNode(obj, "queue");
assert(work != NULL);
current = work->child;
while (current != NULL) {
snprintf(name, 80, "%3.3d", count);
if (current->name != NULL) {
free(current->name);
}
current->name = strdup(name);
count++;
current = current->next;
}
InvokeCallbackChain(work->treeChangeCallbacks, work, pCon, work->value);
work = GetHipadabaNode(obj, "control/maxEntry");
assert(work != NULL);
work->value.v.intValue = count;
NotifyHipadabaPar(work, pCon);
}
/*---------------------------------------------------------------------------*/
static int Dequeue(pSICSOBJ self, SConnection * pCon, pHdb commandNode,
pHdb par[], int nPar)
{
pHdb work = NULL;
char name[80];
pHdbQueue priv = (pHdbQueue) self->pPrivate;
if (priv->isRunning == 1) {
SCWrite(pCon, "ERROR: cannot dequeue while running", eError);
return 0;
}
if (nPar < 1) {
SCWrite(pCon, "ERROR: internal: not enough parameters to Dequeue",
eError);
return 0;
}
snprintf(name, 80, "queue/%3.3d", par[0]->value.v.intValue);
work = GetHipadabaNode(self->objectNode, name);
if (work != NULL) {
DeleteHipadabaNode(work, pCon);
sequentialNames(self->objectNode, pCon);
return 1;
}
return 0;
}
/*---------------------------------------------------------------------------*/
static int Clean(pSICSOBJ self, SConnection * pCon, Hdb commandNode,
pHdb par[], int nPar)
{
int i;
pHdb current = NULL, queue = NULL;
pHdb currentEntry = NULL, tmp = NULL;
pHdbQueue priv = (pHdbQueue) self->pPrivate;
if (priv->isRunning == 1) {
SCWrite(pCon, "ERROR: cannot clean while running", eError);
return 0;
}
currentEntry = GetHipadabaNode(self->objectNode, "control/currentEntry");
queue = GetHipadabaNode(self->objectNode, "queue");
current = queue->child;
for (i = 0; i < currentEntry->value.v.intValue; i++) {
if (current != NULL) {
tmp = current->next;
DeleteNodeData(current);
current = tmp;
}
}
queue->child = tmp;
currentEntry->value.v.intValue = 0;
sequentialNames(self->objectNode, pCon);
NotifyHipadabaPar(currentEntry, pCon);
return 1;
}
/*---------------------------------------------------------------------------*/
static int CleanAll(pSICSOBJ self, SConnection * pCon, pHdb commandNode,
pHdb par[], int nPar)
{
int i;
pHdb current = NULL, queue = NULL;
pHdb currentEntry = NULL, tmp;
pHdbQueue priv = (pHdbQueue) self->pPrivate;
if (priv->isRunning == 1) {
SCWrite(pCon, "ERROR: cannot clear queue while executing", eError);
return 0;
}
currentEntry = GetHipadabaNode(self->objectNode, "control/currentEntry");
queue = GetHipadabaNode(self->objectNode, "queue");
current = queue->child;
while (current != NULL) {
tmp = current->next;
DeleteNodeData(current);
current = tmp;
}
queue->child = NULL;
currentEntry->value.v.intValue = 0;
sequentialNames(self->objectNode, pCon);
NotifyHipadabaPar(currentEntry, pCon);
return 1;
}
/*----------------------------------------------------------------------------*/
static int QueueTask(void *pData)
{
pSICSOBJ self = (pSICSOBJ) pData;
int status, pos;
pHdb work = NULL;
pHdb exeNode = NULL;
pHdb max = NULL;
char name[80];
pHdbQueue priv = (pHdbQueue) self->pPrivate;
if (priv->iStop == 1) {
priv->isRunning = 0;
return 0;
}
work = GetHipadabaNode(self->objectNode, "control/currentEntry");
max = GetHipadabaNode(self->objectNode, "control/maxEntry");
assert(work != NULL && max != NULL);
pos = work->value.v.intValue;
snprintf(name, 80, "queue/%3.3d", pos);
exeNode = GetHipadabaNode(self->objectNode, name);
if (exeNode != NULL) {
MacroPush(priv->pCon);
exeHdbNode(exeNode, priv->pCon);
MacroPop();
}
if (priv->iStop == 1 || SCGetInterrupt(priv->pCon) != eContinue) {
priv->isRunning = 0;
return 0;
}
pos++;
work->value.v.intValue = pos;
NotifyHipadabaPar(work, priv->pCon);
if (pos >= max->value.v.intValue) {
priv->isRunning = 0;
return 0;
}
return 1;
}
/*---------------------------------------------------------------------------*/
static int Start(pSICSOBJ self, SConnection * pCon, pHdb commandNode,
pHdb par[], int nPar)
{
pHdbQueue priv = (pHdbQueue) self->pPrivate;
priv->iStop = 0;
priv->pCon = pCon;
if (priv->isRunning == 1) {
SCWrite(pCon, "ERROR: Hdbqueue is already running", eError);
return 0;
}
priv->isRunning = 1;
TaskRegister(pServ->pTasker, QueueTask, NULL, NULL, self, 10);
return 1;
}
/*---------------------------------------------------------------------------*/
static int Restart(pSICSOBJ self, SConnection * pCon, pHdb commandNode,
pHdb par[], int nPar)
{
pHdbQueue priv = (pHdbQueue) self->pPrivate;
pHdb maxCurrent = NULL;
maxCurrent = GetHipadabaNode(self->objectNode, "control/currentEntry");
if (maxCurrent != NULL) {
maxCurrent->value.v.intValue = 0;
NotifyHipadabaPar(maxCurrent, pCon);
}
return Start(self, pCon, commandNode, par, nPar);
}
/*---------------------------------------------------------------------------*/
static int Stop(pSICSOBJ self, SConnection * pCon, pHdb commandNode,
pHdb par[], int nPar)
{
pHdbQueue priv = (pHdbQueue) self->pPrivate;
priv->iStop = 1;
return 1;
}
/*----------------------------------------------------------------------------*/
static int Move(pSICSOBJ self, SConnection * pCon, pHdb commandNode,
pHdb par[], int nPar)
{
pHdb moveNode = NULL;
pHdb insertNode = NULL;
pHdb prevNode = NULL, queueNode = NULL;
pHdb tmp;
char name[80];
pHdbQueue priv = (pHdbQueue) self->pPrivate;
if (priv->isRunning == 1) {
SCWrite(pCon, "ERROR: cannot move while running", eError);
return 0;
}
if (nPar < 2) {
SCWrite(pCon, "ERROR: internal: not enough parameters to Move",
eError);
return 1;
}
if (par[1]->value.v.intValue == par[0]->value.v.intValue + 1) {
/*
* already in right sequence, nothing to do
*/
return 1;
}
snprintf(name, 80, "queue/%3.3d", par[1]->value.v.intValue);
moveNode = GetHipadabaNode(self->objectNode, name);
snprintf(name, 80, "queue/%3.3d", par[0]->value.v.intValue);
insertNode = GetHipadabaNode(self->objectNode, name);
if (moveNode == NULL || insertNode == NULL) {
SCWrite(pCon,
"ERROR: move not possible, participating nodes not found",
eError);
return 0;
}
queueNode = GetHipadabaNode(self->objectNode, "queue");
if (moveNode == queueNode->child) {
queueNode->child = queueNode->child->next;
moveNode->next = insertNode->next;
insertNode->next = moveNode;
} else {
prevNode = queueNode->child;
while (prevNode != NULL && prevNode->next != moveNode) {
prevNode = prevNode->next;
}
if (insertNode == queueNode->child) {
/*
* insert at top
*/
tmp = queueNode->child;
queueNode->child = moveNode;
prevNode->next = moveNode->next;
moveNode->next = tmp;
} else {
tmp = insertNode->next;
insertNode->next = moveNode;
prevNode->next = moveNode->next;
moveNode->next = tmp;
}
}
sequentialNames(self->objectNode, pCon);
return 1;
}
/*---------------------------------------------------------------------------*/
static void Configure(pSICSOBJ self)
{
pHdb n = NULL, par = NULL;
hdbValue intValue, textValue, funcValue;
pHdb obj = self->objectNode;
intValue = MakeHdbInt(0);
textValue = MakeHdbText("Undefined");
n = MakeHipadabaNode("control", HIPNONE, 1);
AddHipadabaChild(obj, n, NULL);
AddSICSHdbPar(n, "maxEntry", usInternal, intValue);
AddSICSHdbPar(n, "currentEntry", usInternal, intValue);
n = MakeHipadabaNode("queue", HIPNONE, 1);
AddHipadabaChild(obj, n, NULL);
funcValue = MakeSICSFunc(EnqueFunc);
n = MakeSICSHdbPar("enqueue", usUser, funcValue);
AddSICSHdbPar(n, "description", usUser, textValue);
AddHipadabaChild(obj, n, NULL);
AppendHipadabaCallback(n, HCBSET, MakeSICSFuncCallback(self));
funcValue = MakeSICSFunc(AddCmdData);
n = MakeSICSHdbPar("addcommand", usUser, funcValue);
AddSICSHdbPar(n, "command", usUser, textValue);
AddHipadabaChild(obj, n, NULL);
AppendHipadabaCallback(n, HCBSET, MakeSICSFuncCallback(self));
funcValue = MakeSICSFunc(Dequeue);
n = MakeSICSHdbPar("dequeue", usUser, funcValue);
AddHipadabaChild(obj, n, NULL);
AddSICSHdbPar(n, "index", usUser, intValue);
AppendHipadabaCallback(n, HCBSET, MakeSICSFuncCallback(self));
funcValue = MakeSICSFunc(Clean);
n = MakeSICSHdbPar("clean", usUser, funcValue);
AddHipadabaChild(obj, n, NULL);
AppendHipadabaCallback(n, HCBSET, MakeSICSFuncCallback(self));
funcValue = MakeSICSFunc(CleanAll);
n = MakeSICSHdbPar("cleanall", usUser, funcValue);
AddHipadabaChild(obj, n, NULL);
AppendHipadabaCallback(n, HCBSET, MakeSICSFuncCallback(self));
funcValue = MakeSICSFunc(Start);
n = MakeSICSHdbPar("start", usUser, funcValue);
AddHipadabaChild(obj, n, NULL);
AppendHipadabaCallback(n, HCBSET, MakeSICSFuncCallback(self));
funcValue = MakeSICSFunc(Restart);
n = MakeSICSHdbPar("restart", usUser, funcValue);
AddHipadabaChild(obj, n, NULL);
AppendHipadabaCallback(n, HCBSET, MakeSICSFuncCallback(self));
funcValue = MakeSICSFunc(Stop);
n = MakeSICSHdbPar("stop", usUser, funcValue);
AddHipadabaChild(obj, n, NULL);
AppendHipadabaCallback(n, HCBSET, MakeSICSFuncCallback(self));
funcValue = MakeSICSFunc(Move);
n = MakeSICSHdbPar("move", usUser, funcValue);
AddHipadabaChild(obj, n, NULL);
AddSICSHdbPar(n, "moveindex", usUser, intValue);
AddSICSHdbPar(n, "insertindex", usUser, intValue);
AppendHipadabaCallback(n, HCBSET, MakeSICSFuncCallback(self));
}
/*---------------------------------------------------------------------------*/
int MakeHDBQueue(SConnection * pCon, SicsInterp * pSics, void *pData,
int argc, char *argv[])
{
pSICSOBJ self = NULL;
pHdbQueue priv = NULL;
priv = (pHdbQueue) malloc(sizeof(HdbQueue));
self = SetupSICSOBJ(pCon, pSics, pData, argc, argv);
if (self == NULL || priv == NULL) {
return 0;
}
Configure(self);
memset(priv, 0, sizeof(HdbQueue));
self->pPrivate = priv;
self->KillPrivate = free;
return 1;
}

View File

@ -1,15 +0,0 @@
/**
* This is the new Hipadab based queuing system in support of the MountainGum
* user interface.
*
* copyright: see file COPYRIGHT
*
* Mark Koennecke, July 2007
*/
#ifndef HDBQUEUE_H_
#define HDBQUEUE_H_
int MakeHDBQueue(SConnection * pCon, SicsInterp * pSics, void *pData,
int argc, char *argv[]);
#endif /*HDBQUEUE_H_ */

402
hklscan.c
View File

@ -1,402 +0,0 @@
/*--------------------------------------------------------------------------
H K L S C A N
A class for doing scans in reciprocal space for a four circle
diffractometer. All the hard work is done in the scan and hkl objects.
copyright: see copyright.h
Mark Koennecke, June 1999
This is obsolete: h,k,l are now drivable. Logged variables have been added
to the scan module. The command is now implemented through scripts.
This module is left in the source tree in order to allow for a quick
reinstallation in case of problems but should be retired from the
source tree in the shutdown 2007
Mark Koennecke, January 2006
--------------------------------------------------------------------------*/
#include <stdlib.h>
#include <stdio.h>
#include <assert.h>
#include <tcl.h>
#include "fortify.h"
#include "sics.h"
#include "scan.h"
#include "hkl.h"
#include "scan.i"
#include "matrix/matrix.h"
#include "hkl.i"
#include "hklscan.i"
#include "hklscan.h"
/*-----------------------------------------------------------------------*/
static void KillHklscan(void *pData)
{
pHklscan self = NULL;
self = (pHklscan) pData;
if (!self) {
return;
}
if (self->pDes) {
DeleteDescriptor(self->pDes);
}
free(self);
}
/*------------------------------------------------------------------------*/
int HklscanFactory(SConnection * pCon, SicsInterp * pSics, void *pData,
int argc, char *argv[4])
{
pHklscan pNew = NULL;
char pBueffel[512];
int iRet;
/* check number of arguments */
if (argc < 3) {
SCWrite(pCon, "ERROR: expected two arguments to MakeHklscan", eError);
return 0;
}
/* allocate space */
pNew = (pHklscan) malloc(sizeof(sHklscan));
if (!pNew) {
SCWrite(pCon, "ERROR: out of memory in MakeHklscan", eError);
return 0;
}
memset(pNew, 0, sizeof(sHklscan));
pNew->pDes = CreateDescriptor("Hklscan");
/* find scan object */
pNew->pScan = (pScanData) FindCommandData(pSics, argv[1], "ScanObject");
if (!pNew->pScan) {
snprintf(pBueffel,sizeof(pBueffel)-1, "ERROR: %s not found or no scan object", argv[1]);
SCWrite(pCon, pBueffel, eError);
KillHklscan(pNew);
return 0;
}
/* find HKL object */
pNew->pCalc = (pHKL) FindCommandData(pSics, argv[2],
"4-Circle-Calculus");
if (!pNew->pCalc) {
snprintf(pBueffel,sizeof(pBueffel)-1, "ERROR: %s not found or no HKL object", argv[2]);
SCWrite(pCon, pBueffel, eError);
KillHklscan(pNew);
return 0;
}
/* alright. Install command */
iRet = AddCommand(pSics, "__hklscan", HklscanAction, KillHklscan, pNew);
if (!iRet) {
SCWrite(pCon, "ERROR: duplicate command hklscan NOT created", eError);
KillHklscan(pNew);
return 0;
}
return 1;
}
/*------------------------------------------------------------------------*/
static int HklscanDrive(pScanData pScan, int iPoint)
{
pHklscan self = NULL;
int i, iRet;
assert(pScan);
self = (pHklscan) pScan->pSpecial;
assert(self);
/* calculate new Positions */
for (i = 0; i < 3; i++) {
self->fPos[i] = self->fStart[i] + iPoint * self->fStep[i];
}
iRet = DriveHKL(self->pCalc, self->fPos, 0., 0, pScan->pCon);
if (!iRet) {
SCWrite(pScan->pCon, "ERROR: aborting hklscan", eError);
}
return iRet;
}
/*------------------------------------------------------------------------*/
static int WriteHklscanPoint(pScanData self, int iPoint)
{
pHklscan pHaSca = NULL;
int i, i2;
char pLine[512], pItem[30], pInfo[512];
pVarEntry pVar = NULL;
pCountEntry pData = NULL;
void *pPtr = NULL;
assert(self);
pHaSca = (pHklscan) self->pSpecial;
assert(pHaSca);
assert(self->pCon);
assert(self->pSics);
if (!self->fd) {
self->fd = fopen(self->pFile, "r+");
if (!self->fd) {
SCWrite(self->pCon, "ERROR: failed to reopen scan file during scan",
eError);
return 0;
}
}
/* jump to end of header */
fseek(self->fd, self->lPos, SEEK_SET);
if (self->iChannel != 0) {
fprintf(self->fd, "WARNING: Scanning monitor %d\n", self->iChannel);
}
/* make the data header */
snprintf(pLine,sizeof(pLine)-1, "%-5s", "NP");
snprintf(pInfo,sizeof(pInfo)-1, "Scanning Variables: H, K, L STEP: %8.3f %8.3f %8.3f",
pHaSca->fStep[0], pHaSca->fStep[1], pHaSca->fStep[2]);
strcat(pLine, "H K L ");
for (i = 0; i < self->iScanVar; i++) {
DynarGet(self->pScanVar, i, &pPtr);
pVar = (pVarEntry) pPtr;
if (pVar) {
snprintf(pItem,sizeof(pItem)-1, "%-6.6s ", pVar->Name);
strcat(pLine, pItem);
}
}
strcat(pLine, "Counts ");
strcat(pLine, " Monitor1 ");
snprintf(pItem,sizeof(pItem)-1, "\n%d Points,", self->iNP);
strcat(pInfo, pItem);
if (self->iMode == eTimer) {
strcat(pInfo, " Mode: Timer,");
} else {
strcat(pInfo, " Mode: Monitor,");
}
snprintf(pItem,sizeof(pItem)-1, " Preset %f", self->fPreset);
strcat(pInfo, pItem);
fprintf(self->fd, "%s\n", pInfo);
fprintf(self->fd, "%s\n", pLine);
/* print an addon to the status line going to the screen */
snprintf(pLine,sizeof(pLine)-1, "NP H K L ");
SCWrite(self->pCon, pLine, eWarning);
snprintf(pLine,sizeof(pLine)-1, "%-5d%-8.4f%-8.4f%-8.4f ", iPoint, pHaSca->fPos[0],
pHaSca->fPos[1], pHaSca->fPos[2]);
SCWrite(self->pCon, pLine, eWarning);
/* now the scan points */
for (i = 0; i < self->iCounts; i++) {
snprintf(pLine,sizeof(pLine)-1, "%-5d", i);
/* print HKL */
for (i2 = 0; i2 < 3; i2++) {
snprintf(pItem,sizeof(pItem)-1, " %-8.4f",
pHaSca->fStart[i2] + i * pHaSca->fStep[i2]);
strcat(pLine, pItem);
}
/* print chi, ph, om */
for (i2 = 0; i2 < self->iScanVar; i2++) {
DynarGet(self->pScanVar, i2, &pPtr);
pVar = (pVarEntry) pPtr;
if (pVar) {
snprintf(pItem,sizeof(pItem)-1, " %-7.2f", GetScanVarPos(pVar, i));
strcat(pLine, pItem);
}
}
/* print Counts & Monitor */
DynarGet(self->pCounts, i, &pPtr);
pData = (pCountEntry) pPtr;
if (pData) {
snprintf(pItem,sizeof(pItem)-1, " %-13ld", pData->lCount);
strcat(pLine, pItem);
snprintf(pItem,sizeof(pItem)-1, " %-12ld", pData->Monitors[0]);
strcat(pLine, pItem);
}
fprintf(self->fd, "%s\n", pLine);
}
/* done */
fprintf(self->fd, "END-OF-DATA\n");
fclose(self->fd);
self->fd = NULL;
return 1;
}
/*-------------------------------------------------------------------*/
int Hklscan(pHklscan self, SConnection * pCon,
int iNP, int iMode, float fPreset)
{
int iRet;
float fVal;
assert(self);
/* configure the scan thing for our bizarre purpose */
ClearScanVar(self->pScan);
MotorGetPar(self->pCalc->pTheta, "softlowerlim", &fVal);
fVal += .5;
AddScanVar(self->pScan, pServ->pSics, pCon, self->pCalc->pTheta->name,
fVal, 0.);
MotorGetPar(self->pCalc->pOmega, "softlowerlim", &fVal);
fVal += .5;
AddScanVar(self->pScan, pServ->pSics, pCon, self->pCalc->pOmega->name,
fVal, 0.);
MotorGetPar(self->pCalc->pChi, "softlowerlim", &fVal);
fVal += .5;
AddScanVar(self->pScan, pServ->pSics, pCon, self->pCalc->pChi->name,
fVal, 0.);
MotorGetPar(self->pCalc->pPhi, "softlowerlim", &fVal);
fVal += .5;
AddScanVar(self->pScan, pServ->pSics, pCon, self->pCalc->pPhi->name,
fVal, 0.);
self->pScan->WriteScanPoints = WriteHklscanPoint;
self->pScan->ScanDrive = HklscanDrive;
self->pScan->pSpecial = self;
self->pScan->PrepareScan = NonCheckPrepare;
/* scan */
iRet = DoScan(self->pScan, iNP, iMode, fPreset, pServ->pSics, pCon);
/* unset all */
ClearScanVar(self->pScan);
ResetScanFunctions(self->pScan);
self->pScan->pSpecial = NULL;
return iRet;
}
/*-------------------------------------------------------------------------*/
int HklscanAction(SConnection * pCon, SicsInterp * pSics, void *pData,
int argc, char *argv[])
{
char pBueffel[512];
int iRet, iMode, iNP, iPoint;
pHklscan self = NULL;
double dVal;
float fPreset;
void *pPtr;
assert(pCon);
assert(pSics);
assert(pData);
self = (pHklscan) pData;
/* check for the command word */
if (argc < 2) {
SCWrite(pCon, "ERROR: Insufficient number of arguments to hklscan",
eError);
return 0;
}
/* do work according to command word */
strtolower(argv[1]);
if (strcmp(argv[1], "start") == 0) {
if (!SCMatchRights(pCon, usUser)) {
return 0;
}
if (argc < 5) {
SCWrite(pCon,
"Insufficient number of arguments to hklscan", eError);
return 0;
}
iRet = Tcl_GetDouble(pSics->pTcl, argv[2], &dVal);
if (iRet != TCL_OK) {
snprintf(pBueffel,sizeof(pBueffel)-1, "ERROR: failed to convert %s to number", argv[2]);
SCWrite(pCon, pBueffel, eError);
return 0;
}
self->fStart[0] = (float) dVal;
iRet = Tcl_GetDouble(pSics->pTcl, argv[3], &dVal);
if (iRet != TCL_OK) {
snprintf(pBueffel,sizeof(pBueffel)-1, "ERROR: failed to convert %s to number", argv[3]);
SCWrite(pCon, pBueffel, eError);
return 0;
}
self->fStart[1] = (float) dVal;
iRet = Tcl_GetDouble(pSics->pTcl, argv[4], &dVal);
if (iRet != TCL_OK) {
snprintf(pBueffel,sizeof(pBueffel)-1, "ERROR: failed to convert %s to number", argv[4]);
SCWrite(pCon, pBueffel, eError);
return 0;
}
self->fStart[2] = (float) dVal;
SCSendOK(pCon);
return 1;
} else if (strcmp(argv[1], "step") == 0) {
if (!SCMatchRights(pCon, usUser)) {
return 0;
}
if (argc < 5) {
SCWrite(pCon,
"Insufficient number of arguments to hklscan", eError);
return 0;
}
iRet = Tcl_GetDouble(pSics->pTcl, argv[2], &dVal);
if (iRet != TCL_OK) {
snprintf(pBueffel,sizeof(pBueffel)-1, "ERROR: failed to convert %s to number", argv[2]);
SCWrite(pCon, pBueffel, eError);
return 0;
}
self->fStep[0] = (float) dVal;
iRet = Tcl_GetDouble(pSics->pTcl, argv[3], &dVal);
if (iRet != TCL_OK) {
snprintf(pBueffel,sizeof(pBueffel)-1, "ERROR: failed to convert %s to number", argv[3]);
SCWrite(pCon, pBueffel, eError);
return 0;
}
self->fStep[1] = (float) dVal;
iRet = Tcl_GetDouble(pSics->pTcl, argv[4], &dVal);
if (iRet != TCL_OK) {
snprintf(pBueffel,sizeof(pBueffel)-1, "ERROR: failed to convert %s to number", argv[4]);
SCWrite(pCon, pBueffel, eError);
return 0;
}
self->fStep[2] = (float) dVal;
SCSendOK(pCon);
return 1;
} else if (strcmp(argv[1], "run") == 0) {
if (!SCMatchRights(pCon, usUser)) {
return 0;
}
if (argc < 5) {
SCWrite(pCon,
"Insufficient number of arguments to hklscan run", eError);
return 0;
}
iRet = Tcl_GetInt(pSics->pTcl, argv[2], &iNP);
if (iRet != TCL_OK) {
snprintf(pBueffel,sizeof(pBueffel)-1, "ERROR: failed to convert %s to number", argv[2]);
SCWrite(pCon, pBueffel, eError);
return 0;
}
/* interpret Mode */
if (strcmp(argv[3], "timer") == 0) {
iMode = eTimer;
} else if (strcmp(argv[3], "monitor") == 0) {
iMode = ePreset;
} else {
snprintf(pBueffel,sizeof(pBueffel)-1, "ERROR: %s not recognized as valid counter mode",
argv[3]);
SCWrite(pCon, pBueffel, eError);
return 0;
}
/* preset */
iRet = Tcl_GetDouble(pSics->pTcl, argv[4], &dVal);
if (iRet != TCL_OK) {
snprintf(pBueffel,sizeof(pBueffel)-1, "ERROR: expected number, got %s", argv[3]);
SCWrite(pCon, pBueffel, eError);
return 0;
}
fPreset = (float) dVal;
iRet = Hklscan(self, pCon, iNP, iMode, fPreset);
if (iRet) {
SCSendOK(pCon);
}
return iRet;
}
snprintf(pBueffel,sizeof(pBueffel)-1,
"ERROR: %s not recognized as command word to hklscan", argv[1]);
SCWrite(pCon, pBueffel, eError);
return 0;
}

View File

@ -1,25 +0,0 @@
/*--------------------------------------------------------------------------
H K L S C A N
A class for doing scans in reciprocal space. This makes only sense at an
four circle diffractometer. Most of the work is done in the HKL and scan
objects. This class just adapts and used both objects to do the right thing.
Mark Koennecke, June 1999
---------------------------------------------------------------------------*/
#ifndef HKLSCAN
#define HKLSCAN
typedef struct __HKLSCAN *pHklscan;
/*--------------------------------------------------------------------------*/
int HklScan(pHklscan self, SConnection * pCon, int iNP, int iMode,
float fPreset);
/*---------------- interpreter functions -----------------------------------*/
int HklscanFactory(SConnection * pCon, SicsInterp * pSics, void *pData,
int argc, char *argv[]);
int HklscanAction(SConnection * pCon, SicsInterp * pSics, void *pData,
int argc, char *argv[]);
#endif

View File

@ -1,17 +0,0 @@
/*-------------------------------------------------------------------------
Internal data structure for the hklscan object. DO NOT MODIFY.
Modifications only in hklscan.i
Mark Koennecke, June 1999
--------------------------------------------------------------------------*/
typedef struct __HKLSCAN {
pObjectDescriptor pDes;
pScanData pScan;
pHKL pCalc;
float fStart[3];
float fStep[3];
float fPos[3];
} sHklscan;

View File

@ -1,111 +0,0 @@
\subsection{hklscan}
hklscan is an object which implements scanning in reciprocal space. It belongs
to the four circle diffraction line of commands. It requires the hkl object
for doing four circle calculations and a scan object for doing the scanning.
The scan object is configured by overloading its WriteScanPoints and
ScanDrive functions to do the right thing for this. Thus most of the work
is done in scan and hkl.
hklscan has its own data structure looking like this:
\begin{flushleft} \small
\begin{minipage}{\linewidth} \label{scrap1}
$\langle$hklscandat {\footnotesize ?}$\rangle\equiv$
\vspace{-1ex}
\begin{list}{}{} \item
\mbox{}\verb@@\\
\mbox{}\verb@ typedef struct __HKLSCAN {@\\
\mbox{}\verb@ pObjectDescriptor pDes;@\\
\mbox{}\verb@ pScanData pScan;@\\
\mbox{}\verb@ pHKL pCalc; @\\
\mbox{}\verb@ float fStart[3];@\\
\mbox{}\verb@ float fStep[3];@\\
\mbox{}\verb@ float fPos[3];@\\
\mbox{}\verb@ } sHklscan;@\\
\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 object descriptor.
\item[pScan] The scan object used for scanning.
\item[pCalc] The hkl object used for crystallographic computations.
\item[fStart] The start values in H, K, L for scanning.
\item[fStep] The step width in H, K, L.
\item[fPos] The last position in H, K, L.
\end{description}
The hklscan object defines the following external interface:
\begin{flushleft} \small
\begin{minipage}{\linewidth} \label{scrap2}
$\langle$hklscanfunc {\footnotesize ?}$\rangle\equiv$
\vspace{-1ex}
\begin{list}{}{} \item
\mbox{}\verb@@\\
\mbox{}\verb@ typedef struct __HKLSCAN *pHklscan;@\\
\mbox{}\verb@/*--------------------------------------------------------------------------*/@\\
\mbox{}\verb@ int HklScan(pHklscan self, SConnection *pCon, int iNP, int iMode,@\\
\mbox{}\verb@ float fPreset);@\\
\mbox{}\verb@/*---------------- interpreter functions -----------------------------------*/@\\
\mbox{}\verb@ int HklscanFactory(SConnection *pCon, SicsInterp *pSics, void *pData,@\\
\mbox{}\verb@ int argc, char *argv[]);@\\
\mbox{}\verb@ int HklscanAction(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{flushleft} \small
\begin{minipage}{\linewidth} \label{scrap3}
\verb@"hklscan.i"@ {\footnotesize ? }$\equiv$
\vspace{-1ex}
\begin{list}{}{} \item
\mbox{}\verb@@\\
\mbox{}\verb@/*-------------------------------------------------------------------------@\\
\mbox{}\verb@ Internal data structure for the hklscan object. DO NOT MODIFY. @\\
\mbox{}\verb@ Modifications only in hklscan.i@\\
\mbox{}\verb@ @\\
\mbox{}\verb@ Mark Koennecke, June 1999@\\
\mbox{}\verb@--------------------------------------------------------------------------*/@\\
\mbox{}\verb@@$\langle$hklscandat {\footnotesize ?}$\rangle$\verb@@\\
\mbox{}\verb@@$\diamond$
\end{list}
\vspace{-2ex}
\end{minipage}\\[4ex]
\end{flushleft}
\begin{flushleft} \small
\begin{minipage}{\linewidth} \label{scrap4}
\verb@"hklscan.h"@ {\footnotesize ? }$\equiv$
\vspace{-1ex}
\begin{list}{}{} \item
\mbox{}\verb@@\\
\mbox{}\verb@/*--------------------------------------------------------------------------@\\
\mbox{}\verb@ H K L S C A N@\\
\mbox{}\verb@@\\
\mbox{}\verb@ A class for doing scans in reciprocal space. This makes only sense at an@\\
\mbox{}\verb@ four circle diffractometer. Most of the work is done in the HKL and scan@\\
\mbox{}\verb@ objects. This class just adapts and used both objects to do the right thing.@\\
\mbox{}\verb@@\\
\mbox{}\verb@ Mark Koennecke, June 1999@\\
\mbox{}\verb@---------------------------------------------------------------------------*/@\\
\mbox{}\verb@#ifndef HKLSCAN@\\
\mbox{}\verb@#define HKLSCAN@\\
\mbox{}\verb@@$\langle$hklscanfunc {\footnotesize ?}$\rangle$\verb@@\\
\mbox{}\verb@#endif@\\
\mbox{}\verb@@$\diamond$
\end{list}
\vspace{-2ex}
\end{minipage}\\[4ex]
\end{flushleft}

View File

@ -1,70 +0,0 @@
\subsection{hklscan}
hklscan is an object which implements scanning in reciprocal space. It belongs
to the four circle diffraction line of commands. It requires the hkl object
for doing four circle calculations and a scan object for doing the scanning.
The scan object is configured by overloading its WriteScanPoints and
ScanDrive functions to do the right thing for this. Thus most of the work
is done in scan and hkl.
hklscan has its own data structure looking like this:
@d hklscandat @{
typedef struct __HKLSCAN {
pObjectDescriptor pDes;
pScanData pScan;
pHKL pCalc;
float fStart[3];
float fStep[3];
float fPos[3];
} sHklscan;
@}
\begin{description}
\item[pDes] The standard object descriptor.
\item[pScan] The scan object used for scanning.
\item[pCalc] The hkl object used for crystallographic computations.
\item[fStart] The start values in H, K, L for scanning.
\item[fStep] The step width in H, K, L.
\item[fPos] The last position in H, K, L.
\end{description}
The hklscan object defines the following external interface:
@d hklscanfunc @{
typedef struct __HKLSCAN *pHklscan;
/*--------------------------------------------------------------------------*/
int HklScan(pHklscan self, SConnection *pCon, int iNP, int iMode,
float fPreset);
/*---------------- interpreter functions -----------------------------------*/
int HklscanFactory(SConnection *pCon, SicsInterp *pSics, void *pData,
int argc, char *argv[]);
int HklscanAction(SConnection *pCon, SicsInterp *pSics, void *pData,
int argc, char *argv[]);
@}
@o hklscan.i @{
/*-------------------------------------------------------------------------
Internal data structure for the hklscan object. DO NOT MODIFY.
Modifications only in hklscan.i
Mark Koennecke, June 1999
--------------------------------------------------------------------------*/
@<hklscandat@>
@}
@o hklscan.h @{
/*--------------------------------------------------------------------------
H K L S C A N
A class for doing scans in reciprocal space. This makes only sense at an
four circle diffractometer. Most of the work is done in the HKL and scan
objects. This class just adapts and used both objects to do the right thing.
Mark Koennecke, June 1999
---------------------------------------------------------------------------*/
#ifndef HKLSCAN
#define HKLSCAN
@<hklscanfunc@>
#endif
@}

View File

@ -12,7 +12,7 @@ SOBJ = network.o ifile.o conman.o SCinter.o splitter.o passwd.o \
macro.o ofac.o obpar.o obdes.o drive.o status.o intserv.o \
devexec.o mumo.o mumoconf.o selector.o selvar.o fupa.o lld.o \
lld_blob.o strrepl.o lin2ang.o fomerge.o napi5.o napi4.o\
script.o o2t.o alias.o napi.o nxdata.o stringdict.o sdynar.o \
script.o o2t.o alias.o napi.o stringdict.o sdynar.o \
histmem.o histdriv.o histsim.o interface.o callback.o nxio.o \
event.o emon.o evcontroller.o evdriver.o simev.o perfmon.o \
danu.o nxdict.o varlog.o stptok.o nread.o trigd.o cell.o\
@ -36,7 +36,7 @@ SOBJ = network.o ifile.o conman.o SCinter.o splitter.o passwd.o \
moregress.o multicounter.o regresscter.o histregress.o \
sicshdbadapter.o polldriv.o sicspoll.o statemon.o hmslave.o \
nwatch.o asyncqueue.o asyncprotocol.o sicsobj.o frame.o\
nxcopy.o nxinterhelper.o nxinter_wrap.o genericcontroller.o nxstack.o \
nxcopy.o nxinterhelper.o nxinter_wrap.o nxstack.o \
sctdriveadapter.o sctdriveobj.o reflist.o singlex.o fourmess.o \
sgclib.o sgfind.o sgio.o sgsi.o sghkl.o singlediff.o singlebi.o \
singlenb.o simindex.o simidx.o uselect.o singletas.o motorsec.o \

814
nxdata.c
View File

@ -1,814 +0,0 @@
/*--------------------------------------------------------------------------
N X D A T A
This implements the data file writing for the Powder diffractometers
HRPT and DMC.
Mark Koennecke, March-April 1997
Updated and expanded: Mark Koennecke, November 1999
Copyright:
Labor fuer Neutronenstreuung
Paul Scherrer Institut
CH-5423 Villigen-PSI
The authors hereby grant permission to use, copy, modify, distribute,
and license this software and its documentation for any purpose, provided
that existing copyright notices are retained in all copies and that this
notice is included verbatim in any distributions. No written agreement,
license, or royalty fee is required for any of the authorized uses.
Modifications to this software may be copyrighted by their authors
and need not follow the licensing terms described here, provided that
the new terms are clearly indicated on the first page of each file where
they apply.
IN NO EVENT SHALL THE AUTHORS OR DISTRIBUTORS BE LIABLE TO ANY PARTY
FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
ARISING OUT OF THE USE OF THIS SOFTWARE, ITS DOCUMENTATION, OR ANY
DERIVATIVES THEREOF, EVEN IF THE AUTHORS HAVE BEEN ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
THE AUTHORS AND DISTRIBUTORS SPECIFICALLY DISCLAIM ANY WARRANTIES,
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT. THIS SOFTWARE
IS PROVIDED ON AN "AS IS" BASIS, AND THE AUTHORS AND DISTRIBUTORS HAVE
NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR
MODIFICATIONS.
----------------------------------------------------------------------------*/
#include <string.h>
#include <stdlib.h>
#include <assert.h>
#include <math.h>
#include <time.h>
#include "fortify.h"
#include "sics.h"
#include "sicsvar.h"
#include "nxdict.h"
#include "modriv.h"
#include "motor.h"
#include "nxdata.h"
#include "nxutil.h"
#include "selector.h"
#include "selvar.h"
#include "countdriv.h"
#include "counter.h"
#include "danu.h"
#include "HistMem.h"
#include "udpquieck.h"
#include "evcontroller.h"
#include "nxscript.h"
#define DMCDETNAM "DMC-BF3-Detector"
#define DMCDETOB "detector"
#define HRPTDETNAM "Cerca-Detector"
/*-----------------------------------------------------------------------*/
static void SNError(void *pData, char *text)
{
SConnection *pCon;
assert(pData);
pCon = (SConnection *) pData;
SCWrite(pCon, text, eError);
}
/*-----------------------------------------------------------------------*/
char *SNXMakeFileName(SicsInterp * pSics, SConnection * pCon)
{
char *pPtr = NULL;
pPtr = makeFilename(pSics, pCon);
if (pPtr == NULL) {
pPtr = strdup("emergency.hdf");
}
return pPtr;
}
/*------------------------------------------------------------------------*/
char *SNXMakeFileNameOld(SicsInterp * pSics, SConnection * pCon)
{
pSicsVariable pPath = NULL, pPref = NULL, pEnd = NULL;
char *pRes = NULL;
int iLen, iNum, iYear;
char pNumText[10];
CommandList *pCom = NULL;
/* Try, get all the Variables */
pPath = FindVariable(pSics, "sicsdatapath");
pPref = FindVariable(pSics, "sicsdataprefix");
pCom = FindCommand(pSics, "sicsdatanumber");
pEnd = FindVariable(pSics, "sicsdatapostfix");
if ((!pPath) || (!pPref) || (!pCom) || (!pEnd)) {
SCWrite(pCon,
"ERROR: cannot read variables for automatic data file name creation",
eError);
SCWrite(pCon,
"ERROR: This is a VERY, VERY, VERY serious installation problem",
eError);
SCWrite(pCon, "ERROR: your data will be dumped into emergency.hdf",
eError);
return strdup("emergency.hdf");
}
/* find length */
iLen = strlen(pPath->text);
iLen += strlen(pPref->text);
iLen += 8; /* for number + year */
iLen += strlen(pEnd->text);
iLen += 10; /* safety margin */
/* allocate memory */
pRes = (char *) malloc(iLen * sizeof(char));
if (!pRes) {
SCWrite(pCon, "ERROR: no memory in SNXMakeFileName", eError);
return NULL;
}
memset(pRes, 0, iLen);
/* build the filename */
strcpy(pRes, pPath->text);
strcat(pRes, pPref->text);
iNum = IncrementDataNumber(pCom->pData, &iYear);
if (iNum < 0) {
SCWrite(pCon, "ERROR: cannot increment data number!", eError);
SCWrite(pCon, "ERROR: your data will be dumped to emergency.hdf",
eError);
free(pRes);
return strdup("emergency.hdf");
}
sprintf(pNumText, "%5.5d", iNum);
strcat(pRes, pNumText);
sprintf(pNumText, "%4.4d", iYear);
strcat(pRes, pNumText);
strcat(pRes, pEnd->text);
/* install an error handler */
NXMSetError((void *) pCon, SNError);
return pRes;
}
/*-------------------------------------------------------------------------*/
NXhandle SNXStartFile(SConnection * pCon, SicsInterp * pSics)
{
NXhandle pFile = NULL;
char *filename = NULL;
pSicsVariable pVar = NULL;
int iStat;
char pBueffel[512], pTime[132];
/* 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);
free(filename);
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);
}
/* filename no longer needed */
free(filename);
/* write creation time */
SNXFormatTime(pTime, 132);
iStat = NXputattr(pFile, "file_time", pTime, strlen(pTime) + 1, NX_CHAR);
if (iStat == NX_ERROR) {
SCWrite(pCon, "ERROR: writing date attribute to Nexus file", eError);
}
sprintf(pBueffel, "File created at StarDate: %s", pTime);
SCWrite(pCon, pBueffel, eWarning);
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, "address");
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 SNXStartEntry(NXhandle Nfil, int iNew, SicsInterp * pSics)
{
int iStat;
char pName[80];
pSicsVariable pVar = NULL;
int iDim[2];
/* format an entry name */
if (iNew < 10) {
sprintf(pName, "entry%1.1d", iNew);
} else if ((iNew > 9) && (iNew < 100)) {
sprintf(pName, "entry%2.2d", iNew);
} else if ((iNew > 99) && (iNew < 1000)) {
sprintf(pName, "entry%3.3d", iNew);
} else if ((iNew > 9999) && (iNew < 10000)) {
sprintf(pName, "entry%4.4d", iNew);
} else {
return 0;
}
/* create entry and step into it */
iStat = NXmakegroup(Nfil, pName, "NXentry");
if (iStat == NX_ERROR) {
return 0;
}
iStat = NXopengroup(Nfil, pName, "NXentry");
if (iStat == NX_ERROR) {
return 0;
}
/* write entry level attributes here */
pVar = FindVariable(pSics, "title");
if (pVar) {
iDim[0] = strlen(pVar->text) + 1;
NXmakedata(Nfil, "title", NX_CHAR, 1, iDim);
NXopendata(Nfil, "title");
NXputdata(Nfil, pVar->text);
NXclosedata(Nfil);
}
/* write time */
SNXFormatTime(pName, 79);
iDim[0] = strlen(pName) + 1;
NXmakedata(Nfil, "start_time", NX_CHAR, 1, iDim);
NXopendata(Nfil, "start_time");
NXputdata(Nfil, pName);
NXclosedata(Nfil);
return 1;
}
/*-------------------------------------------------------------------------*/
int SNenter(NXhandle Nfil, char *name, char *class)
{
int iStat;
iStat = NXmakegroup(Nfil, name, class);
if (iStat == NX_ERROR) {
NXclose(&Nfil);
return 0;
}
iStat = NXopengroup(Nfil, name, class);
if (iStat == NX_ERROR) {
NXclose(&Nfil);
return 0;
}
return 1;
}
/*-------------------------------------------------------------------------*/
int SNputdata1(NXhandle Nfil, char *name, int datatype, int iLong,
void *pData)
{
int iStat;
int iDim[2];
iDim[0] = iLong;
iStat = NXmakedata(Nfil, name, datatype, 1, (int *) iDim);
if (iStat == NX_ERROR) {
NXclose(&Nfil);
return 0;
}
iStat = NXopendata(Nfil, name);
if (iStat == NX_ERROR) {
NXclose(&Nfil);
return 0;
}
iStat = NXputdata(Nfil, pData);
if (iStat == NX_ERROR) {
NXclose(&Nfil);
return 0;
}
iStat = NXclosedata(Nfil);
if (iStat == NX_ERROR) {
NXclose(&Nfil);
return 0;
}
return 1;
}
/*-------------------------------------------------------------------------*/
int SNputdata1att(NXhandle Nfil, char *name, int datatype, int iLong,
void *pData, char *attname, char *val)
{
int iStat;
int iDim[2];
iDim[0] = iLong;
iStat = NXmakedata(Nfil, name, datatype, 1, (int *) iDim);
if (iStat == NX_ERROR) {
NXclose(&Nfil);
return 0;
}
iStat = NXopendata(Nfil, name);
if (iStat == NX_ERROR) {
NXclose(&Nfil);
return 0;
}
iStat = NXputdata(Nfil, pData);
if (iStat == NX_ERROR) {
NXclose(&Nfil);
return 0;
}
iStat = NXputattr(Nfil, attname, val, strlen(val) + 1, NX_CHAR);
if (iStat == NX_ERROR) {
NXclose(&Nfil);
return 0;
}
iStat = NXclosedata(Nfil);
if (iStat == NX_ERROR) {
NXclose(&Nfil);
return 0;
}
return 1;
}
/*-----------------------------------------------------------------------*/
static int SNPutMotor(NXhandle hfil, SicsInterp * pSics,
SConnection * pCon, char *sicsname,
char *dataname, char *units)
{
float fVal;
char pBueffel[512];
int iRet;
pMotor pMot;
pMot = FindMotor(pSics, sicsname);
if (!pMot) {
sprintf(pBueffel, "ERROR: motor %s not found ", sicsname);
SCWrite(pCon, pBueffel, eError);
return 0;
}
iRet = MotorGetSoftPosition(pMot, pCon, &fVal);
if (iRet != 1) {
sprintf(pBueffel, "ERROR: cannot read motor %s", sicsname);
SCWrite(pCon, pBueffel, eError);
return 0;
}
return SNputdata1att(hfil, dataname, NX_FLOAT32, 1, &fVal, "Units",
units);
}
#ifdef NONINTF
extern float nintf(float f);
#endif
/*--------------------------------------------------------------------------*/
int SNMakeDMC(SConnection * pCon, SicsInterp * pSics)
{
NXhandle Nfil;
NXlink lWave, lDetData, lStart, lTemp, lMoni, lStep, lNumber,
lTheta, lSetData;
int iDim[2];
float fEnd, fStart, fStep;
int iStat;
pSicsVariable pVar;
pSicsSelector pSel = NULL;
pICountable pCountInt;
pIDrivable pDrive = NULL;
pSelVar pPell;
char *pP;
float fVal;
float *fTheta;
float fTh, f2Th, fB1, fB2;
pMotor pMot = NULL;
CommandList *pCom = NULL;
int iVal, i;
char pBuffer[132];
pHistMem pHist = NULL;
HistInt *lData = NULL;
CounterMode eCount;
int *iTVal = NULL;
pDummy pDum;
int bHRPT = 0;
float fMean, fStdDev;
pVarLog pLog = NULL;
/* open the file & entry */
Nfil = SNXStartFile(pCon, pSics);
if (!Nfil) {
return 0;
}
iStat = SNXStartEntry(Nfil, 1, pSics);
if (!iStat) {
NXclose(&Nfil);
return 0;
}
/* create the instrument Vgroup */
pVar = FindVariable(pSics, "instrument");
if (strcmp(pVar->text, "HRPT") == 0) {
bHRPT = 1;
}
assert(pVar);
iStat = SNenter(Nfil, pVar->text, "NXpsdpowder");
if (!iStat) {
return 0;
}
/* write the Kollimator for HRPT */
if (bHRPT) {
iStat = SNenter(Nfil, "kollimator", "NXkollimator");
if (!iStat) {
return 0;
}
pMot = FindMotor(pSics, "CEX1");
if (pMot) {
iStat = MotorGetSoftPosition(pMot, pCon, &fStart);
iStat = SNputdata1att(Nfil, "kollimator1", NX_FLOAT32, 1,
&fStart, "Units", "degrees");
}
pMot = FindMotor(pSics, "CEX2");
if (pMot) {
iStat = MotorGetSoftPosition(pMot, pCon, &fStart);
iStat = SNputdata1att(Nfil, "kollimator2", NX_FLOAT32, 1,
&fStart, "Units", "degrees");
}
NXclosegroup(Nfil); /* leave kollimator */
}
/* write the Monochromator data */
iStat = SNenter(Nfil, "Monochromator", "NXcrystal");
if (!iStat) {
return 0;
}
if (bHRPT) {
pVar = FindVariable(pSics, "lambda");
if (pVar) {
VarGetFloat(pVar, &fVal);
SNputdata1att(Nfil, "lambda", NX_FLOAT32, 1, &fVal,
"Units", "Angstroem");
NXopendata(Nfil, "lambda");
NXgetdataID(Nfil, &lWave);
NXclosedata(Nfil);
}
pVar = FindVariable(pSics, "monotype");
if (pVar) {
iStat = SNputdata1(Nfil, "type", NX_CHAR, strlen(pVar->text),
pVar->text);
}
/* write tons of motors for the monochromator */
SNPutMotor(Nfil, pSics, pCon, "momu", "omega_upper", "degree");
SNPutMotor(Nfil, pSics, pCon, "mtvu",
"vertical_translation_upper", "mm");
SNPutMotor(Nfil, pSics, pCon, "mtpu",
"paralell_translation_upper", "mm");
SNPutMotor(Nfil, pSics, pCon, "mgvu", "vertical_tilt_upper", "degree");
SNPutMotor(Nfil, pSics, pCon, "mgpu", "parallel_tilt_upper", "degree");
SNPutMotor(Nfil, pSics, pCon, "mcvu", "curvature_upper", "");
SNPutMotor(Nfil, pSics, pCon, "moml", "omega_lower", "degree");
SNPutMotor(Nfil, pSics, pCon, "mtvl",
"vertical_translation_lower", "mm");
SNPutMotor(Nfil, pSics, pCon, "mtpl",
"parallel_translation_lower", "degree");
SNPutMotor(Nfil, pSics, pCon, "mgvl", "vertical_tilt_lower", "degree");
SNPutMotor(Nfil, pSics, pCon, "mgpl", "parallel_tilt_lower", "degree");
SNPutMotor(Nfil, pSics, pCon, "mcvl", "curvature_lower", "degree");
SNPutMotor(Nfil, pSics, pCon, "mexz", "lift", "mm");
} else {
pCom = FindCommand(pSics, "mono");
assert(pCom);
pSel = (pSicsSelector) pCom->pData;
pP = MonoGetType(pSel);
iStat = SNputdata1(Nfil, "type", NX_CHAR, strlen(pP), pP);
if (!iStat) {
return 0;
}
pCom = NULL;
pCom = FindCommand(pSics, "lambda");
assert(pCom);
pPell = (pSelVar) pCom->pData;
assert(iHasType(pPell, "SicsSelVar"));
fVal = GetSelValue(pPell, pCon);
iStat = SNputdata1(Nfil, "lambda", NX_FLOAT32, 1, &fVal);
if (!iStat) {
return 0;
}
NXopendata(Nfil, "lambda");
NXputattr(Nfil, "Units", "Angstroem", 10, NX_CHAR);
NXgetdataID(Nfil, &lWave);
NXclosedata(Nfil);
iStat = GetMonoPositions(pSel, pCon, &fTh, &f2Th, &fB1, &fB2);
if (iStat)
/* skip if not readable, error has been reported lower down */
{
SNputdata1att(Nfil, "theta", NX_FLOAT32, 1, &fTh,
"Units", "degrees");
SNputdata1att(Nfil, "two_theta", NX_FLOAT32, 1, &f2Th,
"Units", "degrees");
SNputdata1att(Nfil, "curvature", NX_FLOAT32, 1, &fB1, "Units", "mm");
}
/* more monochromatic motors */
SNPutMotor(Nfil, pSics, pCon, "monox", "x_translation", "mm");
SNPutMotor(Nfil, pSics, pCon, "monoy", "y_translation", "mm");
SNPutMotor(Nfil, pSics, pCon, "monophi", "phi", "degree");
SNPutMotor(Nfil, pSics, pCon, "monochi", "chi", "degree");
}
NXclosegroup(Nfil); /* leave monochromator */
/* start Detector vGroup */
if (bHRPT) {
iStat = SNenter(Nfil, HRPTDETNAM, "NXpsd");
} else {
iStat = SNenter(Nfil, DMCDETNAM, "NXpsd");
}
/* get the histogram memory object */
pCom = FindCommand(pSics, "banana");
assert(pCom);
pHist = pCom->pData;
assert(pHist);
/* counter mode */
eCount = GetHistCountMode(pHist);
if (eCount == eTimer) {
strcpy(pBuffer, "Timer");
} else {
strcpy(pBuffer, "Monitor");
}
iStat =
SNputdata1(Nfil, "CounterMode", NX_CHAR, strlen(pBuffer), pBuffer);
if (!iStat) {
return 0;
}
/* count preset */
fVal = GetHistPreset(pHist);
if (eCount == eTimer) {
iStat = SNputdata1(Nfil, "Preset", NX_FLOAT32, 1, &fVal);
} else {
fVal = nintf(fVal);
iStat = SNputdata1(Nfil, "Preset", NX_FLOAT32, 1, &fVal);
}
if (!iStat) {
return 0;
}
/* monitor value */
pDum = (pDummy) pHist;
pCountInt = pDum->pDescriptor->GetInterface(pDum, COUNTID);
{
pCountInt->TransferData(pHist, pCon);
}
iVal = GetHistMonitor(pHist, 1, pCon);
if (iVal < 0) {
return 0;
}
iStat = SNputdata1(Nfil, "Monitor", NX_INT32, 1, &iVal);
/*
count time
*/
fVal = GetHistCountTime(pHist, pCon);
SNputdata1att(Nfil, "time", NX_FLOAT32, 1, &fVal, "Units", "seconds");
/*
more monitors
*/
iVal = GetHistMonitor(pHist, 0, pCon);
SNputdata1(Nfil, "beam_monitor", NX_INT32, 1, &iVal);
iVal = GetHistMonitor(pHist, 4, pCon);
SNputdata1(Nfil, "proton_monitor", NX_INT32, 1, &iVal);
NXopendata(Nfil, "Monitor");
NXgetdataID(Nfil, &lMoni);
NXclosedata(Nfil);
/* stepwidth */
pVar = FindVariable(pSics, "detstepwidth");
if (!pVar) {
return 0;
}
fVal = pVar->fVal;
iStat = SNputdata1(Nfil, "Step", NX_FLOAT32, 1, &fVal);
if (!iStat) {
return 0;
}
NXopendata(Nfil, "Step");
NXgetdataID(Nfil, &lStep);
NXclosedata(Nfil);
/* histogram Length */
GetHistDim(pHist, iDim, &iVal);
iVal = iDim[0];
if (iVal < 1) {
return 0;
}
iStat = SNputdata1(Nfil, "no_of_steps", NX_INT32, 1, &iVal);
if (iStat < 1) {
return 0;
}
NXopendata(Nfil, "no_of_steps");
NXgetdataID(Nfil, &lNumber);
NXclosedata(Nfil);
/* actual data */
lData = (HistInt *) malloc(iVal * sizeof(HistInt));
if (!lData) {
return 0;
}
iStat =
GetHistogram(pHist, pCon, 0, 0, iVal, lData, iVal * sizeof(HistInt));
if (!iStat) {
return 0;
}
iStat = SNputdata1(Nfil, "Counts", NX_INT32, iVal, lData);
if (!iStat) {
return 0;
}
free(lData);
NXopendata(Nfil, "Counts");
NXgetdataID(Nfil, &lSetData);
strcpy(pBuffer, "1");
NXputattr(Nfil, "signal", pBuffer, strlen(pBuffer) + 1, NX_CHAR);
NXclosedata(Nfil);
/* motor position */
pMot = FindMotor(pSics, "a4");
assert(pMot);
iStat = MotorGetSoftPosition(pMot, pCon, &fStart);
iStat = SNputdata1att(Nfil, "two_theta_start", NX_FLOAT32, 1,
&fStart, "Units", "degrees");
if (!iStat) {
return 0;
}
/* create 2Theta array and store it */
fTheta = NULL;
fTheta = (float *) malloc(iVal * sizeof(NX_FLOAT32));
if (!fTheta) {
return 0;
}
for (i = 0; i < iVal; i++) {
fTheta[i] = fStart + i * fVal;
}
iStat = SNputdata1att(Nfil, "two_theta", NX_FLOAT32, iVal,
fTheta, "Units", "degrees");
if (!iStat) {
return 0;
}
/* get link, put axis attribute */
NXopendata(Nfil, "two_theta");
NXputattr(Nfil, "axis", "1", strlen("1") + 1, NX_CHAR);
NXgetdataID(Nfil, &lTheta);
NXclosedata(Nfil);
free(fTheta);
NXopendata(Nfil, "two_theta_start");
NXgetdataID(Nfil, &lStart);
NXclosedata(Nfil);
NXclosegroup(Nfil); /* detector Vgroup */
NXclosegroup(Nfil); /* instrument Vgroup */
/* do the sample Vgroup */
iStat = SNenter(Nfil, "Sample", "NXpowder");
if (!iStat) {
return 0;
}
pVar = FindVariable(pSics, "sample");
if (pVar) {
iDim[0] = strlen(pVar->text) + 1;
NXmakedata(Nfil, "sample_name", NX_CHAR, 1, iDim);
NXopendata(Nfil, "sample_name");
NXputdata(Nfil, pVar->text);
NXclosedata(Nfil);
}
pVar = FindVariable(pSics, "sample_mur");
if (pVar) {
SNputdata1att(Nfil, "sample_mur", NX_FLOAT32, 1, &pVar->fVal,
"Units", "???");
}
/* do a3 */
SNPutMotor(Nfil, pSics, pCon, "a3", "sample_table_rotation", "degree");
/* 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 */
pLog = EVCGetVarLog((pEVControl) pCom->pData);
if (pLog) {
VarlogGetMean(pLog, &fMean, &fStdDev);
SNputdata1att(Nfil, "temperature_mean", NX_FLOAT32, 1, &fMean,
"Units", "K");
SNputdata1att(Nfil, "temperature_stddev", NX_FLOAT32, 1,
&fStdDev, "Units", "K");
}
fVal = pDrive->GetValue(pCom->pData, pCon);
} else { /* a simple variable */
VarGetFloat((pSicsVariable) pDum, &fVal);
}
SNputdata1att(Nfil, "sample_temperature", NX_FLOAT32, 1, &fVal,
"Units", "K");
}
NXclosegroup(Nfil); /* sample Vgroup */
/* write the data Vgroup */
SNenter(Nfil, "data1", "NXdata");
NXmakelink(Nfil, &lWave);
NXmakelink(Nfil, &lTheta);
NXmakelink(Nfil, &lStart);
NXmakelink(Nfil, &lSetData);
NXmakelink(Nfil, &lMoni);
NXmakelink(Nfil, &lStep);
NXmakelink(Nfil, &lNumber);
/* send quieck message */
i = 131;
iVal = NX_CHAR;
NXgetattr(Nfil, "file_name", pBuffer, &i, &iVal);
SendQuieck(QUIECK, pBuffer);
/* done */
NXclose(&Nfil);
return 1;
}
/*--------------------------------------------------------------------------*/
int SNStoreDMC(SConnection * pCon, SicsInterp * pSics, void *pData,
int argc, char *argv[])
{
return SNMakeDMC(pCon, pSics);
}

View File

@ -1,29 +0,0 @@
/*-------------------------------------------------------------------------
N X D A T A
Some routines for handling Nexus data file writing.
Mark Koennecke, April 1997
copyright: see implementation file.
--------------------------------------------------------------------------*/
#ifndef SICSNXDATA
#define SICSNXDATA
char *SNXMakeFileName(SicsInterp * pSics, SConnection * pCon);
NXhandle SNXStartFile(SConnection * pCon, SicsInterp * pSics);
int SNXStartEntry(NXhandle Nfil, int iNew, SicsInterp * pSics);
void SNXFormatTime(char *pBuffer, int iBufLen);
int SNFinishFile(NXhandle Nfil);
int SNMakeDMC(SConnection * pCon, SicsInterp * pSics);
int SNStoreDMC(SConnection * pCon, SicsInterp * pSics, void *pData,
int argc, char *argv[]);
#endif

View File

@ -1,192 +0,0 @@
\subsection{NXdata}
NXdata is a module for writing Powder Diffraction Data files. The
routines here are somewhat obsolete as they refer to NeXus writing
using the standard Napi routines which is quite involved. Usually,
NeXus files are written from SICS through the NXDICT aware utility
routines in NXUTIL.
If not stated
otherwise, all routines return 1 on successful completion and 0 when an
error is detected. Please note, that many of these routines expect to find
certain data items in the Sics Interpreter. This implies, that any naming
changes in the initialisation file might force changes in here as well.
\begin{flushleft} \small
\begin{minipage}{\linewidth} \label{scrap1}
$\langle$Protos {\footnotesize ?}$\rangle\equiv$
\vspace{-1ex}
\begin{list}{}{} \item
\mbox{}\verb@@\\
\mbox{}\verb@ char *SNXMakeFileName(SicsInterp *pSics, SConnection *pCon);@\\
\mbox{}\verb@@$\diamond$
\end{list}
\vspace{-1ex}
\footnotesize\addtolength{\baselineskip}{-1ex}
\begin{list}{}{\setlength{\itemsep}{-\parsep}\setlength{\itemindent}{-\leftmargin}}
\item Macro defined by scraps ?, ?, ?, ?, ?, ?, ?.
\item Macro referenced in scrap ?.
\end{list}
\end{minipage}\\[4ex]
\end{flushleft}
SNXMakeFileName creates a new filename from the SICS variables SicsDataPath,
SicsDataPresript, SicsDataNumber and SicsDataEnding. SicsDataNumber will be
incremented as well. The function returns a newly allocate buffer with the
assembled filename or NULL on error. Note, that the caller is responsible
for freeing the memory associated with the filename afterwards.
\begin{flushleft} \small
\begin{minipage}{\linewidth} \label{scrap2}
$\langle$Protos {\footnotesize ?}$\rangle\equiv$
\vspace{-1ex}
\begin{list}{}{} \item
\mbox{}\verb@@\\
\mbox{}\verb@ NXhandle SNXStartFile(SConnection *pCon, SicsInterp *pSics); @\\
\mbox{}\verb@@$\diamond$
\end{list}
\vspace{-1ex}
\footnotesize\addtolength{\baselineskip}{-1ex}
\begin{list}{}{\setlength{\itemsep}{-\parsep}\setlength{\itemindent}{-\leftmargin}}
\item Macro defined by scraps ?, ?, ?, ?, ?, ?, ?.
\item Macro referenced in scrap ?.
\end{list}
\end{minipage}\\[4ex]
\end{flushleft}
First calls SNXMakeFileName in order to get a new Filename.
Then a new Nexus file is
created and all the standard headings are filled in: Filename, User,
instrument, date etc. This routine also installs an error handler which
prints errors to pCon.
If successful, the SicsDataNumber is incremented and
an NXhandle into the new file is returned. If there is a problem, NULL
will be returned. The file returned will be positioned at root level.
\begin{flushleft} \small
\begin{minipage}{\linewidth} \label{scrap3}
$\langle$Protos {\footnotesize ?}$\rangle\equiv$
\vspace{-1ex}
\begin{list}{}{} \item
\mbox{}\verb@@\\
\mbox{}\verb@ int SNXStartEntry(NXhandle Nfil, int iNew, SicsInterp *pSics);@\\
\mbox{}\verb@@$\diamond$
\end{list}
\vspace{-1ex}
\footnotesize\addtolength{\baselineskip}{-1ex}
\begin{list}{}{\setlength{\itemsep}{-\parsep}\setlength{\itemindent}{-\leftmargin}}
\item Macro defined by scraps ?, ?, ?, ?, ?, ?, ?.
\item Macro referenced in scrap ?.
\end{list}
\end{minipage}\\[4ex]
\end{flushleft}
\begin{flushleft} \small
\begin{minipage}{\linewidth} \label{scrap4}
$\langle$Protos {\footnotesize ?}$\rangle\equiv$
\vspace{-1ex}
\begin{list}{}{} \item
\mbox{}\verb@@\\
\mbox{}\verb@ void SNXFormatTime(char *pBuffer, int iBufLen);@\\
\mbox{}\verb@@$\diamond$
\end{list}
\vspace{-1ex}
\footnotesize\addtolength{\baselineskip}{-1ex}
\begin{list}{}{\setlength{\itemsep}{-\parsep}\setlength{\itemindent}{-\leftmargin}}
\item Macro defined by scraps ?, ?, ?, ?, ?, ?, ?.
\item Macro referenced in scrap ?.
\end{list}
\end{minipage}\\[4ex]
\end{flushleft}
SNXFormatTime formats the current system time in a form compatible to the
NeXus standard. Input parameters is a Buffer to hold the string and a
length of the buffer. Maximum iBufLen characters will be copied to that
buffer.
SNXStartEntry creates a new entry corresponding to iNew in the Nexus file
Nfil. SNXStartEntry will position Nfil in this new entry. Any data items
labeled as Comment or intent will be written to the file as well.
\begin{flushleft} \small
\begin{minipage}{\linewidth} \label{scrap5}
$\langle$Protos {\footnotesize ?}$\rangle\equiv$
\vspace{-1ex}
\begin{list}{}{} \item
\mbox{}\verb@@\\
\mbox{}\verb@ int SNFinishFile(NXhandle Nfil);@\\
\mbox{}\verb@@$\diamond$
\end{list}
\vspace{-1ex}
\footnotesize\addtolength{\baselineskip}{-1ex}
\begin{list}{}{\setlength{\itemsep}{-\parsep}\setlength{\itemindent}{-\leftmargin}}
\item Macro defined by scraps ?, ?, ?, ?, ?, ?, ?.
\item Macro referenced in scrap ?.
\end{list}
\end{minipage}\\[4ex]
\end{flushleft}
SNFinishFile will end a Nexus file properly.
\begin{flushleft} \small
\begin{minipage}{\linewidth} \label{scrap6}
$\langle$Protos {\footnotesize ?}$\rangle\equiv$
\vspace{-1ex}
\begin{list}{}{} \item
\mbox{}\verb@@\\
\mbox{}\verb@ int SNMakeDMC(SConnection *pCon, SicsInterp *pSics);@\\
\mbox{}\verb@@$\diamond$
\end{list}
\vspace{-1ex}
\footnotesize\addtolength{\baselineskip}{-1ex}
\begin{list}{}{\setlength{\itemsep}{-\parsep}\setlength{\itemindent}{-\leftmargin}}
\item Macro defined by scraps ?, ?, ?, ?, ?, ?, ?.
\item Macro referenced in scrap ?.
\end{list}
\end{minipage}\\[4ex]
\end{flushleft}
SNMakeDMC produces a Nexus DMC data file from the currently valid
information. It orchestrates all of the above.
\begin{flushleft} \small
\begin{minipage}{\linewidth} \label{scrap7}
$\langle$Protos {\footnotesize ?}$\rangle\equiv$
\vspace{-1ex}
\begin{list}{}{} \item
\mbox{}\verb@@\\
\mbox{}\verb@int SNStoreDMC(SConnection *pCon, SicsInterp *pSics, void *pData, int argc,@\\
\mbox{}\verb@ char *argv[]);@\\
\mbox{}\verb@@$\diamond$
\end{list}
\vspace{-1ex}
\footnotesize\addtolength{\baselineskip}{-1ex}
\begin{list}{}{\setlength{\itemsep}{-\parsep}\setlength{\itemindent}{-\leftmargin}}
\item Macro defined by scraps ?, ?, ?, ?, ?, ?, ?.
\item Macro referenced in scrap ?.
\end{list}
\end{minipage}\\[4ex]
\end{flushleft}
SNStoreData is the wrapper function used to install a DMC data storage
command in the Sics interpreter.
\begin{flushleft} \small
\begin{minipage}{\linewidth} \label{scrap8}
\verb@"nxdata.h"@ {\footnotesize ? }$\equiv$
\vspace{-1ex}
\begin{list}{}{} \item
\mbox{}\verb@@\\
\mbox{}\verb@/*-------------------------------------------------------------------------@\\
\mbox{}\verb@ N X D A T A@\\
\mbox{}\verb@@\\
\mbox{}\verb@ Some routines for handling Nexus data file writing.@\\
\mbox{}\verb@@\\
\mbox{}\verb@ Mark Koennecke, April 1997@\\
\mbox{}\verb@ @\\
\mbox{}\verb@ copyright: see implementation file.@\\
\mbox{}\verb@--------------------------------------------------------------------------*/@\\
\mbox{}\verb@#ifndef SICSNXDATA@\\
\mbox{}\verb@#define SICSNXDATA@\\
\mbox{}\verb@@$\langle$Protos {\footnotesize ?, \ldots\ }$\rangle$\verb@ @\\
\mbox{}\verb@#endif @\\
\mbox{}\verb@@\\
\mbox{}\verb@@$\diamond$
\end{list}
\vspace{-2ex}
\end{minipage}\\[4ex]
\end{flushleft}

View File

@ -1,89 +0,0 @@
\subsection{NXdata}
NXdata is a module for writing Powder Diffraction Data files. The
routines here are somewhat obsolete as they refer to NeXus writing
using the standard Napi routines which is quite involved. Usually,
NeXus files are written from SICS through the NXDICT aware utility
routines in NXUTIL.
If not stated
otherwise, all routines return 1 on successful completion and 0 when an
error is detected. Please note, that many of these routines expect to find
certain data items in the Sics Interpreter. This implies, that any naming
changes in the initialisation file might force changes in here as well.
@d Protos @{
char *SNXMakeFileName(SicsInterp *pSics, SConnection *pCon);
@}
SNXMakeFileName creates a new filename from the SICS variables SicsDataPath,
SicsDataPresript, SicsDataNumber and SicsDataEnding. SicsDataNumber will be
incremented as well. The function returns a newly allocate buffer with the
assembled filename or NULL on error. Note, that the caller is responsible
for freeing the memory associated with the filename afterwards.
@d Protos @{
NXhandle SNXStartFile(SConnection *pCon, SicsInterp *pSics);
@}
First calls SNXMakeFileName in order to get a new Filename.
Then a new Nexus file is
created and all the standard headings are filled in: Filename, User,
instrument, date etc. This routine also installs an error handler which
prints errors to pCon.
If successful, the SicsDataNumber is incremented and
an NXhandle into the new file is returned. If there is a problem, NULL
will be returned. The file returned will be positioned at root level.
@d Protos @{
int SNXStartEntry(NXhandle Nfil, int iNew, SicsInterp *pSics);
@}
@d Protos @{
void SNXFormatTime(char *pBuffer, int iBufLen);
@}
SNXFormatTime formats the current system time in a form compatible to the
NeXus standard. Input parameters is a Buffer to hold the string and a
length of the buffer. Maximum iBufLen characters will be copied to that
buffer.
SNXStartEntry creates a new entry corresponding to iNew in the Nexus file
Nfil. SNXStartEntry will position Nfil in this new entry. Any data items
labeled as Comment or intent will be written to the file as well.
@d Protos @{
int SNFinishFile(NXhandle Nfil);
@}
SNFinishFile will end a Nexus file properly.
@d Protos @{
int SNMakeDMC(SConnection *pCon, SicsInterp *pSics);
@}
SNMakeDMC produces a Nexus DMC data file from the currently valid
information. It orchestrates all of the above.
@d Protos @{
int SNStoreDMC(SConnection *pCon, SicsInterp *pSics, void *pData, int argc,
char *argv[]);
@}
SNStoreData is the wrapper function used to install a DMC data storage
command in the Sics interpreter.
@o nxdata.h @{
/*-------------------------------------------------------------------------
N X D A T A
Some routines for handling Nexus data file writing.
Mark Koennecke, April 1997
copyright: see implementation file.
--------------------------------------------------------------------------*/
#ifndef SICSNXDATA
#define SICSNXDATA
@< Protos@>
#endif
@}

6
ofac.c
View File

@ -124,8 +124,6 @@
#include "asyncqueue.h"
#include "asyncprotocol.h"
#include "sicsobj.h"
#include "hdbqueue.h"
#include "genericcontroller.h"
#include "proxy.h"
#include "reflist.h"
#include "singlex.h"
@ -335,10 +333,6 @@ static void InitIniCommands(SicsInterp * pInter, pTaskMan pTask)
AddCommand(pInter, "MakeAsyncQueue", AsyncQueueFactory, NULL, NULL);
AddCommand(pInter, "MakeSicsObj", InstallSICSOBJ, NULL, NULL);
AddCommand(pInter, "DynSicsObj", InstallSICSOBJ, NULL, NULL);
/* AddCommand(pInter,"MakeHdbQueue",MakeHDBQueue,NULL,NULL); */
AddCommand(pInter, "MakeGenController", GenControllerFactory, NULL,
NULL);
AddCommand(pInter, "genconfigure", GenControllerConfigure, NULL, NULL);
AddCommand(pInter, "MakeProxy", ProxyFactory, NULL, NULL);
AddCommand(pInter, "MakeRefList", MakeReflectionList, NULL, NULL);
AddCommand(pInter, "MakeSingleX", MakeSingleX, NULL, NULL);

View File

@ -303,7 +303,13 @@ static int SctMatch(void *data1, void *data2)
return a->node == b->node && strcasecmp(a->name, b->name) == 0;
}
/*
* This routine is running the script chain
* This routine is running the script chain. It is called repeatedly
* with response data from the device serializer (devser). This function
* basically:
* - Figures out which script to run
* - Runs the script
* - Based on the result either returns the next string to send to the
* device or NULL when the script chain is done with
*/
static char *SctActionHandler(void *actionData, char *lastReply,
int commError)
@ -351,7 +357,7 @@ static char *SctActionHandler(void *actionData, char *lastReply,
* When this is a followup, we use the content of the
* state field as the property storing the next script to
* run. If this is the start of a chain this is set to the
* data->name which is mortly either read or write
* data->name which is mostly either read or write
*/
state = GetProp(node, controller->node, "state");
if (state == NULL || strcasecmp(state, "idle") == 0) {

621
sel2.c
View File

@ -1,621 +0,0 @@
/************************************************************************/
/* Hahn-Meitner-Institut Berlin */
/* Bereich Strukturforschung */
/* Abteilung NI / BENSC */
/* Glienicker Strasse 100 */
/* D-14109 Berlin (Wannsee) */
/* Software:K. Emmelmann, Tel.(030)8062-2588, Mail: klaus@dvwbs5.hmi.de */
/************************************************************************/
/* Datei: SEL.C */
/* Teil von: KWS.C */
/* Anwendung bei: V4 - KWS */
/* Titel: Treiberprogramm fuer Geschwindigkeitsselektor DORNIER */
/* Version: 1.0 vom: 30.1.96 */
/************************************************************************/
/*
Legende
=======
30.1.96 Emmelmann Implementierung
1.2.96 Emmelmann Statusdekodierung eingebaut
27.2.96 Emmelmann Strom wird auch im Status geliefert
Das Handbuch sagt Empfangsterminator ist Linefeed.
Jeder Befehl erzeugt ein Echo; argumentlose Befehle werden im Echo
zusaetzlich mit einer Zahl versehen, deren Bedeutung unbekannt ist.
FEHLERMELDUNGEN, die bekannt sind:
****************************************
1. Solldrehzahl zu klein !
2. Solldrehzahl zu gross !
3. derzeit keine Ausfuehrung moeglich !
4. Solldrehzahl in einem kritischen Bereich
- return to m
5. HOCHFAHREN 1
6.
zu 3: Abfrage der Istgeschwindigkeit ist waehrend des Hochfahrens aus dem
Stillstand nur ueber Lesen des Gesamtstatus moeglich
zu 4: es gibt verbotene Geschwindigkeitsbereiche
zu 5: beim Uebergang von Stop in den gestarteten Zustand
Zeitliches Protokollverhalten
-----------------------------
Wird ein Befehl bearbeitet, werden alle weiteren ueber die serielle
Schnittstelle einlaufenden Befehle ignoriert - auch nicht gepuffert !
Max. Befahlsrate: 1 Befehl / 5 Sekunden
Geraete-Verhalten
-----------------
Der Startbefehl faehrt den Selektor auf die Minimalgeschwindigkeit (3100U/min)
Das Protokoll: fuer jeden Befehl erzeugt der Selektor-PC ein Echo !
Host -> Selektor
------------------------
REM (disabled) Remote-Betrieb einschalten
Rueckmeldung: ENABLED / Host nicht betriebsbereit!
TTY (disabled) Local-Betrieb einschalten
Rueckmeldung: DISABLED
??? Sende Status (Status ist nicht fest und geht von der
Interpretation der Kennworte aus !)
TIM (disabled) Setzen des Zeitintervalles zur Time-Out-Ueberwachung des PCs
????
SST Start des Selektors und Ausregeln der Drehzahl (Nur wenn der
Selektor steht !); liefert als Rueckmeldung die Solldrehzahl
SDR nnnnn Vorgabe einer Soll-Drehzahl und geregelten Betrieb einschalten.
3100 => nnnnn <=28300 U/min; liegt der Wert in einem kritischen
Bereich (geht aus Setup-Menue hervor), kommt eine entsprechende
Rueckmeldung
FDR Sende die Solldrehzahl (Format 'RPM n')
STB Leerlauf ohne Regelung
BRE Beginne eine Verlustleistungsmessung - ist bei Statusabruf
lesbar, wenn dort die Betriebsart regeln erscheint !
HAL Bremse Selektor bis zum Stillstand ab (unterhalb 3000 U/min.)
*/
#include stdio.h
#include descrip.h
#include iodef.h
#include errno.h
#include lnmdef.h
#define FALSE 0
#define TRUE !FALSE
#define OK 0L
#define NOT_OK !OK
#define LIMIT_U 3100 /* niedrigste Drehzahl */
#define LIMIT_O 28300
/* Verbotene Drehzahlbereiche (Resonanzgefahr) */
#define RESONANZ_1U 3648
#define RESONANZ_1O 4552
#define RESONANZ_2U 5248
#define RESONANZ_2O 6449
#define RESONANZ_3U 9148
#define RESONANZ_3O 9949
#define TOK_BUF_L 25
#define SELE_LUN 0
extern FILE *fs;
static short chan_s = 6;
/* *********************************************************************** */
/* ------------------------------------------------------------------------ */
long select_setup()
{
register rc;
$DESCRIPTOR(dev_descr, "TXA1:");
chan_s = SELE_LUN;
if ((rc = sys$assign(&dev_descr, &chan_s, NULL, NULL)) != 1) {
printf("Error in Selector_SETUP: Ret = %d\n", rc);
return (NOT_OK);
}
return (OK);
}
/* ------------------------------------------------------------------------ */
/* Function liest ueberprueft das Befehlsecho */
long sele_test_echo(cmd, lng)
char *cmd[];
int lng;
{
char echo[80];
if (sele_read(&echo) != OK)
return (NOT_OK);
if (strncmp(&echo, cmd, lng) != 0) {
printf("Selector:protocol error%s\n", echo);
return (NOT_OK);
} else
return (OK);
}
/* ------------------------------------------------------------------------ */
/* Function prueft die Anzahl der sich im Typeahead-Buffer befindenden Bytes
und liefert das naechste dort anstehende Zeichen, jedoch ohne es
aus dem Puffer zu entnehmen.
*/
long tst_buf_s(bt)
int *bt;
{
int bytes;
register rc;
struct {
unsigned short status, bytes;
int pid;
} iosb;
if ((rc = sys$qiow(NULL, chan_s, IO$_SENSEMODE | IO$M_TYPEAHDCNT, &iosb,
NULL, NULL, &bytes, NULL, NULL, NULL, NULL,
NULL)) != 1) {
print_error(fs, "Error in QIOW");
return (NOT_OK);
}
/**ch = (bytes >> 16) & 0xff;*/
*bt = bytes & 0xffff;
return (OK);
}
/* ------------------------------------------------------------------------ */
long sele_read(message)
char *message;
{
char char_l[8], *ptr;
register rc;
struct {
unsigned short status, bytes;
int pid;
} iosb;
ptr = message;
for (;;) {
if ((rc = sys$qiow(NULL, chan_s, IO$_READVBLK | IO$M_NOECHO,
&iosb, NULL,
NULL, char_l, 1, NULL, NULL, NULL, NULL)) != 1) {
printf("Error in QIOW, READ_MESS: %d\n", rc);
return (NOT_OK);
}
*ptr = char_l[0];
/* Terminator (linefeed) ? */
ptr++;
if (char_l[0] == '\n')
break;
}
return (OK);
}
/* ------------------------------------------------------------------------ */
/* Pruefe ob der Selektor eine Fehlermeldung erzeugt hat und gib sie aus */
long select_error_msg(err)
long *err;
{
char chr[10], msg[80];
float waiti = 3.0; /* Selektor PC hat 3 Sekunden Reaktionszeit !! */
/* Warte ein wenig - es koennte auf den Befehl hin eine Fehlermeldung erscheinen */
lib$wait(&waiti);
/* Es koennen auch mehrere Zeilen sein */
*err = FALSE;
for (;;) {
if (tst_buf_s(&chr) != OK)
return (NOT_OK);
if (chr[0] != NULL) {
if (sele_read(&msg) != OK)
return (NOT_OK);
printf("Selektor failure:");
printf("%s\n\7", msg);
*err = TRUE;
} else
return (OK);
}
}
/* ------------------------------------------------------------------------ */
long sele_write(message)
char message[];
{
char msg[80];
long err;
register rc;
struct {
unsigned short status, bytes;
int pid;
} iosb;
if (select_error_msg(&err) != OK)
return (NOT_OK);
if (err == TRUE)
return (NOT_OK);
if ((rc = sys$qiow(NULL, chan_s, IO$_WRITEVBLK, &iosb, NULL, NULL,
message, strlen(message), NULL, NULL, NULL,
NULL)) != 1) {
printf("Error in QIOW: %d\n", rc);
return (NOT_OK);
}
return (OK);
}
/* -------------------------------------------------------------------------- */
/*
Ein-/ Ausschalten von Stoerungsmeldungen vom Selektor an den Host
Diese Funktion ist z.Z. nur vom Selektor-PC aktivierbar
*/
long select_msg(tim)
long tim;
{
int sts;
long err;
char cmd[20] = "TIM ";
snprintf(&cmd + 4,sizeof(&cmd + 4)-1, "%5u\0", tim);
sts = sele_write(cmd);
if (sele_test_echo(&cmd, 3) != OK)
lib$stop(-1);
if (select_error_msg(&err) != OK)
return (NOT_OK);
if (err == TRUE)
return (NOT_OK);
return (OK);
}
/* -------------------------------------------------------------------------- */
/* Einschaltung der Fremdsteuerung des Selektors
Diese Funktion ist z.Z. nur vom Selektor-PC aktivierbar
*/
long select_remote()
{
int sts;
long err;
char cmd[] = "REM";
sts = sele_write(cmd);
if (sele_test_echo(&cmd, 3) != OK)
lib$stop(-1);
if (select_error_msg(&err) != OK)
return (NOT_OK);
if (err == TRUE)
return (NOT_OK);
}
/* -------------------------------------------------------------------------- */
/* Ausschaltung der Fremdsteuerung des Selektors -
ein Steuerung kann dann nur noch ueber den PC des Geraetes
erfolgen.
Diese Funktion ist z.Z. nur vom Selektor-PC aktivierbar
*/
long select_local()
{
int sts;
long err;
char cmd[] = "TTY";
sts = sele_write(cmd);
if (sele_test_echo(&cmd, 3) != OK)
lib$stop(-1);
if (select_error_msg(&err) != OK)
return (NOT_OK);
if (err == TRUE)
return (NOT_OK);
}
/* -------------------------------------------------------------------------- */
/* Starten des Selektors nach Stillstand auf die Minimaldrehzahl
*/
long select_start()
{
int sts;
long err;
char cmd[] = "SST";
sts = sele_write(cmd);
if (sele_test_echo(&cmd, 3) != OK)
lib$stop(-1);
if (select_error_msg(&err) != OK)
return (NOT_OK);
if (err == TRUE)
return (NOT_OK);
}
/* -------------------------------------------------------------------------- */
/* Bremsen des Selektors bis zum Stillstand; eine
Drehzahlanzeige unterhalb 3000 U/min ist nicht moeglich.
*/
long select_stop()
{
int sts;
long err;
char cmd[] = "HAL";
sts = sele_write(cmd);
if (sele_test_echo(&cmd, 3) != OK)
lib$stop(-1);
if (select_error_msg(&err) != OK)
return (NOT_OK);
if (err == TRUE)
return (NOT_OK);
}
/* -------------------------------------------------------------------------- */
/* Einschalten des geregelten Betriebes mit dem Setzen eines Sollwertes
der Drehzahl.
Aenderungen werden spontan uebernommen und ausgefuehrt.
Neben dem absoluten Minimum und Maximum existieren verbotene
Drehzahlbereiche, die z.Z. noch nicht exakt bekannt sind.
*/
long select_set_rpm(rpm)
int rpm;
{
int sts;
long err;
char cmd[] = "SDR", s_dat[10] = "SDR 00000";
if ((rpm < LIMIT_U) || (rpm > LIMIT_O)) {
print_error(fs, "nominal value out of allowed range");
return;
}
/* Resonanzbereiche sind auch verboten */
if (((rpm >= RESONANZ_1U) && (rpm <= RESONANZ_1O)) ||
((rpm >= RESONANZ_2U) && (rpm <= RESONANZ_2O)) ||
((rpm >= RESONANZ_3U) && (rpm <= RESONANZ_3O))) {
print_error(fs, "nominal value within inhibited range");
return;
}
snprintf(&s_dat + 4,sizeof(&s_dat + 4)-1, "%5u", rpm);
sts = sele_write(s_dat);
if (sele_test_echo(&cmd, 3) != OK)
lib$stop(-1);
if (select_error_msg(&err) != OK)
return (NOT_OK);
if (err == TRUE)
return (NOT_OK);
}
/* -------------------------------------------------------------------------- */
/* Leerlauf des Selektors einschalten; weder Antrieb noch
Verzoegerung erfolgen - eine anschliessende Abbremsung oder
ein Uebergang zum geregelten Betrieb ist moeglich.
*/
long select_set_idle()
{
int sts;
long err;
char cmd[] = "STB";
sts = sele_write(cmd);
if (sele_test_echo(&cmd, 3) != OK)
lib$stop(-1);
if (select_error_msg(&err) != OK)
return (NOT_OK);
if (err == TRUE)
return (NOT_OK);
}
/* -------------------------------------------------------------------------- */
/* Starten der Messung der elektrischen Verlustleistung des
Selektors. Anscheinend wird waehrend der Zeit die
Regelung deaktiviert.
Nach Abschluss der Messung erfolgt ein Uebergang in den\
geregelten Berieb.
Das Messergebnis wird in den Statusinformationsblock eingetragen.
*/
long select_read_power()
{
int sts;
long err;
char cmd[] = "BRE";
sts = sele_write(cmd);
if (sele_test_echo(&cmd, 3) != OK)
lib$stop(-1);
if (select_error_msg(&err) != OK)
return (NOT_OK);
if (err == TRUE)
return (NOT_OK);
}
/* -------------------------------------------------------------------------- */
/* Lesen der aktuellen Drehzahl des Selektors */
long select_read_rpm(rpm)
int *rpm;
{
int sts, tmp;
long err;
char status[80], cmd[] = "FDR";
sts = sele_write(cmd);
if (sele_test_echo(&cmd, 3) != OK)
lib$stop(-1);
sts = sele_read(&status);
sscanf(&status + 4, "%d", &tmp);
*rpm = tmp;
if (select_error_msg(&err) != OK)
return (NOT_OK);
if (err == TRUE)
return (NOT_OK);
}
/* -------------------------------------------------------------------------- */
/* Auslesen des kompletten Statusblockes des Selektors.
Der Informationseintrag 'Verlustleistung' ist anscheinend nur dann
aktuell, wenn zuvor eine Verlustleistungsmessung aktiviert wurde.
Argumente:
rm = Betriebsstatus
[REG == regelnd]
[STB == im Leerlauf]
[BRE == bremsend]
nom_rpm = Soll der Drehzahl (U/min)
cur_rpm = Ist der Drehzahl (U/min)
pwr = Verlustleistung (W)
curr = elektr. Stomstaerke (A)
rot_temp= Temperatur des Rotors (C)
cont_temp= Temperatur des Gehaeuses (C)
inl_temp= Temperatur Kuehlwasser-Einlass
outl_temp= Temperatur Kuehlwasser-Abfluss
cool_wat= Kuehlwasser-Durchfluss (l/min)
vacuum = Betriebsvakuum (mbar)
accel = Rotationsbeschleunigung (g)
komm = Kommunikation zwischen Selektor-PC und Host
'ENABLED' oder "DISABLED'
dat = Tagesdatum dd.m.yyyy
tim = Tageszeit hh.mm.s
*/
long select_read_status(rm, nom_rpm, cur_rpm, pwr, curr, rot_temp,
cont_temp, inl_temp, outl_temp, cool_wat, vacuum,
accel, komm, dat, tim)
char *rm[];
int *nom_rpm, *cur_rpm, *pwr, *rot_temp, *cont_temp, *inl_temp, *outl_temp;
float *cool_wat, *vacuum, *accel, *curr;
char *dat[], *tim[];
short *komm;
{
int cnt, key_id, sl, sts;
long err;
char ena_str[] = "ENABLED";
char dis_str[] = "DISABLED";
char keys[15][9] = {
"Status:\0 ",
"S_DREH:\0 ",
"I_DREH:\0 ",
"P_VERL:\0 ",
"STROM:\0 ",
"T_ROT:\0 ",
"T_GEH:\0 ",
"T_VOR:\0 ",
"T_RUECK:\0",
"DURCHFL:\0",
"VAKUUM:\0 ",
"BESCHL:\0 ",
"KOM: \0 ",
"DATE: \0 ",
"TIME: \0 "
};
char tok_buf[TOK_BUF_L], *ptr_token, *ptr_src, *ptr, tok_c[] = "/\0";
char status[255], cmd[] = "???";
if (sele_write(cmd) != OK)
return (NOT_OK);
if (sele_test_echo(&cmd, 3) == NOT_OK)
lib$stop(-1);
if (sele_read(&status) != OK)
return (NOT_OK); /* Und nun der Status */
ptr_src = &status;
for (;;) {
/* Lies Zeichenfolge bis zum naechsten Trennzeichen '/' */
ptr_token = strtok(ptr_src, &tok_c);
ptr_src = NULL; /* fuer die weitere Suche notwendig */
if (ptr_token == NULL)
break;
strcpy(&tok_buf, ptr_token);
for (key_id = 0; key_id <= 14; key_id++) {
/* Ist das Schluesselwort enthalten ? */
sl = strlen(keys[key_id]);
if (strncmp(&keys[key_id][0], &tok_buf, sl) == NULL) {
/* Schiebe das Schluesselwort raus */
for (cnt = 0; cnt + sl < TOK_BUF_L; cnt++)
tok_buf[cnt] = tok_buf[cnt + sl];
switch (key_id) {
case 0:
{
ptr = rm;
strcpy(ptr, &tok_buf);
break;
}
case 1:{
sscanf(&tok_buf, "%d", nom_rpm);
break;
}
case 2:{
sscanf(&tok_buf, "%d", cur_rpm);
break;
}
case 3:{
sscanf(&tok_buf, "%d", pwr);
break;
}
case 4:{
sscanf(&tok_buf, "%f", curr);
break;
}
case 5:{
sscanf(&tok_buf, "%d", rot_temp);
break;
}
case 6:{
sscanf(&tok_buf, "%d", cont_temp);
break;
}
case 7:{
sscanf(&tok_buf, "%d", inl_temp);
break;
}
case 8:{
sscanf(&tok_buf, "%d", outl_temp);
break;
}
case 9:{
sscanf(&tok_buf, "%f", cool_wat);
break;
}
case 10:{
sscanf(&tok_buf, "%f", vacuum);
break;
}
case 11:{
sscanf(&tok_buf, "%f", accel);
break;
}
case 12:
{
if (strcmp(&tok_buf, &ena_str) == NULL) {
*komm = TRUE;
break;
}
if (strcmp(&tok_buf, &dis_str) == NULL) {
*komm = FALSE;
break;
}
printf("Invalid Communication value");
break;
}
case 13:
{
ptr = dat;
strcpy(ptr, &tok_buf);
break;
}
case 14:
{
ptr = tim;
strcpy(ptr, &tok_buf);
break;
}
}
}
}
}
if (select_error_msg(&err) != OK)
return (NOT_OK);
if (err == TRUE)
return (NOT_OK);
return (OK);
}

View File

@ -10,3 +10,4 @@
MFLAGS=-f makefile_linux$(DUMMY)
HDFROOT=/afs/psi.ch/project/sinq/sl5
TCLINC=.