- SICS cleanup: removed unused code
SKIPPED: psi/make_gen psi/makefile_linux psi/polterwrite.c psi/psi.c
This commit is contained in:
114
cryst.c
114
cryst.c
@ -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 */
|
|
||||||
|
|
||||||
}
|
|
@ -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;
|
|
||||||
}
|
|
@ -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_ */
|
|
524
hdbqueue.c
524
hdbqueue.c
@ -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;
|
|
||||||
}
|
|
15
hdbqueue.h
15
hdbqueue.h
@ -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
402
hklscan.c
@ -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;
|
|
||||||
}
|
|
25
hklscan.h
25
hklscan.h
@ -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
|
|
17
hklscan.i
17
hklscan.i
@ -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;
|
|
||||||
|
|
111
hklscan.tex
111
hklscan.tex
@ -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}
|
|
70
hklscan.w
70
hklscan.w
@ -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
|
|
||||||
@}
|
|
||||||
|
|
4
make_gen
4
make_gen
@ -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 \
|
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 \
|
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\
|
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 \
|
histmem.o histdriv.o histsim.o interface.o callback.o nxio.o \
|
||||||
event.o emon.o evcontroller.o evdriver.o simev.o perfmon.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\
|
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 \
|
moregress.o multicounter.o regresscter.o histregress.o \
|
||||||
sicshdbadapter.o polldriv.o sicspoll.o statemon.o hmslave.o \
|
sicshdbadapter.o polldriv.o sicspoll.o statemon.o hmslave.o \
|
||||||
nwatch.o asyncqueue.o asyncprotocol.o sicsobj.o frame.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 \
|
sctdriveadapter.o sctdriveobj.o reflist.o singlex.o fourmess.o \
|
||||||
sgclib.o sgfind.o sgio.o sgsi.o sghkl.o singlediff.o singlebi.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 \
|
singlenb.o simindex.o simidx.o uselect.o singletas.o motorsec.o \
|
||||||
|
814
nxdata.c
814
nxdata.c
@ -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);
|
|
||||||
}
|
|
29
nxdata.h
29
nxdata.h
@ -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
|
|
192
nxdata.tex
192
nxdata.tex
@ -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}
|
|
89
nxdata.w
89
nxdata.w
@ -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
6
ofac.c
@ -124,8 +124,6 @@
|
|||||||
#include "asyncqueue.h"
|
#include "asyncqueue.h"
|
||||||
#include "asyncprotocol.h"
|
#include "asyncprotocol.h"
|
||||||
#include "sicsobj.h"
|
#include "sicsobj.h"
|
||||||
#include "hdbqueue.h"
|
|
||||||
#include "genericcontroller.h"
|
|
||||||
#include "proxy.h"
|
#include "proxy.h"
|
||||||
#include "reflist.h"
|
#include "reflist.h"
|
||||||
#include "singlex.h"
|
#include "singlex.h"
|
||||||
@ -335,10 +333,6 @@ static void InitIniCommands(SicsInterp * pInter, pTaskMan pTask)
|
|||||||
AddCommand(pInter, "MakeAsyncQueue", AsyncQueueFactory, NULL, NULL);
|
AddCommand(pInter, "MakeAsyncQueue", AsyncQueueFactory, NULL, NULL);
|
||||||
AddCommand(pInter, "MakeSicsObj", InstallSICSOBJ, NULL, NULL);
|
AddCommand(pInter, "MakeSicsObj", InstallSICSOBJ, NULL, NULL);
|
||||||
AddCommand(pInter, "DynSicsObj", 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, "MakeProxy", ProxyFactory, NULL, NULL);
|
||||||
AddCommand(pInter, "MakeRefList", MakeReflectionList, NULL, NULL);
|
AddCommand(pInter, "MakeRefList", MakeReflectionList, NULL, NULL);
|
||||||
AddCommand(pInter, "MakeSingleX", MakeSingleX, NULL, NULL);
|
AddCommand(pInter, "MakeSingleX", MakeSingleX, NULL, NULL);
|
||||||
|
@ -303,7 +303,13 @@ static int SctMatch(void *data1, void *data2)
|
|||||||
return a->node == b->node && strcasecmp(a->name, b->name) == 0;
|
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,
|
static char *SctActionHandler(void *actionData, char *lastReply,
|
||||||
int commError)
|
int commError)
|
||||||
@ -351,7 +357,7 @@ static char *SctActionHandler(void *actionData, char *lastReply,
|
|||||||
* When this is a followup, we use the content of the
|
* When this is a followup, we use the content of the
|
||||||
* state field as the property storing the next script to
|
* state field as the property storing the next script to
|
||||||
* run. If this is the start of a chain this is set to the
|
* 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");
|
state = GetProp(node, controller->node, "state");
|
||||||
if (state == NULL || strcasecmp(state, "idle") == 0) {
|
if (state == NULL || strcasecmp(state, "idle") == 0) {
|
||||||
|
621
sel2.c
621
sel2.c
@ -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);
|
|
||||||
}
|
|
@ -10,3 +10,4 @@
|
|||||||
MFLAGS=-f makefile_linux$(DUMMY)
|
MFLAGS=-f makefile_linux$(DUMMY)
|
||||||
|
|
||||||
HDFROOT=/afs/psi.ch/project/sinq/sl5
|
HDFROOT=/afs/psi.ch/project/sinq/sl5
|
||||||
|
TCLINC=.
|
Reference in New Issue
Block a user