Cleaned up ANSTO code to merge with sinqdev.sics

This is our new RELEASE-4_0 branch which was taken from ansto/93d9a7c
Conflicts:
	.gitignore
	SICSmain.c
	asynnet.c
	confvirtualmot.c
	counter.c
	devexec.c
	drive.c
	event.h
	exebuf.c
	exeman.c
	histmem.c
	interface.h
	motor.c
	motorlist.c
	motorsec.c
	multicounter.c
	napi.c
	napi.h
	napi4.c
	network.c
	nwatch.c
	nxscript.c
	nxxml.c
	nxxml.h
	ofac.c
	reflist.c
	scan.c
	sicshipadaba.c
	sicsobj.c
	site_ansto/docs/Copyright.txt
	site_ansto/instrument/lyrebird/config/tasmad/sicscommon/nxsupport.tcl
	site_ansto/instrument/lyrebird/config/tasmad/taspub_sics/tasscript.tcl
	statusfile.c
	tasdrive.c
	tasub.c
	tasub.h
	tasublib.c
	tasublib.h
This commit is contained in:
Ferdi Franceschini
2015-04-23 20:49:26 +10:00
parent c650788a2c
commit 10d29d597c
1336 changed files with 9430 additions and 226646 deletions

137
.gitignore vendored
View File

@ -1,22 +1,121 @@
SICServer
made_config.h
PATCH.TXT
*.aux
*.pdf
.*.sw?
*.orig
*.svn
# Took these from the https://github.com/github/gitignore project on October 21, 2011
# **** 'Personal' entries don't belong in here - put them in your .git/info/exclude file ****
# Ignore text editor (e.g. emacs) autosave files
*~
CVS
CVSPSI
*.pyc
*.png
*.hdf5
*.a
# Compiled Object files
*.slo
*.lo
*.o
*.obj
*.d
*.out
*.sqlite
parser.out
parsetab.py
_trial_temp
SICServer
# Compiled Dynamic libraries
*.so
# Compiled Static libraries
*.lai
*.la
*.a
# Compiled python files
*.py[co]
# Eclipse-generated files
*.pydevproject
.project
.metadata
bin/**
tmp/**
tmp/**/*
*.tmp
*.bak
*.swp
*~.nib
local.properties
.classpath
.settings/
.loadpath
# External tool builders
.externalToolBuilders/
# Locally stored "Eclipse launch configurations"
*.launch
# CDT-specific
.cproject
# PDT-specific
.buildpath
## Ignore Visual Studio temporary files, build results, and
## files generated by popular Visual Studio add-ons.
*.sln
*.vcproj
*.exe
*.vcxproj
*.filters
# User-specific files
*.suo
*.user
*.sln.docstates
*.sdf
#Test results
*.log
# Build results
[Dd]ebug/
[Rr]elease/
*_i.c
*_p.c
*.ilk
*.meta
*.obj
*.pch
*.pdb
*.pgc
*.pgd
*.rsp
*.sbr
*.tlb
*.tli
*.tlh
*.tmp
*.vspscc
.builds
# Visual C++ cache files
ipch/
*.aps
*.ncb
*.opensdf
*.sdf
# Visual Studio profiler
*.psess
*.vsp
# ReSharper is a .NET coding add-in
_ReSharper*
# Others
*.autosave
# Windows image file caches
Thumbs.db
# Mac OS X Finder
.DS_Store

View File

@ -1,5 +1,5 @@
#line 467 "histogram.w"
#line 470 "histogram.w"
/*---------------------------------------------------------------------------
H I S T D R I V
@ -72,7 +72,7 @@
void *pPriv;
} HistDriver;
#line 479 "histogram.w"
#line 482 "histogram.w"
#line 232 "histogram.w"
@ -84,7 +84,7 @@
HistInt *DefaultSubSample(pHistDriver self, SConnection *pCon,
int bank, char *command);
#line 480 "histogram.w"
#line 483 "histogram.w"
#endif

112
HistMem.h
View File

@ -1,5 +1,5 @@
#line 440 "histogram.w"
#line 443 "histogram.w"
/*--------------------------------------------------------------------------
H I S T M E M
@ -13,89 +13,91 @@
#define SICSHISTMEM
#define MAXDIM 3
typedef struct __HistDriver *pHistDriver;
typedef struct __HistMem *pHistMem;
typedef struct __HistDriver *pHistDriver;
typedef struct __HistMem *pHistMem;
/*-------------------------------------------------------------------------*/
typedef int HistInt;
typedef int HistInt;
/*
32 bit integer on a DigitalUnix
*/
#line 9 "histogram.w"
typedef enum {
eHTransparent,
eHNormal,
eHTOF,
eHStrobo,
eHRPT,
ePSD,
eSANSTOF
} HistMode;
typedef enum {
eHTransparent,
eHNormal,
eHTOF,
eHStrobo,
eHRPT,
ePSD,
eSANSTOF
} HistMode;
#line 36 "histogram.w"
typedef enum {
eOIgnore,
eOCeil,
eOCount,
eReflect
} OverFlowMode;
typedef enum {
eOIgnore,
eOCeil,
eOCount,
eReflect
} OverFlowMode;
#line 460 "histogram.w"
#line 463 "histogram.w"
/*--------------------------------------------------------------------------*/
#line 292 "histogram.w"
pHistMem CreateHistMemory(char *drivername);
void DeleteHistMemory(void *self);
pHistMem CreateHistMemory(char *drivername);
void DeleteHistMemory(void *self);
#line 308 "histogram.w"
int HistGetOption(pHistMem self, char *name, char *result, int iResultLen);
int HistSetOption(pHistMem self, char *name, char *value);
int HistConfigure(pHistMem self, SConnection * pCon, SicsInterp * pSics);
int HistGetOption(pHistMem self, char *name, char *result, int iResultLen);
int HistSetOption(pHistMem self, char *name, char *value);
int HistConfigure(pHistMem self, SConnection *pCon, SicsInterp *pSics);
#line 336 "histogram.w"
float GetHistPreset(pHistMem self);
int SetHistPreset(pHistMem self, float fVal);
CounterMode GetHistCountMode(pHistMem self);
int SetHistCountMode(pHistMem self, CounterMode eNew);
long GetHistMonitor(pHistMem self, int i, SConnection * pCon);
const float *GetHistTimeBin(pHistMem self, int *iLength);
int GetHistLength(pHistMem self);
int GetHistDim(pHistMem self, int iDim[MAXDIM], int *nDim);
float GetHistCountTime(pHistMem self, SConnection * pCon);
int HistDoCount(pHistMem self, SConnection * pCon);
int HistBlockCount(pHistMem self, SConnection * pCon);
void HistDirty(pHistMem self);
float GetHistPreset(pHistMem self);
int SetHistPreset(pHistMem self, float fVal);
CounterMode GetHistCountMode(pHistMem self);
int SetHistCountMode(pHistMem self, CounterMode eNew);
long GetHistMonitor(pHistMem self, int i, SConnection *pCon);
const float *GetHistTimeBin(pHistMem self, int *iLength);
int GetHistLength(pHistMem self);
int GetHistDim(pHistMem self, int iDim[MAXDIM], int *nDim);
float GetHistCountTime(pHistMem self,SConnection *pCon);
int HistDoCount(pHistMem self, SConnection *pCon);
int HistBlockCount(pHistMem self, SConnection *pCon);
void HistDirty(pHistMem self);
int isSecondGen(pHistMem self);
pHistMem FindHM(SicsInterp *pSics, char *name);
#line 366 "histogram.w"
#line 369 "histogram.w"
int SetHistogram(pHistMem self, SConnection * pCon,
int i, int iStart, int iEnd, HistInt * lData);
int GetHistogram(pHistMem self, SConnection * pCon,
int i, int iStart, int iEnd, HistInt * lData,
int iDataLen);
HistInt *GetHistogramPointer(pHistMem self, SConnection * pCon);
int GetHistogramDirect(pHistMem self, SConnection * pCon,
int i, int iStart, int iEnd,
HistInt * lData, int iDataLen);
int PresetHistogram(pHistMem self, SConnection * pCon, HistInt lVal);
int SetHistogram(pHistMem self, SConnection *pCon,
int i,int iStart, int iEnd, HistInt *lData);
int GetHistogram(pHistMem self, SConnection *pCon,
int i,int iStart, int iEnd, HistInt *lData, int iDataLen);
HistInt *GetHistogramPointer(pHistMem self,SConnection *pCon);
int GetHistogramDirect(pHistMem self, SConnection *pCon,
int i, int iStart, int iEnd,
HistInt *lData, int iDataLen);
int PresetHistogram(pHistMem self, SConnection *pCon, HistInt lVal);
#line 409 "histogram.w"
#line 412 "histogram.w"
int MakeHistMemory(SConnection * pCon, SicsInterp * pSics, void *pData,
int argc, char *argv[]);
int MakeHistMemory(SConnection *pCon, SicsInterp *pSics, void *pData,
int argc, char *argv[]);
int HistAction(SConnection * pCon, SicsInterp * pSics, void *pData,
int argc, char *argv[]);
int HistAction(SConnection *pCon, SicsInterp *pSics, void *pData,
int argc, char *argv[]);
#line 462 "histogram.w"
#line 465 "histogram.w"
#endif

View File

@ -1,5 +1,5 @@
#line 485 "histogram.w"
#line 488 "histogram.w"
/*---------------------------------------------------------------------------
H I S T M E M -- Internal
@ -23,7 +23,7 @@
pICallBack pCall;
} HistMem;
#line 495 "histogram.w"
#line 498 "histogram.w"
#endif

View File

@ -273,7 +273,7 @@ static int TclExecFunc(SConnection *pCon, SicsInterp *pInter, void *data,
SCWrite(pCon,(char *)Tcl_GetStringResult(InterpGetTcl(pInter)), eValue );
return 1;
} else {
SCWrite(pCon,(char *)Tcl_GetStringResult(InterpGetTcl(pInter)), eValue );
SCWrite(pCon,(char *)Tcl_GetStringResult(InterpGetTcl(pInter)), eError );
return 0;
}
@ -543,6 +543,7 @@ void DeleteInterp(SicsInterp * self)
call KillSicsUnknown instead to clean up all memory properly. M.Z., Apr 05
*/
Tcl_DeleteInterp(pTcl);
KillSicsUnknown();
}

View File

@ -145,7 +145,7 @@ char *FindAliases(SicsInterp * pSics, char *name);
/*-------------------------------------------------------------------------
FindCommandData finds a command with the name given. It tests the name in the
ObjectDescriptor to be of name class. If all this succeeds a pointer
to the commands data structure is retuned. Else NULL.
to the commands data structure is returned. Else NULL.
Do not test the Object Descriptor name when comclass == NULL.
*/
void *FindCommandData(SicsInterp * pSics, char *name, char *comclass);
@ -155,7 +155,7 @@ void *FindCommandData(SicsInterp * pSics, char *name, char *comclass);
*/
pObjectDescriptor FindCommandDescriptor(SicsInterp * pSics, char *name);
/*------------------------------------------------------------------------
/*---------------------------------------------------------------------
FindDrivable tries to find Drivable object by the name given. Returns a
pointer to the drivable interface in the case of success, NULL in
case of failure. In order to save me fixing header files the pointer must

View File

@ -24,6 +24,7 @@
#include "nserver.h"
#include "servlog.h"
#include "sicsglobal.h"
extern void KeepStartupCommands(); /* ofac.c */
/* ========================= Less dreadful file statics =================== */
@ -60,6 +61,8 @@ int main(int argc, char *argv[])
if (argv[i][0] == '-') {
if (strcasecmp(argv[i], "-nolog") == 0) {
SICSLogEnable(0);
}else if(strcmp(argv[i],"-keepstartup") == 0){
KeepStartupCommands();
#ifdef SITE_ANSTO
} else if (strcasecmp(argv[i], "-v") == 0) {
extern void SiteReportVersion(void);

View File

@ -36,11 +36,18 @@ long sumWindow(int *data, int xstart, int xend, int xlength,
}
for(j = ystart; j < yend; j++){
row = data + j*xlength;
for(i = xstart; i < xend; i++){
result += row[i];
/* for(j = ystart; j < yend; j++){ */
/* row = data + j*xlength; */
/* for(i = xstart; i < xend; i++){ */
/* result += row[i]; */
/* } */
/* } */
for(i = xstart; i < xend; i++){
row = data + i*ylength;
for(j = ystart; j < yend; j++){
result += row[j];
}
}
return result;
}

24
ascon.c
View File

@ -47,7 +47,7 @@ static int CreateSocketAdress(struct sockaddr_in *sockaddrPtr, /* Socket addres
}
/*
* There is a rumor that this assignment may require care on
* some 64 bit machines.
* some 64 bit machines, we do not believe it.
*/
sockaddrPtr->sin_addr.s_addr = addr.s_addr;
return 1;
@ -134,7 +134,11 @@ static void AsconConnect(Ascon * a)
}
colon = strchr(a->hostport, ':');
if (colon == NULL) {
AsconError(a, "expected 'host:port' or 'unconnected'", 0);
if (strcmp(a->hostport, "unconnected") == 0) {
AsconError(a, "offline", 0);
} else {
AsconError(a, "expected 'host:port' or 'unconnected'", 0);
}
return;
}
port = atoi(colon + 1);
@ -672,7 +676,7 @@ Ascon *AsconMake(SConnection * con, int argc, char *argv[])
free(args);
return NULL;
}
a->rdBuffer = CreateDynString(60, 63);
a->rdBuffer = CreateDynString(60, 65536);
a->wrBuffer = CreateDynString(60, 63);
a->errmsg = CreateDynString(60, 63);
@ -765,6 +769,11 @@ AsconStatus AsconTask(Ascon * a)
a->responseValid = 1;
DynStringClear(a->errmsg);
return AsconReady;
case AsconReadDoneReconnect:
a->responseValid = 1;
DynStringClear(a->errmsg);
AsconReconnect(a,NULL);
return AsconReady;
case AsconIdle:
return AsconReady;
case AsconTimeout:
@ -777,7 +786,7 @@ AsconStatus AsconTask(Ascon * a)
lastClose = now;
a->fd = -1;
}
if (now > a->lastReconnect + a->reconnectInterval) {
if (a->reconnectInterval > 0 && now > a->lastReconnect + a->reconnectInterval) {
a->lastReconnect = now;
a->state = AsconConnectStart;
}
@ -844,3 +853,10 @@ double AsconGetSetTimeout(Ascon *a, double timeout, int setmode) {
}
return a->timeout;
}
int AsconReconnectInterval(Ascon *a, int interval) {
if (interval >= 0) {
a->reconnectInterval = interval;
}
return a->reconnectInterval;
}

View File

@ -117,4 +117,12 @@ char *AsconHostport(Ascon *a);
*/
double AsconGetSetTimeout(Ascon *a, double timeout, int setmode);
/**
* \brief set reconnectInterval
* \param a the Ascon
* \param interval the interval to set (0: no reconnect, -1: read value)
* \return the value
*/
int AsconReconnectInterval(Ascon *a, int interval);
#endif

29
ascon.i
View File

@ -25,20 +25,21 @@
* The state of the connection.
*/
typedef enum {
AsconNotConnected, /**< unconnected, not to be connected automatically */
AsconConnectStart, /**< after initialisation or after AsconFailed */
AsconConnecting, /**< after AsconConnectStart or AsconConnecting */
AsconConnectDone, /**< after AsconConnecting */
AsconWriteStart, /**< set by the AsconWrite function */
AsconWriting, /**< after AsconWriteStart or AsconWriting */
AsconWriteDone, /**< after AsconWriting */
AsconReadStart, /**< after AsconWriteDone */
AsconReading, /**< after AsconReadStart or AsconReading */
AsconReadDone, /**< after AsconReading */
AsconIdle, /**< after AsconWriteDone, AsconReadDone, AsconTimeout, AsconIdle */
AsconFailed, /**< after any state */
AsconTimeout, /**< after AsconReading */
AsconMaxState /**< number of states */
AsconNotConnected, /**< unconnected, not to be connected automatically */
AsconConnectStart, /**< after initialisation or after AsconFailed */
AsconConnecting, /**< after AsconConnectStart or AsconConnecting */
AsconConnectDone, /**< after AsconConnecting */
AsconWriteStart, /**< set by the AsconWrite function */
AsconWriting, /**< after AsconWriteStart or AsconWriting */
AsconWriteDone, /**< after AsconWriting */
AsconReadStart, /**< after AsconWriteDone */
AsconReading, /**< after AsconReadStart or AsconReading */
AsconReadDone, /**< after AsconReading */
AsconReadDoneReconnect, /**< after AsconReading, read success, but need to reconnect */
AsconIdle, /**< after AsconWriteDone, AsconReadDone, AsconTimeout, AsconIdle */
AsconFailed, /**< after any state */
AsconTimeout, /**< after AsconReading */
AsconMaxState /**< number of states */
} AsconState;
/** \brief the task handler function prototype

View File

@ -46,6 +46,7 @@
#define RBUFFERSIZE 262144 /* 256kb */
#define WBUFFERSIZE 20*262144
/* #define WBUFFERSIZE 100*262144 */
#define MAXWBUFFERSIZE 128*1000*1024
/*--------------------------------------------------------------------------*/
typedef struct {
int socket;
@ -204,7 +205,7 @@ int ANETregisterSocket(int socket)
flags =1;
setsockopt(socket,IPPROTO_TCP,TCP_NODELAY,(char *) &flags, sizeof(int));
socke.readBuffer = MakeRWPuffer(RBUFFERSIZE);
socke.writeBuffer = MakeRWPuffer(WBUFFERSIZE);
socke.writeBuffer = MakeBigRWPuffer(WBUFFERSIZE, MAXWBUFFERSIZE);
if (socke.readBuffer == NULL || socke.writeBuffer == NULL) {
return ANETMEM;
}
@ -247,6 +248,7 @@ int ANETconnect(char *name, int iPort)
status = connect(socke, (struct sockaddr *) &addresse,
sizeof(struct sockaddr_in));
if (status < 0) {
close(socke);
anetLog(ANETERROR, "Failed to open socket to %s:%d", name, iPort);
return ANETOPENFAIL;
}
@ -503,7 +505,20 @@ int ANETinfo(int handle, char *hostname, int hostnameLen)
}
return 1;
}
/*---------------------------------------------------------------------------*/
int ANETcanWrite(int handle, void *buffer, int count)
{
pSocketDescriptor con = NULL;
int status;
con = findSocketDescriptor(handle);
if (con == NULL) {
return ANETDISCONNECTED;
} else {
ANETprocess();
return CanStoreRWBuffer(con->writeBuffer, buffer, count);
}
}
/*---------------------------------------------------------------------------*/
int ANETwrite(int handle, void *buffer, int count)
{
@ -632,14 +647,3 @@ int ANETreadTillTerm(int handle,
}
return ANETTIMEOUT;
}
char *ANETgetWBuffer(int handle) {
pSocketDescriptor sock;
int len;
char *wdata;
sock = findSocketDescriptor(handle);
wdata = (char *) GetRWBufferData(sock->writeBuffer, &len);
wdata[len] = '\0';
return wdata;
}

View File

@ -145,6 +145,14 @@ int ANETinfo(int handle, char *hostname, int hostNameLen);
* \return 1 on success, 0 on failure
*/
int ANETwrite(int handle, void *buffer, int count);
/**
* \brief Test if the buffer can be written to the network
* \param handle The handle for the connection
* \param buffer A pointer to the data to write
* \param count The number of bytes to write.
* \return 1 when possible, 0 when buffer overrun
*/
int ANETcanWrite(int handle, void *buffer, int count);
/**
* \brief copy at max bufferLength bytes into buffer. The data is not deleted from
* the read buffer yet.
@ -207,9 +215,4 @@ int ANETreadTillTerm(int handle,
* \param userData An opaque pointer with data for lcb
*/
void ANETsetLog(ANETlog lcb, void *userData);
/**
* \brief Return a pointer to the socket descriptor write buffer
* \param handle Connection object socket handle
*/
char *ANETgetWBuffer(int handle);
#endif /*ASYNNET_H_ */

View File

@ -58,7 +58,7 @@ int BackgroundCommand(SConnection * pCon, char *command)
return 0;
}
TaskRegister(pServ->pTasker, BackgroundTask, NULL, KillBckTask, self, 1);
TaskRegisterN(pServ->pTasker, self->command, BackgroundTask, NULL, KillBckTask, self, 1);
return 1;
}

View File

@ -68,7 +68,8 @@ void WriteToCommandLogId(char *prompt, int id, char *text)
time_t now;
char stamp1[32], stamp2[32], buffer[80];
int doStamp, doStampId;
int old;
/* suppress status messages */
if (strstr(text, "status =") != NULL) {
return;
@ -196,6 +197,7 @@ void WriteToCommandLogId(char *prompt, int id, char *text)
if (pServ->pTasker != NULL) {
if (doStamp) {
TaskSignal(pServ->pTasker, COMLOG, stamp1);
SCOnlySockWrite(GetSendingConnection(), stamp1, eLog);
}
TaskSignal(pServ->pTasker, COMLOG, pCopy);
}
@ -489,7 +491,7 @@ int CommandLog(SConnection * pCon, SicsInterp * pSics, void *pData,
SCWrite(pCon, "ERROR: autologging is already active", eError);
return 0;
}
TaskRegister(pServ->pTasker, AutoTask, NULL, NULL, NULL, 1);
TaskRegisterN(pServ->pTasker, "autologger", AutoTask, NULL, NULL, NULL, 1);
SCSendOK(pCon);
iAutoActive = 1;
return 1;

View File

@ -9,7 +9,7 @@
--------------------------------------------------------------------------*/
#ifndef COMMANDLOG
#define COMMANDLOG
void WriteToCommandLog(char *prompt, char *pText);
void WriteToCommandLog(const char *prompt, const char *pText);
void WriteToCommandLogId(char *prompt, int id, char *text);
void WriteToCommandLogCmd(int id, char *text);
int CompactCommandLog(void);

3
cone.c
View File

@ -171,7 +171,6 @@ static long ConeSetValue(void *pData, SConnection * pCon, float fVal)
*/
SICSHdbGetPar(obj, pCon, "target", &v);
target.h = v.v.floatArray[0];
target.k = v.v.floatArray[1];
target.l = v.v.floatArray[2];
SICSHdbGetPar(obj, pCon, "qscale", &v);
/*
@ -198,7 +197,7 @@ static long ConeSetValue(void *pData, SConnection * pCon, float fVal)
mat_free(csToPsi);
if (status != 1) {
SCWrite(pCon, "ERROR: cannot get cone vector into scattering position",
eError);
eLogError);
SCSetInterrupt(pCon, eAbortOperation);
return 0;
}

View File

@ -14,14 +14,14 @@
- a checkscript to be run at the end of driving the motor
- a means to call the write script multiple times. This is useful if
you need to drive to the value in multiple steps. An example is the
BOA double crystal monochromator where you first have to pu the baldes to
BOA double crystal monochromator where you first have to put the blades to
0, then drive the translation and then drive the blades to the real theta.
All this to avoid collisions. In order to support this, a state field and
and a readable target field has been added. The mode of operation is such
that the on first run the, writescript set the state to something different
then idle. This causes after the first set of motors finished running the
writescript to be called again. This can figure out by lookin at the
state variable what to do. This can be doen in repetition until the
state variable what to do. This can be done in repetition until the
writescript sets state to idle again.
Mark Koennecke, April 2012
@ -51,6 +51,7 @@ typedef struct {
pIDrivable pDriv;
float value;
int running;
long taskID;
} RealMotor, *pRealMotor;
/* Data passed by event generating object */
@ -183,9 +184,9 @@ static int startMotorList(pConfigurableVirtualMotor self,
iRet = LLDnodePtr2First(self->motorList);
while (iRet != 0) {
LLDnodeDataTo(self->motorList, &tuktuk);
status = tuktuk.pDriv->SetValue(tuktuk.data, pCon, tuktuk.value);
if (status != 1) {
return status;
tuktuk.taskID = StartDriveTask(tuktuk.data,pCon,tuktuk.name,tuktuk.value);
if (tuktuk.taskID < 0) {
return HWFault;
}
tuktuk.running = 1;
LLDnodeDataFrom(self->motorList, &tuktuk);
@ -346,28 +347,12 @@ static int ConfCheckStatus(void *pData, SConnection * pCon)
while (iRet != 0) {
LLDnodeDataTo(self->motorList, &tuktuk);
if (tuktuk.running == 1) {
status = tuktuk.pDriv->CheckStatus(tuktuk.data, pCon);
switch (status) {
case HWIdle:
tuktuk.running = 0;
status = isTaskIDRunning(pServ->pTasker,tuktuk.taskID);
if(status == 1){
return HWBusy;
} else {
tuktuk.running = 0;
LLDnodeDataFrom(self->motorList, &tuktuk);
break;
case HWBusy:
result = HWBusy;
break;
case HWFault:
case HWPosFault:
if(self->state != NULL){
free(self->state);
self->state = strdup("idle");
}
return status;
break;
default:
/*
this is a programming error and has to be fixed
*/
assert(0);
}
}
iRet = LLDnodePtr2Next(self->motorList);

168
conman.c
View File

@ -73,7 +73,6 @@
#include "statusfile.h"
#include "sicshipadaba.h"
#include "protocol.h"
#include "sicsvar.h"
/*
#define UUDEB 1
define UUDEB , for buffer writing for checking encoding */
@ -106,7 +105,8 @@ typedef struct {
static int iName = 0;
static long lastIdent = 0;
/*------------- sending connection (prevent double write when listening) ----*/
static int sendingConnection = 0;
static SConnection *sendingConnection = NULL;
static int sendingSockHandle = 0;
/*------------- storing connection and context for later use ----*/
struct SCStore {
SConnection *pCon;
@ -115,24 +115,6 @@ struct SCStore {
long macroStack;
commandContext cc;
};
/*
* This will return the value of a SICS int variable called "sicsdebug"
* If sicsdebug is not defined it will return 1
* TODO Maybe define debugging levels.
*
* return 0=debug off, 1=debug on or sicsdebug not defined.
*/
int sicsdebug() {
pSicsVariable debug;
debug = FindVariable(pServ->pSics, "sicsdebug");
if (debug) {
return debug->iVal;
} else {
return 1;
}
}
/*===========================================================================*/
static char *ConName(long ident)
{
@ -165,6 +147,23 @@ void KillFreeConnections()
{
}
/*---------------------------------------------------------------------------*/
SConnection *GetSendingConnection(void)
{
return sendingConnection;
}
/*---------------------------------------------------------------------------*/
static void SetSendingConnection(SConnection *pCon)
{
sendingConnection = pCon;
if (pCon) {
sendingSockHandle = pCon->sockHandle;
} else {
sendingSockHandle = 0;
}
}
/*-------------------------------------------------------------------------*/
static SConnection *SCMakeConnection()
{
@ -605,7 +604,17 @@ int TelnetWriteANET(int sockHandle, char *pBuffer)
}
return iRet;
}
/*------------------------------------------------------------------------*/
static int mustWrite(int iOut)
{
switch(iOut) {
case eLog:
case eLogError:
return 1;
default:
return 0;
}
}
/*-------------------------------------------------------------------------*/
int SCWrite(SConnection * self, char *pBuffer, int iOut)
{
@ -618,7 +627,7 @@ int SCWrite(SConnection * self, char *pBuffer, int iOut)
if (pBuffer == NULL) {
return 0;
}
if(!SCinMacro(self)){
if(!SCinMacro(self) || mustWrite(iOut) ){
traceCommand(ConID(self),"out:%s", pBuffer);
}
return self->write(self, pBuffer, iOut);
@ -726,14 +735,14 @@ static void testAndWriteCommandLog(SConnection * pCon, char *buffer,
{
if (SCGetRights(pCon) <= usUser) {
if (SCinMacro(pCon) != 1) {
sendingConnection = pCon->sockHandle;
SetSendingConnection(pCon);
WriteToCommandLogId(NULL, pCon->sockHandle, buffer);
sendingConnection = 0;
SetSendingConnection(NULL);
} else {
if (iOut == eLog || iOut == eLogError) {
sendingConnection = pCon->sockHandle;
SetSendingConnection(pCon);
WriteToCommandLogId(NULL, pCon->sockHandle, buffer);
sendingConnection = 0;
SetSendingConnection(NULL);
}
}
}
@ -850,9 +859,6 @@ int SCNormalWrite(SConnection * self, char *buffer, int iOut)
/* log it for any case */
#if 0
if ( (sicsdebug() || !SCinMacro(self)) && !(iOut == eInternal
|| (buffer[0] == 'O' && buffer[1] == 'K'
&& (buffer[2] == '\0' || buffer[2] == '\r' || buffer[2] == '\n'))))
SICSLogWrite(buffer, iOut);
#else
testAndWriteSICSLog(self, buffer, iOut);
@ -1079,7 +1085,6 @@ int SCPureSockWrite(SConnection * self, char *buffer, int iOut)
return 1;
}
/*--------------------------------------------------------------------------
special for ClientLog. Do not use elsewhere without check
----------------------------------------------------------------------------*/
@ -1091,7 +1096,9 @@ int SCLogWrite(SConnection * self, char *buffer, int iOut)
if (!VerifyConnection(self)) {
return 0;
}
SetSendingConnection(self);
WriteToCommandLogId(NULL, self->sockHandle, buffer);
SetSendingConnection(NULL);
if(self->iProtocolID == 5) {
if (strlen(buffer) + 30 > 1024) {
@ -1105,6 +1112,18 @@ int SCLogWrite(SConnection * self, char *buffer, int iOut)
if(pPtr != pBueffel){
free(pPtr);
}
} else if(self->iProtocolID == 2) {
if (strlen(buffer) + 30 > 1024) {
pPtr = (char *) malloc((strlen(buffer) + 30) * sizeof(char));
memset(pPtr, 0, strlen(buffer) + 20);
} else {
pPtr = pBueffel;
}
sprintf(pPtr,"%s@@%s",buffer,pCode[iOut]);
testAndWriteSocket(self, pPtr, iOut);
if(pPtr != pBueffel){
free(pPtr);
}
} else {
testAndWriteSocket(self, buffer, iOut);
}
@ -1239,6 +1258,8 @@ int SCWriteZipped(SConnection * self, char *pName, void *pData,
SCWrite(self, "ERROR: no data to write in SCWriteZiped", eError);
return 0;
}
pBuf = malloc(iDataLen*sizeof(char));
memset(pBuf,0,iDataLen*sizeof(char));
@ -1258,13 +1279,26 @@ int SCWriteZipped(SConnection * self, char *pName, void *pData,
compStream.avail_in = iDataLen;
compStream.avail_out = iDataLen;
iRet = deflate(&compStream, Z_FINISH);
if (iRet != Z_STREAM_END) {
if (iRet != Z_STREAM_END && iRet != Z_OK) {
sprintf(outBuf, "ERROR: zlib error: %d", iRet);
SCWrite(self, outBuf, eError);
return 0;
}
compressedLength = compStream.total_out;
/*
If data is large, test if we can do it
*/
if(compressedLength > 2*1000*1024) {
if(!ANETcanWrite(self->sockHandle,pData,compressedLength)){
SCWrite(self,"WARNING: skipping excessive data in SCWriteZipped",eLogError);
deflateEnd(&compStream);
free(pBuf);
return 0;
}
}
/* write header line */
memset(outBuf, 0, 65536);
@ -1331,6 +1365,16 @@ int SCWriteBinary(SConnection * self, char *pName, void *pData,
return 0;
}
/*
If data is large, test if we can do it
*/
if(iDataLen > 2*1000*1024) {
if(!ANETcanWrite(self->sockHandle,pData,iDataLen)){
SCWrite(self,"WARNING: skipping excessive data in SCWriteBinary",eLogError);
return 0;
}
}
/* write header line */
memset(outBuf, 0, 65536);
@ -1582,8 +1626,6 @@ int SCPrompt(SConnection * pCon, char *pPrompt, char *pResult, int iLen)
SCWrite(pCon, pPrompt, eWarning);
master = SCfindMaster(pCon);
eOld = GetStatus();
SetStatus(eInput);
CostaUnlock(master->pStack);
while (1) {
/*
@ -1603,14 +1645,57 @@ int SCPrompt(SConnection * pCon, char *pPrompt, char *pResult, int iLen)
/* do we have data ? */
iRet = CostaPop(master->pStack, &pPtr);
if (iRet == 1) {
SetStatus(eOld);
CostaLock(master->pStack);
strlcpy(pResult, pPtr, iLen);
WriteToCommandLogId(" prompted>", pCon->sockHandle, pPtr);
return 1;
}
}
SetStatus(eOld);
CostaLock(master->pStack);
return 0;
}
/*----------------------------------------------------------------------------*/
int SCPromptTMO(SConnection * pCon, char *pPrompt, char *pResult, int iLen, int timeout)
{
int iRet, i;
char *pPtr = NULL;
char pFrom[50];
Status eOld;
int oldMode;
SConnection *master = NULL;
if (!VerifyConnection(pCon)) {
return 0;
}
SCWrite(pCon, pPrompt, eWarning);
master = SCfindMaster(pCon);
CostaUnlock(master->pStack);
for(i = 0; i < timeout; i++) {
/*
wait a second. We want to wait even in a simulation, otherwise
we go into an endless loop. This is why there is the hack with
oldMode and pServ->simMode.
*/
oldMode = pServ->simMode;
pServ->simMode = 0;
SicsWait(1);
pServ->simMode = oldMode;
/* is there an interrupt pending ? */
if (SCGetInterrupt(pCon) != eContinue) {
break;
}
/* do we have data ? */
iRet = CostaPop(master->pStack, &pPtr);
if (iRet == 1) {
CostaLock(master->pStack);
strlcpy(pResult, pPtr, iLen);
WriteToCommandLogId(" prompted>", pCon->sockHandle, pPtr);
return 1;
}
}
CostaLock(master->pStack);
return 0;
}
@ -1705,7 +1790,7 @@ int SCInvoke(SConnection * self, SicsInterp * pInter, char *pCommand)
* case
*/
if (SCGetWriteFunc(self) != SCNotWrite) {
sendingConnection = self->sockHandle;
SetSendingConnection(self);
if (self->sockHandle >= 0) {
if(strstr(pCommand,"Poch") == NULL){
WriteToCommandLogCmd(self->sockHandle, pCommand);
@ -1713,7 +1798,7 @@ int SCInvoke(SConnection * self, SicsInterp * pInter, char *pCommand)
} else {
WriteToCommandLog("CRON>>", pCommand);
}
sendingConnection = 0;
SetSendingConnection(NULL);
}
}
@ -1736,10 +1821,8 @@ int SCInvoke(SConnection * self, SicsInterp * pInter, char *pCommand)
return 0;
}
strlcpy(pCopy->deviceID, pBueffel, SCDEVIDLEN);
/* SCAdvanceContext(self,pBueffel); */
traceCommand(ConID(self),"in:%s", pCommand);
iRet = InterpExecute(pInter, pCopy, pCommand);
/* SCPopContext(self); */
SCDeleteConnection(pCopy);
StatusFileTask(NULL); /* save changed parameters */
@ -1858,7 +1941,7 @@ int ConfigCon(SConnection * pCon, SicsInterp * pSics, void *pData,
} else if (strcmp(argv[1], "rights") == 0) {
if (argc < 4) {
snprintf(pBueffel,511, "Insufficient number of args to %s", argv[0]);
SCWrite(pCon, pBueffel, eInError);
SCWrite(pCon, pBueffel, eError);
return 0;
}
i = IsValidUser(argv[2], argv[3]);
@ -2366,6 +2449,7 @@ int SCTaskFunction(void *pData)
/* response for monit check */
if (strstr(pPtr, "How are you") == pPtr) {
SCWrite(self, "I am fine", eError);
ANETprocess();
ANETclose(self->sockHandle);
self->iEnd = 1;
free(pPtr);
@ -2439,11 +2523,11 @@ void SCSignalFunction(void *pData, int iSignal, void *pSigData)
} else if (iSignal == SICSBROADCAST) {
pPtr = (char *) pSigData;
if (pPtr != NULL) {
SCWrite(self, pPtr, eWarning);
SCPureSockWrite(self, pPtr, eWarning);
}
} else if (iSignal == COMLOG && self->listening == 1) {
pPtr = (char *) pSigData;
if (pPtr != NULL && self->sockHandle != sendingConnection) {
if (pPtr != NULL && self->sockHandle != sendingSockHandle) {
doSockWrite(self, pPtr);
}
} else if (iSignal == TOKENRELEASE) {

View File

@ -88,6 +88,7 @@ int SCVerifyConnection(SConnection * self);
/*------------------------------- tasking --------------------------------*/
int SCTaskFunction(void *pCon);
void SCSignalFunction(void *pCon, int iSignal, void *pSigData);
SConnection *GetSendingConnection(void);
/* ***************************** I/O ************************************** */
void SCSetOutputClass(SConnection * self, int iClass);
int SCWrite(SConnection * self, char *pBuffer, int iOut);
@ -101,6 +102,7 @@ int SCPrintf(SConnection * self, int iOut, char *fmt, ...) G_GNUC_PRINTF (3, 4);
#undef G_GNUC_PRINTF
int SCRead(SConnection * self, char *pBuffer, int iBufLen);
int SCPrompt(SConnection * pCon, char *pPrompt, char *pResult, int iLen);
int SCPromptTMO(SConnection * pCon, char *pPrompt, char *pResult, int iLen, int timeout);
int SCSendOK(SConnection * self);
int SCnoSock(SConnection * pCon);
int SCWriteUUencoded(SConnection * pCon, char *pName, void *iData,

248
counter.c
View File

@ -61,7 +61,7 @@ typedef struct {
char *pName;
} MonEvent, *pMonEvent;
/*--------------------------------------------------------------------------*/
/*-----------------------------------------------------------------------------*/
static int Halt(void *pData)
{
pCounter self = NULL;
@ -71,7 +71,19 @@ static int Halt(void *pData)
return self->pDriv->Halt(self->pDriv);
}
/*-------------------------------------------------------------------------*/
static void SetCounterError(void *pData, char *text)
{
pCounter self = NULL;
assert(pData);
self = (pCounter) pData;
if(self->error != NULL){
free(self->error);
}
self->error = strdup(text);
}
/*--------------------------------------------------------------------------*/
static void SetCountParameters(void *pData, float fPreset,
CounterMode eMode)
@ -103,6 +115,7 @@ static int StartCount(void *pData, SConnection * pCon)
return 0;
}
SetCounterError(pData,"None");
/* try at least three times to do it */
for (i = 0; i < 3; i++) {
iRet = self->pDriv->Start(self->pDriv);
@ -122,6 +135,7 @@ static int StartCount(void *pData, SConnection * pCon)
eError);
SCSetInterrupt(pCon, eAbortBatch);
ReleaseCountLock(self->pCountInt);
SetCounterError(pData,pError);
return HWFault;
}
}
@ -205,95 +219,6 @@ static int ContinueCount(void *pData, SConnection * pCon)
SCSetInterrupt(pCon, eAbortBatch);
return HWFault;
}
/*--------------------------------------------------------------------------*/
static int CheckCountStatus(void *pData, SConnection * pCon)
{
pCounter self = NULL;
int i, iRet;
int eCt;
char pError[80], pBueffel[132];
int iErr;
float fControl, rate;
MonEvent sMon;
self = (pCounter) pData;
assert(self);
assert(pCon);
eCt = self->pDriv->GetStatus(self->pDriv, &fControl);
if (eCt == HWFault) {
self->badStatusCount++;
iRet = self->pDriv->GetError(self->pDriv, &iErr, pError, 79);
sprintf(pBueffel, "WARNING: %s ", pError);
SCWrite(pCon, pBueffel, eLog);
iRet = self->pDriv->TryAndFixIt(self->pDriv, iErr);
if (iRet == COTERM || self->badStatusCount > 3) {
SCWrite(pCon, "ERROR: Cannot fix counter problem, aborting", eError);
SCSetInterrupt(pCon, eAbortBatch);
InvokeCallBack(self->pCall, COUNTEND, NULL);
ReleaseCountLock(self->pCountInt);
return eCt;
} else {
return HWBusy;
}
}
if(self->pDriv->fTime > .0){
rate = (float)(self->pDriv->lCounts[1])/self->pDriv->fTime;
if(rate > 10000){
SCWrite(pCon,"WARNING: Your control monitor is running into dead time",
eWarning);
}
}
/*
handle count parameters and notify listeners on progress
*/
sMon.fCurrent = fControl;
sMon.fPreset = self->pDriv->fPreset;
sMon.pName = self->name;
self->badStatusCount = 0; /* clear: we managed to read OK */
if (self->iCallbackCounter > 20) {
InvokeCallBack(self->pCall, MONITOR, &sMon);
tracePar(self->name,"control:%f", fControl);
self->iCallbackCounter = 0;
} else {
self->iCallbackCounter++;
}
self->pDriv->fLastCurrent = fControl;
/*
notification on finish
*/
if (eCt == HWIdle) {
self->isUpToDate = 0;
InvokeCallBack(self->pCall, COUNTEND, NULL);
ReleaseCountLock(self->pCountInt);
}
return eCt;
}
/*------------------------------------------------------------------------*/
static int SaveCounterStatus(void *pData, char *name, FILE * fd)
{
pCounter self = NULL;
assert(pData);
assert(fd);
self = (pCounter) pData;
fprintf(fd, "# Counter %s\n", name);
fprintf(fd, "%s SetPreset %f\n", name, self->pDriv->fPreset);
if (self->pDriv->eMode == eTimer) {
fprintf(fd, "%s SetMode Timer\n", name);
} else {
fprintf(fd, "%s SetMode Monitor\n", name);
}
return 1;
}
/*------------------------------------------------------------------------*/
static int TransferData(void *pData, SConnection * pCon)
{
@ -322,6 +247,7 @@ static int TransferData(void *pData, SConnection * pCon)
SCWrite(pCon, "ERROR: Cannot fix counter problem, aborting",
eError);
SCSetInterrupt(pCon, eAbortBatch);
SetCounterError(pData,pError);
return HWFault;
}
}
@ -331,6 +257,98 @@ static int TransferData(void *pData, SConnection * pCon)
return HWFault;
}
/*--------------------------------------------------------------------------*/
static int CheckCountStatus(void *pData, SConnection * pCon)
{
pCounter self = NULL;
int i, iRet;
int eCt;
char pError[80], pBueffel[132];
int iErr;
float fControl = .0, rate;
MonEvent sMon;
self = (pCounter) pData;
assert(self);
assert(pCon);
eCt = self->pDriv->GetStatus(self->pDriv, &fControl);
if (eCt == HWFault) {
self->badStatusCount++;
iRet = self->pDriv->GetError(self->pDriv, &iErr, pError, 79);
sprintf(pBueffel, "WARNING: %s ", pError);
SCWrite(pCon, pBueffel, eLog);
iRet = self->pDriv->TryAndFixIt(self->pDriv, iErr);
if (iRet == COTERM || self->badStatusCount > 3) {
SCWrite(pCon, "ERROR: Cannot fix counter problem, aborting", eError);
SCSetInterrupt(pCon, eAbortBatch);
InvokeCallBack(self->pCall, COUNTEND, NULL);
ReleaseCountLock(self->pCountInt);
SetCounterError(pData,pError);
return eCt;
} else {
return HWBusy;
}
}
/* if(self->pDriv->fTime > .0){ */
/* rate = (float)(self->pDriv->lCounts[1])/self->pDriv->fTime; */
/* if(rate > 10000){ */
/* SCWrite(pCon,"WARNING: Your control monitor is running into dead time", */
/* eLogError); */
/* } */
/* } */
/*
handle count parameters and notify listeners on progress
*/
sMon.fCurrent = fControl;
sMon.fPreset = self->pDriv->fPreset;
sMon.pName = self->name;
self->badStatusCount = 0; /* clear: we managed to read OK */
if (self->iCallbackCounter > 20) {
InvokeCallBack(self->pCall, MONITOR, &sMon);
tracePar(self->name,"control:%f", fControl);
self->iCallbackCounter = 0;
} else {
self->iCallbackCounter++;
}
self->pDriv->fLastCurrent = fControl;
/*
notification on finish
*/
if (eCt == HWIdle) {
self->isUpToDate = 0;
TransferData(self,pCon);
InvokeCallBack(self->pCall, COUNTEND, NULL);
ReleaseCountLock(self->pCountInt);
}
return eCt;
}
/*------------------------------------------------------------------------*/
static int SaveCounterStatus(void *pData, char *name, FILE * fd)
{
pCounter self = NULL;
assert(pData);
assert(fd);
self = (pCounter) pData;
fprintf(fd, "# Counter %s\n", name);
fprintf(fd, "%s SetPreset %f\n", name, self->pDriv->fPreset);
if (self->pDriv->eMode == eTimer) {
fprintf(fd, "%s SetMode Timer\n", name);
} else {
fprintf(fd, "%s SetMode Monitor\n", name);
}
return 1;
}
/*------------------------------------------------------------------------*/
static void *CounterGetInterface(void *pData, int iID)
{
@ -391,8 +409,6 @@ int DoCount(pCounter self, float fPreset, SConnection * pCon, int iBlock)
return 0;
}
eOld = GetStatus();
SetStatus(eCounting);
/* set Preset */
SetCounterPreset(self, fPreset);
@ -405,7 +421,6 @@ int DoCount(pCounter self, float fPreset, SConnection * pCon, int iBlock)
iRet = StartDevice(GetExecutor(), self->name, self->pDes, self, pCon,
level, fPreset);
if (!iRet) {
SetStatus(eOld);
SCWrite(pCon, "Counting aborted", eError);
return 0;
}
@ -426,7 +441,6 @@ int DoCount(pCounter self, float fPreset, SConnection * pCon, int iBlock)
SCWrite(pCon, "Counting finished", eValue);
iRet = 1;
}
SetStatus(eOld);
return iRet;
}
/*-------------------------------------------------------------------------*/
@ -444,12 +458,13 @@ int MakeCounter(SConnection * pCon, SicsInterp * pSics, void *pData,
assert(pCon);
assert(pSics);
argtolower(argc, argv);
if (argc < 3) {
SCWrite(pCon, "ERROR: insuficient number of arguments to MakeCounter",
eError);
return 0;
}
strtolower(argv[1]);
strtolower(argv[2]);
site = getSite();
if (site != NULL) {
pDriv = site->CreateCounterDriver(pCon, argc, argv);
@ -708,13 +723,16 @@ static int isAuthorised(SConnection * pCon, int iCode)
}
/*-----------------------------------------------------------------------*/
static int CounterInterest(int iEvent, void *pEvent, void *pUser)
int CounterInterest(int iEvent, void *pEvent, void *pUser)
{
SConnection *pCon = NULL;
pMonEvent pMon = NULL;
char pBueffel[512];
int rights;
pCon = (SConnection *) pUser;
pMon = (pMonEvent) pEvent;
if (pCon == NULL || !SCisConnected(pCon)) {
return -1;
}
@ -723,17 +741,13 @@ static int CounterInterest(int iEvent, void *pEvent, void *pUser)
return 0;
}
pCon = (SConnection *) pUser;
pMon = (pMonEvent) pEvent;
assert(pCon);
assert(pMon);
snprintf(pBueffel,511, "%s.CountStatus = %f %d", pMon->pName, pMon->fPreset,
(int) nintf(pMon->fCurrent));
/**
* prevent this to be written to log files
*/
SCSetRights(pCon, usSpy);
SCWrite(pCon, pBueffel, eWarning);
SCWrite(pCon, pBueffel, eLog);
return 1;
}
/*------------------------------------------------------------------------*/
@ -789,6 +803,7 @@ pCounter CreateCounter(char *name, pCounterDriver pDriv)
pRes->isUpToDate = 1;
pRes->iExponent = 0;
pRes->name = strdup(name);
pRes->error = strdup("None");
return pRes;
}
@ -829,9 +844,13 @@ int CountAction(SConnection * pCon, SicsInterp * pSics, void *pData,
{"send", 0, {0, 0}},
{"setpar", 3, {FUPATEXT, FUPAINT, FUPAFLOAT}},
{"getpar", 2, {FUPATEXT, FUPAOPT}},
{"getnmon", 0, {0, 0}},
{"state", 0, {0, 0}},
{"error", 0, {0, 0}},
{"getnmon",0,{0,0}},
{"getchannel",0,{0}},
{"setchannel",1,{FUPAINT}}
{"setchannel",1,{FUPAINT}},
{"countstatus", 0, {0, 0}}
};
char *pMode[] = {
"timer",
@ -848,7 +867,7 @@ int CountAction(SConnection * pCon, SicsInterp * pSics, void *pData,
argtolower(argc, argv);
argx = &argv[1];
iRet =
EvaluateFuPa((pFuncTemplate) & ActionTemplate, 25, argc - 1, argx,
EvaluateFuPa((pFuncTemplate) & ActionTemplate, 27 argc - 1, argx,
&PaRes);
if (iRet < 0) {
snprintf(pBueffel, 255,"%s", PaRes.pError);
@ -957,6 +976,7 @@ int CountAction(SConnection * pCon, SicsInterp * pSics, void *pData,
SCSendOK(pCon);
return 1;
case 11: /* status */
case 25:
self->pCountInt->TransferData(self, pCon);
if (GetCounterMode(self) == ePreset) {
lVal = GetCounterPreset(self);
@ -1008,9 +1028,9 @@ int CountAction(SConnection * pCon, SicsInterp * pSics, void *pData,
"ERROR: Insufficient privilege to set threshold", eError);
return 0;
}
if (isInRunMode(pServ->pExecutor)) {
if (isRunning(self->pCountInt)) {
SCWrite(pCon,
"ERROR: cannot change threshold while instrument is active",
"ERROR: cannot change threshold while counting",
eError);
return 0;
}
@ -1155,14 +1175,28 @@ int CountAction(SConnection * pCon, SicsInterp * pSics, void *pData,
case 22: /* getnmon */
snprintf(pBueffel, 131, "%s.getnmon = %d", argv[0], GetNMonitor(self));
SCWrite(pCon, pBueffel, eValue);
break;
case 23: /* state */
if(isRunning(self->pCountInt)){
snprintf(pBueffel, 131, "%s.state = run", argv[0]);
} else {
snprintf(pBueffel, 131, "%s.state = idle", argv[0]);
}
SCWrite(pCon, pBueffel, eValue);
return 1;
break;
case 23: /* getchannel */
case 24: /* error */
snprintf(pBueffel, 131, "%s.error = %s", argv[0],self->error);
SCWrite(pCon, pBueffel, eValue);
return 1;
return 1;
break;
case 25: /* getchannel */
snprintf(pBueffel,131,"%s.getchannel = %d", argv[0], GetControlMonitor(self));
SCWrite(pCon,pBueffel,eValue);
return 1;
break;
case 24: /* setchannel */
case 26: /* setchannel */
if (SetControlMonitor(self, PaRes.Arg[0].iVal)) {
return 1;
} else {

View File

@ -30,6 +30,9 @@ typedef struct __Counter{
int iCallbackCounter;
int badStatusCount;
int haltFixFlag; /* solely here to prevent multiple calls to the halt function on overrun timers in countersec.c*/
int tbLength; /* These two for caching float time bins in second generation HM's */
float *timeBinning;
char *error;
int (*setMode)(struct __Counter *self, CounterMode eMode);
CounterMode (*getMode)(struct __Counter *self);
int (*getNMonitor)(struct __Counter *self);

View File

@ -9,10 +9,13 @@
*
* Mark Koennecke, February 2009
*/
#include <math.h>
#include <time.h>
#include <sics.h>
#include <counter.h>
#include "sicshipadaba.h"
/*---------------------------------------------------------------------------
* defines for commmands
* -------------------------------------------------------------------------*/
@ -26,6 +29,19 @@ typedef struct {
float fCurrent;
char *pName;
} MonEvent, *pMonEvent;
/*-------------------------------------------------------------------------*/
static void SecCounterSetError(pCounter self, char *text)
{
hdbValue v;
pHdb node;
node = GetHipadabaNode(self->pDes->parNode, "error");
if(node != NULL){
v = MakeHdbText(strdup(text));
UpdateHipadabaPar(node,v,NULL);
ReleaseHdbValue(&v);
}
}
/*---------------------------------------------------------------------------*/
int SecCtrInvokeFunction(pCounter self, SConnection *pCon, int code)
{
@ -52,7 +68,7 @@ static int SecStartCount(void *pData, SConnection *pCon)
{
pCounter self = (pCounter)pData;
int status;
pHdb node;
pHdb node, statusNode;
assert(self != NULL);
@ -60,14 +76,14 @@ static int SecStartCount(void *pData, SConnection *pCon)
return 0;
}
statusNode = GetHipadabaNode(self->pDes->parNode, "status");
UpdateHipadabaPar(statusNode,MakeHdbText("run"), pCon);
status = SecCtrInvokeFunction(self,pCon, START);
self->haltFixFlag = 0;
if(status == 1){
self->isUpToDate = 0;
self->badStatusCount = 0;
self->tStart = time(NULL);
node = GetHipadabaNode(self->pDes->parNode, "status");
UpdateHipadabaPar(node,MakeHdbText("run"), pCon);
node = GetHipadabaNode(self->pDes->parNode, "control");
UpdateHipadabaPar(node,MakeHdbFloat(.0), pCon);
SetHdbProperty(node,"geterror", NULL);
@ -79,8 +95,10 @@ static int SecStartCount(void *pData, SConnection *pCon)
node = GetHipadabaNode(self->pDes->parNode, "time");
UpdateHipadabaPar(node,MakeHdbFloat(.0), pCon);
InvokeCallBack(self->pCall,COUNTSTART, pCon);
SecCounterSetError(self,"None");
return 1;
} else {
UpdateHipadabaPar(statusNode,MakeHdbText("error"), pCon);
ReleaseCountLock(self->pCountInt);
return HWFault;
}
@ -104,85 +122,96 @@ static int SecContinue(void *pData, SConnection *pCon)
/*----------------------------------------------------------------------------*/
static int SecCtrCheckStatus(void *pData, SConnection *pCon)
{
pCounter self = (pCounter)pData;
pHdb node = NULL, control = NULL;
hdbValue v;
int status;
MonEvent sMon;
float fControl, fPreset;
pCounter self = (pCounter)pData;
pHdb node = NULL, control = NULL;
hdbValue v;
int status;
MonEvent sMon;
float fControl, fPreset;
char error[132];
assert(self != NULL);
assert(self != NULL);
node = GetHipadabaNode(self->pDes->parNode,"status");
assert(node != NULL);
status = GetHipadabaPar(node,&v,pCon);
node = GetHipadabaNode(self->pDes->parNode,"status");
assert(node != NULL);
status = GetHipadabaPar(node,&v,pCon);
if(status != 1){
ReleaseCountLock(self->pCountInt);
return HWFault;
}
if(status != 1){
ReleaseCountLock(self->pCountInt);
return HWFault;
}
if(v.v.text == NULL){
return HWBusy;
}
if (strstr(v.v.text, "idle") != NULL) {
InvokeCallBack(self->pCall, COUNTEND, NULL);
ReleaseCountLock(self->pCountInt);
status = HWIdle;
} else if (strstr(v.v.text, "run") != NULL) {
status = HWBusy;
} else if (strstr(v.v.text, "nobeam") != NULL) {
status = HWNoBeam;
} else if (strstr(v.v.text, "pause") != NULL) {
status = HWPause;
} else if (strstr(v.v.text, "error") != NULL) {
InvokeCallBack(self->pCall, COUNTEND, NULL);
ReleaseCountLock(self->pCountInt);
status = HWFault;
} else {
SCPrintf(pCon, eError, "ERROR: unknown counter status %s found",
v.v.text);
ReleaseCountLock(self->pCountInt);
status = HWFault;
}
ReleaseHdbValue(&v);
if(v.v.text == NULL){
return HWBusy;
}
if (strstr(v.v.text, "idle") != NULL) {
InvokeCallBack(self->pCall, COUNTEND, NULL);
ReleaseCountLock(self->pCountInt);
status = HWIdle;
} else if (strstr(v.v.text, "run") != NULL) {
status = HWBusy;
} else if (strstr(v.v.text, "nobeam") != NULL) {
status = HWNoBeam;
} else if (strstr(v.v.text, "pause") != NULL) {
status = HWPause;
} else if (strstr(v.v.text, "restart") != NULL) {
SecStartCount(self, pCon);
return HWBusy;
} else if (strstr(v.v.text, "error") != NULL) {
InvokeCallBack(self->pCall, COUNTEND, NULL);
ReleaseCountLock(self->pCountInt);
if(GetHdbProperty(node,"geterror",error,sizeof(error)) == 1){
SCPrintf(pCon,eError,"ERROR: %s", error);
SecCounterSetError(self,error);
} else {
SecCounterSetError(self,"Undefined counter error: set status geterror");
SCPrintf(pCon,eError,"ERROR: Unknown counter status error: set status geterror property");
}
status = HWFault;
} else {
SCPrintf(pCon, eError, "ERROR: unknown counter status %s found",
v.v.text);
ReleaseCountLock(self->pCountInt);
status = HWFault;
}
ReleaseHdbValue(&v);
node = GetHipadabaNode(self->pDes->parNode,"control");
assert(node != NULL);
GetHipadabaPar(node,&v,pCon);
fControl = v.v.doubleValue;
node = GetHipadabaNode(self->pDes->parNode,"preset");
assert(node != NULL);
GetHipadabaPar(node,&v,pCon);
fPreset = v.v.doubleValue;
node = GetHipadabaNode(self->pDes->parNode,"control");
assert(node != NULL);
GetHipadabaPar(node,&v,pCon);
fControl = v.v.doubleValue;
node = GetHipadabaNode(self->pDes->parNode,"preset");
assert(node != NULL);
GetHipadabaPar(node,&v,pCon);
fPreset = v.v.doubleValue;
sMon.fCurrent = fControl;
sMon.fPreset = fPreset;
sMon.pName = self->name;
self->badStatusCount = 0;
sMon.fCurrent = fControl;
sMon.fPreset = fPreset;
sMon.pName = self->name;
self->badStatusCount = 0;
/*
* check for overrun counter boxes
*/
if(self->getMode(self) == eTimer &&
(sMon.fCurrent > sMon.fPreset +1)
&& self->haltFixFlag == 0){
SecCtrHalt(self);
self->haltFixFlag = 1;
}
/*
* check for overrun counter boxes
*/
if(self->getMode(self) == eTimer &&
(sMon.fCurrent > sMon.fPreset +1)
&& self->haltFixFlag == 0){
SecCtrHalt(self);
self->haltFixFlag = 1;
}
/*
* invoke notifiactions, if necessary
*/
if (self->iCallbackCounter > 20) {
InvokeCallBack(self->pCall, MONITOR, &sMon);
self->iCallbackCounter = 0;
} else {
self->iCallbackCounter++;
}
/*
* invoke notifiactions, if necessary
*/
if (self->iCallbackCounter > 20) {
InvokeCallBack(self->pCall, MONITOR, &sMon);
self->iCallbackCounter = 0;
} else {
self->iCallbackCounter++;
}
return status;
return status;
}
/*---------------------------------------------------------------------------
* Here is an issue: this ought to wait until data has arrived. Callers
@ -193,6 +222,12 @@ static int SecCtrCheckStatus(void *pData, SConnection *pCon)
* - add an update callback which deletes the property when done.
* - Check that property or the geterror property here in a loop
* until done or we timeout.
*
* Nope! Update October 2013:
* How it is normally done is to read the data through scripcontext when
* counting is finished and not to finish with counting until this has
* been done. The code below is only usefule for non scriptcontext
* drivers.
* -----------------------------------------------------------------------*/
static int SecCtrTransferData(void *pData, SConnection *pCon)
{
@ -373,25 +408,68 @@ static int CountCmd(pSICSOBJ ccmd, SConnection * con,
Hdb * cmdNode, Hdb * par[], int nPar)
{
float preset;
pHdb presetNode = NULL;
if(nPar < 1){
return 0;
presetNode = GetHipadabaNode(ccmd->objectNode,"preset");
if(presetNode != NULL){
preset = presetNode->value.v.doubleValue;
} else {
/*
This can really only happen when the counter is corrupt
*/
assert(0);
}
} else {
preset = par[0]->value.v.doubleValue;
}
preset = par[0]->value.v.doubleValue;
return DoCount((pCounter)ccmd, preset, con, 1);
}
/*--------------------------------------------------------------------------*/
static int GetMonitorCmd(pSICSOBJ ccmd, SConnection * con,
Hdb * cmdNode, Hdb * par[], int nPar)
{
long counts;
pCounter self = (pCounter)ccmd;
if(nPar < 1) {
SCWrite(con,"ERROR: missing monitor no in getmonitor",eError);
return 0;
}
counts = self->getMonitor(self,par[0]->value.v.intValue,con);
SCPrintf(con,eValue,"%s.monitor.%d = %ld", self->name,
par[0]->value.v.intValue,counts);
return 1;
}
/*--------------------------------------------------------------------------*/
static int GetCountsCmd(pSICSOBJ ccmd, SConnection * con,
Hdb * cmdNode, Hdb * par[], int nPar)
{
long counts;
pCounter self = (pCounter)ccmd;
counts = self->getCounts(self,con);
SCPrintf(con,eValue,"%s.counts = %ld", self->name,counts);
return 1;
}
/*--------------------------------------------------------------------------*/
static int CountNBCmd(pSICSOBJ ccmd, SConnection * con,
Hdb * cmdNode, Hdb * par[], int nPar)
{
float preset;
pHdb presetNode = NULL;
if(nPar < 1){
return 0;
presetNode = GetHipadabaNode(ccmd->objectNode,"preset");
if(presetNode != NULL){
preset = presetNode->value.v.doubleValue;
} else {
/*
This can really only happen when the counter is corrupt
*/
assert(0);
}
} else {
preset = par[0]->value.v.doubleValue;
}
preset = par[0]->value.v.doubleValue;
return DoCount((pCounter)ccmd, preset, con, 0);
}
/*--------------------------------------------------------------------------*/
@ -415,6 +493,55 @@ static int ContinueCmd(pSICSOBJ ccmd, SConnection * con,
pCounter self = (pCounter)ccmd;
return self->pCountInt->Continue(self,con);
}
/*-------------------------------------------------------------------------*/
extern int CounterInterest(int iEvent, void *pEvent, void *pUser);
/*--------------------------------------------------------------------------*/
static int InterestCmd(pSICSOBJ ccmd, SConnection * con,
Hdb * cmdNode, Hdb * par[], int nPar)
{
long lID;
pCounter self = (pCounter)ccmd;
lID = RegisterCallback(self->pCall, MONITOR, CounterInterest,
SCCopyConnection(con), SCDeleteConnection);
SCSendOK(con);
return 1;
}
/*--------------------------------------------------------------------------*/
static int CountStatusCmd(pSICSOBJ ccmd, SConnection * con,
Hdb * cmdNode, Hdb * par[], int nPar)
{
float preset, done;
int exponent;
pHdb node, data;
node = GetHipadabaNode(ccmd->objectNode,"preset");
assert(node != NULL);
preset = node->value.v.doubleValue;
node = GetHipadabaNode(ccmd->objectNode,"mode");
assert(node != NULL);
strtolower(node->value.v.text);
if(strcmp(node->value.v.text,"timer") == 0) {
data = GetHipadabaNode(ccmd->objectNode,"time");
assert(data != NULL);
done = data->value.v.doubleValue;
} else {
data = GetHipadabaNode(ccmd->objectNode,"values");
assert(data != NULL);
done = data->value.v.intArray[0];
data = GetHipadabaNode(ccmd->objectNode,"exponent");
assert(data != NULL);
exponent = data->value.v.intValue;
if(exponent != 0){
done /= pow(10,exponent);
}
}
SCPrintf(con,eValue,"%s.CountStatus = %f %f",
ccmd->objectNode->name, preset, done);
return 1;
}
/*--------------------------------------------------------------------------*/
pCounter CreateSecCounter(SConnection *pCon, char *type, char *name, int length)
{
@ -491,6 +618,9 @@ pCounter CreateSecCounter(SConnection *pCon, char *type, char *name, int length)
return NULL;
}
SetHdbProperty(child, "__save", "true");
SetHdbProperty(child, "values", "timer,monitor");
PrependHipadabaCallback(child,MakeHipadabaCallback(SICSValueCheckCallback,
NULL,NULL));
AddHipadabaChild(node, child, NULL);
child = MakeSICSHdbPar("status", usInternal, MakeHdbText("idle"));
@ -499,6 +629,12 @@ pCounter CreateSecCounter(SConnection *pCon, char *type, char *name, int length)
}
AddHipadabaChild(node, child, NULL);
child = MakeSICSHdbPar("error", usInternal, MakeHdbText("None"));
if (child == NULL) {
return NULL;
}
AddHipadabaChild(node, child, NULL);
child = MakeSICSHdbPar("control", usUser, MakeHdbFloat(.0));
if (child == NULL) {
return NULL;
@ -512,15 +648,29 @@ pCounter CreateSecCounter(SConnection *pCon, char *type, char *name, int length)
}
AddHipadabaChild(node, child, NULL);
child = MakeSICSHdbPar("exponent", usUser,
MakeHdbInt(0));
if (child == NULL) {
return NULL;
}
SetHdbProperty(child, "__save", "true");
AddHipadabaChild(node, child, NULL);
child = AddSICSHdbPar(node,"count", usUser, MakeSICSFunc(CountCmd));
AddSICSHdbPar(child, "preset", usUser, MakeHdbFloat(2));
child = AddSICSHdbPar(node,"countnb", usUser, MakeSICSFunc(CountNBCmd));
AddSICSHdbPar(child, "preset", usUser, MakeHdbFloat(2));
child = AddSICSHdbPar(node,"getmonitor", usSpy, MakeSICSFunc(GetMonitorCmd));
AddSICSHdbPar(child, "no", usSpy, MakeHdbInt(1));
child = AddSICSHdbPar(node,"getcounts", usUser, MakeSICSFunc(GetCountsCmd));
child = AddSICSHdbPar(node,"stop", usUser, MakeSICSFunc(StopCmd));
child = AddSICSHdbPar(node,"pause", usUser, MakeSICSFunc(PauseCmd));
child = AddSICSHdbPar(node,"continue", usUser, MakeSICSFunc(ContinueCmd));
child = AddSICSHdbPar(node,"interest", usUser, MakeSICSFunc(InterestCmd));
child = AddSICSHdbPar(node,"countstatus", usUser, MakeSICSFunc(CountStatusCmd));
return pRes;
}

16
danu.c
View File

@ -75,7 +75,7 @@ static int readDataNumber(pDataNumber self)
}
/*-----------------------------------------------------------------------*/
static int writeDataNumber(pDataNumber self, int iNum)
static int writeDataNumber(pDataNumber self, int iNum)
{
FILE *fd = NULL;
@ -126,7 +126,18 @@ static int InterestCallback(int iEvent, void *pEvent, void *pUser)
}
return 1;
}
/*-------------------------------------------------------------------------*/
static void *GetDanuInterface(void *data, int interfaceID)
{
pDataNumber self = (pDataNumber)data;
if(self == NULL){
return NULL;
}
if(interfaceID == CALLBACKINTERFACE){
return self->pCall;
}
return NULL;
}
/*-------------------------------------------------------------------------*/
pDataNumber CreateDataNumber(char *pFileName)
{
@ -140,6 +151,7 @@ pDataNumber CreateDataNumber(char *pFileName)
memset(pNew, 0, sizeof(DataNumber));
pNew->pDes = CreateDescriptor("DataNumber");
pNew->pDes->GetInterface = GetDanuInterface;
pNew->pCall = CreateCallBackInterface();
if (!pNew->pDes || !pNew->pCall) {
free(pNew);

884
devexec.c

File diff suppressed because it is too large Load Diff

View File

@ -1,5 +1,5 @@
#line 202 "devexec.w"
#line 204 "devexec.w"
/*----------------------------------------------------------------------------
@ -57,7 +57,7 @@
int StartCounter(pExeList self, SicsInterp *pSics, SConnection *pCon,
int level, char *name);
#line 249 "devexec.w"
#line 251 "devexec.w"
/*------------------------------------------------------------------------*/
@ -77,8 +77,10 @@
int DevExecTask(void *pEL);
void DevExecSignal(void *pEL, int iSignal, void *pSigData);
int GetDevExecInstStatus(pExeList self);
#line 251 "devexec.w"
#line 253 "devexec.w"
/*
@ -98,7 +100,7 @@
*/
/*-------------------------------------------------------------------------*/
#line 142 "devexec.w"
#line 144 "devexec.w"
int StopExe(pExeList self, char *name);
int StopExeWait(pExeList self);
@ -122,7 +124,7 @@
int ContinueExecution(pExeList self);
#line 269 "devexec.w"
#line 271 "devexec.w"
/*-------------------------- Commands ------------------------------------*/
int DevexecAction(SConnection *pCon, SicsInterp *pSics, void *pData,
@ -164,13 +166,13 @@
/*--------------------------- Locking ---------------------------------*/
#line 190 "devexec.w"
#line 192 "devexec.w"
void LockDeviceExecutor(pExeList self);
void UnlockDeviceExecutor(pExeList self);
#line 309 "devexec.w"
#line 311 "devexec.w"
/* -------------------------- Executor management -------------------------*/
@ -184,5 +186,8 @@
*/
void *GetExecutorCallback(pExeList self);
/*----------------------- Logging -----------------------------------------*/
void DevexecLog(char *op, char *device);
void DevexecLog(char *op, char *device);
void ExeInterest(pExeList pExe, char *name, char *action);
void InvokeNewTarget(pExeList pExe, char *name, float fTarget);
void SetDevexecStatus(pExeList pExe, int code);
#endif

View File

@ -373,7 +373,10 @@ to the global SICS device executor.
\mbox{}\verb@ */ @\\
\mbox{}\verb@ void *GetExecutorCallback(pExeList self);@\\
\mbox{}\verb@/*----------------------- Logging -----------------------------------------*/@\\
\mbox{}\verb@ void DevexecLog(char *op, char *device); @\\
\mbox{}\verb@ void DevexecLog(char *op, char *device);@\\
\mbox{}\verb@ void ExeInterest(pExeList pExe, char *name, char *action); @\\
\mbox{}\verb@ void InvokeNewTarget(pExeList pExe, char *name, float fTarget);@\\
\mbox{}\verb@ void SetDevexecStatus(pExeList pExe, int code);@\\
\mbox{}\verb@#endif @\\
\mbox{}\verb@@$\Diamond$
\end{list}

View File

@ -101,6 +101,8 @@ From within the SICS main loops this special function is called:
int DevExecTask(void *pEL);
void DevExecSignal(void *pEL, int iSignal, void *pSigData);
int GetDevExecInstStatus(pExeList self);
@}
CheckExeList then scan through its list of executing objects and request a
status from each of them. The next action depend on the status returned from
@ -319,7 +321,10 @@ to the global SICS device executor.
*/
void *GetExecutorCallback(pExeList self);
/*----------------------- Logging -----------------------------------------*/
void DevexecLog(char *op, char *device);
void DevexecLog(char *op, char *device);
void ExeInterest(pExeList pExe, char *name, char *action);
void InvokeNewTarget(pExeList pExe, char *name, float fTarget);
void SetDevexecStatus(pExeList pExe, int code);
#endif
@}

View File

@ -228,7 +228,7 @@ void DevAsconStatistics(DevSer *self, double *avg, \
*longCount = self->maxCount;
}
static int DevQueueTask(void *ds)
int DevQueueTask(void *ds)
{
DevSer *devser = ds;
DevAction *action;
@ -256,17 +256,19 @@ static int DevQueueTask(void *ds)
* TODO: this may be a place to record the end time
*/
if(devser->startTime > 0){
LogResponse(devser,1);
LogResponse(devser,1);
} else {
/* This is a follow up error and should not go into statistics */
/* This is a follow up error and should not go into statistics */
}
} else if (devser->status == AsconReady) {
replyData = AsconRead(devser->ascon);
if(replyData != NULL){
LogResponse(devser,0);
LogResponse(devser,0);
}
} else if (devser->status == AsconOffline) {
replyData = "ASCERR: offline";
} else {
return 1;
return 1;
}
if (devser->steps > 0) { /* debugging mode */
devser->steps--;
@ -308,7 +310,8 @@ DevSer *DevMake(SConnection * con, int argc, char *argv[])
devser->steps = -1; /* no debugging by default */
devser->status = AsconUnconnected;
devser->startTime = -1;
TaskRegister(pServ->pTasker, DevQueueTask, NULL, NULL, devser, 0);
TaskRegisterN(pServ->pTasker, AsconHostport(ascon),
DevQueueTask, NULL, NULL, devser, 0);
return devser;
}
@ -330,7 +333,8 @@ static void DevReset(DevSer * devser)
devser->current->kill(devser->current->data);
}
devser->killCurrent = 0;
/* free(devser->current); */
free(devser->current);
devser->current = NULL;
}
}
@ -601,3 +605,7 @@ char *DevStatus(DevSer *devser) {
double DevGetSetTimeout(DevSer *devser, double timeout, int setmode) {
return AsconGetSetTimeout(devser->ascon, timeout, setmode);
}
int DevReconnectInterval(DevSer *devser, int interval) {
return AsconReconnectInterval(devser->ascon, interval);
}

View File

@ -207,4 +207,20 @@ char *DevStatus(DevSer *devser);
*/
double DevGetSetTimeout(DevSer *devser, double timeout, int setmode);
/**
* \brief set reconnectInterval
* \param a the Ascon
* \param interval the interval to set (0: no reconnect, -1: read value)
* \return the value
*/
int DevReconnectInterval(DevSer *devser, int interval);
/**
* Drive devser processing. Normally called as a SICS task
* @param ds The device serialiser to run
* @return 1 when continuing the task, 0 when the task is to be stopped
*/
int DevQueueTask(void *ds);
#endif

View File

@ -475,7 +475,7 @@ int RunDiffScan(pDiffScan self, pScanData pScan,
InvokeCallBack(self->scanObject->pCall, SCANSTART, self->scanObject);
lID = TaskRegister(pServ->pTasker, DiffScanTask, NULL, NULL, self, 10);
lID = TaskRegisterN(pServ->pTasker,"diffscan", DiffScanTask, NULL, NULL, self, 10);
TaskWait(pServ->pTasker, lID);

View File

@ -113,7 +113,8 @@ experiment.
property on the node or as given on the command line. The alias is expected to match the size and type of
the data. Please note that hipadaba stores all floats as double which is NX_FLOAT64 as number type. Writing
data is started with the offset specified from the start of the data. This is useful to split a histogram
memory area into separate detectors or whatever.
memory area into separate detectors or whatever. The length of the amount of data to
copy is implied by the dimension of the SDS alias points to.
<dt>nxscript puthdbslab path start size
<dd>Put a hipdaba node as a slab. The node must have a property nxalias to determine where to write to.
Start and size are Tcl lists which give the start point where to write and the size of the data
@ -168,6 +169,25 @@ designated by targetAlias.
The difference is that this converts the data to a6 bit int before writing.
And SICSData objects are not supported.
</dl>
<dt>nxscript puts alias sgetstring [dim,dim]
<dd>
Writes any SICS data which can be fetched with sget. The input to sget is the
sgetstring. If sgetstring contains spaces, it must be quoted. The code tries to guess types
and dimensions automatically, thus alias must point to a definition string without -type,
-dim and -rank. The dimensions can be overriden with the optional dim argument which is a
komma separated list of dimensions.
</dl>
<dt>nxscript sappend alias sgetstring point [dim,dim]
<dd>
Appends any SICS data which can be fetched with sget to alias. The input to sget is the
sgetstring. If sgetstring contains spaces, it must be quoted. The code tries to guess types
and dimensions automatically, thus alias must point to a definition string without -type,
-dim and -rank. It is assumed that the first dimension is NX_UNLIMITED. The dimensions can be
overriden with the optional dim argument which is a komma separated list of dimensions. This override
only allows to specify the correct dimensions of the detector, NX_UNLIMITED is prepended
automatically. Point is the count in the dataset where to append to. Usually this is the
scan point number.
</dl>
</p>
<H1>Automatic Updating of NeXus Files</H1>
<P>

113
drive.c
View File

@ -169,7 +169,7 @@ int Start2Run(SConnection * pCon, SicsInterp * pInter, char *name,
/* first try to find the thing to drive */
pObject = FindCommand(pInter, name);
if (!pObject) {
snprintf(pBueffel,511, "Cannot find %s to drive ", name);
snprintf(pBueffel,511, "ERROR: Cannot find %s to drive ", name);
SCWrite(pCon, pBueffel, eError);
return 0;
}
@ -180,7 +180,7 @@ int Start2Run(SConnection * pCon, SicsInterp * pInter, char *name,
pDum = (Dummy *) pObject->pData;
pDes = pDum->pDescriptor;
if (!pDes) {
snprintf(pBueffel,511, "%s is NOT drivable!", pDes->name);
snprintf(pBueffel,511, "ERROR: %s is NOT drivable!", pDes->name);
SCWrite(pCon, pBueffel, eError);
return 0;
}
@ -190,14 +190,14 @@ int Start2Run(SConnection * pCon, SicsInterp * pInter, char *name,
*/
pInt = pDes->GetInterface(pDum, DRIVEID);
if (!pInt) {
snprintf(pBueffel,511, "%s is NOT drivable!", pDes->name);
snprintf(pBueffel,511, "ERROR: %s is NOT drivable!", pDes->name);
SCWrite(pCon, pBueffel, eError);
return 0;
}
if (pInt) {
iRet = pInt->CheckLimits(pDum, fNew, pBueffel, 511);
if (!iRet) {
SCWrite(pCon, pBueffel, eError);
SCPrintf(pCon, eError, "ERROR: %s", pBueffel);
SCSetInterrupt(pCon, eAbortOperation);
return 0;
}
@ -208,7 +208,7 @@ int Start2Run(SConnection * pCon, SicsInterp * pInter, char *name,
return 1;
}
} else {
snprintf(pBueffel,511, "%s is NOT drivable", pDes->name);
snprintf(pBueffel,511, "ERROR: %s is NOT drivable", pDes->name);
SCWrite(pCon, pBueffel, eError);
return 0;
}
@ -302,18 +302,21 @@ int DriveWrapper(SConnection * pCon, SicsInterp * pSics, void *pData,
return 0;
}
<<<<<<< HEAD
/* interpret arguments as pairs (name, value) and check */
SetStatus(eDriving);
=======
/* interprete arguments as pairs name value and try to start */
>>>>>>> master
for (i = 1; i < argc; i += 2) {
if (argv[i + 1] == NULL) {
snprintf(pBueffel, 511, "ERROR: no value found for driving %s", argv[i]);
SCWrite(pCon, pBueffel, eError);
SetStatus(eOld);
return 0;
}
iRet = Tcl_GetDouble(tcl_interp, argv[i + 1], &dTarget);
if (iRet == TCL_ERROR) {
SCWrite(pCon, Tcl_GetStringResult(tcl_interp), eError);
<<<<<<< HEAD
SetStatus(eOld);
return 0;
} else if (!isfinite(dTarget)) {
@ -321,7 +324,6 @@ int DriveWrapper(SConnection * pCon, SicsInterp * pSics, void *pData,
"ERROR: target %s value for %s is not a finite number",
argv[i + 1], argv[i]);
SCWrite(pCon, pBueffel, eError);
SetStatus(eOld);
return 0;
}
}
@ -330,7 +332,9 @@ int DriveWrapper(SConnection * pCon, SicsInterp * pSics, void *pData,
iRet = Tcl_GetDouble(tcl_interp, argv[i + 1], &dTarget);
if (iRet == TCL_ERROR) {
SCWrite(pCon, Tcl_GetStringResult(tcl_interp), eError);
SetStatus(eOld);
=======
StopExe(GetExecutor(), "ALL");
>>>>>>> master
return 0;
}
iRet = Start2Run(pCon, pSics, argv[i], RUNDRIVE, dTarget);
@ -344,7 +348,6 @@ int DriveWrapper(SConnection * pCon, SicsInterp * pSics, void *pData,
}
SCWrite(pCon, pBueffel, eError);
StopExe(GetExecutor(), "ALL");
SetStatus(eOld);
return 0;
}
}
@ -367,17 +370,18 @@ int DriveWrapper(SConnection * pCon, SicsInterp * pSics, void *pData,
sprintf(pBueffel, "Driving finished with problem");
SCWrite(pCon, pBueffel, eError);
ClearExecutor(GetExecutor());
SetStatus(eOld);
return 0;
} else if (iRet == DEVINT) {
sprintf(pBueffel, "ERROR: Driving Interrupted!");
SCWrite(pCon, pBueffel, eError);
ClearExecutor(GetExecutor());
SetStatus(eOld);
return 0;
}
<<<<<<< HEAD
SCWrite(pCon, "Driving finished successfully", eValue);
SetStatus(eOld);
=======
SCWrite(pCon, "Driving finished sucessfully", eValue);
>>>>>>> master
return 1;
}
@ -414,20 +418,21 @@ int RunWrapper(SConnection * pCon, SicsInterp * pSics, void *pData,
return 0;
}
<<<<<<< HEAD
/* interpret arguments as pairs name value and try to start */
SetStatus(eDriving);
=======
/* interprete arguments as pairs name value and try to start */
>>>>>>> master
for (i = 1; i < argc; i += 2) {
if (argv[i + 1] == NULL) {
snprintf(pBueffel,511, "ERROR: no value found for driving %s", argv[i]);
SCWrite(pCon, pBueffel, eError);
SetStatus(eOld);
return 0;
}
iRet = Tcl_GetDouble(tcl_interp, argv[i + 1], &dTarget);
if (iRet == TCL_ERROR) {
SCWrite(pCon, Tcl_GetStringResult(tcl_interp), eError);
StopExe(GetExecutor(), "ALL");
SetStatus(eOld);
return 0;
}
iRet = Start2Run(pCon, pSics, argv[i], RUNRUN, dTarget);
@ -436,13 +441,75 @@ int RunWrapper(SConnection * pCon, SicsInterp * pSics, void *pData,
argv[i + 1]);
SCWrite(pCon, pBueffel, eError);
StopExe(GetExecutor(), "ALL");
SetStatus(eOld);
return 0;
}
}
return 1;
}
/*---------------------------------------------------------------------------*/
int MoveWrapper(SConnection * pCon, SicsInterp * pSics, void *pData,
int argc, char *argv[])
{
Tcl_Interp *tcl_interp;
int iRet, i;
double dTarget;
float curPos;
char pBueffel[512];
Status eOld;
long groupID, taskID;
void *obj;
assert(pCon);
assert(pSics);
tcl_interp = InterpGetTcl(pSics);
/* check Status */
eOld = GetStatus();
/* check no of args */
if (argc < 3) {
snprintf(pBueffel,511, "Insufficient number of args. Usage %s name val",
argv[0]);
SCWrite(pCon, pBueffel, eError);
return 0;
}
/* check authorisation */
if (!SCMatchRights(pCon, usUser)) {
SCWrite(pCon,
"ERROR: You are not authorized to use the mv command",
eError);
return 0;
}
groupID = GetTaskGroupID(pServ->pTasker);
for (i = 1; i < argc; i += 2) {
if (argv[i + 1] == NULL) {
snprintf(pBueffel,511, "ERROR: no value found for driving %s", argv[i]);
SCWrite(pCon, pBueffel, eError);
return 0;
}
iRet = Tcl_GetDouble(tcl_interp, argv[i + 1], &dTarget);
if (iRet == TCL_ERROR) {
SCWrite(pCon, Tcl_GetStringResult(tcl_interp), eError);
StopExe(GetExecutor(), "ALL");
return 0;
}
obj = FindCommandData(pSics,argv[i],NULL);
if(obj == NULL || GetDrivableInterface(obj) == NULL){
SCPrintf(pCon,eError, "ERROR: %s not found, not started",argv[i]);
break;
}
GetDrivablePosition(obj,pCon,&curPos);
dTarget = curPos + dTarget;
taskID = StartDriveTask(obj, pCon, argv[i], (float)dTarget);
AddTaskToGroup(pServ->pTasker,taskID,groupID);
}
while(isTaskGroupRunning(pServ->pTasker,groupID)){
TaskYield(pServ->pTasker);
}
SCSendOK(pCon);
return 0;
}
/*---------------------------------------------------------------------------*/
int MakeDrive(SConnection * pCon, SicsInterp * pSics, void *pData,
int argc, char *argv[])
@ -473,5 +540,17 @@ int MakeDrive(SConnection * pCon, SicsInterp * pSics, void *pData,
SCWrite(pCon, pBueffel, eError);
return 0;
}
if (argc > 3) {
iRet = AddCommand(pSics, argv[2], MoveWrapper, NULL, NULL);
} else {
iRet = AddCommand(pSics, "mv", MoveWrapper, NULL, NULL);
}
if (!iRet) {
sprintf(pBueffel, "ERROR: duplicate command mv not created");
SCWrite(pCon, pBueffel, eError);
return 0;
}
return 1;
}

View File

@ -83,7 +83,15 @@ static int Resize(pDynString self, int iRequested)
self->iBufferSize = iNewSize;
return 1;
}
/*--------------------------------------------------------------------------*/
int DynStringCapacity(pDynString self, int length)
{
if(self->iBufferSize < length){
return Resize(self,length);
} else {
return 1;
}
}
/*--------------------------------------------------------------------------*/
void DeleteDynString(pDynString self)
{

View File

@ -109,4 +109,9 @@ char *Dyn2Cstring(pDynString self);
/*
convert to C string and delete dynstring. The result must be freed when no longer used.
*/
/*
Ensures that the DynString has the capacity length. In order to avoid unnecessary
concatenation when the length is already known.
*/
int DynStringCapacity(pDynString self, int length);
#endif

313
epicsmotor.c Normal file
View File

@ -0,0 +1,313 @@
/**
* This is a very basic first generation SICS EPICS motor driver for testing.
* It should be replaced by a second generation version when SINQ gets serious
* about EPICS and SICS.
*
* Mark Koennecke, February 2012
*/
#include <stdlib.h>
#include <sics.h>
#include <modriv.h>
/* EPICS stuff */
#include <tsDefs.h>
#include <cadef.h>
#include <ezca.h>
#include <alarmString.h>
#include <menuAlarmStat.h>
#include <db_access.h>
#include <epicsThread.h>
typedef struct __epicsMoDriv{
/* general motor driver interface
fields. REQUIRED!
*/
float fUpper; /* upper limit */
float fLower; /* lower limit */
char *name;
int (*GetPosition)(void *self, float *fPos);
int (*RunTo)(void *self,float fNewVal);
int (*GetStatus)(void *self);
void (*GetError)(void *self, int *iCode, char *buffer, int iBufLen);
int (*TryAndFixIt)(void *self, int iError,float fNew);
int (*Halt)(void *self);
int (*GetDriverPar)(void *self, char *name,
float *value);
int (*SetDriverPar)(void *self,SConnection *pCon,
char *name, float newValue);
void (*ListDriverPar)(void *self, char *motorName,
SConnection *pCon);
void (*KillPrivate)(void *self);
/* your drivers private fields follow below */
char *motBaseName;
char *ezcaError;
int ezcaCode;
int connectCount;
} epicsMotorDriver;
/*================================================================
GetPos returns OKOK on success, HWFault on failure
------------------------------------------------------------------*/
static int epicsGetPos(void *data, float *fPos){
epicsMotorDriver *self = NULL;
char fullName[132];
int status;
double position;
self = (epicsMotorDriver *)data;
snprintf(fullName,sizeof(fullName),"%s.DRBV",self->motBaseName);
status = ezcaGet(fullName,ezcaDouble,1, &position);
if(status == EZCA_OK){
*fPos =(float) position;
self->connectCount = 0;
return OKOK;
} else {
ezcaGetErrorString("ERROR: EPICS: ", &self->ezcaError);
self->ezcaCode = status;
return HWFault;
}
}
/*-------------- dummy callback for runto -------------------------*/
static void RunToDummy(struct event_handler_args d)
{
}
/*----------------------------------------------------------------
RunTo starts the motor running. Returns OKOK on success, HWfault
on Errors
------------------------------------------------------------------*/
static int epicsRunTo(void *data, float newValue){
epicsMotorDriver *self = NULL;
char fullName[132];
double position = newValue;
int status;
chid *cid;
self = (epicsMotorDriver *)data;
snprintf(fullName,sizeof(fullName),"%s.DVAL",self->motBaseName);
ezcaPvToChid(fullName,&cid);
status = ca_put_callback(DBR_DOUBLE,*cid,&position, RunToDummy,NULL);
if(status != ECA_NORMAL){
snprintf(fullName, sizeof(fullName),"Bad CA status %d", status);
self->ezcaError = strdup(fullName);
self->ezcaCode = status;
return HWFault;
} else {
ca_pend_event(.05);
self->connectCount = 0;
return OKOK;
}
}
/*------------------------------------------------------------------
CheckStatus queries the sattus of a running motor. Possible return
values can be:
HWBusy : motor still running
HWFault : motor error detected
HWPosFault : motor finished, but position not reached
HWIdle : motor finished OK
HWWarn : motor issued warning
--------------------------------------------------------------------*/
static int epicsCheckStatus(void *data){
epicsMotorDriver *self = NULL;
char fullName[132];
short smov, stat;
int status;
self = (epicsMotorDriver *)data;
snprintf(fullName,sizeof(fullName),"%s.DMOV",self->motBaseName);
status = ezcaGet(fullName,ezcaShort,1, &smov);
if(status == EZCA_OK){
self->connectCount = 0;
if(smov == 0){
return HWBusy;
} else {
snprintf(fullName,sizeof(fullName),"%s.STAT",self->motBaseName);
status = ezcaGet(fullName,ezcaShort,1, &stat);
if(stat != menuAlarmStatNO_ALARM){
snprintf(fullName,sizeof(fullName),"EPICS ALARM: %s", epicsAlarmConditionStrings[stat]);
self->ezcaError = strdup(fullName);
return HWFault;
} else {
return HWIdle;
}
}
} else {
ezcaGetErrorString("ERROR: EPICS: ", &self->ezcaError);
self->ezcaCode = status;
return HWFault;
}
}
/*------------------------------------------------------------------
GetError gets more information about error which occurred
*iCode is an integer error code to be used in TryFixIt as indicator
buffer is a buffer for a text description of the problem
iBufLen is the length of buffer
--------------------------------------------------------------------*/
static void epicsGetError(void *data, int *iCode, char *buffer,
int iBufLen){
epicsMotorDriver *self = NULL;
self = (epicsMotorDriver *)data;
if(self->ezcaError != NULL){
strncpy(buffer,self->ezcaError,iBufLen);
ezcaFree(self->ezcaError);
self->ezcaError = NULL;
}
}
/*------------------------------------------------------------------
TryAndFixIt tries everything which is possible in software to fix
a problem. iError is the error code from GetError, newValue is
the target value for the motor
Possible retrun values are:
MOTOK : everything fixed
MOTREDO : try again
MOTFAIL : cannot fix this
--------------------------------------------------------------------*/
static int epicsFixIt(void *data, int iError, float newValue){
epicsMotorDriver *self = NULL;
self = (epicsMotorDriver *)data;
if(self->ezcaCode == EZCA_NOTCONNECTED && self->connectCount < 2) {
self->connectCount++;
return MOTREDO;
}
return MOTFAIL;
}
/*-------------------------------------------------------------------
Halt tries to stop the motor. Halt errors are ignored.
For some as yet unknown reasons, I cannot send the stop on the
same CA line then the rest. But with a new thread which just sends
the stop, it works. This is a straightforward use of a thread:
do your thing and terminate. Do not interact with other parts
of the program.
---------------------------------------------------------------------*/
static void HaltThreadFunc(void *param)
{
char *pvName = (char *)param;
short stop = 1;
chid cid;
ca_context_create(ca_disable_preemptive_callback);
ca_create_channel(pvName,NULL,NULL,10,&cid);
ca_pend_io(5.);
ca_put(DBR_SHORT,cid,&stop);
ca_pend_io(5.0);
free(pvName);
printf("HaltThread ends\n");
}
/*-------------------------------------------------------------------*/
static int epicsHalt(void *data){
epicsMotorDriver *self = NULL;
char fullName[132];
short stop =1;
chid *cid;
int status;
self = (epicsMotorDriver *)data;
snprintf(fullName,sizeof(fullName),"%s.STOP",self->motBaseName);
/* ezcaStartGroup(); */
/* ezcaPut(fullName,ezcaShort,1,&stop); */
/* ezcaEndGroup(); */
/* ezcaPvToChid(fullName,&cid); */
/* status = ca_put_callback(DBR_SHORT,*cid,&stop, RunToDummy,NULL); */
/* printf("Halt status %d\n", status); */
/* ca_flush_io(); */
/* printf("Halt after poll\n"); */
epicsThreadCreate("Hugo",
epicsThreadPriorityHigh,
epicsThreadStackMedium,
HaltThreadFunc,
(void *)strdup(fullName));
return 1;
}
/*--------------------------------------------------------------------
GetDriverPar retrieves the value of a driver parameter.
Name is the name of the parameter, fValue the value when found.
Returns 0 on success, 0 else
-----------------------------------------------------------------------*/
static int epicsGetDriverPar(void *data, char *name, float *value){
epicsMotorDriver *self = NULL;
self = (epicsMotorDriver *)data;
return 0;
}
/*----------------------------------------------------------------------
SetDriverPar sets a driver parameter. Returns 0 on failure, 1 on
success. Name is the parameter name, pCon the connection to report
errors too, value the new value
------------------------------------------------------------------------*/
static int epicsSetDriverPar(void *data, SConnection *pCon,
char *name, float value){
epicsMotorDriver *self = NULL;
self = (epicsMotorDriver *)data;
return 0;
}
/*-----------------------------------------------------------------------
ListDriverPar lists the names and values of driver parameters to
pCon. Motorname is the name of the motor ro prefix to the listing.
-------------------------------------------------------------------------*/
static void epicsListDriverPar(void *data, char *motorname,
SConnection *pCon){
epicsMotorDriver *self = NULL;
self = (epicsMotorDriver *)data;
}
/*-----------------------------------------------------------------------
KillPrivate has the task to delete possibly dynamically allocated
memory in the private part of the driver structure
------------------------------------------------------------------------*/
static void epicsKillPrivate(void *data){
epicsMotorDriver *self = NULL;
self = (epicsMotorDriver *)data;
if(self->ezcaError != NULL){
ezcaFree(self->ezcaError);
}
if(self->motBaseName != NULL){
free(self->motBaseName);
}
}
/*=======================================================================*/
MotorDriver *epicsMakeMotorDriver(char *baseName) {
epicsMotorDriver *pNew = NULL;
char fullName[132];
double limit;
pNew = malloc(sizeof(epicsMotorDriver));
if(pNew == NULL){
return NULL;
}
memset(pNew,0,sizeof(epicsMotorDriver));
pNew->motBaseName = strdup(baseName);
snprintf(fullName,sizeof(fullName),"%s.DRBV",pNew->motBaseName);
ezcaSetMonitor(fullName,ezcaDouble,1);
snprintf(fullName,sizeof(fullName),"%s.DMOV",pNew->motBaseName);
ezcaSetMonitor(fullName,ezcaShort,1);
snprintf(fullName,sizeof(fullName),"%s.STAT",pNew->motBaseName);
ezcaSetMonitor(fullName,ezcaShort,1);
snprintf(fullName,sizeof(fullName),"%s.HLM",pNew->motBaseName);
ezcaGet(fullName,ezcaDouble,1, &limit);
pNew->fUpper = limit;
snprintf(fullName,sizeof(fullName),"%s.LLM",pNew->motBaseName);
ezcaGet(fullName,ezcaDouble,1, &limit);
pNew->fLower = limit;
pNew->GetPosition = epicsGetPos;
pNew->RunTo = epicsRunTo;
pNew->Halt = epicsHalt;
pNew->GetStatus = epicsCheckStatus;
pNew->GetError = epicsGetError;
pNew->TryAndFixIt = epicsFixIt;
pNew->GetDriverPar = epicsGetDriverPar;
pNew->SetDriverPar = epicsSetDriverPar;
pNew->ListDriverPar = epicsListDriverPar;
pNew->KillPrivate = epicsKillPrivate;
/* ezcaTraceOn(); */
return (MotorDriver *)pNew;
}

View File

@ -80,12 +80,9 @@ static long EVIDrive(void *pData, SConnection * pCon, float fVal)
assert(pCon);
if (self->runScript != NULL) {
savedStatus = GetStatus();
SetStatus(eBatch);
pTcl = InterpGetTcl(pServ->pSics);
snprintf(pBueffel, sizeof(pBueffel), "%s %f", self->runScript, fVal);
iRet = Tcl_Eval(pTcl, pBueffel);
SetStatus(savedStatus);
if (iRet != TCL_OK) {
SCPrintf(pCon, eError,
"ERROR: %s while processing runscript for %s",
@ -423,7 +420,6 @@ static int ErrPause(void *pData)
}
/* OK now, continue */
SetStatus(eEager);
self->iWarned = 0;
ContinueExecution(pExe);
return 1;
@ -674,7 +670,7 @@ pEVControl CreateEVController(pEVDriver pDriv, char *pName, int *iErr)
memset(pRes, 0, sizeof(EVControl));
/* new Object Descriptor */
pRes->pDes = CreateDescriptor("Environment_Controller");
pRes->pDes = CreateDescriptor("Environment Controller");
if (!pRes->pDes) {
free(pRes);
return NULL;
@ -1481,7 +1477,7 @@ int EVControlFactory(SConnection * pCon, SicsInterp * pSics, void *pData,
}
strtolower(argv[2]);
strtolower(argv[3]);
if (FindCommandData(pSics, argv[2], "Environment_Controller")) {
if (FindCommandData(pSics, argv[2], "Environment Controller")) {
if (strcmp(argv[1], "replace") == 0) {
if (!RemoveEVController(pCon, argv[2])) {
return 0;

View File

@ -71,6 +71,8 @@ static char *pEvent[] = {
"STATEEND",
"NEWTARGET",
"DIMCHANGE",
"PAUSE",
"CONTINUE",
NULL
};

18
event.h
View File

@ -1,5 +1,5 @@
#line 103 "event.w"
#line 108 "event.w"
/*----------------------------------------------------------------------------
E V E N T
@ -18,7 +18,7 @@
int Text2Event(char *pText);
#line 116 "event.w"
#line 121 "event.w"
@ -49,12 +49,10 @@
#define STEND 22
#define NEWTARGET 23
#define DIMCHANGE 24
#define STPAUSE 25
#define STCONTINUE 26
#define STBUSY 27
#define STIDLE 28
#define IPAUSE 25
#define CONTINUE 26
#line 118 "event.w"
#line 123 "event.w"
/*----------------- event data structure for the NEWTARGET event ---------*/
@ -64,15 +62,15 @@ typedef struct {
} NewTarget, *pNewTarget;
/*--------------- Signals for the Signalfunction of each task ------------*/
#line 85 "event.w"
#line 90 "event.w"
#define SICSINT 300
#define SICSBROADCAST 301
#define TOKENGRAB 302
#define TOKENRELEASE 303
#define COMLOG 304
#define CRONLIST 305
#define CRONFUNC 305
#line 126 "event.w"
#line 131 "event.w"
#endif

View File

@ -60,6 +60,8 @@ $\langle$VE {\footnotesize ?}$\rangle\equiv$
\mbox{}\verb@#define STEND 22@\\
\mbox{}\verb@#define NEWTARGET 23@\\
\mbox{}\verb@#define DIMCHANGE 24@\\
\mbox{}\verb@#define IPAUSE 25@\\
\mbox{}\verb@#define CONTINUE 26@\\
\mbox{}\verb@@$\Diamond$
\end{list}
\vspace{-1ex}
@ -99,8 +101,11 @@ operation.
\item[HDBVAL] The Hdb is notified of a value change. The eventData will be
the object on which the data changed.
\item[NEWTARGET] is invoked when a new target has been set on a drivable.
\item[PAUSE] Pause counting
\item[CONTINUE] Continue counting
\end{description}
Furthermore event contains system wide signal codes which are interpreted in
the signal functions provided by each SICS task. These code are
evaluated by the TaskSignalFunction which may be configured for each

View File

@ -43,6 +43,8 @@ if the event code is not known, else the apropriate event code.
#define STEND 22
#define NEWTARGET 23
#define DIMCHANGE 24
#define IPAUSE 25
#define CONTINUE 26
@}
\begin{description}
\item[VALUECHANGE] This is a variable changing its value. As event data a pointer to the
@ -74,8 +76,11 @@ operation.
\item[HDBVAL] The Hdb is notified of a value change. The eventData will be
the object on which the data changed.
\item[NEWTARGET] is invoked when a new target has been set on a drivable.
\item[PAUSE] Pause counting
\item[CONTINUE] Continue counting
\end{description}
Furthermore event contains system wide signal codes which are interpreted in
the signal functions provided by each SICS task. These code are
evaluated by the TaskSignalFunction which may be configured for each

View File

@ -91,13 +91,39 @@ static char *locateName(char *filename)
}
return filename;
}
/*----------------------------------------------------------------------
If this is MOUNTAINBATCH file, replace ocurrences of @nl@ with \n
------------------------------------------------------------------------*/
static void fixMountainBatch(pExeBuf self)
{
char *pPtr, *pData, *pNL;
pPtr = GetCharArray(self->bufferContent);
if(strstr(pPtr, "#MOUNTAINBATCH") != pPtr){
/*
nothing to do
*/
return;
}
pData = strdup(pPtr);
DynStringClear(self->bufferContent);
pPtr = pData;
while((pNL = strstr(pPtr,"@nl@")) != NULL){
*pNL = '\n';
*(pNL+1) = '\0';
DynStringConcat(self->bufferContent, pPtr);
pPtr = pNL +4;
}
DynStringConcat(self->bufferContent,pPtr);
free(pData);
}
/*-----------------------------------------------------------------------*/
int exeBufLoad(pExeBuf self, char *filename)
{
char line[256], *pPtr;
FILE *fd = NULL;
int status, idx;
int status, idx, gtsebatch = 0;
assert(self);
fd = fopen(filename, "r");
@ -128,6 +154,7 @@ int exeBufLoad(pExeBuf self, char *filename)
free(self->name);
}
self->name = strdup(locateName(filename));
fixMountainBatch(self);
return 1;
}
@ -297,8 +324,6 @@ int exeBufProcess(pExeBuf self, SicsInterp * pSics,
DeleteDynString(command);
if (SCGetInterrupt(pCon) >= eAbortBatch) {
SCWrite(pCon, "ERROR: batch processing interrupted", eError);
InvokeCallBack(pCall, BATCHEND, self->name);
SetStatus(eEager);
if (pCall != NULL) {
InvokeCallBack(pCall, BATCHEND, self->name);
}
@ -350,7 +375,6 @@ int exeBufProcessErrList(pExeBuf self, SicsInterp * pSics,
DeleteDynString(command);
if (SCGetInterrupt(pCon) >= eAbortBatch) {
SCWrite(pCon, "ERROR: batch processing interrupted", eError);
SetStatus(eEager);
return 0;
} else {
SCSetInterrupt(pCon, eContinue);

View File

@ -224,7 +224,16 @@ pDynString findBatchFile(SicsInterp * pSics, char *name)
}
return locateBatchBuffer(self, name);
}
/*--------------------------------------------------------------------*/
int isBatchRunning()
{
pExeMan self = (pExeMan) FindCommandData(pServ->pSics, "exe", "ExeManager");
if(self != NULL && self->exeStackPtr > 0){
return 1;
} else {
return 0;
}
}
/*--------------------------------------------------------------------*/
static int runBatchBuffer(pExeMan self, SConnection * pCon,
SicsInterp * pSics, char *name)
@ -1175,7 +1184,9 @@ static int printBuffer(pExeMan self, SConnection * pCon,
}
while (fgets(pLine, 511, fd) != NULL) {
DynStringConcat(filePath, pLine);
DynStringConcatChar(filePath,'\n');
if(strrchr(pLine,(int)'\n') == NULL){
DynStringConcatChar(filePath,'\n');
}
}
fclose(fd);
SCWrite(pCon, GetCharArray(filePath), eValue);

View File

@ -19,4 +19,6 @@ pDynString findBatchFile(SicsInterp * pSics, char *name);
int exeHdbBuffer(SConnection * pCon, SicsInterp * pSics, char *name);
int exeHdbNode(pHdb exeNode, SConnection * pCon);
int isBatchRunning();
#endif

View File

@ -20,10 +20,6 @@
#include "scan.h"
#include "fitcenter.h"
#define THRESHOLD .1
float ggf1[] = { 0.006, 0.061, 0.242, 0.383, 0.242, 0.061, 0.006 }; // Gaussian Smooth Filter
float ggf2[] = { 0.1429, 0.1429, 0.1429, 0.1429, 0.1429, 0.1429, 0.1429 }; // Mean Smooth Filter
/*--------------------------------------------------------------------------*/
typedef struct __FitCenter {
pObjectDescriptor pDes;
@ -77,28 +73,6 @@ void DeleteFitCenter(void *pData)
free(self);
}
/*--------------------------------------------------------------------------*/
static void SmoothScanCounts(long *lData, int iDataLen)
{
int ind = (int) (sizeof(ggf1) / sizeof(float) - 1) / 2;
long *pData = (long *) malloc(iDataLen * sizeof(long));
for (int i = 0; i < iDataLen; i++)
pData[i] = lData[i];
for (int i = 0; i < iDataLen; i++) {
lData[i] = pData[i] * ggf1[ind];
for (int j = 1; j <= ind; j++) {
if ((i - j) > 0)
lData[i] += pData[i - j] * ggf1[ind - j];
if ((i + j) < iDataLen)
lData[i] += pData[i + j] * ggf1[ind + j];
}
}
free(pData);
}
/*--------------------------------------------------------------------------*/
static int Init(pFit self)
{
@ -123,9 +97,6 @@ static int Init(pFit self)
}
GetScanCounts(self->pScan, self->lCounts, self->iNP);
SmoothScanCounts(self->lCounts, self->iNP);
GetScanVar(self->pScan, 0, self->fAxis, self->iNP);
GetScanVarName(self->pScan, 0, self->pName, 131);
@ -462,40 +433,11 @@ int FitWrapper(SConnection * pCon, SicsInterp * pSics, void *pData,
int iRet;
char pBueffel[256];
pDynString buf = NULL;
pScanData pScan = NULL;
char *cmd = NULL;
self = (pFit) pData;
assert(self);
/*
* allow for an optional scan object as first argument
* and make cmd point at the command
*/
if (argc > 1) {
cmd = argv[1];
CommandList *pCom = NULL;
pCom = FindCommand(pSics, argv[1]);
if (pCom) {
pDummy pDum = NULL;
pDum = (pDummy) pCom->pData;
if (pDum) {
if (strcmp(pDum->pDescriptor->name, "ScanObject") == 0) {
pScan = (pScanData) pDum;
if (argc > 2)
cmd = argv[2];
}
}
}
}
if (pScan) {
pScanData pScanSave;
pScanSave = self->pScan;
self->pScan = pScan;
iRet = CalculateFit(self);
self->pScan = pScanSave;
} else {
iRet = CalculateFit(self);
}
iRet = CalculateFit(self);
switch (iRet) {
case 0:
SCWrite(pCon, "ERROR: failure to fit your data!", eError);
@ -528,14 +470,14 @@ int FitWrapper(SConnection * pCon, SicsInterp * pSics, void *pData,
This is a little feature to get the peak without rubbish for
the TAS routines
*/
if (cmd) {
strtolower(cmd);
if (strcmp(cmd, "value") == 0) {
sprintf(pBueffel, "%f", self->fCenter);
if (argc > 1) {
strtolower(argv[1]);
if (strcmp(argv[1], "value") == 0) {
snprintf(pBueffel,sizeof(pBueffel)-1, "%f", self->fCenter);
SCWrite(pCon, pBueffel, eValue);
return 1;
}
if (strcmp(cmd, "data") == 0) {
if (strcmp(argv[1], "data") == 0) {
snprintf(pBueffel, 255, "%f,%f,%ld",
self->fCenter, self->FWHM, self->lPeak);
SCWrite(pCon, pBueffel, eValue);
@ -629,5 +571,6 @@ int CenterWrapper(SConnection * pCon, SicsInterp * pSics, void *pData,
self = (pFit) pData;
assert(self);
CalculateFit(self);
return DriveCenter(self, pCon, pSics);
}

View File

@ -19,6 +19,9 @@
extended to support nxscripted file writing: Mark Koennecke, May 2004
extended to support GTSE, Mark Koennecke, May 2008
modifed to support second generation HM's via the bridge,
Mark Koennecke, December 2012
--------------------------------------------------------------------------*/
#include <stdlib.h>
#include <assert.h>
@ -428,20 +431,20 @@ static int updateHMFMData(SicsInterp * pSics, SConnection * pCon)
HistInt *data = NULL;
pHistMem pMem = NULL;
pMem = (pHistMem) FindCommandData(pSics, "hm2", "HistMem");
pMem = (pHistMem) FindHM(pSics, "hm2");
if (pMem == NULL) {
return 0;
}
fTimeBin = GetHistTimeBin(pMem, &iTime);
setFMDataPointer(GetHistogramPointer(pMem, pCon), iTime, MIDDLE);
pMem = (pHistMem) FindCommandData(pSics, "hm1", "HistMem");
pMem = (pHistMem) FindHM(pSics, "hm1");
if (pMem == NULL) {
return 0;
}
setFMDataPointer(GetHistogramPointer(pMem, pCon), iTime, LOWER);
pMem = (pHistMem) FindCommandData(pSics, "hm3", "HistMem");
pMem = (pHistMem) FindHM(pSics, "hm3");
if (pMem == NULL) {
return 0;
}
@ -567,7 +570,7 @@ static int TOFLambda(SicsInterp * pSics, SConnection * pCon,
float fCenter, fFWHM, fStdDev, fVal;
float fMon, fData, distMonoDet, distFermiDet, tdiff, lambda;
pMem = (pHistMem) FindCommandData(pSics, "hm1", "HistMem");
pMem = (pHistMem) FindHM(pSics, "hm1");
if (pMem == NULL) {
SCWrite(pCon,
"ERROR: need lower detector bank for lambda calculation",
@ -650,7 +653,7 @@ static float calcElastic(SicsInterp * pSics, SConnection * pCon)
pHistMem pMem = NULL;
float fCenter, fFWHM, fStdDev, fVal;
pMem = (pHistMem) FindCommandData(pSics, "hm2", "HistMem");
pMem = (pHistMem) FindHM(pSics, "hm2");
if (pMem == NULL) {
SCWrite(pCon,
"ERROR: need middle detector bank for elastic peak calculation",

View File

@ -647,7 +647,7 @@ void z1FromNormalBeam(double lambda, double omega, double gamma,
/*--------------------------------------------------------------------*/
double circlify(double val)
{
while (val > 360.) {
while (val >= 359.8) {
val -= 360.;
}
while (val < 0.) {

View File

@ -753,11 +753,11 @@ static int GenInconsumerate(pSICSOBJ self, SConnection * pCon,
{
double hkl[3], qvec[3];
pFourMess priv = self->pPrivate;
int i, j;
int i, j, iGen = 0, startCount;
if (nPar < 3) {
SCWrite(pCon,
"ERROR: need q displacement vector with three compononts",
"ERROR: need q displacement vector with three components",
eError);
return 0;
}
@ -765,31 +765,32 @@ static int GenInconsumerate(pSICSOBJ self, SConnection * pCon,
qvec[1] = par[1]->value.v.doubleValue;
qvec[2] = par[2]->value.v.doubleValue;
for (i = 0; i < priv->masterCount; i++) {
startCount = priv->masterCount;
for (i = 0; i < startCount; i++) {
GetRefIndex(priv->messList, i, hkl);
if(ABS(hkl[0])+ABS(hkl[1])+ABS(hkl[2]) < .3){
/*
* Stop generation for 0,0,0,
*/
continue;
}
for (j = 0; j < 3; j++) {
hkl[j] += qvec[j];
}
AddRefIdx(priv->messList, hkl);
iGen++;
GetRefIndex(priv->messList, i, hkl);
for (j = 0; j < 3; j++) {
hkl[j] -= qvec[j];
}
AddRefIdx(priv->messList, hkl);
if(FindHKL(priv->messList, hkl[0], hkl[1], hkl[2]) == NULL){
AddRefIdx(priv->messList, hkl);
iGen++;
}
if(SCGetInterrupt(pCon) != eContinue){
SCWrite(pCon,"ERROR: generating incommensurate reflections aborted", eError);
return 0;
}
if( (i % 50) == 0 ){
SCPrintf(pCon,eLog, "%d of %d input reflections processed", i, startCount);
}
}
SCPrintf(pCon, eValue,
"%d additional inconsumerate reflections generated",
priv->masterCount*2);
"%d additional inconsumerate reflections generated", iGen);
return 1;
}

10
frame.c
View File

@ -19,8 +19,8 @@
#include "HistMem.h"
#include "HistMem.i"
#include "HistDriv.i"
#include "psi/hardsup/sinqhm.h"
#include "psi/sinqhmdriv.i"
#include "sicspsi/hardsup/sinqhm.h"
#include "sicspsi/sinqhmdriv.i"
#include "nxdict.h"
#include "frame.h"
@ -66,7 +66,7 @@ static int readHMFrame(SConnection * pCon, pHistMem pHM,
if (nFrame >= noTimeBins) {
nFrame = noTimeBins - 1;
}
if (isSINQHMDriv(pHM->pDriv) && noTimeBins > 2) {
if (!isSecondGen(pHM) && isSINQHMDriv(pHM->pDriv) && noTimeBins > 2) {
/*
read from HM. The 5 is PROJECT__FRAME in Sinqhm_def.h
Again: be friendly: fix out of range frames
@ -81,7 +81,7 @@ static int readHMFrame(SConnection * pCon, pHistMem pHM,
free(buffer);
return 0;
}
} else if(isSINQHTTP(pHM->pDriv) && noTimeBins > 2){
} else if(!isSecondGen(pHM) && isSINQHTTP(pHM->pDriv) && noTimeBins > 2){
if(sansflag){
snprintf(histCommand,132,"sample:0:%d:%d:%d", iDim[0]*iDim[1], nFrame, nFrame+1);
} else {
@ -244,7 +244,7 @@ int PSDFrameAction(SConnection * pCon, SicsInterp * pSics, void *pData,
eError);
return 0;
}
pHM = (pHistMem) FindCommandData(pSics, argv[2], "HistMem");
pHM = (pHistMem) FindHM(pSics, argv[2]);
if (pHM == NULL) {
SCWrite(pCon, "ERROR: Did not find histogram memory", eError);
return 0;

View File

@ -17,6 +17,10 @@
* copyright: see file COPYRIGHT
*
* Mark Koennecke, March 2009
*
* Added CountTblCmd
*
* Mark Koennecke, march 2013
*/
#include <stdlib.h>
#include "sicshipadaba.h"
@ -75,6 +79,20 @@ static int ClearTblCmd(pSICSOBJ self, SConnection *pCon, pHdb commandNode,
return 1;
}
/*----------------------------------------------------------------------*/
int CountTblCmd(pSICSOBJ self, SConnection *pCon, pHdb commandNode,
pHdb par[], int nPar)
{
pHdb node;
int nRows = 0;
node = GetHipadabaNode(self->objectNode,"data");
if(node != NULL){
nRows = CountHdbChildren(node);
}
SCPrintf(pCon,eValue,"rows = %d", nRows);
return 1;
}
/*----------------------------------------------------------------------*/
static int AddTblRowCmd(pSICSOBJ self, SConnection *pCon, pHdb commandNode,
pHdb par[], int nPar)
{
@ -470,6 +488,9 @@ pSICSOBJ MakeHdbTable(char *name, char *hdbclass)
SetHdbProperty(node,"priv","user");
AddHipadabaChild(cmd,node, NULL);
cmd = AddSICSHdbPar(result->objectNode, "count", usSpy,
MakeSICSFunc(CountTblCmd));
return result;
}
/*---------------------------------------------------------------------------*/

View File

@ -10,6 +10,7 @@
#include <stdlib.h>
#include <assert.h>
#include <ctype.h>
#include <math.h>
#include "hipadaba.h"
#define ABS(x) (x < 0 ? -(x) : (x))
@ -21,6 +22,7 @@ static char update[] = { "update" };
static char treeChange[] = { "treeChange" };
static char dataSearch[] = { "dataSearch" };
static char killNode[] = { "killNode" };
static char propertyChange[] = { "propertyChange" };
/*------------------------------------------------------------------------*/
pHdbDataMessage GetHdbSetMessage(pHdbMessage toTest)
@ -76,6 +78,15 @@ pHdbMessage GetHdbKillNodeMessage(pHdbMessage toTest)
return NULL;
}
/*-------------------------------------------------------------------------*/
pHdbPropertyChange GetPropertyChangeMessage(pHdbMessage toTest)
{
if (toTest->type == propertyChange) {
return (pHdbPropertyChange)toTest;
}
return NULL;
}
/*================== internal functions ===================================*/
void DeleteCallbackChain(pHdb node)
{
@ -305,6 +316,10 @@ static pHdb locateChild(pHdb root, char *name)
{
pHdb current = NULL;
if(root == NULL){
return NULL;
}
current = root->child;
while (current != NULL) {
if (strcmp(current->name, name) == 0) {
@ -486,8 +501,57 @@ static unsigned short fletcher16( char *data, size_t len)
result = result << 8 | checkB;
return result ;
}
/*------------------------------------------------------------------------*/
#define MAXLEN 65536
/*------------------------------------------------------------------------*/
static unsigned short longfletcher16(char *data, size_t len)
{
char buffer[MAXLEN];
int i, j, div, count;
char *pPtr;
if(len < MAXLEN){
return fletcher16(data,len);
}
/**
* sum together to run the more complex checksum on
* more juicy data
*/
div = (int)trunc((float)len/(float)MAXLEN);
for(i = 0; i < MAXLEN; i++){
pPtr = data + div*i;
for(j = 0; j < div; j++){
buffer[i] += *(pPtr + j);
}
}
return fletcher16(buffer,MAXLEN);
}
#define MAXLEN 65536
/*------------------------------------------------------------------------*/
static unsigned short longfletcher16(char *data, size_t len)
{
char buffer[MAXLEN];
int i, j, div, count;
char *pPtr;
if(len < MAXLEN){
return fletcher16(data,len);
}
/**
* sum together to run the more complex checksum on
* more juicy data
*/
div = (int)trunc((float)len/(float)MAXLEN);
for(i = 0; i < MAXLEN; i++){
pPtr = data + div*i;
for(j = 0; j < div; j++){
buffer[i] += *(pPtr + j);
}
}
return fletcher16(buffer,MAXLEN);
}
/*------------------------------------------------------------------------*/
unsigned short getHdbCheckSum(hdbValue *val)
{
char *data;
@ -740,7 +804,6 @@ void AddHipadabaChild(pHdb parent, pHdb child, void *callData)
* step to end of child chain
*/
while (current != NULL) {
assert(strcmp(current->name, child->name) != 0);
prev = current;
current = current->next;
}
@ -933,12 +996,22 @@ static int canCopy(hdbValue * source, hdbValue * target)
return 1;
}
}
if(target->dataType == HIPINTAR &&
(source->dataType == HIPINTAR || source->dataType == HIPINTVARAR)
&& target->arrayLength == source->arrayLength){
return 1;
}
if (target->dataType == HIPFLOATVARAR) {
if (source->dataType == HIPFLOATAR ||
source->dataType == HIPFLOATVARAR) {
return 1;
}
}
if(target->dataType == HIPFLOATAR &&
(source->dataType == HIPFLOATAR || source->dataType == HIPFLOATVARAR)
&& target->arrayLength == source->arrayLength){
return 1;
}
if (source->dataType != target->dataType) {
return 0;
} else {
@ -1106,6 +1179,8 @@ static int calcDataLength(pHdb node, int testLength)
/*============================= Property Functions ==========================*/
void SetHdbProperty(pHdb node, char *key, char *value)
{
hdbPropertyChange propMes;
if (node != NULL && key != NULL && node->properties != NULL) {
if (value == NULL) {
StringDictDelete(node->properties, key);
@ -1114,6 +1189,10 @@ void SetHdbProperty(pHdb node, char *key, char *value)
} else {
StringDictAddPair(node->properties, key, value);
}
propMes.type = propertyChange;
propMes.key = key;
propMes.value = value;
InvokeCallbackChain(node,(pHdbMessage)&propMes);
}
}

View File

@ -1,4 +1,4 @@
/** @file
/** @file
* Hipadaba is a hierarchical database of parameters. Parameters can be of
* various types. What happens when a parameter is being set, updated or read
* is largely determined through callbacks which can be registered on
@ -26,6 +26,8 @@
* Added support for properties, Mark Koennecke, January 2007
*
* Refactored callback handling, Markus Zolliker, Mark Koennecke, March 2008
*
* Added property chnage events. Mark Koennecke, February 2015
*/
#ifndef HIPADABA
#define HIPADABA
@ -72,11 +74,12 @@ typedef struct __hipadaba {
char *name;
char *path;
hdbValue value;
int protected;
int iprotected;
pStringDict properties;
} Hdb, *pHdb;
/*-------------- return values for callback functions -------------------------*/
typedef enum { hdbContinue,
typedef enum {
hdbContinue,
hdbAbort,
hdbKill
} hdbCallbackReturn;
@ -102,6 +105,12 @@ typedef struct {
void *result;
} hdbDataSearch, *pHdbDataSearch;
/*-------------------------------------------------------------------------------*/
typedef struct {
char *type;
char *key;
char *value;
} hdbPropertyChange, *pHdbPropertyChange;
/*-------------------------------------------------------------------------------*/
typedef hdbCallbackReturn(*hdbCallbackFunction) (pHdb currentNode,
void *userData,
pHdbMessage message);
@ -157,6 +166,14 @@ pHdbDataSearch GetHdbDataSearchMessage(pHdbMessage toTest);
* pointer if it is.
*/
pHdbMessage GetHdbKillNodeMessage(pHdbMessage toTest);
/**
* Test a message if it is a property change message
* @param toTest The message to test.
* @return NULL if the message is no property chnage message or a message
* pointer if it is.
*/
pHdbPropertyChange GetPropertyChangeMessage(pHdbMessage toTest);
/*======================== Function protoypes: hdbData ========================*/
/**
* make a hdbValue with the given datatype and length

117
histmem.c
View File

@ -18,6 +18,10 @@
Mark Koennecke, March 2009
Added an error field in the options stringdict
Mark Koennecke, June 2013
Copyright:
Labor fuer Neutronenstreuung
@ -70,6 +74,7 @@
#include "event.h"
#include "status.h"
#include "site.h"
#include "histmemsec.h"
#define ABS(x) (x < 0 ? -(x) : (x))
/*
@ -84,6 +89,27 @@ extern pHistDriver CreateRegressHM(pStringDict pOpt);
*/
extern pHistDriver MakeHMSlaveHM(pStringDict pOpt);
/*------------------------------------------------------------------------*/
int isSecondGen(pHistMem self)
{
pDummy test = (pDummy)self;
if(strcmp(test->pDescriptor->name,"HistMemSec") == 0) {
return 1;
} else {
return 0;
}
}
/*-----------------------------------------------------------------------*/
pHistMem FindHM(SicsInterp *pSics, char *name)
{
pHistMem result = NULL;
result = (pHistMem)FindCommandData(pSics,name,"HistMem");
if(result == NULL){
result = (pHistMem)FindCommandData(pSics,name,"HistMemSec");
}
return result;
}
/*------------------------------------------------------------------------*/
static int HistHalt(void *pData)
{
pHistMem self = NULL;
@ -182,12 +208,13 @@ static int HistStartCount(void *pData, SConnection * pCon)
}
/* try at least three times to do it */
StringDictUpdate(self->pDriv->pOption, "error", "None");
for (i = 0; i < 3; i++) {
iRet = self->pDriv->Start(self->pDriv, pCon);
if (iRet == OKOK) {
/* send a COUNTSTART event */
clearHMData(self->pDriv->data);
InvokeCallBack(self->pCall, COUNTSTART, pCon);
updateHMData(self->pDriv->data);
return iRet;
} else {
iRet = self->pDriv->GetError(self->pDriv, &iErr, pError, 79);
@ -199,6 +226,7 @@ static int HistStartCount(void *pData, SConnection * pCon)
eLogError);
SCSetInterrupt(pCon, eAbortBatch);
ReleaseCountLock(self->pCountInt);
StringDictUpdate(self->pDriv->pOption, "error", pError);
return HWFault;
}
}
@ -322,15 +350,16 @@ static int HistCountStatus(void *pData, SConnection * pCon)
SCSetInterrupt(pCon, eAbortBatch);
InvokeCallBack(self->pCall, COUNTEND, NULL);
ReleaseCountLock(self->pCountInt);
StringDictUpdate(self->pDriv->pOption, "error", pError);
return eCt;
} else {
updateHMData(self->pDriv->data);
return HWBusy;
}
}
if (eCt == HWBusy){
updateHMData(self->pDriv->data);
}
/* if (eCt == HWBusy){ */
/* updateHMData(self->pDriv->data); */
/* } */
if (eCt == HWIdle) {
/* force an update of local histogram data with next
@ -377,6 +406,7 @@ static int HistTransfer(void *pData, SConnection * pCon)
SCWrite(pCon, "ERROR: failed to fix histogram memory problem",
eError);
SCSetInterrupt(pCon, eAbortBatch);
StringDictUpdate(self->pDriv->pOption, "error", pError);
iStatus = HWFault;
}
}
@ -443,6 +473,7 @@ pHistMem CreateHistMemory(char *driver)
}
StringDictAddPair(pOption, "driver", driver);
StringDictAddPair(pOption, "update", "0");
StringDictAddPair(pOption, "error", "None");
/* initialise driver */
if (strcmp(driver, "sim") == 0) {
@ -715,6 +746,12 @@ long GetHistMonitor(pHistMem self, int i, SConnection * pCon)
void HistDirty(pHistMem self)
{
assert(self);
if(isSecondGen(self)){
SecHistDirty(self);
return;
}
if(self->pDriv != NULL){
updateHMData(self->pDriv->data);
}
@ -724,6 +761,11 @@ void HistDirty(pHistMem self)
const float *GetHistTimeBin(pHistMem self, int *iLength)
{
assert(self);
if(isSecondGen(self)){
return GetSecHistTimeBin(self,iLength);
}
*iLength = getNoOfTimebins(self->pDriv->data);
return getTimeBinning(self->pDriv->data);
}
@ -733,6 +775,10 @@ int GetHistLength(pHistMem self)
{
assert(self);
if(isSecondGen(self)){
return GetSecHistLength(self);
}
return getHMDataLength(self->pDriv->data);
}
@ -827,6 +873,11 @@ int GetHistogram(pHistMem self, SConnection * pCon,
{
assert(self);
if(isSecondGen(self)){
return GetSecHistogram(self,pCon,i,iStart,iEnd,lData,iDataLen);
}
if (!self->iInit) {
SCWrite(pCon, "ERROR: histogram memory not initialised", eError);
return 0;
@ -837,7 +888,7 @@ int GetHistogram(pHistMem self, SConnection * pCon,
eWarning);
iEnd = (iDataLen / sizeof(HistInt)) - 1;
}
return getHMDataHistogram(self, pCon, i, iStart, iEnd, lData);
return getHMDataHistogram(self, pCon, i, iStart, iEnd-iStart, lData);
}
/*-------------------------------------------------------------------------*/
@ -870,6 +921,7 @@ int GetHistogramDirect(pHistMem self, SConnection * pCon,
SCWrite(pCon, pBueffel, eError);
iRet = self->pDriv->TryAndFixIt(self->pDriv, iErr);
if (iRet == COTERM) {
StringDictUpdate(self->pDriv->pOption, "error", pError);
return 0;
}
}
@ -883,6 +935,11 @@ HistInt *GetHistogramPointer(pHistMem self, SConnection * pCon)
{
assert(self);
if(isSecondGen(self)){
return GetSecHistogramPointer(self,pCon);
}
if (!self->iInit) {
SCWrite(pCon, "ERROR: histogram memory not initialised", eError);
return NULL;
@ -916,6 +973,7 @@ int PresetHistogram(pHistMem self, SConnection * pCon, HistInt lVal)
SCWrite(pCon, pBueffel, eError);
iRet = self->pDriv->TryAndFixIt(self->pDriv, iErr);
if (iRet == COTERM) {
StringDictUpdate(self->pDriv->pOption, "error", pError);
return 0;
}
}
@ -1185,7 +1243,7 @@ int HistAction(SConnection * pCon, SicsInterp * pSics, void *pData,
/* do it */
Arg2Text(argc - 3, &argv[3], pBueffel, 511);
/* authorise */
if (!SCMatchRights(pCon, usUser)) { /* FIXME ffr stupid hack */
if (!SCMatchRights(pCon, usMugger)) {
snprintf(pBueffel,sizeof(pBueffel)-1,
"ERROR: you need to be manager in order to configure %s",
argv[0]);
@ -1271,11 +1329,7 @@ int HistAction(SConnection * pCon, SicsInterp * pSics, void *pData,
}
} else if (strcmp(argv[1], "init") == 0) {
if (GetStatus() != eEager) {
SCWrite(pCon, "ERROR: cannot initialize HM while running", eError);
return 0;
}
if (SCMatchRights(pCon, usUser)) { /* FIXME ffr stupid hack */
if (SCMatchRights(pCon, usMugger)) {
iRet = HistConfigure(self, pCon, pSics);
if (iRet) {
self->iInit = 1;
@ -1288,6 +1342,22 @@ int HistAction(SConnection * pCon, SicsInterp * pSics, void *pData,
} else {
return 0;
}
} else if (strcmp(argv[1], "clearhm") == 0) {
/*
clear the local copy of the HM. Assumes that the HM
clears itself on start. Which it does.
*/
if (SCMatchRights(pCon, usUser)) {
if(self->pDriv->data != NULL){
clearHMData(self->pDriv->data);
SCSendOK(pCon);
return 1;
} else {
return 0;
}
} else {
return 0;
}
} else if (strcmp(argv[1], "list") == 0) {
HMListOption(self, pCon);
return 1;
@ -1301,14 +1371,6 @@ int HistAction(SConnection * pCon, SicsInterp * pSics, void *pData,
SCSendOK(pCon);
return 1;
}
else if (strcmp(argv[1], "astop") == 0) {
if (!SCMatchRights(pCon, usUser)) {
return 0;
}
self->pDriv->Halt(self->pDriv);
SCSendOK(pCon);
return 1;
}
/* pause */
else if (strcmp(argv[1], "pause") == 0) {
if (!SCMatchRights(pCon, usUser)) {
@ -1318,6 +1380,16 @@ int HistAction(SConnection * pCon, SicsInterp * pSics, void *pData,
SCSendOK(pCon);
return 1;
}
/* state */
else if (strcmp(argv[1], "status") == 0) {
HistCountStatus(self,pCon);
if(isRunning(self->pCountInt)){
SCPrintf(pCon,eValue,"%s.status = run",argv[0]);
} else {
SCPrintf(pCon,eValue,"%s.status = idle",argv[0]);
}
return 1;
}
/* normal counting */
else if (strcmp(argv[1], "count") == 0) {
if (SCMatchRights(pCon, self->iAccess)) {
@ -1725,6 +1797,12 @@ int HistAction(SConnection * pCon, SicsInterp * pSics, void *pData,
SCSendOK(pCon);
return 1;
}
/* error */
else if (strcmp(argv[1], "error") == 0) {
StringDictGet(self->pDriv->pOption, "error", pBueffel, sizeof(pBueffel));
SCPrintf(pCon,eValue,"%s.error = %s", argv[0], pBueffel);
return 1;
}
/*-------- sum */
else if (strcmp(argv[1], "sum") == 0) {
/* read following arguments as ints and put them
@ -1759,4 +1837,5 @@ int HistAction(SConnection * pCon, SicsInterp * pSics, void *pData,
SCWrite(pCon, pBueffel, eError);
return 0;
}
return 0;
}

View File

@ -10,10 +10,17 @@
* copyright: see file COPYRIGHT
*
* Mark Koennecke, May 2009
*
* Added bridging routines implementing first gen HM interfaces
*
* Mark Koennecke, December 2012
*/
#include <sics.h>
#include <sicshipadaba.h>
#include <counter.h>
#include "HistMem.h"
#include "HistMem.i"
#include "arrayutil.h"
#define CONFIG 1005
@ -37,9 +44,11 @@ static int initArray(pCounter self, int value)
assert(datalength != NULL);
length = dim->value.v.intArray[0];
for(i = 1; i < rank->value.v.intValue; i++){
for(i = 1; i < dim->value.arrayLength; i++){
length *= dim->value.v.intArray[i];
}
/* printf("initArray called with length %d\n", length);*/
v = MakeHdbInt(length);
UpdateHipadabaPar(datalength, v, NULL);
@ -82,6 +91,45 @@ static int ResetCmd(pSICSOBJ ccmd, SConnection * pCon,
return 1;
}
/*--------------------------------------------------------------------------*/
static int NoTimeBinCmd(pSICSOBJ ccmd, SConnection * pCon,
Hdb * cmdNode, Hdb * par[], int nPar)
{
pHdb timeNode = NULL;
timeNode = GetHipadabaNode(ccmd->objectNode,"time_binning");
if(timeNode == NULL){
SCWrite(pCon,"ERROR: HM has no time binning",eError);
return 0;
}
SCPrintf(pCon,eValue,"%s.totimebin = %d", ccmd->objectNode->name,
timeNode->value.arrayLength);
return 1;
}
/*--------------------------------------------------------------------------*/
static int TimebinsCmd(pSICSOBJ ccmd, SConnection * pCon,
Hdb * cmdNode, Hdb * par[], int nPar)
{
pHdb timeNode = NULL;
pDynString data= NULL;
timeNode = GetHipadabaNode(ccmd->objectNode,"time_binning");
if(timeNode == NULL){
SCWrite(pCon,"ERROR: HM has no time binning",eError);
return 0;
}
data = formatValue(timeNode->value,timeNode);
if(data != NULL){
SCPrintf(pCon,eValue,"%s.timebins = %s", ccmd->objectNode->name,
GetCharArray(data));
DeleteDynString(data);
} else {
SCWrite(pCon,"ERROR: out of memory formatting timebins", eError);
return 0;
}
return 1;
}
/*--------------------------------------------------------------------------*/
static int GenbinCmd(pSICSOBJ ccmd, SConnection * pCon,
Hdb * cmdNode, Hdb * par[], int nPar)
{
@ -124,6 +172,113 @@ static int GenbinCmd(pSICSOBJ ccmd, SConnection * pCon,
return 1;
}
/*--------------------------------------------------------------------------*/
static int ConfigureCmd(pSICSOBJ ccmd, SConnection * pCon,
Hdb * cmdNode, Hdb * par[], int nPar)
{
pHdb dimNode = NULL;
if(nPar < 1) {
SCWrite(pCon,"ERROR: need a parameter to read", eError);
return 0;
}
dimNode = GetHipadabaNode(ccmd->objectNode,"dim");
assert(dimNode != NULL);
if(strcmp(par[0]->value.v.text,"dim0") == 0){
SCPrintf(pCon,eValue,"%s.dim0 = %d", ccmd->objectNode->name,
dimNode->value.v.intArray[0]);
} else if(strcmp(par[0]->value.v.text,"dim1") == 0){
SCPrintf(pCon,eValue,"%s.dim1 = %d", ccmd->objectNode->name,
dimNode->value.v.intArray[1]);
} else {
SCPrintf(pCon,eError,"ERROR: subcommand %s to configure not found",
par[0]->value.v.text);
return 0;
}
return 1;
}
/*--------------------------------------------------------------------------*/
static int SumCmd(pSICSOBJ ccmd, SConnection * pCon,
Hdb * cmdNode, Hdb * par[], int nPar)
{
pHdb dimNode = NULL, dataNode = NULL;
int xstart, xend, ystart, yend, i;
long lSum = 0;
dimNode = GetHipadabaNode(ccmd->objectNode,"dim");
dataNode = GetHipadabaNode(ccmd->objectNode,"data");
assert(dimNode != NULL && dataNode != NULL);
switch(dimNode->value.arrayLength){
case 1:
if(nPar < 2) {
SCWrite(pCon,"ERROR: need start and end for summing 1D data",eError);
return 0;
}
xstart = par[0]->value.v.intValue;
xend = par[1]->value.v.intValue;
if(xstart < 0){
xstart = 0;
}
if(xend > dataNode->value.arrayLength){
xend = dataNode->value.arrayLength;
}
for(i = xstart; i < xend; i++){
lSum += dataNode->value.v.intArray[i];
}
SCPrintf(pCon,eValue,"%s.sum = %ld", ccmd->objectNode->name, lSum);
break;
case 2:
if(nPar < 4) {
SCWrite(pCon,"ERROR: need start and end in x and y for summing 2D data",eError);
return 0;
}
xstart = par[0]->value.v.intValue;
xend = par[1]->value.v.intValue;
if(xstart < 0){
xstart = 0;
}
if(xend > dimNode->value.v.intArray[0]){
xend = dimNode->value.v.intArray[0];
}
ystart = par[2]->value.v.intValue;
yend = par[3]->value.v.intValue;
if(ystart < 0){
ystart = 0;
}
if(yend > dimNode->value.v.intArray[1]){
yend = dimNode->value.v.intArray[1];
}
lSum = sumWindow(dataNode->value.v.intArray, xstart,xend,dimNode->value.v.intArray[0],
ystart, yend, dimNode->value.v.intArray[1]);
SCPrintf(pCon,eValue,"%s.sum = %ld", ccmd->objectNode->name, lSum);
break;
default:
SCPrintf(pCon, eError, "ERROR: summing not supported for %d dimensional data",
dimNode->value.arrayLength);
return 0;
}
return 1;
}
/*-------------------------------------------------------------------------*/
static int TotalCmd(pSICSOBJ ccmd, SConnection * pCon,
Hdb * cmdNode, Hdb * par[], int nPar)
{
pHdb dataNode = NULL;
long lSum = 0;
int i;
dataNode = GetHipadabaNode(ccmd->objectNode,"data");
assert(dataNode != NULL);
for(i = 0, lSum = 0; i < dataNode->value.arrayLength; i++){
lSum += dataNode->value.v.intArray[i];
}
SCPrintf(pCon,eValue,"%s.total = %ld", ccmd->objectNode->name, lSum);
return 1;
}
/*--------------------------------------------------------------------------*/
static int InitCmd(pSICSOBJ ccmd, SConnection * con,
Hdb * cmdNode, Hdb * par[], int nPar)
{
@ -189,6 +344,15 @@ int MakeSecHM(SConnection * pCon, SicsInterp * pSics, void *pData,
if(pRes == NULL){
return 0;
}
/*
remove count and rename countnb to it
*/
node = GetHipadabaNode(pRes->pDes->parNode,"count");
DeleteHipadabaNode(node,NULL);
node = GetHipadabaNode(pRes->pDes->parNode,"countnb");
strcpy(node->name,"count");
pRes->pCountInt->TransferData = HMCtrTransferData;
node = pRes->objectNode;
@ -197,13 +361,13 @@ int MakeSecHM(SConnection * pCon, SicsInterp * pSics, void *pData,
DeleteHipadabaNode(child,pCon);
}
child = MakeSICSHdbPar("rank", usInternal, MakeHdbInt(rank));
child = MakeSICSHdbPar("rank", usMugger, MakeHdbInt(rank));
if (child == NULL) {
return 0;
}
AddHipadabaChild(node, child, NULL);
child = MakeSICSHdbPar("dim", usMugger, makeHdbValue(HIPINTAR,rank));
child = MakeSICSHdbPar("dim", usMugger, makeHdbValue(HIPINTVARAR,rank));
if (child == NULL) {
return 0;
}
@ -228,24 +392,36 @@ int MakeSecHM(SConnection * pCon, SicsInterp * pSics, void *pData,
child = AddSICSHdbPar(node,"init", usMugger, MakeSICSFunc(InitCmd));
child = AddSICSHdbPar(node,"sum", usSpy, MakeSICSFunc(SumCmd));
AddSICSHdbPar(child, "xstart", usSpy, MakeHdbInt(0));
AddSICSHdbPar(child, "xend", usSpy, MakeHdbInt(0));
AddSICSHdbPar(child, "ystart", usSpy, MakeHdbInt(0));
AddSICSHdbPar(child, "yend", usSpy, MakeHdbInt(0));
child = AddSICSHdbPar(node,"total", usSpy, MakeSICSFunc(TotalCmd));
/*
* test TOF option
*/
if(argc > 3){
if(strcmp(argv[3],"tof") == 0){
child = MakeSICSHdbPar("time_binning", usMugger, makeHdbValue(HIPFLOATVARAR,100));
if (child == NULL) {
return 0;
}
AddHipadabaChild(node, child, NULL);
AppendHipadabaCallback(child,
MakeHipadabaCallback(HMTOFCallback, NULL, NULL));
if(strcmp(argv[3],"tof") == 0){
child = MakeSICSHdbPar("time_binning", usMugger, makeHdbValue(HIPFLOATVARAR,100));
if (child == NULL) {
return 0;
}
AddHipadabaChild(node, child, NULL);
AppendHipadabaCallback(child,
MakeHipadabaCallback(HMTOFCallback, NULL, NULL));
child = AddSICSHdbPar(node,"genbin", usMugger, MakeSICSFunc(GenbinCmd));
AddSICSHdbPar(child, "start", usMugger, MakeHdbFloat(10.));
AddSICSHdbPar(child, "step", usMugger, MakeHdbFloat(10.));
AddSICSHdbPar(child, "np", usMugger, MakeHdbInt(10));
}
child = AddSICSHdbPar(node,"genbin", usMugger, MakeSICSFunc(GenbinCmd));
AddSICSHdbPar(child, "start", usMugger, MakeHdbFloat(10.));
AddSICSHdbPar(child, "step", usMugger, MakeHdbFloat(10.));
AddSICSHdbPar(child, "np", usMugger, MakeHdbInt(10));
child = AddSICSHdbPar(node,"notimebin", usSpy, MakeSICSFunc(NoTimeBinCmd));
child = AddSICSHdbPar(node,"timebins", usSpy, MakeSICSFunc(TimebinsCmd));
}
}
status =
@ -257,3 +433,99 @@ int MakeSecHM(SConnection * pCon, SicsInterp * pSics, void *pData,
}
return 1;
}
/*===========================================================================
This is a set of adapter functions which make the second gen HM look like
a first generation one. This saves me from rewriting all the calculation codes
based on the first gen HM
!!!! BEWARE: In the functions below pHistMem should never be a pointer to a
HistMem but rather a second generation HM which is a counter object !!!!
===============================================================================*/
const float *GetSecHistTimeBin(pHistMem self, int *iLength)
{
float *tb = NULL;
pHdb tbNode = NULL;
int i;
pCounter pCter;
assert(self->pDes->parNode != NULL);
pCter = (pCounter)self;
tbNode = GetHipadabaNode(self->pDes->parNode,"time_binning");
if(tbNode == NULL){
return NULL;
}
*iLength = tbNode->value.arrayLength;
if(*iLength != pCter->tbLength){
if(pCter->timeBinning){
free(pCter->timeBinning);
}
pCter->timeBinning = malloc(*iLength*sizeof(float));
}
for(i = 0; i < *iLength; i++){
pCter->timeBinning[i] = tbNode->value.v.floatArray[i];
}
return (const float*)pCter->timeBinning;
}
/*---------------------------------------------------------------------------*/
HistInt *GetSecHistogramPointer(pHistMem self,SConnection *pCon)
{
pHdb dataNode = NULL;
assert(self->pDes->parNode != NULL);
dataNode = GetHipadabaNode(self->pDes->parNode,"data");
if(dataNode == NULL){
return NULL;
}
return (HistInt *)dataNode->value.v.intArray;
}
/*--------------------------------------------------------------------------*/
int GetSecHistogram(pHistMem self, SConnection *pCon,
int i,int iStart, int iEnd, HistInt *lData, int iDataLen)
{
pHdb dataNode = NULL;
assert(self->pDes->parNode != NULL);
dataNode = GetHipadabaNode(self->pDes->parNode,"data");
if(dataNode == NULL){
return 0;
}
if(iEnd > dataNode->value.arrayLength){
iEnd = dataNode->value.arrayLength;
}
if ((iEnd - iStart) > iDataLen / sizeof(HistInt)) {
SCWrite(pCon, "WARNING: truncating request to fit data space",
eWarning);
iEnd = (iDataLen / sizeof(HistInt)) - 1;
}
memcpy(lData,dataNode->value.v.intArray+iStart, (iEnd-iStart)*sizeof(int));
return 1;
}
/*-------------------------------------------------------------------------*/
void SecHistDirty(pHistMem self)
{
/* Nothing to do */
}
/*-------------------------------------------------------------------------*/
int GetSecHistLength(pHistMem self)
{
pHdb dataNode = NULL;
int i, length = 1;
assert(self->pDes->parNode != NULL);
dataNode = GetHipadabaNode(self->pDes->parNode,"dim");
if(dataNode == NULL){
return 0;
}
for(i = 0; i < dataNode->value.arrayLength; i++){
length *= dataNode->value.v.intArray[i];
}
return length;
}

View File

@ -17,4 +17,12 @@
int MakeSecHM(SConnection * pCon, SicsInterp * pSics, void *pData,
int argc, char *argv[]);
const float *GetSecHistTimeBin(pHistMem self, int *iLength);
HistInt *GetSecHistogramPointer(pHistMem self,SConnection *pCon);
int GetSecHistogram(pHistMem self, SConnection *pCon,
int i,int iStart, int iEnd, HistInt *lData, int iDataLen);
void SecHistDirty(pHistMem self);
int GetSecHistLength(pHistMem self);
#endif /*HISTMEMSEC_H_*/

View File

@ -443,6 +443,9 @@ $\langle$Protos {\footnotesize ?}$\rangle\equiv$
\mbox{}\verb@ int HistBlockCount(pHistMem self, SConnection *pCon);@\\
\mbox{}\verb@ void HistDirty(pHistMem self); @\\
\mbox{}\verb@@\\
\mbox{}\verb@ int isSecondGen(pHistMem self);@\\
\mbox{}\verb@ pHistMem FindHM(SicsInterp *pSics, char *name);@\\
\mbox{}\verb@@\\
\mbox{}\verb@@$\Diamond$
\end{list}
\vspace{-1ex}

View File

@ -347,6 +347,9 @@ controlled by the following functions:
int HistBlockCount(pHistMem self, SConnection *pCon);
void HistDirty(pHistMem self);
int isSecondGen(pHistMem self);
pHistMem FindHM(SicsInterp *pSics, char *name);
@}
The first four functions are simple parameter enquiry and manipulation
functions. GetHistMonitor returns the count on monitor number i for the

View File

@ -77,6 +77,7 @@ static int SimConfig(pHistDriver self, SConnection * pCon,
self->pPriv = NewSIMCounter("HistoSim", fFail);
}
/*
configured test value
*/

49
hkl.c
View File

@ -26,6 +26,10 @@
Heavily reworked to fit into the new four circle setup
Mark Koennecke, July 2008
Added calculation of angles between reflection
Mark Koennecke, March 2013
-----------------------------------------------------------------------------*/
#include <math.h>
#include <ctype.h>
@ -687,6 +691,47 @@ static int HKLCalculateTheta(pHKL self, float fHKL[3], double *stt)
*stt = 2. * theta;
return status;
}
/*-------------------------------------------------------------------------*/
static int HKLAngle(SConnection *pCon, int argc, char *argv[])
{
reflection r1, r2;
lattice direct;
const double *cell;
MATRIX B;
double ang;
if(argc < 8){
SCWrite(pCon,"ERROR: insufficient no of arguments to hkl angle",eError);
return 0;
}
r1.h = atof(argv[2]);
r1.k = atof(argv[3]);
r1.l = atof(argv[4]);
r2.h = atof(argv[5]);
r2.k = atof(argv[6]);
r2.l = atof(argv[7]);
cell = SXGetCell();
direct.a = cell[0];
direct.b = cell[1];
direct.c = cell[2];
direct.alpha = cell[3];
direct.beta = cell[4];
direct.gamma = cell[5];
B = mat_creat(3,3,ZERO_MATRIX);
if(B == NULL){
SCWrite(pCon,"ERROR: out of memory in HKL angle",eError);
return 0;
}
calculateBMatrix(direct,B);
ang = angleBetweenReflections(B,r1,r2);
SCPrintf(pCon,eValue,"angle = %f", ang);
mat_free(B);
return 1;
}
/*--------------------------------------------------------------------------*/
static int HandleBiToNB(SConnection *pCon, int argc, char *argv[])
{
@ -993,6 +1038,10 @@ int HKLAction(SConnection * pCon, SicsInterp * pSics, void *pData,
SCPrintf(pCon, eValue, "two-theta = %lf", stt);
return 1;
}
/*--------------- calculate angle */
else if (strcmp(argv[1], "angle") == 0) {
return HKLAngle(pCon,argc,argv);
}
/*------------------ run */
else if (strcmp(argv[1], "run") == 0) {
if (!SCMatchRights(pCon, usUser)) {

View File

@ -126,6 +126,9 @@ static int HMCStatus(void *pData, SConnection * pCon)
assert(self);
if(self->checkSlaves == 0) {
/*
check master
*/
status = self->slaves[0]->CheckCountStatus(self->slaveData[0], pCon);
/*
Warning: this assumes that slaves 1 - MAXSLAVE are histogram memories.
@ -194,7 +197,7 @@ static int HMCBoaStatus(void *pData, SConnection * pCon)
HMCHalt(self);
ReleaseCountLock(self->pCount);
self->checkSlaves = 0;
for(j = 0; j < 100; j++){
for(j = 0; j < 200; j++){
SicsWait(1);
status = self->slaves[i]->CheckCountStatus(self->slaveData[i], pCon);
if(status == HWIdle || status == HWFault) {

View File

@ -58,7 +58,10 @@ void clearHMData(pHMdata self)
if (self->tofMode) {
size *= getNoOfTimebins(self);
}
memset(self->localBuffer, 0, size * sizeof(HistInt));
if(self->localBuffer != NULL){
memset(self->localBuffer, 0, size * sizeof(HistInt));
}
self->nextUpdate = time(NULL) + self->updateIntervall;
}
/*----------------------------------------------------------------------*/
@ -145,18 +148,10 @@ int configureHMdata(pHMdata self, pStringDict pOpt, SConnection * pCon)
self->localBuffer = NULL;
}
/*
note: remove update request in histmem.c
*/
if (self->updateIntervall > 0) {
/*
we do buffer
*/
status = resizeBuffer(self);
if (!status) {
SCWrite(pCon, "ERROR: failed to resize buffer", eError);
return 0;
}
status = resizeBuffer(self);
if (!status) {
SCWrite(pCon, "ERROR: failed to resize buffer", eError);
return 0;
}
return 1;
}
@ -313,7 +308,7 @@ static int updateHMbuffer(pHistMem hist, int bank, SConnection * pCon)
}
if (status == OKOK) {
return 1;
} else {
} else {
return HWFault;
}
}
@ -541,7 +536,7 @@ static pNXDS hmDataToNXDataset(pHMdata self)
if (isInTOFMode(self)) {
result->rank++;
}
result->dim = malloc(self->rank * sizeof(int));
result->dim = malloc(self->rank * sizeof(int64_t));
if (result->dim == NULL) {
free(result);
return NULL;

View File

@ -79,6 +79,7 @@ static int MakeObject(SConnection * con, SicsInterp * sics,
return 0;
}
/* missing check for user (manager?) privilege */
cmdin = (CmdInitializer) GetInitializer("Object", argv[2]);
if (cmdin) {
return cmdin(con, argc, argv, strcasecmp(argv[0], "makeobject") == 0);
@ -141,6 +142,7 @@ static int RemoveObject(SConnection * con, SicsInterp * sics,
return 0;
}
/* missing check for user (manager?) privilege */
desc = FindCommandDescriptor(sics, argv[1]);
if (!desc) {
SCPrintf(con, eError, "ERROR: %s not found", argv[1]);

View File

@ -1,4 +1,4 @@
/*--------------------------------------------------------------------------
/*--------------------------------------------------------------------------
I N T E R F A C E
@ -12,6 +12,11 @@
Paul Scherrer Institut
CH-5423 Villigen-PSI
Extended over time with utility functions
Added Drivable and Countable task functions
Mark Koennecke, February 2013
The authors hereby grant permission to use, copy, modify, distribute,
and license this software and its documentation for any purpose, provided
@ -42,6 +47,7 @@
#include "fortify.h"
#include "sics.h"
#include "motor.h"
#include <status.h>
/*=========================================================================
Empty driveable interface functions
==========================================================================*/
@ -168,7 +174,118 @@ int GetDrivablePosition(void *pObject, SConnection * pCon, float *fPos)
*fPos = value;
return 1;
}
/*--------------------------------------------------------------------------*/
typedef struct {
int id;
void *obj;
pIDrivable pDriv;
SConnection *pCon;
char *name;
}DriveTaskData;
/*-------------------------------------------------------------------------*/
static void KillDriveTaskData(void *data)
{
DriveTaskData *taskData = (DriveTaskData *)data;
if(taskData == NULL){
return;
}
if(taskData->name != NULL){
free(taskData->name);
}
if(taskData->pCon != NULL){
SCDeleteConnection(taskData->pCon);
}
free(taskData);
}
/*-------------------------------------------------------------------------*/
static void DriveTaskSignal(void *data, int iSignal, void *pSigData)
{
DriveTaskData *taskData = (DriveTaskData *)data;
int *interrupt;
assert(taskData != NULL);
if(iSignal == SICSINT){
interrupt = (int *)pSigData;
if(*interrupt != eContinue){
SCPrintf(taskData->pCon,eLogError,"ERROR: Interrupting %s", taskData->name);
taskData->pDriv->Halt(taskData->obj);
SCSetInterrupt(taskData->pCon,*interrupt);
}
}
}
/*--------------------------------------------------------------------------*/
static int DriveTaskFunc(void *data)
{
DriveTaskData *taskData = (DriveTaskData *)data;
int status;
assert(taskData != NULL);
status = taskData->pDriv->CheckStatus(taskData->obj,taskData->pCon);
if(status == HWBusy){
return 1;
}
if(status == HWFault){
taskData->pDriv->iErrorCount++;
}
if(status == HWFault || status == HWPosFault){
SetDevexecStatus(pServ->pExecutor,DEVERROR);
}
DevexecLog("STOP",taskData->name);
if(status == HWIdle || status == OKOK){
ExeInterest(pServ->pExecutor,taskData->name, "finished");
} else {
ExeInterest(pServ->pExecutor,taskData->name, "finished with problem");
}
traceSys("drive","DriveTask %s finished with state %d", taskData->name,status);
return 0;
}
/*--------------------------------------------------------------------------*/
long StartDriveTask(void *obj, SConnection *pCon, char *name, float fTarget)
{
pIDrivable pDriv = NULL;
char error[132], buffer[132];
DriveTaskData *taskData = NULL;
pDriv = GetDrivableInterface(obj);
if(pDriv == NULL){
SCPrintf(pCon,eError,"ERROR: %s is not drivable", name);
return -1;
}
if(pDriv->CheckLimits(obj,fTarget,error,sizeof(error)) != OKOK){
SCPrintf(pCon,eError,"ERROR: %s cannot reach %f, reason %s", name,
fTarget, error);
return -1;
}
taskData = calloc(1,sizeof(DriveTaskData));
if(taskData == NULL){
SCPrintf(pCon,eError,"ERROR: out of memory starting %s", name);
return -1;
}
if(pDriv->SetValue(obj,pCon,fTarget) != OKOK){
return -1;
}
ExeInterest(pServ->pExecutor,name,"started");
DevexecLog("START",name);
InvokeNewTarget(pServ->pExecutor,name,fTarget);
taskData->id = DRIVEID;
taskData->obj = obj;
taskData->pDriv = pDriv;
taskData->pCon = SCCopyConnection(pCon);
taskData->name = strdup(name);
return TaskRegisterN(pServ->pTasker,
name,
DriveTaskFunc,
DriveTaskSignal,
KillDriveTaskData,
taskData,0);
}
/*--------------------------------------------------------------------------*/
pICountable GetCountableInterface(void *pObject)
{
@ -201,6 +318,120 @@ int isRunning(pICountable self)
{
return self->running;
}
/*--------------------------------------------------------------------------*/
typedef struct {
int id;
void *obj;
pICountable pCount;
SConnection *pCon;
char *name;
}CountTaskData;
/*-------------------------------------------------------------------------*/
static void KillCountTaskData(void *data)
{
CountTaskData *taskData = (CountTaskData *)data;
if(taskData == NULL){
return;
}
if(taskData->name != NULL){
free(taskData->name);
}
if(taskData->pCon != NULL){
SCDeleteConnection(taskData->pCon);
}
free(taskData);
}
/*-------------------------------------------------------------------------*/
static void CountTaskSignal(void *data, int iSignal, void *pSigData)
{
CountTaskData *taskData = (CountTaskData *)data;
int *interrupt;
assert(taskData != NULL);
if(iSignal == SICSINT){
interrupt = (int *)pSigData;
if(*interrupt != eContinue){
SCPrintf(taskData->pCon,eLogError,"ERROR: Interrupting %s", taskData->name);
taskData->pCount->Halt(taskData->obj);
SCSetInterrupt(taskData->pCon,*interrupt);
}
} else if(iSignal == IPAUSE){
taskData->pCount->Pause(taskData->obj,taskData->pCon);
} else if(iSignal == CONTINUE){
taskData->pCount->Continue(taskData->obj,taskData->pCon);
}
}
/*--------------------------------------------------------------------------*/
static int CountTaskFunc(void *data)
{
CountTaskData *taskData = (CountTaskData *)data;
int status;
assert(taskData != NULL);
status = taskData->pCount->CheckCountStatus(taskData->obj,taskData->pCon);
if(status == HWBusy) {
return 1;
} else if(status == HWNoBeam){
return 1;
} else if(status == HWPause){
return 1;
}
taskData->pCount->TransferData(taskData->obj, taskData->pCon);
if(status == HWFault){
SetDevexecStatus(pServ->pExecutor,DEVERROR);
}
DevexecLog("STOP",taskData->name);
if(status == HWIdle || status == OKOK){
ExeInterest(pServ->pExecutor,taskData->name, "finished");
} else {
ExeInterest(pServ->pExecutor,taskData->name, "finished with problem");
}
traceSys("count","CountTask %s finished with state %d", taskData->name,status);
return 0;
}
/*--------------------------------------------------------------------------*/
long StartCountTask(void *obj, SConnection *pCon, char *name)
{
pICountable pCount = NULL;
char error[132], buffer[132];
CountTaskData *taskData = NULL;
pCount = FindInterface(obj,COUNTID);
if(pCount == NULL){
SCPrintf(pCon,eError,"ERROR: %s is not countable", name);
return 1;
}
taskData = calloc(1,sizeof(CountTaskData));
if(taskData == NULL){
SCPrintf(pCon,eError,"ERROR: out of memory starting %s", name);
return -1;
}
if(pCount->StartCount(obj,pCon) != OKOK){
pCount->running = 0;
return -1;
}
ExeInterest(pServ->pExecutor,name,"started");
DevexecLog("START",name);
taskData->id = COUNTID;
taskData->obj = obj;
taskData->pCount = pCount;
taskData->pCon = SCCopyConnection(pCon);
taskData->name = strdup(name);
return TaskRegisterN(pServ->pTasker,
name,
CountTaskFunc,
CountTaskSignal,
KillCountTaskData,
taskData,0);
}
/*--------------------------------------------------------------------------*/
pICallBack GetCallbackInterface(void *pObject)

View File

@ -1,5 +1,5 @@
#line 399 "interface.w"
#line 412 "interface.w"
/*---------------------------------------------------------------------------
I N T E R F A C E S
@ -30,108 +30,114 @@
#line 121 "interface.w"
typedef struct {
int ID;
int (*Halt) (void *self);
int (*CheckLimits) (void *self, float fVal, char *error, int iErrLen);
long (*SetValue) (void *self, SConnection * pCon, float fVal);
int (*CheckStatus) (void *self, SConnection * pCon);
float (*GetValue) (void *self, SConnection * pCon);
int iErrorCount;
int drivableStatus;
} IDrivable, *pIDrivable;
typedef struct {
int ID;
int (*Halt)(void *self);
int (*CheckLimits)(void *self, float fVal,
char *error, int iErrLen);
long (*SetValue)(void *self, SConnection *pCon,
float fVal);
int (*CheckStatus)(void *self, SConnection *pCon);
float (*GetValue)(void *self, SConnection *pCon);
int iErrorCount;
int drivableStatus;
} IDrivable, *pIDrivable;
pIDrivable GetDrivableInterface(void *pObject);
int GetDrivablePosition(void *pObject, SConnection * pCon, float *fPos);
pIDrivable GetDrivableInterface(void *pObject);
int GetDrivablePosition(void *pObject, SConnection *pCon,
float *fPos);
long StartDriveTask(void *self, SConnection *pCon, char *name, float fTarget);
#line 425 "interface.w"
pIDrivable CreateDrivableInterface(void);
/* ------------------------ The countable interface ---------------------*/
#line 188 "interface.w"
typedef struct {
int ID;
int running;
int (*Halt) (void *self);
void (*SetCountParameters) (void *self, float fPreset,
CounterMode eMode);
int (*StartCount) (void *self, SConnection * pCon);
int (*CheckCountStatus) (void *self, SConnection * pCon);
int (*Pause) (void *self, SConnection * pCon);
int (*Continue) (void *self, SConnection * pCon);
int (*TransferData) (void *self, SConnection * pCon);
} ICountable, *pICountable;
pICountable GetCountableInterface(void *pObject);
int GetCountLock(pICountable self, SConnection * pCon);
void ReleaseCountLock(pICountable self);
int isRunning(pICountable self);
#line 430 "interface.w"
pICountable CreateCountableInterface(void);
/* ------------------------- The CallBack Interface --------------------*/
#line 253 "interface.w"
typedef void (*KillFuncIT) (void *pData);
typedef int (*SICSCallBack) (int iEvent, void *pEventData,
void *pUserData);
#line 435 "interface.w"
#line 275 "interface.w"
typedef struct __ICallBack *pICallBack;
/* event source side */
pICallBack CreateCallBackInterface(void);
void DeleteCallBackInterface(pICallBack self);
int InvokeCallBack(pICallBack pInterface, int iEvent, void *pEventData);
/* callback client side */
long RegisterCallback(pICallBack pInterface,
int iEvent, SICSCallBack pFunc,
void *pUserData, KillFuncIT pKill);
int RemoveCallback(pICallBack pInterface, long iID);
int RemoveCallback2(pICallBack pInterface, void *pUserData);
int RemoveCallbackUsr(pICallBack self, SICSCallBack pFunc, int (*userfunc)(const void* pContext, const void* pUserData), void *pCtx);
int RemoveCallbackCon(pICallBack pInterface, SConnection * pCon);
int CallbackScript(SConnection * pCon, SicsInterp * pSics, void *pData,
int argc, char *argv[]);
pICallBack GetCallbackInterface(void *pData);
#line 436 "interface.w"
/*---------------------- The Environment Interface --------------------*/
#line 353 "interface.w"
typedef enum { EVIdle, EVDrive, EVMonitor, EVError } EVMode;
typedef struct {
int iID;
EVMode(*GetMode) (void *self);
int (*IsInTolerance) (void *self);
int (*HandleError) (void *self);
} EVInterface, *pEVInterface;
#line 438 "interface.w"
#line 379 "interface.w"
pIDrivable CreateDrivableInterface(void);
pEVInterface CreateEVInterface(void);
/* ------------------------ The countable interface ---------------------*/
#line 439 "interface.w"
#line 195 "interface.w"
typedef struct {
int ID;
int running;
int (*Halt)(void *self);
void (*SetCountParameters)(void *self, float fPreset,
CounterMode eMode);\
int (*StartCount)(void *self, SConnection *pCon);
int (*CheckCountStatus)(void *self, SConnection *pCon);
int (*Pause)(void *self, SConnection *pCon);
int (*Continue)(void *self, SConnection *pCon);
int (*TransferData)(void *self, SConnection *pCon);
} ICountable, *pICountable;
pICountable GetCountableInterface(void *pObject);
int GetCountLock(pICountable self, SConnection *pCon);
void ReleaseCountLock(pICountable self);
int isRunning(pICountable self);
long StartCountTask(void *self, SConnection *pCon, char *name);
#line 443 "interface.w"
pICountable CreateCountableInterface(void);
/* ------------------------- The CallBack Interface --------------------*/
#line 266 "interface.w"
typedef void (*KillFuncIT)(void *pData);
typedef int (*SICSCallBack)(int iEvent, void *pEventData,
void *pUserData);
#line 448 "interface.w"
#line 288 "interface.w"
typedef struct __ICallBack *pICallBack;
/* event source side */
pICallBack CreateCallBackInterface(void);
void DeleteCallBackInterface(pICallBack self);
int InvokeCallBack(pICallBack pInterface, int iEvent, void *pEventData);
/* callback client side */
long RegisterCallback(pICallBack pInterface,
int iEvent, SICSCallBack pFunc,
void *pUserData, KillFuncIT pKill);
int RemoveCallback(pICallBack pInterface, long iID);
int RemoveCallback2(pICallBack pInterface, void *pUserData);
int RemoveCallbackUsr(pICallBack self, SICSCallBack pFunc, int (*userfunc)(const void* pContext, const void* pUserData), void *pCtx);
int RemoveCallbackCon(pICallBack pInterface, SConnection *pCon);
int CallbackScript(SConnection *pCon, SicsInterp *pSics, void *pData,
int argc, char *argv[]);
pICallBack GetCallbackInterface(void *pData);
#line 449 "interface.w"
/*---------------------- The Environment Interface --------------------*/
#line 366 "interface.w"
typedef enum { EVIdle, EVDrive, EVMonitor, EVError } EVMode;
typedef struct {
int iID;
EVMode (*GetMode)(void *self);
int (*IsInTolerance)(void *self);
int (*HandleError)(void *self);
} EVInterface, *pEVInterface;
#line 451 "interface.w"
#line 392 "interface.w"
pEVInterface CreateEVInterface(void);
#line 452 "interface.w"
#endif

View File

@ -154,6 +154,8 @@ $\langle$driv {\footnotesize ?}$\rangle\equiv$
\mbox{}\verb@ int GetDrivablePosition(void *pObject, SConnection *pCon,@\\
\mbox{}\verb@ float *fPos);@\\
\mbox{}\verb@@\\
\mbox{}\verb@ long StartDriveTask(void *self, SConnection *pCon, char *name, float fTarget);@\\
\mbox{}\verb@@\\
\mbox{}\verb@@$\Diamond$
\end{list}
\vspace{-1ex}
@ -206,6 +208,11 @@ will be returned.
object. If the device is a motor corrections for zero points and signs
will be applied. Returns 1 on success and 0 on failure}
{\bf StartDriveTask starts a drivable in a new task. If the task can be started, its
task ID is returned. -1 is returned on failure.
}
\subsubsection{The Countable Interface}
This is an interface for interacting with anything which counts.
@ -233,6 +240,7 @@ $\langle$count {\footnotesize ?}$\rangle\equiv$
\mbox{}\verb@ int GetCountLock(pICountable self, SConnection *pCon);@\\
\mbox{}\verb@ void ReleaseCountLock(pICountable self);@\\
\mbox{}\verb@ int isRunning(pICountable self);@\\
\mbox{}\verb@ long StartCountTask(void *self, SConnection *pCon, char *name);@\\
\mbox{}\verb@@$\Diamond$
\end{list}
\vspace{-1ex}
@ -273,6 +281,11 @@ will be returned.
{\bf ReleaseCountLock} release the count lock.
{\bf isRunning} returns the running flag.
{\bf StartCountTask starts a countable in a new task. If the task can be started, its
task ID is returned. -1 is returned on failure.
}
\subsubsection{The Callback Interface}
The Callback Interface is SICS suport for component behaviour for objects.

View File

@ -137,6 +137,8 @@ environment controllers fit this bill as well.
int GetDrivablePosition(void *pObject, SConnection *pCon,
float *fPos);
long StartDriveTask(void *self, SConnection *pCon, char *name, float fTarget);
@}
The first member of this structure is an ID which can be used in order to
check if the right datastructure has been obtained.
@ -181,6 +183,11 @@ will be returned.
object. If the device is a motor corrections for zero points and signs
will be applied. Returns 1 on success and 0 on failure}
{\bf StartDriveTask starts a drivable in a new task. If the task can be started, its
task ID is returned. -1 is returned on failure.
}
\subsubsection{The Countable Interface}
This is an interface for interacting with anything which counts.
@ -203,6 +210,7 @@ This is an interface for interacting with anything which counts.
int GetCountLock(pICountable self, SConnection *pCon);
void ReleaseCountLock(pICountable self);
int isRunning(pICountable self);
long StartCountTask(void *self, SConnection *pCon, char *name);
@}
{\bf running } Is a flag which says if the counter is operating or not.
@ -236,6 +244,11 @@ will be returned.
{\bf ReleaseCountLock} release the count lock.
{\bf isRunning} returns the running flag.
{\bf StartCountTask starts a countable in a new task. If the task can be started, its
task ID is returned. -1 is returned on failure.
}
\subsubsection{The Callback Interface}
The Callback Interface is SICS suport for component behaviour for objects.

View File

@ -8,6 +8,10 @@
Mark Koennecke, November 1996
Revised: Mark Koennecke, September 1997
Removed unused UDP interrupt port stuff
Mark Koennecke, February 2013
Copyright: see copyright.h
@ -22,10 +26,7 @@
#include <strlutil.h>
#include "fortify.h"
#include "conman.h"
#include "SCinter.h"
#include "nserver.h"
#include "obdes.h"
#include "sics.h"
#include "network.h"
#include "interrupt.h"
#include "status.h"
@ -40,8 +41,6 @@
#define MAXINTERRUPT 7
#define INTERUPTWAIT 5
static mkChannel *IntPort = NULL;
static pTaskMan pTask = NULL;
/*----------------------------------------------------------------------------*/
static char *pIntText[] = {
"continue",
@ -53,35 +52,6 @@ static char *pIntText[] = {
"end",
NULL
};
/*---------------------------------------------------------------------------*/
int ServerSetupInterrupt(int iPort, pNetRead pNet, pTaskMan pTasker)
{
int i;
pTask = pTasker;
/* setup interrupt port */
IntPort = UDPOpen(iPort);
if (IntPort == NULL) {
return 0;
} else {
NetReadRegister(pNet, IntPort, udp, NULL);
return 1;
}
}
/*--------------------------------------------------------------------------*/
void ServerStopInterrupt(void)
{
/* close the port */
if (IntPort) {
NETClosePort(IntPort);
free(IntPort);
}
}
/*-------------------------------------------------------------------------*/
void SetInterrupt(int iCode)
{
@ -89,7 +59,7 @@ void SetInterrupt(int iCode)
iInt = iCode;
TaskSignal(pTask, SICSINT, &iInt);
TaskSignal(pServ->pTasker, SICSINT, &iInt);
}
/*--------------------------------------------------------------------------*/

View File

@ -10,4 +10,4 @@
MFLAGS=-f makefile_linux$(DUMMY)
HDFROOT=/usr/local
TCLINC=/usr/include/tcl8.3
TCLINC=/usr/include/tcl

25
macro.c
View File

@ -172,21 +172,6 @@ static int SicsUnknownProc(ClientData pData, Tcl_Interp * pInter,
return TCL_ERROR;
}
/* check for endless loop */
Arg2Text(margc, myarg, comBuffer, 131);
if (lastCommand != NULL) {
if (strcmp(lastCommand, comBuffer) == 0) {
Tcl_AppendResult(pInter, "ERROR: Never ending loop in unknown\n",
"Offending command: ", comBuffer,
" Probably Tcl command not found", NULL);
SCSetInterrupt(pCon, eAbortBatch);
return TCL_ERROR;
}
}
if (pSics->lastUnknown[pSics->iStack])
free(pSics->lastUnknown[pSics->iStack]);
pSics->lastUnknown[pSics->iStack] = strdup(comBuffer);
/* invoke */
pCon->sicsError = 0;
iMacro = SCinMacro(pCon);
@ -491,8 +476,6 @@ int MacroFileEval(SConnection * pCon, SicsInterp * pInter, void *pData,
}
/* handle status first */
eOld = GetStatus();
SetStatus(eBatch);
SICSLogWrite("Evaluating in MacroFileEval", eValue);
SICSLogWrite(argv[1], eValue);
@ -518,7 +501,6 @@ int MacroFileEval(SConnection * pCon, SicsInterp * pInter, void *pData,
Tcl_DStringAppend(&command, pBueffel, -1);
pCom = Tcl_DStringValue(&command);
if (Tcl_CommandComplete(pCom)) {
SetStatus(eEager);
FirstWord(pCom, pBueffel);
if (FindCommand(pInter, pBueffel) != NULL) {
snprintf(pBueffel,sizeof(pBueffel)-1, "%s:%d>> %s", argv[1], iLine, pCom);
@ -529,7 +511,6 @@ int MacroFileEval(SConnection * pCon, SicsInterp * pInter, void *pData,
pWhere = strdup(pBueffel);
}
iRet = Tcl_Eval(pTcl, pCom);
SetStatus(eBatch);
if (iRet != TCL_OK) {
/* write TCL error and check for total interrupt */
if (Tcl_GetVar(pTcl, SICSERROR, TCL_GLOBAL_ONLY) == NULL) { /* Tcl error */
@ -554,7 +535,6 @@ int MacroFileEval(SConnection * pCon, SicsInterp * pInter, void *pData,
fclose(fp);
Tcl_DStringFree(&command);
SCWrite(pCon, "ERROR: batch processing interrupted", eError);
SetStatus(eEager);
return 0;
} else {
SCSetInterrupt(pCon, eContinue);
@ -572,7 +552,6 @@ int MacroFileEval(SConnection * pCon, SicsInterp * pInter, void *pData,
/* clean up */
fclose(fp);
Tcl_DStringFree(&command);
SetStatus(eOld);
SCSendOK(pCon);
return 1;
}
@ -763,7 +742,7 @@ int ClientLog(SConnection * pCon, SicsInterp * pInter, void *pData,
memset(pMessage, 0, (iLen + 100) * sizeof(char));
Arg2Text(argc - 1, &argv[1], pMessage, (iLen + 100) * sizeof(char));
SCLogWrite(pCon,pMessage, eError);
SCLogWrite(pCon,pMessage, eLog);
free(pMessage);
return 1;
}
@ -1012,7 +991,7 @@ static int TclAction(SConnection * pCon, SicsInterp * pSics, void *pData,
Tcl_UnsetVar(pTcl, SICSERROR, TCL_GLOBAL_ONLY);
}
if (strlen(pTcl->result) > 0) {
SCPrintf(pCon, eError, "ERROR: Tcl reported %s in %s", pTcl->result,
SCPrintf(pCon, eError, "ERROR: Tcl reported %s in %s", pTcl->result,
pCommand);
}
if (pCommand != pBueffel)

View File

@ -5,15 +5,18 @@
# Markus Zolliker March 2003
#---------------------------------------------------------------------------
EPICSOBJ=epicsmotor.o
#EPICSOBJ=
COBJ = Sclient.o network.o ifile.o intcli.o $(FORTIFYOBJ)
SOBJ = network.o ifile.o conman.o SCinter.o splitter.o passwd.o \
servlog.o sicvar.o nserver.o SICSmain.o motorlist.o\
sicsexit.o costa.o task.o $(FORTIFYOBJ) testprot.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 \
lld_blob.o strrepl.o lin2ang.o fomerge.o napi5.o napi4.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 \
lld_blob.o strrepl.o lin2ang.o fomerge.o \
script.o o2t.o alias.o stringdict.o sdynar.o \
histmem.o histdriv.o histsim.o interface.o callback.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\
scan.o fitcenter.o telnet.o token.o wwildcard.o hklmot.o\
@ -23,7 +26,7 @@ SOBJ = network.o ifile.o conman.o SCinter.o splitter.o passwd.o \
simchop.o choco.o chadapter.o trim.o scaldate.o tasub.o\
xytable.o exebuf.o exeman.o ubfour.o ubcalc.o\
circular.o maximize.o sicscron.o scanvar.o tasublib.o\
d_sign.o d_mod.o tcldrivable.o stdscan.o diffscan.o nxxml.o\
d_sign.o d_mod.o tcldrivable.o stdscan.o diffscan.o \
synchronize.o definealias.o oscillate.o tasdrive.o \
hmcontrol.o userscan.o rs232controller.o lomax.o tasscanub.o \
fourlib.o motreg.o motreglist.o anticollider.o nxdataset.o \
@ -36,19 +39,20 @@ SOBJ = network.o ifile.o conman.o SCinter.o splitter.o passwd.o \
moregress.o multicounter.o regresscter.o histregress.o \
sicshdbadapter.o polldriv.o sicspoll.o statemon.o hmslave.o \
nwatch.o asyncqueue.o asyncprotocol.o sicsobj.o frame.o syncedprot.o\
nxcopy.o nxinterhelper.o nxinter_wrap.o nxstack.o arrayutil.o \
nxcopy.o nxinterhelper.o nxinter_wrap.o arrayutil.o \
sctdriveadapter.o sctdriveobj.o reflist.o singlex.o fourmess.o \
sgclib.o sgfind.o sgio.o sgsi.o sghkl.o singlediff.o singlebi.o \
singlenb.o simindex.o simidx.o uselect.o singletas.o motorsec.o \
rwpuffer.o asynnet.o background.o countersec.o hdbtable.o velosec.o \
histmemsec.o sansbc.o sicsutil.o strlutil.o genbinprot.o trace.o\
singlebinb.o
singlebinb.o taskobj.o sctcomtask.o tasmono.o multicountersec.o \
messagepipe.o sicsget.o remoteobject.o
MOTOROBJ = motor.o simdriv.o
COUNTEROBJ = countdriv.o simcter.o counter.o
VELOOBJ = velo.o velosim.o
OBJ = $(SOBJ) $(MOTOROBJ) $(COUNTEROBJ) $(VELOOBJ) $(DIFIL) $(EXTRA)
OBJ = $(SOBJ) $(MOTOROBJ) $(COUNTEROBJ) $(VELOOBJ) $(DIFIL) $(EXTRA) $(EPICSOBJ)
.SUFFIXES:
.SUFFIXES: .tcl .htm .c .o .tc
@ -59,43 +63,37 @@ OBJ = $(SOBJ) $(MOTOROBJ) $(COUNTEROBJ) $(VELOOBJ) $(DIFIL) $(EXTRA)
#--- This .SECONDARY. target is necessary to preserve generated .c files for debugging
.SECONDARY.: sicspoll.c polldriv.c
all: libmat libhlib libtecsl libpsi SICServer
all: libmat libhlib libpsi SICServer
# use this target when some of the libraries SUBLIBS might be incomplete
full: purge all
SICServer: $(OBJ) $(SUBLIBS)
$(CC) -g -o SICServer $(OBJ) $(LIBS)
g++ $(DBG) -o SICServer $(OBJ) $(LIBS)
matrix/libmatrix.a: libmat
libmat:
cd matrix; make $(MFLAGS) libmatrix.a
psi/hardsup/libhlib.a: libhlib
$(SICSROOT)/sicspsi/hardsup/libhlib.a: libhlib
libhlib:
cd psi/hardsup; make $(MFLAGS) libhlib.a
cd $(SICSROOT)/sicspsi/hardsup; make $(MFLAGS) libhlib.a
psi/tecs/libtecsl.a: libtecsl
libtecsl:
cd psi/tecs; make $(MFLAGS) libtecsl.a
psi/libpsi.a: libpsi
$(SICSROOT)/sicspsi/libpsi.a: libpsi
libpsi:
cd psi; make $(MFLAGS) libpsi.a
cd $(SICSROOT)/sicspsi; make $(MFLAGS) libpsi.a
purge:
rm -f SICServer $(SUBLIBS)
clean:
rm -f *.o *.d SICServer
cd psi/hardsup; make $(MFLAGS) clean
cd $(SICSROOT)/sicspsi/hardsup; make $(MFLAGS) clean
cd matrix; make $(MFLAGS) clean
cd psi/tecs; make $(MFLAGS) clean
cd psi; make $(MFLAGS) clean
cd $(SICSROOT)/sicspsi; make $(MFLAGS) clean
Dbg.o: Dbg.c
cc -g -I/data/koenneck/include -c Dbg.c

View File

@ -1,22 +1,4 @@
# M. Zolliker 03.2005
# when SICS_MAKE_VERSION is defined: use this makefile version
# if not: show usage (see makefile_)
%: usage
@echo
%.o: usage
@echo
default: usage
usage:
@ echo ""
@ echo "Usage:"
@ echo ""
@ echo " make -f makefile_xxx [target]"
@ echo ""
@ echo ' where makefile_xxx is one of'
@ echo ""
@ ls -1 makefile_* | pr -t -o 4
# DO NOT DELETE
include makefile_$(SICS_MAKE_VERSION)

25
makefile_ Normal file
View File

@ -0,0 +1,25 @@
# M. Zolliker 03.2005
# this file shows the correct usage of make in the sics source directory
%: usage
@echo
%.o: usage
@echo
default: usage
usage:
@ echo ""
@ echo "Usage:"
@ echo ""
@ echo " make -f makefile_xxx [target]"
@ echo ""
@ echo ' where makefile_xxx is one of'
@ echo ""
@ ls -1 makefile_?* | pr -t -o 4
@ echo ""
@ echo " or use make without args:"
@ echo ""
@ echo " setenv SICS_MAKE_VERSION slinux"
@ echo " make [target]"

View File

@ -19,8 +19,7 @@ CFLAGS = -I$(HDFROOT)/include $(DFORTIFY) -DHDF4 -DHDF5 \
-g -std1 -warnprotos
BINTARGET = bin
EXTRA=
SUBLIBS = psi/libpsi.a psi/hardsup/libhlib.a matrix/libmatrix.a \
psi/tecs/libtecsl.a
SUBLIBS = psi/libpsi.a psi/hardsup/libhlib.a matrix/libmatrix.a
LIBS = -L$(HDFROOT)/lib $(SUBLIBS) \
-ltcl -lfor $(HDFROOT)/lib/libhdf5.a \
$(HDFROOT)/lib/libmfhdf.a $(HDFROOT)/lib/libdf.a \

View File

@ -22,10 +22,9 @@ CFLAGS = -I$(HDFROOT)/include -I/usr/include/hdf -I$(TCLINC) -DHDF4 -DHDF5 \
BINTARGET = bin
EXTRA=nintf.o
SUBLIBS = psi/libpsi.a psi/hardsup/libhlib.a matrix/libmatrix.a \
psi/tecs/libtecsl.a
SUBLIBS = psi/libpsi.a psi/hardsup/libhlib.a matrix/libmatrix.a
LIBS = -L$(HDFROOT)/lib $(SUBLIBS) $(NILIB)\
-ltcl8.3 -lhdf5 -lmfhdf -ldf \
-ltcl -lNeXus -lhdf5 -lmfhdf -ldf \
-lmxml -lghttp -ljpeg -ljson -ldl -lz -lm -lc
include make_gen

View File

@ -22,8 +22,7 @@ CFLAGS = -I$(HDFROOT)/include -I/sw/include -DNXXML -DHDF5 -DHDF4 $(NI) -DMACOSX
BINTARGET = bin
EXTRA=nintf.o
SUBLIBS = psi/libpsi.a psi/hardsup/libhlib.a matrix/libmatrix.a \
psi/tecs/libtecsl.a
SUBLIBS = psi/libpsi.a psi/hardsup/libhlib.a matrix/libmatrix.a
LIBS = -L$(HDFROOT)/lib -L/sw/lib $(SUBLIBS) $(NILIB)\
-ltcl $(HDFROOT)/lib/libhdf5.a -lmfhdf -ldf \
$(HDFROOT)/lib/libsz.a \

View File

@ -4,6 +4,7 @@
#
# Mark Koennecke 1996-2001
# Markus Zolliker, March 2003
# Mark Koennecke, February 2014
#==========================================================================
# assign if the National Instrument GPIB driver is available
SINQDIR=/afs/psi.ch/project/sinq
@ -11,20 +12,25 @@ NI= -DHAVENI
NIOBJ= nigpib.o
NILIB=$(SINQDIR)/sl6/lib/cib.o
EPICSDIR=$(SINQDIR)/sl6/lib/linux-x86
EPICSLIBS=$(EPICSDIR)/libezca.a $(EPICSDIR)/libca.a $(EPICSDIR)/libCom.a -lreadline -lhistory
#EPICSLIBS=-L$(EPICSDIR) -lezca -lca -lCom
include sllinux_def
CC = gcc
CFLAGS = -I$(HDFROOT)/include -DNXXML -DHDF5 $(NI) \
-Ipsi/hardsup -I. -MMD \
-Werror -DCYGNUS -DNONINTF -g $(DFORTIFY) \
-I$(SICSROOT)/sicspsi/hardsup -I$(SICSROOT) -I. -MMD \
-Werror -DCYGNUS -DNONINTF $(DBG) $(DFORTIFY) \
-Wall -Wno-unused -Wunused-value -Wno-comment -Wno-switch
BINTARGET = bin
EXTRA=nintf.o
SUBLIBS = psi/libpsi.a psi/hardsup/libhlib.a matrix/libmatrix.a \
psi/tecs/libtecsl.a
LIBS = -L$(HDFROOT)/lib $(SUBLIBS) $(NILIB)\
-ltcl $(HDFROOT)/lib/libhdf5.a \
SUBLIBS = $(SICSROOT)/sicspsi/libpsi.a $(SICSROOT)/sicspsi/hardsup/libhlib.a \
matrix/libmatrix.a
LIBS = -L$(HDFROOT)/lib $(SUBLIBS) $(NILIB) $(EPICSLIBS) \
-ltcl -lNeXus $(HDFROOT)/lib/libhdf5.a \
$(HDFROOT)/lib/libsz.a \
$(HDFROOT)/lib/libjson.a \
-ldl -lz $(HDFROOT)/lib/libmxml.a $(HDFROOT)/lib/libghttp.a -lm -lc -lpthread
@ -33,9 +39,3 @@ include make_gen
-include $(OBJ:.o=.d)

118
messagepipe.c Normal file
View File

@ -0,0 +1,118 @@
/**
* An implementation for a message pipe system as described in
*
* http://eventuallyconsistent.net/2013/08/14/messaging-as-a-programming-model-part-2/
*
* A message is passed through a series of filter routines which do things.
*
* Rather then loops I try using recursion here.
*
* copyright: GPL Copyleft
*
* Mark Koennecke, November 2013
*/
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#include <messagepipe.h>
/*--------------------------------------------------------------------------------*/
typedef struct __MessagePipe {
void *userData;
mpUserKill killFunc;
mpFilterFunc filterFunc;
struct __MessagePipe *next;
struct __MessagePipe *previous;
} MessagePipe;
/*--------------------------------------------------------------------------------*/
static int EmptyFunc(void *message, void *userData)
{
return MPCONTINUE;
}
/*---------------------------------------------------------------------------------*/
pMP MakeMP()
{
pMP result = NULL;
result = malloc(sizeof(MessagePipe));
if(result != NULL){
memset(result,0,sizeof(MessagePipe));
result->filterFunc = EmptyFunc;
}
return result;
}
/*---------------------------------------------------------------------------------*/
void KillMP(pMP self)
{
if(self == NULL){
return;
}
pMP next = self->next;
if(self->userData != NULL && self->killFunc != NULL){
self->killFunc(self->userData);
}
free(self);
KillMP(next);
}
/*-----------------------------------------------------------------------------------*/
int AppendMPFilter(pMP self, mpFilterFunc func, void *userData, mpUserKill usKill)
{
assert(self != NULL);
assert(func != NULL);
if(self->next == NULL){
self->next = malloc(sizeof(MessagePipe));
if(self->next != NULL){
self->next->previous = self;
self->next->next = NULL;
self->next->userData = userData;
self->next->killFunc = usKill;
self->next->filterFunc = func;
return 0;
} else {
return 1;
}
} else {
return AppendMPFilter(self->next, func, userData, usKill);
}
}
/*-----------------------------------------------------------------------------------*/
pMP PrependMPFilter(pMP self, mpFilterFunc func, void *userData, mpUserKill usKill)
{
pMP result = NULL;
assert(func != NULL);
result = malloc(sizeof(MessagePipe));
if(result != NULL){
result->userData = userData;
result->killFunc = usKill;
result->filterFunc = func;
result->next = self;
result->previous = NULL;
return result;
} else {
/*
we are ignoring an error here.........
*/
return self;
}
}
/*-----------------------------------------------------------------------------------*/
int MPprocess(pMP self, void *message)
{
int status;
if(self == NULL || self->filterFunc == NULL){
return MPCONTINUE;
} else {
status = self->filterFunc(message, self->userData);
if(status == MPSTOP){
return status;
} else {
return MPprocess(self->next, message);
}
}
}

82
messagepipe.h Normal file
View File

@ -0,0 +1,82 @@
/**
* An implementation for a message pipe system as described in
*
* http://eventuallyconsistent.net/2013/08/14/messaging-as-a-programming-model-part-2/
*
* A message is passed through a series of filter routines which do things.
*
* copyright: GPL Copyleft
*
* Mark Koennecke, November 2013
*/
#ifndef __MESSAGEPIPE
#define __MESSAGEPIPE
#define MPCONTINUE 1
#define MPSTOP 0
/**
* The messagePipe data structure defined in messagepipe.c
*/
typedef struct __MessagePipe *pMP;
/**
* Protoype of the message filter function.
* @param message The message to process
* @param Optional private data for this message filter function
* @return MPSTOP for stopping further processing of the filter pipe
* or MPCONTINUE to continue processing
*/
typedef int (*mpFilterFunc)(void *message, void *userData);
/**
* A function to free the userData when it is used
* @param userData The data structure passed in for userData to a filter function.
*/
typedef void (*mpUserKill)(void *userData);
/**
* Create an empty message pipe
* @return A message pipe structure or NULL when out of memory
*/
pMP MakeMP();
/**
* Delete a message pipe
* @param self The message pipe to delete
*/
void KillMP(pMP self);
/**
* Append a filter function to the list of message filters to process
* @param self The message queue to append too
* @param func The filter function to append
* @param Optional userData to pass through to the filter function
* @param usKill An optional function to free the userData when the message pipe gets deleted
* @return 0 on success, 1 when out of memory
*/
int AppendMPFilter(pMP self, mpFilterFunc func, void *userData, mpUserKill usKill);
/**
* Preppend a filter function to the list of message filters to process
* @param self The message queue to append too
* @param func The filter function to append
* @param Optional userData to pass through to the filter function
* @param usKill An optional function to free the userData when the message pipe gets deleted
* @return An updated pointer to the message pipe.
*/
pMP PrependMPFilter(pMP self, mpFilterFunc func, void *userData, mpUserKill usKill);
/**
* Process the message pipe with the given message
* @param self The messae pipe to process
* @param message The message to process.
* @return MPCONTINUE on successfull completion, MPABORT when the chain was
* aborted for some reason.
*/
int MPprocess(pMP self, void *message);
#endif

View File

@ -74,10 +74,10 @@ static int RGRunTo(void *data, float newValue)
RGMotorDriver *self = NULL;
self = (RGMotorDriver *) data;
self->target = newValue;
if (self->errorType == STARTFAIL) {
return HWFault;
}
self->target = newValue;
return OKOK;
}

66
motor.c
View File

@ -82,7 +82,13 @@
#define MOVECOUNT 11
extern double DoubleTime(void);
static void SetMotorError(pMotor self, char *text)
{
if(self->error != NULL){
free(self->error);
}
self->error = strdup(text);
}
/*-------------------------------------------------------------------------*/
static void *MotorGetInterface(void *pData, int iID)
{
@ -383,17 +389,18 @@ static int reportAndFixError(pMotor self, SConnection * pCon)
switch (iRet) {
case MOTFAIL:
snprintf(pBueffel, 255, "ERROR: %s on %s", pError, self->name);
SCWrite(pCon, pBueffel, eError);
SCWrite(pCon, pBueffel, eLogError);
newStatus = HWFault;
SetMotorError(self,pError);
break;
case MOTREDO:
snprintf(pBueffel, 255, "WARNING: %s on %s", pError, self->name);
SCWrite(pCon, pBueffel, eWarning);
SCWrite(pCon, pBueffel, eLog);
newStatus = statusRunTo(self, pCon);
break;
case MOTOK:
snprintf(pBueffel, 255, "WARNING: %s on %s", pError, self->name);
SCWrite(pCon, pBueffel, eWarning);
SCWrite(pCon, pBueffel, eLog);
newStatus = HWIdle;
break;
default:
@ -541,7 +548,7 @@ static int MotorGetParImpl(pMotor self, char *name, float *fVal)
*fVal = self->pDriver->fLower;
return 1;
}
pPar = ObParFind(self->ParArray, name);
if (pPar) {
*fVal = pPar->fVal;
@ -689,8 +696,8 @@ static int MotorGetHardPositionImpl(pMotor self, SConnection * pCon,
/*---------------------------------------------------------------------------*/
static long MotorRunImpl(void *sulf, SConnection * pCon, float fNew)
{
float fHard, fCurrHard, fNewHard, fZero;
int i, iRet, iCode, iSign;
float fHard;
int i, iRet, iCode;
char pBueffel[512];
char pError[132];
pMotor self;
@ -709,13 +716,7 @@ static long MotorRunImpl(void *sulf, SConnection * pCon, float fNew)
SCSetInterrupt(pCon, eAbortBatch);
return 0;
}
self->pDriver->GetPosition(self->pDriver, &fCurrHard);
iSign = ObVal(self->ParArray, SIGN);
fZero = ObVal(self->ParArray, SZERO);
fNewHard = iSign * (fNew + fZero);
if (absf(fCurrHard - fNewHard) <= ObVal(self->ParArray, PREC)) {
return OKOK;
}
SetMotorError(self,"None");
/* check boundaries first */
iRet = MotorCheckBoundaryImpl(self, fNew, &fHard, pError, 131);
@ -723,6 +724,7 @@ static long MotorRunImpl(void *sulf, SConnection * pCon, float fNew)
snprintf(pBueffel, 511, "ERROR: %s", pError);
SCWrite(pCon, pBueffel, eError);
SCSetInterrupt(pCon, eAbortOperation);
SetMotorError(self,pError);
return 0;
}
@ -745,6 +747,7 @@ static long MotorRunImpl(void *sulf, SConnection * pCon, float fNew)
ServerWriteGlobal(pBueffel, eError);
SCSetInterrupt(pCon, eAbortBatch);
self->pDrivInt->iErrorCount = 0;
SetMotorError(self,"Motor ALARM!!!!");
return 0;
}
@ -769,6 +772,7 @@ static long MotorRunImpl(void *sulf, SConnection * pCon, float fNew)
SCWrite(pCon, pError, eError);
SCWrite(pCon, "\n", eError);
SCSetInterrupt(pCon, (int) ObVal(self->ParArray, INT));
SetMotorError(self,pError);
return HWFault;
case MOTREDO:
iRet = self->pDriver->RunTo(self->pDriver, fHard);
@ -837,6 +841,7 @@ pMotor MotorInit(char *drivername, char *name, MotorDriver * pDriv)
pM->pDriver = pDriv;
pM->drivername = strdup(drivername);
pM->name = strdup(name);
pM->error = strdup("None");
/* initialise object descriptor */
@ -1008,6 +1013,7 @@ int MotorCheckPosition(void *sulf, SConnection * pCon)
*/
extern MotorDriver *MakePiPiezo(Tcl_Interp * pTcl, char *pArray);
extern MotorDriver *epicsMakeMotorDriver(char *baseName);
int MotorCreate(SConnection * pCon, SicsInterp * pSics, void *pData,
int argc, char *argv[])
@ -1068,6 +1074,22 @@ int MotorCreate(SConnection * pCon, SicsInterp * pSics, void *pData,
SCWrite(pCon, pBueffel, eLogError);
return 0;
}
} else if (strcmp(argv[2], "epics") == 0) {
if(argc > 3){
pDriver = epicsMakeMotorDriver(argv[3]);
if (!pDriver) {
return 0;
}
pNew = MotorInit("epics", argv[1], pDriver);
if (!pNew) {
snprintf(pBueffel,sizeof(pBueffel)-1, "Failure to create motor %s", argv[1]);
SCWrite(pCon, pBueffel, eLogError);
return 0;
}
} else {
SCWrite(pCon,"ERROR: missing basename argument to create EPICS motor",eError);
return 0;
}
} else {
site = getSite();
if (site != NULL) {
@ -1082,10 +1104,7 @@ int MotorCreate(SConnection * pCon, SicsInterp * pSics, void *pData,
}
/* create the interpreter command */
if (pNew->pActionRoutine)
iRet = AddCommand(pSics, argv[1], pNew->pActionRoutine, MotorKill, pNew);
else
iRet = AddCommand(pSics, argv[1], MotorAction, MotorKill, pNew);
iRet = AddCommand(pSics, argv[1], MotorAction, MotorKill, pNew);
if (!iRet) {
snprintf(pBueffel,sizeof(pBueffel)-1, "ERROR: duplicate command %s not created", argv[1]);
SCWrite(pCon, pBueffel, eError);
@ -1301,6 +1320,10 @@ int MotorAction(SConnection * pCon, SicsInterp * pSics, void *pData,
DeleteTokenList(pList);
SCSendOK(pCon);
return 1;
} /* check for error */
else if (strcmp(pCurrent->text, "error") == 0) {
SCPrintf(pCon,eValue,"%s.error = %s", argv[0], self->error);
return 1;
} else if (strcmp(pCurrent->text, "interest") == 0) { /* interest */
pMoti = (pMotInfo) malloc(sizeof(MotInfo));
if (!pMoti) {
@ -1380,6 +1403,13 @@ int MotorAction(SConnection * pCon, SicsInterp * pSics, void *pData,
SCWrite(pCon, pBueffel, eValue);
DeleteTokenList(pList);
return 1;
} else if(strcmp(pName->text,"status") == 0){
if(self->running){
SCPrintf(pCon,eValue,"%s.status = run",argv[0]);
} else {
SCPrintf(pCon,eValue,"%s.status = idle",argv[0]);
}
return 1;
}
iRet = MotorGetPar(self, pName->text, &fValue);
if (!iRet) {

View File

@ -28,6 +28,7 @@ typedef struct __Motor {
float *fVal);
char *drivername;
char *name;
char *error;
MotorDriver *pDriver;
float fTarget;
float fPosition;
@ -81,6 +82,4 @@ int MotorAction(SConnection * pCon, SicsInterp * pSics, void *pData,
int argc, char *argv[]);
pMotor FindMotor(SicsInterp * pSics, char *name);
/* Made available to oscillate.c to generate MOTEND event. Ferdi */
void finishDriving(pMotor self, SConnection *pCon);
#endif

View File

@ -6,6 +6,10 @@
copyright: see file COPYRIGHT
Mark Koennecke, September 2005
modified to use the task system
Mark Koennecke, January 2014
-----------------------------------------------------------------------*/
#include "motorlist.h"
#include "lld.h"
@ -52,7 +56,7 @@ static int MOLICheckLimits(void *data, float val, char *error, int errlen)
iRet = LLDnodePtr2First(self);
while (iRet != 0) {
LLDnodeDataTo(self, &tuktuk);
test = tuktuk.pDriv->CheckLimits(tuktuk.data, val, error, errlen);
test = tuktuk.pDriv->CheckLimits(tuktuk.data, tuktuk.target, error, errlen);
if (test == 0) {
retVal = 0;
}
@ -73,17 +77,18 @@ static int MOLICheckLimits(void *data, float val, char *error, int errlen)
------------------------------------------------------------------*/
static long MOLISetValue(void *data, SConnection * pCon, float val)
{
int self = 0, iRet, test;
int self = 0, iRet;
MotControl tuktuk;
self = *(int *) data;
iRet = LLDnodePtr2First(self);
while (iRet != 0) {
LLDnodeDataTo(self, &tuktuk);
test = tuktuk.pDriv->SetValue(tuktuk.data, pCon, tuktuk.target);
if (test != 1) {
return test;
tuktuk.taskID = StartDriveTask(tuktuk.data,pCon,tuktuk.name,tuktuk.target);
if (tuktuk.taskID < 0) {
return HWFault;
} else {
tuktuk.running = 1;
LLDnodeDataFrom(self, &tuktuk);
@ -105,7 +110,7 @@ static long MOLISetValue(void *data, SConnection * pCon, float val)
------------------------------------------------------------------*/
static int MOLICheckStatus(void *data, SConnection * pCon)
{
int self = 0, iRet, status, result = HWIdle;
int self = 0, iRet, status;
MotControl tuktuk;
self = *(int *) data;
@ -114,35 +119,17 @@ static int MOLICheckStatus(void *data, SConnection * pCon)
while (iRet != 0) {
LLDnodeDataTo(self, &tuktuk);
if (tuktuk.running == 1) {
status = tuktuk.pDriv->CheckStatus(tuktuk.data, pCon);
switch (status) {
case HWIdle:
tuktuk.running = 0;
status = isTaskIDRunning(pServ->pTasker,tuktuk.taskID);
if(status == 1){
return HWBusy;
} else {
tuktuk.running = 0;
LLDnodeDataFrom(self, &tuktuk);
break;
case HWBusy:
result = HWBusy;
break;
case HWFault:
case HWPosFault:
/**
* It is questionable if one should not set a flag here
* and keep polling: it is not clear if this error is a
* communication problem or that the motor really
* has stopped.
*/
return status;
break;
default:
/*
this is a programming error and has to be fixed
*/
assert(0);
}
}
iRet = LLDnodePtr2Next(self);
}
return result;
return HWIdle;
}
/*---------------------------------------------------------
A special version for EIGER. I am cautious: I have problems
@ -151,39 +138,7 @@ static int MOLICheckStatus(void *data, SConnection * pCon)
-----------------------------------------------------------*/
int MOLIEigerStatus(void *data, SConnection * pCon)
{
int self = 0, iRet, status, result = HWIdle;
MotControl tuktuk;
self = *(int *) data;
iRet = LLDnodePtr2First(self);
while (iRet != 0) {
LLDnodeDataTo(self, &tuktuk);
if (tuktuk.running == 1) {
status = tuktuk.pDriv->CheckStatus(tuktuk.data, pCon);
switch (status) {
case HWIdle:
tuktuk.running = 0;
LLDnodeDataFrom(self, &tuktuk);
break;
case HWBusy:
result = HWBusy;
break;
case HWFault:
case HWPosFault:
tuktuk.running = 0;
LLDnodeDataFrom(self, &tuktuk);
break;
default:
/*
this is a programming error and has to be fixed
*/
assert(0);
}
}
iRet = LLDnodePtr2Next(self);
}
return result;
return MOLICheckStatus(data,pCon);
}
/*----------------------------------------------------------------

View File

@ -19,6 +19,7 @@ typedef struct {
pIDrivable pDriv;
void *data;
int running;
long taskID;
} MotControl, *pMotControl;
/*======================================================================*/

View File

@ -47,6 +47,20 @@
#define ABS(x) (x < 0 ? -(x) : (x))
/*-------------------------------------------------------------------------*/
static void SecMotorSetError(pMotor self, char *text)
{
hdbValue v;
pHdb node;
node = GetHipadabaNode(self->pDescriptor->parNode, "error");
if(node != NULL){
v = MakeHdbText(strdup(text));
UpdateHipadabaPar(node,v,NULL);
ReleaseHdbValue(&v);
}
}
/*--------------------------------------------------------------------------*/
static int SecMotorGetPar(pMotor self, char *name, float *fVal)
{
@ -106,15 +120,17 @@ static long SecMotorRun(void *sulf, SConnection * pCon, float fNew)
}
self->stopped = 0;
self->stopReported = 0;
self->fTarget = fNew;
v = MakeHdbFloat(fNew);
status = SetHipadabaPar(self->pDescriptor->parNode, v, pCon);
SecMotorSetError(sulf,"None");
node = GetHipadabaNode(self->pDescriptor->parNode, "status");
if(node != NULL){
v = MakeHdbText(strdup("run"));
UpdateHipadabaPar(node,v,pCon);
ReleaseHdbValue(&v);
}
v = MakeHdbFloat(fNew);
status = SetHipadabaPar(self->pDescriptor->parNode, v, pCon);
return status;
}
@ -200,12 +216,17 @@ static int SecMotorLimits(void *sulf, float fVal, char *error, int iErrLen)
{
float fHard;
pMotor self;
int status;
assert(sulf);
self = (pMotor) sulf;
return SecMotorCheckBoundary(self, fVal, &fHard, error, iErrLen);
status = SecMotorCheckBoundary(self, fVal, &fHard, error, iErrLen);
if(status != 1){
SecMotorSetError(sulf,error);
}
return status;
}
/*-----------------------------------------------------------------------*/
@ -231,10 +252,11 @@ static int checkPosition(pMotor self, SConnection * pCon)
if (ABS(target - hard) > precision) {
if (self->retryCount >= (int) maxretry) {
SCPrintf(pCon, eLogError,
"ERROR: Aborting %s after %d retries, off position by %f",
"ERROR: aborting %s after %d retries, off position by %f",
self->name, (int) maxretry, target - hard);
node = GetHipadabaNode(self->pDescriptor->parNode, "status");
assert(node != NULL);
SecMotorSetError(self,"Aborted positioning after many retries");
UpdateHipadabaPar(node, MakeHdbText("error"), pCon);
return HWFault;
}
@ -277,6 +299,7 @@ static int SecMotorStatus(void *sulf, SConnection * pCon)
pHdb node = NULL;
hdbValue v;
float interrupt;
char error[132];
assert(sulf);
self = (pMotor) sulf;
@ -298,8 +321,20 @@ static int SecMotorStatus(void *sulf, SConnection * pCon)
handleMoveCallback(self, pCon);
status = HWBusy;
} else if (strstr(v.v.text, "poserror") != NULL) {
SCWrite(pCon,"WARNING: Position not reached",eLog);
status = checkPosition(self, pCon);
} else if (strstr(v.v.text, "restart") != NULL) {
SCPrintf(pCon,eLog,"WARNING: restarting motor %s", self->name);
SecMotorRun(self,pCon,self->fTarget);
return HWBusy;
} else if (strstr(v.v.text, "error") != NULL) {
if(GetHdbProperty(node,"geterror",error,sizeof(error)) == 1){
SecMotorSetError(sulf,error);
}
node = GetHipadabaNode(self->pDescriptor->parNode, "targetposition");
if(GetHdbProperty(node,"geterror",error,sizeof(error)) == 1){
SecMotorSetError(sulf,error);
}
status = HWFault;
} else {
SCPrintf(pCon, eError, "ERROR: unknown motor status %s found",
@ -333,9 +368,16 @@ static float SecMotorGetValue(void *pData, SConnection * pCon)
{
int status;
pMotor self = (pMotor) pData;
hdbValue v;
hdbValue v;
char error[132];
assert(pData);
status = GetHdbProperty(self->pDescriptor->parNode,"geterror", error,sizeof(error));
if(status == 1 && strcmp(error,"none") != 0) {
SCPrintf(pCon,eError,"ERROR: Failed to read %s with %s", self->name, error);
return -9999999.99;
}
status = GetHipadabaPar(self->pDescriptor->parNode, &v, pCon);
if (status != 1) {
return -9999999.99;
@ -423,7 +465,7 @@ static hdbCallbackReturn SecMotorCallback(pHdb node, void *userData,
pHdb child = NULL;
pMotor self = NULL;
float fHard, fVal, sign, zero;
char pBueffel[512], pError[132];
char pBueffel[512], pError[132], *pPtr = NULL;
int status;
self = (pMotor) userData;
@ -467,13 +509,14 @@ static hdbCallbackReturn SecMotorCallback(pHdb node, void *userData,
self->name);
SCWrite(pCon, pBueffel, eWarning);
self->errorCount = 0;
self->pDrivInt->iErrorCount = 0;
}
/*
* check for alarm condition
*/
SecMotorGetPar(self, "failafter", &fVal);
if (self->pDrivInt->iErrorCount > (int) fVal) {
if (self->pDrivInt->iErrorCount >= (int) fVal) {
/* big alarm */
ServerWriteGlobal("ERROR: !!! MOTOR ALARM !!! MOTOR ALARM !!!",
eError);
@ -483,6 +526,8 @@ static hdbCallbackReturn SecMotorCallback(pHdb node, void *userData,
ServerWriteGlobal(pBueffel, eError);
SCSetInterrupt(pCon, eAbortBatch);
self->pDrivInt->iErrorCount = 0;
child = GetHipadabaNode(self->pDescriptor->parNode, "status");
UpdateHipadabaPar(child, MakeHdbText("run"), pCon);
return hdbAbort;
}
@ -490,10 +535,10 @@ static hdbCallbackReturn SecMotorCallback(pHdb node, void *userData,
self->retryCount = 0;
self->stopped = 0;
self->posCount = 0;
child = GetHipadabaNode(self->pDescriptor->parNode, "targetposition");
UpdateHipadabaPar(child, MakeHdbFloat(fHard), pCon);
child = GetHipadabaNode(self->pDescriptor->parNode, "status");
UpdateHipadabaPar(child, MakeHdbText("run"), pCon);
child = GetHipadabaNode(self->pDescriptor->parNode, "targetposition");
UpdateHipadabaPar(child, MakeHdbFloat(fHard), pCon);
child = GetHipadabaNode(self->pDescriptor->parNode, "hardposition");
SetHipadabaPar(child, MakeHdbFloat(fHard), pCon);
@ -504,6 +549,12 @@ static hdbCallbackReturn SecMotorCallback(pHdb node, void *userData,
if (mm != NULL) {
pCon = (SConnection *) mm->callData;
SecMotorGetPar(self, "hardposition", &fVal);
child = GetHipadabaNode(self->pDescriptor->parNode, "hardposition");
if((pPtr = GetHdbProp(child,"geterror")) != NULL){
SetHdbProperty(node,"geterror",pPtr);
} else {
SetHdbProperty(node,"geterror",NULL);
}
fVal = hardToSoftPosition(self, fVal);
node->value.v.doubleValue = fVal;
mm->v->v.doubleValue = fVal;
@ -518,6 +569,7 @@ static hdbCallbackReturn HardUpdateCallback(pHdb node, void *userData,
pHdbMessage message)
{
pHdbDataMessage mm = NULL;
pHdbPropertyChange pm = NULL;
pMotor self = (pMotor) userData;
float fVal;
hdbValue v;
@ -532,6 +584,18 @@ static hdbCallbackReturn HardUpdateCallback(pHdb node, void *userData,
UpdateHipadabaPar(self->pDescriptor->parNode, v, mm->callData);
return hdbContinue;
}
/*
forward geterror
*/
pm = GetPropertyChangeMessage(message);
if(pm != NULL){
if(strstr(pm->key,"geterror") != NULL){
SetHdbProperty(self->pDescriptor->parNode,pm->key, pm->value);
}
}
return hdbContinue;
}
@ -611,6 +675,80 @@ static hdbCallbackReturn SecMotorZeroCallback(pHdb node, void *userData,
return hdbContinue;
}
/*--------------------------------------------------------------------------*/
typedef struct {
char *pName;
SConnection *pCon;
float lastValue;
} MotInfo, *pMotInfo;
/*--------------------------------------------------------------------------*/
static void KillInfo(void *pData)
{
pMotInfo self = NULL;
assert(pData);
self = (pMotInfo) pData;
if (self->pName) {
free(self->pName);
}
if (self->pCon != NULL) {
SCDeleteConnection(self->pCon);
}
free(self);
}
/*-------------------------------------------------------------------------*/
static hdbCallbackReturn InterestCallback(pHdb node, void *userData,
pHdbMessage message)
{
pHdbDataMessage mm = NULL;
pMotor self = (pMotor) userData;
float fVal;
hdbValue v;
pMotInfo priv = (pMotInfo)userData;
assert(self != NULL);
mm = GetHdbUpdateMessage(message);
if (mm != NULL) {
v = *mm->v;
if(!SCisConnected(priv->pCon)){
return hdbKill;
}
if(ABS(v.v.doubleValue - priv->lastValue) > .1) {
SCPrintf(priv->pCon,eValue,"%s.position = %f",
priv->pName, v.v.doubleValue);
priv->lastValue = v.v.doubleValue;
}
return hdbContinue;
}
return hdbContinue;
}
/*---------------------------------------------------------------------------*/
static int InterestCmd(pSICSOBJ ccmd, SConnection * con,
Hdb * cmdNode, Hdb * par[], int nPar)
{
pMotInfo priv = NULL;
priv = malloc(sizeof(MotInfo));
if(priv == NULL){
SCWrite(con,"ERROR: out of memory registering interest",eError);
return 0;
}
if(nPar >= 1 && (strcmp(par[0]->value.v.text,"UNKNOWN") != 0)) {
priv->pName = strdup(par[0]->value.v.text);
} else {
priv->pName = strdup(ccmd->objectNode->name);
}
priv->lastValue = .0;
priv->pCon = SCCopyConnection(con);
AppendHipadabaCallback(ccmd->objectNode,
MakeHipadabaCallback(InterestCallback,priv,KillInfo));
SCSendOK(con);
return 1;
}
/*---------------------------------------------------------------------------*/
pMotor SecMotorInit(char *name)
{
@ -672,6 +810,7 @@ pMotor SecMotorInit(char *name)
child = MakeHipadabaNode("sign", HIPFLOAT, 1);
SetHdbProperty(child, "__save", "true");
SetHdbProperty(child, "priv", "user");
AddHipadabaChild(node, child, NULL);
AppendHipadabaCallback(child,
MakeHipadabaCallback(SecMotorSignCallback, pM,
@ -680,6 +819,7 @@ pMotor SecMotorInit(char *name)
child = MakeHipadabaNode("softzero", HIPFLOAT, 1);
SetHdbProperty(child, "__save", "true");
SetHdbProperty(child, "priv", "user");
AddHipadabaChild(node, child, NULL);
AppendHipadabaCallback(child,
MakeHipadabaCallback(SecMotorZeroCallback, pM,
@ -744,6 +884,13 @@ pMotor SecMotorInit(char *name)
SetHdbProperty(child, "motname", name);
AddHipadabaChild(node, child, NULL);
child = MakeHipadabaNode("error", HIPTEXT, 1);
AddHipadabaChild(node, child, NULL);
child = AddSICSHdbPar(node,"interest", usUser, MakeSICSFunc(InterestCmd));
AddSICSHdbPar(child, "name", usUser, MakeHdbText("UNKNOWN"));
pM->endScriptID = 0;
/* initialise Drivable interface */
@ -791,6 +938,8 @@ static void SecMotorKill(void *data)
free(self->pDrivInt);
}
RemoveHdbNodeFromParent(self->objectNode,NULL);
if (self->pCall) {
DeleteCallBackInterface(self->pCall);
}
@ -821,3 +970,25 @@ int SecMotorFactory(SConnection * pCon, SicsInterp * pSics, void *pData,
SecMotorKill, pNew);
}
/*--------------------------------------------------------------------------
everywhere we need to find a motor for a name quite frequently.......
----------------------------------------------------------------------------*/
pMotor FindMotor(SicsInterp * pSics, char *name)
{
CommandList *pC;
pMotor pMot;
pC = FindCommand(pSics, name);
if (!pC) {
return NULL;
}
pMot = (pMotor) pC->pData;
if (!pMot) {
return NULL;
}
if (strcmp(pMot->pDescriptor->name, "Motor") != 0 ) {
return NULL;
}
return pMot;
}

View File

@ -37,6 +37,7 @@ typedef struct {
pICountable slaves[MAXSLAVE];
char *transferScript;
int nSlaves;
int checkSlaves;
} MultiCounter, *pMultiCounter;
/*--------------------------------------------------------------------------*/
static void KillMultiDriver(struct __COUNTER *data)
@ -77,12 +78,9 @@ static int MMCCHalt(void *pData)
/*-------------------------------------------------------------------------*/
static int MMCCStart(void *pData, SConnection * pCon)
{
int i, status, controlMonitor;
int slavePreset, oneYear = 32000000;
int i, status;
pCounter pCount = NULL;
pMultiCounter self = NULL;
char buffer[128];
CounterMode slaveMode;
pCount = (pCounter) pData;
if (pCount != NULL) {
@ -93,25 +91,12 @@ static int MMCCStart(void *pData, SConnection * pCon)
if (!GetCountLock(pCount->pCountInt, pCon)) {
return HWFault;
}
controlMonitor = GetControlMonitor((pCounter) pCount);
if (pCount->pDriv->eMode == ePreset) {
slaveMode = eTimer;
slavePreset = oneYear;
} else {
slaveMode = pCount->pDriv->eMode;
slavePreset = pCount->pDriv->fPreset;
}
for (i = 0; i < self->nSlaves; i++) {
ReleaseCountLock(self->slaves[i]);
if (i == controlMonitor) {
self->slaves[i]->SetCountParameters(self->slaveData[i],
pCount->pDriv->fPreset,
pCount->pDriv->eMode);
} else {
self->slaves[i]->SetCountParameters(self->slaveData[i],
slavePreset, slaveMode);
}
ReleaseCountLock(self->slaves[i]);
self->slaves[i]->SetCountParameters(self->slaveData[i],
pCount->pDriv->fPreset,
pCount->pDriv->eMode);
status = self->slaves[i]->StartCount(self->slaveData[i], pCon);
if (status != OKOK) {
MMCCHalt(pData);
@ -122,24 +107,18 @@ static int MMCCStart(void *pData, SConnection * pCon)
pCount->isUpToDate = 0;
pCount->tStart = time(NULL);
InvokeCallBack(pCount->pCall, COUNTSTART, pCon);
self->checkSlaves = 0;
return OKOK;
}
/*-------------------------------------------------------------------------*/
static int MMCCStatus(void *pData, SConnection * pCon)
{
int status, ctrStatus, i, controlMonitor;
pCounter pCountController = NULL, pSlaveCounter = NULL;
int status, i;
pCounter pCount = NULL, pMaster = NULL;;
pMultiCounter self = NULL;
pDummy pDum = NULL;
enum {
eIdle,
eBusy,
ePause,
eNoBeam,
eFault
} statusLevel;
pCount = (pCounter) pData;
if (pCount != NULL) {
@ -153,63 +132,47 @@ static int MMCCStatus(void *pData, SConnection * pCon)
return HWFault;
}
status = self->slaves[0]->CheckCountStatus(self->slaveData[0], pCon);
pMaster = (pCounter)self->slaveData[0];
pCount->pDriv->fLastCurrent = GetControlValue(pMaster);
controlMonitor = GetControlMonitor((pCounter) pCount);
pCountController = (pCounter) self->slaveData[controlMonitor];
/* counter states = HWIdle, HWBusy, HWPause, HWNoBeam, HWFault */
status = HWIdle;
statusLevel = eIdle;
for (i = 0; i < self->nSlaves; i++) {
pSlaveCounter = (pCounter) self->slaveData[i];
ctrStatus = self->slaves[i]->CheckCountStatus(pSlaveCounter, pCon);
if (statusLevel >= eFault)
continue;
switch (ctrStatus) {
case HWFault:
statusLevel = eFault;
status = HWFault;
break;
case HWNoBeam:
if (statusLevel < eNoBeam)
statusLevel = eNoBeam;
status = HWNoBeam;
break;
case HWPause:
if (statusLevel < ePause)
statusLevel = ePause;
status = HWPause;
break;
default:
if (pCountController->pDriv->eMode == ePreset && i == controlMonitor
&& ctrStatus == HWIdle) {
statusLevel = eBusy; /* Allow transition to HWPause or higher */
status = HWIdle;
} else if (statusLevel < eBusy && ctrStatus != HWIdle) {
/* ffr: We expect !HWIdle means HWBusy, if not the existing code should handle the exception */
statusLevel = eBusy;
status = ctrStatus;
}
if(self->checkSlaves == 0) {
status = self->slaves[0]->CheckCountStatus(self->slaveData[0], pCon);
if (status == HWIdle || status == HWFault) {
/*
stop counting on slaves when finished or when an error
occurred.
*/
MMCCHalt(pData);
ReleaseCountLock(pCount->pCountInt);
self->checkSlaves = 1;
status = HWBusy;
}
}
if (status == HWIdle || status == HWFault) {
pCount->pDriv->fLastCurrent = GetControlValue(self->slaveData[0]);
} else {
/*
stop counting on slaves when finished or when an error
occurred.
* wait for the detectors to report finish too. Otherwise, with the second
* generation HM data may not be fully transferred.
*/
InvokeCallBack(pCount->pCall, COUNTEND, pCon);
MMCCHalt(pCount);
}
for (i = 1; i < MAXSLAVE; i++) {
if (self->slaves[i] != NULL) {
pDum = (pDummy) self->slaveData[i];
if (strcmp(pDum->pDescriptor->name, "HistMem") == 0) {
HistDirty((pHistMem) self->slaveData[i]);
for(i = 1; i < self->nSlaves; i++){
status = self->slaves[i]->CheckCountStatus(self->slaveData[i], pCon);
if(!(status == HWIdle || status == HWFault)){
return status;
}
ReleaseCountLock(self->slaves[i]);
}
/*
Warning: this assumes that slaves 1 - MAXSLAVE are histogram memories.
If this assumption does not hold, change this code to check if this
is really a histogram memory.
*/
for (i = 1; i < self->nSlaves; i++) {
if (self->slaves[i] != NULL) {
pDum = (pDummy)self->slaveData[i];
if (strcmp(pDum->pDescriptor->name, "HistMem") == 0) {
HistDirty((pHistMem) self->slaveData[i]);
}
ReleaseCountLock(self->slaves[i]);
}
}
status = HWIdle;
InvokeCallBack(pCount->pCall, COUNTEND, pCon);
self->checkSlaves = 0;
}
return status;
}
@ -293,8 +256,7 @@ static void loadCountData(pCounter pCount, const char *data)
pPtr = (char *) data;
pPtr = getNextMMCCNumber(pPtr, pNumber);
// SICS-195 get time from controlling monitor
// pCount->pDriv->fTime = atof(pNumber);
pCount->pDriv->fTime = atof(pNumber);
while (pPtr != NULL && i < MAXCOUNT) {
pPtr = getNextMMCCNumber(pPtr, pNumber);
pCount->pDriv->lCounts[i] = atoi(pNumber);
@ -308,19 +270,14 @@ static int MMCCTransfer(void *pData, SConnection * pCon)
int i, retVal = OKOK, status;
char pBueffel[132];
pCounter pCount = NULL;
pCounter pCountController = NULL, pCountSlave;
pMultiCounter self = NULL;
int tclStatus;
int controlMonitor;
double avCntRt;
pCount = (pCounter) pData;
if (pCount != NULL) {
self = (pMultiCounter) pCount->pDriv->pData;
}
assert(self);
controlMonitor = GetControlMonitor(pCount);
pCountController = (pCounter) self->slaveData[controlMonitor];
for (i = 0; i < self->nSlaves; i++) {
status = self->slaves[i]->TransferData(self->slaveData[i], pCon);
@ -329,18 +286,8 @@ static int MMCCTransfer(void *pData, SConnection * pCon)
snprintf(pBueffel,sizeof(pBueffel)-1,
"WARNING: slave histogram %d failed to transfer data", i);
SCWrite(pCon, pBueffel, eWarning);
} else if (pCountController->pDriv->eMode == ePreset) {
if (i != controlMonitor) {
pCountSlave = (pCounter) self->slaveData[i];
avCntRt =
pCountSlave->pDriv->lCounts[0] / pCountSlave->pDriv->fTime;
pCountSlave->pDriv->lCounts[0] =
avCntRt * pCountController->pDriv->fTime;
pCountSlave->pDriv->fTime = pCountController->pDriv->fTime;
}
}
}
pCount->pDriv->fTime = pCountController->pDriv->fTime;
if (self->transferScript != NULL) {
MacroPush(pCon);
tclStatus = Tcl_Eval(InterpGetTcl(pServ->pSics), self->transferScript);
@ -380,74 +327,74 @@ static void MMCCParameter(void *pData, float fPreset, CounterMode eMode)
static int MultiCounterSet(struct __COUNTER *pCount, char *name,
int iCter, float fVal)
{
pDummy pDum;
int i;
pMultiCounter self = NULL;
pCounter pCter;
pDummy pDum;
int i;
pMultiCounter self = NULL;
pCounter pCter;
self = (pMultiCounter) pCount->pData;
assert(self);
self = (pMultiCounter) pCount->pData;
assert(self);
for (i = 0; i < self->nSlaves; i++) {
pDum = (pDummy)self->slaveData[i];
if(strcmp(pDum->pDescriptor->name, "SingleCounter") == 0){
pCter = (pCounter)self->slaveData[i];
if(pCter->pDriv != NULL){
return pCter->pDriv->Set(pCter->pDriv, name, iCter, fVal);
} else {
return 0;
}
}
}
return 0;
for (i = 0; i < self->nSlaves; i++) {
pDum = (pDummy)self->slaveData[i];
if(strcmp(pDum->pDescriptor->name, "SingleCounter") == 0){
pCter = (pCounter)self->slaveData[i];
if(pCter->pDriv != NULL){
return pCter->pDriv->Set(pCter->pDriv, name, iCter, fVal);
} else {
return 0;
}
}
}
return 0;
}
/*-----------------------------------------------------------------------*/
static int MultiCounterGet(struct __COUNTER *pCount, char *name,
int iCter, float *fVal)
{
pDummy pDum;
int i;
pMultiCounter self = NULL;
pCounter pCter;
pHdb node;
hdbValue v;
pDummy pDum;
int i;
pMultiCounter self = NULL;
pCounter pCter;
pHdb node;
hdbValue v;
self = (pMultiCounter) pCount->pData;
assert(self);
self = (pMultiCounter) pCount->pData;
assert(self);
for (i = 0; i < self->nSlaves; i++) {
pDum = (pDummy)self->slaveData[i];
if(strcmp(pDum->pDescriptor->name, "SingleCounter") == 0){
pCter = (pCounter)self->slaveData[i];
if(pCter->pDriv != NULL){
return pCter->pDriv->Get(pCter->pDriv, name, iCter, fVal);
} else {
return 0;
}
}
}
return 0;
for (i = 0; i < self->nSlaves; i++) {
pDum = (pDummy)self->slaveData[i];
if(strcmp(pDum->pDescriptor->name, "SingleCounter") == 0){
pCter = (pCounter)self->slaveData[i];
if(pCter->pDriv != NULL){
return pCter->pDriv->Get(pCter->pDriv, name, iCter, fVal);
} else {
return 0;
}
}
}
return 0;
}
/*-----------------------------------------------------------------------*/
static int MultiCounterSend(struct __COUNTER *pCount, char *pText,
char *reply, int replylen)
{
pDummy pDum;
int i;
pMultiCounter self = NULL;
pCounter pCter;
pDummy pDum;
int i;
pMultiCounter self = NULL;
pCounter pCter;
self = (pMultiCounter) pCount->pData;
assert(self);
self = (pMultiCounter) pCount->pData;
assert(self);
for (i = 0; i < self->nSlaves; i++) {
pDum = (pDummy)self->slaveData[i];
if(strcmp(pDum->pDescriptor->name, "SingleCounter") == 0){
pCter = (pCounter)self->slaveData[i];
return pCter->pDriv->Send(pCter->pDriv,pText, reply, replylen);
}
}
return 0;
for (i = 0; i < self->nSlaves; i++) {
pDum = (pDummy)self->slaveData[i];
if(strcmp(pDum->pDescriptor->name, "SingleCounter") == 0){
pCter = (pCounter)self->slaveData[i];
return pCter->pDriv->Send(pCter->pDriv,pText, reply, replylen);
}
}
return 0;
}
/*---------------------------------------------------------------------*/
static int MultiCounterError(struct __COUNTER *pDriv, int *iCode,
@ -539,30 +486,6 @@ int MakeMultiCounter(SConnection * pCon, SicsInterp * pSics,
pDriv->pData = self;
pDriv->KillPrivate = KillMultiDriver;
pDriv->iNoOfMonitors = MAXCOUNT;
/*
now loop through the remaining arguments, thereby entering them into
the slave list.
*/
self->nSlaves = 0;
for (i = 2; i < argc; i++) {
pCom = FindCommand(pSics, argv[i]);
if (!pCom) {
snprintf(pBueffel,sizeof(pBueffel)-1, "ERROR: object %s not found in MakeMultiCounter",
argv[i]);
SCWrite(pCon, pBueffel, eError);
continue;
}
pCount = GetCountableInterface(pCom->pData);
if (!pCount) {
snprintf(pBueffel,sizeof(pBueffel)-1, "ERROR: object %s is NOT countable", argv[i]);
SCWrite(pCon, pBueffel, eError);
continue;
}
self->slaves[self->nSlaves] = pCount;
self->slaveData[self->nSlaves] = pCom->pData;
self->nSlaves++;
}
pDriv->iNoOfMonitors = self->nSlaves;
pNew = CreateCounter(argv[1], pDriv);
if (pNew == NULL) {
SCWrite(pCon, "ERROR: out of memory in MakeMultiCounter", eError);
@ -585,6 +508,29 @@ int MakeMultiCounter(SConnection * pCon, SicsInterp * pSics,
pNew->pCountInt->TransferData = MMCCTransfer;
pNew->pCountInt->SetCountParameters = MMCCParameter;
/*
now loop through the remaining arguments, thereby entering them into
the slave list.
*/
for (i = 2; i < argc; i++) {
pCom = FindCommand(pSics, argv[i]);
if (!pCom) {
snprintf(pBueffel,sizeof(pBueffel)-1, "ERROR: object %s not found in MakeMultiCounter",
argv[i]);
SCWrite(pCon, pBueffel, eError);
continue;
}
pCount = GetCountableInterface(pCom->pData);
if (!pCount) {
snprintf(pBueffel,sizeof(pBueffel)-1, "ERROR: object %s is NOT countable", argv[i]);
SCWrite(pCon, pBueffel, eError);
continue;
}
self->slaves[self->nSlaves] = pCount;
self->slaveData[self->nSlaves] = pCom->pData;
self->nSlaves++;
}
/*
now install our action command and we are done
*/

564
multicountersec.c Normal file
View File

@ -0,0 +1,564 @@
/**
* This is a second generation multicounter. It coordinates counting multiple
* HM/CCD with the counter box. It also allows to override transfer such that
* such a counter can be used in a scan. As with the ordinary multicounter.
* This one is supposed to become the standard multicounter replacing the old
* multicounter and the hmcontrol module. The other difference is that the task
* mechanism will be used to keep track of counters.
*
* copyright: see file COPYRIGHT
*
* Mark Koennecke, October 2013
*/
#include <time.h>
#include <sics.h>
#include <counter.h>
#include <stptok.h>
#include <macro.h>
#include <status.h>
#include "sicshipadaba.h"
/*---------------------------------------------------------------------------*/
typedef struct {
float fPreset;
float fCurrent;
char *pName;
} MonEvent, *pMonEvent;
/*-------------------------------------------------------------------------*/
static void SecCounterSetError(pCounter self, char *text)
{
hdbValue v;
pHdb node;
node = GetHipadabaNode(self->pDes->parNode, "error");
if(node != NULL){
v = MakeHdbText(strdup(text));
UpdateHipadabaPar(node,v,NULL);
ReleaseHdbValue(&v);
}
}
/*---------------------------------------------------------------------------------*/
static void doCountCommand(pHdb self, SConnection *pCon, int command)
{
pHdb master = NULL, slaves = NULL;
char *pPtr, name[80];
pICountable pCount = NULL;
void *data;
master = GetHipadabaNode(self,"master");
slaves = GetHipadabaNode(self,"slaves");
assert(master != NULL);
assert(slaves != NULL);
/*
treat master
*/
data = FindCommandData(pServ->pSics,master->value.v.text,NULL);
if(data != NULL){
pCount = GetCountableInterface(data);
if(pCount != NULL){
switch(command){
case 1001: /* stop */
pCount->Halt(data);
break;
case 1002: /*pause */
pCount->Pause(data,pCon);
break;
case 1003: /* continue */
pCount->Continue(data,pCon);
break;
case 1011:
break;
default:
assert(0);
}
}
}
/*
treat slaves
*/
pPtr = slaves->value.v.text;
while((pPtr = stptok(pPtr,name,sizeof(name),",")) != NULL){
data = FindCommandData(pServ->pSics,name,NULL);
if(data != NULL){
pCount = GetCountableInterface(data);
if(pCount != NULL){
switch(command){
case 1001: /* stop */
case 1011:
pCount->Halt(data);
break;
case 1002: /*pause */
pCount->Pause(data,pCon);
break;
case 1003: /* continue */
pCount->Continue(data,pCon);
break;
default:
assert(0);
}
}
}
if(data == NULL || pCount == NULL){
SCPrintf(pCon,eLogError,"ERROR: slave counter %s NOT found or unusable", name);
}
}
}
/*---------------------------------------------------------------------------------*/
static void copyExponent(pHdb self, void *data)
{
pHdb source = NULL, target = NULL;
pCounter count = (pCounter)data;
source = GetHipadabaNode(self,"exponent");
target = GetHipadabaNode(count->pDes->parNode,"exponent");
if(source != NULL && target != NULL){
UpdateHipadabaPar(target,MakeHdbInt(source->value.v.intValue), NULL);
}
}
/*---------------------------------------------------------------------------------*/
static void startMultiCounting(pHdb self, SConnection *pCon)
{
pHdb mode = NULL, preset = NULL, master = NULL, slaves = NULL;
pHdb sID, mID;
char *pPtr, name[80];
pICountable pCount = NULL;
void *data;
long slaveID, masterID;
CounterMode eMode;
hdbValue v;
mode = GetHipadabaNode(self,"mode");
preset = GetHipadabaNode(self,"preset");
master = GetHipadabaNode(self,"master");
slaves = GetHipadabaNode(self,"slaves");
sID = GetHipadabaNode(self,"slaveID");
mID = GetHipadabaNode(self,"masterID");
assert(mode != NULL);
assert(preset != NULL);
assert(master != NULL);
assert(slaves != NULL);
assert(sID != NULL);
assert(mID != NULL);
strtolower(mode->value.v.text);
if(strcmp(mode->value.v.text,"timer") == 0) {
eMode = eTimer;
} else {
eMode = ePreset;
}
/*
start slaves
*/
slaveID = GetTaskGroupID(pServ->pTasker);
pPtr = slaves->value.v.text;
while((pPtr = stptok(pPtr,name,sizeof(name),",")) != NULL){
data = FindCommandData(pServ->pSics,name,NULL);
if(data != NULL){
pCount = GetCountableInterface(data);
if(pCount != NULL){
copyExponent(self,data);
pCount->SetCountParameters(data,preset->value.v.doubleValue,
eMode);
masterID = StartCountTask(data,pCon,name);
if(masterID < 0) {
SCPrintf(pCon,eLogError,"ERROR: failed to start slave %s, aborting", name);
doCountCommand(self,pCon,1001);
return;
} else {
AddTaskToGroup(pServ->pTasker,masterID, slaveID);
}
}
}
if(data == NULL || pCount == NULL){
SCPrintf(pCon,eLogError,"ERROR: slave counter %s NOT found or unusable", name);
}
}
/*
start master
*/
data = FindCommandData(pServ->pSics,master->value.v.text,NULL);
if(data != NULL){
pCount = GetCountableInterface(data);
if(pCount != NULL){
copyExponent(self,data);
pCount->SetCountParameters(data,preset->value.v.doubleValue,
eMode);
masterID = StartCountTask(data,pCon,master->value.v.text);
}
}
v = MakeHdbInt(masterID);
UpdateHipadabaPar(mID,v,pCon);
v = MakeHdbInt(slaveID);
UpdateHipadabaPar(sID,v,pCon);
}
/*---------------------------------------------------------------------------------*/
static hdbCallbackReturn MultiSecControllCallback(pHdb node,
void *userData,
pHdbMessage message)
{
pHdbDataMessage mm = NULL;
pHdb self = NULL;
int code;
SConnection *pCon = NULL;
mm = GetHdbSetMessage(message);
if(mm == NULL){
return hdbContinue;
}
code = (int)mm->v->v.doubleValue;
pCon = (SConnection *)mm->callData;
self = node->mama;
assert(self != NULL);
switch(code){
case 1000: /* start */
startMultiCounting(self, pCon);
break;
case 1001: /* stop */
doCountCommand(self,pCon,code);
break;
case 1002: /*pause */
doCountCommand(self,pCon,code);
break;
case 1003: /* continue */
doCountCommand(self,pCon,code);
break;
default:
if(pCon != NULL){
SCPrintf(pCon,eLogError,"ERROR: control code %d not recognised", code);
return hdbAbort;
}
}
return hdbContinue;
}
/*-------------------------------------------------------------------------2-*/
static int MultiSecTransfer(void *pData, SConnection * pCon)
{
int i, retVal = OKOK, tclStatus;
char pBueffel[132];
pCounter pCount = NULL;
pHdb transfer;
SConnection *myCon;
pCount = (pCounter) pData;
transfer = GetHipadabaNode(pCount->objectNode,"transfer");
if(transfer != NULL){
myCon = SCCopyConnection(pCon);
SCsetMacro(myCon,1);
MacroPush(myCon);
tclStatus = Tcl_Eval(InterpGetTcl(pServ->pSics), transfer->value.v.text);
if (tclStatus != TCL_OK) {
snprintf(pBueffel, 131, "ERROR: TransferScript returned: %s",
Tcl_GetStringResult(InterpGetTcl(pServ->pSics)));
SCWrite(pCon, pBueffel, eError);
MacroPop();
SCDeleteConnection(myCon);
return HWFault;
}
MacroPop();
SCDeleteConnection(myCon);
}
return retVal;
}
/*-------------------------------------------------------------------------------------*/
static int isMultiMasterRunning(pCounter self, SConnection *pCon, int *status)
{
pHdb mID, master, myStatus, control, ccd, stopTime, timeNode;
hdbValue v;
long mlID;
void *data;
pICountable pCount;
float controlVal, tVal;
MonEvent sMon;
mID = GetHipadabaNode(self->objectNode,"masterID");
master = GetHipadabaNode(self->objectNode,"master");
myStatus = GetHipadabaNode(self->objectNode,"status");
control = GetHipadabaNode(self->objectNode,"control");
ccd = GetHipadabaNode(self->objectNode,"ccd");
stopTime = GetHipadabaNode(self->objectNode,"stopTime");
timeNode = GetHipadabaNode(self->objectNode,"time");
assert(mID != NULL);
assert(master != NULL);
assert(myStatus != NULL);
assert(control != NULL);
assert(ccd != NULL);
assert(stopTime != NULL);
assert(timeNode != NULL);
mlID = mID->value.v.intValue;
if(mlID == 0) {
return 0;
}
data = FindCommandData(pServ->pSics,master->value.v.text,NULL);
assert(data != NULL);
pCount = GetCountableInterface(data);
assert(pCount != NULL);
if(isTaskIDRunning(pServ->pTasker,mlID)) {
*status = pCount->CheckCountStatus(data,pCon);
controlVal = GetControlValue((pCounter)data);
UpdateHipadabaPar(control,MakeHdbFloat(controlVal),pCon);
tVal = GetCountTime((pCounter)data,pCon);
UpdateHipadabaPar(timeNode,MakeHdbFloat(tVal),pCon);
SecCounterSetError(self,"None");
switch(*status){
case HWFault:
UpdateHipadabaPar(myStatus,MakeHdbText("error"),pCon);
UpdateHipadabaPar(stopTime,MakeHdbInt(time(NULL)),pCon);
SecCounterSetError(self,"Master counter errror");
*status = HWBusy;
break;
case HWPause:
UpdateHipadabaPar(myStatus,MakeHdbText("paused"),pCon);
*status = HWPause;
break;
case HWNoBeam:
UpdateHipadabaPar(myStatus,MakeHdbText("nobeam"),pCon);
*status = HWNoBeam;
break;
default:
*status = HWBusy;
UpdateHipadabaPar(myStatus,MakeHdbText("run"),pCon);
if (self->iCallbackCounter > 20) {
MultiSecTransfer(self,pCon);
sMon.fCurrent = controlVal;
sMon.fPreset = GetCounterPreset(self);
sMon.pName = self->name;
InvokeCallBack(self->pCall, MONITOR, &sMon);
self->iCallbackCounter = 0;
} else {
self->iCallbackCounter++;
}
break;
}
} else {
/*
we recently stopped. Mark it so and stop slaves.
*/
mID->value.v.intValue = 0;
*status = HWBusy;
UpdateHipadabaPar(myStatus,MakeHdbText("run"),pCon);
UpdateHipadabaPar(stopTime,MakeHdbInt(time(NULL)),pCon);
tVal = GetCountTime((pCounter)data,pCon);
UpdateHipadabaPar(timeNode,MakeHdbFloat(tVal),pCon);
if(ccd->value.v.intValue != 1) {
doCountCommand(self->objectNode,pCon,1011);
}
}
return 1;
}
/*-------------------------------------------------------------------------------------*/
static int areSlavesRunning(pCounter self, SConnection *pCon, int *status)
{
pHdb slaveID, myStatus, stopTime, ccd;
int i;
slaveID = GetHipadabaNode(self->objectNode,"slaveID");
myStatus = GetHipadabaNode(self->objectNode,"status");
stopTime = GetHipadabaNode(self->objectNode,"stopTime");
ccd = GetHipadabaNode(self->objectNode,"ccd");
assert(slaveID != NULL);
assert(myStatus != NULL);
assert(stopTime != NULL);
assert(ccd != NULL);
if(isTaskGroupRunning(pServ->pTasker,slaveID->value.v.intValue)){
if(ccd->value.v.intValue == 1 && time(NULL) > stopTime->value.v.intValue + 100) {
SCWrite(pCon,"WARNING: CCD overrun, restarting counting...", eLogError);
self->pCountInt->Halt(self);
ReleaseCountLock(self->pCountInt);
for(i = 0; i < 100; i++){
SicsWait(1);
if(!isTaskGroupRunning(pServ->pTasker,slaveID->value.v.intValue)){
self->pCountInt->StartCount(self,pCon);
UpdateHipadabaPar(myStatus,MakeHdbText("run"),pCon);
UpdateHipadabaPar(stopTime,MakeHdbInt(time(NULL)),pCon);
*status = HWBusy;
return 1;
}
}
SCWrite(pCon,"ERROR: failed to stop overrun CCD",eLogError);
*status = HWFault;
} else {
*status = HWBusy;
UpdateHipadabaPar(myStatus,MakeHdbText("run"),pCon);
return 1;
}
} else {
*status = HWIdle;
UpdateHipadabaPar(myStatus,MakeHdbText("idle"),pCon);
return 0;
}
return 1;
}
/*------------------------------------------------------------------------------------*/
static void multiEndCounting(pCounter self, SConnection *pCon)
{
InvokeCallBack(self->pCall, COUNTEND, NULL);
ReleaseCountLock(self->pCountInt);
MultiSecTransfer(self,pCon);
}
/*-------------------------------------------------------------------------------------*/
static int MultiSecStatus(void *pData, SConnection * pCon)
{
int status;
void *data;
pICountable pCount = NULL;
pHdb mID = NULL, sID = NULL, master;
pCounter self = (pCounter)pData;
if(isMultiMasterRunning(self,pCon, &status)){
return status;
}
if(areSlavesRunning(self,pCon, &status)){
return status;
}
multiEndCounting(self,pCon);
return HWIdle;
}
/*---------------------------------------------------------------------------
Forward unknown commands to the master counter
-----------------------------------------------------------------------------*/
static int MultiInvokeSICSOBJ(SConnection * pCon, SicsInterp * pSics, void *pData,
int argc, char *argv[])
{
int status;
char buffer[132];
pHdb master = NULL;
pCounter self = (pCounter)pData;
void *data = NULL;
CommandList *pCom;
status = InvokeSICSOBJ(pCon, pSics, pData, argc, argv);
if (status == -1) {
master = GetHipadabaNode(self->objectNode,"master");
assert(master != NULL);
pCom = FindCommand(pSics,master->value.v.text);
if(pCom != NULL){
status = pCom->OFunc(pCon,pSics,pCom->pData,argc,argv);
}
status = 0;
}
return status;
}
/*-------------------------------------------------------------------------------------*/
int MakeMultiSec(SConnection * pCon, SicsInterp * pSics, void *pData,
int argc, char *argv[])
{
pCounter pRes = NULL;
int status, length;
pHdb node, child;
if(argc < 3) {
SCWrite(pCon,"ERROR: need at least a name and length to create a counter",
eError);
return 0;
}
length = atoi(argv[2]);
pRes = CreateSecCounter(pCon,"SingleCounter", argv[1], length);
if(pRes == NULL){
return 0;
}
pRes->pCountInt->CheckCountStatus = MultiSecStatus;
pRes->pCountInt->TransferData = MultiSecTransfer;
node = pRes->objectNode;
child = GetHipadabaNode(node,"control");
AppendHipadabaCallback(child,MakeHipadabaCallback(MultiSecControllCallback,NULL,NULL));
child = MakeSICSHdbPar("master", usMugger, MakeHdbText(""));
if (child == NULL) {
SCWrite(pCon,"ERROR: out of memory in MakeMultiCounterSec",eError);
return 0;
} else {
SetHdbProperty(child, "__save", "true");
AddHipadabaChild(node, child, NULL);
}
child = MakeSICSHdbPar("transfer", usMugger, MakeHdbText(""));
if (child == NULL) {
SCWrite(pCon,"ERROR: out of memory in MakeMultiCounterSec",eError);
return 0;
} else {
SetHdbProperty(child, "__save", "true");
AddHipadabaChild(node, child, NULL);
}
child = MakeSICSHdbPar("error", usMugger, MakeHdbText("None"));
if (child == NULL) {
SCWrite(pCon,"ERROR: out of memory in MakeMultiCounterSec",eError);
return 0;
} else {
AddHipadabaChild(node, child, NULL);
}
child = MakeSICSHdbPar("slaves", usMugger, MakeHdbText(""));
if (child == NULL) {
SCWrite(pCon,"ERROR: out of memory in MakeMultiCounterSec",eError);
return 0;
} else {
SetHdbProperty(child, "__save", "true");
AddHipadabaChild(node, child, NULL);
}
child = MakeSICSHdbPar("ccd", usMugger, MakeHdbInt(0));
if (child == NULL) {
SCWrite(pCon,"ERROR: out of memory in MakeMultiCounterSec",eError);
return 0;
} else {
SetHdbProperty(child, "__save", "true");
AddHipadabaChild(node, child, NULL);
}
child = MakeSICSHdbPar("stopTime", usInternal, MakeHdbInt(0));
if (child == NULL) {
SCWrite(pCon,"ERROR: out of memory in MakeMultiCounterSec",eError);
return 0;
} else {
AddHipadabaChild(node, child, NULL);
}
child = MakeSICSHdbPar("masterID", usInternal, MakeHdbInt(0));
if (child == NULL) {
SCWrite(pCon,"ERROR: out of memory in MakeMultiCounterSec",eError);
return 0;
} else {
AddHipadabaChild(node, child, NULL);
}
child = MakeSICSHdbPar("slaveID", usInternal, MakeHdbInt(0));
if (child == NULL) {
SCWrite(pCon,"ERROR: out of memory in MakeMultiCounterSec",eError);
return 0;
} else {
AddHipadabaChild(node, child, NULL);
}
status =
AddCommand(pSics, argv[1], MultiInvokeSICSOBJ, DeleteCounter,
(void *) pRes);
if (status != 1) {
SCPrintf(pCon,eError, "ERROR: duplicate command %s not created", argv[1]);
return 0;
}
return 1;
}

5
mumo.c
View File

@ -683,6 +683,9 @@ static void RecoverNamPos(pMulMot self, int argc, char *argv[])
decrement, increment and simple values.
DingsBums pos name - makes the current position a named
position with name name.
DingsBums defpos name [alias value..] - makes a named
position with name name. The par is a list of alias value
pairs with the appropriate positions for name.
DingsBums getpos - gets the current named position
DingsBums drop name - deletes the current named position
name.
@ -841,7 +844,7 @@ int MultiWrapper(SConnection * pCon, SicsInterp * pSics, void *pData,
case RECOVERNAMPOS:
/*
This is not meant to be user command but a facility to read
back data from sattus file. This is why the error checking
back data from status file. This is why the error checking
is not happening
*/
RecoverNamPos(self, argc - 2, &argv[2]);

View File

@ -158,28 +158,6 @@ static int GetNextToken(psParser self)
return UNKNOWN;
}
/*--------------------------------------------------------------------------
in this code we need to find a motor for a name quite frequently.......
*/
pMotor FindMotor(SicsInterp * pSics, char *name)
{
CommandList *pC;
pMotor pMot;
pC = FindCommand(pSics, name);
if (!pC) {
return NULL;
}
pMot = (pMotor) pC->pData;
if (!pMot) {
return NULL;
}
if (strcmp(pMot->pDescriptor->name, "Motor") != 0) {
return NULL;
}
return pMot;
}
/*--------------------------------------------------------------------------*/
int MakeMulti(SConnection * pCon, SicsInterp * pSics, void *pData,

2133
napi.c

File diff suppressed because it is too large Load Diff

967
napi.h
View File

@ -1,967 +0,0 @@
/*---------------------------------------------------------------------------
NeXus - Neutron & X-ray Common Data Format
Application Program Interface Header File
Copyright (C) 2000-2011 Mark Koennecke, Uwe Filges
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
For further information, see <http://www.nexusformat.org>
$Id$
----------------------------------------------------------------------------*/
/** \file
* Documentation for the NeXus-API version 4.3
* 2000-2011, the NeXus International Advisory Commitee
* \defgroup c_main C API
* \defgroup c_types Data Types
* \ingroup c_main
* \defgroup c_init General Initialisation and shutdown
* \ingroup c_main
* \defgroup c_group Reading and Writing Groups
* \ingroup c_main
* \defgroup c_readwrite Reading and Writing Data
* \ingroup c_main
* \defgroup c_navigation General File navigation
* \ingroup c_main
* \defgroup c_metadata Meta data routines
* \ingroup c_main
* \defgroup c_linking Linking
* \ingroup c_main
* \defgroup c_memory Memory allocation
* \ingroup c_main
* \defgroup c_external External linking
* \ingroup c_main
*/
#ifndef NEXUSAPI
#define NEXUSAPI
#include <stdint.h>
/* NeXus HDF45 */
#define NEXUS_VERSION "4.3.0" /* major.minor.patch */
#define H5Eset_auto_vers 2
#define H5Dopen_vers 2
#define H5Gopen_vers 2
#define H5Acreate_vers 2
#define H5Dcreate_vers 2
#define H5Gcreate_vers 2
#define H5Aiterate_vers 2
#define CONSTCHAR const char
typedef void* NXhandle; /* really a pointer to a NexusFile structure */
typedef int NXstatus;
typedef char NXname[128];
/*
* Any new NXaccess_mode options should be numbered in 2^n format
* (8, 16, 32, etc) so that they can be bit masked and tested easily.
*
* To test older non bit masked options (values below 8) use e.g.
*
* if ( (mode & NXACCMASK_REMOVEFLAGS) == NXACC_CREATE )
*
* To test new (>=8) options just use normal bit masking e.g.
*
* if ( mode & NXACC_NOSTRIP )
*
*/
#define NXACCMASK_REMOVEFLAGS (0x7) /* bit mask to remove higher flag options */
/** \enum NXaccess_mode
* NeXus file access codes.
* \li NXACC_READ read-only
* \li NXACC_RDWR open an existing file for reading and writing.
* \li NXACC_CREATE create a NeXus HDF-4 file
* \li NXACC_CREATE4 create a NeXus HDF-4 file
* \li NXACC_CREATE5 create a NeXus HDF-5 file.
* \li NXACC_CREATEXML create a NeXus XML file.
* \li NXACC_CHECKNAMESYNTAX Check names conform to NeXus allowed characters.
*/
typedef enum {NXACC_READ=1, NXACC_RDWR=2, NXACC_CREATE=3, NXACC_CREATE4=4,
NXACC_CREATE5=5, NXACC_CREATEXML=6, NXACC_TABLE=8, NXACC_NOSTRIP=128, NXACC_CHECKNAMESYNTAX=256 } NXaccess_mode;
/**
* A combination of options from #NXaccess_mode
*/
typedef int NXaccess;
typedef struct {
char *iname;
int type;
}info_type, *pinfo;
#define NX_OK 1
#define NX_ERROR 0
#define NX_EOD -1
#define NX_UNLIMITED -1
#define NX_MAXRANK 32
#define NX_MAXNAMELEN 64
#define NX_MAXPATHLEN 1024
/**
* \ingroup c_types
* \def NX_FLOAT32
* 32 bit float
* \def NX_FLOAT64
* 64 bit float == double
* \def NX_INT8
* 8 bit integer == byte
* \def NX_UINT8
* 8 bit unsigned integer
* \def NX_INT16
* 16 bit integer
* \def NX_UINT16
* 16 bit unsigned integer
* \def NX_INT32
* 32 bit integer
* \def NX_UINT32
* 32 bit unsigned integer
* \def NX_CHAR
* 8 bit character
* \def NX_BINARY
* lump of binary data == NX_UINT8
*/
/*--------------------------------------------------------------------------*/
/* Map NeXus to HDF types */
#define NX_FLOAT32 5
#define NX_FLOAT64 6
#define NX_INT8 20
#define NX_UINT8 21
#define NX_BOOLEAN NX_UINT
#define NX_INT16 22
#define NX_UINT16 23
#define NX_INT32 24
#define NX_UINT32 25
#define NX_INT64 26
#define NX_UINT64 27
#define NX_CHAR 4
#define NX_BINARY 21
/* Map NeXus compression methods to HDF compression methods */
#define NX_CHUNK 0
#define NX_COMP_NONE 100
#define NX_COMP_LZW 200
#define NX_COMP_RLE 300
#define NX_COMP_HUF 400
/* to test for these we use ((value / 100) == NX_COMP_LZW) */
#define NX_COMP_LZW_LVL0 (100*NX_COMP_LZW + 0)
#define NX_COMP_LZW_LVL1 (100*NX_COMP_LZW + 1)
#define NX_COMP_LZW_LVL2 (100*NX_COMP_LZW + 2)
#define NX_COMP_LZW_LVL3 (100*NX_COMP_LZW + 3)
#define NX_COMP_LZW_LVL4 (100*NX_COMP_LZW + 4)
#define NX_COMP_LZW_LVL5 (100*NX_COMP_LZW + 5)
#define NX_COMP_LZW_LVL6 (100*NX_COMP_LZW + 6)
#define NX_COMP_LZW_LVL7 (100*NX_COMP_LZW + 7)
#define NX_COMP_LZW_LVL8 (100*NX_COMP_LZW + 8)
#define NX_COMP_LZW_LVL9 (100*NX_COMP_LZW + 9)
typedef struct {
long iTag; /* HDF4 variable */
long iRef; /* HDF4 variable */
char targetPath[1024]; /* path to item to link */
int linkType; /* HDF5: 0 for group link, 1 for SDS link */
} NXlink;
#define NXMAXSTACK 50
#define CONCAT(__a,__b) __a##__b /* token concatenation */
# ifdef __VMS
# define MANGLE(__arg) __arg
# else
# define MANGLE(__arg) CONCAT(__arg,_)
# endif
# define NXopen MANGLE(nxiopen)
# define NXreopen MANGLE(nxireopen)
# define NXclose MANGLE(nxiclose)
# define NXmakegroup MANGLE(nximakegroup)
# define NXopengroup MANGLE(nxiopengroup)
# define NXopenpath MANGLE(nxiopenpath)
# define NXgetpath MANGLE(nxigetpath)
# define NXopengrouppath MANGLE(nxiopengrouppath)
# define NXclosegroup MANGLE(nxiclosegroup)
# define NXmakedata MANGLE(nximakedata)
# define NXmakedata64 MANGLE(nximakedata64)
# define NXcompmakedata MANGLE(nxicompmakedata)
# define NXcompmakedata64 MANGLE(nxicompmakedata64)
# define NXcompress MANGLE(nxicompress)
# define NXopendata MANGLE(nxiopendata)
# define NXclosedata MANGLE(nxiclosedata)
# define NXputdata MANGLE(nxiputdata)
# define NXputslab MANGLE(nxiputslab)
# define NXputslab64 MANGLE(nxiputslab64)
# define NXputattr MANGLE(nxiputattr)
# define NXgetdataID MANGLE(nxigetdataid)
# define NXmakelink MANGLE(nximakelink)
# define NXmakenamedlink MANGLE(nximakenamedlink)
# define NXopensourcegroup MANGLE(nxiopensourcegroup)
# define NXmalloc MANGLE(nximalloc)
# define NXmalloc64 MANGLE(nximalloc64)
# define NXfree MANGLE(nxifree)
# define NXflush MANGLE(nxiflush)
# define NXgetinfo MANGLE(nxigetinfo)
# define NXgetinfo64 MANGLE(nxigetinfo64)
# define NXgetrawinfo MANGLE(nxigetrawinfo)
# define NXgetrawinfo64 MANGLE(nxigetrawinfo64)
# define NXgetnextentry MANGLE(nxigetnextentry)
# define NXgetdata MANGLE(nxigetdata)
# define NXgetslab MANGLE(nxigetslab)
# define NXgetslab64 MANGLE(nxigetslab64)
# define NXgetnextattr MANGLE(nxigetnextattr)
# define NXgetattr MANGLE(nxigetattr)
# define NXgetattrinfo MANGLE(nxigetattrinfo)
# define NXgetgroupID MANGLE(nxigetgroupid)
# define NXgetgroupinfo MANGLE(nxigetgroupinfo)
# define NXsameID MANGLE(nxisameid)
# define NXinitgroupdir MANGLE(nxiinitgroupdir)
# define NXinitattrdir MANGLE(nxiinitattrdir)
# define NXsetnumberformat MANGLE(nxisetnumberformat)
# define NXsetcache MANGLE(nxisetcache)
# define NXinquirefile MANGLE(nxiinquirefile)
# define NXisexternalgroup MANGLE(nxiisexternalgroup)
# define NXisexternaldataset MANGLE(nxiisexternaldataset)
# define NXlinkexternal MANGLE(nxilinkexternal)
# define NXlinkexternaldataset MANGLE(nxilinkexternaldataset)
# define NXgetversion MANGLE(nxigetversion)
/*
* FORTRAN helpers - for NeXus internal use only
*/
# define NXfopen MANGLE(nxifopen)
# define NXfclose MANGLE(nxifclose)
# define NXfflush MANGLE(nxifflush)
# define NXfmakedata MANGLE(nxifmakedata)
# define NXfcompmakedata MANGLE(nxifcompmakedata)
# define NXfcompress MANGLE(nxifcompress)
# define NXfputattr MANGLE(nxifputattr)
# define NXfgetpath MANGLE(nxifgetpath)
/*
* Standard interface
*
* Functions added here are not automatically exported from
* a shared library/dll - the symbol name must also be added
* to the file src/nexus_symbols.txt
*
*/
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
/**
* Open a NeXus file.
* NXopen honours full path file names. But it also searches
* for files in all the paths given in the NX_LOAD_PATH environment variable.
* NX_LOAD_PATH is supposed to hold a list of path string separated by the platform
* specific path separator. For unix this is the : , for DOS the ; . Please note
* that crashing on an open NeXus file will result in corrupted data. Only after a NXclose
* or a NXflush will the data file be valid.
* \param filename The name of the file to open
* \param access_method The file access method. This can be:
* \li NXACC__READ read access
* \li NXACC_RDWR read write access
* \li NXACC_CREATE, NXACC_CREATE4 create a new HDF-4 NeXus file
* \li NXACC_CREATE5 create a new HDF-5 NeXus file
* \li NXACC_CREATEXML create an XML NeXus file.
* see #NXaccess_mode
* Support for HDF-4 is deprecated.
* \param pHandle A file handle which will be initialized upon successfull completeion of NXopen.
* \return NX_OK on success, NX_ERROR in the case of an error.
* \ingroup c_init
*/
extern NXstatus NXopen(CONSTCHAR * filename, NXaccess access_method, NXhandle* pHandle);
/**
* Opens an existing NeXus file a second time for e.g. access from another thread.
* \return NX_OK on success, NX_ERROR in the case of an error.
* \ingroup c_init
*/
extern NXstatus NXreopen(NXhandle pOrigHandle, NXhandle* pNewHandle);
/**
* close a NeXus file
* \param pHandle A NeXus file handle as returned from NXopen. pHandle is invalid after this
* call.
* \return NX_OK on success, NX_ERROR in the case of an error.
* \ingroup c_init
*/
extern NXstatus NXclose(NXhandle* pHandle);
/**
* flush data to disk
* \param pHandle A NeXus file handle as initialized by NXopen.
* \return NX_OK on success, NX_ERROR in the case of an error.
* \ingroup c_readwrite
*/
extern NXstatus NXflush(NXhandle* pHandle);
/**
* NeXus groups are NeXus way of structuring information into a hierarchy.
* This function creates a group but does not open it.
* \param handle A NeXus file handle as initialized NXopen.
* \param name The name of the group
* \param NXclass the class name of the group. Should start with the prefix NX
* \return NX_OK on success, NX_ERROR in the case of an error.
* \ingroup c_group
*/
extern NXstatus NXmakegroup (NXhandle handle, CONSTCHAR *name, CONSTCHAR* NXclass);
/**
* Step into a group. All further access will be within the opened group.
* \param handle A NeXus file handle as initialized by NXopen.
* \param name The name of the group
* \param NXclass the class name of the group. Should start with the prefix NX
* \return NX_OK on success, NX_ERROR in the case of an error.
* \ingroup c_group
*/
extern NXstatus NXopengroup (NXhandle handle, CONSTCHAR *name, CONSTCHAR* NXclass);
/**
* Open the NeXus object with the path specified
* \param handle A NeXus file handle as returned from NXopen.
* \param path A unix like path string to a NeXus group or dataset. The path string
* is a list of group names and SDS names separated with / (slash).
* Example: /entry1/sample/name
* \return NX_OK on success, NX_ERROR in the case of an error.
* \ingroup c_navigation
*/
extern NXstatus NXopenpath (NXhandle handle, CONSTCHAR *path);
/**
* Opens the group in which the NeXus object with the specified path exists
* \param handle A NeXus file handle as initialized by NXopen.
* \param path A unix like path string to a NeXus group or dataset. The path string
* is a list of group names and SDS names separated with / (slash).
* Example: /entry1/sample/name
* \return NX_OK on success, NX_ERROR in the case of an error.
* \ingroup c_navigation
*/
extern NXstatus NXopengrouppath (NXhandle handle, CONSTCHAR *path);
/**
* Retrieve the current path in the NeXus file
* \param handle a NeXus file handle
* \param path A buffer to copy the path too
* \param pathlen The maximum number of characters to copy into path
* \return NX_OK or NX_ERROR
* \ingroup c_navigation
*/
extern NXstatus NXgetpath(NXhandle handle, char *path, int pathlen);
/**
* Closes the currently open group and steps one step down in the NeXus file
* hierarchy.
* \return NX_OK on success, NX_ERROR in the case of an error.
* \ingroup c_group
*/
extern NXstatus NXclosegroup(NXhandle handle);
/**
* Create a multi dimensional data array or dataset. The dataset is NOT opened.
* \param handle A NeXus file handle as initialized by NXopen.
* \param label The name of the dataset
* \param datatype The data type of this data set.
* \param rank The number of dimensions this dataset is going to have
* \param dim An array of size rank holding the size of the dataset in each dimension. The first dimension
* can be NX_UNLIMITED. Data can be appended to such a dimension using NXputslab.
* \return NX_OK on success, NX_ERROR in the case of an error.
* \ingroup c_readwrite
*/
extern NXstatus NXmakedata (NXhandle handle, CONSTCHAR* label, int datatype, int rank, int dim[]);
/**
* @copydoc NXmakedata()
*/
extern NXstatus NXmakedata64 (NXhandle handle, CONSTCHAR* label, int datatype, int rank, int64_t dim[]);
/**
* Create a compressed dataset. The dataset is NOT opened. Data from this set will automatically be compressed when
* writing and decompressed on reading.
* \param handle A NeXus file handle as initialized by NXopen.
* \param label The name of the dataset
* \param datatype The data type of this data set.
* \param rank The number of dimensions this dataset is going to have
* \param comp_typ The compression scheme to use. Possible values:
* \li NX_COMP_NONE no compression
* \li NX_COMP_LZW lossless Lempel Ziv Welch compression (recommended)
* \li NX_COMP_RLE run length encoding (only HDF-4)
* \li NX_COMP_HUF Huffmann encoding (only HDF-4)
* \param dim An array of size rank holding the size of the dataset in each dimension. The first dimension
* can be NX_UNLIMITED. Data can be appended to such a dimension using NXputslab.
* \param bufsize The dimensions of the subset of the data which usually be writen in one go.
* This is a parameter used by HDF for performance optimisations. If you write your data in one go, this
* should be the same as the data dimension. If you write it in slabs, this is your preferred slab size.
* \return NX_OK on success, NX_ERROR in the case of an error.
* \ingroup c_readwrite
*/
extern NXstatus NXcompmakedata (NXhandle handle, CONSTCHAR* label, int datatype, int rank, int dim[], int comp_typ, int bufsize[]);
/**
* @copydoc NXcompmakedata()
*/
extern NXstatus NXcompmakedata64 (NXhandle handle, CONSTCHAR* label, int datatype, int rank, int64_t dim[], int comp_typ, int64_t chunk_size[]);
/**
* Switch compression on. This routine is superseeded by NXcompmakedata and thus
* is deprecated.
* \param handle A NeXus file handle as initialized by NXopen.
* \param compr_type The compression scheme to use. Possible values:
* \li NX_COMP_NONE no compression
* \li NX_COMP_LZW lossless Lempel Ziv Welch compression (recommended)
* \li NX_COMP_RLE run length encoding (only HDF-4)
* \li NX_COMP_HUF Huffmann encoding (only HDF-4)
* \ingroup c_readwrite
*/
extern NXstatus NXcompress (NXhandle handle, int compr_type);
/**
* Open access to a dataset. After this call it is possible to write and read data or
* attributes to and from the dataset.
* \param handle A NeXus file handle as initialized by NXopen.
* \param label The name of the dataset
* \return NX_OK on success, NX_ERROR in the case of an error.
* \ingroup c_readwrite
*/
extern NXstatus NXopendata (NXhandle handle, CONSTCHAR* label);
/**
* Close access to a dataset.
* \param handle A NeXus file handle as initialized by NXopen.
* \return NX_OK on success, NX_ERROR in the case of an error.
* \ingroup c_readwrite
*/
extern NXstatus NXclosedata(NXhandle handle);
/**
* Write data to a datset which has previouly been opened with NXopendata.
* This writes all the data in one go. Data should be a pointer to a memory
* area matching the datatype and dimensions of the dataset.
* \param handle A NeXus file handle as initialized by NXopen.
* \param data Pointer to data to write.
* \return NX_OK on success, NX_ERROR in the case of an error.
* \ingroup c_readwrite
*/
extern NXstatus NXputdata(NXhandle handle, const void* data);
/**
* Write an attribute. The kind of attribute written depends on the
* poistion in the file: at root level, a global attribute is written, if
* agroup is open but no dataset, a group attribute is written, if a dataset is
* open, a dataset attribute is written.
* \param handle A NeXus file handle as initialized by NXopen.
* \param name The name of the attribute.
* \param data A pointer to the data to write for the attribute.
* \param iDataLen The length of the data in data in bytes.
* \param iType The NeXus data type of the attribute.
* \return NX_OK on success, NX_ERROR in the case of an error.
* \ingroup c_readwrite
*/
extern NXstatus NXputattr(NXhandle handle, CONSTCHAR* name, const void* data, int iDataLen, int iType);
/**
* Write a subset of a multi dimensional dataset.
* \param handle A NeXus file handle as initialized by NXopen.
* \param data A pointer to a memory area holding the data to write.
* \param start An array holding the start indices where to start the data subset.
* \param size An array holding the size of the data subset to write in each dimension.
* \return NX_OK on success, NX_ERROR in the case of an error.
* \ingroup c_readwrite
*/
extern NXstatus NXputslab(NXhandle handle, const void* data, const int start[], const int size[]);
/**
* @copydoc NXputdata()
*/
extern NXstatus NXputslab64(NXhandle handle, const void* data, const int64_t start[], const int64_t size[]);
/**
* Retrieve link data for a dataset. This link data can later on be used to link this
* dataset into a different group.
* \param handle A NeXus file handle as initialized by NXopen.
* \param pLink A link data structure which will be initialized with the required information
* for linking.
* \return NX_OK on success, NX_ERROR in the case of an error.
* \ingroup c_linking
*/
extern NXstatus NXgetdataID(NXhandle handle, NXlink* pLink);
/**
* Create a link to the group or dataset described by pLink in the currently open
* group.
* \param handle A NeXus file handle as initialized by NXopen.
* \param pLink A link data structure describing the object to link. This must have been initialized
* by either a call to NXgetdataID or NXgetgroupID.
* \return NX_OK on success, NX_ERROR in the case of an error.
* \ingroup c_linking
*/
extern NXstatus NXmakelink(NXhandle handle, NXlink* pLink);
/**
* Create a link to the group or dataset described by pLink in the currently open
* group. But give the linked item a new name.
* \param handle A NeXus file handle as initialized by NXopen.
* \param newname The new name of the item in the currently open group.
* \param pLink A link data structure describing the object to link. This must have been initialized
* by either a call to NXgetdataID or NXgetgroupID.
* \return NX_OK on success, NX_ERROR in the case of an error.
* \ingroup c_linking
*/
extern NXstatus NXmakenamedlink(NXhandle handle, CONSTCHAR* newname, NXlink* pLink);
/**
* Open the source group of a linked group or dataset. Returns an error when the item is
* not a linked item.
* \param handle A NeXus file handle as initialized by NXopen.
* \return NX_OK on success, NX_ERROR in the case of an error.
* \ingroup c_navigation
*/
extern NXstatus NXopensourcegroup(NXhandle handle);
/**
* Read a complete dataset from the currently open dataset into memory.
* \param handle A NeXus file handle as initialized by NXopen.
* \param data A pointer to the memory area where to read the data, too. Data must point to a memory
* area large enough to accomodate the data read. Otherwise your program may behave in unexpected
* and unwelcome ways.
* \return NX_OK on success, NX_ERROR in the case of an error.
* \ingroup c_readwrite
*/
extern NXstatus NXgetdata(NXhandle handle, void* data);
/**
* Retrieve information about the curretly open dataset.
* \param handle A NeXus file handle as initialized by NXopen.
* \param rank A pointer to an integer which will be filled with the rank of
* the dataset.
* \param dimension An array which will be initialized with the size of the dataset in any of its
* dimensions. The array must have at least the size of rank.
* \param datatype A pointer to an integer which be set to the NeXus data type code for this dataset.
* \return NX_OK on success, NX_ERROR in the case of an error.
* \ingroup c_metadata
*/
extern NXstatus NXgetinfo(NXhandle handle, int* rank, int dimension[], int* datatype);
/**
* @copydoc NXgetinfo()
*/
extern NXstatus NXgetinfo64(NXhandle handle, int* rank, int64_t dimension[], int* datatype);
/**
* Get the next entry in the currently open group. This is for retrieving infromation about the
* content of a NeXus group. In order to search a group #NXgetnextentry is called in a loop until
* #NXgetnextentry returns NX_EOD which indicates that there are no further items in the group.
* Reset search using #NXinitgroupdir
* \param handle A NeXus file handle as initialized by NXopen.
* \param name The name of the object
* \param nxclass The NeXus class name for a group or the string SDS for a dataset.
* \param datatype The NeXus data type if the item is a SDS.
* \return NX_OK on success, NX_ERROR in the case of an error, NX_EOD when there are no more items.
* \ingroup c_navigation
*/
extern NXstatus NXgetnextentry(NXhandle handle, NXname name, NXname nxclass, int* datatype);
/**
* Read a subset of data from file into memory.
* \param handle A NeXus file handle as initialized by NXopen.
* \param data A pointer to the memory data where to copy the data too. The pointer must point
* to a memory area large enough to accomodate the size of the data read.
* \param start An array holding the start indices where to start reading the data subset.
* \param size An array holding the size of the data subset to read for each dimension.
* \return NX_OK on success, NX_ERROR in the case of an error.
* \ingroup c_readwrite
*/
extern NXstatus NXgetslab(NXhandle handle, void* data, int start[], int size[]);
/**
* @copydoc NXgetslab()
*/
extern NXstatus NXgetslab64(NXhandle handle, void* data, const int64_t start[], const int64_t size[]);
/**
* Iterate over global, group or dataset attributes depending on the currently open group or
* dataset. In order to search attributes multiple calls to #NXgetnextattr are performed in a loop
* until #NXgetnextattr returns NX_EOD which indicates that there are no further attributes.
* reset search using #NXinitattrdir
* \param handle A NeXus file handle as initialized by NXopen.
* \param pName The name of the attribute
* \param iLength A pointer to an integer which be set to the length of the attribute data.
* \param iType A pointer to an integer which be set to the NeXus data type of the attribute.
* \return NX_OK on success, NX_ERROR in the case of an error, NX_EOD when there are no more items.
* \ingroup c_readwrite
*/
extern NXstatus NXgetnextattr(NXhandle handle, NXname pName, int *iLength, int *iType);
/**
* Read an attribute.
* \param handle A NeXus file handle as initialized by NXopen.
* \param name The name of the atrribute to read.
* \param data A pointer to a memory area large enough to hold the attributes value.
* \param iDataLen The length of data in bytes.
* \param iType A pointer to an integer which will had been set to the NeXus data type of the attribute.
* \return NX_OK on success, NX_ERROR in the case of an error.
* \ingroup c_readwrite
*/
extern NXstatus NXgetattr(NXhandle handle, char* name, void* data, int* iDataLen, int* iType);
/**
* Get the count of attributes in the currently open dataset, group or global attributes when at root level.
* \param handle A NeXus file handle as initialized by NXopen.
* \param no_items A pointer to an integer which be set to the number of attributes available.
* \return NX_OK on success, NX_ERROR in the case of an error.
* \ingroup c_metadata
*/
extern NXstatus NXgetattrinfo(NXhandle handle, int* no_items);
/**
* Retrieve link data for the currently open group. This link data can later on be used to link this
* group into a different group.
* \param handle A NeXus file handle as initialized by NXopen.
* \param pLink A link data structure which will be initialized with the required information
* for linking.
* \return NX_OK on success, NX_ERROR in the case of an error.
* \ingroup c_linking
*/
extern NXstatus NXgetgroupID(NXhandle handle, NXlink* pLink);
/**
* Retrieve information about the currently open group.
* \param handle A NeXus file handle as initialized by NXopen.
* \param no_items A pointer to an integer which will be set to the count
* of group elements available. This is the count of other groups and
* data sets in this group.
* \param name The name of the group.
* \param nxclass The NeXus class name of the group.
* \return NX_OK on success, NX_ERROR in the case of an error.
* \ingroup c_metadata
*/
extern NXstatus NXgetgroupinfo(NXhandle handle, int* no_items, NXname name, NXname nxclass);
/**
* Tests if two link data structures describe the same item.
* \param handle A NeXus file handle as initialized by NXopen.
* \param pFirstID The first link data for the test.
* \param pSecondID The second link data structure.
* \return NX_OK when both link data structures describe the same item, NX_ERROR else.
* \ingroup c_linking
*/
extern NXstatus NXsameID(NXhandle handle, NXlink* pFirstID, NXlink* pSecondID);
/**
* Resets a pending group search to the start again. To be called in a #NXgetnextentry loop when
* a group search has to be restarted.
* \param handle A NeXus file handle as initialized by NXopen.
* \return NX_OK on success, NX_ERROR in the case of an error.
* \ingroup c_navigation
*/
extern NXstatus NXinitgroupdir(NXhandle handle);
/**
* Resets a pending attribute search to the start again. To be called in a #NXgetnextattr loop when
* an attribute search has to be restarted.
* \param handle A NeXus file handle as initialized by NXopen.
* \return NX_OK on success, NX_ERROR in the case of an error.
* \ingroup c_navigation
*/
extern NXstatus NXinitattrdir(NXhandle handle);
/**
* Sets the format for number printing. This call has only an effect when using the XML physical file
* format.
* \param handle A NeXus file handle as initialized by NXopen.
* \param type The NeXus data type to set the format for.
* \param format The C-language format string to use for this data type.
* \return NX_OK on success, NX_ERROR in the case of an error.
* \ingroup c_readwrite
*/
extern NXstatus NXsetnumberformat(NXhandle handle, int type, char *format);
/**
* Inquire the filename of the currently open file. FilenameBufferLength of the file name
* will be copied into the filename buffer.
* \param handle A NeXus file handle as initialized by NXopen.
* \param filename The buffer to hold the filename.
* \param filenameBufferLength The length of the filename buffer.
* \return NX_OK on success, NX_ERROR in the case of an error.
* \ingroup c_metadata
*/
extern NXstatus NXinquirefile(NXhandle handle, char *filename, int filenameBufferLength);
/**
* Test if a group is actually pointing to an external file. If so, retrieve the URL of the
* external file.
* \param handle A NeXus file handle as initialized by NXopen.
* \param name The name of the group to test.
* \param nxclass The class name of the group to test.
* \param url A buffer to copy the URL too.
* \param urlLen The length of the Url buffer. At maximum urlLen bytes will be copied to url.
* \return NX_OK when the group is pointing to an external file, NX_ERROR else.
* \ingroup c_external
*/
extern NXstatus NXisexternalgroup(NXhandle handle, CONSTCHAR *name, CONSTCHAR *nxclass, char *url, int urlLen);
/**
* Test if a dataset is actually pointing to an external file. If so, retrieve the URL of the
* external file.
* \param handle A NeXus file handle as initialized by NXopen.
* \param name The name of the dataset to test.
* \param url A buffer to copy the URL too.
* \param urlLen The length of the Url buffer. At maximum urlLen bytes will be copied to url.
* \return NX_OK when the dataset is pointing to an external file, NX_ERROR else.
* \ingroup c_external
*/
extern NXstatus NXisexternaldataset(NXhandle handle, CONSTCHAR *name, char *url, int urlLen);
/**
* Create a link to a group in an external file. This works by creating a NeXus group under the current level in
* the hierarchy which actually points to a group in another file.
* \param handle A NeXus file handle as initialized by NXopen.
* \param name The name of the group which points to the external file.
* \param nxclass The class name of the group which points to the external file.
* \param url The URL of the external file. Currently only one URL format is supported: nxfile://path-tofile\#path-in-file.
* This consists of two parts: the first part is of course the path to the file. The second part, path-in-file, is the
* path to the group in the external file which appears in the first file.
* \return NX_OK on success, NX_ERROR in the case of an error.
* \ingroup c_external
*/
extern NXstatus NXlinkexternal(NXhandle handle, CONSTCHAR *name, CONSTCHAR *nxclass, CONSTCHAR *url);
/**
* Create a link to a dataset in an external file. This works by creating a dataset under the current level in
* the hierarchy which actually points to a dataset in another file.
* \param handle A NeXus file handle as initialized by NXopen.
* \param name The name of the dataset which points to the external file.
* \param url The URL of the external file. Currently only one URL format is supported: nxfile://path-tofile\#path-in-file.
* This consists of two parts: the first part is of course the path to the file. The second part, path-in-file, is the
* path to the dataset in the external file which appears in the first file.
* \return NX_OK on success, NX_ERROR in the case of an error.
* \ingroup c_external
*/
extern NXstatus NXlinkexternaldataset(NXhandle handle, CONSTCHAR *name, CONSTCHAR *url);
/**
* Utility function which allocates a suitably sized memory area for the dataset characteristics specified.
* \param data A pointer to a pointer which will be initialized with a pointer to a suitably sized memory area.
* \param rank the rank of the data.
* \param dimensions An array holding the size of the data in each dimension.
* \param datatype The NeXus data type of the data.
* \return NX_OK when allocation succeeds, NX_ERROR in the case of an error.
* \ingroup c_memory
*/
extern NXstatus NXmalloc(void** data, int rank, int dimensions[], int datatype);
/**
* @copydoc NXmalloc()
*/
extern NXstatus NXmalloc64(void** data, int rank, int64_t dimensions[], int datatype);
/**
* Utility function to return NeXus version
* \return pointer to string in static storage. Version in
* same format as NEXUS_VERSION string in napi.h i.e. "major.minor.patch"
* \ingroup c_metadata
*/
extern const char* NXgetversion();
/**
* Utility function to release the memory for data.
* \param data A pointer to a pointer to free.
* \return NX_OK on success, NX_ERROR in the case of an error.
* \ingroup c_memory
*/
extern NXstatus NXfree(void** data);
/*-----------------------------------------------------------------------
NAPI internals
------------------------------------------------------------------------*/
/**
* Retrieve information about the currently open dataset. In contrast to the main function below,
* this function does not try to find out about the size of strings properly.
* \param handle A NeXus file handle as initialized by NXopen.
* \param rank A pointer to an integer which will be filled with the rank of
* the dataset.
* \param dimension An array which will be initialized with the size of the dataset in any of its
* dimensions. The array must have at least the size of rank.
* \param datatype A pointer to an integer which be set to the NeXus data type code for this dataset.
* \return NX_OK on success, NX_ERROR in the case of an error.
* \ingroup c_metadata
*/
extern NXstatus NXgetrawinfo(NXhandle handle, int* rank, int dimension[], int* datatype);
/**
* @copydoc NXgetrawinfo
*/
extern NXstatus NXgetrawinfo64(NXhandle handle, int* rank, int64_t dimension[], int* datatype);
/** \typedef void (*ErrFunc)(void *data, char *text)
* All NeXus error reporting happens through this special function, the
* ErrFunc. The NeXus-API allows to replace this error reporting function
* through a user defined implementation. The default error function prints to stderr. User
* defined ones may pop up dialog boxes or whatever.
* \param data A pointer to some user defined data structure
* \param text The text of the error message to display.
*/
typedef void (*ErrFunc)(void *data, char *text);
/**
* Set a global error function.
* Not threadsafe.
* \param pData A pointer to a user defined data structure which be passed to
* the error display function.
* \param newErr The new error display function.
*/
extern void NXMSetError(void *pData, ErrFunc newErr);
/**
* Set an error function for the current thread.
* When used this overrides anything set in NXMSetError (for the current thread).
* Use this method in threaded applications.
* \param pData A pointer to a user defined data structure which be passed to
* the error display function.
* \param newErr The new error display function.
*/
extern void NXMSetTError(void *pData, ErrFunc newErr);
/**
* Retrieve the current error display function
* \return The current error display function.
*/
extern ErrFunc NXMGetError();
/**
* Suppress error reports from the NeXus-API
*/
extern void NXMDisableErrorReporting();
/**
* Enable error reports from the NeXus-API
*/
extern void NXMEnableErrorReporting();
/**
* Dispatches the error message to the error function defined by NXMSetTError
*/
extern void NXReportError(char *text);
/**
* Do not use, first parameter should be set by NXMSetTError
*/
extern void NXIReportError(void *pData,char *text);
/* extern void *NXpData; */
extern char *NXIformatNeXusTime();
extern NXstatus NXIprintlink(NXhandle fid, NXlink* link);
/**
* A function for setting the default cache size for HDF-5
* \ingroup c_init
*/
extern NXstatus NXsetcache(long newVal);
typedef struct {
NXhandle pNexusData;
NXstatus ( *nxreopen)(NXhandle pOrigHandle, NXhandle* pNewHandle);
NXstatus ( *nxclose)(NXhandle* pHandle);
NXstatus ( *nxflush)(NXhandle* pHandle);
NXstatus ( *nxmakegroup) (NXhandle handle, CONSTCHAR *name, CONSTCHAR* NXclass);
NXstatus ( *nxopengroup) (NXhandle handle, CONSTCHAR *name, CONSTCHAR* NXclass);
NXstatus ( *nxclosegroup)(NXhandle handle);
NXstatus ( *nxmakedata64) (NXhandle handle, CONSTCHAR* label, int datatype, int rank, int64_t dim[]);
NXstatus ( *nxcompmakedata64) (NXhandle handle, CONSTCHAR* label, int datatype, int rank, int64_t dim[], int comp_typ, int64_t bufsize[]);
NXstatus ( *nxcompress) (NXhandle handle, int compr_type);
NXstatus ( *nxopendata) (NXhandle handle, CONSTCHAR* label);
NXstatus ( *nxclosedata)(NXhandle handle);
NXstatus ( *nxputdata)(NXhandle handle, const void* data);
NXstatus ( *nxputattr)(NXhandle handle, CONSTCHAR* name, const void* data, int iDataLen, int iType);
NXstatus ( *nxputslab64)(NXhandle handle, const void* data, const int64_t start[], const int64_t size[]);
NXstatus ( *nxgetdataID)(NXhandle handle, NXlink* pLink);
NXstatus ( *nxmakelink)(NXhandle handle, NXlink* pLink);
NXstatus ( *nxmakenamedlink)(NXhandle handle, CONSTCHAR *newname, NXlink* pLink);
NXstatus ( *nxgetdata)(NXhandle handle, void* data);
NXstatus ( *nxgetinfo64)(NXhandle handle, int* rank, int64_t dimension[], int* datatype);
NXstatus ( *nxgetnextentry)(NXhandle handle, NXname name, NXname nxclass, int* datatype);
NXstatus ( *nxgetslab64)(NXhandle handle, void* data, const int64_t start[], const int64_t size[]);
NXstatus ( *nxgetnextattr)(NXhandle handle, NXname pName, int *iLength, int *iType);
NXstatus ( *nxgetattr)(NXhandle handle, char* name, void* data, int* iDataLen, int* iType);
NXstatus ( *nxgetattrinfo)(NXhandle handle, int* no_items);
NXstatus ( *nxgetgroupID)(NXhandle handle, NXlink* pLink);
NXstatus ( *nxgetgroupinfo)(NXhandle handle, int* no_items, NXname name, NXname nxclass);
NXstatus ( *nxsameID)(NXhandle handle, NXlink* pFirstID, NXlink* pSecondID);
NXstatus ( *nxinitgroupdir)(NXhandle handle);
NXstatus ( *nxinitattrdir)(NXhandle handle);
NXstatus ( *nxsetnumberformat)(NXhandle handle, int type, char *format);
NXstatus ( *nxprintlink)(NXhandle handle, NXlink* link);
NXstatus ( *nxnativeexternallink)(NXhandle handle, CONSTCHAR* name, CONSTCHAR* externalfile, CONSTCHAR* remotetarget);
NXstatus ( *nxnativeinquirefile)(NXhandle handle, char* externalfile, const int filenamelength);
NXstatus ( *nxnativeisexternallink)(NXhandle handle, CONSTCHAR* name, char* url, int urllen);
int stripFlag;
int checkNameSyntax;
} NexusFunction, *pNexusFunction;
/*---------------------*/
extern long nx_cacheSize;
/* FORTRAN internals */
extern NXstatus NXfopen(char * filename, NXaccess* am,
NXhandle pHandle);
extern NXstatus NXfclose (NXhandle pHandle);
extern NXstatus NXfputattr(NXhandle fid, const char *name, const void *data,
int *pDatalen, int *pIType);
extern NXstatus NXfcompress(NXhandle fid, int *compr_type);
extern NXstatus NXfcompmakedata(NXhandle fid, char *name,
int *pDatatype,
int *pRank, int dimensions[],
int *compression_type, int chunk[]);
extern NXstatus NXfmakedata(NXhandle fid, char *name, int *pDatatype,
int *pRank, int dimensions[]);
extern NXstatus NXfflush(NXhandle pHandle);
extern NXstatus NXfgetpath(NXhandle fid, char *path, int *pathlen);
#ifdef __cplusplus
}
#endif /* __cplusplus */
/**
* Freddie Akeroyd 11/8/2009
* Add NeXus schema support - this uses BASE.xsd as the initial file
*/
#define NEXUS_SCHEMA_VERSION "3.1" /**< version of NeXus definition schema */
#define NEXUS_SCHEMA_ROOT "http://definition.nexusformat.org/schema/" /**< XML schema namespace specified by xmlns */
#define NEXUS_SCHEMA_NAMESPACE NEXUS_SCHEMA_ROOT NEXUS_SCHEMA_VERSION /**< XML schema namespace specified by xmlns */
#define NEXUS_SCHEMA_BASE "BASE"
#define NEXUS_SCHEMA_FILE NEXUS_SCHEMA_BASE ".xsd" /**< default schema file for namespace */
#define NEXUS_SCHEMA_URL NEXUS_SCHEMA_NAMESPACE "/" NEXUS_SCHEMA_FILE /**< location of default schema file for namespace */
#endif /*NEXUSAPI*/

1983
napi4.c

File diff suppressed because it is too large Load Diff

60
napi4.h
View File

@ -1,60 +0,0 @@
#ifndef NAPI4_H
#define NAPI4_H
#define NXSIGNATURE 959697
#include "mfhdf.h"
/* #include "napi4.c" */
/*
* HDF4 interface
*/
extern NXstatus NX4open(CONSTCHAR *filename, NXaccess access_method, NXhandle* pHandle);
extern NXstatus NX4close(NXhandle* pHandle);
extern NXstatus NX4flush(NXhandle* pHandle);
extern NXstatus NX4makegroup (NXhandle handle, CONSTCHAR* Vgroup, CONSTCHAR* NXclass);
extern NXstatus NX4opengroup (NXhandle handle, CONSTCHAR* Vgroup, CONSTCHAR* NXclass);
extern NXstatus NX4closegroup(NXhandle handle);
extern NXstatus NX4makedata64 (NXhandle handle, CONSTCHAR* label, int datatype, int rank, int64_t dim[]);
extern NXstatus NX4compmakedata64 (NXhandle handle, CONSTCHAR* label, int datatype, int rank, int64_t dim[], int comp_typ, int64_t bufsize[]);
extern NXstatus NX4compress (NXhandle handle, int compr_type);
extern NXstatus NX4opendata (NXhandle handle, CONSTCHAR* label);
extern NXstatus NX4closedata(NXhandle handle);
extern NXstatus NX4getdata(NXhandle handle, void* data);
extern NXstatus NX4getslab64(NXhandle handle, void* data, const int64_t start[], const int64_t size[]);
extern NXstatus NX4getattr(NXhandle handle, char* name, void* data, int* iDataLen, int* iType);
extern NXstatus NX4putdata(NXhandle handle, const void* data);
extern NXstatus NX4putslab64(NXhandle handle, const void* data, const int64_t start[], const int64_t size[]);
extern NXstatus NX4putattr(NXhandle handle, CONSTCHAR* name, const void* data, int iDataLen, int iType);
extern NXstatus NX4getinfo64(NXhandle handle, int* rank, int64_t dimension[], int* datatype);
extern NXstatus NX4getgroupinfo(NXhandle handle, int* no_items, NXname name, NXname nxclass);
extern NXstatus NX4initgroupdir(NXhandle handle);
extern NXstatus NX4getnextentry(NXhandle handle, NXname name, NXname nxclass, int* datatype);
extern NXstatus NX4getattrinfo(NXhandle handle, int* no_items);
extern NXstatus NX4initattrdir(NXhandle handle);
extern NXstatus NX4getnextattr(NXhandle handle, NXname pName, int *iLength, int *iType);
extern NXstatus NX4getgroupID(NXhandle handle, NXlink* pLink);
extern NXstatus NX4getdataID(NXhandle handle, NXlink* pLink);
extern NXstatus NX4makelink(NXhandle handle, NXlink* pLink);
extern NXstatus NX4printlink(NXhandle handle, NXlink* pLink);
void NX4assignFunctions(pNexusFunction fHandle);
/*
* HDF changed from MAX_VAR_DIMS to H4_MAX_VAR_DIMS aronud 9/5/2007
* to avoid potential conflicts with NetCDF-3 library
*/
#ifndef H4_MAX_VAR_DIMS
#define H4_MAX_VAR_DIMS MAX_VAR_DIMS
#endif
#endif /* NAPI4_H */

2301
napi5.c

File diff suppressed because it is too large Load Diff

54
napi5.h
View File

@ -1,54 +0,0 @@
#ifndef NAPI5_H
#define NAPI5_H
#define NX5SIGNATURE 959695
#include <hdf5.h>
/* HDF5 interface */
extern NXstatus NX5open(CONSTCHAR *filename, NXaccess access_method, NXhandle* pHandle);
extern NXstatus NX5reopen(NXhandle pOrigHandle, NXhandle* pNewHandle);
extern NXstatus NX5close(NXhandle* pHandle);
extern NXstatus NX5flush(NXhandle* pHandle);
extern NXstatus NX5makegroup (NXhandle handle, CONSTCHAR *name, CONSTCHAR* NXclass);
extern NXstatus NX5opengroup (NXhandle handle, CONSTCHAR *name, CONSTCHAR* NXclass);
extern NXstatus NX5closegroup(NXhandle handle);
extern NXstatus NX5makedata64 (NXhandle handle, CONSTCHAR* label, int datatype, int rank, int64_t dim[]);
extern NXstatus NX5compmakedata64 (NXhandle handle, CONSTCHAR* label, int datatype, int rank, int64_t dim[], int comp_typ, int64_t bufsize[]);
extern NXstatus NX5compress (NXhandle handle, int compr_type);
extern NXstatus NX5opendata (NXhandle handle, CONSTCHAR* label);
extern NXstatus NX5closedata(NXhandle handle);
extern NXstatus NX5putdata(NXhandle handle, const void* data);
extern NXstatus NX5putattr(NXhandle handle, CONSTCHAR* name, const void* data, int iDataLen, int iType);
extern NXstatus NX5putslab64(NXhandle handle, const void* data, const int64_t start[], const int64_t size[]);
extern NXstatus NX5getdataID(NXhandle handle, NXlink* pLink);
extern NXstatus NX5makelink(NXhandle handle, NXlink* pLink);
extern NXstatus NX5printlink(NXhandle handle, NXlink* pLink);
extern NXstatus NX5getdata(NXhandle handle, void* data);
extern NXstatus NX5getinfo64(NXhandle handle, int* rank, int64_t dimension[], int* datatype);
extern NXstatus NX5getnextentry(NXhandle handle, NXname name, NXname nxclass, int* datatype);
extern NXstatus NX5getslab64(NXhandle handle, void* data, const int64_t start[], const int64_t size[]);
extern NXstatus NX5getnextattr(NXhandle handle, NXname pName, int *iLength, int *iType);
extern NXstatus NX5getattr(NXhandle handle, char* name, void* data, int* iDataLen, int* iType);
extern NXstatus NX5getattrinfo(NXhandle handle, int* no_items);
extern NXstatus NX5getgroupID(NXhandle handle, NXlink* pLink);
extern NXstatus NX5getgroupinfo(NXhandle handle, int* no_items, NXname name, NXname nxclass);
extern NXstatus NX5initgroupdir(NXhandle handle);
extern NXstatus NX5initattrdir(NXhandle handle);
void NX5assignFunctions(pNexusFunction fHandle);
herr_t attr_info(hid_t loc_id, const char *name, const H5A_info_t *unused, void *opdata);
herr_t group_info(hid_t loc_id, const char *name, const H5L_info_t *unused, void *opdata);
herr_t nxgroup_info(hid_t loc_id, const char *name, const H5L_info_t *unused, void *op_data);
#endif /* NAPI5_H */

View File

@ -67,7 +67,7 @@ struct timeval lastclose = { -1, 0 };
/*-----------------------------------------------------------------------
Redefine this function if another means of error reporting is necessary.
*/
static void NetError(char *pText)
static void NetError(const char pText[])
{
/*
SICSLogWrite(pText,eError);
@ -287,8 +287,9 @@ mkChannel *NETConnectWithFlags(char *name, int port, int flags)
iRet = connect(pRes->sockid, (struct sockaddr *) &(pRes->adresse),
sizeof(struct sockaddr_in));
if (iRet < 0) {
if (iRet < 0 && errno ) {
if (errno != EINPROGRESS) {
close(pRes->sockid);
free(pRes);
return NULL;
}
@ -607,7 +608,7 @@ int NETReadTillTerm(mkChannel * self, long timeout,
gettimeofday(&start, NULL);
if (pTerm == NULL)
pTerm = "";
pTerm = strdup("");
length = strlen(pTerm);
memset(pBuffer, 0, iBufLen);
@ -848,8 +849,9 @@ mkChannel *UDPOpen(int iPort)
i = 1;
setsockopt(pRes->sockid, SOL_SOCKET, SO_REUSEADDR, &i, sizeof(int));
assert(pRes->sockid < FD_SETSIZE);
/* if this fails the masks for select will be to
/*
assert(pRes->sockid < (sizeof(long) * 8));
if this fails the masks for select will be to
short.
*/

10
nread.c
View File

@ -1108,6 +1108,7 @@ static int CommandAcceptCB(int handle, void *userData)
{
SConnection *pCon = NULL;
pCommandCBData usData = NULL;
char buffer[80];
pCon = SCreateConnection(pServ->pSics, handle, 3);
usData = malloc(sizeof(CommandCBData));
@ -1122,7 +1123,9 @@ static int CommandAcceptCB(int handle, void *userData)
}
usData->pCon = pCon;
usData->state = COLLECT;
TaskRegister(pServ->pTasker,
snprintf(buffer,sizeof(buffer),"con%ld", pCon->ident);
TaskRegisterN(pServ->pTasker,
buffer,
SCTaskFunction,
SCSignalFunction, SCDeleteConnection, pCon, 1);
ANETsetReadCallback(handle, CommandDataCB, usData, killCommandCBData);
@ -1313,6 +1316,7 @@ static int TelnetAcceptCB(int handle, void *userData)
SConnection *pCon = NULL;
pCommandCBData usData = NULL;
pTelTask pTel = NULL;
char buffer[80];
pCon = SCreateConnection(pServ->pSics, handle, 3);
usData = malloc(sizeof(CommandCBData));
@ -1336,7 +1340,9 @@ static int TelnetAcceptCB(int handle, void *userData)
}
/* register connection and task */
pCon->iTelnet = 1;
TaskRegister(pServ->pTasker,
snprintf(buffer,sizeof(buffer),"con%ld", pCon->ident);
TaskRegisterN(pServ->pTasker,
buffer,
TelnetTask, TelnetSignal, DeleteTelnet, pTel, 1);
ANETsetReadCallback(handle, ANETTelnetProcess,
usData, killCommandCBData);

View File

@ -39,10 +39,6 @@
#include "sicshipadaba.h"
#include "commandlog.h"
int ServerSetupInterrupt(int iPort, pNetRead pNet, pTaskMan pTasker);
/*
configures a port for listening for interrupts
*/
extern int openDevexecLog(); /* in devexec.c */
@ -185,7 +181,8 @@ int InitServer(char *file, pServer * pServ)
assert((pReader =
CreateNetReader(self, iPasswordTimeOut,
iCommandTimeOut)) != NULL);
TaskRegister(self->pTasker, NetReaderTask, NetReaderSignal, NULL, /* call DeleteNetReader later than TaskerDelete */
TaskRegisterN(self->pTasker, "Network Reader",
NetReaderTask, NetReaderSignal, NULL, /* call DeleteNetReader later than TaskerDelete */
pReader, 1);
self->pReader = pReader;
@ -230,7 +227,6 @@ int InitServer(char *file, pServer * pServ)
printf("Cannot find InterruptPort number in options file %s\n",
"This value is required!");
DeleteInterp(self->pSics);
IFDeleteOptions(pSICSOptions);
return 0;
}
iRet = sscanf(pText, "%d", &iPort);
@ -241,26 +237,25 @@ int InitServer(char *file, pServer * pServ)
IFDeleteOptions(pSICSOptions);
return 0;
}
iRet = ServerSetupInterrupt(iPort, pReader, self->pTasker);
if (!iRet) {
SCWrite(pCon, "WARNING: UDP interrupt port not initialized", eWarning);
}
/* install a secret fully priviledged entry point for ME */
AddUser("Achterbahn", "Kiel", usInternal);
/* install a secret entry point for remote objects */
AddUser("RemoteMaster","3ed4c656a15f0aa45e02fd5ec429225bb93b762e7eb06cc81a0b4f6c35c76184",usInternal);
/* install environment monitor */
self->pMonitor = GetEnvMon(self->pSics);
TaskRegister(self->pTasker,
TaskRegisterN(self->pTasker,"EV Monitor",
EnvMonTask, EnvMonSignal, NULL, self->pMonitor, 1);
/* install performance monitor */
pMon = CreatePerfMon(20);
AddCommand(self->pSics, "Performance", PerfMonWrapper, DeletePerfMon,
pMon);
TaskRegister(self->pTasker, PerfMonTask, PerfMonSignal, NULL, pMon, 1);
TaskRegisterN(self->pTasker,"perfmon", PerfMonTask, PerfMonSignal, NULL, pMon, 1);
/* Install a second one for higher granularity measurement */
pMon = CreatePerfMon(2);
TaskRegister(self->pTasker, PerfMonTask, PerfMonSignal, DeletePerfMon, pMon, 1);
TaskRegisterN(self->pTasker,"perfmon2",
PerfMonTask, PerfMonSignal, DeletePerfMon, pMon, 1);
/* install telnet port */
@ -275,6 +270,9 @@ int InitServer(char *file, pServer * pServ)
INIT(StatusFileInit);
/* install status task */
InitStatus();
/* exit handlers need to be installed here */
atexit(StopExit);
(void)Fortify_CheckAllMemory();
@ -350,10 +348,6 @@ void StopServer(pServer self)
/* remove the in memory password database */
KillPasswd();
/* close Interrupt system */
ServerStopInterrupt();
/* Remove Status Callback */
KillStatus(NULL);
@ -471,20 +465,23 @@ int UserWait(SConnection * pCon, SicsInterp * pSics, void *pData,
return 1;
}
eOld = GetStatus();
SetStatus(eUserWait);
sWait.dFinish = DoubleTime() + (double)fVal;
sWait.iEnd = 0;
lID = TaskRegister(pTask, WaitTask, WaitSignal, NULL, &sWait, 1);
TaskWait(pTask, lID);
SetStatus(eOld);
if (SCGetInterrupt(pCon) != eContinue) {
lID = TaskRegisterN(pTask,"wait", WaitTask, WaitSignal, NULL, &sWait, 1);
TaskWait(pTask, lID); if (SCGetInterrupt(pCon) != eContinue) {
return 0;
} else {
return 1;
}
}
/*--------------------------------------------------------------------------*/
int UserYield(SConnection * pCon, SicsInterp * pSics, void *pData,
int argc, char *argv[])
{
TaskYield(pServ->pTasker);
return 1;
}
/*--------------------------------------------------------------------------*/
int SicsWait(long lTime)
{
pTaskMan pTasker = NULL;

View File

@ -47,7 +47,7 @@
/*--------------------------------------------------------------------------
Things defined in napi.c for error reporting
---------------------------------------------------------------------------*/
static void *NXpData = NULL;
void *NXpData = NULL;
/*--------------------------------------------------------------------------*/
/* #define DEFDEBUG 1 */
/* define DEFDEBUG when you wish to print your definition strings before

747
nxio.c
View File

@ -1,747 +0,0 @@
/**
* This file contains functions necessary to perform XML-I/O for
* NeXus with the mxml-library.
*
* Most notably it contains the callback function for reading and
* writing data
*
* Copyright (C) 2004 Mark Koennecke
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* For further information, see <http://www.nexusformat.org>
*/
#ifdef NXXML
#include <mxml.h>
#include <assert.h>
#include "napi.h"
#include "nxio.h"
#include "nxdataset.h"
#include "napiconfig.h"
/* fix for mxml-2.3 */
#ifndef MXML_WRAP
#define MXML_WRAP 79
#endif
#ifdef _MSC_VER
#define snprintf _snprintf
#endif /* _MSC_VER */
/* #define TESTMAIN 1 */
/*=================== type code handling ================================= */
typedef struct {
char name[30];
char format[30];
int nx_type;
}type_code;
#define NTYPECODE 11
static type_code typecode[NTYPECODE];
/*-----------------------------------------------------------------------*/
void initializeNumberFormats(){
type_code myCode;
strcpy(myCode.name,"NX_FLOAT32");
strcpy(myCode.format,"%12.4f");
myCode.nx_type = NX_FLOAT32;
typecode[0] = myCode;
strcpy(myCode.name,"NX_FLOAT64");
strcpy(myCode.format,"%16.5f");
myCode.nx_type = NX_FLOAT64;
typecode[1] = myCode;
strcpy(myCode.name,"NX_INT8");
strcpy(myCode.format,"%5d");
myCode.nx_type = NX_INT8;
typecode[2] = myCode;
strcpy(myCode.name,"NX_UINT8");
strcpy(myCode.format,"%5d");
myCode.nx_type = NX_UINT8;
typecode[3] = myCode;
strcpy(myCode.name,"NX_INT16");
strcpy(myCode.format,"%8d");
myCode.nx_type = NX_INT16;
typecode[4] = myCode;
strcpy(myCode.name,"NX_UINT16");
strcpy(myCode.format,"%8d");
myCode.nx_type = NX_UINT16;
typecode[5] = myCode;
strcpy(myCode.name,"NX_INT32");
strcpy(myCode.format,"%12d");
myCode.nx_type = NX_INT32;
typecode[6] = myCode;
strcpy(myCode.name,"NX_UINT32");
strcpy(myCode.format,"%12d");
myCode.nx_type = NX_UINT32;
typecode[7] = myCode;
strcpy(myCode.name,"NX_INT64");
strcpy(myCode.format,"%24lld");
myCode.nx_type = NX_INT64;
typecode[8] = myCode;
strcpy(myCode.name,"NX_UINT64");
strcpy(myCode.format,"%24llu");
myCode.nx_type = NX_UINT64;
typecode[9] = myCode;
strcpy(myCode.name,"NX_CHAR");
strcpy(myCode.format,"%c");
myCode.nx_type = NX_CHAR;
typecode[10] = myCode;
}
/*----------------------------------------------------------------------*/
void setNumberFormat(int nx_type, char *format){
int i;
for(i = 0; i < NTYPECODE; i++){
if(typecode[i].nx_type == nx_type){
strncpy(typecode[i].format,format,29);
}
}
}
/*------------------------------------------------------------------*/
static void getNumberFormat(int nx_type, char format[30]){
int i;
for(i = 0; i < NTYPECODE; i++){
if(typecode[i].nx_type == nx_type){
strncpy(format,typecode[i].format,29);
}
}
}
/*----------------------------------------------------------------*/
void getNumberText(int nx_type, char *typestring, int typeLen){
int i;
for(i = 0; i < NTYPECODE; i++){
if(typecode[i].nx_type == nx_type){
strncpy(typestring,typecode[i].name,typeLen);
}
}
}
/*
* 'mxml_add_char()' - Add a character to a buffer, expanding as needed.
* copied here from mxml-file.c to achieve compatibility with mxml-2.1
* standard
*/
static int /* O - 0 on success, -1 on error */
myxml_add_char(int ch, /* I - Character to add */
char **bufptr, /* IO - Current position in buffer */
char **buffer, /* IO - Current buffer */
size_t *bufsize) /* IO - Current buffer size */
{
char *newbuffer; /* New buffer value */
if (*bufptr >= (*buffer + *bufsize - 4))
{
/*
* Increase the size of the buffer...
*/
if (*bufsize < 1024)
{
(*bufsize) *= 2;
}
else
{
(*bufsize) *= 3;
(*bufsize) /= 2;
}
newbuffer = (char *)malloc(*bufsize*sizeof(char));
if(!newbuffer){
free(*buffer);
mxml_error("Unable to expand string buffer to %d bytes!", *bufsize);
return (-1);
}
memset(newbuffer,0,*bufsize*sizeof(char));
memcpy(newbuffer,*buffer,*bufptr - *buffer);
free(*buffer);
*bufptr = newbuffer + (*bufptr - *buffer);
*buffer = newbuffer;
}
if (ch < 128)
{
/*
* Single byte ASCII...
*/
*(*bufptr)++ = ch;
}
else if (ch < 2048)
{
/*
* Two-byte UTF-8...
*/
*(*bufptr)++ = 0xc0 | (ch >> 6);
*(*bufptr)++ = 0x80 | (ch & 0x3f);
}
else if (ch < 65536)
{
/*
* Three-byte UTF-8...
*/
*(*bufptr)++ = 0xe0 | (ch >> 12);
*(*bufptr)++ = 0x80 | ((ch >> 6) & 0x3f);
*(*bufptr)++ = 0x80 | (ch & 0x3f);
}
else
{
/*
* Four-byte UTF-8...
*/
*(*bufptr)++ = 0xf0 | (ch >> 18);
*(*bufptr)++ = 0x80 | ((ch >> 12) & 0x3f);
*(*bufptr)++ = 0x80 | ((ch >> 6) & 0x3f);
*(*bufptr)++ = 0x80 | (ch & 0x3f);
}
return (0);
}
/*------------------------------------------------------------------*/
extern char *stptok(char *s, char *tok, size_t toklen, char *brk);
/*=====================================================================
actual stuff for implementing the callback functions
=====================================================================*/
/*
* if passed NX_CHAR, then returns dimension of -1 and the caller
* needs to do a strlen() or equivalent
*/
void analyzeDim(const char *typeString, int *rank,
int64_t *iDim, int *type){
char dimString[132];
char dim[20];
const char *dimStart, *dimEnd;
char* dimTemp;
int myRank;
if(strchr(typeString,(int)'[') == NULL){
*rank = 1;
switch(*type){
case NX_INT8:
case NX_UINT8:
case NX_INT16:
case NX_UINT16:
case NX_INT32:
case NX_UINT32:
case NX_INT64:
case NX_UINT64:
case NX_FLOAT32:
case NX_FLOAT64:
iDim[0] = 1;
break;
case NX_CHAR:
iDim[0] = -1; /* length unknown, caller needs to determine later */
break;
default:
mxml_error("ERROR: (analyzeDim) unknown type code %d for typeString %s", *type, typeString);
break;
}
} else {
/*
we have to determine rank and the dims.
Start by extracting the dimension string.
*/
dimStart = strchr(typeString,(int)'[') + 1;
dimEnd = strchr(typeString,(int)']');
if(!dimStart || !dimEnd) {
mxml_error("ERROR: malformed dimension string in %s",typeString);
return;
}
if((dimEnd - dimStart) > 131){
mxml_error("ERROR: run away dimension definition in %s",typeString);
return;
}
memset(dimString,0,132);
memcpy(dimString,dimStart,(dimEnd-dimStart)*sizeof(char));
dimTemp = stptok(dimString,dim,19,",");
myRank = 0;
while(dimTemp != NULL){
iDim[myRank] = atoi(dim);
dimTemp = stptok(dimTemp,dim,19,",");
myRank++;
}
*rank = myRank;
}
}
/*--------------------------------------------------------------------*/
int translateTypeCode(const char *code){
int i, result = -1;
for(i = 0; i < NTYPECODE; i++){
if(strstr(code,typecode[i].name) != NULL){
result = typecode[i].nx_type;
break;
}
}
return result;
}
/*
* This is used to locate an Idims node from the new style table data layout
*/
static mxml_node_t* findDimsNode(mxml_node_t *node)
{
mxml_node_t *tnode = NULL;
const char* name = node->value.element.name;
if ( (node->parent != NULL) && !strcmp(node->parent->value.element.name, DATA_NODE_NAME) )
{
tnode = mxmlFindElement(node->parent->parent, node->parent->parent, DIMS_NODE_NAME, NULL, NULL, MXML_DESCEND_FIRST);
if (tnode != NULL)
{
tnode = mxmlFindElement(tnode,tnode,name,NULL,NULL,MXML_DESCEND_FIRST);
}
}
return tnode;
}
/*---------------------------------------------------------------------*/
/*return 1 if in table mode , 0 if not */
static void analyzeDataType(mxml_node_t *parent, int *rank, int *type,
int64_t *iDim){
const char *typeString;
mxml_node_t* tnode;
int nx_type = -1;
int table_mode = 0;
*rank = 1;
*type = NX_CHAR;
iDim[0] = -1;
/*
get the type attribute. No attribute means: plain text
*/
tnode = findDimsNode(parent);
if (tnode != NULL)
{
table_mode = 1;
parent = tnode;
}
typeString = mxmlElementGetAttr(parent,TYPENAME);
if(typeString == NULL){
return;
}
nx_type = translateTypeCode((char *)typeString);
/*
assign type
*/
if(nx_type == -1){
mxml_error(
"ERROR: %s is an invalid NeXus type, I try to continue but may fail",
typeString);
*type =NX_CHAR;
return;
}
*type = nx_type;
analyzeDim(typeString, rank, iDim, type);
if (table_mode)
{
*rank = 1;
iDim[0] = 1;
}
return;
}
/*-------------------------------------------------------------------*/
void destroyDataset(void *data){
if(data != NULL){
dropNXDataset((pNXDS)data);
}
}
/*-------------------------------------------------------------------*/
static char *getNextNumber(char *pStart, char pNumber[80]){
int charCount = 0;
pNumber[0] = '\0';
/* advance to first digit */
while(isspace(*pStart) && *pStart != '\0'){
pStart++;
}
if(*pStart == '\0'){
return NULL;
}
/* copy */
while(!isspace(*pStart) && *pStart != '\0' && charCount < 78){
pNumber[charCount] = *pStart;
pStart++;
charCount++;
}
pNumber[charCount] = '\0';
return pStart;
}
/*--------------------------------------------------------------------*/
mxml_type_t nexusTypeCallback(mxml_node_t *parent){
const char *typeString;
if(strstr(parent->value.element.name,"?xml") != NULL ||
!strncmp(parent->value.element.name,"NX",2) ||
!strcmp(parent->value.element.name,DATA_NODE_NAME) ||
!strcmp(parent->value.element.name,DIMS_NODE_NAME)){
return MXML_ELEMENT;
} else {
/* data nodes do not habe TYPENAME in table style but are always CUSTOM */
if (parent->parent != NULL && !strcmp(parent->parent->value.element.name, DATA_NODE_NAME))
{
return MXML_CUSTOM;
}
if (parent->parent != NULL && !strcmp(parent->parent->value.element.name, DIMS_NODE_NAME))
{
return MXML_OPAQUE;
}
typeString = mxmlElementGetAttr(parent,TYPENAME);
if(typeString == NULL){
/*
MXML_TEXT seems more appropriate here. But mxml hacks text into
single words which is not what NeXus wants.
*/
return MXML_OPAQUE;
} else{
if(strstr(typeString,"NX_CHAR") != NULL){
return MXML_OPAQUE;
} else {
return MXML_CUSTOM;
}
}
}
}
/*----------------------------------------------------------------------*/
int nexusLoadCallback(mxml_node_t *node, const char *buffer){
mxml_node_t *parent = NULL;
int rank, type;
int64_t iDim[NX_MAXRANK];
char pNumber[80], *pStart;
long address, maxAddress;
pNXDS dataset = NULL;
parent = node->parent;
analyzeDataType(parent,&rank,&type,iDim);
if(iDim[0] == -1 || !strcmp(parent->parent->value.element.name, DIMS_NODE_NAME)){
iDim[0] = strlen(buffer);
node->value.custom.data = strdup(buffer);
node->value.custom.destroy = free;
return 0;
} else {
node->value.custom.data = createNXDataset(rank,type,iDim);
dataset = (pNXDS)node->value.custom.data;
if(dataset == NULL){
mxml_error("Failed to allocate custom dataset");
return 1;
}
node->value.custom.destroy = destroyDataset;
}
/*
load data
*/
pStart = (char *)buffer;
maxAddress = getNXDatasetLength(dataset);
address = 0;
while( (pStart = getNextNumber(pStart,pNumber)) != NULL &&
address < maxAddress){
putNXDatasetValueAt(dataset,address,atof(pNumber));
address++;
}
return 0;
}
/*---------------------------------------------------------------------*/
static void stringIntoBuffer(char **buffer, char **bufPtr, size_t *bufSize,
char *string){
size_t i;
for(i = 0; i < strlen(string); i++){
myxml_add_char(string[i],bufPtr,buffer,bufSize);
}
}
/*--------------------------------------------------------------------*/
static void formatNumber(double value, char *txt, int txtLen,
char *format, int type){
switch(type){
case NX_INT8:
case NX_UINT8:
case NX_INT16:
case NX_UINT16:
case NX_INT32:
case NX_UINT32:
snprintf(txt,txtLen,format,(int)value);
break;
case NX_INT64:
snprintf(txt,txtLen,format,(int64_t)value);
break;
case NX_UINT64:
snprintf(txt,txtLen,format,(uint64_t)value);
break;
case NX_FLOAT32:
case NX_FLOAT64:
snprintf(txt,txtLen,format,value);
break;
default:
/*assert(0); something is very wrong here */
printf("Problem\n");
break;
}
}
/*--------------------------------------------------------------------*/
static int countDepth(mxml_node_t *node){
int count = 0;
mxml_node_t *cur;
cur = node;
while(cur != NULL){
count++;
cur = cur->parent;
}
count--;
return count;
}
/*---------------------------------------------------------------------*/
char *nexusWriteCallback(mxml_node_t *node){
int type, col;
char pNumber[80], indent[80], format[30];
char *buffer, *bufPtr;
pNXDS dataset;
int currentLen, table_style = 0;
size_t i, bufsize, length;
int is_definition = 0;
/* this is set by nxconvert when making a definiton */
is_definition = (getenv("NX_IS_DEFINITION") != NULL);
if (!strcmp(node->parent->parent->value.element.name, DATA_NODE_NAME))
{
table_style = 1;
}
/*
allocate output buffer
*/
buffer = (char *)malloc(1024*sizeof(char));
if(buffer == NULL){
mxml_error("Unable to allocate buffer");
return NULL;
}
memset(buffer,0,1024);
bufPtr = buffer;
bufsize = 1024;
dataset = (pNXDS)node->value.custom.data;
/*
prepare indentation level
*/
col = countDepth(node)*2;
memset(indent,0,80);
for(i = 0; i < col; i++){
indent[i] = ' ';
}
/*
get dataset info
*/
type = getNXDatasetType(dataset);
if (is_definition) {
length = 1;
} else {
length = getNXDatasetLength(dataset);
}
if(dataset->format != NULL){
strcpy(format,dataset->format);
} else {
getNumberFormat(type,format);
}
/*
actually get the data out
*/
if (table_style)
{
for(i = 0; i < length; i++){
formatNumber(getNXDatasetValueAt(dataset,i),pNumber,79,format,type);
stringIntoBuffer(&buffer,&bufPtr,&bufsize,pNumber);
}
}
else
{
currentLen = col;
myxml_add_char('\n',&bufPtr,&buffer,&bufsize);
stringIntoBuffer(&buffer,&bufPtr,&bufsize,indent);
for(i = 0; i < length; i++){
formatNumber(getNXDatasetValueAt(dataset,i),pNumber,79,format,type);
if(currentLen + strlen(pNumber) > MXML_WRAP){
/*
wrap line
*/
myxml_add_char('\n',&bufPtr,&buffer,&bufsize);
stringIntoBuffer(&buffer,&bufPtr,&bufsize,indent);
currentLen = col;
}
stringIntoBuffer(&buffer,&bufPtr,&bufsize,pNumber);
myxml_add_char(' ',&bufPtr,&buffer,&bufsize);
currentLen += strlen(pNumber) + 1;
}
}
myxml_add_char('\0',&bufPtr,&buffer,&bufsize);
return (char *)buffer;
}
/*------------------------------------------------------------------*/
int isDataNode(mxml_node_t *node){
if(mxmlElementGetAttr(node,"name") != NULL){
return 0;
}
if(strcmp(node->value.element.name,"NXroot") == 0){
return 0;
}
if(strcmp(node->value.element.name,DIMS_NODE_NAME) == 0){
return 0;
}
if(strcmp(node->value.element.name,DATA_NODE_NAME) == 0){
return 0;
}
if(strcmp(node->value.element.name,"NAPIlink") == 0){
return 0;
}
return 1;
}
/*--------------------------------------------------------------------*/
static int isTextData(mxml_node_t *node){
const char *attr = NULL;
if(!isDataNode(node)){
return 0;
}
/*
test datasets
*/
attr = mxmlElementGetAttr(node,TYPENAME);
if(attr == NULL){
return 1;
}
if(strstr(attr,"NX_CHAR") != NULL){
return 1;
} else {
return 0;
}
}
/*---------------------------------------------------------------------*/
/*
* note: not reentrant or thead safe; returns pointer to static storage
*/
const char *NXwhitespaceCallback(mxml_node_t *node, int where){
static char *indent = NULL;
int len;
if(strstr(node->value.element.name,"?xml") != NULL){
return NULL;
}
if (node->parent != NULL && !strcmp(node->parent->value.element.name, DATA_NODE_NAME))
{
return NULL;
}
if (where == MXML_WS_BEFORE_CLOSE && !strcmp(node->value.element.name, DATA_NODE_NAME))
{
return NULL;
}
if(isTextData(node)){
if(where == MXML_WS_BEFORE_OPEN){
len = countDepth(node)*2 + 2;
if (indent != NULL)
{
free(indent);
indent = NULL;
}
indent = (char *)malloc(len*sizeof(char));
if(indent != NULL){
memset(indent,' ',len);
indent[0]= '\n';
indent[len-1] = '\0';
return (const char*)indent;
}
}
return NULL;
}
if(where == MXML_WS_BEFORE_OPEN || where == MXML_WS_BEFORE_CLOSE){
len = countDepth(node)*2 + 2;
if (indent != NULL)
{
free(indent);
indent = NULL;
}
indent = (char *)malloc(len*sizeof(char));
if(indent != NULL){
memset(indent,' ',len);
indent[0]= '\n';
indent[len-1] = '\0';
return (const char*)indent;
}
}
return NULL;
}
/*-----------------------------------------------------------------------*/
#ifdef TESTMAIN
#include <stdio.h>
int main(int argc, char *argv[]){
mxml_node_t *root = NULL;
FILE *f;
mxmlSetCustomHandlers(nexusLoadCallback, nexusWriteCallback);
initializeNumberFormats();
/*
read test
*/
f = fopen("dmc.xml","r");
root = mxmlLoadFile(NULL,f,nexusTypeCallback);
fclose(f);
/*
write test
*/
setNumberFormat(NX_INT32,"%8d");
setNumberFormat(NX_FLOAT32,"%8.2f");
f = fopen("dmc2.xml","w");
mxmlSaveFile(root,f,NXwhitespaceCallback);
fclose(f);
}
#endif
#endif /*NXXML*/

50
nxio.h
View File

@ -1,50 +0,0 @@
/**
* This file contains functions necessary to perform XML-I/O for
* NeXus with the mxml-library.
*
* Most notably it contains the callback function for reading data
*
* Copyright (C) 2004 Mark Koennecke
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* For further information, see <http://www.nexusformat.org>
*/
#ifndef __NXIO
#define __NXIO
#include <mxml.h>
#define TYPENAME "NAPItype"
#define DIMS_NODE_NAME "columns"
#define DATA_NODE_NAME "row"
mxml_type_t nexusTypeCallback(mxml_node_t *parent);
const char *NXwhitespaceCallback(mxml_node_t *node, int where);
int nexusLoadCallback(mxml_node_t *node, const char *buffer);
char *nexusWriteCallback(mxml_node_t *node);
void setNumberFormat(int dataType, char *formatString);
void initializeNumberFormats();
void getNumberText(int nx_type, char *typestring, int typeLen);
void destroyDataset(void *data);
int translateTypeCode(const char *code);
int isDataNode(mxml_node_t *node);
void analyzeDim(const char *typeString, int *rank,
int64_t *iDim, int *type);
#endif

Some files were not shown because too many files have changed in this diff Show More