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:
137
.gitignore
vendored
137
.gitignore
vendored
@ -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
|
||||
|
||||
|
@ -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
112
HistMem.h
@ -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
|
||||
|
@ -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
|
||||
|
@ -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();
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
|
15
arrayutil.c
15
arrayutil.c
@ -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
24
ascon.c
@ -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;
|
||||
}
|
||||
|
8
ascon.h
8
ascon.h
@ -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
29
ascon.i
@ -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
|
||||
|
28
asynnet.c
28
asynnet.c
@ -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;
|
||||
}
|
||||
|
13
asynnet.h
13
asynnet.h
@ -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_ */
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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
3
cone.c
@ -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;
|
||||
}
|
||||
|
@ -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
168
conman.c
@ -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) {
|
||||
|
2
conman.h
2
conman.h
@ -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
248
counter.c
@ -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 {
|
||||
|
@ -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);
|
||||
|
308
countersec.c
308
countersec.c
@ -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
16
danu.c
@ -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);
|
||||
|
21
devexec.h
21
devexec.h
@ -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
|
||||
|
@ -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}
|
||||
|
@ -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
|
||||
@}
|
||||
|
||||
|
22
devser.c
22
devser.c
@ -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);
|
||||
}
|
||||
|
16
devser.h
16
devser.h
@ -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
|
||||
|
@ -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);
|
||||
|
||||
|
||||
|
@ -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
113
drive.c
@ -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;
|
||||
}
|
||||
|
10
dynstring.c
10
dynstring.c
@ -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)
|
||||
{
|
||||
|
@ -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
313
epicsmotor.c
Normal 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;
|
||||
}
|
@ -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;
|
||||
|
2
event.c
2
event.c
@ -71,6 +71,8 @@ static char *pEvent[] = {
|
||||
"STATEEND",
|
||||
"NEWTARGET",
|
||||
"DIMCHANGE",
|
||||
"PAUSE",
|
||||
"CONTINUE",
|
||||
NULL
|
||||
};
|
||||
|
||||
|
18
event.h
18
event.h
@ -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
|
||||
|
@ -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
|
||||
|
5
event.w
5
event.w
@ -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
|
||||
|
32
exebuf.c
32
exebuf.c
@ -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);
|
||||
|
15
exeman.c
15
exeman.c
@ -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);
|
||||
|
2
exeman.h
2
exeman.h
@ -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
|
||||
|
73
fitcenter.c
73
fitcenter.c
@ -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);
|
||||
}
|
||||
|
13
fomerge.c
13
fomerge.c
@ -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",
|
||||
|
@ -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.) {
|
||||
|
25
fourmess.c
25
fourmess.c
@ -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
10
frame.c
@ -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;
|
||||
|
21
hdbtable.c
21
hdbtable.c
@ -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;
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
|
83
hipadaba.c
83
hipadaba.c
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
23
hipadaba.h
23
hipadaba.h
@ -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
117
histmem.c
@ -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;
|
||||
}
|
||||
|
304
histmemsec.c
304
histmemsec.c
@ -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;
|
||||
}
|
||||
|
@ -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_*/
|
||||
|
@ -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}
|
||||
|
@ -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
|
||||
|
@ -77,6 +77,7 @@ static int SimConfig(pHistDriver self, SConnection * pCon,
|
||||
self->pPriv = NewSIMCounter("HistoSim", fFail);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
configured test value
|
||||
*/
|
||||
|
49
hkl.c
49
hkl.c
@ -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)) {
|
||||
|
@ -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) {
|
||||
|
25
hmdata.c
25
hmdata.c
@ -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;
|
||||
|
@ -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]);
|
||||
|
233
interface.c
233
interface.c
@ -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)
|
||||
|
196
interface.h
196
interface.h
@ -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
|
||||
|
@ -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.
|
||||
|
13
interface.w
13
interface.w
@ -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.
|
||||
|
42
intserv.c
42
intserv.c
@ -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);
|
||||
}
|
||||
|
||||
/*--------------------------------------------------------------------------*/
|
||||
|
@ -10,4 +10,4 @@
|
||||
MFLAGS=-f makefile_linux$(DUMMY)
|
||||
|
||||
HDFROOT=/usr/local
|
||||
TCLINC=/usr/include/tcl8.3
|
||||
TCLINC=/usr/include/tcl
|
25
macro.c
25
macro.c
@ -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)
|
||||
|
42
make_gen
42
make_gen
@ -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
|
||||
|
24
makefile
24
makefile
@ -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
25
makefile_
Normal 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]"
|
@ -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 \
|
||||
|
@ -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
|
||||
|
@ -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 \
|
||||
|
@ -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
118
messagepipe.c
Normal 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
82
messagepipe.h
Normal 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
|
@ -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
66
motor.c
@ -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) {
|
||||
|
3
motor.h
3
motor.h
@ -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
|
||||
|
81
motorlist.c
81
motorlist.c
@ -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);
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------
|
||||
|
@ -19,6 +19,7 @@ typedef struct {
|
||||
pIDrivable pDriv;
|
||||
void *data;
|
||||
int running;
|
||||
long taskID;
|
||||
} MotControl, *pMotControl;
|
||||
|
||||
/*======================================================================*/
|
||||
|
189
motorsec.c
189
motorsec.c
@ -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;
|
||||
}
|
||||
|
302
multicounter.c
302
multicounter.c
@ -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
564
multicountersec.c
Normal 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
5
mumo.c
@ -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]);
|
||||
|
22
mumoconf.c
22
mumoconf.c
@ -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,
|
||||
|
967
napi.h
967
napi.h
@ -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*/
|
60
napi4.h
60
napi4.h
@ -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 */
|
54
napi5.h
54
napi5.h
@ -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 */
|
12
network.c
12
network.c
@ -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
10
nread.c
@ -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);
|
||||
|
43
nserver.c
43
nserver.c
@ -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;
|
||||
|
2
nxdict.c
2
nxdict.c
@ -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
747
nxio.c
@ -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
50
nxio.h
@ -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
Reference in New Issue
Block a user